mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-20 11:34:19 +01:00
Merge branch 'master' of https://github.com/Fordoxia/CRUNCHParadise
This commit is contained in:
+1
-1
@@ -24,8 +24,8 @@ _build_dependencies.sh @AffectedArc07
|
||||
|
||||
# Executables that need to be security-cleared
|
||||
dreamchecker.exe @AffectedArc07
|
||||
milla.dll @AffectedArc07
|
||||
rust_g.dll @AffectedArc07
|
||||
librust_g.so @AffectedArc07
|
||||
|
||||
### S34NW
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
name: Build MILLA
|
||||
on:
|
||||
issue_comment:
|
||||
types: created
|
||||
|
||||
jobs:
|
||||
build-milla:
|
||||
if: |
|
||||
github.event.issue.pull_request &&
|
||||
(github.event.comment.body == '!build_milla') &&
|
||||
((github.event.sender.id == github.event.issue.user.id) ||
|
||||
(github.event.comment.author_association == 'COLLABORATOR') ||
|
||||
(github.event.comment.author_association == 'MEMBER') ||
|
||||
(github.event.comment.author_association == 'OWNER'))
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Like the comment
|
||||
env:
|
||||
BASE_REPOSITORY: ${{ github.repository }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh api \
|
||||
--method POST \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
/repos/$BASE_REPOSITORY/issues/comments/${{ github.event.comment.id }}/reactions \
|
||||
-f content='+1'
|
||||
|
||||
- name: PR Data
|
||||
run: |
|
||||
pr_json=$(curl -L -s --fail-with-body -H "Authorization: token ${{ github.token }}" ${{ github.event.issue.pull_request.url }})
|
||||
if [ `jq -r '.maintainer_can_modify' <<<$pr_json` == "false" ] ; then
|
||||
gh pr comment ${{ github.event.issue.html_url }} --body 'GitHub Actions can not push to the repository without "Allow edits and access to secrets by maintainers" checked.'
|
||||
echo "FAIL_NOTIFIED=true" >> "$GITHUB_ENV"
|
||||
exit 1
|
||||
fi
|
||||
echo "PR_REPO=`jq -r '.head.repo.full_name' <<<$pr_json`" >> $GITHUB_ENV
|
||||
echo "PR_BRANCH=`jq -r '.head.ref' <<<$pr_json`" >> $GITHUB_ENV
|
||||
echo "PR_HEAD_LABEL=`jq -r '.head.label' <<<$pr_json`" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ env.PR_REPO }}
|
||||
ref: ${{ env.PR_BRANCH }}
|
||||
token: ${{ github.token }}
|
||||
|
||||
- name: Build MILLA
|
||||
env:
|
||||
BASE_BRANCH: ${{ github.event.repository.default_branch }}
|
||||
BASE_REPOSITORY: ${{ github.repository }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
# Get the code.
|
||||
git config user.name paradisess13[bot]
|
||||
git config user.email "165046124+paradisess13[bot]@users.noreply.github.com"
|
||||
git pull origin "$PR_BRANCH" --depth=$((ahead_by + 1))
|
||||
git remote add upstream "https://github.com/$BASE_REPOSITORY.git"
|
||||
git fetch upstream "$BASE_BRANCH" --depth=$((behind_by + 1))
|
||||
cd milla
|
||||
|
||||
# Get dependencies.
|
||||
rustup target add i686-unknown-linux-gnu
|
||||
rustup target add i686-pc-windows-gnu
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-get update
|
||||
sudo apt-get install zlib1g-dev:i386 lib32gcc-11-dev mingw-w64 mingw-w64-i686-dev
|
||||
|
||||
# Build it.
|
||||
cargo build --release --target i686-unknown-linux-gnu
|
||||
cargo build --release --target i686-pc-windows-gnu
|
||||
|
||||
# Copy the built targets to their checked-in locations.
|
||||
cp target/i686-unknown-linux-gnu/release/libmilla.so ../tools/ci/libmilla_ci.so
|
||||
cp target/i686-pc-windows-gnu/release/milla.dll ../milla.dll
|
||||
|
||||
# Check if a workflow file would be modified by the merge (permissions prevent pushes if so)
|
||||
latest_workflow_commit=$(git log -n 1 --pretty=format:"%H" upstream/$BASE_BRANCH -- .github/workflows)
|
||||
if ! git branch --contains $latest_workflow_commit | grep -q "$(git rev-parse --abbrev-ref HEAD)"; then
|
||||
gh pr comment ${{ github.event.issue.html_url }} --body "GitHub Actions can not push to this branch as workflow files have been changed since your branch was last updated. Please update your branch past https://github.com/$BASE_REPOSITORY/commit/$latest_workflow_commit before using this command again."
|
||||
echo "FAIL_NOTIFIED=true" >> "$GITHUB_ENV"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git commit -a -m "Build MILLA" --allow-empty
|
||||
git push origin
|
||||
|
||||
- name: Notify Failure
|
||||
if: failure() && env.FAIL_NOTIFIED != 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh pr comment ${{ github.event.issue.html_url }} -b 'Building MILLA failed, see the action run log for details: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||
@@ -109,6 +109,16 @@ jobs:
|
||||
git merge FETCH_HEAD
|
||||
git push origin
|
||||
|
||||
- name: Rebuild TGUI
|
||||
run: |
|
||||
if git diff-tree --name-only -r $(git rev-parse HEAD~2) | grep "tgui/public/"
|
||||
bash tgui/bin/tgui
|
||||
git commit -m "Rebuild TGUI"
|
||||
git push origin
|
||||
else
|
||||
echo "No changes to rebuild TGUI"
|
||||
fi
|
||||
|
||||
- name: Notify Failure
|
||||
if: failure() && env.FAIL_NOTIFIED != 'true'
|
||||
run: |
|
||||
|
||||
@@ -171,9 +171,11 @@
|
||||
#define HUD_STYLE_STANDARD 1
|
||||
#define HUD_STYLE_REDUCED 2
|
||||
#define HUD_STYLE_NOHUD 3
|
||||
#define HUD_STYLE_ACTIONHUD 4
|
||||
|
||||
|
||||
#define HUD_VERSIONS 3 //used in show_hud()
|
||||
#define HUD_VERSIONS 4 //used in show_hud()
|
||||
//1 = standard hud
|
||||
//2 = reduced hud (just hands and intent switcher)
|
||||
//3 = no hud (for screenshots)
|
||||
//4 = Only action buttons (so vampires / changelings and such can use abilities while asleep)
|
||||
|
||||
@@ -1,21 +1,30 @@
|
||||
/mob/proc/overlay_fullscreen(category, type, severity)
|
||||
/mob/proc/overlay_fullscreen(category, type, severity, animated = 0)
|
||||
var/atom/movable/screen/fullscreen/screen = screens[category]
|
||||
var/is_centered = istype(screen, /atom/movable/screen/fullscreen/center)
|
||||
|
||||
if(!screen || screen.type != type)
|
||||
// needs to be recreated
|
||||
clear_fullscreen(category, FALSE)
|
||||
screens[category] = screen = new type()
|
||||
else if((!severity || severity == screen.severity) && (!client || screen.screen_loc != "CENTER-7,CENTER-7" || screen.view == client.view))
|
||||
else if((!severity || severity == screen.severity) && (!is_centered && (!client || screen.screen_loc != "CENTER-7,CENTER-7" || screen.view == client.view)))
|
||||
// doesn't need to be updated
|
||||
return screen
|
||||
|
||||
screen.icon_state = "[initial(screen.icon_state)][severity]"
|
||||
screen.severity = severity
|
||||
if(client && screen.should_show_to(src))
|
||||
screen.update_for_view(client.view)
|
||||
if(animated)
|
||||
INVOKE_ASYNC(src, PROC_REF(apply_screen_animation), animated, screen)
|
||||
if(!is_centered)
|
||||
screen.update_for_view(client.view)
|
||||
client.screen += screen
|
||||
|
||||
return screen
|
||||
|
||||
/mob/proc/apply_screen_animation(animated = 0, atom/movable/screen/fullscreen/screen)
|
||||
screen.alpha = 0
|
||||
animate(screen, alpha = 255, time = animated)
|
||||
|
||||
/mob/proc/clear_fullscreen(category, animated = 10)
|
||||
var/atom/movable/screen/fullscreen/screen = screens[category]
|
||||
if(!screen)
|
||||
@@ -30,10 +39,11 @@
|
||||
if(client)
|
||||
client.screen -= screen
|
||||
qdel(screen)
|
||||
else
|
||||
if(client)
|
||||
client.screen -= screen
|
||||
qdel(screen)
|
||||
return
|
||||
|
||||
if(client)
|
||||
client.screen -= screen
|
||||
qdel(screen)
|
||||
|
||||
/mob/proc/clear_fullscreens()
|
||||
for(var/category in screens)
|
||||
@@ -46,28 +56,21 @@
|
||||
for(var/category in screens)
|
||||
screen = screens[category]
|
||||
if(screen.should_show_to(mymob))
|
||||
screen.update_for_view(mymob.client.view)
|
||||
mymob.client.screen |= screen
|
||||
else
|
||||
mymob.client.screen -= screen
|
||||
continue
|
||||
mymob.client.screen -= screen
|
||||
|
||||
/atom/movable/screen/fullscreen
|
||||
icon = 'icons/mob/screen_full.dmi'
|
||||
icon_state = "default"
|
||||
screen_loc = "CENTER-7,CENTER-7"
|
||||
var/view
|
||||
layer = FULLSCREEN_LAYER
|
||||
plane = FULLSCREEN_PLANE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
var/view = 7
|
||||
var/severity = 0
|
||||
var/show_when_dead = FALSE
|
||||
|
||||
/atom/movable/screen/fullscreen/proc/update_for_view(client_view)
|
||||
if(screen_loc == "CENTER-7,CENTER-7" && view != client_view)
|
||||
var/list/actualview = getviewsize(client_view)
|
||||
view = client_view
|
||||
transform = matrix(actualview[1]/FULLSCREEN_OVERLAY_RESOLUTION_X, 0, 0, 0, actualview[2]/FULLSCREEN_OVERLAY_RESOLUTION_Y, 0)
|
||||
|
||||
/atom/movable/screen/fullscreen/proc/should_show_to(mob/mymob)
|
||||
if(!show_when_dead && mymob.stat == DEAD)
|
||||
return FALSE
|
||||
@@ -77,51 +80,62 @@
|
||||
severity = 0
|
||||
return ..()
|
||||
|
||||
/atom/movable/screen/fullscreen/brute
|
||||
/// Stretch version is suitable for images that stick to screen edges, as they scale with user screen size
|
||||
/// For centrally located screen objects, use /atom/movable/screen/fullscreen/center
|
||||
/atom/movable/screen/fullscreen/stretch
|
||||
view = 7
|
||||
|
||||
/atom/movable/screen/fullscreen/proc/update_for_view(client_view)
|
||||
if(screen_loc == "CENTER-7,CENTER-7" && view != client_view)
|
||||
var/list/actualview = getviewsize(client_view)
|
||||
view = client_view
|
||||
transform = matrix(actualview[1]/FULLSCREEN_OVERLAY_RESOLUTION_X, 0, 0, 0, actualview[2]/FULLSCREEN_OVERLAY_RESOLUTION_Y, 0)
|
||||
|
||||
/atom/movable/screen/fullscreen/stretch/brute
|
||||
icon_state = "brutedamageoverlay"
|
||||
layer = UI_DAMAGE_LAYER
|
||||
|
||||
/atom/movable/screen/fullscreen/oxy
|
||||
/atom/movable/screen/fullscreen/stretch/oxy
|
||||
icon_state = "oxydamageoverlay"
|
||||
layer = UI_DAMAGE_LAYER
|
||||
|
||||
/atom/movable/screen/fullscreen/crit
|
||||
/atom/movable/screen/fullscreen/stretch/crit
|
||||
icon_state = "passage"
|
||||
layer = CRIT_LAYER
|
||||
|
||||
/atom/movable/screen/fullscreen/blind
|
||||
/atom/movable/screen/fullscreen/stretch/blind
|
||||
icon_state = "blackimageoverlay"
|
||||
layer = BLIND_LAYER
|
||||
|
||||
/atom/movable/screen/fullscreen/impaired
|
||||
/atom/movable/screen/fullscreen/stretch/impaired
|
||||
icon_state = "impairedoverlay"
|
||||
|
||||
/atom/movable/screen/fullscreen/payback
|
||||
/atom/movable/screen/fullscreen/stretch/payback
|
||||
icon = 'icons/mob/screen_payback.dmi'
|
||||
icon_state = "payback"
|
||||
show_when_dead = TRUE
|
||||
|
||||
/atom/movable/screen/fullscreen/fog
|
||||
/atom/movable/screen/fullscreen/stretch/fog
|
||||
icon = 'icons/mob/screen_fog.dmi'
|
||||
icon_state = "fog"
|
||||
color = "#FF0000"
|
||||
|
||||
/atom/movable/screen/fullscreen/flash
|
||||
/atom/movable/screen/fullscreen/stretch/flash
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "flash"
|
||||
|
||||
/atom/movable/screen/fullscreen/flash/noise
|
||||
/atom/movable/screen/fullscreen/stretch/flash/noise
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "noise"
|
||||
|
||||
/atom/movable/screen/fullscreen/high
|
||||
/atom/movable/screen/fullscreen/stretch/high
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "druggy"
|
||||
|
||||
/atom/movable/screen/fullscreen/lighting_backdrop
|
||||
/atom/movable/screen/fullscreen/stretch/lighting_backdrop
|
||||
icon = 'icons/mob/screen_gen.dmi'
|
||||
icon_state = "flash"
|
||||
transform = matrix(200, 0, 0, 0, 200, 0)
|
||||
@@ -130,18 +144,18 @@
|
||||
show_when_dead = TRUE
|
||||
|
||||
//Provides darkness to the back of the lighting plane
|
||||
/atom/movable/screen/fullscreen/lighting_backdrop/lit
|
||||
/atom/movable/screen/fullscreen/stretch/lighting_backdrop/lit
|
||||
invisibility = INVISIBILITY_LIGHTING
|
||||
layer = BACKGROUND_LAYER+21
|
||||
color = "#000"
|
||||
show_when_dead = TRUE
|
||||
|
||||
//Provides whiteness in case you don't see lights so everything is still visible
|
||||
/atom/movable/screen/fullscreen/lighting_backdrop/unlit
|
||||
/atom/movable/screen/fullscreen/stretch/lighting_backdrop/unlit
|
||||
layer = BACKGROUND_LAYER+20
|
||||
show_when_dead = TRUE
|
||||
|
||||
/atom/movable/screen/fullscreen/see_through_darkness
|
||||
/atom/movable/screen/fullscreen/stretch/see_through_darkness
|
||||
icon_state = "nightvision"
|
||||
plane = LIGHTING_PLANE
|
||||
layer = LIGHTING_LAYER
|
||||
@@ -149,7 +163,7 @@
|
||||
show_when_dead = TRUE
|
||||
|
||||
/// An effect which tracks the cursor's location on the screen
|
||||
/atom/movable/screen/fullscreen/cursor_catcher
|
||||
/atom/movable/screen/fullscreen/stretch/cursor_catcher
|
||||
icon_state = "fullscreen_blocker" // Fullscreen semi transparent icon
|
||||
plane = HUD_PLANE
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
@@ -167,14 +181,14 @@
|
||||
var/mouse_params
|
||||
|
||||
/// Links this up with a mob
|
||||
/atom/movable/screen/fullscreen/cursor_catcher/proc/assign_to_mob(mob/owner)
|
||||
/atom/movable/screen/fullscreen/stretch/cursor_catcher/proc/assign_to_mob(mob/owner)
|
||||
src.owner = owner
|
||||
view_list = getviewsize(owner.client.view)
|
||||
RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
|
||||
calculate_params()
|
||||
|
||||
/// Update when the mob we're assigned to has moved
|
||||
/atom/movable/screen/fullscreen/cursor_catcher/proc/on_move(atom/source, atom/oldloc, dir, forced)
|
||||
/atom/movable/screen/fullscreen/stretch/cursor_catcher/proc/on_move(atom/source, atom/oldloc, dir, forced)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!given_turf)
|
||||
@@ -183,19 +197,18 @@
|
||||
var/y_offset = source.loc.y - oldloc.y
|
||||
given_turf = locate(given_turf.x + x_offset, given_turf.y + y_offset, given_turf.z)
|
||||
|
||||
|
||||
/atom/movable/screen/fullscreen/cursor_catcher/MouseEntered(location, control, params)
|
||||
/atom/movable/screen/fullscreen/stretch/cursor_catcher/MouseEntered(location, control, params)
|
||||
. = ..()
|
||||
MouseMove(location, control, params)
|
||||
if(usr == owner)
|
||||
calculate_params()
|
||||
|
||||
/atom/movable/screen/fullscreen/cursor_catcher/MouseMove(location, control, params)
|
||||
/atom/movable/screen/fullscreen/stretch/cursor_catcher/MouseMove(location, control, params)
|
||||
if(usr != owner)
|
||||
return
|
||||
mouse_params = params
|
||||
|
||||
/atom/movable/screen/fullscreen/cursor_catcher/proc/calculate_params()
|
||||
/atom/movable/screen/fullscreen/stretch/cursor_catcher/proc/calculate_params()
|
||||
var/list/modifiers = params2list(mouse_params)
|
||||
var/icon_x = text2num(LAZYACCESS(modifiers, "vis-x"))
|
||||
if(isnull(icon_x))
|
||||
@@ -209,6 +222,28 @@
|
||||
given_x = round(icon_x - world.icon_size * our_x, 1)
|
||||
given_y = round(icon_y - world.icon_size * our_y, 1)
|
||||
|
||||
/// Centered fullscreen atoms
|
||||
/// These are used to center a widescreen image so it scales properly across screen sizes, not suitable for screen images that eminate from the edge of the screen
|
||||
/atom/movable/screen/fullscreen/center
|
||||
appearance_flags = TILE_BOUND
|
||||
|
||||
/atom/movable/screen/fullscreen/center/Initialize(mapload)
|
||||
. = ..()
|
||||
var/icon/I = new(icon)
|
||||
var/x_offset = -((I.Width() - world.icon_size) / 2)
|
||||
var/y_offset = -((I.Height() - world.icon_size) / 2)
|
||||
qdel(I)
|
||||
screen_loc = "CENTER:[x_offset],CENTER:[y_offset]"
|
||||
|
||||
/atom/movable/screen/fullscreen/center/blind/sleeping
|
||||
icon = 'icons/mob/screen_sleeping.dmi'
|
||||
icon_state = "sleepblind"
|
||||
layer = BLIND_LAYER
|
||||
|
||||
/atom/movable/screen/fullscreen/center/blind/disky
|
||||
icon = 'icons/mob/screen_tight.dmi'
|
||||
icon_state = "disky"
|
||||
layer = BLIND_LAYER
|
||||
|
||||
#undef FULLSCREEN_LAYER
|
||||
#undef BLIND_LAYER
|
||||
|
||||
@@ -210,6 +210,15 @@
|
||||
if(length(infodisplay))
|
||||
mymob.client.screen -= infodisplay
|
||||
|
||||
if(HUD_STYLE_ACTIONHUD) //No HUD
|
||||
hud_shown = TRUE //Governs behavior of other procs
|
||||
if(static_inventory.len)
|
||||
mymob.client.screen -= static_inventory
|
||||
if(toggleable_inventory.len)
|
||||
mymob.client.screen -= toggleable_inventory
|
||||
if(infodisplay.len)
|
||||
mymob.client.screen -= infodisplay
|
||||
|
||||
hud_version = display_hud_version
|
||||
persistent_inventory_update()
|
||||
mymob.update_action_buttons(1)
|
||||
@@ -244,6 +253,9 @@
|
||||
return
|
||||
|
||||
/mob/proc/hide_hud()
|
||||
if(HAS_TRAIT(src, TRAIT_KNOCKEDOUT) && isliving(src))
|
||||
to_chat(src, "<span class='warning'>You can not change huds while asleep!</span>")
|
||||
return
|
||||
if(hud_used && client)
|
||||
hud_used.show_hud() //Shows the next hud preset
|
||||
to_chat(src, "<span class='info'>Switched HUD mode. Press the key you just pressed to toggle the HUD mode again.</span>")
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
/datum/hud/human/New(mob/living/carbon/human/owner, ui_style = 'icons/mob/screen_white.dmi', ui_color = "#ffffff", ui_alpha = 255)
|
||||
..()
|
||||
owner.overlay_fullscreen("see_through_darkness", /atom/movable/screen/fullscreen/see_through_darkness)
|
||||
owner.overlay_fullscreen("see_through_darkness", /atom/movable/screen/fullscreen/stretch/see_through_darkness)
|
||||
|
||||
var/atom/movable/screen/using
|
||||
var/atom/movable/screen/inventory/inv_box
|
||||
@@ -393,7 +393,7 @@
|
||||
if(!mymob)
|
||||
return
|
||||
var/mob/living/carbon/human/H = mymob
|
||||
if(inventory_shown && hud_shown)
|
||||
if(inventory_shown && hud_version == HUD_STYLE_STANDARD)
|
||||
if(H.shoes)
|
||||
H.shoes.screen_loc = ui_shoes
|
||||
H.client.screen += H.shoes
|
||||
@@ -436,7 +436,7 @@
|
||||
if(!mymob)
|
||||
return
|
||||
var/mob/living/carbon/human/H = mymob
|
||||
if(hud_shown)
|
||||
if(hud_version == HUD_STYLE_STANDARD)
|
||||
if(H.s_store)
|
||||
H.s_store.screen_loc = ui_sstore1
|
||||
H.client.screen += H.s_store
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
static_inventory += using
|
||||
action_intent = using
|
||||
|
||||
user.overlay_fullscreen("see_through_darkness", /atom/movable/screen/fullscreen/see_through_darkness)
|
||||
user.overlay_fullscreen("see_through_darkness", /atom/movable/screen/fullscreen/stretch/see_through_darkness)
|
||||
|
||||
/datum/hud/corgi/New(mob/user)
|
||||
..()
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
|
||||
/atom/movable/screen/plane_master/lighting/backdrop(mob/mymob)
|
||||
. = ..()
|
||||
mymob.overlay_fullscreen("lighting_backdrop_lit", /atom/movable/screen/fullscreen/lighting_backdrop/lit)
|
||||
mymob.overlay_fullscreen("lighting_backdrop_unlit", /atom/movable/screen/fullscreen/lighting_backdrop/unlit)
|
||||
mymob.overlay_fullscreen("lighting_backdrop_lit", /atom/movable/screen/fullscreen/stretch/lighting_backdrop/lit)
|
||||
mymob.overlay_fullscreen("lighting_backdrop_unlit", /atom/movable/screen/fullscreen/stretch/lighting_backdrop/unlit)
|
||||
|
||||
/atom/movable/screen/plane_master/lighting/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
if(!R.module)
|
||||
return
|
||||
|
||||
if(R.shown_robot_modules && hud_shown)
|
||||
if(R.shown_robot_modules && hud_version == HUD_STYLE_STANDARD)
|
||||
//Modules display is shown
|
||||
R.client.screen += module_store_icon //"store" icon
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* return int The number of UIs updated.
|
||||
*/
|
||||
/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object)
|
||||
/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object, full_update = FALSE)
|
||||
var/count = 0
|
||||
var/key = "[src_object.UID()]"
|
||||
// No UIs opened for this src_object
|
||||
@@ -196,7 +196,10 @@ SUBSYSTEM_DEF(tgui)
|
||||
for(var/datum/tgui/ui in open_uis_by_src[key])
|
||||
// Check if UI is valid.
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user))
|
||||
ui.process(force = TRUE)
|
||||
if(full_update)
|
||||
ui.send_full_update(null, TRUE)
|
||||
else
|
||||
ui.process(force = TRUE)
|
||||
count++
|
||||
return count
|
||||
|
||||
|
||||
@@ -670,13 +670,13 @@
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/drill_payback/on_apply()
|
||||
owner.overlay_fullscreen("payback", /atom/movable/screen/fullscreen/payback, 0)
|
||||
owner.overlay_fullscreen("payback", /atom/movable/screen/fullscreen/stretch/payback, 0)
|
||||
addtimer(CALLBACK(src, PROC_REF(payback_phase_2)), 2.7 SECONDS)
|
||||
return TRUE
|
||||
|
||||
/datum/status_effect/drill_payback/proc/payback_phase_2()
|
||||
owner.clear_fullscreen("payback")
|
||||
owner.overlay_fullscreen("payback", /atom/movable/screen/fullscreen/payback, 1)
|
||||
owner.overlay_fullscreen("payback", /atom/movable/screen/fullscreen/stretch/payback, 1)
|
||||
|
||||
/datum/status_effect/drill_payback/tick() //They are not staying down. This will be a fight.
|
||||
if(!drilled_successfully && (get_dist(owner, drilled) >= 9)) //We don't want someone drilling the safe at arivals then raiding bridge with the buff
|
||||
|
||||
@@ -1023,7 +1023,7 @@
|
||||
/datum/status_effect/bubblegum_curse/on_creation(mob/living/new_owner, mob/living/source)
|
||||
. = ..()
|
||||
source_UID = source.UID()
|
||||
owner.overlay_fullscreen("Bubblegum", /atom/movable/screen/fullscreen/fog, 1)
|
||||
owner.overlay_fullscreen("Bubblegum", /atom/movable/screen/fullscreen/stretch/fog, 1)
|
||||
|
||||
/datum/status_effect/bubblegum_curse/tick()
|
||||
var/mob/living/simple_animal/hostile/megafauna/bubblegum/attacker = locateUID(source_UID)
|
||||
@@ -1031,7 +1031,7 @@
|
||||
qdel(src)
|
||||
if(attacker.health <= attacker.maxHealth / 2)
|
||||
owner.clear_fullscreen("Bubblegum")
|
||||
owner.overlay_fullscreen("Bubblegum", /atom/movable/screen/fullscreen/fog, 2)
|
||||
owner.overlay_fullscreen("Bubblegum", /atom/movable/screen/fullscreen/stretch/fog, 2)
|
||||
if(!coward_checking)
|
||||
if(owner.z != attacker.z)
|
||||
addtimer(CALLBACK(src, PROC_REF(onstation_coward_callback)), 12 SECONDS)
|
||||
|
||||
@@ -26,7 +26,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
uplink_items[I.category] = list()
|
||||
|
||||
uplink_items[I.category] += I
|
||||
if(I.limited_stock < 0 && !I.cant_discount && I.item && I.cost > 5)
|
||||
if(I.limited_stock < 0 && I.can_discount && I.item && I.cost > 5)
|
||||
sales_items += I
|
||||
|
||||
for(var/datum/uplink_item/I in last)
|
||||
@@ -79,7 +79,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
/// This makes an item on the uplink only show up to the specified species
|
||||
var/list/species = null
|
||||
var/surplus = 100 //Chance of being included in the surplus crate (when pick() selects it)
|
||||
var/cant_discount = FALSE
|
||||
var/can_discount = TRUE
|
||||
var/limited_stock = -1 // Can you only buy so many? -1 allows for infinite purchases
|
||||
var/hijack_only = FALSE //can this item be purchased only during hijackings?
|
||||
var/refundable = FALSE
|
||||
@@ -379,7 +379,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
reference = "SKD"
|
||||
item = /obj/item/melee/knuckleduster/syndie
|
||||
cost = 10
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
|
||||
// GRENADES AND EXPLOSIVES
|
||||
|
||||
@@ -751,7 +751,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
cost = 10
|
||||
surplus = 0
|
||||
hijack_only = TRUE //This is an item only useful for a hijack traitor, as such, it should only be available in those scenarios.
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
|
||||
/datum/uplink_item/device_tools/advpinpointer
|
||||
name = "Advanced Pinpointer"
|
||||
@@ -887,7 +887,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
reference = "BABA"
|
||||
item = /obj/item/toy/syndicateballoon
|
||||
cost = 100
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
|
||||
/datum/uplink_item/badass/bomber
|
||||
name = "Syndicate Bomber Jacket"
|
||||
@@ -906,7 +906,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
/datum/uplink_item/bundles_TC
|
||||
category = "Bundles and Telecrystals"
|
||||
surplus = 0
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
|
||||
/datum/uplink_item/bundles_TC/telecrystal
|
||||
name = "Raw Telecrystal"
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
refund_path = /obj/item/antag_spawner/nuke_ops
|
||||
cost = 100
|
||||
refundable = TRUE
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
|
||||
/datum/uplink_item/support/reinforcement/assault_borg
|
||||
name = "Syndicate Assault Cyborg"
|
||||
@@ -347,7 +347,7 @@
|
||||
reference = "C4B"
|
||||
item = /obj/item/storage/backpack/duffel/syndie/c4
|
||||
cost = 40 //20% discount!
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
uplinktypes = list(UPLINK_TYPE_NUCLEAR, UPLINK_TYPE_SST)
|
||||
|
||||
/datum/uplink_item/explosives/breaching_charge
|
||||
@@ -366,7 +366,7 @@
|
||||
reference = "X4B"
|
||||
item = /obj/item/storage/backpack/duffel/syndie/x4
|
||||
cost = 20
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
uplinktypes = list(UPLINK_TYPE_NUCLEAR, UPLINK_TYPE_SST)
|
||||
|
||||
/datum/uplink_item/explosives/grenadier
|
||||
@@ -643,7 +643,7 @@
|
||||
cost = 55
|
||||
excludefrom = list(UPLINK_TYPE_TRAITOR, UPLINK_TYPE_SIT)
|
||||
surplus = 0
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
hijack_only = FALSE
|
||||
|
||||
/datum/uplink_item/explosives/emp_bomb/nuke
|
||||
@@ -651,7 +651,7 @@
|
||||
cost = 50
|
||||
excludefrom = list(UPLINK_TYPE_TRAITOR, UPLINK_TYPE_SIT)
|
||||
surplus = 0
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
|
||||
/datum/uplink_item/explosives/atmosfiregrenades/nuke
|
||||
reference = "NAPG"
|
||||
@@ -659,7 +659,7 @@
|
||||
cost = 60
|
||||
excludefrom = list(UPLINK_TYPE_TRAITOR, UPLINK_TYPE_SIT)
|
||||
surplus = 0
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
|
||||
/datum/uplink_item/stealthy_tools/chameleon/nuke
|
||||
reference = "NCHAM"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/// This uplink catagory is for uplink items avalible by special circumstances. Think station traits, or if some event rolling in a round gave traitors special items, or an objective.
|
||||
/datum/uplink_item/special
|
||||
category = "Special Offers"
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
surplus = 0
|
||||
excludefrom = list(UPLINK_TYPE_NUCLEAR, UPLINK_TYPE_SST, UPLINK_TYPE_TRAITOR, UPLINK_TYPE_SIT)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
/datum/uplink_item/jobspecific
|
||||
category = "Job Specific Tools"
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
excludefrom = list(UPLINK_TYPE_NUCLEAR, UPLINK_TYPE_SST) // Stops the job specific category appearing for nukies
|
||||
|
||||
//Clown
|
||||
@@ -333,7 +333,7 @@
|
||||
|
||||
/datum/uplink_item/species_restricted
|
||||
category = "Species Specific Gear"
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
excludefrom = list(UPLINK_TYPE_NUCLEAR, UPLINK_TYPE_SST) // Stops the job specific category appearing for nukies
|
||||
|
||||
//skrell
|
||||
@@ -420,7 +420,7 @@
|
||||
refund_path = /obj/item/guardiancreator/tech/choose
|
||||
refundable = TRUE
|
||||
surplus = 0 // This being refundable makes this a big no no in my mind.
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
|
||||
/datum/uplink_item/stealthy_weapons/martialarts
|
||||
name = "Martial Arts Scroll"
|
||||
@@ -431,7 +431,7 @@
|
||||
item = /obj/item/sleeping_carp_scroll
|
||||
cost = 65
|
||||
excludefrom = list(UPLINK_TYPE_NUCLEAR, UPLINK_TYPE_SST)
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
|
||||
/datum/uplink_item/stealthy_weapons/bearserk
|
||||
name = "Bearserker Pelt"
|
||||
@@ -548,7 +548,7 @@
|
||||
cost = 70
|
||||
excludefrom = list(UPLINK_TYPE_NUCLEAR, UPLINK_TYPE_SST)
|
||||
surplus = 0
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
|
||||
/datum/uplink_item/cyber_implants/sensory_enhancer
|
||||
name = "Qani-Laaca Sensory Computer Autoimplanter"
|
||||
@@ -659,7 +659,7 @@
|
||||
cost = 40
|
||||
excludefrom = list(UPLINK_TYPE_NUCLEAR, UPLINK_TYPE_SST)
|
||||
surplus = 0
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
hijack_only = TRUE
|
||||
|
||||
/datum/uplink_item/explosives/emp_bomb
|
||||
@@ -671,7 +671,7 @@
|
||||
cost = 40
|
||||
excludefrom = list(UPLINK_TYPE_NUCLEAR, UPLINK_TYPE_SST)
|
||||
surplus = 0
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
|
||||
/datum/uplink_item/explosives/emp_bomb/New()
|
||||
..()
|
||||
@@ -687,7 +687,7 @@
|
||||
cost = 50
|
||||
excludefrom = list(UPLINK_TYPE_NUCLEAR, UPLINK_TYPE_SST)
|
||||
surplus = 0
|
||||
cant_discount = TRUE
|
||||
can_discount = FALSE
|
||||
|
||||
/datum/uplink_item/stealthy_tools/chameleon
|
||||
name = "Chameleon Kit"
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
//This is a beta game mode to test ways to implement an "infinite" traitor round in which more traitors are automatically added in as needed.
|
||||
//Automatic traitor adding is complete pending the inevitable bug fixes. Need to add a respawn system to let dead people respawn after 30 minutes or so.
|
||||
|
||||
|
||||
/datum/game_mode/traitor/autotraitor
|
||||
name = "AutoTraitor"
|
||||
config_tag = "extend-a-traitormongous"
|
||||
@@ -11,10 +7,9 @@
|
||||
|
||||
/datum/game_mode/traitor/autotraitor/announce()
|
||||
..()
|
||||
to_chat(world, "<B>Game mode is AutoTraitor. Traitors will be added to the round automagically as needed.</B>")
|
||||
to_chat(world, "<b>Game mode is AutoTraitor. Traitors will be added to the round automagically as needed.</b>")
|
||||
|
||||
/datum/game_mode/traitor/autotraitor/pre_setup()
|
||||
|
||||
if(GLOB.configuration.gamemode.prevent_mindshield_antags)
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
@@ -24,7 +19,6 @@
|
||||
if(P.client && P.ready)
|
||||
num_players++
|
||||
|
||||
//var/r = rand(5)
|
||||
var/num_traitors = 1
|
||||
var/max_traitors = 1
|
||||
var/traitor_prob = 0
|
||||
@@ -33,7 +27,7 @@
|
||||
|
||||
// Stop setup if no possible traitors
|
||||
if(!length(possible_traitors))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
if(GLOB.configuration.gamemode.traitor_scaling)
|
||||
num_traitors = max_traitors - 1 + prob(traitor_prob)
|
||||
@@ -42,8 +36,7 @@
|
||||
else
|
||||
num_traitors = max(1, min(num_players(), traitors_possible))
|
||||
|
||||
|
||||
for(var/i = 0, i < num_traitors, i++)
|
||||
for(var/i in 1 to num_traitors)
|
||||
var/datum/mind/traitor = pick(possible_traitors)
|
||||
pre_traitors += traitor
|
||||
possible_traitors.Remove(traitor)
|
||||
@@ -56,128 +49,91 @@
|
||||
traitor.special_role = SPECIAL_ROLE_TRAITOR
|
||||
traitor.restricted_roles = restricted_jobs
|
||||
|
||||
// if(!length(traitors))
|
||||
// return 0
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/traitor/autotraitor/post_setup()
|
||||
..()
|
||||
traitorcheckloop()
|
||||
addtimer(CALLBACK(src, PROC_REF(traitor_check_loop)), 15 MINUTES)
|
||||
|
||||
/datum/game_mode/traitor/autotraitor/proc/traitorcheckloop()
|
||||
spawn(9000)
|
||||
if(SSshuttle.emergency.mode >= SHUTTLE_ESCAPE)
|
||||
return
|
||||
//message_admins("Performing AutoTraitor Check")
|
||||
var/playercount = 0
|
||||
var/traitorcount = 0
|
||||
var/possible_traitors[0]
|
||||
for(var/mob/living/player in GLOB.mob_list)
|
||||
if(player.client && player.stat != DEAD)
|
||||
playercount += 1
|
||||
if(!player.mind)
|
||||
continue
|
||||
if(player.mind.special_role)
|
||||
traitorcount += 1
|
||||
continue
|
||||
if(ishuman(player) || isAI(player))
|
||||
if((ROLE_TRAITOR in player.client.prefs.be_special) && !player.client.skip_antag && !jobban_isbanned(player, ROLE_TRAITOR) && !jobban_isbanned(player, ROLE_SYNDICATE))
|
||||
possible_traitors += player.mind
|
||||
for(var/datum/mind/player in possible_traitors)
|
||||
for(var/job in restricted_jobs)
|
||||
if(player.assigned_role == job)
|
||||
possible_traitors -= player
|
||||
if(!player.current || !ishuman(player.current)) // Remove mindshield-implanted mobs from the list
|
||||
/datum/game_mode/traitor/autotraitor/proc/traitor_check_loop()
|
||||
if(SSshuttle.emergency.mode >= SHUTTLE_ESCAPE)
|
||||
return
|
||||
|
||||
var/player_count = 0
|
||||
var/traitor_count = 0
|
||||
var/list/possible_traitors = list()
|
||||
for(var/mob/living/player in GLOB.mob_list)
|
||||
if(player.client && player.stat != DEAD)
|
||||
player_count += 1
|
||||
if(!player.mind)
|
||||
continue
|
||||
var/mob/living/carbon/human/H = player.current
|
||||
for(var/obj/item/bio_chip/mindshield/I in H.contents)
|
||||
if(I && I.implanted)
|
||||
possible_traitors -= player
|
||||
if(!H.job || H.mind.offstation_role) //Golems, special events stuff, etc.
|
||||
if(player.mind.special_role)
|
||||
traitor_count += 1
|
||||
continue
|
||||
if(ishuman(player) || isAI(player))
|
||||
if((ROLE_TRAITOR in player.client.prefs.be_special) && !player.client.skip_antag && !jobban_isbanned(player, ROLE_TRAITOR) && !jobban_isbanned(player, ROLE_SYNDICATE))
|
||||
possible_traitors += player.mind
|
||||
for(var/datum/mind/player in possible_traitors)
|
||||
for(var/job in restricted_jobs)
|
||||
if(player.assigned_role == job)
|
||||
possible_traitors -= player
|
||||
//message_admins("Live Players: [playercount]")
|
||||
//message_admins("Live Traitors: [traitorcount]")
|
||||
// message_admins("Potential Traitors:")
|
||||
// for(var/mob/living/traitorlist in possible_traitors)
|
||||
// message_admins("[traitorlist.real_name]")
|
||||
if(!player.current || !ishuman(player.current)) // Remove mindshield-implanted mobs from the list
|
||||
continue
|
||||
var/mob/living/carbon/human/H = player.current
|
||||
for(var/obj/item/bio_chip/mindshield/I in H.contents)
|
||||
if(I && I.implanted)
|
||||
possible_traitors -= player
|
||||
if(!H.job || H.mind.offstation_role) //Golems, special events stuff, etc.
|
||||
possible_traitors -= player
|
||||
|
||||
// var/r = rand(5)
|
||||
// var/target_traitors = 1
|
||||
var/max_traitors = 1
|
||||
var/traitor_prob = 0
|
||||
max_traitors = round(playercount / 10) + 1
|
||||
traitor_prob = (playercount - (max_traitors - 1) * 10) * 5
|
||||
if(traitorcount < max_traitors - 1)
|
||||
traitor_prob += 50
|
||||
var/max_traitors = 1
|
||||
var/traitor_prob = 0
|
||||
max_traitors = round(player_count / 10) + 1
|
||||
traitor_prob = (player_count - (max_traitors - 1) * 10) * 5
|
||||
if(traitor_count < max_traitors - 1)
|
||||
traitor_prob += 50
|
||||
|
||||
if(traitor_count < max_traitors)
|
||||
if(prob(traitor_prob))
|
||||
message_admins("Making a new Traitor.")
|
||||
if(!length(possible_traitors))
|
||||
message_admins("No potential traitors. Cancelling new traitor.")
|
||||
addtimer(CALLBACK(src, PROC_REF(traitor_check_loop)), 15 MINUTES)
|
||||
return
|
||||
var/datum/mind/new_traitor_mind = pick(possible_traitors)
|
||||
var/mob/living/new_traitor = new_traitor_mind.current
|
||||
|
||||
if(traitorcount < max_traitors)
|
||||
//message_admins("Number of Traitors is below maximum. Rolling for new Traitor.")
|
||||
//message_admins("The probability of a new traitor is [traitor_prob]%")
|
||||
|
||||
if(prob(traitor_prob))
|
||||
message_admins("Making a new Traitor.")
|
||||
if(!length(possible_traitors))
|
||||
message_admins("No potential traitors. Cancelling new traitor.")
|
||||
traitorcheckloop()
|
||||
return
|
||||
var/datum/mind/newtraitormind = pick(possible_traitors)
|
||||
var/mob/living/newtraitor = newtraitormind.current
|
||||
//message_admins("[newtraitor.real_name] is the new Traitor.")
|
||||
|
||||
to_chat(newtraitor, "<span class='danger'>ATTENTION:</span> It is time to pay your debt to the Syndicate...")
|
||||
newtraitor.mind.add_antag_datum(/datum/antagonist/traitor)
|
||||
//else
|
||||
//message_admins("No new traitor being added.")
|
||||
//else
|
||||
//message_admins("Number of Traitors is at maximum. Not making a new Traitor.")
|
||||
|
||||
traitorcheckloop()
|
||||
|
||||
to_chat(new_traitor, "<span class='danger'>ATTENTION:</span> It is time to pay your debt to the Syndicate...")
|
||||
new_traitor.mind.add_antag_datum(/datum/antagonist/traitor)
|
||||
|
||||
addtimer(CALLBACK(src, PROC_REF(traitor_check_loop)), 15 MINUTES)
|
||||
|
||||
/datum/game_mode/traitor/autotraitor/latespawn(mob/living/carbon/human/character)
|
||||
..()
|
||||
if(SSshuttle.emergency.mode >= SHUTTLE_ESCAPE)
|
||||
return
|
||||
//message_admins("Late Join Check")
|
||||
|
||||
if(character.client && (ROLE_TRAITOR in character.client.prefs.be_special) && !character.client.skip_antag && !jobban_isbanned(character, ROLE_TRAITOR) && !jobban_isbanned(character, ROLE_SYNDICATE))
|
||||
//message_admins("Late Joiner has Be Syndicate")
|
||||
//message_admins("Checking number of players")
|
||||
var/playercount = 0
|
||||
var/traitorcount = 0
|
||||
var/player_count = 0
|
||||
var/traitor_count = 0
|
||||
for(var/mob/living/player in GLOB.mob_list)
|
||||
if(player.client && player.stat != DEAD)
|
||||
playercount += 1
|
||||
player_count += 1
|
||||
if(player.mind && player.mind.special_role)
|
||||
traitorcount += 1
|
||||
//message_admins("Live Players: [playercount]")
|
||||
//message_admins("Live Traitors: [traitorcount]")
|
||||
traitor_count += 1
|
||||
|
||||
//var/r = rand(5)
|
||||
//var/target_traitors = 1
|
||||
var/max_traitors = 2
|
||||
var/traitor_prob = 0
|
||||
max_traitors = round(playercount / 10) + 1
|
||||
traitor_prob = (playercount - (max_traitors - 1) * 10) * 5
|
||||
if(traitorcount < max_traitors - 1)
|
||||
max_traitors = round(player_count / 10) + 1
|
||||
traitor_prob = (player_count - (max_traitors - 1) * 10) * 5
|
||||
if(traitor_count < max_traitors - 1)
|
||||
traitor_prob += 50
|
||||
|
||||
//target_traitors = max(1, min(round((playercount + r) / 10, 1), traitors_possible))
|
||||
//message_admins("Target Traitor Count is: [target_traitors]")
|
||||
if(traitorcount < max_traitors)
|
||||
if(traitor_count < max_traitors)
|
||||
for(var/job in restricted_jobs)
|
||||
if(character.mind.assigned_role == job || !ishuman(character))
|
||||
return
|
||||
//message_admins("Number of Traitors is below maximum. Rolling for New Arrival Traitor.")
|
||||
//message_admins("The probability of a new traitor is [traitor_prob]%")
|
||||
|
||||
if(prob(traitor_prob))
|
||||
message_admins("New traitor roll passed. Making a new Traitor.")
|
||||
character.mind.make_Traitor() //TEMP: Add proper checks for loyalty here. uc_guy
|
||||
//else
|
||||
//message_admins("New traitor roll failed. No new traitor.")
|
||||
//else
|
||||
//message_admins("Late Joiner does not have Be Syndicate")
|
||||
message_admins("New traitor roll passed. Making a new Traitor.")
|
||||
character.mind.make_Traitor()
|
||||
|
||||
@@ -398,7 +398,7 @@
|
||||
|
||||
/obj/machinery/camera/get_remote_view_fullscreens(mob/user)
|
||||
if(view_range == short_range) //unfocused
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 2)
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/stretch/impaired, 2)
|
||||
|
||||
/obj/machinery/camera/update_remote_sight(mob/living/user)
|
||||
if(isXRay() && isAI(user))
|
||||
|
||||
@@ -208,7 +208,7 @@
|
||||
if(final)
|
||||
playsound(origin, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
|
||||
remote_eye.setLoc(get_turf(final))
|
||||
C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/noise)
|
||||
C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/stretch/flash/noise)
|
||||
C.clear_fullscreen("flash", 3) //Shorter flash than normal since it's an ~~advanced~~ console!
|
||||
else
|
||||
playsound(origin, 'sound/machines/terminal_prompt_deny.ogg', 25, FALSE)
|
||||
|
||||
@@ -35,6 +35,28 @@ Possible to do for anyone motivated enough:
|
||||
|
||||
GLOBAL_LIST_EMPTY(holopads)
|
||||
|
||||
/**
|
||||
* A stationary holopad for projecting hologram and making and receiving holocalls.
|
||||
*
|
||||
* Holopads are floor-plane machines similar, in appearance and interactive function, to quantum pads. They can be
|
||||
* used by crew members to make and answer holocalls, or by the AI to project holograms autonomously.
|
||||
*
|
||||
* Holopads are machines which can project a hologram up to `holo_range` tiles away. They do this in one of two modes:
|
||||
* holocalls, and AI holograms. Holocalls require a user to stand on a holopad, use its menu to select a remote holopad,
|
||||
* and make a call. Holocalls must be answered by the receiving holopad, or they will fail. Holopads can be configured
|
||||
* globally to auto-accept instead of failing, with the debug static variable `force_answer_call`. They can also be
|
||||
* individually configured to auto-accept calls immediately by setting their public mode option (`public_mode`),
|
||||
* which can be done in-game by using a screwdriver and then a multitool on a holopad. Holocalls will automatically end
|
||||
* if power goes out, the caller moves off the calling holopad, the caller projects outside the receiving holopad's
|
||||
* range, the caller is killed or incapacitated, the caller ghosts or disconnects, or the caller is QDELETED. AI
|
||||
* holograms require the AI to focus on the originating holopad and click on it; no answer is required. If the AI moves
|
||||
* out of a holopad's range and into the range of another, it will attempt to transfer its hologram to the next holopad.
|
||||
* Otherwise, AI holograms will stop projecting if power goes out for the originating holopad, the AI clicks on its
|
||||
* origin holopad, or, like holocalls, if the AI is killed, incapacitated, disconnected, QDELETED, or ghosts.
|
||||
* Holopads relay speech from the caller made with the :h radio key, and relay all speech on the answering end to the
|
||||
* caller or AI.
|
||||
*/
|
||||
|
||||
/obj/machinery/hologram/holopad
|
||||
name = "holopad"
|
||||
desc = "It's a floor-mounted device for projecting holographic images."
|
||||
@@ -47,17 +69,29 @@ GLOBAL_LIST_EMPTY(holopads)
|
||||
max_integrity = 300
|
||||
armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, rad = 0, fire = 50, acid = 0)
|
||||
|
||||
var/list/masters = list()//List of living mobs that use the holopad
|
||||
var/list/holorays = list()//Holoray-mob link.
|
||||
var/last_request = 0 //to prevent request spam. ~Carn
|
||||
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
|
||||
/// List of living mobs currently using the holopad
|
||||
var/list/masters = list()
|
||||
/// Holoray-mob link.
|
||||
var/list/holorays = list()
|
||||
/// Last request time, to prevent request spam. ~Carn
|
||||
var/last_request = 0
|
||||
/// The range, in tiles, that a holopad can project a hologram.
|
||||
var/holo_range = 5
|
||||
var/temp = ""
|
||||
var/list/holo_calls //array of /datum/holocalls
|
||||
var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs
|
||||
var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
|
||||
/// A list of holocalls associated with this holopad.
|
||||
var/list/holo_calls
|
||||
/// The outgoing holocall currently being processed by this holopad.
|
||||
var/datum/holocall/outgoing_call
|
||||
/// Universal debug toggle for whether holopads will automatically answer calls after a few rings.
|
||||
var/static/force_answer_call = FALSE
|
||||
/// Toggle for auto-answering calls immediately, set via multitool.
|
||||
var/public_mode = FALSE
|
||||
/// The ray effect emanating from this holopad to the produced hologram.
|
||||
var/obj/effect/overlay/holoray/ray
|
||||
/// Whether or not this holopad is currently ringing, from being called by another pad.
|
||||
var/ringing = FALSE
|
||||
var/dialling_input = FALSE //The user is currently selecting where to send their call
|
||||
/// Whether or not the user is currently selecting where to send their call.
|
||||
var/dialling_input = FALSE
|
||||
|
||||
/obj/machinery/hologram/holopad/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -120,6 +154,13 @@ GLOBAL_LIST_EMPTY(holopads)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/hologram/holopad/multitool_act(mob/living/user, obj/item/I)
|
||||
. = TRUE
|
||||
if(!I.use_tool(src, user, 0, volume = I.tool_volume))
|
||||
return
|
||||
public_mode = !public_mode
|
||||
to_chat(user, "<span class='notice'>You [public_mode ? "enable" : "disable"] the holopad's public mode setting.</span>")
|
||||
|
||||
/obj/machinery/hologram/holopad/screwdriver_act(mob/user, obj/item/I)
|
||||
. = TRUE
|
||||
default_deconstruction_screwdriver(user, "holopad_open", "holopad0", I)
|
||||
@@ -143,6 +184,11 @@ GLOBAL_LIST_EMPTY(holopads)
|
||||
user.set_machine(src)
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/hologram/holopad/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Its maintenance panel can be <b>screwed [panel_open ? "closed" : "open"]</b>.</span>"
|
||||
. += "<span class='notice'>Its public mode indicator reads <b>[public_mode ? "on" : "off"]</b>. It can be <b>turned [public_mode ? "off" : "on"]</b> by using a multitool while the maintenance panel is open.</span>"
|
||||
|
||||
/obj/machinery/hologram/holopad/AltClick(mob/living/carbon/human/user)
|
||||
if(..())
|
||||
return
|
||||
@@ -300,7 +346,7 @@ GLOBAL_LIST_EMPTY(holopads)
|
||||
continue
|
||||
|
||||
if(HC.connected_holopad != src)
|
||||
if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2)))
|
||||
if((force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2))) || public_mode)
|
||||
HC.Answer(src)
|
||||
break
|
||||
if(outgoing_call)
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
|
||||
#define MATTER_100 100
|
||||
#define MATTER_500 500
|
||||
|
||||
#define TAB_AIRLOCK_TYPE 1
|
||||
#define TAB_AIRLOCK_ACCESS 2
|
||||
|
||||
@@ -10,6 +6,204 @@
|
||||
#define MODE_WINDOW "Windows"
|
||||
#define MODE_DECON "Deconstruction"
|
||||
|
||||
/// A generic action for an RCD.
|
||||
/datum/rcd_act
|
||||
/// How much compressed matter this action costs.
|
||||
var/cost = 0
|
||||
/// How long this action takes.
|
||||
var/delay = 0
|
||||
/// The message (if any) to send the user when the action starts.
|
||||
var/start_message
|
||||
/// The effect (if any) to create when the action starts.
|
||||
var/obj/effect/start_effect_type
|
||||
/// The effect (if any) to create when the action completes.
|
||||
var/obj/effect/end_effect_type
|
||||
/// The mode the RCD must be in.
|
||||
var/mode
|
||||
|
||||
/// Attempt the action. This should not need to be overridden.
|
||||
/datum/rcd_act/proc/try_act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
if(!can_act(A, rcd))
|
||||
return FALSE
|
||||
// We don't use the sound effect from use_tool because RCDs have a different sound effect for the start and end.
|
||||
playsound(get_turf(rcd), 'sound/machines/click.ogg', 50, TRUE)
|
||||
if(!rcd.tool_use_check(user, cost))
|
||||
return FALSE
|
||||
if(start_message)
|
||||
to_chat(user, start_message)
|
||||
var/obj/effect/start_effect
|
||||
if(start_effect_type)
|
||||
start_effect = new start_effect_type(get_turf(A))
|
||||
if(!rcd.use_tool(A, user, delay, cost))
|
||||
if(!QDELETED(start_effect))
|
||||
qdel(start_effect)
|
||||
return FALSE
|
||||
if(start_effect)
|
||||
qdel(start_effect)
|
||||
// If time elapsed, check our preconditions again.
|
||||
if(delay && !can_act(A, rcd))
|
||||
return FALSE
|
||||
if(end_effect_type)
|
||||
new end_effect_type(get_turf(A))
|
||||
playsound(get_turf(rcd), 'sound/items/deconstruct.ogg', 50, TRUE)
|
||||
act(A, rcd, user)
|
||||
return TRUE
|
||||
|
||||
/// Test to see if the act is possible. You should usually override this.
|
||||
/datum/rcd_act/proc/can_act(atom/A, obj/item/rcd/rcd)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
return rcd.mode == mode
|
||||
|
||||
/// Perform the act. You should usually override this.
|
||||
/datum/rcd_act/proc/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
return
|
||||
|
||||
/datum/rcd_act/place_floor
|
||||
mode = MODE_TURF
|
||||
cost = 1
|
||||
start_message = "Building floor..."
|
||||
end_effect_type = /obj/effect/temp_visual/rcd_effect/end
|
||||
|
||||
/datum/rcd_act/place_floor/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return isspaceturf(A) || istype(A, /obj/structure/lattice)
|
||||
|
||||
/datum/rcd_act/place_floor/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/turf/act_on = get_turf(A)
|
||||
act_on.ChangeTurf(/turf/simulated/floor/plating)
|
||||
|
||||
/datum/rcd_act/place_wall
|
||||
mode = MODE_TURF
|
||||
cost = 3
|
||||
start_message = "Building wall..."
|
||||
delay = 2 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/short
|
||||
end_effect_type = /obj/effect/temp_visual/rcd_effect/end
|
||||
|
||||
/datum/rcd_act/place_wall/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return isfloorturf(A)
|
||||
|
||||
/datum/rcd_act/place_wall/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/turf/act_on = get_turf(A)
|
||||
act_on.ChangeTurf(/turf/simulated/wall)
|
||||
|
||||
/datum/rcd_act/place_airlock
|
||||
mode = MODE_AIRLOCK
|
||||
cost = 10
|
||||
start_message = "Building airlock..."
|
||||
delay = 5 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect
|
||||
end_effect_type = /obj/effect/temp_visual/rcd_effect/end
|
||||
|
||||
/datum/rcd_act/place_airlock/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return isfloorturf(A) && !(/obj/machinery/door/airlock in A.contents)
|
||||
|
||||
/datum/rcd_act/place_airlock/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/obj/machinery/door/airlock/T = new rcd.door_type(A)
|
||||
if(T.glass)
|
||||
T.polarized_glass = rcd.electrochromic
|
||||
T.name = rcd.door_name
|
||||
T.autoclose = TRUE
|
||||
if(rcd.one_access)
|
||||
T.req_one_access = rcd.selected_accesses.Copy()
|
||||
else
|
||||
T.req_access = rcd.selected_accesses.Copy()
|
||||
|
||||
/datum/rcd_act/place_window
|
||||
mode = MODE_WINDOW
|
||||
cost = 2
|
||||
start_message = "Building window..."
|
||||
delay = 2 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/short
|
||||
end_effect_type = /obj/effect/temp_visual/rcd_effect/end
|
||||
|
||||
/datum/rcd_act/place_window/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return isfloorturf(A) && !(/obj/structure/grille in A.contents)
|
||||
|
||||
/datum/rcd_act/place_window/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/turf/act_on= A
|
||||
for(var/obj/structure/window/window_to_delete in act_on)
|
||||
qdel(window_to_delete)
|
||||
new /obj/structure/grille(act_on)
|
||||
new /obj/structure/window/full/reinforced(act_on)
|
||||
act_on.ChangeTurf(/turf/simulated/floor/plating) // Platings go under windows.
|
||||
|
||||
/datum/rcd_act/remove_floor
|
||||
mode = MODE_DECON
|
||||
cost = 5
|
||||
start_message = "Deconstructing floor..."
|
||||
delay = 5 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/reverse
|
||||
|
||||
/datum/rcd_act/remove_floor/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return isfloorturf(A)
|
||||
|
||||
/datum/rcd_act/remove_floor/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/turf/act_on = get_turf(A)
|
||||
act_on.ChangeTurf(act_on.baseturf)
|
||||
|
||||
/datum/rcd_act/remove_wall
|
||||
mode = MODE_DECON
|
||||
cost = 5
|
||||
start_message = "Deonstructing wall..."
|
||||
delay = 5 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/reverse
|
||||
|
||||
/datum/rcd_act/remove_wall/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(isreinforcedwallturf(A) && !rcd.canRwall)
|
||||
return FALSE
|
||||
if(istype(A, /turf/simulated/wall/indestructible))
|
||||
return FALSE
|
||||
return iswallturf(A)
|
||||
|
||||
/datum/rcd_act/remove_wall/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/turf/act_on = get_turf(A)
|
||||
act_on.ChangeTurf(/turf/simulated/floor/plating)
|
||||
|
||||
/datum/rcd_act/remove_airlock
|
||||
mode = MODE_DECON
|
||||
cost = 20
|
||||
start_message = "Deconstructing airlock..."
|
||||
delay = 5 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/reverse
|
||||
|
||||
/datum/rcd_act/remove_airlock/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return istype(A, /obj/machinery/door/airlock)
|
||||
|
||||
/datum/rcd_act/remove_airlock/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
qdel(A)
|
||||
|
||||
/datum/rcd_act/remove_window
|
||||
mode = MODE_DECON
|
||||
cost = 2
|
||||
start_message = "Deconstructing window..."
|
||||
delay = 2 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/reverse_short
|
||||
|
||||
/datum/rcd_act/remove_window/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return istype(A, /obj/structure/window)
|
||||
|
||||
/datum/rcd_act/remove_window/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/turf/act_on = get_turf(A)
|
||||
qdel(A)
|
||||
for(var/obj/structure/grille/grill_to_destroy in act_on)
|
||||
qdel(grill_to_destroy)
|
||||
|
||||
/obj/item/rcd
|
||||
name = "rapid-construction-device (RCD)"
|
||||
desc = "A device used to rapidly build and deconstruct walls, floors and airlocks."
|
||||
@@ -25,7 +219,6 @@
|
||||
materials = list(MAT_METAL = 30000)
|
||||
origin_tech = "engineering=4;materials=2"
|
||||
toolspeed = 1
|
||||
usesound = 'sound/items/deconstruct.ogg'
|
||||
flags_2 = NO_MAT_REDEMPTION_2
|
||||
req_access = list(ACCESS_ENGINE)
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 100, ACID = 50)
|
||||
@@ -37,7 +230,7 @@
|
||||
/// The current amount of matter stored.
|
||||
var/matter = NONE
|
||||
/// The max amount of matter that can be stored.
|
||||
var/max_matter = MATTER_100
|
||||
var/max_matter = 100
|
||||
/// The RCD's current build mode.
|
||||
var/mode = MODE_TURF
|
||||
/// If the RCD can deconstruct reinforced walls.
|
||||
@@ -65,9 +258,16 @@
|
||||
var/static/list/door_types_ui_list = list()
|
||||
/// An associative list containing all station accesses. Includes their name and access number. For use with the UI.
|
||||
var/static/list/door_accesses_list = list()
|
||||
/// The list of potential RCD actions.
|
||||
var/static/list/possible_actions
|
||||
|
||||
/obj/item/rcd/Initialize()
|
||||
. = ..()
|
||||
if(!length(possible_actions))
|
||||
possible_actions = list()
|
||||
for(var/action_type in subtypesof(/datum/rcd_act))
|
||||
possible_actions += new action_type()
|
||||
|
||||
spark_system = new /datum/effect_system/spark_spread
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
@@ -364,214 +564,6 @@
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Called in `afterattack()` if `mode` is set to `MODE_TURF`.
|
||||
*
|
||||
* Creates either a plating, or a wall, depending on the turf that already exists at the location.
|
||||
*
|
||||
* Arguments:
|
||||
* * A - the location we're trying to build at.
|
||||
* * user - the mob using the RCD.
|
||||
*/
|
||||
/obj/item/rcd/proc/mode_turf(atom/A, mob/user)
|
||||
if(isspaceturf(A) || istype(A, /obj/structure/lattice))
|
||||
if(useResource(1, user))
|
||||
to_chat(user, "Building Floor...")
|
||||
playsound(loc, usesound, 50, 1)
|
||||
var/turf/AT = get_turf(A)
|
||||
new/obj/effect/temp_visual/rcd_effect/end(get_turf(A))
|
||||
AT.ChangeTurf(/turf/simulated/floor/plating)
|
||||
return TRUE
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
return FALSE
|
||||
|
||||
if(isfloorturf(A))
|
||||
if(checkResource(3, user))
|
||||
to_chat(user, "Building Wall...")
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
var/obj/effect/temp_visual/rcd_effect/short/E = new(get_turf(A))
|
||||
if(do_after(user, 2 SECONDS * toolspeed, target = A))
|
||||
if(!isfloorturf(A))
|
||||
return FALSE
|
||||
if(!useResource(3, user))
|
||||
return FALSE
|
||||
playsound(loc, usesound, 50, 1)
|
||||
var/turf/AT = A
|
||||
new/obj/effect/temp_visual/rcd_effect/end(get_turf(A))
|
||||
AT.ChangeTurf(/turf/simulated/wall)
|
||||
return TRUE
|
||||
qdel(E)
|
||||
return FALSE
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
return FALSE
|
||||
to_chat(user, "<span class='warning'>ERROR! Location unsuitable for wall construction!</span>")
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Called in `afterattack()` if `mode` is set to `MODE_AIRLOCK`.
|
||||
*
|
||||
* Creates an `door_type` airlock at the given location `A`, and assigns it accesses from `selected_accesses`.
|
||||
*
|
||||
* Arguments:
|
||||
* * A - the location we're trying to build at.
|
||||
* * user - the mob using the RCD.
|
||||
*/
|
||||
/obj/item/rcd/proc/mode_airlock(atom/A, mob/user)
|
||||
if(isfloorturf(A))
|
||||
if(checkResource(10, user))
|
||||
to_chat(user, "Building Airlock...")
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
var/obj/effect/temp_visual/rcd_effect/E = new(get_turf(A))
|
||||
if(do_after(user, 5 SECONDS * toolspeed, target = A))
|
||||
if(locate(/obj/machinery/door/airlock) in A.contents)
|
||||
return FALSE
|
||||
if(!useResource(10, user))
|
||||
return FALSE
|
||||
playsound(loc, usesound, 50, 1)
|
||||
new/obj/effect/temp_visual/rcd_effect/end(get_turf(A))
|
||||
var/obj/machinery/door/airlock/T = new door_type(A)
|
||||
if(T.glass)
|
||||
T.polarized_glass = electrochromic
|
||||
T.name = door_name
|
||||
T.autoclose = TRUE
|
||||
if(one_access)
|
||||
T.req_one_access = selected_accesses.Copy()
|
||||
else
|
||||
T.req_access = selected_accesses.Copy()
|
||||
return FALSE
|
||||
qdel(E)
|
||||
return FALSE
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
return FALSE
|
||||
to_chat(user, "<span class='warning'>ERROR! Location unsuitable for airlock construction!</span>")
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Called in `afterattack()` if `mode` is set to `MODE_DECON`.
|
||||
*
|
||||
* Deconstrcts the target atom `A`.
|
||||
* Valid atoms are: basic walls, reinforced walls (if `canRwall` is `TRUE`), airlocks, and windows.
|
||||
*
|
||||
* Arguments:
|
||||
* * A - the location we're trying to build at.
|
||||
* * user - the mob using the RCD.
|
||||
*/
|
||||
/obj/item/rcd/proc/mode_decon(atom/A, mob/user)
|
||||
if(iswallturf(A))
|
||||
if(isreinforcedwallturf(A) && !canRwall)
|
||||
return FALSE
|
||||
if(istype(A, /turf/simulated/wall/indestructible))
|
||||
return FALSE
|
||||
if(checkResource(5, user))
|
||||
to_chat(user, "Deconstructing Wall...")
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
var/obj/effect/temp_visual/rcd_effect/reverse/E = new(get_turf(A))
|
||||
if(do_after(user, 5 SECONDS * toolspeed, target = A))
|
||||
if(!useResource(5, user))
|
||||
return FALSE
|
||||
playsound(loc, usesound, 50, 1)
|
||||
var/turf/AT = A
|
||||
AT.ChangeTurf(/turf/simulated/floor/plating)
|
||||
return TRUE
|
||||
qdel(E)
|
||||
return FALSE
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
return FALSE
|
||||
|
||||
if(isfloorturf(A))
|
||||
if(checkResource(5, user))
|
||||
to_chat(user, "Deconstructing Floor...")
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
var/obj/effect/temp_visual/rcd_effect/reverse/E = new(get_turf(A))
|
||||
if(do_after(user, 5 SECONDS * toolspeed, target = A))
|
||||
if(!useResource(5, user))
|
||||
return FALSE
|
||||
playsound(loc, usesound, 50, 1)
|
||||
var/turf/AT = A
|
||||
AT.ChangeTurf(AT.baseturf)
|
||||
return TRUE
|
||||
qdel(E)
|
||||
return FALSE
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
return FALSE
|
||||
|
||||
if(istype(A, /obj/machinery/door/airlock))
|
||||
if(checkResource(20, user))
|
||||
to_chat(user, "Deconstructing Airlock...")
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
var/obj/effect/temp_visual/rcd_effect/reverse/E = new(get_turf(A))
|
||||
if(do_after(user, 5 SECONDS * toolspeed, target = A))
|
||||
if(!useResource(20, user))
|
||||
return FALSE
|
||||
playsound(loc, usesound, 50, 1)
|
||||
qdel(A)
|
||||
return TRUE
|
||||
qdel(E)
|
||||
return FALSE
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
return FALSE
|
||||
|
||||
if(istype(A, /obj/structure/window))
|
||||
if(!checkResource(2, user))
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
return FALSE
|
||||
to_chat(user, "Deconstructing window...")
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
var/obj/effect/temp_visual/rcd_effect/reverse_short/E = new(get_turf(A))
|
||||
if(!do_after(user, 20 * toolspeed, target = A))
|
||||
qdel(E)
|
||||
return FALSE
|
||||
if(!useResource(2, user))
|
||||
return FALSE
|
||||
playsound(loc, usesound, 50, 1)
|
||||
var/turf/T1 = get_turf(A)
|
||||
QDEL_NULL(A)
|
||||
for(var/obj/structure/grille/G in T1.contents)
|
||||
qdel(G)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Called in `afterattack()` if `mode` is set to `MODE_WINDOW`.
|
||||
*
|
||||
* Constructs a grille and 4 reinforced window panes at the given location `A`.
|
||||
*
|
||||
* Arguments:
|
||||
* * A - the location we're trying to build at.
|
||||
* * user - the mob using the RCD.
|
||||
*/
|
||||
/obj/item/rcd/proc/mode_window(atom/A, mob/user)
|
||||
if(isfloorturf(A))
|
||||
if(locate(/obj/structure/grille) in A)
|
||||
return FALSE // We already have window
|
||||
if(!checkResource(2, user))
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
return FALSE
|
||||
to_chat(user, "Constructing window...")
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
var/obj/effect/temp_visual/rcd_effect/short/E = new(get_turf(A))
|
||||
if(!do_after(user, 20 * toolspeed, target = A))
|
||||
qdel(E)
|
||||
return FALSE
|
||||
if(locate(/obj/structure/grille) in A)
|
||||
return FALSE // We already have window
|
||||
if(!useResource(2, user))
|
||||
return FALSE
|
||||
playsound(loc, usesound, 50, 1)
|
||||
new/obj/effect/temp_visual/rcd_effect/end(get_turf(A))
|
||||
new /obj/structure/grille(A)
|
||||
for(var/obj/structure/window/W in A)
|
||||
qdel(W)
|
||||
new /obj/structure/window/full/reinforced(A)
|
||||
var/turf/AT = A
|
||||
AT.ChangeTurf(/turf/simulated/floor/plating) // Platings go under windows.
|
||||
return TRUE
|
||||
to_chat(user, "<span class='warning'>ERROR! Location unsuitable for window construction!</span>")
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
return FALSE
|
||||
|
||||
/obj/item/rcd/afterattack(atom/A, mob/user, proximity)
|
||||
if(!proximity)
|
||||
return FALSE
|
||||
@@ -580,31 +572,29 @@
|
||||
if(!is_type_in_list(A, allowed_targets))
|
||||
return FALSE
|
||||
|
||||
switch(mode)
|
||||
if(MODE_TURF)
|
||||
. = mode_turf(A, user)
|
||||
if(MODE_AIRLOCK)
|
||||
. = mode_airlock(A, user)
|
||||
if(MODE_DECON)
|
||||
. = mode_decon(A, user)
|
||||
if(MODE_WINDOW)
|
||||
. = mode_window(A, user)
|
||||
else
|
||||
to_chat(user, "ERROR: RCD in MODE: [mode] attempted use by [user]. Send this text #coderbus or an admin.")
|
||||
. = 0
|
||||
for(var/datum/rcd_act/act in possible_actions)
|
||||
if(act.can_act(A, src))
|
||||
. = act.try_act(A, src, user)
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
SStgui.update_uis(src)
|
||||
return
|
||||
|
||||
if(mode == MODE_DECON)
|
||||
to_chat(user, "<span class='warning'>You can't deconstruct that!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Location unsuitable for construction.</span>")
|
||||
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
SStgui.update_uis(src)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Called in each of the four build modes after an object is successfully built.
|
||||
*
|
||||
* Subtracts the amount of matter used from `matter`.
|
||||
* Attempts to use matter from the RCD.
|
||||
*
|
||||
* Arguments:
|
||||
* * amount - the amount of matter that was used.
|
||||
* * amount - the amount of matter to use
|
||||
*/
|
||||
/obj/item/rcd/proc/useResource(amount, mob/user)
|
||||
/obj/item/rcd/use(amount)
|
||||
if(matter < amount)
|
||||
return FALSE
|
||||
matter -= amount
|
||||
@@ -617,7 +607,7 @@
|
||||
* Arguments:
|
||||
* * amount - an amount of matter to check for
|
||||
*/
|
||||
/obj/item/rcd/proc/checkResource(amount, mob/user)
|
||||
/obj/item/rcd/tool_use_check(mob/user, amount)
|
||||
. = matter >= amount
|
||||
if(!. && user)
|
||||
to_chat(user, no_ammo_message)
|
||||
@@ -639,13 +629,13 @@
|
||||
/obj/item/rcd/borg/syndicate
|
||||
power_use_multiplier = 80
|
||||
|
||||
/obj/item/rcd/borg/useResource(amount, mob/user)
|
||||
if(!isrobot(user))
|
||||
/obj/item/rcd/borg/use(amount)
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
if(!istype(R))
|
||||
return FALSE
|
||||
var/mob/living/silicon/robot/R = user
|
||||
return R.cell.use(amount * power_use_multiplier)
|
||||
|
||||
/obj/item/rcd/borg/checkResource(amount, mob/user)
|
||||
/obj/item/rcd/borg/tool_use_check(mob/user, amount)
|
||||
if(!isrobot(user))
|
||||
return FALSE
|
||||
var/mob/living/silicon/robot/R = user
|
||||
@@ -675,8 +665,8 @@
|
||||
name = "combat RCD"
|
||||
icon_state = "crcd"
|
||||
item_state = "crcd"
|
||||
max_matter = MATTER_500
|
||||
matter = MATTER_500
|
||||
max_matter = 500
|
||||
matter = 500
|
||||
canRwall = TRUE
|
||||
|
||||
/obj/item/rcd_ammo
|
||||
@@ -701,9 +691,6 @@
|
||||
/obj/item/rcd_ammo/large
|
||||
ammoamt = 100
|
||||
|
||||
#undef MATTER_100
|
||||
#undef MATTER_500
|
||||
|
||||
#undef TAB_AIRLOCK_TYPE
|
||||
#undef TAB_AIRLOCK_ACCESS
|
||||
#undef MODE_TURF
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
|
||||
//Bottles for borg liquid squirters. PSSH PSSH
|
||||
/obj/item/reagent_containers/spray/alien
|
||||
name = "liquid synthesizer"
|
||||
desc = "squirts alien liquids."
|
||||
name = "generic chemical synthesizer"
|
||||
desc = "If you can see this, make an issue report on GitHub. Something has gone wrong!"
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "borg-default"
|
||||
|
||||
/obj/item/reagent_containers/spray/alien/smoke
|
||||
name = "smoke synthesizer"
|
||||
desc = "squirts smokey liquids."
|
||||
name = "smokescreen module"
|
||||
desc = "Releases a dense smoke cloud that cannot be seen through. Your thermal vision is still able to see targets through it."
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "borg-spray-smoke"
|
||||
list_reagents = list("water" = 50)
|
||||
@@ -50,8 +50,8 @@
|
||||
reagents.check_and_add("water", volume, 2 * coeff)
|
||||
|
||||
/obj/item/reagent_containers/spray/alien/acid
|
||||
name = "acid synthesizer"
|
||||
desc = "squirts burny liquids."
|
||||
name = "polyacid synthesizer"
|
||||
desc = "Sprays concentrated polyacid."
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "borg-spray-acid"
|
||||
list_reagents = list("facid" = 125, "sacid" = 125)
|
||||
@@ -60,20 +60,14 @@
|
||||
reagents.check_and_add("facid", volume / 2, 2 * coeff) // Volume / 2 here becuase there should be an even amount of both chems.
|
||||
reagents.check_and_add("sacid", volume / 2, 2 * coeff)
|
||||
|
||||
/obj/item/reagent_containers/spray/alien/stun
|
||||
name = "paralytic toxin synthesizer"
|
||||
desc = "squirts ether."
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "borg-spray-stun"
|
||||
list_reagents = list("ether" = 250)
|
||||
|
||||
/obj/item/reagent_containers/spray/alien/stun/cyborg_recharge(coeff, emagged)
|
||||
reagents.check_and_add("ether", volume, 2 * coeff)
|
||||
|
||||
//SKREEEEEEEEEEEE tool
|
||||
|
||||
/obj/item/flash/cyborg/alien
|
||||
name = "eye flash"
|
||||
desc = "Useful for taking pictures, making friends and flash-frying chips."
|
||||
icon = 'icons/mob/alien.dmi'
|
||||
icon_state = "borg-flash"
|
||||
|
||||
/obj/item/flash/cyborg/alien/cyborg_recharge(coeff, emagged)
|
||||
if(broken)
|
||||
broken = FALSE
|
||||
times_used = 0
|
||||
icon_state = "borg-flash"
|
||||
|
||||
@@ -374,7 +374,7 @@
|
||||
|
||||
/obj/structure/closet/get_remote_view_fullscreens(mob/user)
|
||||
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/stretch/impaired, 1)
|
||||
|
||||
/obj/structure/closet/ex_act(severity)
|
||||
for(var/atom/A in contents)
|
||||
|
||||
@@ -241,7 +241,7 @@
|
||||
|
||||
/obj/structure/morgue/get_remote_view_fullscreens(mob/user)
|
||||
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 2)
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/stretch/impaired, 2)
|
||||
|
||||
/*
|
||||
* Morgue tray
|
||||
@@ -534,7 +534,7 @@ GLOBAL_LIST_EMPTY(crematoriums)
|
||||
|
||||
/obj/structure/crematorium/get_remote_view_fullscreens(mob/user)
|
||||
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 2)
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/stretch/impaired, 2)
|
||||
|
||||
/*
|
||||
* Crematorium tray
|
||||
|
||||
@@ -359,13 +359,13 @@ GLOBAL_LIST_EMPTY(safes)
|
||||
drill.song.start_playing(driller)
|
||||
notify_ghosts("Security assault in progress in [get_area(src)]!", enter_link="<a href=byond://?src=[UID()];follow=1>(Click to jump to!)</a>", source = src, action = NOTIFY_FOLLOW)
|
||||
for(var/mob/dead/observer/O in GLOB.player_list)
|
||||
O.overlay_fullscreen("payback", /atom/movable/screen/fullscreen/payback, 0)
|
||||
O.overlay_fullscreen("payback", /atom/movable/screen/fullscreen/stretch/payback, 0)
|
||||
addtimer(CALLBACK(src, PROC_REF(ghost_payback_phase_2)), 2.7 SECONDS)
|
||||
|
||||
/obj/structure/safe/proc/ghost_payback_phase_2()
|
||||
for(var/mob/dead/observer/O in GLOB.player_list)
|
||||
O.clear_fullscreen("payback")
|
||||
O.overlay_fullscreen("payback", /atom/movable/screen/fullscreen/payback, 1)
|
||||
O.overlay_fullscreen("payback", /atom/movable/screen/fullscreen/stretch/payback, 1)
|
||||
addtimer(CALLBACK(src, PROC_REF(clear_payback)), 2 MINUTES)
|
||||
|
||||
/obj/structure/safe/proc/clear_payback()
|
||||
|
||||
@@ -2149,18 +2149,20 @@
|
||||
if(ismindshielded(player.current))
|
||||
possible_traitors -= player
|
||||
if(length(possible_traitors))
|
||||
var/datum/mind/newtraitormind = pick(possible_traitors)
|
||||
var/datum/mind/new_traitor_mind = pick(possible_traitors)
|
||||
|
||||
var/datum/objective/assassinate/kill_objective = new()
|
||||
kill_objective.target = H.mind
|
||||
kill_objective.explanation_text = "Assassinate [H.mind.name], the [H.mind.assigned_role]"
|
||||
newtraitormind.add_mind_objective(kill_objective)
|
||||
new_traitor_mind.add_mind_objective(kill_objective)
|
||||
|
||||
var/datum/antagonist/traitor/T = new()
|
||||
T.give_objectives = FALSE
|
||||
to_chat(newtraitormind.current, "<span class='danger'>ATTENTION:</span> It is time to pay your debt to the Syndicate...")
|
||||
to_chat(newtraitormind.current, "<b>Goal: <span class='danger'>KILL [H.real_name]</span>, currently in [get_area(H.loc)]</b>")
|
||||
newtraitormind.add_antag_datum(T)
|
||||
to_chat(new_traitor_mind.current, "<span class='danger'>ATTENTION:</span> It is time to pay your debt to the Syndicate...")
|
||||
to_chat(new_traitor_mind.current, "<b>Goal: <span class='danger'>KILL [H.real_name]</span>, currently in [get_area(H.loc)]</b>")
|
||||
new_traitor_mind.add_antag_datum(T)
|
||||
message_admins("[key_name_admin(new_traitor_mind)] was chosen to be the traitor for a smite!")
|
||||
log_admin("[key_name(new_traitor_mind)] was made into a traitor to hunt [key_name(H)] for 'Crew Traitor' smite.")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>ERROR: Unable to find any valid candidate to send after [H].</span>")
|
||||
return
|
||||
|
||||
@@ -482,7 +482,7 @@
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/get_remote_view_fullscreens(mob/user)
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/stretch/impaired, 1)
|
||||
|
||||
/obj/machinery/atmospherics/unary/cryo_cell/update_remote_sight(mob/living/user)
|
||||
return //we don't see the pipe network while inside cryo.
|
||||
|
||||
@@ -270,7 +270,7 @@
|
||||
//bad recipe, ruins the drink
|
||||
var/contents = pick("thick goop", "pungent sludge", "unspeakable slurry", "gross-looking concoction", "eldritch abomination of liquids")
|
||||
visible_message("<span class='warning'>The [con_type] fills with \an [contents]...</span>")
|
||||
drink_container.reagents.add_reagent(pick("????", "toxic_slurry", "meatslurry", "glowing_slury", "fishwater"), pick(30, 50))
|
||||
drink_container.reagents.add_reagent(pick("????", "toxic_slurry", "meatslurry", "glowing_slurry", "fishwater"), pick(30, 50))
|
||||
drink_container.name = "Liquid Mistakes"
|
||||
drink_container.desc = "WARNING: CONTENTS MAY BE AWFUL, DRINK AT OWN RISK."
|
||||
else
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
/obj/effect/hallucination/delamination_alarm/Initialize(mapload, mob/living/carbon/target)
|
||||
. = ..()
|
||||
target.playsound_local(target, 'sound/machines/engine_alert2.ogg', 25, FALSE, 30, 30)
|
||||
target.hear_radio(message_to_multilingual("Danger! Crystal hyperstructure integrity faltering! Integrity: [rand(30, 50)]%"), vname = "supermatter crystal", part_a = "<span class='[SSradio.frequency_span_class(PUB_FREQ)]'><b>\[[get_frequency_name(PUB_FREQ)]\]</b> <span class='name'>", part_b = "</span> <span class='message'>")
|
||||
target.hear_radio(message_to_multilingual("<b>Danger! Crystal hyperstructure integrity faltering! Integrity: [rand(30, 50)]%</b>"), vname = "supermatter crystal", part_a = "<span class='[SSradio.frequency_span_class(PUB_FREQ)]'><b>\[[get_frequency_name(PUB_FREQ)]\]</b> <span class='name'>", part_b = "</span> <span class='message'>")
|
||||
|
||||
/**
|
||||
* # Hallucination - Plasma Flood
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
inv.update_icon()
|
||||
|
||||
if(wear_suit)
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
if(hud_used.inventory_shown) //if the inventory is open ...
|
||||
wear_suit.screen_loc = ui_oclothing //TODO //...draw the item in the inventory screen
|
||||
client.screen += wear_suit //Either way, add the item to the HUD
|
||||
|
||||
@@ -319,7 +319,7 @@
|
||||
severity = 9
|
||||
if(-INFINITY to -95)
|
||||
severity = 10
|
||||
overlay_fullscreen("crit", /atom/movable/screen/fullscreen/crit, severity)
|
||||
overlay_fullscreen("crit", /atom/movable/screen/fullscreen/stretch/crit, severity)
|
||||
else if(stat == CONSCIOUS)
|
||||
if(check_death_method())
|
||||
clear_fullscreen("crit")
|
||||
@@ -340,7 +340,7 @@
|
||||
severity = 6
|
||||
if(45 to INFINITY)
|
||||
severity = 7
|
||||
overlay_fullscreen("oxy", /atom/movable/screen/fullscreen/oxy, severity)
|
||||
overlay_fullscreen("oxy", /atom/movable/screen/fullscreen/stretch/oxy, severity)
|
||||
else
|
||||
clear_fullscreen("oxy")
|
||||
|
||||
@@ -356,7 +356,7 @@
|
||||
if(45 to 70) severity = 4
|
||||
if(70 to 85) severity = 5
|
||||
if(85 to INFINITY) severity = 6
|
||||
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
|
||||
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/stretch/brute, severity)
|
||||
else
|
||||
clear_fullscreen("brute")
|
||||
|
||||
|
||||
@@ -353,7 +353,7 @@
|
||||
if((E && (E.status & ORGAN_DEAD)) || !.)
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, laser_pointer = FALSE, type = /atom/movable/screen/fullscreen/flash)
|
||||
/mob/living/carbon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, laser_pointer = FALSE, type = /atom/movable/screen/fullscreen/stretch/flash)
|
||||
//Parent proc checks if a mob can_be_flashed()
|
||||
. = ..()
|
||||
|
||||
@@ -1201,9 +1201,9 @@ so that different stomachs can handle things in different ways VB*/
|
||||
/mob/living/carbon/proc/update_tint()
|
||||
var/tinttotal = get_total_tint()
|
||||
if(tinttotal >= TINT_BLIND)
|
||||
overlay_fullscreen("tint", /atom/movable/screen/fullscreen/blind)
|
||||
overlay_fullscreen("tint", /atom/movable/screen/fullscreen/stretch/blind)
|
||||
else if(tinttotal >= TINT_IMPAIR)
|
||||
overlay_fullscreen("tint", /atom/movable/screen/fullscreen/impaired, 2)
|
||||
overlay_fullscreen("tint", /atom/movable/screen/fullscreen/stretch/impaired, 2)
|
||||
else
|
||||
clear_fullscreen("tint", 0)
|
||||
|
||||
|
||||
@@ -567,7 +567,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
inv.update_icon()
|
||||
|
||||
if(w_uniform && istype(w_uniform, /obj/item/clothing/under))
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
if(hud_used.inventory_shown) //if the inventory is open ...
|
||||
w_uniform.screen_loc = ui_iclothing //...draw the item in the inventory screen
|
||||
client.screen += w_uniform //Either way, add the item to the HUD
|
||||
@@ -644,7 +644,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
inv.update_icon()
|
||||
|
||||
if(wear_id)
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
wear_id.screen_loc = ui_id
|
||||
client.screen += wear_id
|
||||
|
||||
@@ -660,7 +660,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
inv.update_icon()
|
||||
|
||||
if(gloves)
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
if(hud_used.inventory_shown) //if the inventory is open ...
|
||||
gloves.screen_loc = ui_gloves //...draw the item in the inventory screen
|
||||
client.screen += gloves //Either way, add the item to the HUD
|
||||
@@ -702,7 +702,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
if(glasses)
|
||||
var/mutable_appearance/new_glasses
|
||||
var/obj/item/organ/external/head/head_organ = get_organ("head")
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
if(hud_used.inventory_shown) //if the inventory is open ...
|
||||
glasses.screen_loc = ui_glasses //...draw the item in the inventory screen
|
||||
client.screen += glasses //Either way, add the item to the HUD
|
||||
@@ -744,7 +744,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
|
||||
if(l_ear || r_ear)
|
||||
if(l_ear)
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
if(hud_used.inventory_shown) //if the inventory is open ...
|
||||
l_ear.screen_loc = ui_l_ear //...draw the item in the inventory screen
|
||||
client.screen += l_ear //Either way, add the item to the HUD
|
||||
@@ -761,7 +761,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
overlays_standing[EARS_LAYER] = mutable_appearance('icons/mob/clothing/ears.dmi', "[t_type]", layer = -EARS_LAYER)
|
||||
|
||||
if(r_ear)
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
if(hud_used.inventory_shown) //if the inventory is open ...
|
||||
r_ear.screen_loc = ui_r_ear //...draw the item in the inventory screen
|
||||
client.screen += r_ear //Either way, add the item to the HUD
|
||||
@@ -786,7 +786,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
inv.update_icon()
|
||||
|
||||
if(shoes)
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
if(hud_used.inventory_shown) //if the inventory is open ...
|
||||
shoes.screen_loc = ui_shoes //...draw the item in the inventory screen
|
||||
client.screen += shoes //Either way, add the item to the HUD
|
||||
@@ -822,7 +822,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
inv.update_icon()
|
||||
|
||||
if(s_store)
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
s_store.screen_loc = ui_sstore1
|
||||
client.screen += s_store
|
||||
|
||||
@@ -872,7 +872,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
if(inv)
|
||||
inv.update_icon()
|
||||
|
||||
if(hud_used.hud_shown && belt)
|
||||
if(hud_used.hud_version == HUD_STYLE_STANDARD && belt)
|
||||
client.screen += belt
|
||||
belt.screen_loc = ui_belt
|
||||
|
||||
@@ -899,7 +899,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
inv.update_icon()
|
||||
|
||||
if(wear_suit && istype(wear_suit, /obj/item/clothing/suit))
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
if(hud_used.inventory_shown) //if the inventory is open ...
|
||||
wear_suit.screen_loc = ui_oclothing //TODO //...draw the item in the inventory screen
|
||||
client.screen += wear_suit //Either way, add the item to the HUD
|
||||
@@ -948,7 +948,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
if(inv)
|
||||
inv.update_icon()
|
||||
|
||||
if(hud_used.hud_shown)
|
||||
if(hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
if(l_store)
|
||||
client.screen += l_store
|
||||
l_store.screen_loc = ui_storage1
|
||||
@@ -1082,21 +1082,21 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
|
||||
|
||||
//update whether our head item appears on our hud.
|
||||
/mob/living/carbon/human/update_hud_head(obj/item/I)
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
if(hud_used.inventory_shown)
|
||||
I.screen_loc = ui_head
|
||||
client.screen += I
|
||||
|
||||
//update whether our mask item appears on our hud.
|
||||
/mob/living/carbon/human/update_hud_wear_mask(obj/item/I)
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
if(hud_used.inventory_shown)
|
||||
I.screen_loc = ui_mask
|
||||
client.screen += I
|
||||
|
||||
//update whether our back item appears on our hud.
|
||||
/mob/living/carbon/human/update_hud_back(obj/item/I)
|
||||
if(client && hud_used && hud_used.hud_shown)
|
||||
if(client && hud_used && hud_used.hud_version == HUD_STYLE_STANDARD)
|
||||
I.screen_loc = ui_back
|
||||
client.screen += I
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
/mob/living/carbon/human/update_nearsighted_effects()
|
||||
var/obj/item/clothing/glasses/G = glasses
|
||||
if(HAS_TRAIT(src, TRAIT_NEARSIGHT) && (!istype(G) || !G.prescription))
|
||||
overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/impaired, 1)
|
||||
overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/stretch/impaired, 1)
|
||||
else
|
||||
clear_fullscreen("nearsighted")
|
||||
|
||||
|
||||
@@ -828,7 +828,7 @@
|
||||
return TRUE
|
||||
|
||||
//called when the mob receives a bright flash
|
||||
/mob/living/proc/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, laser_pointer = FALSE, type = /atom/movable/screen/fullscreen/flash)
|
||||
/mob/living/proc/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, laser_pointer = FALSE, type = /atom/movable/screen/fullscreen/stretch/flash)
|
||||
if(can_be_flashed(intensity, override_blindness_check))
|
||||
overlay_fullscreen("flash", type)
|
||||
addtimer(CALLBACK(src, PROC_REF(clear_fullscreen), "flash", 25), 25)
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
healths.icon_state = "health7"
|
||||
severity = 6
|
||||
if(severity > 0)
|
||||
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
|
||||
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/stretch/brute, severity)
|
||||
else
|
||||
clear_fullscreen("brute")
|
||||
if(health <= HEALTH_THRESHOLD_CRIT)
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
/mob/living/update_blind_effects()
|
||||
/mob/living/update_blind_effects(sleeping = FALSE, force_clear_sleeping = FALSE)
|
||||
if(force_clear_sleeping) //We force it on waking up, as if you are blind from other methods it will refuse to clear it.
|
||||
clear_fullscreen("sleepblind")
|
||||
clear_fullscreen("disky")
|
||||
if(!has_vision(information_only=TRUE))
|
||||
overlay_fullscreen("blind", /atom/movable/screen/fullscreen/blind)
|
||||
if(sleeping)
|
||||
overlay_fullscreen("sleepblind", /atom/movable/screen/fullscreen/center/blind/sleeping, animated = 2 SECONDS)
|
||||
overlay_fullscreen("disky", /atom/movable/screen/fullscreen/center/blind/disky, animated = 7 SECONDS)
|
||||
throw_alert("blind", /atom/movable/screen/alert/blind)
|
||||
return TRUE
|
||||
overlay_fullscreen("blind", /atom/movable/screen/fullscreen/stretch/blind)
|
||||
throw_alert("blind", /atom/movable/screen/alert/blind)
|
||||
return TRUE
|
||||
else
|
||||
clear_fullscreen("blind")
|
||||
clear_fullscreen("sleepblind")
|
||||
clear_fullscreen("disky")
|
||||
clear_alert("blind")
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/mob/living/update_blurry_effects()
|
||||
var/atom/movable/plane_master_controller/game_plane_master_controller = hud_used?.plane_master_controllers[PLANE_MASTERS_GAME]
|
||||
@@ -19,7 +29,7 @@
|
||||
|
||||
/mob/living/update_druggy_effects()
|
||||
if(AmountDruggy())
|
||||
overlay_fullscreen("high", /atom/movable/screen/fullscreen/high)
|
||||
overlay_fullscreen("high", /atom/movable/screen/fullscreen/stretch/high)
|
||||
throw_alert("high", /atom/movable/screen/alert/high)
|
||||
sound_environment_override = SOUND_ENVIRONMENT_DRUGGED
|
||||
else
|
||||
@@ -29,7 +39,7 @@
|
||||
|
||||
/mob/living/update_nearsighted_effects()
|
||||
if(HAS_TRAIT(src, TRAIT_NEARSIGHT))
|
||||
overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/impaired, 1)
|
||||
overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/stretch/impaired, 1)
|
||||
else
|
||||
clear_fullscreen("nearsighted")
|
||||
|
||||
|
||||
@@ -821,13 +821,11 @@
|
||||
/obj/item/crowbar/cyborg/red,
|
||||
/obj/item/melee/energy/alien/claws,
|
||||
/obj/item/flash/cyborg/alien,
|
||||
/obj/item/reagent_containers/spray/alien/stun,
|
||||
/obj/item/reagent_containers/spray/alien/smoke,
|
||||
)
|
||||
emag_override_modules = list(/obj/item/reagent_containers/spray/alien/acid)
|
||||
special_rechargables = list(
|
||||
/obj/item/reagent_containers/spray/alien/acid,
|
||||
/obj/item/reagent_containers/spray/alien/stun,
|
||||
/obj/item/reagent_containers/spray/alien/smoke
|
||||
)
|
||||
|
||||
|
||||
@@ -447,7 +447,7 @@
|
||||
/mob/living/silicon/get_access()
|
||||
return IGNORE_ACCESS //silicons always have access
|
||||
|
||||
/mob/living/silicon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash/noise)
|
||||
/mob/living/silicon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/stretch/flash/noise)
|
||||
if(affect_silicon)
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -285,12 +285,11 @@
|
||||
back_to_hunt()
|
||||
return
|
||||
|
||||
if(no_handcuffs) // should we not cuff?
|
||||
if(!(iscarbon(target) && target.canBeHandcuffed()))
|
||||
back_to_idle()
|
||||
return
|
||||
|
||||
if(!(iscarbon(target) && target.canBeHandcuffed()))
|
||||
back_to_idle()
|
||||
if(no_handcuffs) // should we not cuff?
|
||||
return
|
||||
|
||||
if(currently_cuffing)
|
||||
|
||||
@@ -347,14 +347,14 @@
|
||||
back_to_hunt()
|
||||
return
|
||||
// target is stunned and nearby
|
||||
if(no_handcuffs) // should we not cuff?
|
||||
back_to_idle()
|
||||
return
|
||||
|
||||
if(!(iscarbon(target) && target.canBeHandcuffed()))
|
||||
back_to_idle()
|
||||
return
|
||||
|
||||
if(no_handcuffs) // should we not cuff?
|
||||
return
|
||||
|
||||
if(currently_cuffing)
|
||||
return
|
||||
|
||||
|
||||
@@ -103,9 +103,21 @@ Difficulty: Hard
|
||||
BL = new /mob/living/simple_animal/hostile/ancient_robot_leg(loc, src, BOTTOM_LEFT)
|
||||
beam = new /obj/effect/abstract(loc)
|
||||
mode = pick(BLUESPACE, GRAV, PYRO, FLUX, VORTEX, CRYO) //picks one of the 6 cores
|
||||
if(mode == FLUX) // Main attack is shock, so flux makes it stronger
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 25
|
||||
switch(mode)
|
||||
if(BLUESPACE)
|
||||
desc += " It emits sparks of blue energy."
|
||||
if(GRAV)
|
||||
desc += " Gravity seems to distort around it."
|
||||
if(PYRO)
|
||||
desc += " You see flames burning around it."
|
||||
if(FLUX) // Main attack is shock, so flux makes it stronger
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 25
|
||||
desc += " It seems to overflow with energy."
|
||||
if(VORTEX)
|
||||
desc += " You see space bend and distort around it."
|
||||
if(CRYO)
|
||||
desc += " The air surrounding it is cold and listless."
|
||||
body_shield()
|
||||
add_overlay("[mode]")
|
||||
add_overlay("eyes")
|
||||
|
||||
@@ -141,7 +141,7 @@ Difficulty: Hard
|
||||
H.apply_status_effect(STATUS_EFFECT_BUBBLEGUM_CURSE, src)
|
||||
if(second_life)
|
||||
H.clear_fullscreen("Bubblegum")
|
||||
H.overlay_fullscreen("Bubblegum", /atom/movable/screen/fullscreen/fog, 2)
|
||||
H.overlay_fullscreen("Bubblegum", /atom/movable/screen/fullscreen/stretch/fog, 2)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/death(gibbed)
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
healths.icon_state = "slime_health7"
|
||||
severity = 6
|
||||
if(severity > 0)
|
||||
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
|
||||
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/stretch/brute, severity)
|
||||
else
|
||||
clear_fullscreen("brute")
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@
|
||||
|
||||
if(updating)
|
||||
update_sight()
|
||||
update_blind_effects()
|
||||
update_blind_effects(TRUE)
|
||||
set_typing_indicator(FALSE)
|
||||
if(hud_used && client)
|
||||
hud_used.show_hud(HUD_STYLE_ACTIONHUD)
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -40,7 +42,9 @@
|
||||
|
||||
if(updating)
|
||||
update_sight()
|
||||
update_blind_effects()
|
||||
update_blind_effects(force_clear_sleeping = TRUE)
|
||||
if(hud_used && client)
|
||||
hud_used.show_hud(HUD_STYLE_STANDARD)
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -1254,7 +1254,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
|
||||
sync_nightvision_screen() //Sync up the overlay used for nightvision to the amount of see_in_dark a mob has. This needs to be called everywhere sync_lighting_plane_alpha() is.
|
||||
|
||||
/mob/proc/sync_nightvision_screen()
|
||||
var/atom/movable/screen/fullscreen/see_through_darkness/S = screens["see_through_darkness"]
|
||||
var/atom/movable/screen/fullscreen/stretch/see_through_darkness/S = screens["see_through_darkness"]
|
||||
if(S)
|
||||
var/suffix = ""
|
||||
switch(see_in_dark)
|
||||
|
||||
@@ -363,8 +363,8 @@
|
||||
if(!Process_Spacemove(get_dir(pulling.loc, A)))
|
||||
return
|
||||
var/target_turf = get_step(pulling, get_dir(pulling.loc, A))
|
||||
if(!Adjacent(target_turf)) //Make sure the turf we are trying to pull to is adjacent to the user.
|
||||
return
|
||||
if(get_dist(target_turf, loc) > 1) // Make sure the turf we are trying to pull to is adjacent to the user.
|
||||
return // We do not use Adjacent() here because it checks if there are dense objects in the way, making it impossible to move an object to the side if we're blocked on both sides.
|
||||
if(ismob(pulling))
|
||||
var/mob/M = pulling
|
||||
var/atom/movable/t = M.pulling
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
/// Overlay we add to each grabbed atom.
|
||||
var/image/kinesis_icon
|
||||
/// Our mouse movement catcher.
|
||||
var/atom/movable/screen/fullscreen/cursor_catcher/kinesis/kinesis_catcher
|
||||
var/atom/movable/screen/fullscreen/stretch/cursor_catcher/kinesis/kinesis_catcher
|
||||
/// The sounds playing while we grabbed an object.
|
||||
var/datum/looping_sound/kinesis/soundloop
|
||||
///The pixel_X of whatever we were grabbing before hand.
|
||||
@@ -83,7 +83,7 @@
|
||||
pre_pixel_x = grabbed_atom.pixel_x
|
||||
pre_pixel_y = grabbed_atom.pixel_y
|
||||
beam.chain = beam.Beam(grabbed_atom, icon_state = "kinesis", icon='icons/effects/beam.dmi', time = 100 SECONDS, maxdistance = 15, beam_type = /obj/effect/ebeam, beam_sleep_time = 3)
|
||||
kinesis_catcher = mod.wearer.overlay_fullscreen("kinesis", /atom/movable/screen/fullscreen/cursor_catcher/kinesis, 0)
|
||||
kinesis_catcher = mod.wearer.overlay_fullscreen("kinesis", /atom/movable/screen/fullscreen/stretch/cursor_catcher/kinesis, 0)
|
||||
kinesis_catcher.assign_to_mob(mod.wearer)
|
||||
soundloop.start()
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
@@ -249,7 +249,7 @@
|
||||
complexity = 0
|
||||
use_power_cost = DEFAULT_CHARGE_DRAIN * 5
|
||||
|
||||
/atom/movable/screen/fullscreen/cursor_catcher/kinesis
|
||||
/atom/movable/screen/fullscreen/stretch/cursor_catcher/kinesis
|
||||
icon = 'icons/mob/screen_kinesis.dmi'
|
||||
icon_state = "kinesis"
|
||||
|
||||
|
||||
@@ -348,7 +348,7 @@
|
||||
if(STAGE_ONE)
|
||||
steps = 1
|
||||
if(STAGE_TWO)
|
||||
steps = 3//Yes this is right
|
||||
steps = 2
|
||||
if(STAGE_THREE)
|
||||
steps = 3
|
||||
if(STAGE_FOUR)
|
||||
|
||||
@@ -323,7 +323,7 @@
|
||||
var/image/causality_field = image(icon, null, "causality_field")
|
||||
add_overlay(causality_field)
|
||||
|
||||
var/speaking = "[emergency_alert] The supermatter has reached critical integrity failure. Emergency causality destabilization field has been activated."
|
||||
var/speaking = "<span class='reallybig'>[emergency_alert] The supermatter has reached critical integrity failure. Emergency causality destabilization field has been activated.</span>"
|
||||
for(var/mob/M in GLOB.player_list) // for all players
|
||||
var/turf/T = get_turf(M)
|
||||
if(istype(T) && atoms_share_level(T, src)) // if the player is on the same zlevel as the SM shared
|
||||
@@ -336,7 +336,7 @@
|
||||
damage = explosion_point - 1 // One point below exploding, so it will re-start the countdown once unfrozen
|
||||
return
|
||||
if(damage < explosion_point) // Cutting it a bit close there engineers
|
||||
radio.autosay("[safe_alert] Failsafe has been disengaged.", name, null)
|
||||
radio.autosay("<span class='big'>[safe_alert] Failsafe has been disengaged.</span>", name, null)
|
||||
cut_overlay(causality_field, TRUE)
|
||||
final_countdown = FALSE
|
||||
remove_filter(list("outline", "icon"))
|
||||
@@ -345,9 +345,9 @@
|
||||
sleep(10)
|
||||
continue
|
||||
else if(i > 50)
|
||||
speaking = "[DisplayTimeText(i, TRUE)] remain before causality stabilization."
|
||||
speaking = "<b>[DisplayTimeText(i, TRUE)] remain before causality stabilization.</b>"
|
||||
else
|
||||
speaking = "[i*0.1]..."
|
||||
speaking = "<span class='reallybig'>[i * 0.1]...</span>"
|
||||
radio.autosay(speaking, name, null)
|
||||
sleep(10)
|
||||
|
||||
@@ -648,27 +648,27 @@
|
||||
|
||||
//Oh shit it's bad, time to freak out
|
||||
if(damage > emergency_point)
|
||||
radio.autosay("[emergency_alert] Integrity: [get_integrity()]%", name, null)
|
||||
radio.autosay("<span class='big'>[emergency_alert] Integrity: [get_integrity()]%</span>", name, null)
|
||||
lastwarning = REALTIMEOFDAY
|
||||
if(!has_reached_emergency)
|
||||
investigate_log("has reached the emergency point for the first time.", "supermatter")
|
||||
message_admins("[src] has reached the emergency point [ADMIN_JMP(src)].")
|
||||
has_reached_emergency = TRUE
|
||||
else if(damage >= damage_archived) // The damage is still going up
|
||||
radio.autosay("[warning_alert] Integrity: [get_integrity()]%", name, "Engineering")
|
||||
radio.autosay("<b>[warning_alert] Integrity: [get_integrity()]%</b>", name, "Engineering")
|
||||
lastwarning = REALTIMEOFDAY - (WARNING_DELAY * 5)
|
||||
|
||||
else // Phew, we're safe
|
||||
radio.autosay("[safe_alert] Integrity: [get_integrity()]%", name, "Engineering")
|
||||
radio.autosay("<b>[safe_alert] Integrity: [get_integrity()]%</b>", name, "Engineering")
|
||||
lastwarning = REALTIMEOFDAY
|
||||
|
||||
if(power > POWER_PENALTY_THRESHOLD)
|
||||
radio.autosay("Warning: Hyperstructure has reached dangerous power level.", name, "Engineering")
|
||||
radio.autosay("<b>Warning: Hyperstructure has reached dangerous power level.</b>", name, "Engineering")
|
||||
if(powerloss_inhibitor < 0.5)
|
||||
radio.autosay("DANGER: CHARGE INERTIA CHAIN REACTION IN PROGRESS.", name, "Engineering")
|
||||
radio.autosay("<b>DANGER: CHARGE INERTIA CHAIN REACTION IN PROGRESS.</b>", name, "Engineering")
|
||||
|
||||
if(combined_gas > MOLE_CRUNCH_THRESHOLD)
|
||||
radio.autosay("Warning: Critical coolant mass reached.", name, "Engineering")
|
||||
radio.autosay("<b>Warning: Critical coolant mass reached.</b>", name, "Engineering")
|
||||
//Boom (Mind blown)
|
||||
if(damage > explosion_point)
|
||||
countdown()
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
return
|
||||
|
||||
/datum/supermatter_event/proc/on_end()
|
||||
sm_radio_say("Anomalous crystal activity has ended.")
|
||||
sm_radio_say("<b>Anomalous crystal activity has ended.</b>")
|
||||
supermatter.heat_penalty_threshold = SUPERMATTER_HEAT_PENALTY_THRESHOLD
|
||||
supermatter.gas_multiplier = 1
|
||||
supermatter.power_additive = 0
|
||||
@@ -120,7 +120,7 @@
|
||||
duration = 1 MINUTES
|
||||
|
||||
/datum/supermatter_event/bravo_tier/alert_engi()
|
||||
sm_radio_say("Anomalous crystal activity detected! Activity class: [name]. Operator intervention is required!")
|
||||
sm_radio_say("<b>Anomalous crystal activity detected! Activity class: [name]. Operator intervention is required!</b>")
|
||||
|
||||
|
||||
// more gas
|
||||
@@ -150,7 +150,7 @@
|
||||
duration = 10 SECONDS
|
||||
|
||||
/datum/supermatter_event/alpha_tier/alert_engi()
|
||||
sm_radio_say("ALERT: Critical anomalous crystal activity detected! Activity class: [name]. IMMEDIATE Operator intervention is REQUIRED!")
|
||||
sm_radio_say("<span class='big'>ALERT: Critical anomalous crystal activity detected! Activity class: [name]. IMMEDIATE Operator intervention is REQUIRED!</span>")
|
||||
|
||||
/datum/supermatter_event/alpha_tier/apc_short
|
||||
name = "A-1"
|
||||
@@ -181,16 +181,16 @@
|
||||
duration = 7 MINUTES // 2 MINUTES of s-tier anomaly
|
||||
|
||||
/datum/supermatter_event/sierra_tier/alert_engi()
|
||||
general_radio_say("ALERT: Anomalous supermatter state expected in: 5 minutes.")
|
||||
sm_radio_say("EMERGENCY ALERT: 5 MINUTES UNTIL [supermatter] EXHIBITS [name] CLASS ANOMALOUS ACTIVITY!")
|
||||
general_radio_say("<span class='big'>ALERT: Anomalous supermatter state expected in: 5 minutes.</span>")
|
||||
sm_radio_say("<span class='reallybig'>EMERGENCY ALERT: 5 MINUTES UNTIL [supermatter] EXHIBITS [name] CLASS ANOMALOUS ACTIVITY!</span>")
|
||||
|
||||
/datum/supermatter_event/sierra_tier/on_start()
|
||||
addtimer(CALLBACK(src, PROC_REF(start_sierra_event)), 5 MINUTES)
|
||||
supermatter.has_run_sclass = TRUE
|
||||
|
||||
/datum/supermatter_event/sierra_tier/proc/start_sierra_event()
|
||||
general_radio_say("ALERT: ANOMALOUS SUPERMATTER STATE DETECTED!")
|
||||
sm_radio_say("EMERGENCY ALERT: Class [name] anomalous behavior in progress!")
|
||||
general_radio_say("<span class='big'>ALERT: ANOMALOUS SUPERMATTER STATE DETECTED!</span>")
|
||||
sm_radio_say("<span class='reallybig'>EMERGENCY ALERT: Class [name] anomalous behavior in progress!</span>")
|
||||
|
||||
//S class events
|
||||
//Arc-type
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
var/temp_html = ""
|
||||
var/printing = null
|
||||
var/wait = null
|
||||
var/selected_strain_index = 1
|
||||
var/obj/item/reagent_containers/beaker = null
|
||||
|
||||
/obj/machinery/computer/pandemic/Initialize(mapload)
|
||||
@@ -26,23 +27,33 @@
|
||||
stat |= BROKEN
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/computer/pandemic/proc/GetVirusByIndex(index)
|
||||
/obj/machinery/computer/pandemic/proc/GetViruses()
|
||||
if(beaker && beaker.reagents)
|
||||
if(length(beaker.reagents.reagent_list))
|
||||
var/datum/reagent/blood/BL = locate() in beaker.reagents.reagent_list
|
||||
if(BL)
|
||||
if(BL.data && BL.data["viruses"])
|
||||
var/list/viruses = BL.data["viruses"]
|
||||
return viruses[index]
|
||||
return viruses
|
||||
|
||||
/obj/machinery/computer/pandemic/proc/GetResistancesByIndex(index)
|
||||
/obj/machinery/computer/pandemic/proc/GetVirusByIndex(index)
|
||||
var/list/viruses = GetViruses()
|
||||
if(viruses && index > 0 && index <= length(viruses))
|
||||
return viruses[index]
|
||||
|
||||
/obj/machinery/computer/pandemic/proc/GetResistances()
|
||||
if(beaker && beaker.reagents)
|
||||
if(length(beaker.reagents.reagent_list))
|
||||
var/datum/reagent/blood/BL = locate() in beaker.reagents.reagent_list
|
||||
if(BL)
|
||||
if(BL.data && BL.data["resistances"])
|
||||
var/list/resistances = BL.data["resistances"]
|
||||
return resistances[index]
|
||||
return resistances
|
||||
|
||||
/obj/machinery/computer/pandemic/proc/GetResistancesByIndex(index)
|
||||
var/list/resistances = GetResistances()
|
||||
if(resistances && index > 0 && index <= length(resistances))
|
||||
return resistances[index]
|
||||
|
||||
/obj/machinery/computer/pandemic/proc/GetVirusTypeByIndex(index)
|
||||
var/datum/disease/D = GetVirusByIndex(index)
|
||||
@@ -68,117 +79,233 @@
|
||||
if(!wait)
|
||||
. += "waitlight"
|
||||
|
||||
/obj/machinery/computer/pandemic/Topic(href, href_list)
|
||||
/obj/machinery/computer/pandemic/proc/create_culture(name, bottle_type = "culture", cooldown = 50)
|
||||
var/obj/item/reagent_containers/glass/bottle/B = new/obj/item/reagent_containers/glass/bottle(loc)
|
||||
B.icon_state = "round_bottle"
|
||||
B.pixel_x = rand(-3, 3)
|
||||
B.pixel_y = rand(-3, 3)
|
||||
replicator_cooldown(cooldown)
|
||||
B.name = "[name] [bottle_type] bottle"
|
||||
return B
|
||||
|
||||
/obj/machinery/computer/pandemic/ui_act(action, params, datum/tgui/ui, datum/ui_state/state)
|
||||
if(..())
|
||||
return
|
||||
|
||||
usr.set_machine(src)
|
||||
if(!beaker) return
|
||||
|
||||
if(href_list["create_vaccine"])
|
||||
if(!wait)
|
||||
var/obj/item/reagent_containers/glass/bottle/B = new/obj/item/reagent_containers/glass/bottle(loc)
|
||||
if(B)
|
||||
B.pixel_x = rand(-3, 3)
|
||||
B.pixel_y = rand(-3, 3)
|
||||
var/path = GetResistancesByIndex(text2num(href_list["create_vaccine"]))
|
||||
var/vaccine_type = path
|
||||
var/vaccine_name = "Unknown"
|
||||
|
||||
if(!ispath(vaccine_type))
|
||||
if(GLOB.archive_diseases[path])
|
||||
var/datum/disease/D = GLOB.archive_diseases[path]
|
||||
if(D)
|
||||
vaccine_name = D.name
|
||||
vaccine_type = path
|
||||
else if(vaccine_type)
|
||||
var/datum/disease/D = new vaccine_type(0, null)
|
||||
if(D)
|
||||
vaccine_name = D.name
|
||||
|
||||
if(vaccine_type)
|
||||
|
||||
B.name = "[vaccine_name] vaccine bottle"
|
||||
B.reagents.add_reagent("vaccine", 15, list(vaccine_type))
|
||||
replicator_cooldown(200)
|
||||
else
|
||||
temp_html = "The replicator is not ready yet."
|
||||
updateUsrDialog()
|
||||
if(inoperable())
|
||||
return
|
||||
else if(href_list["create_virus_culture"])
|
||||
if(!wait)
|
||||
var/type = GetVirusTypeByIndex(text2num(href_list["create_virus_culture"]))//the path is received as string - converting
|
||||
|
||||
|
||||
. = TRUE
|
||||
|
||||
switch(action)
|
||||
if("clone_strain")
|
||||
if(wait)
|
||||
atom_say("The replicator is not ready yet.")
|
||||
return
|
||||
|
||||
var/strain_index = text2num(params["strain_index"])
|
||||
if(isnull(strain_index))
|
||||
atom_say("Unable to respond to command.")
|
||||
return
|
||||
var/datum/disease/virus = GetVirusByIndex(strain_index)
|
||||
var/datum/disease/D = null
|
||||
if(!virus)
|
||||
atom_say("Unable to find requested strain.")
|
||||
return
|
||||
var/type = virus.GetDiseaseID()
|
||||
if(!ispath(type))
|
||||
D = GetVirusByIndex(text2num(href_list["create_virus_culture"]))
|
||||
var/datum/disease/advance/A = GLOB.archive_diseases[D.GetDiseaseID()]
|
||||
var/datum/disease/advance/A = GLOB.archive_diseases[type]
|
||||
if(A)
|
||||
D = new A.type(0, A)
|
||||
else if(type)
|
||||
if(type in GLOB.diseases) // Make sure this is a disease
|
||||
D = new type(0, null)
|
||||
if(!D)
|
||||
atom_say("Unable to synthesize requested strain.")
|
||||
return
|
||||
var/name = tgui_input_text(usr, "Name:", "Name the culture", D.name, MAX_NAME_LEN)
|
||||
var/default_name = ""
|
||||
if(D.name == "Unknown" || D.name == "")
|
||||
default_name = replacetext(beaker.name, new/regex(" culture bottle\\Z", "g"), "")
|
||||
else
|
||||
default_name = D.name
|
||||
var/name = tgui_input_text(usr, "Name:", "Name the culture", default_name, MAX_NAME_LEN)
|
||||
if(name == null || wait)
|
||||
return
|
||||
var/obj/item/reagent_containers/glass/bottle/B = new/obj/item/reagent_containers/glass/bottle(loc)
|
||||
B.icon_state = "round_bottle"
|
||||
B.pixel_x = rand(-3, 3)
|
||||
B.pixel_y = rand(-3, 3)
|
||||
replicator_cooldown(50)
|
||||
var/list/data = list("viruses"=list(D))
|
||||
B.name = "[name] culture bottle"
|
||||
var/obj/item/reagent_containers/glass/bottle/B = create_culture(name)
|
||||
B.desc = "A small bottle. Contains [D.agent] culture in synthblood medium."
|
||||
B.reagents.add_reagent("blood",20,data)
|
||||
updateUsrDialog()
|
||||
else
|
||||
temp_html = "The replicator is not ready yet."
|
||||
updateUsrDialog()
|
||||
return
|
||||
else if(href_list["empty_beaker"])
|
||||
beaker.reagents.clear_reagents()
|
||||
eject_beaker()
|
||||
updateUsrDialog()
|
||||
return
|
||||
else if(href_list["eject"])
|
||||
eject_beaker()
|
||||
updateUsrDialog()
|
||||
return
|
||||
else if(href_list["clear"])
|
||||
temp_html = ""
|
||||
updateUsrDialog()
|
||||
return
|
||||
else if(href_list["name_disease"])
|
||||
var/new_name = tgui_input_text(usr, "Name the Disease", "New Name", max_length = MAX_NAME_LEN)
|
||||
if(!new_name)
|
||||
return
|
||||
if(..())
|
||||
return
|
||||
var/id = GetVirusTypeByIndex(text2num(href_list["name_disease"]))
|
||||
if(GLOB.archive_diseases[id])
|
||||
var/datum/disease/advance/A = GLOB.archive_diseases[id]
|
||||
B.reagents.add_reagent("blood", 20, list("viruses" = list(D)))
|
||||
if("clone_vaccine")
|
||||
if(wait)
|
||||
atom_say("The replicator is not ready yet.")
|
||||
return
|
||||
|
||||
var/resistance_index = text2num(params["resistance_index"])
|
||||
if(isnull(resistance_index))
|
||||
atom_say("Unable to find requested antibody.")
|
||||
return
|
||||
var/vaccine_type = GetResistancesByIndex(resistance_index)
|
||||
var/vaccine_name = "Unknown"
|
||||
if(!ispath(vaccine_type))
|
||||
if(GLOB.archive_diseases[vaccine_type])
|
||||
var/datum/disease/D = GLOB.archive_diseases[vaccine_type]
|
||||
if(D)
|
||||
vaccine_name = D.name
|
||||
else if(vaccine_type)
|
||||
var/datum/disease/D = new vaccine_type(0, null)
|
||||
if(D)
|
||||
vaccine_name = D.name
|
||||
|
||||
if(!vaccine_type)
|
||||
atom_say("Unable to synthesize requested antibody.")
|
||||
return
|
||||
|
||||
var/obj/item/reagent_containers/glass/bottle/B = create_culture(vaccine_name, "vaccine", 200)
|
||||
B.reagents.add_reagent("vaccine", 15, list(vaccine_type))
|
||||
if("eject_beaker")
|
||||
eject_beaker()
|
||||
if("destroy_eject_beaker")
|
||||
beaker.reagents.clear_reagents()
|
||||
eject_beaker()
|
||||
if("print_release_forms")
|
||||
var/strain_index = text2num(params["strain_index"])
|
||||
if(isnull(strain_index))
|
||||
atom_say("Unable to respond to command.")
|
||||
return
|
||||
var/type = GetVirusTypeByIndex(strain_index)
|
||||
if(!type)
|
||||
atom_say("Unable to find requested strain.")
|
||||
return
|
||||
var/datum/disease/advance/A = GLOB.archive_diseases[type]
|
||||
if(!A)
|
||||
atom_say("Unable to find requested strain.")
|
||||
return
|
||||
print_form(A, usr)
|
||||
if("name_strain")
|
||||
var/strain_index = text2num(params["strain_index"])
|
||||
if(isnull(strain_index))
|
||||
atom_say("Unable to respond to command.")
|
||||
return
|
||||
var/type = GetVirusTypeByIndex(strain_index)
|
||||
if(!type)
|
||||
atom_say("Unable to find requested strain.")
|
||||
return
|
||||
var/datum/disease/advance/A = GLOB.archive_diseases[type]
|
||||
if(!A)
|
||||
atom_say("Unable to find requested strain.")
|
||||
return
|
||||
if(A.name != "Unknown")
|
||||
atom_say("Request rejected. Strain already has a name.")
|
||||
return
|
||||
var/new_name = tgui_input_text(usr, "Name the Strain", "New Name", max_length = MAX_NAME_LEN)
|
||||
if(!new_name)
|
||||
return
|
||||
A.AssignName(new_name)
|
||||
for(var/datum/disease/advance/AD in GLOB.active_diseases)
|
||||
AD.Refresh()
|
||||
updateUsrDialog()
|
||||
else if(href_list["print_form"])
|
||||
var/datum/disease/D = GetVirusByIndex(text2num(href_list["print_form"]))
|
||||
D = GLOB.archive_diseases[D.GetDiseaseID()]//We know it's advanced no need to check
|
||||
print_form(D, usr)
|
||||
if("switch_strain")
|
||||
var/strain_index = text2num(params["strain_index"])
|
||||
if(isnull(strain_index) || strain_index < 1)
|
||||
atom_say("Unable to respond to command.")
|
||||
return
|
||||
var/list/viruses = GetViruses()
|
||||
if(strain_index > length(viruses))
|
||||
atom_say("Unable to find requested strain.")
|
||||
return
|
||||
selected_strain_index = strain_index;
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/computer/pandemic/ui_state(mob/user)
|
||||
return GLOB.default_state
|
||||
|
||||
else
|
||||
usr << browse(null, "window=pandemic")
|
||||
updateUsrDialog()
|
||||
return
|
||||
/obj/machinery/computer/pandemic/ui_interact(mob/user, datum/tgui/ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "PanDEMIC", name)
|
||||
ui.open()
|
||||
|
||||
add_fingerprint(usr)
|
||||
/obj/machinery/computer/pandemic/ui_data(mob/user)
|
||||
var/datum/reagent/blood/Blood = null
|
||||
if(beaker)
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
for(var/datum/reagent/blood/B in R.reagent_list)
|
||||
if(B)
|
||||
Blood = B
|
||||
break
|
||||
|
||||
var/list/data = list(
|
||||
"synthesisCooldown" = wait ? TRUE : FALSE,
|
||||
"beakerLoaded" = beaker ? TRUE : FALSE,
|
||||
"beakerContainsBlood" = Blood ? TRUE : FALSE,
|
||||
"beakerContainsVirus" = length(Blood?.data["viruses"]) != 0,
|
||||
"selectedStrainIndex" = selected_strain_index,
|
||||
)
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/pandemic/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
. = data
|
||||
|
||||
var/datum/reagent/blood/Blood = null
|
||||
if(beaker)
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
for(var/datum/reagent/blood/B in R.reagent_list)
|
||||
if(B)
|
||||
Blood = B
|
||||
break
|
||||
|
||||
var/list/strains = list()
|
||||
for(var/datum/disease/D in GetViruses())
|
||||
if(D.visibility_flags & HIDDEN_PANDEMIC)
|
||||
continue
|
||||
|
||||
var/list/symptoms = list()
|
||||
if(istype(D, /datum/disease/advance))
|
||||
var/datum/disease/advance/A = D
|
||||
D = GLOB.archive_diseases[A.GetDiseaseID()]
|
||||
if(!D)
|
||||
CRASH("We weren't able to get the advance disease from the archive.")
|
||||
for(var/datum/symptom/S in A.symptoms)
|
||||
symptoms += list(list(
|
||||
"name" = S.name,
|
||||
"stealth" = S.stealth,
|
||||
"resistance" = S.resistance,
|
||||
"stageSpeed" = S.stage_speed,
|
||||
"transmissibility" = S.transmittable,
|
||||
"complexity" = S.level,
|
||||
))
|
||||
|
||||
strains += list(list(
|
||||
"commonName" = D.name,
|
||||
"description" = D.desc,
|
||||
"bloodDNA" = Blood.data["blood_DNA"],
|
||||
"bloodType" = Blood.data["blood_type"],
|
||||
"diseaseAgent" = D.agent,
|
||||
"possibleTreatments" = D.cure_text,
|
||||
"transmissionRoute" = D.spread_text,
|
||||
"symptoms" = symptoms,
|
||||
"isAdvanced" = istype(D, /datum/disease/advance),
|
||||
))
|
||||
data["strains"] = strains
|
||||
|
||||
var/list/resistances = list()
|
||||
for(var/resistance in GetResistances())
|
||||
if(!ispath(resistance))
|
||||
var/datum/disease/D = GLOB.archive_diseases[resistance]
|
||||
if(D)
|
||||
resistances += list(D.name)
|
||||
else if(resistance)
|
||||
var/datum/disease/D = new resistance(0, null)
|
||||
if(D)
|
||||
resistances += list(D.name)
|
||||
data["resistances"] = resistances
|
||||
|
||||
/obj/machinery/computer/pandemic/proc/eject_beaker()
|
||||
beaker.forceMove(loc)
|
||||
beaker = null
|
||||
icon_state = "pandemic0"
|
||||
selected_strain_index = 1
|
||||
|
||||
//Prints a nice virus release form. Props to Urbanliner for the layout
|
||||
/obj/machinery/computer/pandemic/proc/print_form(datum/disease/advance/D, mob/living/user)
|
||||
@@ -241,108 +368,16 @@
|
||||
P.info = info_text.Join("")
|
||||
P.update_icon()
|
||||
|
||||
/obj/machinery/computer/pandemic/attack_ai(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/pandemic/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/dat = ""
|
||||
if(temp_html)
|
||||
dat = "[temp_html]<BR><BR><A href='byond://?src=[UID()];clear=1'>Main Menu</A>"
|
||||
else if(!beaker)
|
||||
dat += "Please insert beaker.<BR>"
|
||||
dat += "<A href='byond://?src=[user.UID()];mach_close=pandemic'>Close</A>"
|
||||
else
|
||||
var/datum/reagents/R = beaker.reagents
|
||||
var/datum/reagent/blood/Blood = null
|
||||
for(var/datum/reagent/blood/B in R.reagent_list)
|
||||
if(B)
|
||||
Blood = B
|
||||
break
|
||||
if(!R.total_volume||!length(R.reagent_list))
|
||||
dat += "The beaker is empty<BR>"
|
||||
else if(!Blood)
|
||||
dat += "No blood sample found in beaker."
|
||||
else if(!Blood.data)
|
||||
dat += "No blood data found in beaker."
|
||||
else
|
||||
dat += "<h3>Blood sample data:</h3>"
|
||||
dat += "<b>Blood DNA:</b> [(Blood.data["blood_DNA"]||"none")]<BR>"
|
||||
dat += "<b>Blood Type:</b> [(Blood.data["blood_type"]||"none")]<BR>"
|
||||
|
||||
|
||||
if(Blood.data["viruses"])
|
||||
var/list/vir = Blood.data["viruses"]
|
||||
if(length(vir))
|
||||
var/i = 0
|
||||
for(var/thing in Blood.data["viruses"])
|
||||
var/datum/disease/D = thing
|
||||
i++
|
||||
if(!(D.visibility_flags & HIDDEN_PANDEMIC))
|
||||
|
||||
if(istype(D, /datum/disease/advance))
|
||||
|
||||
var/datum/disease/advance/A = D
|
||||
D = GLOB.archive_diseases[A.GetDiseaseID()]
|
||||
if(D)
|
||||
if(D.name == "Unknown")
|
||||
dat += "<b><a href='byond://?src=[UID()];name_disease=[i]'>Name Disease</a></b><BR>"
|
||||
else
|
||||
dat += "<b><a href='byond://?src=[UID()];print_form=[i]'>Print release form</a></b><BR>"
|
||||
|
||||
if(!D)
|
||||
CRASH("We weren't able to get the advance disease from the archive.")
|
||||
|
||||
dat += "<b>Disease Agent:</b> [D?"[D.agent] - <A href='byond://?src=[UID()];create_virus_culture=[i]'>Create virus culture bottle</A>":"none"]<BR>"
|
||||
dat += "<b>Common name:</b> [(D.name||"none")]<BR>"
|
||||
dat += "<b>Description: </b> [(D.desc||"none")]<BR>"
|
||||
dat += "<b>Spread:</b> [(D.spread_text||"none")]<BR>"
|
||||
dat += "<b>Possible cure:</b> [(D.cure_text||"none")]<BR><BR>"
|
||||
|
||||
if(istype(D, /datum/disease/advance))
|
||||
var/datum/disease/advance/A = D
|
||||
dat += "<b>Symptoms:</b> "
|
||||
var/english_symptoms = list()
|
||||
for(var/datum/symptom/S in A.symptoms)
|
||||
english_symptoms += S.name
|
||||
dat += english_list(english_symptoms)
|
||||
|
||||
else
|
||||
dat += "No detectable virus in the sample."
|
||||
else
|
||||
dat += "No detectable virus in the sample."
|
||||
|
||||
dat += "<BR><b>Contains antibodies to:</b> "
|
||||
if(Blood.data["resistances"])
|
||||
var/list/res = Blood.data["resistances"]
|
||||
if(length(res))
|
||||
dat += "<ul>"
|
||||
var/i = 0
|
||||
for(var/type in Blood.data["resistances"])
|
||||
i++
|
||||
var/disease_name = "Unknown"
|
||||
|
||||
if(!ispath(type))
|
||||
var/datum/disease/advance/A = GLOB.archive_diseases[type]
|
||||
if(A)
|
||||
disease_name = A.name
|
||||
else
|
||||
var/datum/disease/D = new type(0, null)
|
||||
disease_name = D.name
|
||||
|
||||
dat += "<li>[disease_name] - <A href='byond://?src=[UID()];create_vaccine=[i]'>Create vaccine bottle</A></li>"
|
||||
dat += "</ul><BR>"
|
||||
else
|
||||
dat += "nothing<BR>"
|
||||
else
|
||||
dat += "nothing<BR>"
|
||||
dat += "<BR><A href='byond://?src=[UID()];eject=1'>Eject beaker</A>[((R.total_volume&&length(R.reagent_list)) ? "-- <A href='byond://?src=[UID()];empty_beaker=1'>Empty and eject beaker</A>":"")]<BR>"
|
||||
dat += "<A href='byond://?src=[user.UID()];mach_close=pandemic'>Close</A>"
|
||||
|
||||
var/datum/browser/popup = new(user, "pandemic", name, 575, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open(0)
|
||||
onclose(user, "pandemic")
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/pandemic/attack_ghost(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params)
|
||||
if(default_unfasten_wrench(user, I, time = 4 SECONDS))
|
||||
@@ -361,6 +396,7 @@
|
||||
beaker.loc = src
|
||||
to_chat(user, "<span class='notice'>You add the beaker to the machine.</span>")
|
||||
updateUsrDialog()
|
||||
SStgui.update_uis(src, TRUE)
|
||||
icon_state = "pandemic1"
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -545,7 +545,7 @@
|
||||
|
||||
/obj/machinery/disposal/get_remote_view_fullscreens(mob/user)
|
||||
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 2)
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/stretch/impaired, 2)
|
||||
|
||||
/obj/machinery/disposal/force_eject_occupant(mob/target)
|
||||
target.forceMove(get_turf(src))
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/obj/item/whiteship_port_generator
|
||||
name = "docking area signaller"
|
||||
desc = "A signaling device for the NT expeditionary vessel, used to designate new docking areas."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "gangtool-white"
|
||||
|
||||
var/list/placed_docks = list()
|
||||
var/max_docks = 3
|
||||
|
||||
/obj/item/whiteship_port_generator/examine(mob/user)
|
||||
. = ..()
|
||||
var/count = max_docks - length(placed_docks)
|
||||
var/plural = count > 1
|
||||
. += "There [plural ? "are" : "is"] [count] use[plural ? "s" : ""] left."
|
||||
|
||||
/obj/item/whiteship_port_generator/attack_self(mob/living/user)
|
||||
if(is_station_level(user.z))
|
||||
log_admin("[key_name(user)] attempted to create a whiteship dock in the station's sector at [COORD(user)].")
|
||||
to_chat(user, "<span class='notice'>New docking areas cannot be designated within the station's sector!</span>")
|
||||
return
|
||||
|
||||
if(is_admin_level(user.z))
|
||||
log_admin("[key_name(user)] attempted to create a whiteship dock on Centcomm level at [COORD(user)].")
|
||||
to_chat(user, "<span class='notice'>New docking areas cannot be designated in this sector!</span>")
|
||||
return
|
||||
|
||||
if(is_mining_level(user.z))
|
||||
log_admin("[key_name(user)] attempted to create a whiteship dock on Lavaland at [COORD(user)].")
|
||||
to_chat(user, "<span class='notice'>New docking areas cannot be designated planet side!</span>")
|
||||
return
|
||||
|
||||
for(var/obj/placed_dock in placed_docks)
|
||||
if(placed_dock.z == user.z)
|
||||
to_chat(user, "<span class='notice'>A docking area has already been placed in this sector!</span>")
|
||||
return
|
||||
|
||||
var/list/dir_choices = list("North" = NORTH, "East" = EAST, "South" = SOUTH, "West" = WEST)
|
||||
var/dir_choice = tgui_input_list(user, "Select the new docking area orientation.", "Dock Orientation", dir_choices)
|
||||
if(!dir_choice)
|
||||
return
|
||||
|
||||
var/dest_dir = dir_choices[dir_choice]
|
||||
var/turf/destination = get_step(user.loc, dest_dir)
|
||||
var/obj/docking_port/stationary/whiteship/port = new(destination)
|
||||
port.dir = dest_dir
|
||||
|
||||
var/min_x = -1
|
||||
var/min_y = -1
|
||||
var/max_x = -1
|
||||
var/max_y = -1
|
||||
|
||||
var/list/ordered_turfs = port.return_ordered_turfs()
|
||||
for(var/turf/T in ordered_turfs)
|
||||
min_x = min_x < 0 ? T.x : min(min_x, T.x)
|
||||
min_y = min_y < 0 ? T.y : min(min_y, T.y)
|
||||
max_x = max_x < 0 ? T.x : max(max_x, T.x)
|
||||
max_y = max_y < 0 ? T.y : max(max_y, T.y)
|
||||
if(!isspaceturf(T))
|
||||
to_chat(user, "<span class='notice'>Obstruction found in docking space area, aborting!</span>")
|
||||
qdel(port, force = TRUE)
|
||||
return
|
||||
for(var/obj/O in T.contents)
|
||||
if(O == port)
|
||||
continue
|
||||
else
|
||||
to_chat(user, "<span class='notice'>Objects found in docking space area, aborting!</span>")
|
||||
qdel(port, force = TRUE)
|
||||
return
|
||||
|
||||
if(min_x <= TRANSITION_BORDER_WEST + 1 || max_x >= TRANSITION_BORDER_EAST - 1)
|
||||
to_chat(user, "<span class='notice'>Docking space area too close to edge of sector, aborting!</span>")
|
||||
qdel(port, force = TRUE)
|
||||
return
|
||||
if(min_y <= TRANSITION_BORDER_SOUTH + 1 || max_y >= TRANSITION_BORDER_NORTH - 1)
|
||||
to_chat(user, "<span class='notice'>Docking space area too close to edge of sector, aborting!</span>")
|
||||
qdel(port, force = TRUE)
|
||||
return
|
||||
|
||||
placed_docks += port
|
||||
var/dock_count = length(placed_docks)
|
||||
|
||||
var/basename = "Custom Dock #[dock_count]"
|
||||
var/name = tgui_input_text(user,
|
||||
message = "Select the new docking area name.",
|
||||
title = "New Dock Name",
|
||||
default = basename,
|
||||
max_length = 20
|
||||
)
|
||||
port.name = name ? name : basename
|
||||
port.id = "whiteship_custom_[dock_count]"
|
||||
port.register()
|
||||
|
||||
for(var/obj/machinery/computer/shuttle/white_ship/S in GLOB.machines)
|
||||
S.possible_destinations = null
|
||||
S.connect()
|
||||
|
||||
log_admin("[key_name(user)] created a whiteship dock named '[name]' at [COORD(port)].")
|
||||
|
||||
if(dock_count < max_docks)
|
||||
to_chat(user, "<span class='info'>Landing zone set.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='info'>Landing zone set. The signaller vanishes!</span>")
|
||||
qdel(src)
|
||||
@@ -98,10 +98,12 @@
|
||||
SSticker.mode.secondary_goals -= src
|
||||
message_admins("[key_name_admin(usr)] removed secondary goal [src] ([admin_desc])")
|
||||
log_admin("[key_name_admin(usr)] removed secondary goal [src] ([admin_desc])")
|
||||
tracker.unregister(SSshuttle.supply)
|
||||
qdel(src)
|
||||
usr.client.modify_goals()
|
||||
else if(href_list["mark_complete"])
|
||||
completed = 1
|
||||
tracker.unregister(SSshuttle.supply)
|
||||
usr.client.modify_goals()
|
||||
message_admins("[key_name_admin(usr)] marked secondary goal [src] ([admin_desc]) as complete")
|
||||
log_admin("[key_name_admin(usr)] marked secondary goal [src] ([admin_desc]) as complete")
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
var/datum/secondary_goal_progress/real_progress
|
||||
var/datum/secondary_goal_progress/temporary_progress
|
||||
var/datum/station_goal/secondary/goal
|
||||
var/registered = FALSE
|
||||
|
||||
/datum/secondary_goal_tracker/New(datum/station_goal/secondary/goal_in, datum/secondary_goal_progress/progress)
|
||||
goal = goal_in
|
||||
@@ -11,6 +12,8 @@
|
||||
/datum/secondary_goal_tracker/proc/reset()
|
||||
real_progress = new real_progress.type(goal)
|
||||
temporary_progress = real_progress.Copy()
|
||||
if(!registered)
|
||||
register(SSshuttle.supply)
|
||||
|
||||
/datum/secondary_goal_tracker/proc/register(shuttle)
|
||||
RegisterSignal(shuttle, COMSIG_CARGO_BEGIN_SCAN, PROC_REF(reset_tempporary_progress))
|
||||
@@ -19,6 +22,7 @@
|
||||
RegisterSignal(shuttle, COMSIG_CARGO_DO_PRIORITY_SELL, PROC_REF(update_progress))
|
||||
RegisterSignal(shuttle, COMSIG_CARGO_SEND_ERROR, PROC_REF(update_progress))
|
||||
RegisterSignal(shuttle, COMSIG_CARGO_END_SELL, PROC_REF(check_for_completion))
|
||||
registered = TRUE
|
||||
|
||||
/datum/secondary_goal_tracker/proc/unregister(shuttle)
|
||||
UnregisterSignal(shuttle, COMSIG_CARGO_BEGIN_SCAN)
|
||||
@@ -27,6 +31,7 @@
|
||||
UnregisterSignal(shuttle, COMSIG_CARGO_DO_PRIORITY_SELL)
|
||||
UnregisterSignal(shuttle, COMSIG_CARGO_SEND_ERROR)
|
||||
UnregisterSignal(shuttle, COMSIG_CARGO_END_SELL)
|
||||
registered = FALSE
|
||||
|
||||
// Resets the temporary porgress to match the real progress.
|
||||
/datum/secondary_goal_tracker/proc/reset_tempporary_progress(obj/docking_port/mobile/supply/shuttle)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 74 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 22 KiB |
@@ -2713,6 +2713,7 @@
|
||||
#include "code\modules\server_commands\servermsg.dm"
|
||||
#include "code\modules\server_commands\commands\newroundannounce.dm"
|
||||
#include "code\modules\shuttle\assault_pod.dm"
|
||||
#include "code\modules\shuttle\dock_generator.dm"
|
||||
#include "code\modules\shuttle\emergency.dm"
|
||||
#include "code\modules\shuttle\ert_shuttle.dm"
|
||||
#include "code\modules\shuttle\navigation_computer.dm"
|
||||
|
||||
@@ -24,10 +24,11 @@ export const computeFlexClassName = (props: FlexProps) => {
|
||||
};
|
||||
|
||||
export const computeFlexProps = (props: FlexProps) => {
|
||||
const { className, direction, wrap, align, justify, inline, ...rest } = props;
|
||||
const { className, direction, wrap, align, justify, inline, style, ...rest } =
|
||||
props;
|
||||
return computeBoxProps({
|
||||
style: {
|
||||
...rest.style,
|
||||
...style,
|
||||
'flex-direction': direction,
|
||||
'flex-wrap': wrap === true ? 'wrap' : wrap,
|
||||
'align-items': align,
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
import { BooleanLike } from '../../common/react';
|
||||
import { InfernoNode } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import {
|
||||
Button,
|
||||
Flex,
|
||||
LabeledList,
|
||||
Section,
|
||||
Stack,
|
||||
Table,
|
||||
Tabs,
|
||||
} from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
interface PathogenSymptom {
|
||||
name: string;
|
||||
stealth: number;
|
||||
resistance: number;
|
||||
stageSpeed: number;
|
||||
transmissibility: number;
|
||||
}
|
||||
|
||||
interface PathogenStrain {
|
||||
commonName?: string;
|
||||
description?: string;
|
||||
bloodDNA?: string;
|
||||
bloodType?: string;
|
||||
diseaseAgent: string;
|
||||
possibleTreatments?: string;
|
||||
transmissionRoute?: string;
|
||||
symptoms?: PathogenSymptom[];
|
||||
isAdvanced: BooleanLike;
|
||||
}
|
||||
|
||||
interface PanDEMICData {
|
||||
synthesisCooldown: BooleanLike;
|
||||
beakerLoaded: BooleanLike;
|
||||
beakerContainsBlood: BooleanLike;
|
||||
beakerContainsVirus: BooleanLike;
|
||||
selectedStrainIndex: number;
|
||||
strains?: PathogenStrain[];
|
||||
resistances?: string[];
|
||||
}
|
||||
|
||||
export const PanDEMIC = (props, context) => {
|
||||
const { data } = useBackend<PanDEMICData>(context);
|
||||
const {
|
||||
beakerLoaded,
|
||||
beakerContainsBlood,
|
||||
beakerContainsVirus,
|
||||
resistances = [],
|
||||
} = data;
|
||||
|
||||
let emptyPlaceholder;
|
||||
if (!beakerLoaded) {
|
||||
emptyPlaceholder = <>No container loaded.</>;
|
||||
} else if (!beakerContainsBlood) {
|
||||
emptyPlaceholder = <>No blood sample found in the loaded container.</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Window width={575} height={510}>
|
||||
<Window.Content>
|
||||
<Stack fill vertical>
|
||||
{emptyPlaceholder && (
|
||||
<Section
|
||||
title="Container Information"
|
||||
buttons={<CommonCultureActions />}
|
||||
>
|
||||
{emptyPlaceholder}
|
||||
</Section>
|
||||
)}
|
||||
{!!beakerContainsVirus && <CultureInformationSection />}
|
||||
{resistances?.length > 0 && <ResistancesSection />}
|
||||
</Stack>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const CommonCultureActions = (props, context) => {
|
||||
const { act, data } = useBackend<PanDEMICData>(context);
|
||||
const { beakerLoaded } = data;
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
icon="eject"
|
||||
content="Eject"
|
||||
disabled={!beakerLoaded}
|
||||
onClick={() => act('eject_beaker')}
|
||||
/>
|
||||
<Button.Confirm
|
||||
icon="trash-alt"
|
||||
confirmIcon="eraser"
|
||||
content="Destroy"
|
||||
confirmContent="Destroy"
|
||||
disabled={!beakerLoaded}
|
||||
onClick={() => act('destroy_eject_beaker')}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const StrainInformation = (
|
||||
props: { strain: PathogenStrain; strainIndex: number },
|
||||
context
|
||||
) => {
|
||||
const { act, data } = useBackend<PanDEMICData>(context);
|
||||
const { beakerContainsVirus } = data;
|
||||
const {
|
||||
commonName,
|
||||
description,
|
||||
diseaseAgent,
|
||||
bloodDNA,
|
||||
bloodType,
|
||||
possibleTreatments,
|
||||
transmissionRoute,
|
||||
isAdvanced,
|
||||
} = props.strain;
|
||||
|
||||
const bloodInformation = (
|
||||
<>
|
||||
<LabeledList.Item label="Blood DNA">
|
||||
{!bloodDNA ? (
|
||||
'Undetectable'
|
||||
) : (
|
||||
<span style={{ 'font-family': "'Courier New', monospace" }}>
|
||||
{bloodDNA}
|
||||
</span>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Blood Type">
|
||||
{
|
||||
<div
|
||||
// blood type can sometimes contain a span
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{ __html: bloodType ?? 'Undetectable' }}
|
||||
/>
|
||||
}
|
||||
</LabeledList.Item>
|
||||
</>
|
||||
);
|
||||
|
||||
if (!beakerContainsVirus) {
|
||||
return <LabeledList>{bloodInformation}</LabeledList>;
|
||||
}
|
||||
|
||||
let nameButtons;
|
||||
if (isAdvanced) {
|
||||
if (
|
||||
commonName !== undefined &&
|
||||
commonName !== null &&
|
||||
commonName !== 'Unknown'
|
||||
) {
|
||||
nameButtons = (
|
||||
<Button
|
||||
icon="print"
|
||||
content="Print Release Forms"
|
||||
onClick={() =>
|
||||
act('print_release_forms', {
|
||||
strain_index: props.strainIndex,
|
||||
})
|
||||
}
|
||||
style={{ 'margin-left': 'auto' }}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
nameButtons = (
|
||||
<Button
|
||||
icon="pen"
|
||||
content="Name Disease"
|
||||
onClick={() =>
|
||||
act('name_strain', { strain_index: props.strainIndex })
|
||||
}
|
||||
style={{ 'margin-left': 'auto' }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Common Name" className="common-name-label">
|
||||
<Stack horizontal align="center">
|
||||
{commonName ?? 'Unknown'}
|
||||
{nameButtons}
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
{description && (
|
||||
<LabeledList.Item label="Description">{description}</LabeledList.Item>
|
||||
)}
|
||||
<LabeledList.Item label="Disease Agent">{diseaseAgent}</LabeledList.Item>
|
||||
{bloodInformation}
|
||||
<LabeledList.Item label="Spread Vector">
|
||||
{transmissionRoute ?? 'None'}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Possible Cures">
|
||||
{possibleTreatments ?? 'None'}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
);
|
||||
};
|
||||
|
||||
const StrainInformationSection = (
|
||||
props: {
|
||||
strain: PathogenStrain;
|
||||
strainIndex: number;
|
||||
sectionTitle?: string;
|
||||
sectionButtons?: InfernoNode | InfernoNode[];
|
||||
},
|
||||
context
|
||||
) => {
|
||||
const { act, data } = useBackend<PanDEMICData>(context);
|
||||
let synthesisCooldown = !!data.synthesisCooldown;
|
||||
const appliedSectionButtons = (
|
||||
<>
|
||||
<Button
|
||||
icon={synthesisCooldown ? 'spinner' : 'clone'}
|
||||
iconSpin={synthesisCooldown}
|
||||
content="Clone"
|
||||
disabled={synthesisCooldown}
|
||||
onClick={() => act('clone_strain', { strain_index: props.strainIndex })}
|
||||
/>
|
||||
{props.sectionButtons}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex.Item>
|
||||
<Section
|
||||
title={props.sectionTitle ?? 'Strain Information'}
|
||||
buttons={appliedSectionButtons}
|
||||
>
|
||||
<StrainInformation
|
||||
strain={props.strain}
|
||||
strainIndex={props.strainIndex}
|
||||
/>
|
||||
</Section>
|
||||
</Flex.Item>
|
||||
);
|
||||
};
|
||||
|
||||
const CultureInformationSection = (props, context) => {
|
||||
const { act, data } = useBackend<PanDEMICData>(context);
|
||||
const { selectedStrainIndex, strains } = data;
|
||||
const selectedStrain = strains[selectedStrainIndex - 1];
|
||||
|
||||
if (strains.length === 1) {
|
||||
return (
|
||||
<>
|
||||
<StrainInformationSection
|
||||
strain={strains[0]}
|
||||
strainIndex={1}
|
||||
sectionButtons={<CommonCultureActions />}
|
||||
/>
|
||||
{strains[0].symptoms?.length > 0 && (
|
||||
<StrainSymptomsSection strain={strains[0]} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const sectionButtons = <CommonCultureActions />;
|
||||
|
||||
return (
|
||||
<Stack.Item grow>
|
||||
<Section title="Culture Information" fill buttons={sectionButtons}>
|
||||
<Flex direction="column" style={{ 'height': '100%' }}>
|
||||
<Flex.Item>
|
||||
<Tabs>
|
||||
{strains.map((strain, i) => (
|
||||
<Tabs.Tab
|
||||
key={i}
|
||||
icon="virus"
|
||||
selected={selectedStrainIndex - 1 === i}
|
||||
onClick={() => act('switch_strain', { strain_index: i + 1 })}
|
||||
>
|
||||
{strain.commonName ?? 'Unknown'}
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
</Flex.Item>
|
||||
<StrainInformationSection
|
||||
strain={selectedStrain}
|
||||
strainIndex={selectedStrainIndex}
|
||||
/>
|
||||
{selectedStrain.symptoms?.length > 0 && (
|
||||
<StrainSymptomsSection
|
||||
className="remove-section-bottom-padding"
|
||||
strain={selectedStrain}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
);
|
||||
};
|
||||
|
||||
const sum = (values: number[]) => {
|
||||
return values.reduce((r, value) => r + value, 0);
|
||||
};
|
||||
|
||||
const StrainSymptomsSection = (props: {
|
||||
className?: string;
|
||||
strain: PathogenStrain;
|
||||
}) => {
|
||||
const { symptoms } = props.strain;
|
||||
return (
|
||||
<Flex.Item grow>
|
||||
<Section title="Infection Symptoms" fill className={props.className}>
|
||||
<Table className="symptoms-table">
|
||||
<Table.Row>
|
||||
<Table.Cell>Name</Table.Cell>
|
||||
<Table.Cell>Stealth</Table.Cell>
|
||||
<Table.Cell>Resistance</Table.Cell>
|
||||
<Table.Cell>Stage Speed</Table.Cell>
|
||||
<Table.Cell>Transmissibility</Table.Cell>
|
||||
</Table.Row>
|
||||
{symptoms.map((symptom, index) => (
|
||||
<Table.Row key={index}>
|
||||
<Table.Cell>{symptom.name}</Table.Cell>
|
||||
<Table.Cell>{symptom.stealth}</Table.Cell>
|
||||
<Table.Cell>{symptom.resistance}</Table.Cell>
|
||||
<Table.Cell>{symptom.stageSpeed}</Table.Cell>
|
||||
<Table.Cell>{symptom.transmissibility}</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
<Table.Row className="table-spacer" />
|
||||
<Table.Row>
|
||||
<Table.Cell style={{ 'font-weight': 'bold' }}>Total</Table.Cell>
|
||||
<Table.Cell>{sum(symptoms.map((s) => s.stealth))}</Table.Cell>
|
||||
<Table.Cell>{sum(symptoms.map((s) => s.resistance))}</Table.Cell>
|
||||
<Table.Cell>{sum(symptoms.map((s) => s.stageSpeed))}</Table.Cell>
|
||||
<Table.Cell>
|
||||
{sum(symptoms.map((s) => s.transmissibility))}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table>
|
||||
</Section>
|
||||
</Flex.Item>
|
||||
);
|
||||
};
|
||||
|
||||
const VaccineSynthesisIcons = ['flask', 'vial', 'eye-dropper'];
|
||||
|
||||
const ResistancesSection = (props, context) => {
|
||||
const { act, data } = useBackend<PanDEMICData>(context);
|
||||
const { synthesisCooldown, beakerContainsVirus, resistances } = data;
|
||||
return (
|
||||
<Stack.Item>
|
||||
<Section
|
||||
title="Antibodies"
|
||||
fill
|
||||
buttons={!beakerContainsVirus && <CommonCultureActions />}
|
||||
>
|
||||
<Stack horizontal wrap>
|
||||
{resistances.map((r, i) => (
|
||||
<Stack.Item key={i}>
|
||||
<Button
|
||||
icon={VaccineSynthesisIcons[i % VaccineSynthesisIcons.length]}
|
||||
disabled={!!synthesisCooldown}
|
||||
onClick={() =>
|
||||
act('clone_vaccine', { resistance_index: i + 1 })
|
||||
}
|
||||
mr="0.5em"
|
||||
/>
|
||||
{r}
|
||||
</Stack.Item>
|
||||
))}
|
||||
</Stack>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
.symptoms-table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 0.5ex;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.symptoms-table > tbody > tr:first-child {
|
||||
width: 100%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.symptoms-table > tbody > tr:nth-child(2) > td:first-child {
|
||||
padding-top: 0.5ex;
|
||||
}
|
||||
|
||||
.symptoms-table > tbody > tr > td:nth-child(n + 2) {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.common-name-label > .LabeledList__cell {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.table-spacer {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.remove-section-bottom-padding .Section__content {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
@@ -57,6 +57,7 @@
|
||||
@include meta.load-css('./interfaces/Newscaster.scss');
|
||||
@include meta.load-css('./interfaces/NuclearBomb.scss');
|
||||
@include meta.load-css('./interfaces/OreRedemption.scss');
|
||||
@include meta.load-css('./interfaces/PanDEMIC.scss');
|
||||
@include meta.load-css('./interfaces/PDA.scss');
|
||||
@include meta.load-css('./interfaces/PdaPainter.scss');
|
||||
@include meta.load-css('./interfaces/PoolController.scss');
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+76
-76
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user