diff --git a/.github/boring-cyborg.yml b/.github/boring-cyborg.yml index 4b8d729834..d6047f49af 100644 --- a/.github/boring-cyborg.yml +++ b/.github/boring-cyborg.yml @@ -6,24 +6,24 @@ labelPRBasedOnFilePath: # Add 'Type: Map' to any changes to .dmm files "Type: Map": - - '**.dmm' + - '**/*.dmm' # Add 'Type: Map' to any changes to image files "Type: Icon": - - '**.dmi' - - '**.png' - - '**.jpg' + - '**/*.dmi' + - '**/*.png' + - '**/*.jpg' # Add 'Type: Sound' to any change to sound files "Type: Sound": - - '**.ogg' - - '**.mp3' - - '**.wav' + - '**/*.ogg' + - '**/*.mp3' + - '**/*.wav' # Add 'Type: Fluff' to any change to *custom_items* "Type: Fluff": - - '**custom_items**' - - '**loadout_fluff**' + - '**/*custom_items*' + - '**/*loadout_fluff*' # Contains changes to system folders "Type: .git or .github": diff --git a/code/__defines/is_helpers.dm b/code/__defines/is_helpers.dm index d7bab37345..f97f206634 100644 --- a/code/__defines/is_helpers.dm +++ b/code/__defines/is_helpers.dm @@ -54,4 +54,4 @@ //--------------- //#define isturf(D) istype(D, /turf) //Built in #define isopenspace(A) istype(A, /turf/simulated/open) -#define isspace(A) istype(A, /turf/space) +#define isspace(A) istype(A, /turf/space) diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 518cc78b91..978f2d782d 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -159,3 +159,23 @@ #define ui_ghost_teleport "SOUTH:6,CENTER+1:24" #define ui_ghost_pai "SOUTH: 6,CENTER+2:24" #define ui_ghost_updown "SOUTH: 6,CENTER+3:24" + +// Rig panel +#define ui_rig_deco1 "WEST:-7, SOUTH+5" +#define ui_rig_deco2 "WEST:-7, SOUTH+6" +#define ui_rig_pwr "WEST+1:-7, SOUTH+6" +#define ui_rig_health "WEST+1:-7, SOUTH+6" +#define ui_rig_air "WEST+1:-7, SOUTH+5" +#define ui_rig_airtoggle "WEST+1:-7, SOUTH+5" +#define ui_rig_deco1_f "WEST+2:-7, SOUTH+5" +#define ui_rig_deco2_f "WEST+2:-7, SOUTH+6" + +// Mech panel +#define ui_mech_deco1 "WEST:-7, SOUTH+8" +#define ui_mech_deco2 "WEST:-7, SOUTH+9" +#define ui_mech_pwr "WEST+1:-7, SOUTH+9" +#define ui_mech_health "WEST+1:-7, SOUTH+9" +#define ui_mech_air "WEST+1:-7, SOUTH+8" +#define ui_mech_airtoggle "WEST+1:-7, SOUTH+8" +#define ui_mech_deco1_f "WEST+2:-7, SOUTH+8" +#define ui_mech_deco2_f "WEST+2:-7, SOUTH+9" diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 2b18b5a90d..7e23e31692 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -36,8 +36,9 @@ alert = new type if(new_master) - alert.icon_state = "template" // blank, so our icon is presented + alert.icon_state = "itembased" var/image/I = image(icon = new_master.icon, icon_state = new_master.icon_state, dir = SOUTH) + I.plane = PLANE_PLAYER_HUD_ABOVE alert.add_overlay(I) alert.master = new_master else @@ -220,6 +221,11 @@ The box in your backpack has an oxygen tank and gas mask in it." or something covering your eyes." icon_state = "blind" +/obj/screen/alert/confused + name = "Confused" + desc = "You're confused, and may stumble into things! This may be from concussive effects, drugs, or dizzyness. Walking will help reduce incidents." + icon_state = "confused" + /obj/screen/alert/high name = "High" desc = "Whoa man, you're tripping balls! Careful you don't get addicted... if you aren't already." @@ -312,12 +318,14 @@ Recharging stations are available in robotics, the dormitory bathrooms, and the name = "Hacked" desc = "Hazardous non-standard equipment detected. Please ensure any usage of this equipment is in line with unit's laws, if any." icon_state = "hacked" + no_underlay = TRUE /obj/screen/alert/locked name = "Locked Down" desc = "Unit has been remotely locked down. Usage of a Robotics Control Console like the one in the Research Director's \ office by your AI master or any qualified human may resolve this matter. Robotics may provide further assistance if necessary." icon_state = "locked" + no_underlay = TRUE /obj/screen/alert/newlaw name = "Law Update" @@ -325,6 +333,7 @@ office by your AI master or any qualified human may resolve this matter. Robotic so as to remain in compliance with the most up-to-date laws." icon_state = "newlaw" timeout = 300 + no_underlay = TRUE //MECHS @@ -397,12 +406,13 @@ so as to remain in compliance with the most up-to-date laws." for(var/i = 1, i <= alerts.len, i++) var/obj/screen/alert/alert = alerts[alerts[i]] - if(alert.icon_state in cached_icon_states(ui_style)) // prevents "" state from attempting matches + if(alert.icon_state in cached_icon_states(ui_style)) alert.icon = ui_style else if(!alert.no_underlay) var/image/I = image(icon = ui_style, icon_state = "template") I.color = ui_color + I.alpha = ui_alpha alert.underlays = list(I) switch(i) diff --git a/code/_onclick/hud/ghost.dm b/code/_onclick/hud/ghost.dm index 048b0e716d..7af541e9d3 100644 --- a/code/_onclick/hud/ghost.dm +++ b/code/_onclick/hud/ghost.dm @@ -1,30 +1,43 @@ /obj/screen/ghost icon = 'icons/mob/screen_ghost.dmi' -/obj/screen/ghost/MouseEntered() +/obj/screen/ghost/MouseEntered(location,control,params) flick(icon_state + "_anim", src) + openToolTip(usr, src, params, title = name, content = desc) + +/obj/screen/ghost/MouseExited() + closeToolTip(usr) + +/obj/screen/ghost/Click() + closeToolTip(usr) /obj/screen/ghost/jumptomob name = "Jump to mob" + desc = "Pick a mob from a list to jump to." icon_state = "jumptomob" /obj/screen/ghost/jumptomob/Click() + ..() var/mob/observer/dead/G = usr G.jumptomob() /obj/screen/ghost/orbit name = "Orbit" + desc = "Pick a mob to follow and orbit." icon_state = "orbit" /obj/screen/ghost/orbit/Click() + ..() var/mob/observer/dead/G = usr G.follow() /obj/screen/ghost/reenter_corpse name = "Reenter corpse" + desc = "Only applicable if you HAVE a corpse..." icon_state = "reenter_corpse" /obj/screen/ghost/reenter_corpse/Click() + ..() var/mob/observer/dead/G = usr G.reenter_corpse() @@ -33,30 +46,37 @@ icon_state = "teleport" /obj/screen/ghost/teleport/Click() + ..() var/mob/observer/dead/G = usr G.dead_tele() /obj/screen/ghost/pai - name = "pAI Candidate" + name = "pAI Alert" + desc = "Ping all the unoccupied pAI devices in the world." icon_state = "pai" /obj/screen/ghost/pai/Click() + ..() var/mob/observer/dead/G = usr G.paialert() /obj/screen/ghost/up name = "Move Upwards" + desc = "Move up a z-level." icon_state = "up" /obj/screen/ghost/up/Click() + ..() var/mob/observer/dead/G = usr G.zMove(UP) /obj/screen/ghost/down name = "Move Downwards" + desc = "Move down a z-level." icon_state = "down" /obj/screen/ghost/down/Click() + ..() var/mob/observer/dead/G = usr G.zMove(DOWN) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index c4dabaf3ca..5fbe760240 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -184,6 +184,7 @@ var/list/global_huds = list( var/list/adding var/list/other + var/list/miniobjs var/list/obj/screen/hotkeybuttons var/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle @@ -193,6 +194,8 @@ var/list/global_huds = list( var/icon/ui_style var/ui_color var/ui_alpha + + var/list/minihuds = list() datum/hud/New(mob/owner) mymob = owner @@ -219,6 +222,7 @@ datum/hud/New(mob/owner) hotkeybuttons = null // item_action_list = null // ? mymob = null + qdel_null(minihuds) /datum/hud/proc/hidden_inventory_update() if(!mymob) return @@ -325,6 +329,26 @@ datum/hud/New(mob/owner) HUD.ui_color = client?.prefs?.UI_style_color HUD.ui_alpha = client?.prefs?.UI_style_alpha +/datum/hud/proc/apply_minihud(var/datum/mini_hud/MH) + if(MH in minihuds) + return + minihuds += MH + if(mymob.client) + mymob.client.screen -= miniobjs + miniobjs += MH.get_screen_objs() + if(mymob.client) + mymob.client.screen += miniobjs + +/datum/hud/proc/remove_minihud(var/datum/mini_hud/MH) + if(!(MH in minihuds)) + return + minihuds -= MH + if(mymob.client) + mymob.client.screen -= miniobjs + miniobjs -= MH.get_screen_objs() + if(mymob.client) + mymob.client.screen += miniobjs + //Triggered when F12 is pressed (Unless someone changed something in the DMF) /mob/verb/button_pressed_F12(var/full = 0 as null) set name = "F12" @@ -332,61 +356,66 @@ datum/hud/New(mob/owner) if(!hud_used) to_chat(usr, "This mob type does not use a HUD.") - return - - if(!ishuman(src)) - to_chat(usr, "Inventory hiding is currently only supported for human mobs, sorry.") - return - - if(!client) return + return FALSE + if(!client) + return FALSE if(client.view != world.view) - return + return FALSE + + toggle_hud_vis(full) + +/mob/proc/toggle_hud_vis(full) if(hud_used.hud_shown) hud_used.hud_shown = 0 - if(src.hud_used.adding) - src.client.screen -= src.hud_used.adding - if(src.hud_used.other) - src.client.screen -= src.hud_used.other - if(src.hud_used.hotkeybuttons) - src.client.screen -= src.hud_used.hotkeybuttons - - //Due to some poor coding some things need special treatment: - //These ones are a part of 'adding', 'other' or 'hotkeybuttons' but we want them to stay - if(!full) - src.client.screen += src.hud_used.l_hand_hud_object //we want the hands to be visible - src.client.screen += src.hud_used.r_hand_hud_object //we want the hands to be visible - src.client.screen += src.hud_used.action_intent //we want the intent swticher visible - src.hud_used.action_intent.screen_loc = ui_acti_alt //move this to the alternative position, where zone_select usually is. - else - src.client.screen -= src.healths - src.client.screen -= src.internals - src.client.screen -= src.gun_setting_icon - - //These ones are not a part of 'adding', 'other' or 'hotkeybuttons' but we want them gone. - src.client.screen -= src.zone_sel //zone_sel is a mob variable for some reason. - + if(hud_used.adding) + client.screen -= hud_used.adding + if(hud_used.other) + client.screen -= hud_used.other + if(hud_used.hotkeybuttons) + client.screen -= hud_used.hotkeybuttons else hud_used.hud_shown = 1 - if(src.hud_used.adding) - src.client.screen += src.hud_used.adding - if(src.hud_used.other && src.hud_used.inventory_shown) - src.client.screen += src.hud_used.other - if(src.hud_used.hotkeybuttons && !src.hud_used.hotkey_ui_hidden) - src.client.screen += src.hud_used.hotkeybuttons - if(src.healths) - src.client.screen |= src.healths - if(src.internals) - src.client.screen |= src.internals - if(src.gun_setting_icon) - src.client.screen |= src.gun_setting_icon + if(hud_used.adding) + client.screen += hud_used.adding + if(hud_used.other && hud_used.inventory_shown) + client.screen += hud_used.other + if(hud_used.hotkeybuttons && !hud_used.hotkey_ui_hidden) + client.screen += hud_used.hotkeybuttons + if(healths) + client.screen |= healths + if(internals) + client.screen |= internals + if(gun_setting_icon) + client.screen |= gun_setting_icon - src.hud_used.action_intent.screen_loc = ui_acti //Restore intent selection to the original position - src.client.screen += src.zone_sel //This one is a special snowflake + hud_used?.action_intent.screen_loc = ui_acti //Restore intent selection to the original position + client.screen += zone_sel //This one is a special snowflake hud_used.hidden_inventory_update() hud_used.persistant_inventory_update() update_action_buttons() hud_used.reorganize_alerts() + return TRUE + +/mob/living/carbon/human/toggle_hud_vis(full) + ..() + + // Prevents humans from hiding a few hud elements + if(!hud_used.hud_shown) // transitioning to hidden + //Due to some poor coding some things need special treatment: + //These ones are a part of 'adding', 'other' or 'hotkeybuttons' but we want them to stay + if(!full) + client.screen += hud_used.l_hand_hud_object //we want the hands to be visible + client.screen += hud_used.r_hand_hud_object //we want the hands to be visible + client.screen += hud_used.action_intent //we want the intent swticher visible + hud_used?.action_intent.screen_loc = ui_acti_alt //move this to the alternative position, where zone_select usually is. + else + client.screen -= healths + client.screen -= internals + client.screen -= gun_setting_icon + + //These ones are not a part of 'adding', 'other' or 'hotkeybuttons' but we want them gone. + client.screen -= zone_sel //zone_sel is a mob variable for some reason. //Similar to button_pressed_F12() but keeps zone_sel, gun_setting_icon, and healths. /mob/proc/toggle_zoom_hud() diff --git a/code/_onclick/hud/rigmech.dm b/code/_onclick/hud/rigmech.dm new file mode 100644 index 0000000000..91632e1604 --- /dev/null +++ b/code/_onclick/hud/rigmech.dm @@ -0,0 +1,267 @@ +/datum/mini_hud + var/datum/hud/main_hud + var/list/screenobjs = list() + var/list/types_to_instantiate + var/needs_processing = FALSE + +/datum/mini_hud/New(var/datum/hud/other) + apply_to_hud(other) + if(needs_processing) + START_PROCESSING(SSprocessing, src) + +/datum/mini_hud/Destroy() + main_hud?.remove_minihud(src) + main_hud = null + if(needs_processing) + STOP_PROCESSING(SSprocessing, src) + return ..() + +// Apply to a real /datum/hud +/datum/mini_hud/proc/apply_to_hud(var/datum/hud/other) + if(main_hud) + unapply_to_hud(main_hud) + main_hud = other + main_hud.apply_minihud(src) + +// Remove from a real /datum/hud +/datum/mini_hud/proc/unapply_to_hud(var/datum/hud/other) + main_hud.remove_minihud(src) + +// Update the hud +/datum/mini_hud/process() + return PROCESS_KILL // You shouldn't be here! + +// Return a list of screen objects we use +/datum/mini_hud/proc/get_screen_objs(var/mob/M) + return screenobjs + +// Specific types +/datum/mini_hud/rig + var/obj/item/weapon/rig/owner_rig + var/obj/screen/rig/power/power + var/obj/screen/rig/health/health + var/obj/screen/rig/air/air + var/obj/screen/rig/airtoggle/airtoggle + + needs_processing = TRUE + +/datum/mini_hud/rig/New(var/datum/hud/other, var/obj/item/weapon/rig/owner) + owner_rig = owner + power = new () + health = new () + air = new () + airtoggle = new () + + screenobjs = list(power, health, air, airtoggle) + screenobjs += new /obj/screen/rig/deco1 + screenobjs += new /obj/screen/rig/deco2 + screenobjs += new /obj/screen/rig/deco1_f + screenobjs += new /obj/screen/rig/deco2_f + + for(var/scr in screenobjs) + var/obj/screen/S = scr + S.master = owner_rig + ..() + +/datum/mini_hud/rig/Destroy() + if(owner_rig) + //owner_rig.minihud = null + owner_rig = null + return ..() + +/datum/mini_hud/rig/process() + if(!owner_rig) + qdel(src) + return + + var/obj/item/weapon/cell/rigcell = owner_rig.cell + var/obj/item/weapon/tank/rigtank = owner_rig.air_supply + + var/charge_percentage = rigcell ? rigcell.charge / rigcell.maxcharge : 0 + var/air_percentage = rigtank ? CLAMP(rigtank.air_contents.total_moles / 17.4693, 0, 1) : 0 + var/air_on = owner_rig.wearer?.internal ? 1 : 0 + + power.icon_state = "pwr[round(charge_percentage / 0.2, 1)]" + air.icon_state = "air[round(air_percentage / 0.2, 1)]" + health.icon_state = owner_rig.malfunctioning ? "health1" : "health5" + airtoggle.icon_state = "airon[air_on]" + +/datum/mini_hud/mech + var/obj/mecha/owner_mech + var/obj/screen/mech/power/power + var/obj/screen/mech/health/health + var/obj/screen/mech/air/air + var/obj/screen/mech/airtoggle/airtoggle + + needs_processing = TRUE + +/datum/mini_hud/mech/New(var/datum/hud/other, var/obj/mecha/owner) + owner_mech = owner + power = new () + health = new () + air = new () + airtoggle = new () + + screenobjs = list(power, health, air, airtoggle) + screenobjs += new /obj/screen/mech/deco1 + screenobjs += new /obj/screen/mech/deco2 + screenobjs += new /obj/screen/mech/deco1_f + screenobjs += new /obj/screen/mech/deco2_f + + for(var/scr in screenobjs) + var/obj/screen/S = scr + S.master = owner_mech + ..() + +/datum/mini_hud/mech/Destroy() + if(owner_mech) + owner_mech.minihud = null + owner_mech = null + return ..() + +/datum/mini_hud/mech/process() + if(!owner_mech) + qdel(src) + return + + var/obj/item/weapon/cell/mechcell = owner_mech.cell + var/obj/machinery/portable_atmospherics/canister/mechtank = owner_mech.internal_tank + + var/charge_percentage = mechcell ? mechcell.charge / mechcell.maxcharge : 0 + var/air_percentage = mechtank ? CLAMP(mechtank.air_contents.total_moles / 1863.47, 0, 1) : 0 + var/health_percentage = owner_mech.health / owner_mech.maxhealth + var/air_on = owner_mech.use_internal_tank + + power.icon_state = "pwr[round(charge_percentage / 0.2, 1)]" + air.icon_state = "air[round(air_percentage / 0.2, 1)]" + health.icon_state = "health[round(health_percentage / 0.2, 1)]" + airtoggle.icon_state = "airon[air_on]" + +// Screen objects +/obj/screen/rig + icon = 'icons/mob/screen_rigmech.dmi' + +/obj/screen/rig/deco1 + name = "RIG Status" + icon_state = "frame1_1" + screen_loc = ui_rig_deco1 + +/obj/screen/rig/deco2 + name = "RIG Status" + icon_state = "frame1_2" + screen_loc = ui_rig_deco2 + +/obj/screen/rig/deco1_f + name = "RIG Status" + icon_state = "frame1_1_far" + screen_loc = ui_rig_deco1_f + +/obj/screen/rig/deco2_f + name = "RIG Status" + icon_state = "frame1_2_far" + screen_loc = ui_rig_deco2_f + +/obj/screen/rig/power + name = "Charge Level" + icon_state = "pwr5" + screen_loc = ui_rig_pwr + +/obj/screen/rig/health + name = "Integrity Level" + icon_state = "health5" + screen_loc = ui_rig_health + +/obj/screen/rig/air + name = "Air Storage" + icon_state = "air5" + screen_loc = ui_rig_air + +/obj/screen/rig/airtoggle + name = "Toggle Air" + icon_state = "airoff" + screen_loc = ui_rig_airtoggle + +/obj/screen/rig/airtoggle/Click() + var/mob/living/carbon/human/user = usr + if(!istype(user) || user.stat || user.incapacitated()) + return + var/obj/item/weapon/rig/owner_rig = master + if(user != owner_rig.wearer) + return + user.toggle_internals() + +/obj/screen/mech + icon = 'icons/mob/screen_rigmech.dmi' + +/obj/screen/mech/deco1 + name = "Mech Status" + icon_state = "frame1_1" + screen_loc = ui_mech_deco1 + +/obj/screen/mech/deco2 + name = "Mech Status" + icon_state = "frame1_2" + screen_loc = ui_mech_deco2 + +/obj/screen/mech/deco1_f + name = "Mech Status" + icon_state = "frame1_1_far" + screen_loc = ui_mech_deco1_f + +/obj/screen/mech/deco2_f + name = "Mech Status" + icon_state = "frame1_2_far" + screen_loc = ui_mech_deco2_f + +/obj/screen/mech/power + name = "Charge Level" + icon_state = "pwr5" + screen_loc = ui_mech_pwr + +/obj/screen/mech/health + name = "Integrity Level" + icon_state = "health5" + screen_loc = ui_mech_health + +/obj/screen/mech/air + name = "Air Storage" + icon_state = "air5" + screen_loc = ui_mech_air + +/obj/screen/mech/airtoggle + name = "Toggle Air" + icon_state = "airoff" + screen_loc = ui_mech_airtoggle + +/obj/screen/mech/airtoggle/Click() + var/mob/living/carbon/human/user = usr + if(!istype(user) || user.stat || user.incapacitated()) + return + var/obj/mecha/owner_mech = master + if(user != owner_mech.occupant) + return + owner_mech.toggle_internal_tank() + +/* +/mob/observer/dead/create_mob_hud(datum/hud/HUD, apply_to_client = TRUE) + ..() + + var/list/adding = list() + HUD.adding = adding + + var/obj/screen/using + using = new /obj/screen/ghost/jumptomob() + using.screen_loc = ui_ghost_jumptomob + using.hud = src + adding += using + + using = new /obj/screen/ghost/orbit() + using.screen_loc = ui_ghost_orbit + using.hud = src + adding += using + + using = new /obj/screen/ghost/reenter_corpse() + using.screen_loc = ui_ghost_reenter_corpse + using.hud = src + adding += using +*/ \ No newline at end of file diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm index 8b194a139c..7c214e3a29 100644 --- a/code/datums/helper_datums/getrev.dm +++ b/code/datums/helper_datums/getrev.dm @@ -5,40 +5,75 @@ var/global/datum/getrev/revdata = new() var/revision var/date var/showinfo + var/list/testmerge = list() /datum/getrev/New() - var/list/head_branch = file2list(".git/HEAD", "\n") - if(head_branch.len) - branch = copytext(head_branch[1], 17) + if(world.TgsAvailable()) // Try TGS maybe + testmerge = world.TgsTestMerges() + var/datum/tgs_revision_information/REV = world.TgsRevision() + if(REV) + revision = REV.origin_commit || REV.commit + branch = "-Using TGS-" // TGS doesn't provide branch info yet + date = "-Using TGS-" // Or date + + if(!revision) // File parse method + var/list/head_branch = file2list(".git/HEAD", "\n") + if(head_branch.len) + branch = copytext(head_branch[1], 17) - var/list/head_log = file2list(".git/logs/HEAD", "\n") - for(var/line=head_log.len, line>=1, line--) - if(head_log[line]) - var/list/last_entry = splittext(head_log[line], " ") - if(last_entry.len < 2) continue - revision = last_entry[2] - // Get date/time - if(last_entry.len >= 5) - var/unix_time = text2num(last_entry[5]) - if(unix_time) - date = unix2date(unix_time) - break + var/list/head_log = file2list(".git/logs/HEAD", "\n") + for(var/line=head_log.len, line>=1, line--) + if(head_log[line]) + var/list/last_entry = splittext(head_log[line], " ") + if(last_entry.len < 2) continue + revision = last_entry[2] + // Get date/time + if(last_entry.len >= 5) + var/unix_time = text2num(last_entry[5]) + if(unix_time) + date = unix2date(unix_time) + break - to_world_log("Running revision:") - to_world_log(branch) - to_world_log(date) - to_world_log(revision) + to_world_log("-Revision Info-") + to_world_log("Branch: [branch]") + to_world_log("Date: [date]") + to_world_log("Revision: [revision]") + +/datum/getrev/proc/GetTestMergeInfo(header = TRUE) + if(!testmerge.len) + return "" + . = header ? "The following pull requests are currently test merged:
" : "" + for(var/line in testmerge) + var/datum/tgs_revision_information/test_merge/tm = line + var/cm = tm.pull_request_commit + var/details = ": '" + html_encode(tm.title) + "' by " + html_encode(tm.author) + " at commit " + html_encode(copytext_char(cm, 1, 11)) + if(details && findtext(details, "\[s\]") && (!usr || !usr.client.holder)) + continue + . += "#[tm.number][details]
" client/verb/showrevinfo() set category = "OOC" set name = "Show Server Revision" set desc = "Check the current server code revision" + var/list/msg = list() + if(revdata.revision) - to_chat(src, "Server revision: [revdata.branch] - [revdata.date]") + msg += "Server revision: [revdata.branch] - [revdata.date]" if(config.githuburl) - to_chat(src, "[revdata.revision]") + msg += "[revdata.revision]" else to_chat(src,revdata.revision) else - to_chat(src, "Revision unknown") + msg += "Server revision: Unknown" + + if(world.TgsAvailable()) + var/datum/tgs_version/version = world.TgsVersion() + msg += "TGS version: [version.raw_parameter]" + var/datum/tgs_version/api_version = world.TgsApiVersion() + msg += "DMAPI version: [api_version.raw_parameter]" + + if(revdata.testmerge.len) + msg += revdata.GetTestMergeInfo() + + to_chat(src, msg.Join("
")) diff --git a/code/datums/outfits/jobs/security.dm b/code/datums/outfits/jobs/security.dm index 814cda5054..a5e058ca9c 100644 --- a/code/datums/outfits/jobs/security.dm +++ b/code/datums/outfits/jobs/security.dm @@ -41,8 +41,8 @@ /decl/hierarchy/outfit/job/security/detective/forensic name = OUTFIT_JOB_NAME("Forensic technician") head = /obj/item/clothing/head/helmet/detective_alt - suit = null - uniform = /obj/item/clothing/under/detective_alt + suit = /datum/gear/uniform/detective_alt2 + uniform = /obj/item/clothing/under/det //VOREStation Edit End /decl/hierarchy/outfit/job/security/officer diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 87a09d538a..01f5e687d8 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -21,7 +21,7 @@ var/icon_rotation = 0 // Used to rotate icons in update_transform() var/old_x = 0 var/old_y = 0 - var/datum/riding/riding_datum //VOREStation Add - Moved from /obj/vehicle + var/datum/riding/riding_datum = null var/does_spin = TRUE // Does the atom spin when thrown (of course it does :P) var/movement_type = NONE diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index a410ad79b3..2200ef94c6 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -53,15 +53,6 @@ return TRUE return FALSE -/obj/machinery/optable/MouseDrop_T(obj/O as obj, mob/user as mob) - - if((!(istype(O, /obj/item/weapon)) || user.get_active_hand() != O)) - return - user.drop_item() - if(O.loc != src.loc) - step(O, get_dir(O, src)) - return - /obj/machinery/optable/proc/check_victim() if(locate(/mob/living/carbon/human, src.loc)) var/mob/living/carbon/human/M = locate(/mob/living/carbon/human, src.loc) @@ -102,40 +93,43 @@ else icon_state = "table2-idle" -/obj/machinery/optable/MouseDrop_T(mob/target, mob/user) - - var/mob/living/M = user - if(user.stat || user.restrained() || !check_table(user) || !iscarbon(target)) - return - if(istype(M)) - take_victim(target,user) - else +/obj/machinery/optable/MouseDrop_T(mob/living/carbon/target, mob/living/user) + if(!istype(target) || !istype(user)) return ..() + if(!Adjacent(target) || !Adjacent(user)) + return ..() + + if(user.incapacitated() || !check_table(target, user)) + return ..() + + take_victim(target, user) + /obj/machinery/optable/verb/climb_on() set name = "Climb On Table" set category = "Object" set src in oview(1) - if(usr.stat || !ishuman(usr) || usr.restrained() || !check_table(usr)) + var/mob/living/user = usr + if(!istype(user) || user.incapacitated() || !check_table(user, user)) return - take_victim(usr,usr) + take_victim(user, user) -/obj/machinery/optable/attackby(obj/item/weapon/W as obj, mob/living/carbon/user as mob) +/obj/machinery/optable/attackby(obj/item/weapon/W, mob/living/carbon/user) if(istype(W, /obj/item/weapon/grab)) var/obj/item/weapon/grab/G = W - if(iscarbon(G.affecting) && check_table(G.affecting)) - take_victim(G.affecting,usr) + if(iscarbon(G.affecting) && check_table(G.affecting, user)) + take_victim(G.affecting, user) qdel(W) return -/obj/machinery/optable/proc/check_table(mob/living/carbon/patient as mob) +/obj/machinery/optable/proc/check_table(mob/living/carbon/patient, mob/living/user) check_victim() if(victim && get_turf(victim) == get_turf(src) && victim.lying) - to_chat(usr, "\The [src] is already occupied!") + to_chat(user, "\The [src] is already occupied!") return 0 if(patient.buckled) - to_chat(usr, "Unbuckle \the [patient] first!") + to_chat(user, "Unbuckle \the [patient] first!") return 0 return 1 \ No newline at end of file diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index f7fd84eca7..60541e0fe3 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -152,11 +152,11 @@ cameraFollow = null /mob/living/silicon/ai/proc/ai_actual_track(mob/living/target as mob) - if(!istype(target)) return + if(!istype(target)) return FALSE var/mob/living/silicon/ai/U = usr if(target == U.cameraFollow) - return + return TRUE if(U.cameraFollow) U.ai_cancel_tracking() @@ -185,6 +185,8 @@ return sleep(10) + return TRUE + /obj/machinery/camera/attack_ai(var/mob/living/silicon/ai/user as mob) if (!istype(user)) return diff --git a/code/game/machinery/oxygen_pump.dm b/code/game/machinery/oxygen_pump.dm index b40314d2c2..37c75957be 100644 --- a/code/game/machinery/oxygen_pump.dm +++ b/code/game/machinery/oxygen_pump.dm @@ -41,8 +41,11 @@ return ..() /obj/machinery/oxygen_pump/MouseDrop(var/mob/living/carbon/human/target, src_location, over_location) - ..() - if(istype(target) && CanMouseDrop(target)) + var/mob/living/user = usr + if(!istype(user) || !istype(target)) + return ..() + + if(CanMouseDrop(target, user)) if(!can_apply_to_target(target, usr)) // There is no point in attempting to apply a mask if it's impossible. return usr.visible_message("\The [usr] begins placing \the [contained] onto [target].") diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 990a99bc05..594c89a4ee 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -100,6 +100,8 @@ var/static/image/radial_image_lighttoggle = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_light") var/static/image/radial_image_statpanel = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine2") + var/datum/mini_hud/mech/minihud + /obj/mecha/drain_power(var/drain_check) @@ -195,6 +197,7 @@ QDEL_NULL(pr_give_air) QDEL_NULL(pr_internal_damage) QDEL_NULL(spark_system) + QDEL_NULL(minihud) mechas_list -= src //global mech list . = ..() @@ -1321,6 +1324,8 @@ src.verbs += /obj/mecha/verb/eject src.log_append_to_last("[H] moved in as pilot.") src.icon_state = src.reset_icon() + if(occupant.hud_used) + minihud = new (occupant.hud_used, src) update_cell_alerts() update_damage_alerts() set_dir(dir_in) @@ -1386,6 +1391,7 @@ /obj/mecha/proc/go_out() if(!src.occupant) return var/atom/movable/mob_container + QDEL_NULL(minihud) if(ishuman(occupant)) mob_container = src.occupant else if(istype(occupant, /mob/living/carbon/brain)) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index c295a1a08c..4835268bfa 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -341,7 +341,7 @@ var/list/global/slot_flags_enumeration = list( //If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen. //Set disable_warning to 1 if you wish it to not give you outputs. //Should probably move the bulk of this into mob code some time, as most of it is related to the definition of slots and not item-specific -/obj/item/proc/mob_can_equip(M as mob, slot, disable_warning = 0) +/obj/item/proc/mob_can_equip(M as mob, slot, disable_warning = FALSE) if(!slot) return 0 if(!M) return 0 diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm index 562ed56990..08d4440d66 100644 --- a/code/game/objects/items/devices/gps.dm +++ b/code/game/objects/items/devices/gps.dm @@ -183,6 +183,13 @@ var/list/GPS_list = list() /obj/item/device/gps/security/on tracking = TRUE +/obj/item/device/gps/security/hos + icon_state = "gps-sec-hos" + gps_tag = "HOS0" + +/obj/item/device/gps/security/hos/on + tracking = TRUE + /obj/item/device/gps/medical icon_state = "gps-med" gps_tag = "MED0" @@ -190,6 +197,13 @@ var/list/GPS_list = list() /obj/item/device/gps/medical/on tracking = TRUE +/obj/item/device/gps/medical/cmo + icon_state = "gps-med-cmo" + gps_tag = "CMO0" + +/obj/item/device/gps/medical/cmo/on + tracking = TRUE + /obj/item/device/gps/science icon_state = "gps-sci" gps_tag = "SCI0" @@ -197,6 +211,13 @@ var/list/GPS_list = list() /obj/item/device/gps/science/on tracking = TRUE +/obj/item/device/gps/science/rd + icon_state = "gps-sci-rd" + gps_tag = "RD0" + +/obj/item/device/gps/science/rd/on + tracking = TRUE + /obj/item/device/gps/engineering icon_state = "gps-eng" gps_tag = "ENG0" @@ -204,6 +225,20 @@ var/list/GPS_list = list() /obj/item/device/gps/engineering/on tracking = TRUE +/obj/item/device/gps/engineering/atmos + icon_state = "gps-eng-atm" + gps_tag = "ATM0" + +/obj/item/device/gps/engineering/atmos/on + tracking = TRUE + +/obj/item/device/gps/engineering/ce + icon_state = "gps-eng-ce" + gps_tag = "CE0" + +/obj/item/device/gps/engineering/ce/on + tracking = TRUE + /obj/item/device/gps/mining icon_state = "gps-mine" gps_tag = "MINE0" diff --git a/code/game/objects/items/weapons/storage/internal.dm b/code/game/objects/items/weapons/storage/internal.dm index ddb7e873e6..63afc51b4e 100644 --- a/code/game/objects/items/weapons/storage/internal.dm +++ b/code/game/objects/items/weapons/storage/internal.dm @@ -18,7 +18,7 @@ /obj/item/weapon/storage/internal/attack_hand() return //make sure this is never picked up -/obj/item/weapon/storage/internal/mob_can_equip(M as mob, slot, disable_warning = 0) +/obj/item/weapon/storage/internal/mob_can_equip(M as mob, slot, disable_warning = FALSE) return 0 //make sure this is never picked up //Helper procs to cleanly implement internal storages - storage items that provide inventory slots for other items. diff --git a/code/game/objects/random/_random.dm b/code/game/objects/random/_random.dm index b559495eb5..8b616c83f5 100644 --- a/code/game/objects/random/_random.dm +++ b/code/game/objects/random/_random.dm @@ -11,15 +11,7 @@ . = ..() if (!prob(spawn_nothing_percentage)) spawn_item() - Random_SafeDestroy(0) - -// This function should, theoretically, guarantee the deletion of the random object. Not all of them destroy themselves for some reason, especially if created through non-standard means. -/obj/random/proc/Random_SafeDestroy(var/recursion_level) - set waitfor = FALSE - sleep(30) - qdel(src) - if(src && recursion_level < 5) - Random_SafeDestroy(recursion_level + 1) + return INITIALIZE_HINT_QDEL // this function should return a specific item to spawn /obj/random/proc/item_to_spawn() diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index e0a94e285b..40c47c9bb9 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -14,8 +14,8 @@ var/glass = 0 // 0 = glass can be installed. -1 = glass can't be installed. 1 = glass is already installed. Text = mineral plating is installed instead. var/created_name = null - New() - update_state() +/obj/structure/door_assembly/New() + update_state() /obj/structure/door_assembly/door_assembly_com base_icon_state = "com" @@ -136,23 +136,23 @@ airlock_type = "/multi_tile/glass" glass = -1 //To prevent bugs in deconstruction process. - New() - if(dir in list(EAST, WEST)) - bound_width = width * world.icon_size - bound_height = world.icon_size - else - bound_width = world.icon_size - bound_height = width * world.icon_size - update_state() +/obj/structure/door_assembly/multi_tile/New() + if(dir in list(EAST, WEST)) + bound_width = width * world.icon_size + bound_height = world.icon_size + else + bound_width = world.icon_size + bound_height = width * world.icon_size + update_state() - Moved(atom/old_loc, direction, forced = FALSE) - . = ..() - if(dir in list(EAST, WEST)) - bound_width = width * world.icon_size - bound_height = world.icon_size - else - bound_width = world.icon_size - bound_height = width * world.icon_size +/obj/structure/door_assembly/multi_tile/Moved(atom/old_loc, direction, forced = FALSE) + . = ..() + if(dir in list(EAST, WEST)) + bound_width = width * world.icon_size + bound_height = world.icon_size + else + bound_width = world.icon_size + bound_height = width * world.icon_size /obj/structure/door_assembly/proc/rename_door(mob/living/user) var/t = sanitizeSafe(input(user, "Enter the name for the windoor.", src.name, src.created_name), MAX_NAME_LEN) diff --git a/code/game/objects/structures/target_stake.dm b/code/game/objects/structures/target_stake.dm index 1e9c091ccb..7802e258ea 100644 --- a/code/game/objects/structures/target_stake.dm +++ b/code/game/objects/structures/target_stake.dm @@ -8,45 +8,45 @@ w_class = ITEMSIZE_HUGE var/obj/item/target/pinned_target // the current pinned target - Moved(atom/old_loc, direction, forced = FALSE) - . = ..() - // Move the pinned target along with the stake - if(pinned_target in view(3, src)) - pinned_target.forceMove(loc) +/obj/structure/target_stake/Moved(atom/old_loc, direction, forced = FALSE) + . = ..() + // Move the pinned target along with the stake + if(pinned_target in view(3, src)) + pinned_target.forceMove(loc) - else // Sanity check: if the pinned target can't be found in immediate view - pinned_target = null - density = 1 + else // Sanity check: if the pinned target can't be found in immediate view + pinned_target = null + density = 1 - attackby(obj/item/W as obj, mob/user as mob) - // Putting objects on the stake. Most importantly, targets - if(pinned_target) - return // get rid of that pinned target first! +/obj/structure/target_stake/attackby(obj/item/W as obj, mob/user as mob) + // Putting objects on the stake. Most importantly, targets + if(pinned_target) + return // get rid of that pinned target first! - if(istype(W, /obj/item/target)) - density = 0 - W.density = 1 - user.remove_from_mob(W) - W.loc = loc - W.layer = ABOVE_JUNK_LAYER - pinned_target = W - to_chat(user, "You slide the target into the stake.") - return + if(istype(W, /obj/item/target)) + density = 0 + W.density = 1 + user.remove_from_mob(W) + W.loc = loc + W.layer = ABOVE_JUNK_LAYER + pinned_target = W + to_chat(user, "You slide the target into the stake.") + return - attack_hand(mob/user as mob) - // taking pinned targets off! - if(pinned_target) - density = 1 - pinned_target.density = 0 - pinned_target.layer = OBJ_LAYER +/obj/structure/target_stake/attack_hand(mob/user as mob) + // taking pinned targets off! + if(pinned_target) + density = 1 + pinned_target.density = 0 + pinned_target.layer = OBJ_LAYER - pinned_target.loc = user.loc - if(ishuman(user)) - if(!user.get_active_hand()) - user.put_in_hands(pinned_target) - to_chat(user, "You take the target out of the stake.") - else - pinned_target.loc = get_turf(user) + pinned_target.loc = user.loc + if(ishuman(user)) + if(!user.get_active_hand()) + user.put_in_hands(pinned_target) to_chat(user, "You take the target out of the stake.") + else + pinned_target.loc = get_turf(user) + to_chat(user, "You take the target out of the stake.") - pinned_target = null + pinned_target = null diff --git a/code/game/verbs/advanced_who.dm b/code/game/verbs/advanced_who.dm index 9f067054f2..4498136b2b 100644 --- a/code/game/verbs/advanced_who.dm +++ b/code/game/verbs/advanced_who.dm @@ -7,24 +7,36 @@ var/list/Lines = list() - if(holder && (R_ADMIN & holder.rights || R_MOD & holder.rights)) + if(holder) for(var/client/C in GLOB.clients) - var/entry = "\t[C.key]" + var/entry = "[C.key]" if(C.holder && C.holder.fakekey) entry += " (as [C.holder.fakekey])" - entry += " - Playing as [C.mob.real_name]" - switch(C.mob.stat) - if(UNCONSCIOUS) - entry += " - Unconscious" - if(DEAD) - if(isobserver(C.mob)) - var/mob/observer/dead/O = C.mob - if(O.started_as_observer) - entry += " - Observing" - else - entry += " - DEAD" + + entry += "" + + if(C.mob.real_name) + switch(C.mob.stat) + if(UNCONSCIOUS) + entry += "Unconscious" // these are literally all spans so I can apply .inverted to them because black on dark grey isn't legible + + if(DEAD) + if(isobserver(C.mob)) + var/mob/observer/dead/O = C.mob + if(O.started_as_observer) + entry += "Observing" + else + entry += "Died" + else - entry += " - DEAD" + entry += "Playing" + + entry += " as [C.mob.real_name]" + + else if(isnewplayer(C.mob)) + entry += "In lobby" + + entry += "" var/age if(isnum(C.player_age)) @@ -33,14 +45,20 @@ age = 0 if(age <= 1) - age = "[age]" + age = "[age]" else if(age < 10) - age = "[age]" + age = "[age]" - entry += " - [age]" + entry += "Age: [age]" + entry += "" if(is_special_character(C.mob)) - entry += " - Antagonist" + if(C.mob?.mind?.special_role) + entry += "[C.mob.mind.special_role]" + else + entry += "Antagonist" + + entry += "" if(C.is_afk()) var/seconds = C.last_activity_seconds() @@ -48,7 +66,9 @@ entry += "[round(seconds / 60)] minutes, " entry += "[seconds % 60] seconds)" + entry += "" entry += " (?)" + entry += "" Lines += entry else @@ -60,16 +80,17 @@ entry += "[C.key]" var/mob/observer/dead/O = C.mob if(isobserver(O)) - entry += " - Observing" + entry += " - Observing
" else if(istype(O,/mob/new_player)) - entry += " - In Lobby" + entry += " - In Lobby
" else - entry += " - Playing" + entry += " - Playing
" Lines += entry + msg += "" for(var/line in sortList(Lines)) - msg += "[line]\n" - + msg += "[line]" + msg += "
" msg += "Total Players: [length(Lines)]" - msg = "" + msg + "" + msg = "" + msg + "" to_chat(src, msg) \ No newline at end of file diff --git a/code/modules/admin/admin_tools.dm b/code/modules/admin/admin_tools.dm index 376aa2da44..8b4e1ae44c 100644 --- a/code/modules/admin/admin_tools.dm +++ b/code/modules/admin/admin_tools.dm @@ -9,18 +9,18 @@ if(M.mind) dat += "Current Antag?: [(M.mind.special_role)?"Yes":"No"]
" dat += "
Note: This is arranged from earliest to latest.

" - + if(!isemptylist(M.attack_log)) - dat += "
" + dat += "
" for(var/l in M.attack_log) dat += "[l]
" - + dat += "
" - + else dat += "No attack logs found for [M]." - + var/datum/browser/popup = new(usr, "admin_attack_log", "[src]", 650, 650, src) popup.set_content(jointext(dat,null)) popup.open() @@ -43,13 +43,13 @@ if(!isemptylist(M.dialogue_log)) dat += "
" - + for(var/d in M.dialogue_log) dat += "[d]
" - + dat += "
" else - dat += "No dialogue logs found for [M]." + dat += "No dialogue logs found for [M]." var/datum/browser/popup = new(usr, "admin_dialogue_log", "[src]", 650, 650, src) popup.set_content(jointext(dat,null)) popup.open() @@ -58,5 +58,8 @@ feedback_add_details("admin_verb","PDL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - + +// Used to get `atom/O as obj|mob|turf in view()` to match against strings containing apostrophes immediately after substrings that match to other objects. Somehow. - Ater +/proc/admin_atom_validate(atom/A) + return view() \ No newline at end of file diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index ace7d48e91..d85a88cbef 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -616,7 +616,7 @@ Traitors and the like can also be revived with the previous role mostly intact. message_admins("[key_name_admin(src)] has created a command report", 1) feedback_add_details("admin_verb","CCR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/cmd_admin_delete(atom/O as obj|mob|turf in view()) +/client/proc/cmd_admin_delete(atom/O as obj|mob|turf in admin_atom_validate(O)) // I don't understand precisely how this fixes the string matching against a substring, but it does - Ater set category = "Admin" set name = "Delete" diff --git a/code/modules/client/preference_setup/loadout/loadout_suit_vr.dm b/code/modules/client/preference_setup/loadout/loadout_suit_vr.dm index ecba5dd228..35ce55e1fa 100644 --- a/code/modules/client/preference_setup/loadout/loadout_suit_vr.dm +++ b/code/modules/client/preference_setup/loadout/loadout_suit_vr.dm @@ -38,3 +38,15 @@ display_name = "Colorful poncho" description = "A mexican looking poncho. It look like it fits wolf taurs as well." path = /obj/item/clothing/suit/poncho + +//Detective alternative +/datum/gear/uniform/detective_alt + display_name = "sleek modern coat, detective" + path = /obj/item/clothing/suit/storage/det_trench/alt + allowed_roles = list("Head of Security", "Detective") + +//Detective alternative +/datum/gear/uniform/detective_alt2 + display_name = "sleek modern coat (long), detective" + path = /obj/item/clothing/suit/storage/det_trench/alt2 + allowed_roles = list("Head of Security", "Detective") diff --git a/code/modules/client/preference_setup/loadout/loadout_uniform_vr.dm b/code/modules/client/preference_setup/loadout/loadout_uniform_vr.dm index dee35edaa3..a276be58cf 100644 --- a/code/modules/client/preference_setup/loadout/loadout_uniform_vr.dm +++ b/code/modules/client/preference_setup/loadout/loadout_uniform_vr.dm @@ -174,12 +174,6 @@ Swimsuits display_name = "Varmacorp nanovest" path = /obj/item/clothing/under/fluff/v_nanovest -//Detective alternative -/datum/gear/uniform/detective_alt - display_name = "sleek modern coat, detective" - path = /obj/item/clothing/under/detective_alt - allowed_roles = list("Head of Security", "Detective") - /* Qipao */ diff --git a/code/modules/client/preference_setup/occupation/occupation.dm b/code/modules/client/preference_setup/occupation/occupation.dm index d0ff9588d5..ab0f338747 100644 --- a/code/modules/client/preference_setup/occupation/occupation.dm +++ b/code/modules/client/preference_setup/occupation/occupation.dm @@ -146,7 +146,7 @@ //VOREStation Add if(!job.player_has_enough_playtime(user.client)) var/available_in_hours = job.available_in_playhours(user.client) - . += "[rank] \[IN [(available_in_hours)] DEPTHOURS]" + . += "[rank] \[IN [round(available_in_hours, 0.1)] DEPTHOURS]" continue //VOREStation Add End if(job.minimum_character_age && user.client && (user.client.prefs.age < job.minimum_character_age)) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 88ef31f884..0f5e85ec4b 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -59,7 +59,7 @@ user.recalculate_vis() //BS12: Species-restricted clothing check. -/obj/item/clothing/mob_can_equip(M as mob, slot, disable_warning = 0) +/obj/item/clothing/mob_can_equip(M as mob, slot, disable_warning = FALSE) //if we can't equip the item anyway, don't bother with species_restricted (cuts down on spam) if (!..()) @@ -337,7 +337,7 @@ return */ -/obj/item/clothing/gloves/mob_can_equip(mob/user, slot, disable_warning = 0) +/obj/item/clothing/gloves/mob_can_equip(mob/user, slot, disable_warning = FALSE) var/mob/living/carbon/human/H = user if(slot && slot == slot_gloves) diff --git a/code/modules/clothing/gloves/arm_guards.dm b/code/modules/clothing/gloves/arm_guards.dm index 791bb0a10b..6b0517642a 100644 --- a/code/modules/clothing/gloves/arm_guards.dm +++ b/code/modules/clothing/gloves/arm_guards.dm @@ -7,7 +7,7 @@ w_class = ITEMSIZE_NORMAL drop_sound = 'sound/items/drop/metalshield.ogg' -/obj/item/clothing/gloves/arm_guard/mob_can_equip(var/mob/living/carbon/human/H, slot, disable_warning = 0) +/obj/item/clothing/gloves/arm_guard/mob_can_equip(var/mob/living/carbon/human/H, slot, disable_warning = FALSE) if(..()) //This will only run if no other problems occured when equiping. if(H.wear_suit) if(H.wear_suit.body_parts_covered & ARMS) diff --git a/code/modules/clothing/gloves/gauntlets.dm b/code/modules/clothing/gloves/gauntlets.dm index eb5d05c909..efb25587a9 100644 --- a/code/modules/clothing/gloves/gauntlets.dm +++ b/code/modules/clothing/gloves/gauntlets.dm @@ -14,7 +14,7 @@ punch_force = 5 var/obj/item/clothing/gloves/gloves = null //Undergloves -/obj/item/clothing/gloves/gauntlets/mob_can_equip(mob/user, slot, disable_warning = 0) +/obj/item/clothing/gloves/gauntlets/mob_can_equip(mob/user, slot, disable_warning = FALSE) var/mob/living/carbon/human/H = user if(H.gloves) gloves = H.gloves diff --git a/code/modules/clothing/shoes/leg_guards.dm b/code/modules/clothing/shoes/leg_guards.dm index a6eefc1247..a4079087ab 100644 --- a/code/modules/clothing/shoes/leg_guards.dm +++ b/code/modules/clothing/shoes/leg_guards.dm @@ -9,7 +9,7 @@ can_hold_knife = TRUE drop_sound = 'sound/items/drop/boots.ogg' -/obj/item/clothing/shoes/leg_guard/mob_can_equip(var/mob/living/carbon/human/H, slot, disable_warning = 0) +/obj/item/clothing/shoes/leg_guard/mob_can_equip(var/mob/living/carbon/human/H, slot, disable_warning = FALSE) if(..()) //This will only run if no other problems occured when equiping. if(H.wear_suit) if(H.wear_suit.body_parts_covered & LEGS) diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index 392ec65ad8..1afd78dee0 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -93,6 +93,7 @@ // Wiring! How exciting. var/datum/wires/rig/wires var/datum/effect/effect/system/spark_spread/spark_system + var/datum/mini_hud/rig/minihud /obj/item/weapon/rig/examine() . = ..() @@ -188,6 +189,7 @@ START_PROCESSING(SSobj, src) else STOP_PROCESSING(SSobj, src) + QDEL_NULL(minihud) // Just in case we get removed some other way // If we've lost any parts, grab them back. var/mob/living/M @@ -363,6 +365,11 @@ // Success! canremove = seal_target + if(M.hud_used) + if(canremove) + QDEL_NULL(minihud) + else + minihud = new (M.hud_used, src) to_chat(M, "Your entire suit [canremove ? "loosens as the components relax" : "tightens around you as the components lock into place"].") M.client.screen -= booting_L qdel(booting_L) diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 3920ddd636..c41ff83d81 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -9,7 +9,7 @@ max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE siemens_coefficient = 0.6 -/obj/item/clothing/suit/mob_can_equip(var/mob/living/carbon/human/H, slot, disable_warning = 0) +/obj/item/clothing/suit/mob_can_equip(var/mob/living/carbon/human/H, slot, disable_warning = FALSE) if(..()) //This will only run if no other problems occured when equiping. for(var/obj/item/clothing/I in list(H.gloves, H.shoes)) if(I && (src.body_parts_covered & ARMS && I.body_parts_covered & ARMS) ) diff --git a/code/modules/clothing/suits/miscellaneous_vr.dm b/code/modules/clothing/suits/miscellaneous_vr.dm index 097407f0e8..dc181579b9 100644 --- a/code/modules/clothing/suits/miscellaneous_vr.dm +++ b/code/modules/clothing/suits/miscellaneous_vr.dm @@ -71,3 +71,18 @@ icon_state = "whitedress1" flags_inv = HIDESHOES +/obj/item/clothing/suit/storage/det_trench/alt + name = "sleek modern coat" + desc = "A sleek overcoat made of neo-laminated fabric. Has a reasonably sized pocket on the inside." + icon = 'icons/obj/clothing/suits_vr.dmi' + icon_override = 'icons/mob/suit_vr.dmi' + icon_state = "cyberpunksleek" + item_state = "cyberpunksleek" + +/obj/item/clothing/suit/storage/det_trench/alt2 + name = "sleek modern coat (long)" + desc = "A sleek long overcoat made of neo-laminated fabric. Has a reasonably sized pocket on the inside." + icon = 'icons/obj/clothing/suits_vr.dmi' + icon_override = 'icons/mob/suit_vr.dmi' + icon_state = "cyberpunksleek_long" + item_state = "cyberpunksleek_long" diff --git a/code/modules/clothing/under/jobs/security_vr.dm b/code/modules/clothing/under/jobs/security_vr.dm index 72d4ebfb45..e69de29bb2 100644 --- a/code/modules/clothing/under/jobs/security_vr.dm +++ b/code/modules/clothing/under/jobs/security_vr.dm @@ -1,6 +0,0 @@ -/obj/item/clothing/under/detective_alt - desc = "sleek modern coat" - icon = 'icons/obj/clothing/uniforms_vr.dmi' - icon_override = 'icons/mob/uniform_vr.dmi' - icon_state = "cyberpunksleek" - item_state = "cyberpunksleek" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 0af9f90225..c08fb9b20e 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1658,7 +1658,7 @@ var/obj/item/organ/external/e = organs_by_name[name] if(!e) continue - if((e.status & ORGAN_BROKEN && (!e.splinted || (e.splinted && e.splinted in e.contents && prob(30))) || e.status & ORGAN_BLEEDING) && (getBruteLoss() + getFireLoss() >= 100)) + if((e.status & ORGAN_BROKEN && (!e.splinted || (e.splinted in e.contents && prob(30))) || e.status & ORGAN_BLEEDING) && (getBruteLoss() + getFireLoss() >= 100)) return 1 else return ..() diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index aeab794552..ed74c02828 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -8,7 +8,7 @@ Returns standard 0 if fail */ -/mob/living/proc/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/soaked = 0, var/used_weapon = null, var/sharp = 0, var/edge = 0) +/mob/living/proc/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/soaked = 0, var/used_weapon = null, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null) if(Debug2) to_world_log("## DEBUG: apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked].") if(!damage || (blocked >= 100)) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 2fdfcf4c56..7b425a18ec 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -154,6 +154,9 @@ /mob/living/proc/handle_confused() if(confused) AdjustConfused(-1) + throw_alert("confused", /obj/screen/alert/confused) + else + clear_alert("confused") return confused /mob/living/proc/handle_disabilities() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 316bb2be88..61d937644f 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -785,6 +785,8 @@ default behaviour is: to_chat(usr, "OOC Metadata is not supported by this server!") //VOREStation Edit End - Making it so SSD people have prefs with fallback to original style. + return + // Almost all of this handles pulling movables behind us /mob/living/Move(atom/newloc, direct, movetime) if(buckled && buckled.loc != newloc) //not updating position @@ -797,9 +799,8 @@ default behaviour is: // Prior to our move it's already too far away if(pullee && get_dist(src, pullee) > 1) stop_pulling() - // Shenanigans! + // Shenanigans! Pullee closed into locker for eg. if(pullee && !isturf(pullee.loc) && pullee.loc != loc) - log_debug("[src]'s pull on [pullee] was broken despite [pullee] being in [pullee.loc]. Pull stopped manually.") stop_pulling() // Can't pull with no hands if(restrained()) @@ -1235,7 +1236,7 @@ default behaviour is: //actually throw it! src.visible_message("[src] has thrown [item].") - if((istype(src.loc, /turf/space)) || (src.lastarea?.has_gravity == 0)) + if((isspace(src.loc)) || (src.lastarea?.has_gravity == 0)) src.inertia_dir = get_dir(target, src) step(src, inertia_dir) diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index 8256fe29a0..9407a7cb18 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -8,7 +8,10 @@ return !P.can_hit_target(src, P.permutated, src == P.original, TRUE) return (!mover.density || !density || lying) -/mob/living/SelfMove(turf/n, direct) +/mob/CanZASPass(turf/T, is_zone) + return ATMOS_PASS_YES + +/mob/living/SelfMove(turf/n, direct, movetime) // If on walk intent, don't willingly step into hazardous tiles. // Unless the walker is confused. if(m_intent == "walk" && confused <= 0) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 61f0be1a95..22707c6dbb 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -483,6 +483,19 @@ var/list/ai_verbs_default = list( else to_chat(src, "System error. Cannot locate [html_decode(href_list["trackname"])].") return + + if(href_list["trackbot"]) + var/mob/living/bot/target = locate(href_list["trackbot"]) in mob_list + if(target) + ai_actual_track(target) + else + to_chat(src, "Target is not on or near any active cameras on the station.") + return + + if(href_list["open"]) + var/mob/target = locate(href_list["open"]) in mob_list + if(target) + open_nearest_door(target) return @@ -825,6 +838,39 @@ var/list/ai_verbs_default = list( /mob/living/silicon/ai/proc/is_in_chassis() return istype(loc, /turf) +/mob/living/silicon/ai/proc/open_nearest_door(mob/living/target) // Rykka ports AI opening doors + if(!istype(target)) + return + + if(target && ai_actual_track(target)) + var/obj/machinery/door/airlock/A = null + + var/dist = -1 + for(var/obj/machinery/door/airlock/D in range(3, target)) + if(!D.density) + continue + + var/curr_dist = get_dist(D, target) + + if(dist < 0) + dist = curr_dist + A = D + else if(dist > curr_dist) + dist = curr_dist + A = D + + if(istype(A)) + switch(alert(src, "Do you want to open \the [A] for [target]?", "Doorknob_v2a.exe", "Yes", "No")) + if("Yes") + A.AIShiftClick() + to_chat(src, "You open \the [A] for [target].") + else + to_chat(src, "You deny the request.") + else + to_chat(src, "Unable to locate an airlock near [target].") + + else + to_chat(src, "Target is not on or near any active cameras on the station.") /mob/living/silicon/ai/ex_act(var/severity) if(severity == 1.0) @@ -906,15 +952,20 @@ var/list/ai_verbs_default = list( jobname = "Unknown" var/track = "" - if(changed_voice) - if(impersonating) + if(changed_voice) // They have a fake name + if(impersonating) // And we found a mob with that name above, track them instead track = "[speaker_name] ([jobname])" - else + track += "\[OPEN\]" // Rykka ports AI opening doors + else // We couldn't find a mob with their fake name, don't track at all track = "[speaker_name] ([jobname])" - else - track = "[speaker_name] ([jobname])" + else // Not faking their name + if(istype(speaker, /mob/living/bot)) // It's a bot, and no fake name! (That'd be kinda weird.) :p + track = "[speaker_name] ([jobname])" + else // It's not a bot, and no fake name! + track = "[speaker_name] ([jobname])" + track += "\[OPEN\]" // Rykka ports AI opening doors - return track + return track // Feed variable back to AI /mob/living/silicon/ai/proc/relay_speech(mob/living/M, list/message_pieces, verb) var/message = combine_message(message_pieces, verb, M) diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm index 4b1c533f21..fe05775c51 100644 --- a/code/modules/mob/living/silicon/robot/robot_movement.dm +++ b/code/modules/mob/living/silicon/robot/robot_movement.dm @@ -25,7 +25,7 @@ . += ..() // NEW: Use power while moving. -/mob/living/silicon/robot/SelfMove(turf/n, direct) +/mob/living/silicon/robot/SelfMove(turf/n, direct, movetime) if (!is_component_functioning("actuator")) return 0 diff --git a/code/modules/mob/living/simple_mob/simple_mob.dm b/code/modules/mob/living/simple_mob/simple_mob.dm index 82d16472c1..6a750ea518 100644 --- a/code/modules/mob/living/simple_mob/simple_mob.dm +++ b/code/modules/mob/living/simple_mob/simple_mob.dm @@ -193,7 +193,7 @@ . = ..() to_chat(src,"You are \the [src]. [player_msg]") -/mob/living/simple_mob/SelfMove(turf/n, direct) +/mob/living/simple_mob/SelfMove(turf/n, direct, movetime) var/turf/old_turf = get_turf(src) var/old_dir = dir . = ..() diff --git a/code/modules/mob/living/simple_mob/subtypes/mechanical/drones/mining_drone.dm b/code/modules/mob/living/simple_mob/subtypes/mechanical/drones/mining_drone.dm index 5c6660e67c..2e014482f2 100644 --- a/code/modules/mob/living/simple_mob/subtypes/mechanical/drones/mining_drone.dm +++ b/code/modules/mob/living/simple_mob/subtypes/mechanical/drones/mining_drone.dm @@ -32,7 +32,7 @@ movement_cooldown = 5 hovering = TRUE - base_attack_cooldown = 5 + base_attack_cooldown = 2.5 SECONDS projectiletype = /obj/item/projectile/energy/excavate projectilesound = 'sound/weapons/pulse3.ogg' diff --git a/code/modules/mob/new_player/sprite_accessories_vr.dm b/code/modules/mob/new_player/sprite_accessories_vr.dm index c720b96b6d..749e35ed35 100644 --- a/code/modules/mob/new_player/sprite_accessories_vr.dm +++ b/code/modules/mob/new_player/sprite_accessories_vr.dm @@ -1154,3 +1154,15 @@ icon_state = "claws" color_blend_mode = ICON_MULTIPLY body_parts = list(BP_L_HAND,BP_R_HAND) + + equine_snout //Why the long face? Works best with sergal bodytype. + name = "Equine Snout" + icon_state = "donkey" + color_blend_mode = ICON_MULTIPLY + body_parts = list(BP_HEAD) + + equine_nose + name = "Equine Nose" + icon_state = "dnose" + color_blend_mode = ICON_MULTIPLY + body_parts = list(BP_HEAD) diff --git a/code/modules/paperwork/faxmachine.dm b/code/modules/paperwork/faxmachine.dm index 15b597275f..a850cf9989 100644 --- a/code/modules/paperwork/faxmachine.dm +++ b/code/modules/paperwork/faxmachine.dm @@ -120,17 +120,7 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins SSnanoui.update_uis(src) /obj/machinery/photocopier/faxmachine/attackby(obj/item/O as obj, mob/user as mob) - if(istype(O, /obj/item/weapon/paper) || istype(O, /obj/item/weapon/photo) || istype(O, /obj/item/weapon/paper_bundle)) - if(!copyitem) - user.drop_item() - copyitem = O - O.loc = src - to_chat(user, "You insert \the [O] into \the [src].") - playsound(loc, "sound/machines/click.ogg", 100, 1) - flick(insert_anim, src) - else - to_chat(user, "There is already something in \the [src].") - else if(istype(O, /obj/item/device/multitool) && panel_open) + if(O.is_multitool() && panel_open) var/input = sanitize(input(usr, "What Department ID would you like to give this fax machine?", "Multitool-Fax Machine Interface", department)) if(!input) to_chat(usr, "No input found. Please hang up and try your call again.") @@ -138,17 +128,8 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins department = input if( !(("[department]" in alldepartments) || ("[department]" in admin_departments)) && !(department == "Unknown")) alldepartments |= department - else if(O.is_wrench()) - playsound(loc, O.usesound, 50, 1) - anchored = !anchored - to_chat(user, "You [anchored ? "wrench" : "unwrench"] \the [src].") - else if(default_deconstruction_screwdriver(user, O)) - return - else if(default_deconstruction_crowbar(user, O)) - return - - return + return ..() /obj/machinery/photocopier/faxmachine/proc/sendfax(var/destination) if(stat & (BROKEN|NOPOWER)) diff --git a/code/modules/power/smes_construction.dm b/code/modules/power/smes_construction.dm index 558e879a87..a43bf079c8 100644 --- a/code/modules/power/smes_construction.dm +++ b/code/modules/power/smes_construction.dm @@ -58,7 +58,7 @@ // Pre-installed and pre-charged SMES hidden from the station, for use in submaps. /obj/machinery/power/smes/buildable/point_of_interest/Initialize() . = ..() - charge = 1e7 // Should be enough for an individual POI. + charge = capacity // Should be enough for an individual POI. RCon = FALSE input_level = input_level_max output_level = output_level_max diff --git a/code/modules/vchat/css/ss13styles.css b/code/modules/vchat/css/ss13styles.css index d4676f123e..873cf0d61b 100644 --- a/code/modules/vchat/css/ss13styles.css +++ b/code/modules/vchat/css/ss13styles.css @@ -165,7 +165,7 @@ h1.alert, h2.alert {color: #000000;} .bug {color: #9e9e39;} .vox {color: #AA00AA;} .promethean {color: #5A5A5A; font-family:"Comic Sans MS","Comic Sans",cursive;} -.inverted .promethean {color: #A5A5A5; font-family:"Comic Sans MS","Comic Sans",cursive;} +.inverted .promethean {color: #A5A5A5; font-family:"Comic Sans MS","Comic Sans",cursive;} .zaddat {color: #941C1C;} .rough {font-family: "Trebuchet MS", cursive, sans-serif;} .say_quote {font-family: Georgia, Verdana, sans-serif;} @@ -176,6 +176,21 @@ h1.alert, h2.alert {color: #000000;} .wingdings {font-family: Wingdings, Webdings} /* YW Edit End */ +.black {color: #000000;} +.darkgray {color: #808080;} +.gray {color: #A9A9A9;} +.red {color: #FF0000;} +.orange {color: #FF8C00;} +.blue {color: #0000FF;} +.green {color: #00DD00;} +.inverted .black {color: #606060;} +.inverted .darkgray {color: #808080;} +.inverted .gray {color: #A9A9A9;} +.inverted .red {color: #FF4444;} +.inverted .orange {color: #FF8C00;} +.inverted .blue {color: #6666FF;} +.inverted .green {color: #44FF44;} + /*BIG IMG.icon {width: 32px; height: 32px;}*/ img.icon {vertical-align: middle; max-height: 1em;} img.icon.bigicon {max-height: 32px;} diff --git a/code/modules/vehicles/bike.dm b/code/modules/vehicles/bike.dm index 1d4cb49a3b..fe059b9e07 100644 --- a/code/modules/vehicles/bike.dm +++ b/code/modules/vehicles/bike.dm @@ -1,6 +1,7 @@ /obj/vehicle/bike name = "space-bike" desc = "Space wheelies! Woo!" + description_info = "Use ctrl-click to quickly toggle the engine if you're adjacent (only when vehicle is stationary). Alt-click will similarly toggle the kickstand." icon = 'icons/obj/bike.dmi' icon_state = "bike_off" dir = SOUTH diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm index 939c72110e..94437458cf 100644 --- a/code/modules/vehicles/cargo_train.dm +++ b/code/modules/vehicles/cargo_train.dm @@ -2,6 +2,7 @@ name = "cargo train tug" desc = "A ridable electric car designed for pulling cargo trolleys." icon = 'icons/obj/vehicles_vr.dmi' //VOREStation Edit + description_info = "Use ctrl-click to quickly toggle the engine if you're adjacent (only when vehicle is stationary). Alt-click will grab the keys, if present." icon_state = "cargo_engine" on = 0 powered = 1 diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index ed7bdc9a2a..e43228c4be 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -42,8 +42,6 @@ var/load_offset_y = 0 //pixel_y offset for item overlay var/mob_offset_y = 0 //pixel_y offset for mob overlay - //var/datum/riding/riding_datum = null //VOREStation Edit - Moved to movables. - //------------------------------------------- // Standard procs //------------------------------------------- diff --git a/code/modules/vore/appearance/sprite_accessories_vr.dm b/code/modules/vore/appearance/sprite_accessories_vr.dm index 4f9cceb981..9cc9519bfb 100644 --- a/code/modules/vore/appearance/sprite_accessories_vr.dm +++ b/code/modules/vore/appearance/sprite_accessories_vr.dm @@ -331,6 +331,14 @@ color_blend_mode = ICON_MULTIPLY extra_overlay = "otie-inner" +/datum/sprite_accessory/ears/donkey + name = "donkey, colorable" + desc = "" + icon_state = "donkey" + do_colouration = 1 + color_blend_mode = ICON_MULTIPLY + extra_overlay = "otie-inner" + /datum/sprite_accessory/ears/zears name = "jagged ears" desc = "" diff --git a/code/stylesheet.dm b/code/stylesheet.dm index 22bee5dda4..504472e334 100644 --- a/code/stylesheet.dm +++ b/code/stylesheet.dm @@ -122,4 +122,13 @@ BIG IMG.icon {width: 32px; height: 32px;} .debug_debug {color:#0000FF;} .debug_trace {color:#888888;} +.black {color: #000000;} +.darkgray {color: #808080;} +.gray {color: #A9A9A9;} +.red {color: #FF0000;} +.orange {color: #FF8C00;} +.blue {color: #0000FF;} +.green {color: #00DD00;} + + "} diff --git a/html/changelog.html b/html/changelog.html index 6045c2ca04..cc0d540a75 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,39 @@ -->
+

13 May 2020

+

Atermonera updated:

+ +

Layne updated:

+ +

Mechoid updated:

+ +

atlantiscze updated:

+ +

29 April 2020

Leshana updated: