Air Status
-
| '+r.name+" | ";a+="
|---|
| ";var u=r.accesses;if(u)for(var d,p=-1,h=u.length-1;h>p;)d=u[p+=1],a+=""+n.link(d.name,d.req?"check-square-o":"square-o","set",{access:d.id},null,d.req?"selected":null)+" ";a+=" | "}return a+="
"
dat += "General Settings" dat += "UI Style: [UI_style]" - dat += "Fancy NanoUI: [(nanoui_fancy) ? "Yes" : "No"] " + dat += "tgui Style: [(tgui_fancy) ? "Fancy" : "No Frills"] " dat += "Play admin midis: [(toggles & SOUND_MIDI) ? "Yes" : "No"] " dat += "Play lobby music: [(toggles & SOUND_LOBBY) ? "Yes" : "No"] " dat += "Ghost ears: [(chat_toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"] " @@ -721,7 +721,7 @@ var/list/preferences_datums = list() if("undershirt") undershirt = random_undershirt(gender) if("socks") - socks = random_socks(gender) + socks = random_socks() if("eyes") eye_color = random_eye_color() if("s_tone") @@ -834,10 +834,7 @@ var/list/preferences_datums = list() if("socks") var/new_socks - if(gender == MALE) - new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in socks_m - else - new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in socks_f + new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in socks_list if(new_socks) socks = new_socks @@ -1001,7 +998,7 @@ var/list/preferences_datums = list() gender = MALE underwear = random_underwear(gender) undershirt = random_undershirt(gender) - socks = random_socks(gender) + socks = random_socks() facial_hair_style = random_facial_hair_style(gender) hair_style = random_hair_style(gender) @@ -1018,8 +1015,8 @@ var/list/preferences_datums = list() else UI_style = "Midnight" - if("nanoui") - nanoui_fancy = !nanoui_fancy + if("tgui_fancy") + tgui_fancy = !tgui_fancy if("hear_adminhelps") toggles ^= SOUND_ADMINHELP diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 53c66f1f520..b53b52e06e1 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -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,13 @@ 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 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 +191,7 @@ 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", "Slimecore", "Operative"), 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)) 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 +211,7 @@ 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["be_special"] << be_special S["default_slot"] << default_slot S["toggles"] << toggles @@ -323,14 +321,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car facial_hair_style = sanitize_inlist(facial_hair_style, facial_hair_styles_male_list) underwear = sanitize_inlist(underwear, underwear_m) undershirt = sanitize_inlist(undershirt, undershirt_m) - socks = sanitize_inlist(socks, socks_m) else hair_style = sanitize_inlist(hair_style, hair_styles_female_list) facial_hair_style = sanitize_inlist(facial_hair_style, facial_hair_styles_female_list) underwear = sanitize_inlist(underwear, underwear_f) undershirt = sanitize_inlist(undershirt, undershirt_f) - socks = sanitize_inlist(socks, socks_f) - + socks = sanitize_inlist(socks, socks_list) age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age)) hair_color = sanitize_hexcolor(hair_color, 3, 0) facial_hair_color = sanitize_hexcolor(facial_hair_color, 3, 0) diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 1fe7e79d754..d2fd8ff78c2 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -93,7 +93,7 @@ desc = "An extremely robust, space-worthy helmet in a nefarious red and black stripe pattern." icon_state = "swatsyndie" item_state = "swatsyndie" - armor = list(melee = 40, bullet = 30, laser = 25,energy = 25, bomb = 50, bio = 10, rad = 0) + armor = list(melee = 40, bullet = 30, laser = 30,energy = 30, bomb = 50, bio = 90, rad = 20) cold_protection = HEAD min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT heat_protection = HEAD diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index 66729755e1e..bf565cd3664 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -3,6 +3,7 @@ Contains: - Captain's spacesuit - Death squad's hardsuit + - SWAT suit - Officer's beret/spacesuit - NASA Voidsuit - Father Christmas' magical clothes @@ -53,13 +54,23 @@ Contains: desc = "A heavily armored, advanced space suit that protects against most forms of damage." icon_state = "deathsquad" item_state = "swat_suit" - allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/tank/internals) + allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/tank/internals,/obj/item/weapon/kitchen/knife/combat) armor = list(melee = 80, bullet = 80, laser = 50, energy = 50, bomb = 100, bio = 100, rad = 100) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT unacidable = 1 helmettype = /obj/item/clothing/head/helmet/space/hardsuit/deathsquad + //NEW SWAT suit +/obj/item/clothing/suit/space/swat + name = "SWAT armor" + desc = "Space-proof tactical SWAT armor." + icon_state = "heavy" + item_state = "swat_suit" + allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/tank/internals,/obj/item/weapon/kitchen/knife/combat) + armor = list(melee = 40, bullet = 30, laser = 30,energy = 30, bomb = 50, bio = 90, rad = 20) + strip_delay = 120 + /obj/item/clothing/head/helmet/space/beret name = "officer's beret" desc = "An armored beret commonly used by special operations officers. Uses advanced force field technology to protect the head from space." diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 40d77f12752..89c27f94d13 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -1,5 +1,5 @@ /obj/item/clothing/suit/armor - allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/device/flashlight/seclite,/obj/item/weapon/melee/classic_baton/telescopic) + allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/device/flashlight/seclite,/obj/item/weapon/melee/classic_baton/telescopic,/obj/item/weapon/kitchen/knife/combat) body_parts_covered = CHEST cold_protection = CHEST|GROIN min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT @@ -118,7 +118,7 @@ name = "armor" desc = "An armored vest with a detective's badge on it." icon_state = "detective-armor" - allowed = list(/obj/item/weapon/tank/internals/emergency_oxygen,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter,/obj/item/device/detective_scanner,/obj/item/device/taperecorder) + allowed = list(/obj/item/weapon/tank/internals/emergency_oxygen,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter,/obj/item/device/detective_scanner,/obj/item/device/taperecorder,/obj/item/weapon/melee/classic_baton/telescopic) burn_state = FLAMMABLE @@ -304,4 +304,4 @@ name = "crusader armour" desc = "God wills it!" icon_state = "knight_templar" - item_state = "knight_templar" \ No newline at end of file + item_state = "knight_templar" diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index d63c5c43a70..dd112de5f44 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -81,7 +81,7 @@ item_state = "det_suit" blood_overlay_type = "coat" body_parts_covered = CHEST|GROIN|LEGS|ARMS - allowed = list(/obj/item/weapon/tank/internals/emergency_oxygen,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter,/obj/item/device/detective_scanner,/obj/item/device/taperecorder) + allowed = list(/obj/item/weapon/tank/internals/emergency_oxygen,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter,/obj/item/device/detective_scanner,/obj/item/device/taperecorder,/obj/item/weapon/melee/classic_baton/telescopic) armor = list(melee = 25, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0) cold_protection = CHEST|GROIN|LEGS|ARMS heat_protection = CHEST|GROIN|LEGS|ARMS diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm index 5e03c3db4e4..1b242b34cfa 100644 --- a/code/modules/crafting/recipes.dm +++ b/code/modules/crafting/recipes.dm @@ -283,9 +283,11 @@ result = /obj/item/clothing/head/lizard time = 20 reqs = list(/obj/item/organ/severedtail = 1) + category = CAT_MISC /datum/table_recipe/lizardhat_alternate name = "Lizard Cloche Hat" result = /obj/item/clothing/head/lizard time = 20 reqs = list(/obj/item/stack/sheet/animalhide/lizard = 1) + category = CAT_MISC diff --git a/code/modules/events/abductor.dm b/code/modules/events/abductor.dm index 499306b617a..3eaf7e3c0c7 100644 --- a/code/modules/events/abductor.dm +++ b/code/modules/events/abductor.dm @@ -4,7 +4,7 @@ weight = 5 max_occurrences = 1 - earliest_start = 180000 // 30 min + earliest_start = 18000 // 30 min gamemode_blacklist = list("nuclear","wizard","revolution","abduction") diff --git a/code/modules/events/wizard/advanced_darkness.dm b/code/modules/events/wizard/advanced_darkness.dm new file mode 100644 index 00000000000..8e60fce2208 --- /dev/null +++ b/code/modules/events/wizard/advanced_darkness.dm @@ -0,0 +1,14 @@ +/datum/round_event_control/wizard/darkness + name = "Advanced Darkness" + weight = 2 + typepath = /datum/round_event/wizard/darkness + max_occurrences = 2 + earliest_start = 0 + +/datum/round_event/wizard/darkness + endWhen = 0 + +/datum/round_event/wizard/darkness/start() + var/datum/weather/advanced_darkness/darkness = new + darkness.weather_start_up() + return diff --git a/code/modules/events/wizard/imposter.dm b/code/modules/events/wizard/imposter.dm index ec6f4fa06c5..c260a51251c 100644 --- a/code/modules/events/wizard/imposter.dm +++ b/code/modules/events/wizard/imposter.dm @@ -38,11 +38,9 @@ ticker.mode.apprentices += I.mind I.mind.special_role = "imposter" - var/datum/objective/protect/protect_objective = new /datum/objective/protect - protect_objective.owner = I.mind + var/datum/objective/protect_objective = add_objective(I.mind, /datum/objective/default/protect) protect_objective.target = W.mind protect_objective.explanation_text = "Protect [W.real_name], the wizard." - I.mind.objectives += protect_objective ticker.mode.update_wiz_icons_added(I.mind) I.attack_log += "\[[time_stamp()]\] Is an imposter!" diff --git a/code/modules/events/wizard/lava.dm b/code/modules/events/wizard/lava.dm index 23d9afeeff3..fe6044182dd 100644 --- a/code/modules/events/wizard/lava.dm +++ b/code/modules/events/wizard/lava.dm @@ -6,37 +6,9 @@ earliest_start = 0 /datum/round_event/wizard/lava/ - - endWhen = 30 //half a minutes + endWhen = 0 /datum/round_event/wizard/lava/start() - - for(var/turf/simulated/floor/F in world) - if(F.z == ZLEVEL_STATION) - F.name = "lava" - F.desc = "The floor is LAVA!" - F.overlays += "lava" - F.lava = 1 - -/datum/round_event/wizard/lava/tick() - - for(var/mob/living/carbon/L in living_mob_list) - if(istype(L.loc, /turf/simulated/floor)) // Are they on LAVA?! - var/turf/simulated/floor/F = L.loc - if(F.lava) - var/safe = 0 - for(var/obj/structure/O in F.contents) - if(O.level > F.level && !istype(O, /obj/structure/window)) // Something to stand on and it isn't under the floor! - safe = 1 - if(!safe) - L.adjustFireLoss(3) - -/datum/round_event/wizard/lava/end() - - for(var/turf/simulated/floor/F in world) // Reset everything. - if(F.z == ZLEVEL_STATION) - F.name = initial(F.name) - F.desc = initial(F.desc) - F.overlays.Cut() - F.lava = 0 - F.update_icon() \ No newline at end of file + var/datum/weather/floor_is_lava/LAVA = new /datum/weather/floor_is_lava + LAVA.weather_start_up() + return diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index 49027281407..1c3365cd59a 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -281,29 +281,31 @@ Gunshots/explosions/opening doors/less rare audio (done) /obj/effect/hallucination/delusion var/list/image/delusions = list() -/obj/effect/hallucination/delusion/New(loc,var/mob/living/carbon/T) +/obj/effect/hallucination/delusion/New(loc,mob/living/carbon/T,force_kind = null , duration = 300,skip_nearby = 1) target = T var/image/A = null - var/kind = rand(1,3) + var/kind = force_kind ? force_kind : pick("clown","corgi","carp","skeleton","demon") for(var/mob/living/carbon/human/H in living_mob_list) if(H == target) continue - if(H in view(target)) + if(skip_nearby && (H in view(target))) continue switch(kind) - if(1)//Clown + if("clown")//Clown A = image('icons/mob/animal.dmi',H,"clown") - if(2)//Carp + if("carp")//Carp A = image('icons/mob/animal.dmi',H,"carp") - if(3)//Corgi + if("corgi")//Corgi A = image('icons/mob/pets.dmi',H,"corgi") - if(4)//Skeletons + if("skeleton")//Skeletons A = image('icons/mob/human.dmi',H,"skeleton_s") + if("demon")//Demon + A = image('icons/mob/mob.dmi',H,"daemon") A.override = 1 if(target.client) delusions |= A target.client.images |= A - sleep(300) + sleep(duration) for(var/image/I in delusions) if(target.client) target.client.images.Remove(I) diff --git a/code/modules/food&drinks/drinks/drinks.dm b/code/modules/food&drinks/drinks/drinks.dm index 69cbccb4d99..b9f6cc3fbd3 100644 --- a/code/modules/food&drinks/drinks/drinks.dm +++ b/code/modules/food&drinks/drinks/drinks.dm @@ -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 diff --git a/code/modules/food&drinks/drinks/drinks/bottle.dm b/code/modules/food&drinks/drinks/drinks/bottle.dm index e97d65fdea7..9b9bccc986e 100644 --- a/code/modules/food&drinks/drinks/drinks/bottle.dm +++ b/code/modules/food&drinks/drinks/drinks/bottle.dm @@ -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 diff --git a/code/modules/html_interface/html_interface.dm b/code/modules/html_interface/html_interface.dm index 38fb620fddb..66ced5276c6 100644 --- a/code/modules/html_interface/html_interface.dm +++ b/code/modules/html_interface/html_interface.dm @@ -221,7 +221,7 @@ mob/verb/test() hclient = getClient(hclient, TRUE) if (istype(hclient)) - if (type in asset_list && islist(asset_list[type])) + if ((type in asset_list) && islist(asset_list[type])) send_asset_list(hclient.client, asset_list[type], TRUE) if (!winexists(hclient.client, "browser_\ref[src]")) diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index a14996e18b9..aa59022f094 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -174,7 +174,7 @@ var/global/list/datum/cachedbook/cachedbooks // List of our cached book datums var/checkoutperiod = 5 // In minutes var/obj/machinery/libraryscanner/scanner // Book scanner that will be used when uploading books to the Archive var/list/libcomp_menu - var/page = 1 //current page of the external archives + var/page = 1 //current page of the external archives var/bibledelay = 0 // LOL NO SPAM (1 minute delay) -- Doohl /obj/machinery/computer/libraryconsole/bookmanagement/proc/build_library_menu() @@ -184,7 +184,7 @@ var/global/list/datum/cachedbook/cachedbooks // List of our cached book datums if(!cachedbooks) return libcomp_menu = list("") - + for(var/i in 1 to cachedbooks.len) var/datum/cachedbook/C = cachedbooks[i] var/page = round(i/250)+1 @@ -434,7 +434,7 @@ var/global/list/datum/cachedbook/cachedbooks // List of our cached book datums B.title = title B.author = author B.dat = content - B.icon_state = "book[rand(1,7)]" + B.icon_state = "book[rand(1,8)]" src.visible_message("[src]'s printer hums as it produces a completely bound book. How did it do that?") break src.add_fingerprint(usr) diff --git a/code/modules/library/random_books.dm b/code/modules/library/random_books.dm index 16c3dee6ac9..56514b6113d 100644 --- a/code/modules/library/random_books.dm +++ b/code/modules/library/random_books.dm @@ -39,7 +39,7 @@ B.title = query.item[3] B.dat = query.item[4] B.name = "Book: [B.title]" - B.icon_state= "book[rand(1,7)]" + B.icon_state= "book[rand(1,8)]" else log_game("SQL ERROR populating library bookshelf. Category: \[[category]\], Count: [book_count], Error: \[[query.ErrorMsg()]\]\n") update_icon() diff --git a/code/modules/lighting/lighting_system.dm b/code/modules/lighting/lighting_system.dm index 9b67f630def..7367f760a0b 100644 --- a/code/modules/lighting/lighting_system.dm +++ b/code/modules/lighting/lighting_system.dm @@ -131,7 +131,7 @@ if(AM.opacity) range = 0 break - + owner.luminosity = range if (!range) return 0 diff --git a/code/modules/mining/lavaland/lavaland_areas.dm b/code/modules/mining/lavaland/lavaland_areas.dm new file mode 100644 index 00000000000..e3fa70aa43d --- /dev/null +++ b/code/modules/mining/lavaland/lavaland_areas.dm @@ -0,0 +1,28 @@ +/**********************Lavaland Areas**************************/ + +/area/lavaland + icon_state = "mining" + has_gravity = 1 + +/area/lavaland/surface + name = "Lavaland" + icon_state = "explored" + music = null + requires_power = 1 + ambientsounds = list('sound/ambience/ambimine.ogg') + +/area/lavaland/underground + name = "Lavaland Caves" + icon_state = "unexplored" + music = null + always_unpowered = 1 + requires_power = 1 + poweralm = 0 + power_environ = 0 + power_equip = 0 + power_light = 0 + ambientsounds = list('sound/ambience/ambimine.ogg') + + +/area/lavaland/surface/outdoors + name = "Lavaland Wastes" diff --git a/code/modules/mining/lavaland/weather.dm b/code/modules/mining/lavaland/weather.dm new file mode 100644 index 00000000000..2d24616df50 --- /dev/null +++ b/code/modules/mining/lavaland/weather.dm @@ -0,0 +1,100 @@ +#define STARTUP_STAGE 1 +#define MAIN_STAGE 2 +#define WIND_DOWN_STAGE 3 +#define END_STAGE 4 + +/datum/weather + var/name = "storm" + var/start_up_time = 300 //30 seconds + var/start_up_message = "The wind begins to pick up." + var/duration = 120 //2 minutes + var/duration_lower = 120 + var/duration_upper = 120 + var/duration_message = "A storm has started!" + var/wind_down = 300 // 30 seconds + var/wind_down_message = "The storm is passing." + + var/target_z = 1 + var/exclude_walls = TRUE + var/area_type = /area/space + var/stage = STARTUP_STAGE + + + var/start_up_overlay = "lava" + var/duration_overlay = "lava" + var/overlay_layer = 10 //This is the default area layer, and above everything else. 2 is floors/below walls and mobs. + var/purely_aesthetic = FALSE //If we just want gentle rain that doesn't hurt people + var/list/impacted_areas = list() + +/datum/weather/proc/weather_start_up() + for(var/area/N in get_areas(area_type)) + if(N.z == target_z) + impacted_areas += N + duration = rand(duration_lower,duration_upper) + update_areas() + for(var/mob/M in player_list) + if(M.z == target_z) + M << start_up_message + + spawn(start_up_time) + stage = MAIN_STAGE + weather_main() + + +/datum/weather/proc/weather_main() + update_areas() + for(var/mob/M in player_list) + if(M.z == target_z) + M << "[duration_message]" + if(purely_aesthetic) + sleep(duration*10) + else //Storm effects + for(var/i in 1 to duration-1) + for(var/mob/living/L in living_mob_list) + var/area/storm_area = get_area(L) + if(storm_area in impacted_areas) + storm_act(L) + sleep(10) + + stage = WIND_DOWN_STAGE + weather_wind_down() + + +/datum/weather/proc/weather_wind_down() + update_areas() + for(var/mob/M in player_list) + if(M.z == target_z) + M << wind_down_message + + sleep(wind_down) + + stage = END_STAGE + update_areas() + + +/datum/weather/proc/storm_act(mob/living/L) + if(prob(30)) //Dont want it spammed very tick + L << "You're buffeted by the storm!" + L.adjustBruteLoss(1) + +/datum/weather/proc/update_areas() + for(var/area/N in impacted_areas) + N.layer = overlay_layer + N.icon = 'icons/effects/weather_effects.dmi' + N.invisibility = 0 + switch(stage) + if(STARTUP_STAGE) + N.icon_state = start_up_overlay + + if(MAIN_STAGE) + N.icon_state = duration_overlay + + if(WIND_DOWN_STAGE) + N.icon_state = start_up_overlay + + if(END_STAGE) + N.icon_state = initial(N.icon_state) + N.icon = 'icons/turf/areas.dmi' + N.layer = 10 //Just default back to normal area stuff since I assume setting a var is faster than initial + N.invisibility = 100 + N.opacity = 0 \ No newline at end of file diff --git a/code/modules/mining/lavaland/weather_types.dm b/code/modules/mining/lavaland/weather_types.dm new file mode 100644 index 00000000000..89308d4437c --- /dev/null +++ b/code/modules/mining/lavaland/weather_types.dm @@ -0,0 +1,90 @@ +///The floor is lava + +/datum/weather/floor_is_lava + name = "floor is lava" + start_up_time = 30 //3 seconds + start_up_message = "The ground begins to bubble." + duration_lower = 45 + duration_upper = 60 //1 minute + duration_message = "The floor is lava!" + wind_down = 30// 3 seconds + wind_down_message = "The ground begins to cool." + + target_z = 1 + exclude_walls = TRUE + area_type = /area + + start_up_overlay = "lava" + duration_overlay = "lava" + overlay_layer = 2 //Covers floors only + + +/datum/weather/floor_is_lava/storm_act(mob/living/L) + var/turf/F = get_turf(L) + for(var/obj/structure/O in F.contents) + if(O.level > F.level && !istype(O, /obj/structure/window)) // Something to stand on and it isn't under the floor! + return + L.adjustFireLoss(3) + + + +/datum/weather/advanced_darkness + name = "advanced darkness" + start_up_time = 100 //10 seconds + start_up_message = "The lights begin to dim... is power going out?" + duration_lower = 45 + duration_upper = 60 //1 minute + duration_message = "This isn't average everyday darkness... this is advanced darkness!" + wind_down = 100 // 10 seconds + wind_down_message = "The darkness is receding. Thank god." + purely_aesthetic = TRUE + + target_z = 1 + exclude_walls = TRUE + area_type = /area + + start_up_overlay = "" + duration_overlay = "" + overlay_layer = 10 + +/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 + +/datum/weather/ash_storm + name = "ash storm" + start_up_time = 300 //30 seconds + start_up_message = "The wind begins to pick up. Seek shelter." + duration_lower = 90 //1.5 minutes + duration_upper = 360 //3 minutes + duration_message = "An ash storm has started! Get inside!" + wind_down = 300 // 30 seconds + wind_down_message = "The storm begins to fade. Should be safe to go outside again." + + target_z = ZLEVEL_LAVALAND + area_type = /area/lavaland/surface/outdoors + + start_up_overlay = "light_ash" + duration_overlay = "ash_storm" + overlay_layer = 10 + + +/datum/weather/ash_storm/false_alarm //No storm, just light ember fall + purely_aesthetic = TRUE + duration_overlay = "light_ash" + duration_message = "Looks like the storm just missed the mining area. False alarm." + wind_down_message = "The ash fall starts to trail off." + +/datum/weather/ash_storm/storm_act(mob/living/L) + if(ishuman(L)) + var/mob/living/carbon/human/H = L + var/thermal_protection = H.get_thermal_protection() + if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT) + return + L.adjustFireLoss(4) diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 5958d0275ad..f15c5a5c37e 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -191,6 +191,7 @@ qdel(src) /obj/item/weapon/survivalcapsule/proc/load() + var/list/blacklist = list(/area/shuttle) //Shuttles move based on area, and we'd like not to break them var/turf/start_turf = get_turf(src.loc) var/turf/cur_turf var/x_size = 5 @@ -243,7 +244,9 @@ threshhold.nitrogen = 82 threshhold.carbon_dioxide = 0 threshhold.toxins = 0 - L.contents += threshhold + var/area/ZZ = get_area(threshhold) + if(!is_type_in_list(ZZ, blacklist)) + L.contents += threshhold threshhold.overlays.Cut() var/list/turfs = room["floors"] @@ -261,5 +264,6 @@ A.air.temperature = 293.15 SSair.add_to_active(A) A.overlays.Cut() - - L.contents += A + var/area/Z = get_area(A) + if(!is_type_in_list(Z, blacklist)) + L.contents += A diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 1d3e6ed3a72..641fa9446f5 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -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 << "Another consciousness is in your body...It is resisting you." return - SSnano.on_transfer(src, mind.current) // Transfer NanoUIs. + SStgui.on_transfer(src, mind.current) // Transfer NanoUIs. mind.current.key = key return 1 diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index fa00df2f7db..753b66235b6 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -173,3 +173,52 @@ //if(hasvar(src,"r_hand")) if(src:r_hand) items += src:r_hand return items + + +/obj/item/proc/equip_to_best_slot(var/mob/M) + if(src != M.get_active_hand()) + M << "You are not holding anything to equip!" + return 0 + + if(M.equip_to_appropriate_slot(src)) + if(M.hand) + M.update_inv_l_hand() + else + M.update_inv_r_hand() + return 1 + + if(M.s_active && M.s_active.can_be_inserted(src,1)) //if storage active insert there + M.s_active.handle_item_insertion(src) + return 1 + + var/obj/item/weapon/storage/S = M.get_inactive_hand() + if(istype(S) && S.can_be_inserted(src,1)) //see if we have box in other hand + S.handle_item_insertion(src) + return 1 + + S = M.get_item_by_slot(slot_belt) + if(istype(S) && S.can_be_inserted(src,1)) //else we put in belt + S.handle_item_insertion(src) + return 1 + + S = M.get_item_by_slot(slot_drone_storage) //else we put in whatever is in drone storage + if(istype(S) && S.can_be_inserted(src,1)) + S.handle_item_insertion(src) + + S = M.get_item_by_slot(slot_back) //else we put in backpack + if(istype(S) && S.can_be_inserted(src,1)) + S.handle_item_insertion(src) + playsound(src.loc, "rustle", 50, 1, -5) + return 1 + + M << "You are unable to equip that!" + return 0 + + +/mob/verb/quick_equip() + set name = "quick-equip" + set hidden = 1 + + var/obj/item/I = get_active_hand() + if (I) + I.equip_to_best_slot(src) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm index 27d29ef4e50..40727647cd7 100644 --- a/code/modules/mob/living/carbon/brain/posibrain.dm +++ b/code/modules/mob/living/carbon/brain/posibrain.dm @@ -39,7 +39,10 @@ var/global/posibrain_notif_cooldown = 0 spawn(askDelay) //Seperate from the global cooldown. notified = 0 update_icon() - visible_message("The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?") + if(brainmob.stat == CONSCIOUS && brainmob.client) + visible_message("The positronic brain pings, and its lights start flashing. Success!") + else + visible_message("The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?") 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") - ..() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index d1f2c2c10b2..36184591213 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -87,8 +87,7 @@ if(reagents.has_reagent("teslium")) shock_damage *= 1.5 //If the mob has teslium in their body, shocks are 50% more damaging! take_overall_damage(0,shock_damage) - //src.burn_skin(shock_damage) - //src.adjustFireLoss(shock_damage) //burn_skin will do this for us + //src.adjustFireLoss(shock_damage) //src.updatehealth() visible_message( "[src] was shocked by \the [source]!", \ @@ -388,7 +387,7 @@ var/const/GALOSHES_DONT_HELP = 4 last_special = world.time + CLICK_CD_BREAKOUT visible_message("[src] attempts to unbuckle themself!", \ "You attempt to unbuckle yourself... (This will take around one minute and you need to stay still.)") - if(do_after(src, 600, needhand = 0, target = src)) + if(do_after(src, 600, 0, target = src)) if(!buckled) return buckled.user_unbuckle_mob(src,src) @@ -431,7 +430,7 @@ var/const/GALOSHES_DONT_HELP = 4 if(!cuff_break) visible_message("[src] attempts to remove [I]!") src << "You attempt to remove [I]... (This will take around [displaytime] minutes and you need to stand still.)" - if(do_after(src, breakouttime, 10, 0, target = src)) + if(do_after(src, breakouttime, 0, target = src)) if(I.loc != src || buckled) return visible_message("[src] manages to remove [I]!") @@ -457,7 +456,7 @@ var/const/GALOSHES_DONT_HELP = 4 breakouttime = 50 visible_message("[src] is trying to break [I]!") src << "You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)" - if(do_after(src, breakouttime, needhand = 0, target = src)) + if(do_after(src, breakouttime, 0, target = src)) if(!I.loc || buckled) return visible_message("[src] manages to break [I]!") diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 752e796573f..5cfa976e679 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -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" diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 5c866d142fb..36978456f8a 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -1,38 +1,6 @@ /mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = 0) return dna.species.can_equip(I, slot, disable_warning, src) -/mob/living/carbon/human/verb/quick_equip() - set name = "quick-equip" - set hidden = 1 - - if(ishuman(src)) - var/mob/living/carbon/human/H = src - var/obj/item/I = H.get_active_hand() - var/obj/item/weapon/storage/S = H.get_inactive_hand() - if(!I) - H << "You are not holding anything to equip!" - return - if(H.equip_to_appropriate_slot(I)) - if(hand) - update_inv_l_hand() - else - update_inv_r_hand() - else if(s_active && s_active.can_be_inserted(I,1)) //if storage active insert there - s_active.handle_item_insertion(I) - else if(istype(S, /obj/item/weapon/storage) && S.can_be_inserted(I,1)) //see if we have box in other hand - S.handle_item_insertion(I) - else - S = H.get_item_by_slot(slot_belt) - if(istype(S, /obj/item/weapon/storage) && S.can_be_inserted(I,1)) //else we put in belt - S.handle_item_insertion(I) - else - S = H.get_item_by_slot(slot_back) //else we put in backpack - if(istype(S, /obj/item/weapon/storage) && S.can_be_inserted(I,1)) - S.handle_item_insertion(I) - playsound(src.loc, "rustle", 50, 1, -5) - else - H << "You are unable to equip that!" - /mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/I, list/slots, qdel_on_fail = 1) for(var/slot in slots) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 34803e4bff7..27a76f7eec2 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -106,14 +106,8 @@ if(!dna || !dna.species.handle_fire(src)) ..() if(on_fire) - var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures - if(wear_suit) - if(wear_suit.max_heat_protection_temperature >= FIRE_SUIT_MAX_TEMP_PROTECT) - thermal_protection += (wear_suit.max_heat_protection_temperature*0.7) - if(head) - if(head.max_heat_protection_temperature >= FIRE_HELM_MAX_TEMP_PROTECT) - thermal_protection += (head.max_heat_protection_temperature*THERMAL_PROTECTION_HEAD) - thermal_protection = round(thermal_protection) + var/thermal_protection = get_thermal_protection() + if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT) return if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT) @@ -121,6 +115,16 @@ else bodytemperature += (BODYTEMP_HEATING_MAX + (fire_stacks * 12)) +/mob/living/carbon/human/proc/get_thermal_protection() + var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures + if(wear_suit) + if(wear_suit.max_heat_protection_temperature >= FIRE_SUIT_MAX_TEMP_PROTECT) + thermal_protection += (wear_suit.max_heat_protection_temperature*0.7) + if(head) + if(head.max_heat_protection_temperature >= FIRE_HELM_MAX_TEMP_PROTECT) + thermal_protection += (head.max_heat_protection_temperature*THERMAL_PROTECTION_HEAD) + thermal_protection = round(thermal_protection) + return thermal_protection /mob/living/carbon/human/IgniteMob() if(!dna || !dna.species.IgniteMob(src)) @@ -302,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) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 98eb3b5f3a8..c46d0f1cfde 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -208,27 +208,6 @@ Sorry Giacom. Please don't be mad :( return pressure -//sort of a legacy burn method for /electrocute, /shock, and the e_chair -/mob/living/proc/burn_skin(burn_amount) - if(istype(src, /mob/living/carbon/human)) - //world << "DEBUG: burn_skin(), mutations=[mutations]" - var/mob/living/carbon/human/H = src //make this damage method divide the damage to be done among all the body parts, then burn each body part for that much damage. will have better effect then just randomly picking a body part - var/divided_damage = (burn_amount)/(H.organs.len) - var/extradam = 0 //added to when organ is at max dam - for(var/obj/item/organ/limb/affecting in H.organs) - if(!affecting) continue - if(affecting.take_damage(0, divided_damage+extradam)) //TODO: fix the extradam stuff. Or, ebtter yet...rewrite this entire proc ~Carn - H.update_damage_overlays(0) - H.updatehealth() - return 1 - else if(istype(src, /mob/living/carbon/monkey)) - var/mob/living/carbon/monkey/M = src - M.adjustFireLoss(burn_amount) - M.updatehealth() - return 1 - else if(istype(src, /mob/living/silicon/ai)) - return 0 - /mob/living/proc/adjustBodyTemp(actual, desired, incrementboost) var/temperature = actual var/difference = abs(actual-desired) //get difference diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 462c2912e93..1af50b500f1 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -187,6 +187,7 @@ var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(user, src) if(buckled) user << "You cannot grab [src], \he is buckled in!" + return 0 if(!G) //the grab will delete itself in New if src is anchored return 0 user.put_in_active_hand(G) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 45525ee11a0..9a4875bfe9a 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -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 \ No newline at end of file + 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 = "Relayed Speech: [name_used] " + show_message(rendered, 2) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index f3569d4c503..d03587fd26d 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -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) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/laws.dm b/code/modules/mob/living/silicon/ai/laws.dm index 50c188ca629..9f11d34359b 100644 --- a/code/modules/mob/living/silicon/ai/laws.dm +++ b/code/modules/mob/living/silicon/ai/laws.dm @@ -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++ + diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index ff680cf7131..97a5c7174a3 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -152,6 +152,7 @@ target_types += /obj/effect/decal/cleanable/ash target_types += /obj/effect/decal/cleanable/greenglow target_types += /obj/effect/decal/cleanable/dirt + target_types += /obj/effect/decal/cleanable/deadcockroach if(blood) target_types += /obj/effect/decal/cleanable/xenoblood/ diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index d84a6d112df..a0d0ef6b331 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -110,7 +110,7 @@ Auto Patrol: []"}, "[arrest_type ? "Detain" : "Arrest"]", "[declare_arrests ? "Yes" : "No"]", "[auto_patrol ? "On" : "Off"]" ) - + return dat /mob/living/simple_animal/bot/secbot/Topic(href, href_list) @@ -402,101 +402,5 @@ Auto Patrol: []"}, return ..() -//Secbot Construction - -/obj/item/clothing/head/helmet/attackby(obj/item/device/assembly/signaler/S, mob/user, params) - ..() - if(!issignaler(S)) - ..() - return - - if(type != /obj/item/clothing/head/helmet/sec) //Eh, but we don't want people making secbots out of space helmets. - return - - if(F) //Has a flashlight. Player must remove it, else it will be lost forever. - user << "The mounted flashlight is in the way, remove it first!" - return - - if(S.secured) - qdel(S) - var/obj/item/weapon/secbot_assembly/A = new /obj/item/weapon/secbot_assembly - user.put_in_hands(A) - user << "You add the signaler to the helmet." - user.unEquip(src, 1) - qdel(src) - else - return - -/obj/item/weapon/secbot_assembly/attackby(obj/item/I, mob/user, params) - ..() - if(istype(I, /obj/item/weapon/weldingtool)) - if(!build_step) - var/obj/item/weapon/weldingtool/WT = I - if(WT.remove_fuel(0, user)) - build_step++ - overlays += "hs_hole" - user << "You weld a hole in [src]!" - else if(build_step == 1) - var/obj/item/weapon/weldingtool/WT = I - if(WT.remove_fuel(0, user)) - build_step-- - overlays -= "hs_hole" - user << "You weld the hole in [src] shut!" - - else if(isprox(I) && (build_step == 1)) - if(!user.unEquip(I)) - return - build_step++ - user << "You add the prox sensor to [src]!" - overlays += "hs_eye" - name = "helmet/signaler/prox sensor assembly" - qdel(I) - - else if(((istype(I, /obj/item/robot_parts/l_arm)) || (istype(I, /obj/item/robot_parts/r_arm))) && (build_step == 2)) - if(!user.unEquip(I)) - return - build_step++ - user << "You add the robot arm to [src]!" - name = "helmet/signaler/prox sensor/robot arm assembly" - overlays += "hs_arm" - qdel(I) - - else if((istype(I, /obj/item/weapon/melee/baton)) && (build_step >= 3)) - if(!user.unEquip(I)) - return - build_step++ - user << "You complete the Securitron! Beep boop." - var/mob/living/simple_animal/bot/secbot/S = new/mob/living/simple_animal/bot/secbot(get_turf(src)) - S.name = created_name - qdel(I) - qdel(src) - - else if(istype(I, /obj/item/weapon/pen)) - var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN) - if(!t) - return - if(!in_range(src, usr) && loc != usr) - return - created_name = t - - else if(istype(I, /obj/item/weapon/screwdriver)) - if(!build_step) - new /obj/item/device/assembly/signaler(get_turf(src)) - new /obj/item/clothing/head/helmet/sec(get_turf(src)) - user << "You disconnect the signaler from the helmet." - qdel(src) - - else if(build_step == 2) - overlays -= "hs_eye" - new /obj/item/device/assembly/prox_sensor(get_turf(src)) - user << "You detach the proximity sensor from [src]." - build_step-- - - else if(build_step == 3) - overlays -= "hs_arm" - new /obj/item/robot_parts/l_arm(get_turf(src)) - user << "You remove the robot arm from [src]." - build_step-- - /obj/machinery/bot_core/secbot req_access = list(access_security) diff --git a/code/modules/mob/living/simple_animal/corpse.dm b/code/modules/mob/living/simple_animal/corpse.dm index 75e71a6ed77..fa0f4d29a38 100644 --- a/code/modules/mob/living/simple_animal/corpse.dm +++ b/code/modules/mob/living/simple_animal/corpse.dm @@ -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 \ No newline at end of file + 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" \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm index 9e4eac0075c..f863d12faa1 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm @@ -33,7 +33,7 @@ D << "You can't seem to find the [pick(faux_gadgets)]! Without it, [src] [pick(faux_problems)]." return D.visible_message("[D] begins to reactivate [src].", "You begin to reactivate [src]...") - if(do_after(user,30,needhand = 1, target = src)) + if(do_after(user,30, 1, target = src)) adjustBruteLoss(-getBruteLoss()) //Heal all brute damage stat = CONSCIOUS icon_state = icon_living @@ -49,7 +49,7 @@ if("Cannibalize") if(D.health < D.maxHealth) D.visible_message("[D] begins to cannibalize parts from [src].", "You begin to cannibalize parts from [src]...") - if(do_after(D, 60,5,0, target = src)) + if(do_after(D, 60, 0, target = src)) D.visible_message("[D] repairs itself using [src]'s remains!", "You repair yourself using [src]'s remains.") D.adjustBruteLoss(-src.maxHealth) new /obj/effect/decal/cleanable/oil/streak(get_turf(src)) diff --git a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm index 8c057a49d3c..b717b0ac252 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm @@ -113,28 +113,3 @@ /mob/living/simple_animal/drone/stripPanelEquip(obj/item/what, mob/who, where) ..(what, who, where, 1) - -/mob/living/simple_animal/drone/verb/quick_equip() - set name = "quick-equip" - set hidden = 1 - var/obj/item/I = get_active_hand() - var/obj/item/weapon/storage/S = get_inactive_hand() - var/obj/item/weapon/storage/T = internal_storage - if (!I) - usr << "You are not holding anything to equip!" - return - if(equip_to_appropriate_slot(I)) - if(hand) - update_inv_l_hand() - else - update_inv_r_hand() - else if(s_active && s_active.can_be_inserted(I,1)) //if storage active insert there - s_active.handle_item_insertion(I) - else if(istype(S, /obj/item/weapon/storage) && S.can_be_inserted(I,1)) //see if we have box in other hand - S.handle_item_insertion(I) - else if (istype(T) && T.can_be_inserted(I,1)) // If carrying storage item like toolbox - T.handle_item_insertion(I) - else if(!internal_storage) - equip_to_slot(I, slot_drone_storage) - else - usr << "You are unable to equip that!" diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index c4e5c7efb8c..9fabb8f858a 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -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) @@ -217,7 +210,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 +257,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 +290,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 +414,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 +491,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 +597,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 +625,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 +659,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 = "...but soon settles again. Guess they weren't ready to hatch after all." - -/obj/item/weapon/guardiancreator/biological/choose - random = FALSE - - /obj/item/weapon/paper/guardian name = "Holoparasite Guide" icon_state = "alienpaper_words" @@ -724,11 +690,6 @@ return - - - - - ///HUD /datum/hud/proc/guardian_hud(ui_style = 'icons/mob/screen_midnight.dmi') @@ -761,8 +722,6 @@ mymob.client.screen += adding - - //HUD BUTTONS /obj/screen/guardian diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index b2f13828c02..7d8e73e889b 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -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) diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm index 65a603ddb9e..a7c6dff1d42 100644 --- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm +++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm @@ -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() ..() diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 31ae1247d0a..f1774d355f4 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -155,6 +155,9 @@ if(ranged)//We ranged? Shoot at em if(target_distance >= 2 && ranged_cooldown <= 0)//But make sure they're a tile away at least, and our range attack is off cooldown OpenFire(target) + if(!Process_Spacemove()) // Drifting + walk(src,0) + return 1 if(retreat_distance != null)//If we have a retreat distance, check if we need to run from our target if(target_distance <= retreat_distance)//If target's closer than our retreat distance, run walk_away(src,target,retreat_distance,move_to_delay) @@ -320,4 +323,4 @@ . = 0 /mob/living/simple_animal/hostile/proc/AIShouldSleep(var/list/possible_targets) - return !FindTarget(possible_targets, 1) + return !FindTarget(possible_targets, 1) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/illusion.dm b/code/modules/mob/living/simple_animal/hostile/illusion.dm index 257967c8712..c0474b51e44 100644 --- a/code/modules/mob/living/simple_animal/hostile/illusion.dm +++ b/code/modules/mob/living/simple_animal/hostile/illusion.dm @@ -58,7 +58,7 @@ return var/mob/living/simple_animal/hostile/illusion/M = new(loc) M.faction = faction.Copy() - M.Copy_Parent(parent_mob, life_span, health/2, melee_damage_upper, multiply_chance) + M.Copy_Parent(parent_mob, 80, health/2, melee_damage_upper, multiply_chance/2) M.GiveTarget(L) ///////Actual Types///////// diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm index 95e12f3ba7c..bfd17bc69db 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm @@ -136,7 +136,6 @@ wanted_objects = list(/obj/item/weapon/ore/diamond, /obj/item/weapon/ore/gold, /obj/item/weapon/ore/silver, /obj/item/weapon/ore/uranium) - var/alerted = 0 var/chase_time = 100 /mob/living/simple_animal/hostile/asteroid/goldgrub/New() @@ -157,7 +156,8 @@ visible_message("The [src.name] tries to flee from [target.name]!") retreat_distance = 10 minimum_distance = 10 - Burrow() + spawn(chase_time) + Burrow() /mob/living/simple_animal/hostile/asteroid/goldgrub/AttackingTarget() if(istype(target, /obj/item/weapon/ore)) @@ -173,12 +173,9 @@ visible_message("The ore was swallowed whole!") /mob/living/simple_animal/hostile/asteroid/goldgrub/proc/Burrow()//Begin the chase to kill the goldgrub in time - if(!alerted) - alerted = 1 - spawn(chase_time) - if(alerted) - visible_message("The [src.name] buries into the ground, vanishing from sight!") - qdel(src) + if(!stat) + visible_message("The [src.name] buries into the ground, vanishing from sight!") + qdel(src) /mob/living/simple_animal/hostile/asteroid/goldgrub/bullet_act(obj/item/projectile/P) visible_message("The [P.name] was repelled by [src.name]'s girth!") @@ -220,12 +217,16 @@ minimum_distance = 3 pass_flags = PASSTABLE loot = list(/obj/item/organ/internal/hivelord_core) + var/next_brood = 0 + var/brood_cooldown = 20 /mob/living/simple_animal/hostile/asteroid/hivelord/OpenFire(the_target) - var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood(src.loc) - A.GiveTarget(target) - A.friends = friends - A.faction = faction + if(world.time >= next_brood) + var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood(src.loc) + A.GiveTarget(target) + A.friends = friends + A.faction = faction + next_brood = world.time + brood_cooldown return /mob/living/simple_animal/hostile/asteroid/hivelord/AttackingTarget() @@ -373,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("The [src.name] digs its tentacles under [target.name]!") new /obj/effect/goliath_tentacle/original(tturf) diff --git a/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm b/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm new file mode 100644 index 00000000000..7d75f4a747e --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/nanotrasen.dm @@ -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) \ No newline at end of file diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 082296dcaf2..ed176d9aa3c 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -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 diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index f1bc6dcabcc..968b4f0c16c 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -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]) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 585d7ddb96c..82362afc3c1 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -278,30 +278,12 @@ var/next_mob_id = 0 /mob/proc/equip_to_slot_or_del(obj/item/W, slot) equip_to_slot_if_possible(W, slot, 1, 1, 0) -//The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot. -var/list/slot_equipment_priority = list( \ - slot_back,\ - slot_wear_id,\ - slot_w_uniform,\ - slot_wear_suit,\ - slot_wear_mask,\ - slot_head,\ - slot_shoes,\ - slot_gloves,\ - slot_ears,\ - slot_glasses,\ - slot_belt,\ - slot_s_store,\ - slot_l_store,\ - slot_r_store\ - ) - //puts the item "W" into an appropriate slot in a human's inventory //returns 0 if it cannot, 1 if successful /mob/proc/equip_to_appropriate_slot(obj/item/W) if(!istype(W)) return 0 - for(var/slot in slot_equipment_priority) + for(var/slot in W.slot_equipment_priority) if(equip_to_slot_if_possible(W, slot, 0, 1, 1)) //qdel_on_fail = 0; disable_warning = 0; redraw_mob = 1 return 1 diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 2792e69b0f1..0b51dc021d1 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -373,7 +373,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp return /proc/IsAdminGhost(var/mob/user) - if(check_rights(R_ADMIN, 0) && istype(user, /mob/dead/observer)) + if(check_rights(R_ADMIN, 0) && istype(user, /mob/dead/observer) && user.client.AI_Interact) return 1 else return 0 \ No newline at end of file diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index 4e55cef28f9..7f622559c7d 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -7,7 +7,7 @@ gender = pick(MALE,FEMALE) underwear = random_underwear(gender) undershirt = random_undershirt(gender) - socks = random_socks(gender) + socks = random_socks() skin_tone = random_skin_tone() hair_style = random_hair_style(gender) facial_hair_style = random_facial_hair_style(gender) diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 689058e6aea..97fec9be03e 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -993,112 +993,90 @@ /datum/sprite_accessory/socks/nude name = "Nude" icon_state = null - gender = NEUTER /datum/sprite_accessory/socks/white_norm name = "Normal White" icon_state = "white_norm" - gender = NEUTER /datum/sprite_accessory/socks/black_norm name = "Normal Black" icon_state = "black_norm" - gender = NEUTER /datum/sprite_accessory/socks/white_short name = "Short White" icon_state = "white_short" - gender = NEUTER /datum/sprite_accessory/socks/black_short name = "Short Black" icon_state = "black_short" - gender = NEUTER /datum/sprite_accessory/socks/white_knee name = "Knee-high White" icon_state = "white_knee" - gender = NEUTER /datum/sprite_accessory/socks/black_knee name = "Knee-high Black" icon_state = "black_knee" - gender = NEUTER /datum/sprite_accessory/socks/thin_knee name = "Knee-high Thin" icon_state = "thin_knee" - gender = FEMALE /datum/sprite_accessory/socks/striped_knee name = "Knee-high Striped" icon_state = "striped_knee" - gender = NEUTER /datum/sprite_accessory/socks/rainbow_knee name = "Knee-high Rainbow" icon_state = "rainbow_knee" - gender = NEUTER /datum/sprite_accessory/socks/white_thigh name = "Thigh-high White" icon_state = "white_thigh" - gender = NEUTER /datum/sprite_accessory/socks/black_thigh name = "Thigh-high Black" icon_state = "black_thigh" - gender = NEUTER /datum/sprite_accessory/socks/thin_thigh name = "Thigh-high Thin" icon_state = "thin_thigh" - gender = FEMALE /datum/sprite_accessory/socks/striped_thigh name = "Thigh-high Striped" icon_state = "striped_thigh" - gender = NEUTER /datum/sprite_accessory/socks/rainbow_thigh name = "Thigh-high Rainbow" icon_state = "rainbow_thigh" - gender = NEUTER /datum/sprite_accessory/socks/usa_knee name = "Knee-High Freedom Stripes" icon_state = "assblastusa_knee" - gender = NEUTER /datum/sprite_accessory/socks/usa_thigh name = "Thigh-high Freedom Stripes" icon_state = "assblastusa_thigh" - gender = NEUTER /datum/sprite_accessory/socks/uk_knee name = "Knee-High UK Stripes" icon_state = "uk_knee" - gender = NEUTER /datum/sprite_accessory/socks/uk_thigh name = "Thigh-high UK Stripes" icon_state = "uk_thigh" - gender = NEUTER /datum/sprite_accessory/socks/commie_knee name = "Knee-High Commie Stripes" icon_state = "commie_knee" - gender = NEUTER /datum/sprite_accessory/socks/commie_thigh name = "Thigh-high Commie Stripes" icon_state = "commie_thigh" - gender = NEUTER /datum/sprite_accessory/socks/pantyhose name = "Pantyhose" icon_state = "pantyhose" - gender = FEMALE //////////.////////////////// // MutantParts Definitions // diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm deleted file mode 100644 index c713e14bb45..00000000000 --- a/code/modules/nano/nanoui.dm +++ /dev/null @@ -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 = 0, 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) - // Strip junk. - send_data_json = replacetext(send_data_json, "'", "'") - send_data_json = replacetext(send_data_json, "ÿ", "") - - // Populate it. - var/send_html = replacetext(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(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) \ No newline at end of file diff --git a/code/modules/nano/states/admin.dm b/code/modules/nano/states/admin.dm deleted file mode 100644 index d4048b9e11d..00000000000 --- a/code/modules/nano/states/admin.dm +++ /dev/null @@ -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 diff --git a/code/modules/nano/states/conscious.dm b/code/modules/nano/states/conscious.dm deleted file mode 100644 index 07574e91da7..00000000000 --- a/code/modules/nano/states/conscious.dm +++ /dev/null @@ -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 diff --git a/code/modules/nano/states/contained.dm b/code/modules/nano/states/contained.dm deleted file mode 100644 index 89b18d0b136..00000000000 --- a/code/modules/nano/states/contained.dm +++ /dev/null @@ -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) diff --git a/code/modules/nano/states/deep_inventory.dm b/code/modules/nano/states/deep_inventory.dm deleted file mode 100644 index d01f43bb2f4..00000000000 --- a/code/modules/nano/states/deep_inventory.dm +++ /dev/null @@ -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) diff --git a/code/modules/nano/states/hands.dm b/code/modules/nano/states/hands.dm deleted file mode 100644 index 32807335433..00000000000 --- a/code/modules/nano/states/hands.dm +++ /dev/null @@ -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 \ No newline at end of file diff --git a/code/modules/nano/states/inventory.dm b/code/modules/nano/states/inventory.dm deleted file mode 100644 index e1160339e8a..00000000000 --- a/code/modules/nano/states/inventory.dm +++ /dev/null @@ -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) diff --git a/code/modules/nano/states/physical.dm b/code/modules/nano/states/physical.dm deleted file mode 100644 index 569e284e447..00000000000 --- a/code/modules/nano/states/physical.dm +++ /dev/null @@ -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. diff --git a/code/modules/nano/states/self.dm b/code/modules/nano/states/self.dm deleted file mode 100644 index 9817c68ac0e..00000000000 --- a/code/modules/nano/states/self.dm +++ /dev/null @@ -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) diff --git a/code/modules/nano/states/states.dm b/code/modules/nano/states/states.dm deleted file mode 100644 index 532f7e4dfb9..00000000000 --- a/code/modules/nano/states/states.dm +++ /dev/null @@ -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. \ No newline at end of file diff --git a/code/modules/ninja/ninja_event.dm b/code/modules/ninja/ninja_event.dm index fda579af7ef..e4b60e7d420 100644 --- a/code/modules/ninja/ninja_event.dm +++ b/code/modules/ninja/ninja_event.dm @@ -76,64 +76,37 @@ Contents: else if(M.assigned_role in command_positions) possible_targets[M] = 1 //good-guy +/* + Alright, so, if I had my way I'd axe all this retarded bullshit entirely, but I know some people would complain because + porting ninja specifics to the random gen system would go horribly. I can at the very least axe 99% of the autism + and make ninja code slightly more bearable. + - Iamgoofball +*/ var/list/objectives = list(1,2,3,4) - while(Mind.objectives.len < 6) //still not enough objectives! - switch(pick_n_take(objectives)) + while(Mind.objectives.len < 6) //still not enough objectives! // WHY DOES THIS CALL FOR 6 OBJECTIVES + switch(pick_n_take(objectives)) // BUT THEN PREVENT YOU FROM GETTING 4 IN THE END if(1) //research - var/datum/objective/download/O = new /datum/objective/download() - O.owner = Mind - O.gen_amount_goal() - Mind.objectives += O + add_objective(Mind, /datum/objective/download) if(2) //steal - var/datum/objective/steal/special/O = new /datum/objective/steal/special() - O.owner = Mind - Mind.objectives += O + add_objective(Mind, /datum/objective/default/steal/special) if(3) //protect/kill - if(!possible_targets.len) continue - var/selected = rand(1,possible_targets.len) - var/datum/mind/M = possible_targets[selected] - var/is_bad_guy = possible_targets[M] - possible_targets.Cut(selected,selected+1) - - if(is_bad_guy ^ helping_station) //kill (good-ninja + bad-guy or bad-ninja + good-guy) - var/datum/objective/assassinate/O = new /datum/objective/assassinate() - O.owner = Mind - O.target = M - O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]." - Mind.objectives += O - else //protect - var/datum/objective/protect/O = new /datum/objective/protect() - O.owner = Mind - O.target = M - O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm." - Mind.objectives += O + if(prob(50)) + add_objective(Mind, /datum/objective/default/assassinate) + else + add_objective(Mind, /datum/objective/default/protect) if(4) //debrain/capture - if(!possible_targets.len) continue - var/selected = rand(1,possible_targets.len) - var/datum/mind/M = possible_targets[selected] - var/is_bad_guy = possible_targets[M] - possible_targets.Cut(selected,selected+1) - - if(is_bad_guy ^ helping_station) //debrain (good-ninja + bad-guy or bad-ninja + good-guy) - var/datum/objective/debrain/O = new /datum/objective/debrain() - O.owner = Mind - O.target = M - O.explanation_text = "Steal the brain of [M.current.real_name]." - Mind.objectives += O - else //capture - var/datum/objective/capture/O = new /datum/objective/capture() - O.owner = Mind - O.gen_amount_goal() - Mind.objectives += O + if(prob(50)) + add_objective(Mind, /datum/objective/default/debrain) + else + add_objective(Mind, /datum/objective/capture) else break //Add a survival objective since it's usually broad enough for any round type. - var/datum/objective/O = new /datum/objective/survive() - O.owner = Mind - Mind.objectives += O + add_objective(Mind, /datum/objective/escape_obj/survive) + //add some RP-fluff Mind.store_memory("I am an elite mercenary assassin of the mighty Spider Clan. A SPACE NINJA!") diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 240c534e634..a53171e4621 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -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, 515) 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 diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index b2ca9ae4a1b..9a021cd1b4e 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -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 diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm index cc65f704968..aa748fbbf03 100644 --- a/code/modules/power/singularity/containment_field.dm +++ b/code/modules/power/singularity/containment_field.dm @@ -92,7 +92,7 @@ var/stun = min(shock_damage, 15) user.Stun(stun) user.Weaken(10) - user.burn_skin(shock_damage) + user.electrocute_act(shock_damage, src, 1) user.visible_message("[user.name] was shocked by the [src.name]!", \ "You feel a powerful shock course through your body, sending you flying!", \ "You hear a heavy electrical crack.") diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index a51b1f0c7bd..9d0238fba71 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -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 off","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 off","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) diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index 58f62ad9f8f..f138b106657 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -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() diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index f1af4c5f66f..e1e2018779e 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -73,6 +73,7 @@ var/list/blacklisted_tesla_types = list(/obj/machinery/atmospherics, spawn(100) var/obj/singularity/energy_ball/EB = new(loc) orbiting_balls.Add(EB) + poi_list.Remove(EB) EB.transform *= pick(0.3,0.4,0.5,0.6,0.7) EB.is_orbiting = 1 var/icon/I = icon(icon,icon_state,dir) diff --git a/code/modules/projectiles/ammunition/magazines.dm b/code/modules/projectiles/ammunition/magazines.dm index 818601f831d..ea35c457cb9 100644 --- a/code/modules/projectiles/ammunition/magazines.dm +++ b/code/modules/projectiles/ammunition/magazines.dm @@ -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() diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index ac922b9637a..51e0a7822be 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -428,6 +428,10 @@ obj/item/weapon/gun/proc/newshot() process_fire(target, user, 1, params) +/obj/item/weapon/gun/proc/unlock() //used in summon guns and as a convience for admins + if(pin) + qdel(pin) + pin = new /obj/item/device/firing_pin ///////////// // ZOOMING // diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index e2659248250..ea52cf11f12 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -39,7 +39,7 @@ item_state = "laser" desc = "An industrial-grade heavy-duty laser rifle with a modified laser lense to scatter its shot into multiple smaller lasers. The inner-core can self-charge for theorically infinite use." origin_tech = "combat=5;materials=4;powerstorage=4" - ammo_type = list(/obj/item/ammo_casing/energy/laser, /obj/item/ammo_casing/energy/laser/scatter) + ammo_type = list(/obj/item/ammo_casing/energy/laser/scatter, /obj/item/ammo_casing/energy/laser) /obj/item/weapon/gun/energy/laser/cyborg can_charge = 0 @@ -55,7 +55,7 @@ /obj/item/weapon/gun/energy/laser/scatter name = "scatter laser gun" desc = "A laser gun equipped with a refraction kit that spreads bolts." - ammo_type = list(/obj/item/ammo_casing/energy/laser, /obj/item/ammo_casing/energy/laser/scatter) + ammo_type = list(/obj/item/ammo_casing/energy/laser/scatter, /obj/item/ammo_casing/energy/laser) /obj/item/weapon/gun/energy/lasercannon name = "laser cannon" diff --git a/code/modules/projectiles/guns/mounted.dm b/code/modules/projectiles/guns/mounted.dm new file mode 100644 index 00000000000..d6a54ffa0ea --- /dev/null +++ b/code/modules/projectiles/guns/mounted.dm @@ -0,0 +1,28 @@ +/obj/item/weapon/gun/energy/gun/advtaser/mounted + name = "mounted taser" + desc = "An arm mounted dual-mode weapon that fires electrodes and disabler shots." + icon_state = "armcannon" + force = 5 + selfcharge = 1 + flags = NODROP + slot_flags = null + w_class = 5 + can_flashlight = 0 + +/obj/item/weapon/gun/energy/gun/advtaser/mounted/dropped()//if somebody manages to drop this somehow... + src.loc = null//send it to nullspace to get retrieved by the implant later on. gotta cover those edge cases. + +/obj/item/weapon/gun/energy/laser/mounted + name = "mounted laser" + desc = "An arm mounted cannon that fires lethal lasers. Doesn't come with a charge beam." + icon_state = "armcannon" + item_state = "armcannonlase" + force = 5 + selfcharge = 1 + flags = NODROP + slot_flags = null + w_class = 5 + materials = null + +/obj/item/weapon/gun/energy/laser/mounted/dropped() + src.loc = null diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index 80f135be1ba..681db297fc3 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -37,7 +37,6 @@ if(istype(AM, mag_type)) if(magazine) user << "You perform a tactical reload on \the [src], replacing the magazine." - 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 \ No newline at end of file diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm index ff5927f326c..ee8f3198a85 100644 --- a/code/modules/projectiles/guns/projectile/shotgun.dm +++ b/code/modules/projectiles/guns/projectile/shotgun.dm @@ -113,6 +113,40 @@ ..() user << "The bolt is [bolt_open ? "open" : "closed"]." + +/obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted + name = "enchanted bolt action rifle" + desc = "Careful not to lose your head." + var/guns_left = 30 + mag_type = /obj/item/ammo_box/magazine/internal/boltaction/enchanted + +/obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted/New() + ..() + bolt_open = 1 + pump() + +/obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted/dropped() + guns_left = 0 + +/obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted/shoot_live_shot(mob/living/user as mob|obj, pointblank = 0, mob/pbtarget = null, message = 1) + ..() + if(guns_left) + var/obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted/GUN = new + GUN.guns_left = src.guns_left - 1 + user.drop_item() + user.swap_hand() + user.put_in_hands(GUN) + else + user.drop_item() + src.throw_at_fast(pick(oview(7,get_turf(user))),1,1) + user.visible_message("[user] tosses aside the spent rifle!") + + +/obj/item/ammo_box/magazine/internal/boltaction/enchanted + max_ammo =1 + + + ///////////////////////////// // DOUBLE BARRELED SHOTGUN // ///////////////////////////// diff --git a/code/modules/projectiles/guns/projectile/toy.dm b/code/modules/projectiles/guns/projectile/toy.dm index 06fd47933ba..2555a8ac16a 100644 --- a/code/modules/projectiles/guns/projectile/toy.dm +++ b/code/modules/projectiles/guns/projectile/toy.dm @@ -16,6 +16,9 @@ /obj/item/weapon/gun/projectile/automatic/toy/process_chamber(eject_casing = 0, empty_chamber = 1) ..() +/obj/item/weapon/gun/projectile/automatic/toy/unrestricted + pin = /obj/item/device/firing_pin + /obj/item/weapon/gun/projectile/automatic/toy/pistol name = "foam force pistol" desc = "A small, easily concealable toy handgun. Ages 8 and up." @@ -39,6 +42,12 @@ magazine = new /obj/item/ammo_box/magazine/toy/pistol/riot(src) ..() +/obj/item/weapon/gun/projectile/automatic/toy/pistol/unrestricted + pin = /obj/item/device/firing_pin + +/obj/item/weapon/gun/projectile/automatic/toy/pistol/riot/unrestricted + pin = /obj/item/device/firing_pin + /obj/item/weapon/gun/projectile/shotgun/toy name = "foam force shotgun" desc = "A toy shotgun with wood furniture and a four-shell capacity underneath. Ages 8 and up." @@ -55,6 +64,9 @@ if(chambered && !chambered.BB) qdel(chambered) +/obj/item/weapon/gun/projectile/shotgun/toy/unrestricted + pin = /obj/item/device/firing_pin + /obj/item/weapon/gun/projectile/shotgun/toy/crossbow name = "foam force crossbow" desc = "A weapon favored by many overactive children. Ages 8 and up." @@ -77,6 +89,10 @@ /obj/item/weapon/gun/projectile/automatic/c20r/toy/process_chamber(eject_casing = 0, empty_chamber = 1) ..() + +/obj/item/weapon/gun/projectile/automatic/c20r/toy/unrestricted + pin = /obj/item/device/firing_pin + /obj/item/weapon/gun/projectile/automatic/l6_saw/toy name = "donksoft LMG" desc = "A heavily modified toy light machine gun, designated 'L6 SAW'. Ages 8 and up." @@ -86,4 +102,7 @@ mag_type = /obj/item/ammo_box/magazine/toy/m762 /obj/item/weapon/gun/projectile/automatic/l6_saw/toy/process_chamber(eject_casing = 0, empty_chamber = 1) - ..() \ No newline at end of file + ..() + +/obj/item/weapon/gun/projectile/automatic/l6_saw/toy/unrestricted + pin = /obj/item/device/firing_pin \ No newline at end of file diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index e29f2604fe5..cb9f8e0894e 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -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, 412, 600) 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) diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index 2e19186075b..eacd2fba7e9 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -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() diff --git a/code/modules/reagents/chemistry/reagents/blob_reagents.dm b/code/modules/reagents/chemistry/reagents/blob_reagents.dm index 3ec9c3c9a0d..4704c01e251 100644 --- a/code/modules/reagents/chemistry/reagents/blob_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/blob_reagents.dm @@ -2,6 +2,7 @@ /datum/reagent/blob name = "Unknown" description = "shouldn't exist and you should adminhelp immediately." + var/shortdesc = null //just damage and on_mob effects, doesn't include special, blob-tile only effects var/blobbernaut_message = "slams" //blobbernaut attack verb var/message = "The blob strikes you" //message sent to any mob hit by the blob var/message_living = null //extension to first mob sent to only living mobs i.e. silicons have no skin to be burnt @@ -41,6 +42,7 @@ name = "Sporing Pods" id = "sporing_pods" description = "will do low toxin damage and produce fragile spores when killed or on expanding." + shortdesc = "will do low toxin damage." color = "#E88D5D" message_living = ", and you feel sick" @@ -70,6 +72,7 @@ name = "Replicating Foam" id = "replicating_foam" description = "will do medium brute damage and replicate when damaged." + shortdesc = "will do medium brute damage." color = "#7B5A57" /datum/reagent/blob/replicating_foam/reaction_mob(mob/living/M, method=TOUCH, reac_volume) @@ -93,7 +96,8 @@ /datum/reagent/blob/energized_fibers name = "Energized Fibers" id = "energized_fibers" - description = "will do low burn, high stamina damage, and react to stamina damage." + description = "will do low burn and high stamina damage, and react to stamina damage." + shortdesc = "will do low burn and high stamina damage." color = "#FFDC73" blobbernaut_message = "shocks" message_living = ", and you feel a strong tingling sensation" @@ -153,7 +157,7 @@ /datum/reagent/blob/envenomed_filaments name = "Envenomed Filaments" id = "envenomed_filaments" - description = "will cause medium toxin damage, stamina damage, and inject targets with toxins." + description = "will cause medium toxin and stamina damage, and inject targets with toxins." color = "#9ACD32" message_living = ", and you feel sick and nauseated" @@ -170,7 +174,7 @@ /datum/reagent/blob/lexorin_jelly name = "Lexorin Jelly" id = "lexorin_jelly" - description = "will cause low brute damage, high oxygen damage, and cause targets to be unable to breathe." + description = "will cause low brute and high oxygen damage, and cause targets to be unable to breathe." color = "#00E5B1" message_living = ", and your lungs feel heavy and weak" @@ -208,7 +212,7 @@ /datum/reagent/blob/cryogenic_liquid name = "Cryogenic Liquid" id = "cryogenic_liquid" - description = "will do low burn damage, stamina damage, and cause targets to freeze." + description = "will do low burn and stamina damage, and cause targets to freeze." color = "#8BA6E9" blobbernaut_message = "splashes" message = "The blob splashes you with an icy liquid" @@ -229,6 +233,7 @@ name = "Synchronous Mesh" id = "synchronous_mesh" description = "will do brute damage for each nearby blob and spread damage between nearby blobs." + shortdesc = "will do brute damage for each nearby blob." color = "#65ADA2" blobbernaut_message = "synchronously strikes" message = "The blobs strike you" @@ -259,7 +264,8 @@ /datum/reagent/blob/pressurized_slime name = "Pressurized Slime" id = "pressurized_slime" - description = "will do low brute damage, oxygen damage, stamina damage, and wet tiles when damaged or killed." + description = "will do low brute, oxygen, and stamina damage, and wet tiles when damaged or killed." + shortdesc = "will do low brute, oxygen, and stamina damage, and wet tiles under targets." color = "#AAAABB" blobbernaut_message = "emits slime at" message = "The blob splashes into you" diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 11d169070d1..39986a13f8f 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -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 @@ -763,6 +763,16 @@ if(method==PATCH || method==INGEST || method==INJECT || (method == VAPOR && prob(min(reac_volume,100)*(1 - touch_protection)))) M.ContractDisease(new /datum/disease/transformation/xeno(0)) +/datum/reagent/fungalspores + name = "Tubercle bacillus Cosmosis microbes" + id = "fungalspores" + description = "Active fungal spores." + color = "#92D17D" // rgb: 146, 209, 125 + +/datum/reagent/fungalspores/reaction_mob(mob/M, method=TOUCH, reac_volume, show_message = 1, touch_protection = 0) + if(method==PATCH || method==INGEST || method==INJECT || (method == VAPOR && prob(min(reac_volume,100)*(1 - touch_protection)))) + M.ForceContractDisease(new /datum/disease/tuberculosis(0)) + /datum/reagent/fluorosurfactant//foam precursor name = "Fluorosurfactant" id = "fluorosurfactant" diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 100c6e85271..47d9191bcfd 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -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 diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm index 1ac7629b5bd..36b9eb2ed21 100644 --- a/code/modules/reagents/reagent_containers/bottle.dm +++ b/code/modules/reagents/reagent_containers/bottle.dm @@ -296,4 +296,16 @@ name = "Spanish flu culture bottle" desc = "A small bottle. Contains a sample of Inquisitius." icon_state = "bottle3" - spawned_disease = /datum/disease/fluspanish \ No newline at end of file + spawned_disease = /datum/disease/fluspanish + +/obj/item/weapon/reagent_containers/glass/bottle/tuberculosis + name = "Fungal Tuberculosis culture bottle" + desc = "A small bottle. Contains a sample of Fungal Tubercle bacillus." + icon_state = "bottle3" + spawned_disease = /datum/disease/tuberculosis + +/obj/item/weapon/reagent_containers/glass/bottle/tuberculosiscure + name = "BVAK bottle" + desc = "A small bottle containing Bio Virus Antidote Kit." + icon_state = "bottle5" + list_reagents = list("atropine" = 5, "epinephrine" = 5, "salbutamol" = 10, "spaceacillin" = 10) diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index e9275ebd71c..11ad8afc028 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -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 @@ -282,3 +282,12 @@ user << "[src]'s contents spill all over you!" reagents.reaction(user, TOUCH) reagents.clear_reagents() + +/obj/item/weapon/reagent_containers/glass/bucket/equip_to_best_slot(var/mob/M) + if(reagents.total_volume) //If there is water in a bucket, don't quick equip it to the head + var/index = slot_equipment_priority.Find(slot_head) + slot_equipment_priority.Remove(slot_head) + . = ..() + slot_equipment_priority.Insert(index, slot_head) + return + return ..() diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index df207b0b3cf..090942bf0e6 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -112,3 +112,11 @@ name = "morphine medipen" desc = "A rapid way to get you out of a tight situation and fast! You'll feel rather drowsy, though." list_reagents = list("morphine" = 10) + +/obj/item/weapon/reagent_containers/hypospray/medipen/tuberculosiscure + name = "BVAK autoinjector" + desc = "Bio Virus Antidote Kit autoinjector. Has a two use system for yourself, and someone else. Inject when infected." + icon_state = "stimpen" + volume = 60 + amount_per_transfer_from_this = 30 + list_reagents = list("atropine" = 10, "epinephrine" = 10, "salbutamol" = 20, "spaceacillin" = 20) diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm index 135b716506b..f35a8196405 100644 --- a/code/modules/research/stock_parts.dm +++ b/code/modules/research/stock_parts.dm @@ -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" \ No newline at end of file + origin_tech = "materials=8;programming=8;magnets=8;powerstorage=8;bluespace=8;combat=8;biotech=8;syndicate=8;engineering=8;plasmatech=8" diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 8ddda4e49f7..3097d3f8b1b 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -460,6 +460,7 @@ unacidable = 1 mouse_opacity = 0 var/mob/living/immune = list() // the one who creates the timestop is immune + var/list/stopped_atoms = list() var/freezerange = 2 var/duration = 140 alpha = 125 @@ -474,9 +475,10 @@ /obj/effect/timestop/proc/timestop() playsound(get_turf(src), 'sound/magic/TIMEPARADOX2.ogg', 100, 1, -1) - while(loc) - if(duration) - for(var/mob/living/M in orange (freezerange, src.loc)) + for(var/i in 1 to duration-1) + for(var/atom/A in orange (freezerange, src.loc)) + if(istype(A, /mob/living)) + var/mob/living/M = A if(M in immune) continue M.stunned = 10 @@ -485,24 +487,36 @@ var/mob/living/simple_animal/hostile/H = M H.AIStatus = AI_OFF H.LoseTarget() - continue - for(var/obj/item/projectile/P in orange (freezerange, src.loc)) + stopped_atoms |= M + else if(istype(A, /obj/item/projectile)) + var/obj/item/projectile/P = A P.paused = TRUE - duration -- - else - for(var/mob/living/M in orange (freezerange+2, src.loc)) //longer range incase they lag out of it or something - M.stunned = 0 - M.anchored = 0 - if(istype(M, /mob/living/simple_animal/hostile)) - var/mob/living/simple_animal/hostile/H = M - H.AIStatus = initial(H.AIStatus) - continue - for(var/obj/item/projectile/P in orange(freezerange+2, src.loc)) - P.paused = FALSE - qdel(src) - return + stopped_atoms |= P + + for(var/mob/living/M in stopped_atoms) + if(get_dist(get_turf(M),get_turf(src)) > freezerange) //If they lagged/ran past the timestop somehow, just ignore them + unfreeze_mob(M) + stopped_atoms -= M sleep(1) + //End + for(var/mob/living/M in stopped_atoms) + unfreeze_mob(M) + + for(var/obj/item/projectile/P in stopped_atoms) + P.paused = FALSE + qdel(src) + return + + + +/obj/effect/timestop/proc/unfreeze_mob(mob/living/M) + M.stunned = 0 + M.anchored = 0 + if(istype(M, /mob/living/simple_animal/hostile)) + var/mob/living/simple_animal/hostile/H = M + H.AIStatus = initial(H.AIStatus) + /obj/effect/timestop/wizard duration = 100 diff --git a/code/modules/ruins/ruin_areas.dm b/code/modules/ruins/ruin_areas.dm new file mode 100644 index 00000000000..f0c8cade312 --- /dev/null +++ b/code/modules/ruins/ruin_areas.dm @@ -0,0 +1,23 @@ +//Parent types + +/area/ruin/ + name = "\improper Unexplored Location" + icon_state = "away" + + +/area/ruin/unpowered + always_unpowered = 0 + +/area/ruin/unpowered/no_grav + has_gravity = 0 + +/area/ruin/powered + requires_power = 0 + + + +//Areas + +/area/ruin/unpowered/no_grav/way_home + name = "\improper Salvation" + icon_state = "away" \ No newline at end of file diff --git a/code/modules/surgery/cavity_implant.dm b/code/modules/surgery/cavity_implant.dm index c32bca635a4..c56b673a067 100644 --- a/code/modules/surgery/cavity_implant.dm +++ b/code/modules/surgery/cavity_implant.dm @@ -25,7 +25,7 @@ /datum/surgery_step/handle_cavity/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(tool) - if(IC || tool.w_class > 3 || NODROP in tool.flags || istype(tool, /obj/item/organ)) + if(IC || tool.w_class > 3 || (NODROP in tool.flags) || istype(tool, /obj/item/organ)) user << "You can't seem to fit [tool] in [target]'s [target_zone]!" return 0 else diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index b904d93f9e3..e6314c5b040 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -253,6 +253,73 @@ if(H.stat == CONSCIOUS) H << "You feel your heart beating again!" +/obj/item/organ/internal/cyberimp/chest/arm_mod//dummy parent item for making arm-mod implants. works best with nodrop items that are sent to nullspace upon being dropped. + name = "Arm-mounted item implant" + desc = "You shouldn't see this! Adminhelp and report this as an issue on github!" + icon_state = "chest_implant" + implant_color = "#007ACC" + slot = "shoulders" + origin_tech = "materials=5;biotech=4;powerstorage=4" + organ_action_name = "Toggle Arm Mod" + var/obj/holder//is defined as the retractable item itself. ensure this is defined somewhere! + var/out = 0//determines if the item is in the owner's hand or not + var/overloaded = 0//is set to 1 when owner gets EMPed. if set to 1, implant doesn't work. + +/obj/item/organ/internal/cyberimp/chest/arm_mod/ui_action_click() + if(overloaded)//ensure the implant isn't broken + owner.visible_message("The implant doesn't respond. It seems to be broken...") + return + if(out)//check if the owner has the item out already + owner.unEquip(holder, 1)//if he does, take it away. then, + holder.loc = null//stash it in nullspace + out = 0//and set this to clarify the item isn't out. + owner.visible_message("You retract [holder].") + playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1) + else//if he doesn't have the item out + if(owner.put_in_hands(holder))//put it in his hands. + out = 1 + owner.visible_message("You extend [holder]!") + playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1) + else//if this fails to put the item in his hands, + holder.loc = null//keep it in nullspace + owner.visible_message("You can't extend [holder] if you can't use your hands!") + +/obj/item/organ/internal/cyberimp/chest/arm_mod/emp_act(severity)//if the implant gets EMPed... + if(!owner || overloaded)//ensure that it's in an owner and that it's not already EMPed, then... + return + if(out)//check if he has the item out... + owner.unEquip(holder, 1)//if he does, take it away. + holder.loc = null + out = 0 + owner.visible_message("[holder] forcibly retracts into your arm.") + owner.visible_message("A loud bang comes from [owner]...") + playsound(get_turf(owner), 'sound/weapons/flashbang.ogg', 100, 1) + owner << "You feel an explosion erupt inside you as your chest implant breaks. Is it hot in here?" + owner.adjust_fire_stacks(20) + owner.IgniteMob()//ignite the owner, as well as + owner.say("AUUUUUUUUUUUUUUUUUUGH!!") + owner.adjustFireLoss(25)//severely injure him! + overloaded = 1//then make sure this can't happen again by breaking the implant. + +/obj/item/organ/internal/cyberimp/chest/arm_mod/tase//mounted, self-charging taser! + name = "Arm-cannon taser implant" + desc = "A variant of the arm cannon implant that fires electrodes and disabler shots. The cannon emerges from the subject's arms and remains in the shoulders when not in use." + icon_state = "armcannon_tase_implant" + origin_tech = "materials=5;combat=5;biotech=4;powerstorage=4" + organ_action_name = "Toggle Arm Cannon Taser" + +/obj/item/organ/internal/cyberimp/chest/arm_mod/tase/New()//when the implant is created... + holder = new /obj/item/weapon/gun/energy/gun/advtaser/mounted(src)//assign a brand new item to it. (in this case, a gun) + +/obj/item/organ/internal/cyberimp/chest/arm_mod/lase//mounted, self-charging laser! + name = "Arm-cannon laser implant" + desc = "A variant of the arm cannon implant that fires lethal laser beams. The cannon emerges from the subject's arms and remains in the shoulders when not in use." + icon_state = "armcannon_lase_implant" + origin_tech = "materials=5;combat=5;biotech=4;powerstorage=4;syndicate=5"//this is kinda nutty and i might lower it + organ_action_name = "Toggle Arm Cannon Laser" + +/obj/item/organ/internal/cyberimp/chest/arm_mod/lase/New() + holder = new /obj/item/weapon/gun/energy/laser/mounted(src) //BOX O' IMPLANTS diff --git a/code/modules/nano/external.dm b/code/modules/tgui/external.dm similarity index 50% rename from code/modules/nano/external.dm rename to code/modules/tgui/external.dm index 7a15197eedc..1efa5cee8fe 100644 --- a/code/modules/nano/external.dm +++ b/code/modules/tgui/external.dm @@ -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)) diff --git a/code/modules/tgui/states/admin.dm b/code/modules/tgui/states/admin.dm new file mode 100644 index 00000000000..c9a3bb467c4 --- /dev/null +++ b/code/modules/tgui/states/admin.dm @@ -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 diff --git a/code/modules/tgui/states/conscious.dm b/code/modules/tgui/states/conscious.dm new file mode 100644 index 00000000000..1b781a458d7 --- /dev/null +++ b/code/modules/tgui/states/conscious.dm @@ -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 diff --git a/code/modules/tgui/states/contained.dm b/code/modules/tgui/states/contained.dm new file mode 100644 index 00000000000..20cda3241e0 --- /dev/null +++ b/code/modules/tgui/states/contained.dm @@ -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) diff --git a/code/modules/tgui/states/deep_inventory.dm b/code/modules/tgui/states/deep_inventory.dm new file mode 100644 index 00000000000..4fef9ad5b3c --- /dev/null +++ b/code/modules/tgui/states/deep_inventory.dm @@ -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) diff --git a/code/modules/nano/states/default.dm b/code/modules/tgui/states/default.dm similarity index 52% rename from code/modules/nano/states/default.dm rename to code/modules/tgui/states/default.dm index cd5155b9c05..8e1c3e8dec9 100644 --- a/code/modules/nano/states/default.dm +++ b/code/modules/tgui/states/default.dm @@ -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 ..() diff --git a/code/modules/tgui/states/hands.dm b/code/modules/tgui/states/hands.dm new file mode 100644 index 00000000000..536a90597e4 --- /dev/null +++ b/code/modules/tgui/states/hands.dm @@ -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 \ No newline at end of file diff --git a/code/modules/tgui/states/inventory.dm b/code/modules/tgui/states/inventory.dm new file mode 100644 index 00000000000..a5f7233f00d --- /dev/null +++ b/code/modules/tgui/states/inventory.dm @@ -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) diff --git a/code/modules/nano/states/notcontained.dm b/code/modules/tgui/states/notcontained.dm similarity index 66% rename from code/modules/nano/states/notcontained.dm rename to code/modules/tgui/states/notcontained.dm index 11dfe67025c..8df75b57626 100644 --- a/code/modules/nano/states/notcontained.dm +++ b/code/modules/tgui/states/notcontained.dm @@ -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) diff --git a/code/modules/tgui/states/physical.dm b/code/modules/tgui/states/physical.dm new file mode 100644 index 00000000000..a3fae3b276e --- /dev/null +++ b/code/modules/tgui/states/physical.dm @@ -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. diff --git a/code/modules/tgui/states/self.dm b/code/modules/tgui/states/self.dm new file mode 100644 index 00000000000..edb7c3ef300 --- /dev/null +++ b/code/modules/tgui/states/self.dm @@ -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) diff --git a/code/modules/tgui/states/states.dm b/code/modules/tgui/states/states.dm new file mode 100644 index 00000000000..195d9394e3e --- /dev/null +++ b/code/modules/tgui/states/states.dm @@ -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. \ No newline at end of file diff --git a/code/modules/nano/states/zlevel.dm b/code/modules/tgui/states/zlevel.dm similarity index 53% rename from code/modules/nano/states/zlevel.dm rename to code/modules/tgui/states/zlevel.dm index 199c22e22c0..2f06f36c8f8 100644 --- a/code/modules/nano/states/zlevel.dm +++ b/code/modules/tgui/states/zlevel.dm @@ -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 diff --git a/code/modules/nano/subsystem.dm b/code/modules/tgui/subsystem.dm similarity index 60% rename from code/modules/nano/subsystem.dm rename to code/modules/tgui/subsystem.dm index b539566bd45..14b4dd5f7e5 100644 --- a/code/modules/nano/subsystem.dm +++ b/code/modules/tgui/subsystem.dm @@ -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. diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm new file mode 100644 index 00000000000..8cc69f3145e --- /dev/null +++ b/code/modules/tgui/tgui.dm @@ -0,0 +1,348 @@ + /** + * 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.html, "{}", 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, + "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) \ No newline at end of file diff --git a/code/modules/vehicles/atv.dm b/code/modules/vehicles/atv.dm new file mode 100644 index 00000000000..6d9d94747dd --- /dev/null +++ b/code/modules/vehicles/atv.dm @@ -0,0 +1,82 @@ + +/obj/vehicle/atv + name = "all-terrain vehicle" + desc = "An all-terrain vehicle built for traversing rough terrain with ease. One of the few old-earth technologies that are still relevant on most planet-bound outposts." + icon_state = "atv" + keytype = /obj/item/key + generic_pixel_x = 0 + generic_pixel_y = 4 + vehicle_move_delay = 1 + var/static/image/atvcover = null + + +/obj/vehicle/atv/New() + ..() + if(!atvcover) + atvcover = image("icons/obj/vehicles.dmi", "atvcover") + atvcover.layer = MOB_LAYER + 0.1 + + +obj/vehicle/atv/post_buckle_mob(mob/living/M) + if(buckled_mob) + overlays += atvcover + else + overlays -= atvcover + + +/obj/vehicle/atv/handle_vehicle_layer() + if(dir == SOUTH) + layer = MOB_LAYER+0.1 + else + layer = OBJ_LAYER + + +//TURRETS! +/obj/vehicle/atv/turret + var/obj/machinery/porta_turret/syndicate/vehicle_turret/turret = null + + +/obj/machinery/porta_turret/syndicate/vehicle_turret + name = "mounted turret" + scan_range = 7 + emp_vunerable = 1 + density = 0 + + +/obj/vehicle/atv/turret/New() + ..() + turret = new(loc) + turret.base = src + + +/obj/vehicle/atv/turret/handle_vehicle_layer() + if(dir == SOUTH) + layer = MOB_LAYER+0.1 + else + layer = OBJ_LAYER + + if(turret) + if(dir == NORTH) + turret.layer = MOB_LAYER+0.1 + else + turret.layer = OBJ_LAYER + + +/obj/vehicle/atv/turret/handle_vehicle_offsets() + ..() + if(turret) + turret.loc = loc + switch(dir) + if(NORTH) + turret.pixel_x = 0 + turret.pixel_y = 4 + if(EAST) + turret.pixel_x = -12 + turret.pixel_y = 4 + if(SOUTH) + turret.pixel_x = 0 + turret.pixel_y = 4 + if(WEST) + turret.pixel_x = 12 + turret.pixel_y = 4 + diff --git a/code/modules/vehicles/pimpin_ride.dm b/code/modules/vehicles/pimpin_ride.dm new file mode 100644 index 00000000000..c74b66caee1 --- /dev/null +++ b/code/modules/vehicles/pimpin_ride.dm @@ -0,0 +1,93 @@ + + +//PIMP-CART +/obj/vehicle/janicart + name = "janicart (pimpin' ride)" + desc = "A brave janitor cyborg gave its life to produce such an amazing combination of speed and utility." + icon_state = "pussywagon" + keytype = /obj/item/key/janitor + var/obj/item/weapon/storage/bag/trash/mybag = null + var/floorbuffer = 0 + + +/obj/vehicle/janicart/handle_vehicle_offsets() + ..() + if(buckled_mob) + switch(buckled_mob.dir) + if(NORTH) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 4 + if(EAST) + buckled_mob.pixel_x = -12 + buckled_mob.pixel_y = 7 + if(SOUTH) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 7 + if(WEST) + buckled_mob.pixel_x = 12 + buckled_mob.pixel_y = 7 + + +/obj/item/key/janitor + desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"." + icon_state = "keyjanitor" + + +/obj/item/janiupgrade + name = "floor buffer upgrade" + desc = "An upgrade for mobile janicarts." + icon = 'icons/obj/vehicles.dmi' + icon_state = "upgrade" + + +/obj/vehicle/janicart/Moved(atom/OldLoc, Dir) + if(floorbuffer) + var/turf/tile = loc + if(isturf(tile)) + tile.clean_blood() + for(var/A in tile) + if(is_cleanable(A)) + qdel(A) + + +/obj/vehicle/janicart/examine(mob/user) + ..() + if(floorbuffer) + user << "It has been upgraded with a floor buffer." + + +/obj/vehicle/janicart/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/weapon/storage/bag/trash)) + if(keytype == /obj/item/key/janitor) + if(!user.drop_item()) + return + user << "You hook the trashbag onto \the [name]." + I.loc = src + mybag = I + else if(istype(I, /obj/item/janiupgrade)) + if(keytype == /obj/item/key/janitor) + floorbuffer = 1 + qdel(I) + user << "You upgrade \the [name] with the floor buffer." + update_icon() + + ..() + + +/obj/vehicle/janicart/update_icon() + overlays.Cut() + if(mybag) + overlays += "cart_garbage" + if(floorbuffer) + overlays += "cart_buffer" + + +/obj/vehicle/janicart/attack_hand(mob/user) + if(..()) + return 1 + else if(mybag) + mybag.loc = get_turf(user) + user.put_in_hands(mybag) + mybag = null + update_icon() + diff --git a/code/modules/vehicles/secway.dm b/code/modules/vehicles/secway.dm new file mode 100644 index 00000000000..0a440eb370c --- /dev/null +++ b/code/modules/vehicles/secway.dm @@ -0,0 +1,13 @@ + +/obj/vehicle/secway + name = "secway" + desc = "A brave security cyborg gave its life to help you look like a complete tool." + icon_state = "secway" + keytype = /obj/item/key/security + generic_pixel_x = 0 + generic_pixel_y = 4 + + +/obj/item/key/security + desc = "A keyring with a small steel key, and a rubber stun baton accessory." + icon_state = "keysec" \ No newline at end of file diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm new file mode 100644 index 00000000000..6c6c8dbf6a1 --- /dev/null +++ b/code/modules/vehicles/vehicle.dm @@ -0,0 +1,125 @@ + +/obj/vehicle + name = "vehicle" + desc = "A basic vehicle, vroom" + icon = 'icons/obj/vehicles.dmi' + icon_state = "fuckyou" + density = 1 + anchored = 0 + can_buckle = 1 + buckle_lying = 0 + var/keytype = null //item typepath, if non-null an item of this type is needed in your hands to drive this vehicle + var/next_vehicle_move = 0 //used for move delays + var/vehicle_move_delay = 2 //tick delay between movements, lower = faster, higher = slower + var/auto_door_open = TRUE + + //Pixels + var/generic_pixel_x = 0 //All dirs show this pixel_x for the driver + var/generic_pixel_y = 0 //All dirs shwo this pixel_y for the driver + + +/obj/vehicle/New() + ..() + handle_vehicle_layer() + + +//APPEARANCE +/obj/vehicle/proc/handle_vehicle_layer() + if(dir != NORTH) + layer = MOB_LAYER+0.1 + else + layer = OBJ_LAYER + + +//Override this to set your vehicle's various pixel offsets +//if they differ between directions, otherwise use the +//generic variables +/obj/vehicle/proc/handle_vehicle_offsets() + if(buckled_mob) + buckled_mob.dir = dir + buckled_mob.pixel_x = generic_pixel_x + buckled_mob.pixel_y = generic_pixel_y + + +/obj/vehicle/update_icon() + return + + + +//KEYS +/obj/vehicle/proc/keycheck(mob/user) + if(keytype) + if(istype(user.l_hand, keytype) || istype(user.r_hand, keytype)) + return 1 + else + return 1 + return 0 + +/obj/item/key + name = "key" + desc = "A small grey key." + icon = 'icons/obj/vehicles.dmi' + icon_state = "key" + w_class = 1 + + +//BUCKLE HOOKS +/obj/vehicle/unbuckle_mob(force = 0) + if(buckled_mob) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 0 + . = ..() + + +/obj/vehicle/user_buckle_mob(mob/living/M, mob/user) + if(user.incapacitated()) + return + for(var/atom/movable/A in get_turf(src)) + if(A.density) + if(A != src && A != M) + return + M.loc = get_turf(src) + ..() + handle_vehicle_offsets() + + +//MOVEMENT +/obj/vehicle/relaymove(mob/user, direction) + if(user.incapacitated()) + unbuckle_mob() + + if(keycheck(user)) + if(!Process_Spacemove(direction) || !has_gravity(src.loc) || world.time < next_vehicle_move || !isturf(loc)) + return + next_vehicle_move = world.time + vehicle_move_delay + + step(src, direction) + + if(buckled_mob) + if(buckled_mob.loc != loc) + buckled_mob.buckled = null //Temporary, so Move() succeeds. + buckled_mob.buckled = src //Restoring + + handle_vehicle_layer() + handle_vehicle_offsets() + else + user << "You'll need the keys in one of your hands to drive \the [name]." + + +/obj/vehicle/Move(NewLoc,Dir=0,step_x=0,step_y=0) + ..() + handle_vehicle_layer() + handle_vehicle_offsets() + + +/obj/vehicle/attackby(obj/item/I, mob/user, params) + if(keytype && istype(I, keytype)) + user << "Hold [I] in one of your hands while you drive \the [name]." + + +/obj/vehicle/Bump(atom/movable/M) + . = ..() + if(auto_door_open) + if(istype(M, /obj/machinery/door) && buckled_mob) + M.Bumped(buckled_mob) + diff --git a/config/admins.txt b/config/admins.txt index 40eb253258d..1da322c5d64 100644 --- a/config/admins.txt +++ b/config/admins.txt @@ -104,4 +104,5 @@ Lzimann = Game Master As334 = Game Master neersighted = Game Master Swankcookie = Game Master -Ressler = Game Master \ No newline at end of file +Ressler = Game Master +Bawhoppennn = Game Master \ No newline at end of file diff --git a/config/awaymissionconfig.txt b/config/awaymissionconfig.txt index dde7edfc7b6..986900d5c1d 100644 --- a/config/awaymissionconfig.txt +++ b/config/awaymissionconfig.txt @@ -18,3 +18,4 @@ #_maps/RandomZLevels/undergroundoutpost45.dmm #_maps/RandomZLevels/caves.dmm #_maps/RandomZLevels/snowdin.dmm +#_maps/RandomZLevels/research.dmm diff --git a/config/lavaRuinConfig.txt b/config/lavaRuinConfig.txt new file mode 100644 index 00000000000..c677f1e344a --- /dev/null +++ b/config/lavaRuinConfig.txt @@ -0,0 +1,4 @@ +#List the potential random ruins here. This file is for small things that would appear in lavaland, such as hidden temples or labs. +#Maps must be the full path to them +#Ruins should be 30x30 at max. Anymore than that will break the game. +#SPECIFYING AN INVALID MAP WILL RESULT IN RUNTIMES ON GAME START \ No newline at end of file diff --git a/config/spaceRuinConfig.txt b/config/spaceRuinConfig.txt new file mode 100644 index 00000000000..a0de267df38 --- /dev/null +++ b/config/spaceRuinConfig.txt @@ -0,0 +1,6 @@ +#List the potential random ruins here. This file is for small things that would appear in space, like an asteroid or broken escape pod. +#Maps must be the full path to them +#Ruins should be 40x40 at max. Anymore than that will break the game. +#SPECIFYING AN INVALID MAP WILL RESULT IN RUNTIMES ON GAME START + +#_maps/RandomRuins/SpaceRuins/way_home.dmm \ No newline at end of file diff --git a/html/changelog.html b/html/changelog.html index 94c4d651767..5c85c074aeb 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,106 @@ -->
+ 02 January 2016+Kor updated:+
Kor and GunHog updated:+
MMMiracles updated:+
01 January 2016+Iamgoofball updated:+
Incoming5643 updated:+
Joan updated:+
Kor updated:+
MrStonedOne updated:+
31 December 2015+Bawhoppen updated:+
Joan updated:+
PKPenguin321 updated:+
incoming5643 updated:+
28 December 2015+AnturK updated:+
Joan updated:+
MrStonedOne updated:+
Ressler updated:+
neersighted updated:+
27 December 2015Joan updated:
Air Status
- {{? info.danger_level == 2}}
-
- {{?? info.danger_level == 1}}
-
- {{??}}
-
- {{?}}
- {{=helper.fixed(info.value, 2)}}{{=info.unit}}
-
-
- {{? data.danger_level == 2}}
- Danger (Internals Required)
- {{?? data.danger_level == 1}}
- Caution
- {{??}}
- Optimal
- {{?}}
-
-
- {{? data.atmos_alarm}}
- Atmosphere Alarm
- {{?? data.fire_alarm}}
- Fire Alarm
- {{??}}
- Nominal
- {{?}}
-
- - Loading...
'+n.link("Engaged","lock","toggleaccess",null,e.locked?"selected":null)+n.link("Disengaged","unlock","toggleaccess",null,e.locked?null:"selected")+" Air Status',a+=2==r.danger_level?'':1==r.danger_level?'':'',a+=""+n.fixed(r.value,2)+r.unit+" ',a+=2==e.danger_level?'Danger (Internals Required)':1==e.danger_level?'Caution':'Optimal',a+=' ',a+=e.atmos_alarm?'Atmosphere Alarm':e.fire_alarm?'Fire Alarm':'Nominal',a+=" Air Controls'+c.long_name+'',a+=c.power?""+n.link("On","power-off","adjust",{id_tag:c.id_tag,command:"power",val:0},null,null):""+n.link("Off","close","adjust",{id_tag:c.id_tag,command:"power",val:1},null,"danger"),a+=' ',a+="release"==c.direction?'Pressurizing':'Siphoning',a+=' '+n.link("Internal","sign-in","adjust",{id_tag:c.id_tag,command:"incheck",val:c.checks},null,c.incheck?"selected":null)+n.link("External","sign-out","adjust",{id_tag:c.id_tag,command:"excheck",val:c.checks},null,c.excheck?"selected":null)+' '+n.link(n.fixed(c.external),"pencil","adjust",{id_tag:c.id_tag,command:"set_external_pressure"})+n.link("Reset","refresh","adjust",{id_tag:c.id_tag,command:"reset_external_pressure"},c.extdefault?"disabled":null)+" '+p.long_name+'',a+=p.power?""+n.link("On","power-off","adjust",{id_tag:p.id_tag,command:"power",val:0},null,null):""+n.link("Off","close","adjust",{id_tag:p.id_tag,command:"power",val:1},null,"danger"),a+=' ',a+=p.scrubbing?""+n.link("Scrubbing","filter","adjust",{id_tag:p.id_tag,command:"scrubbing",val:0},null,null):""+n.link("Siphoning","sign-in","adjust",{id_tag:p.id_tag,command:"scrubbing",val:1},null,"danger"),a+=' ',a+=p.widenet?""+n.link("Extended","expand","adjust",{id_tag:p.id_tag,command:"widenet",val:0},null,"caution"):""+n.link("Normal","compress","adjust",{id_tag:p.id_tag,command:"widenet",val:1},null,null),a+=' '+n.link("CO2",p.filter_co2?"check-square-o":"square-o","adjust",{id_tag:p.id_tag,command:"co2_scrub",val:p.filter_co2?0:1},null,p.filter_co2?"selected":null)+n.link("N2O",p.filter_n2o?"check-square-o":"square-o","adjust",{id_tag:p.id_tag,command:"n2o_scrub",val:p.filter_n2o?0:1},null,p.filter_n2o?"selected":null)+n.link("Plasma",p.filter_toxins?"check-square-o":"square-o","adjust",{id_tag:p.id_tag,command:"tox_scrub",val:p.filter_toxins?0:1},null,p.filter_toxins?"selected":null)+" Environmental ModesAlarm Thresholds
System Overrides',a+=e.locked&&!e.siliconUser?e.coverLocked?"Engaged":"Disengaged":""+n.link("Engaged","lock","lock",null,e.coverLocked?"selected":null)+n.link("Disengaged","unlock","lock",null,e.coverLocked?null:"selected"),a+=" '+n.link(e.on?"On":"Off",e.on?"power-off":"close","power")+' '+n.link("Set","pencil","pressure",{set:"custom"})+n.link("Max","plus","pressure",{set:"max"},e.set_pressure==e.max_pressure?"disabled":null)+' '+n.link("Nothing",null,"filter",{mode:-1},-1==e.filter_type?"selected":null)+n.link("Plasma",null,"filter",{mode:0},0==e.filter_type?"selected":null)+n.link("O2",null,"filter",{mode:1},1==e.filter_type?"selected":null)+n.link("N2",null,"filter",{mode:2},2==e.filter_type?"selected":null)+n.link("CO2",null,"filter",{mode:3},3==e.filter_type?"selected":null)+n.link("N2O",null,"filter",{mode:4},4==e.filter_type?"selected":null)+" '+n.link(e.on?"On":"Off",e.on?"power-off":"close","power")+' '+n.link("Set","pencil","pressure",{set:"custom"})+n.link("Max","plus","pressure",{set:"max"},e.set_pressure==e.max_pressure?"disabled":null)+' '+n.link("","fast-backward","node1",{concentration:"-0.1"},null)+n.link("","backward","node1",{concentration:"-0.01"},null)+n.link("","forward","node1",{concentration:"0.01"},null)+n.link("","fast-forward","node1",{concentration:"0.1"},null)+' '+n.link("","fast-backward","node2",{concentration:"-0.1"},null)+n.link("","backward","node2",{concentration:"-0.01"},null)+n.link("","forward","node2",{concentration:"0.01"},null)+n.link("","fast-forward","node2",{concentration:"0.1"},null)+' '+n.link(e.on?"On":"Off",e.on?"power-off":"close","power")+" '+n.link("Set","pencil","transfer",{set:"custom"})+n.link("Max","plus","transfer",{set:"max"},e.transfer_rate==e.max_rate?"disabled":null)+' '+n.link("Set","pencil","pressure",{set:"custom"})+n.link("Max","plus","pressure",{set:"max"},e.set_pressure==e.max_pressure?"disabled":null)+' Canister'+e.tankPressure+' kPa ',a+=e.portConnected?'Connected':'Disconnected',a+=' Valve'+n.bar(e.releasePressure,e.minReleasePressure,e.maxReleasePressure,null,e.releasePressure+" kPa")+' Pressure Regulator: '+n.link("Reset","refresh","pressure",{set:"reset"},e.releasePressure!=e.defaultReleasePressure?null:"disabled")+n.link("Min","minus","pressure",{set:"min"},e.releasePressure>e.minReleasePressure?null:"disabled")+n.link("Set","pencil","pressure",{set:"custom"},null)+n.link("Max","plus","pressure",{set:"max"},e.releasePressure "},TMPL.cryo=function(e,t,n){var a='Valve: '+n.link("Open","unlock","valve",null,e.valveOpen?"selected":null)+n.link("Close","lock","valve",null,e.valveOpen?null:"selected")+' Holding Tank'+e.holdingTank.name+' '+e.holdingTank.tankPressure+" kPa Status'+n.bar(e.energy,0,e.maxEnergy,null,e.energy+" Units")+' ',s=e.beakerTransferAmounts;if(s)for(var r,i=-1,l=s.length-1;l>i;)r=s[i+=1],a+=""+n.link(r,"plus","amount",{set:r},e.amount==r?"selected":null);a+=' DispenseBeaker'+n.link("Eject","eject","eject",null,e.isBeakerLoaded?null:"disabled")+' ';var d=e.beakerTransferAmounts;if(d)for(var r,i=-1,p=d.length-1;p>i;)r=d[i+=1],a+=""+n.link(r,"minus","remove",{amount:r});if(a+=' Contents: ',e.isBeakerLoaded)if(e.beakerContents.length){a+=""+e.beakerCurrentVolume+"/"+e.beakerMaxVolume+" Units ";var h=e.beakerContents;if(h)for(var f,i=-1,v=h.length-1;v>i;)f=h[i+=1],a+=''+f.volume+" units of "+f.name+" "}else a+='Beaker Empty';else a+='No Beaker Loaded';return a+=" Status'+n.link(e.isActive?"On":"Off",e.isActive?"power-off":"close","power",null,e.isBeakerLoaded?null:"disabled")+' '+n.link(e.targetTemp+"K","pencil","temperature")+' Beaker';if(e.isBeakerLoaded)if(a+="Temperature: "+e.currentTemp+"K ",e.beakerContents.length){var s=e.beakerContents;if(s)for(var r,i=-1,l=s.length-1;l>i;)r=s[i+=1],a+=''+r.volume+" units of "+r.name+" "}else a+='Beaker Empty';else a+='No Beaker Loaded';return a+=" Occupant';if(a+=e.hasOccupant?""+e.occupant.name+"":'No Occupant',a+=" ',a+=0==e.occupant.stat?'Conscious':1==e.occupant.stat?'Unconscious':'Dead',a+=' '+n.round(e.occupant.bodyTemperature)+" K '+n.bar(e.occupant.health,e.occupant.minHealth,e.occupant.Maxhealth,e.occupant.health>=0?"good":"average",n.round(e.occupant.health))+' '+n.bar(e.occupant.bruteLoss,0,e.occupant.maxHealth,"bad",n.round(e.occupant.bruteLoss))+' '+n.bar(e.occupant.oxyLoss,0,e.occupant.maxHealth,"bad",n.round(e.occupant.oxyLoss))+' '+n.bar(e.occupant.toxLoss,0,e.occupant.maxHealth,"bad",n.round(e.occupant.toxLoss))+' '+n.bar(e.occupant.fireLoss,0,e.occupant.maxHealth,"bad",n.round(e.occupant.fireLoss))+" Cell',a+=e.isOperating?""+n.link("On","power-off","off"):""+n.link("Off","close","on"),a+=' '+e.cellTemperature+' K ',a+=e.isOpen?""+n.link("Open","unlock","close"):""+n.link("Closed","lock","open"),a+=e.autoEject?""+n.link("Auto","sign-out","autoeject"):""+n.link("Manual","sign-in","autoeject"),a+=' Beaker',e.isBeakerLoaded)if(e.beakerContents.length){var s=e.beakerContents;if(s)for(var r,i=-1,l=s.length-1;l>i;)r=s[i+=1],a+=''+r.volume+" units of "+r.name+" "}else a+='Beaker Empty';else a+='No Beaker Loaded';return a+=" Storage'+n.bar(e.capacityPercent,0,100,e.capacityPercent>=50?"good":e.capacityPercent>=15?"average":"bad",n.round(e.capacityPercent)+"%")+' Input'+n.link("Auto","refresh","tryinput",null,e.inputAttempt?"selected":null)+n.link("Off","close","tryinput",null,e.inputAttempt?null:"selected")+" ";return a+=e.capacityPercent>=99?"[Fully Charged]":e.inputting?"[Charging]":"[Not Charging]",a+=' '+n.bar(e.inputLevel,0,e.inputLevelMax,null,e.inputLevel+" W")+' '+n.link("","fast-backward","input",{set:"min"},e.inputLevel?null:"selected")+n.link("","backward","input",{set:"minus"},e.inputLevel?null:"disabled")+n.link("Set","pencil","input",{set:"custom"},null)+n.link("","forward","input",{set:"plus"},e.inputLevel==e.inputLevelMax?"disabled":null)+n.link("","fast-forward","input",{set:"max"},e.inputLevel==e.inputLevelMax?"selected":null)+' '+e.inputAvailable+' W Output'+n.link("On","power-off","tryoutput",null,e.outputAttempt?"selected":null)+n.link("Off","close","tryoutput",null,e.outputAttempt?null:"selected")+" ",a+=e.outputting?'[Sending]':e.charge>0?'[Not Sending]':'[No Charge]',a+=' '+n.bar(e.outputLevel,0,e.outputLevelMax,null,e.outputLevel+" W")+' '+n.link("","fast-backward","output",{set:"min"},e.outputLevel?null:"selected")+n.link("","backward","output",{set:"minus"},e.outputLevel?null:"disabled")+n.link("Set","pencil","output",{set:"custom"},null)+n.link("","forward","output",{set:"plus"},e.outputLevel==e.outputLevelMax?"disabled":null)+n.link("","fast-forward","output",{set:"max"},e.outputLevel==e.outputLevelMax?"selected":null)+' '+e.outputUsed+" W Status'+e.generated+' W '+e.angle+"° ("+e.direction+') '+n.link("15°","step-backward","control",{cdir:"-15"})+n.link("1°","backward","control",{cdir:"-1"})+n.link("1°","forward","control",{cdir:"1"})+n.link("15°","step-forward","control",{cdir:"15"})+' Tracking'+n.link("Off","close","tracking",{mode:"0"},0==e.tracking_state?"selected":"")+n.link("Timed","clock-o","tracking",{mode:"1"},1==e.tracking_state?"selected":"");return a+=e.connected_tracker?""+n.link("Auto","refresh","tracking",{mode:"2"},2==e.tracking_state?"selected":""):""+n.link("Auto","refresh",null,null,"disabled"),a+=' '+e.tracking_rate+" deg/h ("+e.rotating_way+') '+n.link("180°","fast-backward","control",{tdir:"-180"})+n.link("30°","step-backward","control",{tdir:"-30"})+n.link("1°","backward","control",{tdir:"-1"})+n.link("1°","forward","control",{tdir:"1"})+n.link("30°","step-forward","control",{tdir:"30"})+n.link("180°","fast-forward","control",{tdir:"180"})+' Devices'+n.link("Refresh","refresh","refresh")+' ',a+=e.connected_tracker?'Found':'Not Found',a+=' '+e.connected_panels+" Connected Status'+n.link("On","power-off","power",null,e.on?"selected":null)+n.link("Off","close","power",null,e.on?null:"selected")+' ';return a+=e.hasPowercell?""+n.bar(e.powerLevel,0,100,"good",e.powerLevel+"%"):'No power cell loaded.',a+=" ',a+=e.hasPowercell?""+n.link("Eject","eject","ejectcell"):""+n.link("Install","eject","installcell"),a+=" Thermostat'+e.currentTemp+'°C '+e.targetTemp+"°C '+n.link("","fast-backward","temp",{set:-20},e.targetTemp>e.minTemp?null:"disabled")+n.link("","backward","temp",{set:-5},e.targetTemp>e.minTemp?null:"disabled")+n.link("Set","pencil","temp",{set:"custom"},null)+n.link("","forward","temp",{set:5},e.targetTemp ',a+=e.open?""+n.link("Heat","long-arrow-up","mode",{mode:"heat"},"heat"!=e.mode?null:"selected")+n.link("Cool","long-arrow-down","mode",{mode:"cool"},"cool"!=e.mode?null:"selected")+n.link("Auto","arrows-v","mode",{mode:"auto"},"heat"==e.mode||"cool"==e.mode?null:"selected"):"heat"==e.mode?'Heat':"cool"==e.mode?'Cool':'Auto',
-a+=" '+n.bar(e.tankPressure,0,1013,e.tankPressure>200?"good":e.tankPressure>100?"average":"bad",e.tankPressure+" kPa")+' '+n.bar(e.releasePressure,e.minReleasePressure,e.maxReleasePressure,null,e.releasePressure+" kPa")+' '+n.link("Reset","refresh","pressure",{set:"reset"},e.releasePressure!=e.defaultReleasePressure?null:"disabled")+n.link("Min","minus","pressure",{set:"min"},e.releasePressure>e.minReleasePressure?null:"disabled")+n.link("Set","pencil","pressure",{set:"custom"},null)+n.link("Max","plus","pressure",{set:"max"},e.releasePressure
-
-
-
-
-
-
- '+n.link("Open","unlock","valve",null,e.maskConnected?e.valveOpen?"selected":null:"disabled")+n.link("Close","lock","valuve",null,e.valveOpen?null:"selected")+"
-
-
-
-
-
diff --git a/nano/package.json b/nano/package.json
deleted file mode 100644
index d1749cf972d..00000000000
--- a/nano/package.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- "name": "nanoui",
- "private": true,
- "dependencies": {
- "autoprefixer": "^6.2.2",
- "coffee-script": "^1.10.0",
- "del": "^2.2.0",
- "gulp": "^3.9.0",
- "gulp-bytediff": "^1.0.0",
- "gulp-coffee": "^2.3.1",
- "gulp-concat": "^2.6.0",
- "gulp-csscomb": "^3.0.6",
- "gulp-cssnano": "^2.0.0",
- "gulp-dot-precompiler": "git+https://github.com/kentliau/gulp-dot-precompiler.git",
- "gulp-filter": "^3.0.1",
- "gulp-header": "^1.7.1",
- "gulp-htmlmin": "^1.3.0",
- "gulp-if": "^2.0.0",
- "gulp-jsbeautifier": "^1.0.1",
- "gulp-less": "^3.0.5",
- "gulp-load-plugins": "^1.1.0",
- "gulp-postcss": "^6.0.1",
- "gulp-rename": "^1.2.2",
- "gulp-replace": "^0.5.4",
- "gulp-size": "^2.0.0",
- "gulp-sourcemaps": "^1.6.0",
- "gulp-uglify": "^1.5.1",
- "gulp-util": "^3.0.7",
- "hexa-color-regex": "^1.0.0",
- "main-bower-files": "^2.11.0",
- "merge2": "^0.3.6",
- "pleeease-filters": "^2.0.0",
- "postcss-color-rgba-fallback": "git+https://github.com/postcss/postcss-color-rgba-fallback",
- "postcss-colorblind": "^0.4.0",
- "postcss-filter-gradient": "^0.2.1",
- "postcss-font-weights": "^2.0.1",
- "postcss-opacity": "^3.0.0"
- }
-}
diff --git a/nano/scripts/chrome.coffee b/nano/scripts/chrome.coffee
deleted file mode 100644
index d024f7deee3..00000000000
--- a/nano/scripts/chrome.coffee
+++ /dev/null
@@ -1,106 +0,0 @@
-class @Chrome
- constructor: (@nanoui, data) ->
- @nanoui.updated.add @linkStatus
- @nanoui.updated.add @windowStatus
- @nanoui.rendered.add @handleLinks
-
- return unless data.config.user.fancy
- @dragging = false
- @resizing = false
-
- @switchChrome()
- @calcOffsets()
- @handleButtons()
- @handleDrag()
- @handleResize()
-
- linkStatus: (data) ->
- links = document.queryAll ".link"
- if data.config.status isnt NANO.INTERACTIVE
- links.forEach (element) ->
- element.className = "link disabled"
-
- windowStatus: (data) ->
- statusicons = document.queryAll ".statusicon"
- statusicons.forEach (statusicon) ->
- switch data.config.status
- when NANO.INTERACTIVE
- klass = "good"
- when NANO.UPDATE
- klass = "average"
- else
- klass = "bad"
- statusicon.classList.remove "good", "bad", "average"
- statusicon.classList.add klass
-
- handleLinks: (data) ->
- onClick = ->
- action = @getAttribute "data-action"
- params = JSON.parse @getAttribute "data-params"
- if action? and params? and data.config.status is NANO.INTERACTIVE
- nanoui.act action, params
-
- document.queryAll(".link.active").forEach (link) ->
- link.addEventListener "click", onClick
-
- switchChrome: ->
- @nanoui.winset "titlebar", 0
- @nanoui.winset "can-resize", 0
- fancy = document.queryAll ".fancy"
- fancy.forEach (chrome) ->
- chrome.classList.remove "fancy"
-
- calcOffsets: =>
- @xOriginal = window.screenLeft
- @yOriginal = window.screenTop
- @nanoui.setPos 0, 0 # Move to 0,0 to measure offsets.
- @xOffset = window.screenLeft
- @yOffset = window.screenTop
- @nanoui.setPos @xOriginal - @xOffset, @yOriginal - @yOffset # Put the window back.
-
- handleButtons: ->
- closers = document.queryAll ".close"
- closers.forEach (closer) ->
- closer.addEventListener "click", => @nanoui.close()
-
- minimizers = document.queryAll ".minimize"
- minimizers.forEach (minimizer) ->
- minimizer.addEventListener "click", => @nanoui.minimize()
-
- handleDrag: =>
- drag = (event = window.event) =>
- return unless @dragging
-
- @xDrag = event.screenX unless @xDrag?
- @yDrag = event.screenY unless @yDrag?
-
- x = (event.screenX - @xDrag) + (window.screenLeft - @xOffset)
- y = (event.screenY - @yDrag) + (window.screenTop - @yOffset)
- @nanoui.setPos x, y
-
- @xDrag = event.screenX
- @yDrag = event.screenY
-
- titlebar = document.query "#titlebar"
- document.addEventListener "mousemove", drag
- titlebar.addEventListener "mousedown", => @dragging = true
- document.addEventListener "mouseup", => @dragging = false; delete @xDrag; delete @yDrag
-
- handleResize: =>
- resize = (event = window.event) =>
- return unless @resizing
-
- @xResize = event.screenX unless @xResize?
- @yResize = event.screenY unless @yResize?
-
- x = Math.max 250, (event.screenX - @xResize) + window.innerWidth
- y = Math.max 250, (event.screenY - @yResize) + window.innerHeight
- @nanoui.setSize x, y
-
- @xResize = event.screenX
- @yResize = event.screenY
-
- handle = document.query "#resize"
- document.addEventListener "mousemove", resize
- handle.addEventListener "mousedown", => @resizing = true
- document.addEventListener "mouseup", => @resizing = false; delete @xResize; delete @yResize
diff --git a/nano/scripts/constants.coffee b/nano/scripts/constants.coffee
deleted file mode 100644
index 825a336af65..00000000000
--- a/nano/scripts/constants.coffee
+++ /dev/null
@@ -1,5 +0,0 @@
-@NANO =
- INTERACTIVE: 2
- UPDATE: 1
- DISABLED: 0
- CLOSE: -1
diff --git a/nano/scripts/helpers.coffee b/nano/scripts/helpers.coffee
deleted file mode 100644
index 77b20403406..00000000000
--- a/nano/scripts/helpers.coffee
+++ /dev/null
@@ -1,43 +0,0 @@
-@helpers =
- link: (text = "", icon = "", action = "", params = {}, status = "", klass = "") ->
- params = JSON.stringify params
-
- if !!icon
- icon = ""
- klass += " iconed"
-
- if !!status
- "#{icon}#{text}"
- else
- "#{icon}#{text}"
-
- bar: (value = 0, min = 0, max = 100, klass = "", text = "") ->
- if min < max
- if value < min
- value = min
- else if value > max
- value = max
- else
- if value > min
- value = min
- else if value < max
- value = max
-
- percentage = Math.round((value - min) / (max - min) * 100)
-
- ""
-
- round: (number) ->
- Math.round number
-
- fixed: (number, decimals = 1) ->
- Number Math.round(number + "e" + decimals) + "e-" + decimals
-
- floor: (number) ->
- Math.floor number
-
- ceil: (number) ->
- Math.ceil number
diff --git a/nano/scripts/nanoui.coffee b/nano/scripts/nanoui.coffee
deleted file mode 100644
index c6692897bf5..00000000000
--- a/nano/scripts/nanoui.coffee
+++ /dev/null
@@ -1,87 +0,0 @@
-class NanoUI
- constructor: ->
- @laidout = false
-
- @dragging = false
- @resizing = false
-
- try
- data = document.query "meta[name='data']"
- @data = JSON.parse data.getAttribute "content"
- catch error
- @error error
- if not (@data? and "data" of @data and "config" of @data)
- @error "Initial data did not load correctly."
-
- @render @data
- @chrome = new Chrome this, @data
-
- @initialized.dispatch @data
- @incoming.add @update
- initialized: new MiniSignal
- incoming: new MiniSignal
-
- update: (dataString) =>
- try
- data = JSON.parse dataString
-
- if not data.data?
- if @data.data?
- data.data = @data.data
- else
- data.data = {}
-
- @data = data
- catch error
- @error error
- @render @data
- @updated.dispatch @data
- updated: new MiniSignal
-
- render: (data) =>
- try
- if not @laidout
- @laidout = true
- document.query("body").classList.add data.config.layout
- layout = TMPL[data.config.templates.layout](data.data, data.config, helpers)
- document.query("#layout").innerHTML = layout
-
- content = TMPL[data.config.templates.content](data.data, data.config, helpers)
- document.query("#content").innerHTML = content
-
- @rendered.dispatch @data
- catch error
- @error error
- rendered: new MiniSignal
-
-
- href: (params = {}, url = "") ->
- "byond://#{url}?" + Object.keys(params).map (key) ->
- "#{encodeURIComponent(key)}=#{encodeURIComponent(params[key])}"
- .join("&")
-
- act: (action, params = {}) =>
- params.src = @data.config.ref
- params.nano = action
- location.href = @href params, null
- error: (error) ->
- location.href = @href {nano_error: error}, null
-
- winset: (key, value, window) =>
- window = @data.config.window unless window?
- location.href = @href {"#{window}.#{key}": value}, "winset"
- setPos: (x, y) =>
- @winset "pos", "#{x},#{y}"
- setSize: (w, h) =>
- @winset "size", "#{w},#{h}"
- focusMap: =>
- @winset "focus", 1, "mapwindow.map"
-
- close: =>
- @winset "is-visible", "false"
- location.href = @href {command: "nanoclose #{@data.config.ref}"}, "winset"
- minimize: =>
- @winset "is-minimized", "true"
-
-
-@nanoui = new NanoUI
diff --git a/nano/styles/_bar.less b/nano/styles/_bar.less
deleted file mode 100644
index 6da5019d3b5..00000000000
--- a/nano/styles/_bar.less
+++ /dev/null
@@ -1,40 +0,0 @@
-@import "_config";
-@import "_util";
-
-
-.bar {
- display: inline-block;
- position: relative;
- top: 4px; // Because this is an empty div, hack it so that it lines up.
- vertical-align: top;
- box-sizing: border-box;
- width: 100%;
- height: 20px; // Buttons are 22px, but look 20px because of their dark borders.
- margin: 1px;
- padding: 1px;
-
- border: 1px solid @normal;
-
- background: @dark;
-
- .barText {
- position: absolute;
- top: 1px;
- right: 3px;
-
- .fontReset;
- }
-
- .barFill {
- display: block;
- height: 100%;
-
- overflow: hidden;
-
- background: @normal;
- &.good { background: @good; }
- &.average { background: @average; }
- &.bad { background: @bad; }
- &.highlight { background: @highlight; }
- }
-}
diff --git a/nano/styles/_chrome.less b/nano/styles/_chrome.less
deleted file mode 100644
index 750b5adb51e..00000000000
--- a/nano/styles/_chrome.less
+++ /dev/null
@@ -1,86 +0,0 @@
-@import "_config";
-@import "_util";
-
-
-div.loading {
- .noticeStripes;
-
- padding: 8px;
-}
-
-div.content {
- margin: 32px 4px 0 4px;
- &.titlebared {
- padding-top: 3px;
- }
-}
-
-header.titlebar {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 32px;
-
- background-color: @titlebar;
- box-shadow: 0 3px 3px rgba(0, 0, 0, 0.1);
-
- .statusicon {
- position: absolute;
- top: 4px;
- left: 12px;
- }
-
- .title {
- position: absolute;
- top: 6px;
- left: 46px;
-
- color: @title;
- font-size: 16px;
- white-space: nowrap;
- }
-
- .titlebutton() {
- display: inline-block;
- position: relative;
- padding: 7px; // To make a bigger clickable area.
- margin: -7px;
-
- color: @title;
-
- &:hover {
- color: lighten(@title, @hover);
- }
- }
- .minimize {
- .titlebutton;
- position: absolute;
- top: 6px;
- right: 46px;
- }
- .close {
- .titlebutton;
- position: absolute;
- top: 4px;
- right: 12px;
- }
-}
-
-div.resize {
- position: fixed;
- bottom: 0;
- right: 0;
- width: 0;
- height: 0;
-
- border-style: solid;
- border-width: 0 0 30px 30px;
- border-color: transparent transparent @resize transparent;
-
- transform: rotate(360deg);
-}
-
-.fancy {
- .hidden;
-}
diff --git a/nano/styles/_config.less b/nano/styles/_config.less
deleted file mode 100644
index da58aa148e7..00000000000
--- a/nano/styles/_config.less
+++ /dev/null
@@ -1,35 +0,0 @@
-// Fonts
-@font: Verdana, Geneva, sans-serif;
-@fontsize: 12px;
-
-// Global Colors
-@normal: #40628a;
-@good: #537d29;
-@average: #be6209;
-@bad: #b00e0e;
-@highlight: #8ba5c4;
-@info: #e9C183;
-@label: @highlight;
-@dark: #272727;
-
-// Body Colors
-@title: #98b0c3;
-@text: white;
-@textinverse: black;
-@titlebar: #363636;
-@background-start: #2a2a2a;
-@background-end: #202020;
-@resize: #363636;
-
-// Component Colors
-@border: @dark;
-@rule: @normal;
-@notice1: #bb9b68;
-@notice2: #b1905d;
-
-// Link Colors
-@hover: 10%;
-@selected: #2f943c;
-@caution: #9a9d00;
-@danger: #9d0808;
-@disabled: #999999;
diff --git a/nano/styles/_document.less b/nano/styles/_document.less
deleted file mode 100644
index 7bd1ca078ed..00000000000
--- a/nano/styles/_document.less
+++ /dev/null
@@ -1,41 +0,0 @@
-@import "_config";
-@import "_util";
-
-
-html {
- min-height: 100%;
- margin: 0;
-
- cursor: default; // Reset the cursor.
-}
-
-body {
- min-height: 100%;
- height: 100%;
- margin: 0;
-
- background-color: @background-end; // Fallback for old browsers.
-
- font-family: @font;
- font-size: @fontsize;
- color: @text;
-}
-
-h1 {
- font-size: @fontsize + 6px;
- margin: 0;
- padding: 6px 0;
-}
-h2 {
- &:extend(h1);
- font-size: @fontsize + 4px;
-}
-h3 {
- &:extend(h1);
- font-size: @fontsize + 2px;
-}
-
-hr {
- background-color: @rule;
- border: none;
-}
diff --git a/nano/styles/_generic.less b/nano/styles/_generic.less
deleted file mode 100644
index ffdc3cd4ff9..00000000000
--- a/nano/styles/_generic.less
+++ /dev/null
@@ -1,8 +0,0 @@
-@import "_config";
-
-
-body.generic {
- background: linear-gradient(to bottom,
- @background-start 0%,
- @background-end 100%);
-}
diff --git a/nano/styles/_link.less b/nano/styles/_link.less
deleted file mode 100644
index e179f3b684a..00000000000
--- a/nano/styles/_link.less
+++ /dev/null
@@ -1,49 +0,0 @@
-@import "_config";
-@import "_util";
-
-
-.active(@color) {
- background-color: @color;
- &:hover {
- background-color: lighten(@color, @hover);
- }
-}
-
-
-// Basic Link (Button) Element
-span.link {
- display: inline-block;
- box-sizing: border-box;
- height: 22px;
- margin: 1px;
- padding: 2px 3px;
- white-space: nowrap;
-
- border: 1px solid @border;
-
- .fontReset; // Reset font settings.
-
- // Tweak spacing to fit icons.
- .fa { margin-right: 3px; }
- .iconed { padding-left: 3px; }
-
- // Link colors:
- background-color: @normal;
- &.active {
- .active(@normal);
- &.selected { .active(@selected); }
- &.caution { .active(@caution); }
- &.danger { .active(@danger); }
- }
- &.inactive {
- background-color: @disabled;
- &.selected { background-color: @selected; }
- &.caution { background-color: @caution; }
- &.danger { background-color: @danger; }
- }
- &.disabled { background-color: @disabled; }
-
- &.gridable {
- width: 125px;
- }
-}
diff --git a/nano/styles/_nanotrasen.less b/nano/styles/_nanotrasen.less
deleted file mode 100644
index b9b0fb94489..00000000000
--- a/nano/styles/_nanotrasen.less
+++ /dev/null
@@ -1,9 +0,0 @@
-@import "_config";
-
-
-body.nanotrasen {
- background: data-uri('nanotrasen.svg') no-repeat fixed center/70% 70%,
- linear-gradient(to bottom,
- @background-start 0%,
- @background-end 100%);
-}
diff --git a/nano/styles/_section.less b/nano/styles/_section.less
deleted file mode 100644
index b36eae5ec9e..00000000000
--- a/nano/styles/_section.less
+++ /dev/null
@@ -1,94 +0,0 @@
-@import "_config";
-@import "_util";
-
-
-article.display {
- display: flex;
- flex-flow: column nowrap;
- width: auto;
- padding: 4px;
- margin: 6px 2px;
-
- background-color: rgba(0, 0, 0, 0.33); // Transparent background.
- box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.5);
-
- header {
- padding-left: 4px;
- margin-bottom: 6px;
-
- border-bottom: 2px solid @rule;
- }
-
- section {
- width: 100%;
- padding: 3px 0;
- }
-
- .cell() {
- display: inline-block;
- margin: 0;
- }
-
- .label {
- .cell;
- width: 33%;
-
- color: @label;
- }
-
- .content {
- .cell;
- width: 66%;
- }
-
- .line {
- .cell;
- width: 100%;
- }
-
- .buttoninfo {
- margin-left: 5px;
- }
-
- table {
- width: auto;
-
- border-collapse: collapse;
- }
-
- table.grow {
- width: 100%;
- }
-
- th {
- vertical-align: top;
- padding: 4px 16px 4px 0;
- text-align: left;
-
- .fontReset;
- color: @label;
- }
-
- td {
- &:extend(th);
- padding: 2px 2px 0 0;
- vertical-align: top;
- }
-}
-
-article.notice {
- &:extend(article.display all);
- margin: 8px 2px;
-
- box-shadow: none;
-
- color: @textinverse;
- font-weight: bold;
- font-style: italic;
-
- .label {
- color: @textinverse;
- }
-
- .noticeStripes;
-}
diff --git a/nano/styles/_util.less b/nano/styles/_util.less
deleted file mode 100644
index 82c988ba6ad..00000000000
--- a/nano/styles/_util.less
+++ /dev/null
@@ -1,57 +0,0 @@
-@import "_config";
-
-
-// Colors
-.color(@color) { // Explort a given color as a class.
- &.@{color} {
- color: @@color;
- }
-}
-
-.color(normal);
-.color(good);
-.color(average);
-.color(bad);
-.color(label);
-.color(highlight);
-.color(dark);
-
-// Text Styles
-.bold { font-weight: bold; }
-.italic { font-style: italic; }
-.fontReset() {
- color: @text;
- font-size: @fontsize;
- font-weight: normal;
- font-style: normal;
- text-decoration: none;
-}
-
-// Fancy "Notice Me" Stripes
-.noticeStripes() {
- background-color: @notice1; // Fallback for old browers.
- background-image: repeating-linear-gradient(
- -45deg,
- @notice1,
- @notice1 10px,
- @notice2 10px,
- @notice2 20px
- );
-}
-
-// General Helpers
-.hidden { display: none !important; }
-
-.clearBoth { clear: both; }
-.clearLeft { clear: left; }
-.clearRight { clear: right; }
-
-.floatNone { float: none; }
-.floatLeft { float: left; }
-.floatRight { float: right; }
-
-.alignTop { vertical-align: top; }
-.alignBottom { vertical-align: bottom; }
-.alignLeft { text-align: left; }
-.alignCenter { text-align: center; }
-.alignRight { text-align: right; }
diff --git a/nano/styles/nanoui.less b/nano/styles/nanoui.less
deleted file mode 100644
index f28043bb223..00000000000
--- a/nano/styles/nanoui.less
+++ /dev/null
@@ -1,14 +0,0 @@
-@charset "utf-8";
-
-@import "_config";
-
-@import "_document";
-@import "_util";
-
-@import "_chrome";
-@import "_section";
-@import "_link";
-@import "_bar";
-
-@import "_generic";
-@import "_nanotrasen";
diff --git a/nano/templates/_generic.dot b/nano/templates/_generic.dot
deleted file mode 100644
index 698191ae91c..00000000000
--- a/nano/templates/_generic.dot
+++ /dev/null
@@ -1,14 +0,0 @@
-Loading...
-
-
diff --git a/nano/templates/_nanotrasen.dot b/nano/templates/_nanotrasen.dot
deleted file mode 100644
index c41921a7824..00000000000
--- a/nano/templates/_nanotrasen.dot
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
diff --git a/nano/templates/air_alarm.dot b/nano/templates/air_alarm.dot
deleted file mode 100644
index 364767cbfc9..00000000000
--- a/nano/templates/air_alarm.dot
+++ /dev/null
@@ -1,233 +0,0 @@
-
- {{=helper.link('Engaged', 'lock', 'toggleaccess', null, data.locked ? 'selected' : null)}}
- {{=helper.link('Disengaged', 'unlock', 'toggleaccess', null, data.locked ? null : 'selected')}}
-
- Air Status
- {{? info.danger_level == 2}}
-
- {{?? info.danger_level == 1}}
-
- {{??}}
-
- {{?}}
- {{=helper.fixed(info.value, 2)}}{{=info.unit}}
-
-
- {{? data.danger_level == 2}}
- Danger (Internals Required)
- {{?? data.danger_level == 1}}
- Caution
- {{??}}
- Optimal
- {{?}}
-
-
- {{? data.atmos_alarm}}
- Atmosphere Alarm
- {{?? data.fire_alarm}}
- Fire Alarm
- {{??}}
- Nominal
- {{?}}
-
- - Air Controls{{=vent.long_name}}
- {{? vent.power}}
- {{=helper.link('On', 'power-off', 'adjust', {'id_tag': vent.id_tag, 'command': 'power', 'val': 0}, null, null)}}
- {{??}}
- {{=helper.link('Off', 'close', 'adjust', {'id_tag': vent.id_tag, 'command': 'power', 'val': 1}, null, 'danger')}}
- {{?}}
-
-
- {{? vent.direction == "release"}}
- Pressurizing
- {{??}}
- Siphoning
- {{?}}
-
-
- {{=helper.link('Internal', 'sign-in', 'adjust', {'id_tag': vent.id_tag, 'command': 'incheck', 'val': vent.checks}, null, vent.incheck ? 'selected' : null)}}
- {{=helper.link('External', 'sign-out', 'adjust', {'id_tag': vent.id_tag, 'command': 'excheck', 'val': vent.checks}, null, vent.excheck ? 'selected' : null)}}
-
-
- {{=helper.link(helper.fixed(vent.external), 'pencil', 'adjust', {'id_tag': vent.id_tag, 'command': 'set_external_pressure'})}}
- {{=helper.link('Reset', 'refresh', 'adjust', {'id_tag': vent.id_tag, 'command': 'reset_external_pressure'}, vent.extdefault ? 'disabled' : null)}}
-
- {{=scrubber.long_name}}
- {{? scrubber.power}}
- {{=helper.link('On', 'power-off', 'adjust', {'id_tag': scrubber.id_tag, 'command': 'power', 'val': 0}, null, null)}}
- {{??}}
- {{=helper.link('Off', 'close', 'adjust', {'id_tag': scrubber.id_tag, 'command': 'power', 'val': 1}, null, 'danger')}}
- {{?}}
-
-
- {{? scrubber.scrubbing}}
- {{=helper.link('Scrubbing', 'filter', 'adjust', {'id_tag': scrubber.id_tag, 'command': 'scrubbing', 'val': 0}, null, null)}}
- {{??}}
- {{=helper.link('Siphoning', 'sign-in', 'adjust', {'id_tag': scrubber.id_tag, 'command': 'scrubbing', 'val': 1}, null, 'danger')}}
- {{?}}
-
-
- {{? scrubber.widenet}}
- {{=helper.link('Extended', 'expand', 'adjust', {'id_tag': scrubber.id_tag, 'command': 'widenet', 'val': 0}, null, 'caution')}}
- {{??}}
- {{=helper.link('Normal', 'compress', 'adjust', {'id_tag': scrubber.id_tag, 'command': 'widenet', 'val': 1}, null, null)}}
- {{?}}
-
-
- {{=helper.link("CO2", scrubber.filter_co2 ? 'check-square-o' : 'square-o', 'adjust', {'id_tag': scrubber.id_tag, 'command': "co2_scrub", 'val': scrubber.filter_co2 ? 0 : 1}, null, scrubber.filter_co2 ? 'selected' : null)}}
- {{=helper.link("N2O", scrubber.filter_n2o ? 'check-square-o' : 'square-o', 'adjust', {'id_tag': scrubber.id_tag, 'command': "n2o_scrub", 'val': scrubber.filter_n2o ? 0 : 1}, null, scrubber.filter_n2o ? 'selected' : null)}}
- {{=helper.link("Plasma", scrubber.filter_toxins ? 'check-square-o' : 'square-o', 'adjust', {'id_tag': scrubber.id_tag, 'command': "tox_scrub", 'val': scrubber.filter_toxins ? 0 : 1}, null, scrubber.filter_toxins ? 'selected' : null)}}
-
- Environmental ModesAlarm Thresholds
- {{=helper.link('Engaged', 'lock', 'toggleaccess', null, data.locked ? 'selected' : null)}}
- {{=helper.link('Disengaged', 'unlock', 'toggleaccess', null, data.malfStatus >= 2 ? 'linkOff' : (data.locked ? null : 'selected'))}}
-
- Power Status
- {{? data.locked && !data.siliconUser}}
- {{? data.isOperating}}
- On
- {{??}}
- Off
- {{?}}
- {{??}}
- {{=helper.link('On', 'power-off', 'breaker', null, data.isOperating ? 'selected' : null)}}
- {{=helper.link('Off', 'close', 'breaker', null, data.isOperating ? null : 'selected')}}
- {{?}}
-
-
- {{? data.externalPower == 2}}
- Good
- {{?? data.externalPower == 1}}
- Low
- {{??}}
- None
- {{?}}
-
-
- {{? data.powerCellStatus != null}}
- {{=helper.bar(data.powerCellStatus, 0, 100, data.powerCellStatus >= 50 ? "good" : data.powerCellStatus >= 25 ? "average" : "bad", helper.fixed(data.powerCellStatus) + "%")}}
- {{??}}
- Power cell removed.
- {{?}}
-
-
- {{? data.locked && !data.siliconUser}}
- {{? data.chargeMode}}
- Auto
- {{??}}
- Off
- {{?}}
- {{??}}
- {{=helper.link('Auto', 'refresh', 'chargemode', null, data.chargeMode ? 'selected' : null)}}
- {{=helper.link('Off', 'close', 'chargemode', null, data.chargeMode ? null : 'selected')}}
- {{?}}
-
- {{? data.chargingStatus > 1}}
- [Fully Charged]
- {{?? data.chargingStatus == 1}}
- [Charging]
- {{??}}
- [Not Charging]
- {{?}}
-
- Power Channels
System Overrides
- {{? data.locked && !data.siliconUser}}
- {{? data.coverLocked}}
- Engaged
- {{??}}
- Disengaged
- {{?}}
- {{??}}
- {{=helper.link('Engaged', 'lock', 'lock', null, data.coverLocked ? 'selected' : null)}}
- {{=helper.link('Disengaged', 'unlock', 'lock', null, data.coverLocked ? null : 'selected')}}
- {{?}}
-
-
- {{=helper.link(data.on? 'On' : 'Off', data.on ? 'power-off' : 'close', 'power')}}
-
-
- {{=helper.link('Set', 'pencil', 'pressure', {'set': 'custom'})}}
- {{=helper.link('Max', 'plus', 'pressure', {'set': 'max'}, data.set_pressure == data.max_pressure ? 'disabled' : null)}}
-
-
-
- {{=helper.link('Nothing', null, 'filter', {'mode': -1}, data.filter_type == -1 ? 'selected' : null)}}
- {{=helper.link('Plasma', null, 'filter', {'mode': 0}, data.filter_type == 0 ? 'selected' : null)}}
- {{=helper.link('O2', null, 'filter', {'mode': 1}, data.filter_type == 1 ? 'selected' : null)}}
- {{=helper.link('N2', null, 'filter', {'mode': 2}, data.filter_type == 2 ? 'selected' : null)}}
- {{=helper.link('CO2', null, 'filter', {'mode': 3}, data.filter_type == 3 ? 'selected' : null)}}
- {{=helper.link('N2O', null, 'filter', {'mode': 4}, data.filter_type == 4 ? 'selected' : null)}}
-
-
- {{=helper.link(data.on? 'On' : 'Off', data.on? 'power-off' : 'close', 'power')}}
-
-
- {{=helper.link('Set', 'pencil', 'pressure', {'set': 'custom'})}}
- {{=helper.link('Max', 'plus', 'pressure', {'set': 'max'}, data.set_pressure == data.max_pressure ? 'disabled' : null)}}
-
-
-
- {{=helper.link('', 'fast-backward', 'node1', {'concentration' : '-0.1'}, null)}}
- {{=helper.link('', 'backward', 'node1', {'concentration' : '-0.01'}, null)}}
- {{=helper.link('', 'forward', 'node1', {'concentration' : '0.01'}, null)}}
- {{=helper.link('', 'fast-forward', 'node1', {'concentration' : '0.1'}, null)}}
-
-
-
- {{=helper.link('', 'fast-backward', 'node2', {'concentration' : '-0.1'}, null)}}
- {{=helper.link('', 'backward', 'node2', {'concentration' : '-0.01'}, null)}}
- {{=helper.link('', 'forward', 'node2', {'concentration' : '0.01'}, null)}}
- {{=helper.link('', 'fast-forward', 'node2', {'concentration' : '0.1'}, null)}}
-
-
-
- {{=helper.link(data.on? 'On' : 'Off', data.on? 'power-off' : 'close', 'power')}}
-
-
- {{=helper.link('Set', 'pencil', 'transfer', {'set': 'custom'})}}
- {{=helper.link('Max', 'plus', 'transfer', {'set' : 'max'}, data.transfer_rate == data.max_rate ? 'disabled' : null)}}
-
-
-
- {{=helper.link('Set', 'pencil', 'pressure', {'set': 'custom'})}}
- {{=helper.link('Max', 'plus', 'pressure', {'set' : 'max'}, data.set_pressure == data.max_pressure ? 'disabled' : null)}}
-
-
- Canister
- {{=data.tankPressure}} kPa
-
-
- {{? data.portConnected}}
- Connected
- {{??}}
- Disconnected
- {{?}}
-
- Valve
- {{=helper.bar(data.releasePressure, data.minReleasePressure, data.maxReleasePressure, null, data.releasePressure + ' kPa')}}
-
- Pressure Regulator:
-
- {{=helper.link('Reset', 'refresh', 'pressure', {'set': 'reset'}, (data.releasePressure != data.defaultReleasePressure) ? null : 'disabled')}}
- {{=helper.link('Min', 'minus', 'pressure', {'set': 'min'}, (data.releasePressure > data.minReleasePressure) ? null : 'disabled')}}
- {{=helper.link('Set', 'pencil', 'pressure', {'set': 'custom'}, null)}}
- {{=helper.link('Max', 'plus', 'pressure', {'set': 'max'}, (data.releasePressure < data.maxReleasePressure) ? null : 'disabled')}}
-
- Valve:
-
- {{=helper.link('Open', 'unlock', 'valve', null, data.valveOpen ? 'selected' : null)}}
- {{=helper.link('Close', 'lock', 'valve', null, data.valveOpen ? null : 'selected')}}
-
- Holding Tank
- {{=data.holdingTank.name}}
-
-
- {{=data.holdingTank.tankPressure}} kPa
-
- Status
- {{=helper.bar(data.energy, 0, data.maxEnergy, null, data.energy + ' Units')}}
-
-
- {{~ data.beakerTransferAmounts :amount:i}}
- {{=helper.link(amount, 'plus', 'amount', {'set': amount}, (data.amount == amount) ? 'selected' : null)}}
- {{~}}
-
- DispenseBeaker
- {{=helper.link('Eject', 'eject', 'eject', null, data.isBeakerLoaded ? null : 'disabled')}}
-
-
- {{~ data.beakerTransferAmounts :amount:i}}
- {{=helper.link(amount, 'minus', 'remove', {'amount': amount})}}
- {{~}}
-
- Contents:
-
- {{? data.isBeakerLoaded}}
- {{? data.beakerContents.length}}
- {{=data.beakerCurrentVolume}}/{{=data.beakerMaxVolume}} Units
- - {{~ data.beakerContents :reagent:i}} - {{=reagent.volume}} units of {{=reagent.name}} - {{~}} - {{??}} - Beaker Empty - {{?}} - {{??}} - No Beaker Loaded - {{?}} - Status
- {{=helper.link(data.isActive ? 'On' : 'Off', data.isActive ? 'power-off' : 'close', 'power', null, data.isBeakerLoaded ? null : 'disabled')}}
-
-
- {{=helper.link(data.targetTemp + 'K', 'pencil', 'temperature')}}
-
- Beaker
- {{? data.isBeakerLoaded}}
- Temperature: {{=data.currentTemp}}K
- - {{? data.beakerContents.length}} - {{~ data.beakerContents :reagent:i}} - {{=reagent.volume}} units of {{=reagent.name}} - {{~}} - {{??}} - Beaker Empty - {{?}} - {{??}} - No Beaker Loaded - {{?}} - Occupant
- {{? data.hasOccupant}}
- {{=data.occupant.name}}
- {{??}}
- No Occupant
- {{?}}
-
-
- {{? data.occupant.stat == 0}}
- Conscious
- {{?? data.occupant.stat == 1}}
- Unconscious
- {{??}}
- Dead
- {{?}}
-
-
- {{=helper.round(data.occupant.bodyTemperature)}} K
-
-
- {{=helper.bar(data.occupant.health, data.occupant.minHealth, data.occupant.Maxhealth, data.occupant.health >= 0 ? 'good' : 'average', helper.round(data.occupant.health))}}
-
-
- {{=helper.bar(data.occupant.bruteLoss, 0, data.occupant.maxHealth, 'bad', helper.round(data.occupant.bruteLoss))}}
-
-
- {{=helper.bar(data.occupant.oxyLoss, 0, data.occupant.maxHealth, 'bad', helper.round(data.occupant.oxyLoss))}}
-
-
- {{=helper.bar(data.occupant.toxLoss, 0, data.occupant.maxHealth, 'bad', helper.round(data.occupant.toxLoss))}}
-
-
- {{=helper.bar(data.occupant.fireLoss, 0, data.occupant.maxHealth, 'bad', helper.round(data.occupant.fireLoss))}}
-
- Cell
- {{? data.isOperating}}
- {{=helper.link('On', 'power-off', 'off')}}
- {{??}}
- {{=helper.link('Off', 'close', 'on')}}
- {{?}}
-
-
- {{=data.cellTemperature}} K
-
-
- {{? data.isOpen}}
- {{=helper.link('Open', 'unlock', 'close')}}
- {{??}}
- {{=helper.link('Closed', 'lock', 'open')}}
- {{?}}
- {{? data.autoEject}}
- {{=helper.link('Auto', 'sign-out', 'autoeject')}}
- {{??}}
- {{=helper.link('Manual', 'sign-in', 'autoeject')}}
- {{?}}
-
- Beaker
- {{? data.isBeakerLoaded}}
- {{? data.beakerContents.length}}
- {{~ data.beakerContents :reagent:i}}
- {{=reagent.volume}} units of {{=reagent.name}}
- - {{~}} - {{??}} - Beaker Empty - {{?}} - {{??}} - No Beaker Loaded - {{?}} - Storage
- {{=helper.bar(data.capacityPercent, 0, 100, data.capacityPercent >= 50 ? 'good' : data.capacityPercent >= 15 ? 'average' : 'bad', helper.round(data.capacityPercent) + '%')}}
-
- Input
- {{=helper.link('Auto', 'refresh', 'tryinput', null, data.inputAttempt ? 'selected' : null)}}
- {{=helper.link('Off', 'close', 'tryinput', null, data.inputAttempt ? null : 'selected')}}
-
- {{? data.capacityPercent >= 99}}
- [Fully Charged]
- {{?? data.inputting}}
- [Charging]
- {{??}}
- [Not Charging]
- {{?}}
-
-
- {{=helper.bar(data.inputLevel, 0, data.inputLevelMax, null, data.inputLevel + ' W')}}
-
-
- {{=helper.link('', 'fast-backward', 'input', {'set': 'min'}, data.inputLevel ? null : 'selected')}}
- {{=helper.link('', 'backward', 'input', {'set': 'minus'}, data.inputLevel ? null : 'disabled')}}
- {{=helper.link('Set', 'pencil', 'input', {'set': 'custom'}, null)}}
- {{=helper.link('', 'forward', 'input', {'set': 'plus'}, data.inputLevel == data.inputLevelMax ? 'disabled' : null)}}
- {{=helper.link('', 'fast-forward', 'input', {'set': 'max'}, data.inputLevel == data.inputLevelMax ? 'selected' : null)}}
-
-
- {{=data.inputAvailable}} W
-
- Output
- {{=helper.link('On', 'power-off', 'tryoutput', null, data.outputAttempt ? 'selected' : null)}}
- {{=helper.link('Off', 'close', 'tryoutput', null, data.outputAttempt ? null : 'selected')}}
-
- {{? data.outputting}}
- [Sending]
- {{?? data.charge > 0}}
- [Not Sending]
- {{??}}
- [No Charge]
- {{?}}
-
-
- {{=helper.bar(data.outputLevel, 0, data.outputLevelMax, null, data.outputLevel + ' W')}}
-
-
- {{=helper.link('', 'fast-backward', 'output', {'set': 'min'}, data.outputLevel ? null : 'selected')}}
- {{=helper.link('', 'backward', 'output', {'set': 'minus'}, data.outputLevel ? null : 'disabled')}}
- {{=helper.link('Set', 'pencil', 'output', {'set': 'custom'}, null)}}
- {{=helper.link('', 'forward', 'output', {'set': 'plus'}, data.outputLevel == data.outputLevelMax ? 'disabled' : null)}}
- {{=helper.link('', 'fast-forward', 'output', {'set': 'max'}, data.outputLevel == data.outputLevelMax ? 'selected' : null)}}
-
-
- {{=data.outputUsed}} W
-
- Status
- {{=data.generated}} W
-
-
- {{=data.angle}}° ({{=data.direction}})
-
-
- {{=helper.link('15°', 'step-backward', 'control', {'cdir': '-15'})}}
- {{=helper.link('1°', 'backward', 'control', {'cdir': '-1'})}}
- {{=helper.link('1°', 'forward', 'control', {'cdir': '1'})}}
- {{=helper.link('15°', 'step-forward', 'control', {'cdir': '15'})}}
-
- Tracking
- {{=helper.link('Off', 'close', 'tracking', {'mode': '0'}, (data.tracking_state == 0) ? 'selected' : '')}}
- {{=helper.link('Timed', 'clock-o', 'tracking', {'mode': '1'}, (data.tracking_state == 1) ? 'selected' : '')}}
- {{? data.connected_tracker}}
- {{=helper.link('Auto', 'refresh', 'tracking', {'mode': '2'}, (data.tracking_state == 2) ? 'selected' : '')}}
- {{??}}
- {{=helper.link('Auto', 'refresh', null, null, 'disabled')}}
- {{?}}
-
-
- {{=data.tracking_rate}} deg/h ({{=data.rotating_way}})
-
-
- {{=helper.link('180°', 'fast-backward', 'control', {'tdir': '-180'})}}
- {{=helper.link('30°', 'step-backward', 'control', {'tdir': '-30'})}}
- {{=helper.link('1°', 'backward', 'control', {'tdir': '-1'})}}
- {{=helper.link('1°', 'forward', 'control', {'tdir': '1'})}}
- {{=helper.link('30°', 'step-forward', 'control', {'tdir': '30'})}}
- {{=helper.link('180°', 'fast-forward', 'control', {'tdir': '180'})}}
-
- Devices
- {{=helper.link('Refresh', 'refresh', 'refresh')}}
-
-
- {{? data.connected_tracker}}
- Found
- {{??}}
- Not Found
- {{?}}
-
-
- {{=data.connected_panels}} Connected
-
-
-Status
- {{=helper.link('On', 'power-off', 'power', null, data.on ? 'selected' : null)}}
- {{=helper.link('Off', 'close', 'power', null, data.on ? null : 'selected')}}
-
-
- {{? data.hasPowercell}}
- {{=helper.bar(data.powerLevel, 0, 100, 'good', data.powerLevel + '%')}}
- {{??}}
- No power cell loaded.
- {{?}}
-
-
- {{? data.hasPowercell}}
- {{=helper.link('Eject', 'eject', 'ejectcell')}}
- {{??}}
- {{=helper.link('Install', 'eject', 'installcell')}}
- {{?}}
-
- Thermostat
- {{=data.currentTemp}}°C
-
-
- {{=data.targetTemp}}°C
-
-
- {{=helper.link('', 'fast-backward', 'temp', {'set': -20}, data.targetTemp > data.minTemp ? null : 'disabled')}}
- {{=helper.link('', 'backward', 'temp', {'set': -5}, data.targetTemp > data.minTemp ? null : 'disabled')}}
- {{=helper.link('Set', 'pencil', 'temp', {'set': 'custom'}, null)}}
- {{=helper.link('', 'forward', 'temp', {'set': 5}, data.targetTemp < data.maxTemp ? null : 'disabled')}}
- {{=helper.link('', 'fast-forward', 'temp', {'set': 20}, data.targetTemp < data.maxTemp ? null : 'disabled')}}
-
-
- {{? data.open}}
- {{=helper.link('Heat', 'long-arrow-up', 'mode', {'mode': 'heat'}, data.mode != "heat" ? null : 'selected')}}
- {{=helper.link('Cool', 'long-arrow-down', 'mode', {'mode': 'cool'}, data.mode != "cool" ? null : 'selected')}}
- {{=helper.link('Auto', 'arrows-v', 'mode', {'mode': 'auto'}, (data.mode == "heat" || data.mode == "cool") ? null : 'selected')}}
- {{??}}
- {{? data.mode == "heat"}}
- Heat
- {{?? data.mode == "cool"}}
- Cool
- {{??}}
- Auto
- {{?}}
- {{?}}
-
-
- {{=helper.bar(data.tankPressure, 0, 1013, (data.tankPressure > 200) ? 'good' : ((data.tankPressure > 100) ? 'average' : 'bad'), data.tankPressure + ' kPa')}}
-
-
-
- {{=helper.bar(data.releasePressure, data.minReleasePressure, data.maxReleasePressure, null, data.releasePressure + ' kPa')}}
-
-
- {{=helper.link('Reset', 'refresh', 'pressure', {'set': 'reset'}, (data.releasePressure != data.defaultReleasePressure) ? null : 'disabled')}}
- {{=helper.link('Min', 'minus', 'pressure', {'set': 'min'}, (data.releasePressure > data.minReleasePressure) ? null : 'disabled')}}
- {{=helper.link('Set', 'pencil', 'pressure', {'set': 'custom'}, null)}}
- {{=helper.link('Max', 'plus', 'pressure', {'set': 'max'}, (data.releasePressure < data.maxReleasePressure) ? null : 'disabled')}}
-
-
- {{=helper.link('Open', 'unlock', 'valve', null, data.maskConnected ? (data.valveOpen ? 'selected' : null) : 'disabled')}}
- {{=helper.link('Close', 'lock', 'valuve', null, data.valveOpen ? null : 'selected')}}
-
-
+ {{#if title}}
+
diff --git a/tgui/scripts/components/notice.ract b/tgui/scripts/components/notice.ract
new file mode 100644
index 00000000000..f6c063596d8
--- /dev/null
+++ b/tgui/scripts/components/notice.ract
@@ -0,0 +1,3 @@
+{{title}}+ {{#if button}}{{yield button}}{{/if}} +
+ {{yield}}
+
diff --git a/tgui/scripts/components/resize.ract b/tgui/scripts/components/resize.ract
new file mode 100644
index 00000000000..3f847a9aa73
--- /dev/null
+++ b/tgui/scripts/components/resize.ract
@@ -0,0 +1,23 @@
+
+
+{{#if config.fancy}}
+
+{{/if}}
diff --git a/tgui/scripts/components/section.ract b/tgui/scripts/components/section.ract
new file mode 100644
index 00000000000..bcdd3e0e6e8
--- /dev/null
+++ b/tgui/scripts/components/section.ract
@@ -0,0 +1,14 @@
+
+ {{yield}}
+
+ {{/if}}
+ {{else}}
+ {{yield}}
+ {{/if}}
+
+ {{#if title}}
+
diff --git a/tgui/scripts/components/titlebar.ract b/tgui/scripts/components/titlebar.ract
new file mode 100644
index 00000000000..f4cc29dc0fe
--- /dev/null
+++ b/tgui/scripts/components/titlebar.ract
@@ -0,0 +1,42 @@
+
+
+{{title}}+ {{#if button}}{{yield button}}{{/if}} ++ +
{{Math.round(powerLoad)}} W
+ {{status >= 2 ? "On" : "Off"}}
+ [{{status == 1 || status == 3 ? "Auto" : "Manual"}}]
+
+ {{#if !data.locked || data.siliconUser}}
+
+ + {{#each adata.beakerContents}} + {{Math.fixed(volume, 2)}} units of {{name}} + {{else}} + Beaker Empty + {{/each}} + {{else}} + No Beaker + {{/if}} + + {{#each adata.beakerContents}} + {{Math.fixed(volume, 2)}} units of {{name}} + {{else}} + Beaker Empty + {{/each}} + {{else}} + No Beaker + {{/if}} + + {{else}} + Beaker Empty + {{/each}} + {{else}} + No Beaker + {{/if}} +
+
+
+
+
+
Loading...
+ |