mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-07-18 19:53:35 +01:00
[MIRROR] Medigun Port (#12098)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com> Co-authored-by: Guti <32563288+TheCaramelion@users.noreply.github.com> Co-authored-by: vorestation-ci[bot] <199609141+vorestation-ci[bot]@users.noreply.github.com> Co-authored-by: Killian <49700375+KillianKirilenko@users.noreply.github.com> Co-authored-by: Jenny <ghosttehspychecka@gmail.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com> Co-authored-by: Will <7099514+Willburd@users.noreply.github.com> Co-authored-by: TheToaster98 <51209769+TheToaster98@users.noreply.github.com> Co-authored-by: Selis <12716288+ItsSelis@users.noreply.github.com> Co-authored-by: SatinIsle <98125273+SatinIsle@users.noreply.github.com> Co-authored-by: Aura Dusklight <46622484+NovaDusklight@users.noreply.github.com> Co-authored-by: Aroliacue <96730930+Aroliacue@users.noreply.github.com> Co-authored-by: Aroliacue <avaylaiss34@gmail.com> Co-authored-by: nesquik <24830358+lbnesquik@users.noreply.github.com> Co-authored-by: ShadowLarkens <shadowlarkens@gmail.com> Co-authored-by: MeepleMuncher <76881946+MeepleMuncher@users.noreply.github.com> Co-authored-by: Olive <49600480+zeskorion@users.noreply.github.com> Co-authored-by: shybandit5213 <shybandit5213@gmail.com> Co-authored-by: Bandit <queenjess521@gmail.com>
This commit is contained in:
committed by
GitHub
parent
a8ad45d7b8
commit
f4fe45f8d3
@@ -110,3 +110,20 @@
|
||||
**Creator / Copyright:** Toriate<br>
|
||||
**License Holders:** Matica<br>
|
||||
**License:** [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/)<br>
|
||||
<br>
|
||||
**File:** `icons/obj/borkmedigun.dmi`<br>
|
||||
**Creator:** Commissioned by Cross_Exonar from Toriate<br>
|
||||
**Link:** https://github.com/TS-Rogue-Star/Rogue-Star/pull/1010<br>
|
||||
**License:** [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)<br>
|
||||
<br>
|
||||
**File:** `icons/mob/items/lefthand_medigun.dmi`<br>
|
||||
**Icon-States:**medblaster-wielded, medblaster, medblaster_cmo<br>
|
||||
**Creator:** Commissioned by Cross_Exonar from Toriate<br>
|
||||
**Link:** https://github.com/TS-Rogue-Star/Rogue-Star/pull/1010<br>
|
||||
**License:** [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)<br>
|
||||
<br>
|
||||
**File:** `icons/mob/items/righthand_medigun.dmi`<br>
|
||||
**Icon-States:**medblaster-wielded, medblaster, medblaster_cmo<br>
|
||||
**Creator:** Commissioned by Cross_Exonar from Toriate<br>
|
||||
**Link:** https://github.com/TS-Rogue-Star/Rogue-Star/pull/1010<br>
|
||||
**License:** [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)<br>
|
||||
|
||||
@@ -168,7 +168,8 @@ NOTICE: Do not leave trailing commas!!!!
|
||||
#define POCKET_BAYSUIT \
|
||||
/obj/item/storage/backpack, \
|
||||
/obj/item/bluespaceradio, \
|
||||
/obj/item/defib_kit
|
||||
/obj/item/defib_kit, \
|
||||
/obj/item/medigun_backpack
|
||||
|
||||
/// Wrapper for adding clothing based traits
|
||||
#define ADD_CLOTHING_TRAIT(mob, trait) ADD_TRAIT(mob, trait, "[CLOTHING_TRAIT]_[REF(src)]")
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#define MEDIGUN_IDLE 0
|
||||
#define MEDIGUN_CANCELLED 1
|
||||
#define MEDIGUN_BUSY 2
|
||||
@@ -85,6 +85,7 @@
|
||||
#define TECHWEB_NODE_MEDBAY_EQUIP_ADV "medbay_equip_adv"
|
||||
#define TECHWEB_NODE_MEDBAY_EQUIP_HIGH_TECH "medbay_equip_high_tech"
|
||||
#define TECHWEB_NODE_MEDIGUN "medbay_medigun"
|
||||
#define TECHWEB_NODE_MEDIGUN_CONSTANT "medbay_medigun_constant"
|
||||
#define TECHWEB_NODE_MINING "mining"
|
||||
#define TECHWEB_NODE_MINING_ADV "mining_adv"
|
||||
#define TECHWEB_NODE_MOD_ANOMALY "mod_anomaly"
|
||||
|
||||
@@ -16,7 +16,8 @@ GLOBAL_LIST_INIT(allowed_recharger_devices, list(
|
||||
/obj/item/paicard,
|
||||
/obj/item/personal_shield_generator,
|
||||
/obj/item/gun/projectile/cell_loaded,
|
||||
/obj/item/ammo_magazine/cell_mag
|
||||
/obj/item/ammo_magazine/cell_mag,
|
||||
/obj/item/medigun_backpack
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(allowed_wallcharger_devices, list(
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/obj/item/bork_medigun
|
||||
name = "prototype bluespace medigun"
|
||||
desc = "The Bork BSM-92 or 'Blue Space Medigun' utilizes advanced bluespace technology to transfer beneficial reagents directly to torn tissue. This way, even larger wounds can be mended efficiently in short periods of time"
|
||||
icon = 'icons/obj/borkmedigun.dmi'
|
||||
icon_state = "medblaster"
|
||||
var/wielded_item_state = "medblaster-wielded"
|
||||
var/base_icon_state = "medblaster"
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_medigun.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_medigun.dmi',
|
||||
)
|
||||
w_class = ITEMSIZE_HUGE
|
||||
force = 0
|
||||
var/beam_range = 3 // How many tiles away it can scan. Changing this also changes the box size.
|
||||
var/busy = MEDIGUN_IDLE // Set to true when scanning, to stop multiple scans.
|
||||
var/action_cancelled = FALSE
|
||||
var/wielded = FALSE
|
||||
var/mob/current_target
|
||||
var/mgcmo
|
||||
canremove = FALSE
|
||||
|
||||
/obj/item/bork_medigun/update_twohanding()
|
||||
var/mob/living/M = loc
|
||||
if(istype(M) && M.item_is_in_hands(src) && !M.hands_are_full())
|
||||
wielded = TRUE
|
||||
name = "[initial(name)] (wielded)"
|
||||
else
|
||||
wielded = FALSE
|
||||
name = initial(name)
|
||||
..()
|
||||
|
||||
/obj/item/bork_medigun/update_held_icon()
|
||||
if(wielded_item_state)
|
||||
var/mob/living/M = loc
|
||||
if(istype(M))
|
||||
if(M.can_wield_item(src) && src.is_held_twohanded(M))
|
||||
LAZYSET(item_state_slots, slot_l_hand_str, wielded_item_state)
|
||||
LAZYSET(item_state_slots, slot_r_hand_str, wielded_item_state)
|
||||
else
|
||||
LAZYSET(item_state_slots, slot_l_hand_str, initial(item_state))
|
||||
LAZYSET(item_state_slots, slot_r_hand_str, initial(item_state))
|
||||
..()
|
||||
|
||||
// Draws a box showing the limits of movement while scanning something.
|
||||
// Only the client supplied will see the box.
|
||||
/obj/item/bork_medigun/proc/draw_box(atom/A, box_size, client/C)
|
||||
var/list/our_box = list()
|
||||
// Things moved with pixel_[x|y] will move the box, so this is to correct that.
|
||||
var/pixel_x_correction = -A.pixel_x
|
||||
var/pixel_y_correction = -A.pixel_y
|
||||
|
||||
var/our_icon_size = world.icon_size
|
||||
// First, place the bottom-left corner.
|
||||
our_box += draw_line(A, SOUTHWEST, (-box_size * our_icon_size) + pixel_x_correction, (-box_size * our_icon_size) + pixel_y_correction, C)
|
||||
|
||||
var/rendered_size = (box_size * 2) - 1
|
||||
// Make a line on the bottom, going right.
|
||||
for(var/i = 1 to rendered_size)
|
||||
var/x_displacement = (-box_size * our_icon_size) + (our_icon_size * i) + pixel_x_correction
|
||||
var/y_displacement = (-box_size * our_icon_size) + pixel_y_correction
|
||||
our_box += draw_line(A, SOUTH, x_displacement, y_displacement, C)
|
||||
|
||||
// Bottom-right corner.
|
||||
our_box += draw_line(A, SOUTHEAST, (box_size * our_icon_size) + pixel_x_correction, (-box_size * our_icon_size) + pixel_y_correction, C)
|
||||
|
||||
// Second line, for the right side going up.
|
||||
for(var/i = 1 to rendered_size)
|
||||
var/x_displacement = (box_size * our_icon_size) + pixel_x_correction
|
||||
var/y_displacement = (-box_size * our_icon_size) + (our_icon_size * i) + pixel_y_correction
|
||||
our_box += draw_line(A, EAST, x_displacement, y_displacement, C)
|
||||
|
||||
// Top-right corner.
|
||||
our_box += draw_line(A, NORTHEAST, (box_size * our_icon_size) + pixel_x_correction, (box_size * our_icon_size) + pixel_y_correction, C)
|
||||
|
||||
// Third line, for the top, going right.
|
||||
for(var/i = 1 to rendered_size)
|
||||
var/x_displacement = (-box_size * our_icon_size) + (our_icon_size * i) + pixel_x_correction
|
||||
var/y_displacement = (box_size * our_icon_size) + pixel_y_correction
|
||||
our_box += draw_line(A, NORTH, x_displacement, y_displacement, C)
|
||||
|
||||
// Top-left corner.
|
||||
our_box += draw_line(A, NORTHWEST, (-box_size * our_icon_size) + pixel_x_correction, (box_size * our_icon_size) + pixel_y_correction, C)
|
||||
|
||||
// Fourth and last line, for the left side going up.
|
||||
for(var/i = 1 to rendered_size)
|
||||
var/x_displacement = (-box_size * our_icon_size) + pixel_x_correction
|
||||
var/y_displacement = (-box_size * our_icon_size) + (our_icon_size * i) + pixel_y_correction
|
||||
our_box += draw_line(A, WEST, x_displacement, y_displacement, C)
|
||||
return our_box
|
||||
|
||||
// Draws an individual segment of the box.
|
||||
/obj/item/bork_medigun/proc/draw_line(atom/A, line_dir, line_pixel_x, line_pixel_y, client/C)
|
||||
var/image/line = image(icon = 'icons/effects/effects.dmi', loc = A, icon_state = "stripes", dir = line_dir)
|
||||
line.pixel_x = line_pixel_x
|
||||
line.pixel_y = line_pixel_y
|
||||
line.plane = PLANE_FULLSCREEN // It's technically a HUD element but it doesn't need to show above item slots.
|
||||
line.appearance_flags = RESET_TRANSFORM|RESET_COLOR|RESET_ALPHA|NO_CLIENT_COLOR|TILE_BOUND
|
||||
line.alpha = 125
|
||||
C.images += line
|
||||
return line
|
||||
|
||||
// Removes the box that was generated before from the client.
|
||||
/obj/item/bork_medigun/proc/delete_box(list/box_segments, client/C)
|
||||
for(var/i in box_segments)
|
||||
C.images -= i
|
||||
qdel(i)
|
||||
|
||||
/obj/item/bork_medigun/proc/color_box(list/box_segments, new_color, new_time)
|
||||
for(var/i in box_segments)
|
||||
animate(i, color = new_color, time = new_time)
|
||||
|
||||
/obj/item/bork_medigun/attack_hand(mob/user)
|
||||
if(user.get_inactive_hand() == src)// && loc != get_turf)
|
||||
return
|
||||
return ..()
|
||||
@@ -0,0 +1,280 @@
|
||||
/obj/item/bork_medigun/linked
|
||||
var/obj/item/medigun_backpack/medigun_base_unit
|
||||
|
||||
/obj/item/bork_medigun/linked/Destroy()
|
||||
if(medigun_base_unit)
|
||||
var/obj/item/bork_medigun/medigun = medigun_base_unit.get_medigun()
|
||||
//ensure the base unit's icon updates
|
||||
if(medigun == src)
|
||||
medigun = null
|
||||
medigun_base_unit.replace_icon()
|
||||
if(ismob(loc))
|
||||
var/mob/user = loc
|
||||
user.update_inv_back()
|
||||
medigun_base_unit = null
|
||||
return ..()
|
||||
|
||||
/obj/item/bork_medigun/linked/forceMove(atom/destination) //Forcemove override, ugh
|
||||
if(destination == medigun_base_unit || destination == medigun_base_unit.loc || isturf(destination))
|
||||
. = doMove(destination, 0, 0)
|
||||
if(isturf(destination))
|
||||
for(var/atom/A as anything in destination) // If we can't scan the turf, see if we can scan anything on it, to help with aiming.
|
||||
if(istype(A,/obj/structure/closet ))
|
||||
break
|
||||
|
||||
/obj/item/bork_medigun/linked/proc/check_charge(var/charge_amt)
|
||||
return (medigun_base_unit.bcell && medigun_base_unit.bcell.check_charge(charge_amt))
|
||||
|
||||
/obj/item/bork_medigun/linked/proc/checked_use(var/charge_amt)
|
||||
return (medigun_base_unit.bcell && medigun_base_unit.bcell.checked_use(charge_amt))
|
||||
|
||||
/obj/item/bork_medigun/linked/attack_self(mob/living/user)
|
||||
if(medigun_base_unit.is_twohanded())
|
||||
update_twohanding()
|
||||
if(busy)
|
||||
busy = MEDIGUN_CANCELLED
|
||||
|
||||
/obj/item/bork_medigun/linked/proc/should_stop(var/mob/living/target, var/mob/living/user, var/active_hand)
|
||||
if(!target || !user || (!active_hand && medigun_base_unit.is_twohanded()) || !istype(target) || !istype(user) || busy < MEDIGUN_BUSY)
|
||||
return TRUE
|
||||
|
||||
if((user.get_active_hand() != active_hand || wielded == 0) && medigun_base_unit.is_twohanded())
|
||||
to_chat(user, span_warning("Please keep your hands free!"))
|
||||
return TRUE
|
||||
|
||||
if(user.is_incorporeal())
|
||||
return TRUE
|
||||
|
||||
if(user.incapacitated(INCAPACITATION_DEFAULT | INCAPACITATION_KNOCKDOWN | INCAPACITATION_DISABLED | INCAPACITATION_KNOCKOUT | INCAPACITATION_STUNNED | INCAPACITATION_RESTRAINED))
|
||||
return TRUE
|
||||
|
||||
if(user.stat)
|
||||
return TRUE
|
||||
|
||||
if(target.isSynthetic())
|
||||
to_chat(user, span_warning("Target is not organic."))
|
||||
return TRUE
|
||||
|
||||
//if(get_dist(user, target) > beam_range)
|
||||
if(!(target in range(beam_range, user)) || (!(target in view(10, user)) && !(medigun_base_unit.smodule.get_rating() >= 5)))
|
||||
to_chat(user, span_warning("You are too far away from \the [target] to heal them, Or they are not in view. Get closer."))
|
||||
return TRUE
|
||||
|
||||
if(!isliving(target))
|
||||
//to_chat(user, span_warning("\the [target] is not a valid target."))
|
||||
return TRUE
|
||||
|
||||
if(!ishuman(target))
|
||||
return TRUE
|
||||
|
||||
/*if(!H.getBruteLoss() && !H.getFireLoss() && !H.getToxLoss())// && !H.getOxyLoss()) // No point Wasting fuel/power if target healed
|
||||
playsound(src, 'sound/machines/ping.ogg', 50)
|
||||
to_chat(user, span_warning("\the [target] is fully healed."))
|
||||
return TRUE
|
||||
*/
|
||||
return FALSE
|
||||
|
||||
/obj/item/bork_medigun/linked/afterattack(atom/target, mob/user, proximity_flag)
|
||||
// Things that invalidate the scan immediately.
|
||||
if(isturf(target))
|
||||
for(var/atom/A as anything in target) // If we can't scan the turf, see if we can scan anything on it, to help with aiming.
|
||||
if(isliving(A))
|
||||
target = A
|
||||
break
|
||||
if(!istype(medigun_base_unit, /obj/item/medigun_backpack/cmo))
|
||||
update_twohanding()
|
||||
if(busy && !(target == current_target) && isliving(target))
|
||||
to_chat(user, span_warning("\The [src] is already targeting something."))
|
||||
return
|
||||
|
||||
if(!ishuman(target))
|
||||
return
|
||||
|
||||
if(!medigun_base_unit.smanipulator)
|
||||
to_chat(user, span_warning("\The [src] Blinks a red error light, Manipulator missing."))
|
||||
return
|
||||
if(!medigun_base_unit.scapacitor)
|
||||
to_chat(user, span_warning("\The [src] Blinks a blue error light, capacitor missing."))
|
||||
return
|
||||
if(!medigun_base_unit.slaser)
|
||||
to_chat(user, span_warning("\The [src] Blinks an orange error light, laser missing."))
|
||||
return
|
||||
if(!medigun_base_unit.smodule)
|
||||
to_chat(user, span_warning("\The [src] Blinks a pink error light, scanning module missing."))
|
||||
return
|
||||
if(!check_charge(5))
|
||||
to_chat(user, span_warning("\The [src] doesn't have enough charge left to do that."))
|
||||
return
|
||||
if(get_dist(target, user) > beam_range)
|
||||
to_chat(user, span_warning("You are too far away from \the [target] to affect it. Get closer."))
|
||||
return
|
||||
|
||||
if(target == current_target && busy)
|
||||
busy = MEDIGUN_CANCELLED
|
||||
return
|
||||
if(target == user)
|
||||
to_chat(user, span_warning("Cant heal yourself."))
|
||||
return
|
||||
if(!(target in range(beam_range, user)) || (!(target in view(10, user)) && !medigun_base_unit.smodule))
|
||||
to_chat(user, span_warning("You are too far away from \the [target] to heal them, Or they are not in view. Get closer."))
|
||||
return
|
||||
|
||||
current_target = target
|
||||
busy = MEDIGUN_BUSY
|
||||
update_icon()
|
||||
var/myicon = "medbeam_basic"
|
||||
var/mycolor = "#037ffc"
|
||||
var/datum/beam/scan_beam = user.Beam(target, icon = 'icons/obj/borkmedigun.dmi', icon_state = myicon, time = 6000)
|
||||
var/filter = filter(type = "outline", size = 1, color = mycolor)
|
||||
var/list/box_segments = list()
|
||||
playsound(src, 'sound/weapons/wave.ogg', 50)
|
||||
var/mob/living/carbon/human/H = target
|
||||
to_chat(user, span_notice("Locking on to [H]"))
|
||||
to_chat(H, span_warning("[user] is targetting you with their medigun"))
|
||||
if(user.client)
|
||||
box_segments = draw_box(target, beam_range, user.client)
|
||||
color_box(box_segments, mycolor, 5)
|
||||
process_medigun(H, user, filter)
|
||||
|
||||
action_cancelled = FALSE
|
||||
busy = MEDIGUN_IDLE
|
||||
current_target = null
|
||||
|
||||
// Now clean up the effects.
|
||||
update_icon()
|
||||
QDEL_NULL(scan_beam)
|
||||
target.filters -= filter
|
||||
if(user.client) // If for some reason they logged out mid-scan the box will be gone anyways.
|
||||
delete_box(box_segments, user.client)
|
||||
|
||||
/obj/item/bork_medigun/linked/proc/process_medigun(mob/living/carbon/human/H, mob/user, filter, ishealing = FALSE)
|
||||
if(should_stop(H, user, user.get_active_hand()))
|
||||
return
|
||||
|
||||
if(do_after(user, 1 SECOND, user, timed_action_flags = IGNORE_USER_LOC_CHANGE, hidden = TRUE))
|
||||
var/washealing = ishealing // Did we heal last cycle
|
||||
ishealing = FALSE // The default is 'we didn't heal this cycle'
|
||||
if(!checked_use(5))
|
||||
to_chat(user, span_warning("\The [src] doesn't have enough charge left to do that."))
|
||||
return
|
||||
if(H.stat == DEAD)
|
||||
process_medigun(H, user, filter)
|
||||
return
|
||||
var/lastier = medigun_base_unit.slaser.get_rating()
|
||||
if(lastier >= 2)
|
||||
if(checked_use(5))
|
||||
H.add_modifier(/datum/modifier/medbeameffect, 2 SECONDS)
|
||||
if(H.getHalLoss() && checked_use(5))
|
||||
H.adjustHalLoss(-20)
|
||||
if(H.weakened && checked_use(5))
|
||||
H.AdjustWeakened(-1)
|
||||
if(lastier >= 3)
|
||||
if(H.paralysis && (checked_use(15)))
|
||||
H.AdjustParalysis(-1)
|
||||
|
||||
var/healmod = lastier
|
||||
/*if(H.getBruteLoss())
|
||||
healmod = min(lastier,medigun_base_unit.brutecharge,H.getBruteLoss())
|
||||
if(medigun_base_unit.brutecharge >= healmod)
|
||||
if(!checked_use(healmod))
|
||||
to_chat(user, span_warning("\The [src] doesn't have enough charge left to do that."))
|
||||
break
|
||||
if(healmod < 0)
|
||||
healmod = 0
|
||||
else
|
||||
H.adjustBruteLoss(-healmod)
|
||||
medigun_base_unit.brutecharge -= healmod
|
||||
ishealing = 1
|
||||
if(H.getFireLoss())
|
||||
healmod = min(lastier,medigun_base_unit.burncharge,H.getFireLoss())
|
||||
if(medigun_base_unit.burncharge >= healmod)
|
||||
if(!checked_use(healmod))
|
||||
to_chat(user, span_warning("\The [src] doesn't have enough charge left to do that."))
|
||||
break
|
||||
if(healmod < 0)
|
||||
healmod = 0
|
||||
else
|
||||
H.adjustFireLoss(-healmod)
|
||||
medigun_base_unit.burncharge -= healmod
|
||||
ishealing = 1*/
|
||||
if(H.getToxLoss())
|
||||
healmod = min(lastier,medigun_base_unit.toxcharge,H.getToxLoss())
|
||||
if(medigun_base_unit.toxcharge >= healmod)
|
||||
if(!checked_use(healmod))
|
||||
to_chat(user, span_warning("\The [src] doesn't have enough charge left to do that."))
|
||||
return
|
||||
if(healmod < 0)
|
||||
healmod = 0
|
||||
else
|
||||
H.adjustToxLoss(-healmod)
|
||||
medigun_base_unit.toxcharge -= healmod
|
||||
ishealing = TRUE
|
||||
if(H.getOxyLoss())
|
||||
healmod = min(10*lastier,H.getOxyLoss())
|
||||
if(!checked_use(min(10,healmod)))
|
||||
to_chat(user, span_warning("\The [src] doesn't have enough charge left to do that."))
|
||||
return
|
||||
H.adjustOxyLoss(-healmod)
|
||||
ishealing = TRUE
|
||||
|
||||
ishealing = process_wounds(H, lastier, lastier, ishealing)
|
||||
//if(medigun_base_unit.brutecharge <= 0 || medigun_base_unit.burncharge <= 0 || medigun_base_unit.toxcharge <= 0)
|
||||
medigun_base_unit.update_icon()
|
||||
//if(medigun_base_unit.slaser.get_rating() >= 5)
|
||||
|
||||
//Blood regeneration if there is some space
|
||||
if(lastier >= 5)
|
||||
if(H.vessel.get_reagent_amount("blood") < H.species.blood_volume)
|
||||
var/datum/reagent/blood/B = locate() in H.vessel.reagent_list //Grab some blood
|
||||
B.volume += min(5, (H.species.blood_volume - H.vessel.get_reagent_amount("blood")))// regenerate blood
|
||||
|
||||
if(ishealing != washealing) // Either we stopped or started healing this cycle
|
||||
if(ishealing)
|
||||
H.filters += filter
|
||||
else
|
||||
H.filters -= filter
|
||||
|
||||
process_medigun(H, user, filter, ishealing)
|
||||
|
||||
/obj/item/bork_medigun/linked/proc/process_wounds(mob/living/carbon/human/H, heal_ticks, remaining_strength, ishealing)
|
||||
while(heal_ticks > 0)
|
||||
if(remaining_strength <= 0)
|
||||
return ishealing
|
||||
if((!H.getFireLoss() || medigun_base_unit.burncharge <= 0) && (!H.getBruteLoss() || medigun_base_unit.burncharge <= 0))
|
||||
return ishealing
|
||||
|
||||
for(var/name in BP_ALL)
|
||||
var/obj/item/organ/external/O = H.organs_by_name[name]
|
||||
for(var/datum/wound/W in O.wounds)
|
||||
if (W.internal)
|
||||
continue
|
||||
//if (W.bandaged && W.disinfected)
|
||||
// continue
|
||||
if (W.damage_type == BRUISE || W.damage_type == CUT || W.damage_type == PIERCE)
|
||||
if(medigun_base_unit.brutecharge >= 1)
|
||||
if(W.damage <= 1)
|
||||
O.wounds -= W
|
||||
medigun_base_unit.brutecharge -= 1
|
||||
ishealing = TRUE
|
||||
else if(medigun_base_unit.brutecharge >= 1)
|
||||
W.damage -= 1
|
||||
medigun_base_unit.brutecharge -= 1
|
||||
remaining_strength -= 1
|
||||
ishealing = TRUE
|
||||
if (W.damage_type == BURN)
|
||||
if(medigun_base_unit.burncharge >= 1)
|
||||
if(W.damage <= 1)
|
||||
O.wounds -= W
|
||||
medigun_base_unit.burncharge -= 1
|
||||
ishealing = TRUE
|
||||
else if(medigun_base_unit.burncharge >= 1)
|
||||
W.damage -= 1
|
||||
medigun_base_unit.burncharge -= 1
|
||||
remaining_strength -= 1
|
||||
ishealing = TRUE
|
||||
if(remaining_strength <= 0)
|
||||
return ishealing
|
||||
if(remaining_strength <= 0)
|
||||
return ishealing
|
||||
heal_ticks--
|
||||
return ishealing
|
||||
@@ -0,0 +1,569 @@
|
||||
//backpack item
|
||||
/obj/item/medigun_backpack
|
||||
name = "protoype bluespace medigun backpack"
|
||||
desc = "Contains a bluespace medigun, this portable unit digitizes and stores chems and battery power used by the attached gun."
|
||||
icon = 'icons/obj/borkmedigun.dmi'
|
||||
icon_override = 'icons/obj/borkmedigun.dmi'
|
||||
icon_state = "mg-backpack"
|
||||
item_state = "mg-backpack-onmob"
|
||||
slot_flags = SLOT_BACK
|
||||
force = 5
|
||||
throwforce = 6
|
||||
preserve_item = TRUE
|
||||
w_class = ITEMSIZE_HUGE
|
||||
unacidable = TRUE
|
||||
origin_tech = list(TECH_BIO = 4, TECH_POWER = 2, TECH_BLUESPACE = 4)
|
||||
|
||||
var/obj/item/bork_medigun/linked/medigun_path = /obj/item/bork_medigun/linked
|
||||
var/obj/item/cell/bcell = /obj/item/cell
|
||||
var/obj/item/cell/ccell = null
|
||||
var/obj/item/stock_parts/matter_bin/sbin = /obj/item/stock_parts/matter_bin
|
||||
var/obj/item/stock_parts/scanning_module/smodule = /obj/item/stock_parts/scanning_module
|
||||
var/obj/item/stock_parts/manipulator/smanipulator = /obj/item/stock_parts/manipulator
|
||||
var/obj/item/stock_parts/capacitor/scapacitor = /obj/item/stock_parts/capacitor
|
||||
var/obj/item/stock_parts/micro_laser/slaser = /obj/item/stock_parts/micro_laser
|
||||
var/charging = FALSE
|
||||
var/brutecharge = 0
|
||||
var/toxcharge = 0
|
||||
var/burncharge = 0
|
||||
var/brutevol = 0
|
||||
var/toxvol = 0
|
||||
var/burnvol = 0
|
||||
var/chemcap = 60
|
||||
var/tankmax = 30
|
||||
var/containsgun = TRUE
|
||||
var/maintenance = FALSE
|
||||
var/smaniptier = 1
|
||||
var/sbintier = 1
|
||||
var/gridstatus = 0
|
||||
var/chargecap = 1000
|
||||
|
||||
//backpack item
|
||||
/obj/item/medigun_backpack/cmo
|
||||
name = "prototype bluespace medigun backpack - CMO"
|
||||
desc = "Contains a compact version of the bluespace medigun able to be used one handed, this portable unit digitizes and stores chems and battery power used by the attached gun."
|
||||
icon_state = "mg-backpack_cmo"
|
||||
item_state = "mg-backpack_cmo-onmob"
|
||||
scapacitor = /obj/item/stock_parts/capacitor/adv
|
||||
smanipulator = /obj/item/stock_parts/manipulator/nano
|
||||
smodule = /obj/item/stock_parts/scanning_module/adv
|
||||
slaser = /obj/item/stock_parts/micro_laser/high
|
||||
bcell = /obj/item/cell/apc
|
||||
tankmax = 60
|
||||
brutecharge = 60
|
||||
toxcharge = 60
|
||||
burncharge = 60
|
||||
chemcap = 120
|
||||
brutevol = 120
|
||||
toxvol = 120
|
||||
burnvol = 120
|
||||
chargecap = 5000
|
||||
|
||||
/obj/item/medigun_backpack/proc/is_twohanded()
|
||||
return TRUE
|
||||
|
||||
/obj/item/medigun_backpack/cmo/is_twohanded()
|
||||
return FALSE
|
||||
|
||||
/obj/item/medigun_backpack/proc/apc_charge()
|
||||
gridstatus = 0
|
||||
var/area/A = get_area(src)
|
||||
if(!istype(A) || !A.powered(EQUIP))
|
||||
return FALSE
|
||||
gridstatus = 1
|
||||
if(bcell && (bcell.charge < bcell.maxcharge))
|
||||
var/cur_charge = bcell.charge
|
||||
var/delta = min(50, bcell.maxcharge-cur_charge)
|
||||
bcell.give(delta)
|
||||
A.use_power_oneoff(delta*100, EQUIP)
|
||||
gridstatus = 2
|
||||
return TRUE
|
||||
|
||||
/obj/item/medigun_backpack/proc/adjust_brutevol(modifier)
|
||||
if(modifier > brutevol)
|
||||
modifier = brutevol
|
||||
if(modifier > (tankmax - brutecharge))
|
||||
modifier = tankmax - brutecharge
|
||||
brutevol -= modifier
|
||||
brutecharge += modifier
|
||||
|
||||
/obj/item/medigun_backpack/proc/adjust_burnvol(modifier)
|
||||
if(modifier > burnvol)
|
||||
modifier = burnvol
|
||||
if(modifier > (tankmax - burncharge))
|
||||
modifier = tankmax - burncharge
|
||||
burnvol -= modifier
|
||||
burncharge += modifier
|
||||
|
||||
/obj/item/medigun_backpack/proc/adjust_toxvol(modifier)
|
||||
if(modifier > toxvol)
|
||||
modifier = toxvol
|
||||
if(modifier > (tankmax - toxcharge))
|
||||
modifier = tankmax - toxcharge
|
||||
toxvol -= modifier
|
||||
toxcharge += modifier
|
||||
|
||||
/obj/item/medigun_backpack/process()
|
||||
if(!bcell)
|
||||
return
|
||||
|
||||
var/obj/item/bork_medigun/medigun = get_medigun()
|
||||
|
||||
if(bcell.charge >= 10)
|
||||
var/icon_needs_update = FALSE
|
||||
if(brutecharge < tankmax && brutevol > 0 && (bcell.checked_use(smaniptier * 2)))
|
||||
adjust_brutevol(smaniptier * 2)
|
||||
icon_needs_update = TRUE
|
||||
if(burncharge < tankmax && burnvol > 0 && (bcell.checked_use(smaniptier * 2)))
|
||||
adjust_burnvol(smaniptier * 2)
|
||||
icon_needs_update = TRUE
|
||||
if(toxcharge < tankmax && toxvol > 0 && (bcell.checked_use(smaniptier * 2)))
|
||||
adjust_toxvol(smaniptier * 2)
|
||||
icon_needs_update = TRUE
|
||||
//Alien tier
|
||||
if(sbintier >= 5 && medigun.busy == MEDIGUN_IDLE && (bcell.charge >= 10))
|
||||
if(brutevol < chemcap && (bcell.checked_use(10)))
|
||||
icon_needs_update = TRUE
|
||||
brutevol ++
|
||||
if(burnvol < chemcap && (bcell.checked_use(10)))
|
||||
icon_needs_update = TRUE
|
||||
burnvol ++
|
||||
if(toxvol < chemcap && (bcell.checked_use(10)))
|
||||
icon_needs_update = TRUE
|
||||
toxvol ++
|
||||
|
||||
if(icon_needs_update)
|
||||
update_icon()
|
||||
|
||||
if(scapacitor.get_rating() >= 5)
|
||||
if(apc_charge())
|
||||
charging = FALSE
|
||||
return
|
||||
charging = TRUE
|
||||
|
||||
if(!charging || !ccell)
|
||||
return
|
||||
|
||||
var/scaptier = scapacitor.get_rating()
|
||||
var/missing = min(scaptier*25, bcell.amount_missing())
|
||||
|
||||
if(missing > 0)
|
||||
if(ccell && ccell.checked_use(missing))
|
||||
bcell.give(missing)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(ismob(loc))
|
||||
to_chat(loc, span_notice("The [ccell] runs out of power.."))
|
||||
charging = FALSE
|
||||
|
||||
/obj/item/medigun_backpack/get_cell()
|
||||
return bcell
|
||||
|
||||
/obj/item/medigun_backpack/update_icon()
|
||||
. = ..()
|
||||
cut_overlays()
|
||||
if((bcell.percent() <= 5 ))
|
||||
add_overlay(image('icons/obj/borkmedigun.dmi', "no_battery"))
|
||||
else if((bcell.percent() <= 25 && bcell.percent() > 5))
|
||||
add_overlay(image('icons/obj/borkmedigun.dmi', "low_battery"))
|
||||
|
||||
if(brutevol <= 0 && brutecharge > 0)
|
||||
add_overlay(image('icons/obj/borkmedigun.dmi', "red"))
|
||||
else if(brutecharge <= 0 && brutevol <= 0)
|
||||
add_overlay(image('icons/obj/borkmedigun.dmi', "redstrike-blink"))
|
||||
|
||||
if(toxvol <= 0 && toxcharge > 0)
|
||||
add_overlay(image('icons/obj/borkmedigun.dmi', "green"))
|
||||
else if(toxcharge <= 0 && toxvol <= 0)
|
||||
add_overlay(image('icons/obj/borkmedigun.dmi', "greenstrike-blink"))
|
||||
|
||||
if(burnvol <= 0 && burncharge > 0)
|
||||
add_overlay(image('icons/obj/borkmedigun.dmi', "orange"))
|
||||
else if(burncharge <= 0 && burnvol <= 0)
|
||||
add_overlay(image('icons/obj/borkmedigun.dmi', "orangestrike-blink"))
|
||||
|
||||
/obj/item/medigun_backpack/proc/replace_icon(inhand)
|
||||
var/obj/item/bork_medigun/medigun = get_medigun()
|
||||
if(inhand)
|
||||
icon_state = "mg-backpack-deployed"
|
||||
item_state = "mg-backpack-deployed-onmob"
|
||||
if(is_twohanded())
|
||||
medigun.icon_state = "medblaster"
|
||||
medigun.base_icon_state = "medblaster"
|
||||
medigun.wielded_item_state = "medblaster-wielded"
|
||||
medigun.update_icon()
|
||||
else
|
||||
medigun.icon_state = "medblaster_cmo"
|
||||
medigun.base_icon_state = "medblaster_cmo"
|
||||
medigun.wielded_item_state = ""
|
||||
medigun.update_icon()
|
||||
else if(is_twohanded())
|
||||
icon_state = "mg-backpack"
|
||||
item_state = "mg-backpack-onmob"
|
||||
medigun.icon_state = "medblaster"
|
||||
medigun.base_icon_state = "medblaster"
|
||||
else
|
||||
icon_state = "mg-backpack_cmo"
|
||||
item_state = "mg-backpack_cmo-onmob"
|
||||
medigun.icon_state = "medblaster_cmo"
|
||||
medigun.base_icon_state = "medblaster_cmo"
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/item/medigun_backpack/Initialize(mapload)
|
||||
AddComponent(/datum/component/tethered_item, medigun_path)
|
||||
. = ..()
|
||||
|
||||
var/obj/item/bork_medigun/linked/medigun = get_medigun()
|
||||
medigun.medigun_base_unit = src
|
||||
|
||||
if(!is_twohanded())
|
||||
medigun.beam_range = 4
|
||||
medigun.icon_state = "medblaster_cmo"
|
||||
medigun.base_icon_state = "medblaster_cmo"
|
||||
medigun.wielded_item_state = ""
|
||||
medigun.update_icon()
|
||||
if(ispath(bcell))
|
||||
bcell = new bcell(src)
|
||||
bcell.charge = 0
|
||||
if(ispath(sbin))
|
||||
sbin = new sbin(src)
|
||||
if(ispath(smodule))
|
||||
smodule = new smodule(src)
|
||||
START_PROCESSING(SSobj, src)
|
||||
if(ispath(smanipulator))
|
||||
smanipulator = new smanipulator(src)
|
||||
if(ispath(scapacitor))
|
||||
scapacitor = new scapacitor(src)
|
||||
if(ispath(slaser))
|
||||
slaser = new slaser(src)
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/item/medigun_backpack/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
QDEL_NULL(bcell)
|
||||
QDEL_NULL(smodule)
|
||||
QDEL_NULL(smanipulator)
|
||||
QDEL_NULL(scapacitor)
|
||||
QDEL_NULL(slaser)
|
||||
. = ..()
|
||||
|
||||
/obj/item/medigun_backpack/proc/get_medigun()
|
||||
var/datum/component/tethered_item/TI = GetComponent(/datum/component/tethered_item)
|
||||
return TI.get_handheld()
|
||||
|
||||
/obj/item/medigun_backpack/emp_act(severity)
|
||||
. = ..()
|
||||
if(bcell)
|
||||
bcell.emp_act(severity)
|
||||
|
||||
/obj/item/medigun_backpack/attack_hand(mob/living/user)
|
||||
// See important note in tethered_item.dm
|
||||
if(SEND_SIGNAL(src,COMSIG_ITEM_ATTACK_SELF,user) & COMPONENT_CANCEL_ATTACK_CHAIN)
|
||||
return TRUE
|
||||
. = ..()
|
||||
|
||||
/obj/item/medigun_backpack/MouseDrop()
|
||||
if(ismob(src.loc))
|
||||
if(!CanMouseDrop(src))
|
||||
return
|
||||
var/mob/M = src.loc
|
||||
if(!M.unEquip(src))
|
||||
return
|
||||
src.add_fingerprint(usr)
|
||||
M.put_in_any_hand_if_possible(src)
|
||||
/*icon_state = "mg-backpack"
|
||||
item_state = "mg-backpack-onmob"
|
||||
update_icon() //success
|
||||
usr.update_inv_back()*/
|
||||
|
||||
|
||||
/obj/item/medigun_backpack/attackby(obj/item/W, mob/user, params)
|
||||
if(refill_reagent(W, user))
|
||||
return
|
||||
|
||||
var/obj/item/bork_medigun/medigun = get_medigun()
|
||||
|
||||
if(W.is_crowbar() && maintenance)
|
||||
if(smodule )
|
||||
smodule.forceMove(get_turf(loc))
|
||||
smodule = null
|
||||
|
||||
if(smanipulator)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
smanipulator.forceMove(get_turf(loc))
|
||||
smanipulator = null
|
||||
smaniptier = 0
|
||||
|
||||
if(slaser)
|
||||
slaser.forceMove(get_turf(loc))
|
||||
slaser = null
|
||||
|
||||
if(scapacitor)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
scapacitor.forceMove(get_turf(loc))
|
||||
scapacitor = null
|
||||
|
||||
if(sbin)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
sbin.forceMove(get_turf(loc))
|
||||
sbin = null
|
||||
sbintier = 0
|
||||
|
||||
to_chat(user, span_notice("You remove the Components from \the [src]."))
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
if(W.is_screwdriver())
|
||||
if(!maintenance)
|
||||
maintenance = TRUE
|
||||
to_chat(user, span_notice("You open the maintenance hatch on \the [src]."))
|
||||
return
|
||||
|
||||
maintenance = FALSE
|
||||
to_chat(user, span_notice("You close the maintenance hatch on \the [src]."))
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/cell))
|
||||
if(!user.unEquip(W))
|
||||
return
|
||||
W.forceMove(src)
|
||||
if(ccell)
|
||||
to_chat(user, span_notice("You swap the [W] for \the [ccell]."))
|
||||
ccell = W
|
||||
to_chat(user, span_notice("You install the [W] into \the [src]."))
|
||||
charging = TRUE
|
||||
return
|
||||
|
||||
if(maintenance)
|
||||
if(istype(W, /obj/item/stock_parts/scanning_module))
|
||||
if(smodule)
|
||||
to_chat(user, span_notice("\The [src] already has a scanning module."))
|
||||
else
|
||||
if(!user.unEquip(W))
|
||||
return
|
||||
W.forceMove(src)
|
||||
smodule = W
|
||||
to_chat(user, span_notice("You install the [W] into \the [src]."))
|
||||
medigun.beam_range = 3+smodule.get_rating()
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/stock_parts/manipulator))
|
||||
if(smanipulator)
|
||||
to_chat(user, span_notice("\The [src] already has a manipulator."))
|
||||
return
|
||||
if(!user.unEquip(W))
|
||||
return
|
||||
W.forceMove(src)
|
||||
smanipulator = W
|
||||
smaniptier = smanipulator.get_rating()
|
||||
if(sbin && scapacitor)START_PROCESSING(SSobj, src)
|
||||
to_chat(user, span_notice("You install the [W] into \the [src]."))
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/stock_parts/micro_laser))
|
||||
if(slaser)
|
||||
to_chat(user, span_notice("\The [src] already has a micro laser."))
|
||||
return
|
||||
if(!user.unEquip(W))
|
||||
return
|
||||
W.forceMove(src)
|
||||
slaser = W
|
||||
to_chat(user, span_notice("You install the [W] into \the [src]."))
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/stock_parts/capacitor))
|
||||
if(scapacitor)
|
||||
to_chat(user, span_notice("\The [src] already has a capacitor."))
|
||||
return
|
||||
if(!user.unEquip(W))
|
||||
return
|
||||
W.forceMove(src)
|
||||
scapacitor = W
|
||||
var/scaptier = scapacitor.get_rating()
|
||||
if(scaptier == 1)
|
||||
chargecap = 1000
|
||||
bcell.maxcharge = 1000
|
||||
if(bcell.charge > chargecap)
|
||||
bcell.charge = chargecap
|
||||
else if(scaptier == 2)
|
||||
chargecap = 2000
|
||||
bcell.maxcharge = 2000
|
||||
if(bcell.charge > chargecap)
|
||||
bcell.charge = chargecap
|
||||
else if(scaptier == 3)
|
||||
chargecap = 3000
|
||||
bcell.maxcharge = 3000
|
||||
if(bcell.charge > chargecap)
|
||||
bcell.charge = chargecap
|
||||
else if(scaptier == 4)
|
||||
chargecap = 4000
|
||||
bcell.maxcharge = 4000
|
||||
if(bcell.charge > chargecap)
|
||||
bcell.charge = chargecap
|
||||
else if(scaptier == 5)
|
||||
chargecap = 5000
|
||||
bcell.maxcharge = 5000
|
||||
if(bcell.charge > chargecap)
|
||||
bcell.charge = chargecap
|
||||
|
||||
if(sbin && smanipulator)START_PROCESSING(SSobj, src)
|
||||
to_chat(user, span_notice("You install the [W] into \the [src]."))
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/stock_parts/matter_bin))
|
||||
if(sbin)
|
||||
to_chat(user, span_notice("\The [src] already has a matter bin."))
|
||||
return
|
||||
if(!user.unEquip(W))
|
||||
return
|
||||
W.forceMove(src)
|
||||
sbin = W
|
||||
sbintier = sbin.get_rating()
|
||||
if(sbintier >= 5)
|
||||
chemcap = 300
|
||||
tankmax = 150
|
||||
else
|
||||
chemcap = 60*(sbintier)
|
||||
tankmax = 30*sbintier
|
||||
if(brutecharge > chemcap)
|
||||
brutecharge = chemcap
|
||||
if(burncharge > chemcap)
|
||||
burncharge = chemcap
|
||||
if(toxcharge > chemcap)
|
||||
toxcharge = chemcap
|
||||
if(brutecharge > tankmax)
|
||||
brutecharge = tankmax
|
||||
if(burncharge > tankmax)
|
||||
burncharge = tankmax
|
||||
if(toxcharge > tankmax)
|
||||
toxcharge = tankmax
|
||||
if(scapacitor && smanipulator)START_PROCESSING(SSobj, src)
|
||||
to_chat(user, span_notice("You install the [W] into \the [src]."))
|
||||
update_icon()
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/medigun_backpack/proc/refill_reagent(var/obj/item/container, mob/user)
|
||||
. = FALSE
|
||||
if(!maintenance && (istype(container, /obj/item/reagent_containers/glass/beaker) || istype(container, /obj/item/reagent_containers/glass/bottle)))
|
||||
|
||||
if(!(container.flags & OPENCONTAINER))
|
||||
to_chat(user, span_warning("You need to open the [container] first!"))
|
||||
return
|
||||
|
||||
var/reagentwhitelist = list(REAGENT_ID_BICARIDINE, REAGENT_ID_ANTITOXIN, REAGENT_ID_KELOTANE, REAGENT_ID_DERMALINE)//, "tricordrazine")
|
||||
|
||||
for(var/G in container.reagents.reagent_list)
|
||||
var/datum/reagent/R = G
|
||||
var/modifier = 1
|
||||
var/totransfer = 0
|
||||
var/name = ""
|
||||
|
||||
if(R.id in reagentwhitelist)
|
||||
switch(R.id)
|
||||
if(REAGENT_ID_BICARIDINE)
|
||||
name = "bruteheal"
|
||||
modifier = 4
|
||||
totransfer = chemcap - brutevol
|
||||
if(REAGENT_ID_ANTITOXIN)
|
||||
name = "toxheal"
|
||||
modifier = 4
|
||||
totransfer = chemcap - toxvol
|
||||
if(REAGENT_ID_KELOTANE)
|
||||
name = "burnheal"
|
||||
modifier = 4
|
||||
totransfer = chemcap - burnvol
|
||||
if(REAGENT_ID_DERMALINE)
|
||||
name = "burnheal"
|
||||
modifier = 8
|
||||
totransfer = chemcap - burnvol
|
||||
/*if("tricordrazine")
|
||||
name = "tricordrazine"
|
||||
modifier = 1
|
||||
if((brutevol != chemcap) && (burnvol != chemcap) && (toxvol != chemcap))
|
||||
totransfer = 1 //tempcheck to get past the totransfer check
|
||||
else
|
||||
totransfer = 0*/
|
||||
if(totransfer <= 0)
|
||||
to_chat(user, span_notice("The [src] cannot accept anymore [name]!"))
|
||||
totransfer = min(totransfer, container.reagents.get_reagent_amount(R.id) * modifier)
|
||||
|
||||
switch(R.id)
|
||||
if(REAGENT_ID_BICARIDINE)
|
||||
brutevol += totransfer
|
||||
if(REAGENT_ID_ANTITOXIN)
|
||||
toxvol += totransfer
|
||||
if(REAGENT_ID_KELOTANE)
|
||||
burnvol += totransfer
|
||||
if(REAGENT_ID_DERMALINE)
|
||||
burnvol += totransfer
|
||||
/*if("tricordrazine") //Tricord too problematic
|
||||
var/maxamount = container.reagents.get_reagent_amount(R.id)
|
||||
var/amountused
|
||||
var/oldbrute = brutevol
|
||||
var/oldburn = burnvol
|
||||
var/oldtox = toxvol
|
||||
|
||||
while(maxamount > 0)
|
||||
if(brutevol >= chemcap && burnvol >= chemcap && toxvol >= chemcap)
|
||||
break
|
||||
maxamount --
|
||||
amountused++
|
||||
totransfer ++
|
||||
if(brutevol < chemcap)
|
||||
brutevol ++
|
||||
if(burnvol < chemcap)
|
||||
burnvol ++
|
||||
if(toxvol < chemcap)
|
||||
toxvol ++
|
||||
var/readout = "You add [amountused] units of [R.name] to the [src]. \n The [src] Stores "
|
||||
var/readoutadditions = FALSE
|
||||
if(oldbrute != brutevol)
|
||||
readout += "[round(brutevol - oldbrute)] U of bruteheal vol"
|
||||
readoutadditions = TRUE
|
||||
if(oldburn != burnvol)
|
||||
if(readoutadditions)
|
||||
readout += ", "
|
||||
readout += "[round(burnvol - oldburn)] U of burnheal vol"
|
||||
readoutadditions = TRUE
|
||||
if(oldtox != toxvol)
|
||||
if(readoutadditions)
|
||||
readout += ", "
|
||||
readout += "[round(toxvol - oldtox)] U of toxheal vol"
|
||||
if(oldbrute != brutevol || oldburn != burnvol || oldtox != toxvol)to_chat(user, span_notice("[readout]."))*/
|
||||
if(totransfer > 0)
|
||||
if(R.id != "tricordrazine")
|
||||
to_chat(user, span_notice("You add [totransfer / modifier] units of [R.name] to the [src]. \n The [src] stores [round(totransfer)] U of [name]."))
|
||||
container.reagents.remove_reagent(R.id, totransfer / modifier)
|
||||
playsound(src, 'sound/weapons/empty.ogg', 50, 1)
|
||||
update_icon()
|
||||
. = TRUE
|
||||
return
|
||||
|
||||
//checks that the base unit is in the correct slot to be used
|
||||
/obj/item/medigun_backpack/proc/slot_check()
|
||||
var/mob/M = loc
|
||||
if(!istype(M))
|
||||
return FALSE //not equipped
|
||||
|
||||
if((slot_flags & SLOT_BACK) && M.get_equipped_item(slot_back) == src)
|
||||
return TRUE
|
||||
if((slot_flags & SLOT_BACK) && M.get_equipped_item(slot_s_store) == src)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/medigun_backpack/dropped(mob/user)
|
||||
..()
|
||||
replace_icon()
|
||||
|
||||
/obj/item/medigun_backpack/proc/checked_use(var/charge_amt)
|
||||
return (bcell && bcell.checked_use(charge_amt))
|
||||
@@ -0,0 +1,167 @@
|
||||
/obj/item/medigun_backpack/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Medigun", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/medigun_backpack/tgui_data(mob/user)
|
||||
var/obj/item/bork_medigun/medigun = get_medigun()
|
||||
var/mob/living/carbon/human/H = medigun.current_target
|
||||
var/patientname
|
||||
var/patienthealth = 0
|
||||
var/patientbruteloss = 0
|
||||
var/patientfireloss = 0
|
||||
var/patienttoxloss = 0
|
||||
var/patientoxyloss = 0
|
||||
var/patientstatus = 0
|
||||
var/list/bloodData = list()
|
||||
var/inner_bleeding = FALSE
|
||||
var/organ_damage = FALSE
|
||||
|
||||
//var/minhealth = 0
|
||||
if(scapacitor?.get_rating() < 5)
|
||||
gridstatus = 3
|
||||
if(H)
|
||||
for(var/obj/item/organ/org in H.internal_organs)
|
||||
if(org.robotic >= ORGAN_ROBOT)
|
||||
continue
|
||||
if(org.status & ORGAN_BLEEDING)
|
||||
inner_bleeding = TRUE
|
||||
if(org.damage >= 1 && !istype(org, /obj/item/organ/internal/brain))
|
||||
organ_damage = TRUE
|
||||
patientname = H
|
||||
patienthealth = max(0, (H.health + abs(-H.getMaxHealth())) / (H.getMaxHealth() + abs(-H.getMaxHealth())))
|
||||
patientbruteloss = H.getBruteLoss()
|
||||
patientfireloss = H.getFireLoss()
|
||||
patienttoxloss = H.getToxLoss()
|
||||
patientoxyloss = H.getOxyLoss()
|
||||
patientstatus = H.stat
|
||||
if(H.vessel)
|
||||
bloodData["volume"] = round(H.vessel.get_reagent_amount("blood"))
|
||||
bloodData["max_volume"] = H.species.blood_volume
|
||||
var/list/data = list(
|
||||
"maintenance" = maintenance,
|
||||
"generator" = charging,
|
||||
"gridstatus" = gridstatus,
|
||||
"tankmax" = tankmax,
|
||||
"power_cell_status" = bcell ? bcell.percent() : null,
|
||||
"cell_status" = ccell ? (ccell.percent()/100) : null,
|
||||
"bruteheal_charge" = scapacitor ? brutecharge : null,
|
||||
"burnheal_charge" = scapacitor ? burncharge : null,
|
||||
"toxheal_charge" = scapacitor ? toxcharge : null,
|
||||
"bruteheal_vol" = sbin ? brutevol : null,
|
||||
"burnheal_vol" = sbin ? burnvol : null,
|
||||
"toxheal_vol" = sbin ? toxvol : null,
|
||||
"patient_name" = smodule ? patientname : null,
|
||||
"patient_health" = smodule ? patienthealth : null,
|
||||
"patient_brute" = smodule ? patientbruteloss : null,
|
||||
"patient_burn" = smodule ? patientfireloss : null,
|
||||
"patient_tox" = smodule ? patienttoxloss : null,
|
||||
"patient_oxy" = smodule ? patientoxyloss : null,
|
||||
"blood_status" = smodule ? bloodData : null,
|
||||
"patient_status" = smodule ? patientstatus : null,
|
||||
"organ_damage" = smodule ? organ_damage : null,
|
||||
"inner_bleeding" = smodule ? inner_bleeding : null,
|
||||
"examine_data" = get_examine_data()
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/item/medigun_backpack/proc/get_examine_data()
|
||||
var/obj/item/bork_medigun/medigun = get_medigun()
|
||||
|
||||
return list(
|
||||
"smodule" = smodule ? list("name" = smodule.name, "range" = medigun.beam_range, "rating" = smodule.get_rating()) : null,
|
||||
"smanipulator" = smanipulator ? list("name" = smanipulator.name, "rating" = smaniptier) : null,
|
||||
"slaser" = slaser ? list("name" = slaser.name, "rating" = slaser.get_rating()) : null,
|
||||
"scapacitor" = scapacitor ? list("name" = scapacitor.name, "chargecap" = chargecap, "rating" = scapacitor.get_rating()) : null,
|
||||
"sbin" = sbin ? list("name" = sbin.name, "chemcap" = chemcap, "tankmax" = tankmax, "rating" = sbin.get_rating()) : null
|
||||
)
|
||||
|
||||
/obj/item/medigun_backpack/tgui_act(action, params, datum/tgui/ui)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
. = TRUE
|
||||
|
||||
var/obj/item/bork_medigun/medigun = get_medigun()
|
||||
|
||||
switch(action)
|
||||
if("celleject")
|
||||
cell_eject()
|
||||
return TRUE
|
||||
|
||||
if("cancel_healing")
|
||||
if(medigun?.busy)
|
||||
medigun.busy = MEDIGUN_CANCELLED
|
||||
return TRUE
|
||||
|
||||
if("toggle_maintenance")
|
||||
maintenance = !maintenance
|
||||
return TRUE
|
||||
|
||||
if("rem_smodule")
|
||||
if(!smodule || !maintenance)
|
||||
return FALSE
|
||||
smodule.forceMove(get_turf(loc))
|
||||
to_chat(ui.user, span_notice("You remove the [smodule] from \the [src]."))
|
||||
smodule = null
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
if("rem_mani")
|
||||
if(!smanipulator || !maintenance)
|
||||
return FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
smanipulator.forceMove(get_turf(loc))
|
||||
to_chat(ui.user, span_notice("You remove the [smanipulator] from \the [src]."))
|
||||
smanipulator = null
|
||||
smaniptier = 0
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
if("rem_laser")
|
||||
if(!slaser || !maintenance)
|
||||
return FALSE
|
||||
slaser.forceMove(get_turf(loc))
|
||||
to_chat(ui.user, span_notice("You remove the [slaser] from \the [src]."))
|
||||
slaser = null
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
if("rem_cap")
|
||||
if(!scapacitor || !maintenance)
|
||||
return FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
scapacitor.forceMove(get_turf(loc))
|
||||
to_chat(ui.user, span_notice("You remove the [scapacitor] from \the [src]."))
|
||||
scapacitor = null
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
if("rem_bin")
|
||||
if(!sbin || !maintenance)
|
||||
return FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
sbin.forceMove(get_turf(loc))
|
||||
to_chat(ui.user, span_notice("You remove the [sbin] from \the [src]."))
|
||||
sbin = null
|
||||
sbintier = 0
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/medigun_backpack/ShiftClick(mob/user)
|
||||
. = ..()
|
||||
var/obj/item/bork_medigun/medigun = get_medigun()
|
||||
if(!medigun)
|
||||
return
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/item/medigun_backpack/proc/cell_eject()
|
||||
if(!ccell)
|
||||
return FALSE
|
||||
charging = FALSE
|
||||
ccell.forceMove(get_turf(loc))
|
||||
to_chat(usr, span_notice("You remove the [ccell] from \the [src]."))
|
||||
ccell = null
|
||||
update_icon()
|
||||
return TRUE
|
||||
@@ -0,0 +1,8 @@
|
||||
/datum/modifier/medbeameffect
|
||||
name = "medgunffect"
|
||||
desc = "You're being stabilized"
|
||||
mob_overlay_state = "medigun_effect"
|
||||
stacks = MODIFIER_STACK_EXTEND
|
||||
//pain_immunity = TRUE
|
||||
bleeding_rate_percent = 0.1 //only a little
|
||||
incoming_oxy_damage_percent = 0
|
||||
@@ -0,0 +1,28 @@
|
||||
/obj/item/medigun_backpack/verb/toggle_medigun()
|
||||
set name = "Toggle medigun"
|
||||
set category = "Object"
|
||||
|
||||
var/mob/living/carbon/human/user = usr
|
||||
if(maintenance)
|
||||
to_chat(user, span_warning("Please close the maintenance hatch with a screwdriver first, or to remove components, use a crowbar."))
|
||||
return
|
||||
|
||||
if(!medigun)
|
||||
to_chat(user, span_warning("The medigun is missing!"))
|
||||
return
|
||||
|
||||
if(medigun.loc != src)
|
||||
reattach_medigun(user) //Remove from their hands and back onto the medigun unit
|
||||
return
|
||||
|
||||
if(!slot_check())
|
||||
to_chat(user, span_warning("You need to equip [src] before taking out [medigun]."))
|
||||
else
|
||||
if(!user.put_in_hands(medigun)) //Detach the medigun into the user's hands
|
||||
to_chat(user, span_warning("You need a free hand to hold the medigun!"))
|
||||
else
|
||||
containsgun = 0
|
||||
replace_icon(TRUE)
|
||||
if(is_twohanded())
|
||||
medigun.update_twohanding()
|
||||
user.update_inv_back()
|
||||
@@ -406,6 +406,7 @@
|
||||
active_armourpen = 25
|
||||
projectile_parry_chance = 40
|
||||
colorable = TRUE
|
||||
item_flags = DROPDEL | NOSTRIP
|
||||
|
||||
hitcost = 75
|
||||
|
||||
|
||||
@@ -870,6 +870,17 @@
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE
|
||||
|
||||
/datum/design_techweb/medigun_constant
|
||||
name = "Prototype Bluespace Medigun Backpack"
|
||||
id = "medigun_constant"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_STEEL = 8000, MAT_PLASTIC = 8000, MAT_GLASS = 5000, MAT_SILVER = 1000, MAT_GOLD = 1000, MAT_URANIUM = 1000)
|
||||
build_path = /obj/item/medigun_backpack
|
||||
category = list(
|
||||
RND_CATEGORY_WEAPONS + RND_SUBCATEGORY_WEAPONS_RANGED
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE
|
||||
|
||||
/datum/design_techweb/upgradeAOE
|
||||
name = "Mining Explosion Upgrade"
|
||||
desc = "An area of effect upgrade for the Proto-Kinetic Accelerator."
|
||||
|
||||
@@ -9,3 +9,16 @@
|
||||
if(check.size_multiplier < 1.25 && check.size_multiplier > 0.75)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/experiment/scanning/people/hurt_medigun
|
||||
required_count = 3
|
||||
required_traits_desc = "Our newly and improvised Medi-Gun needs field testing! Surely, there has to be someone who's gotten a few bruises or scratches here or there."
|
||||
|
||||
/datum/experiment/scanning/people/hurt_medigun/is_valid_scan_target(mob/living/carbon/human/check, datum/component/experiment_handler/experiment_handler)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/HP_percent = check.health/check.getMaxHealth()
|
||||
if(HP_percent < 1)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -173,6 +173,18 @@
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS)
|
||||
announce_channels = list(CHANNEL_MEDICAL)
|
||||
|
||||
/datum/techweb_node/medigun_constant
|
||||
id = TECHWEB_NODE_MEDIGUN_CONSTANT
|
||||
display_name = "Medigun Backpack"
|
||||
description = "A revised version of the ML3M series. This one features a cell-powered constant beam, and ability to charge it with chemicals."
|
||||
prereq_ids = list(TECHWEB_NODE_MEDIGUN)
|
||||
design_ids = list(
|
||||
"medigun_constant"
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS)
|
||||
announce_channels = list(CHANNEL_MEDICAL)
|
||||
discount_experiments = list(/datum/experiment/scanning/people/hurt_medigun = TECHWEB_TIER_3_POINTS)
|
||||
|
||||
/datum/techweb_node/nif
|
||||
id = TECHWEB_NODE_NIF
|
||||
display_name = "Nanite-Implant Frameworks"
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
@@ -0,0 +1,39 @@
|
||||
import { Box, LabeledList, ProgressBar, Stack } from 'tgui-core/components';
|
||||
|
||||
export const ChargeStatus = (props: {
|
||||
name: string;
|
||||
color: string;
|
||||
charge: number | null;
|
||||
max: number | null;
|
||||
volume: number | null;
|
||||
}) => {
|
||||
const { name, color, charge, max, volume } = props;
|
||||
|
||||
return (
|
||||
<LabeledList.Item label={name}>
|
||||
<Stack>
|
||||
<Stack.Item grow>
|
||||
{charge !== null ? (
|
||||
<ProgressBar color={color} value={charge / (max || 1)}>
|
||||
{charge.toFixed()} / {max}
|
||||
</ProgressBar>
|
||||
) : (
|
||||
<Box color="red">Missing Capacitor</Box>
|
||||
)}
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Box color="label">Reserve:</Box>
|
||||
</Stack.Item>
|
||||
<Stack.Item basis="10%">
|
||||
{volume !== null ? (
|
||||
<Box color={color} bold>
|
||||
{volume.toFixed()}
|
||||
</Box>
|
||||
) : (
|
||||
<Box color="red">Missing Bin</Box>
|
||||
)}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</LabeledList.Item>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,270 @@
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
LabeledList,
|
||||
ProgressBar,
|
||||
Section,
|
||||
Stack,
|
||||
} from 'tgui-core/components';
|
||||
import {
|
||||
gridStatusToColor,
|
||||
gridStatusToText,
|
||||
powerToColor,
|
||||
powerToText,
|
||||
statToColor,
|
||||
statToString,
|
||||
} from '../constants';
|
||||
import { ChargeStatus } from '../MedigunHelpers/ChargeStatus';
|
||||
import type { Data, SModule } from '../types';
|
||||
|
||||
export const MedigunContent = (props: { smodule: SModule }) => {
|
||||
const { act, data } = useBackend<Data>();
|
||||
|
||||
const {
|
||||
maintenance,
|
||||
tankmax,
|
||||
generator,
|
||||
gridstatus,
|
||||
power_cell_status,
|
||||
cell_status,
|
||||
bruteheal_charge,
|
||||
burnheal_charge,
|
||||
toxheal_charge,
|
||||
bruteheal_vol,
|
||||
burnheal_vol,
|
||||
toxheal_vol,
|
||||
patient_name,
|
||||
patient_health,
|
||||
patient_brute,
|
||||
patient_burn,
|
||||
patient_tox,
|
||||
patient_oxy,
|
||||
blood_status,
|
||||
patient_status,
|
||||
organ_damage,
|
||||
inner_bleeding,
|
||||
} = data;
|
||||
|
||||
const { smodule } = props;
|
||||
|
||||
const moduleLevel = smodule?.rating || 0;
|
||||
|
||||
return (
|
||||
<Stack vertical fill>
|
||||
<Stack.Item>
|
||||
<Section title="Power Status">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Power Cell">
|
||||
{maintenance ? (
|
||||
<Box color="red">Maintenance Hatch Open</Box>
|
||||
) : power_cell_status !== null ? (
|
||||
<ProgressBar
|
||||
ranges={{
|
||||
good: [50, Infinity],
|
||||
average: [25, 50],
|
||||
bad: [-Infinity, 25],
|
||||
}}
|
||||
minValue={0}
|
||||
maxValue={100}
|
||||
value={power_cell_status}
|
||||
/>
|
||||
) : (
|
||||
<Box color="red">Missing Cell</Box>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
{gridstatus !== 3 && (
|
||||
<LabeledList.Item
|
||||
label="Wireless Power"
|
||||
color={gridStatusToColor[gridstatus]}
|
||||
>
|
||||
{gridStatusToText[gridstatus] || 'Unavailable'}
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
<LabeledList.Item
|
||||
label="Battery Status"
|
||||
color={powerToColor[generator]}
|
||||
buttons={
|
||||
<Button
|
||||
content={generator ? 'Eject' : 'Missing'}
|
||||
selected={generator}
|
||||
color={generator ? '' : 'bad'}
|
||||
onClick={() => act('celleject')}
|
||||
/>
|
||||
}
|
||||
>
|
||||
[ {powerToText[generator] || 'Unavailable'} ]
|
||||
</LabeledList.Item>
|
||||
{cell_status !== null ? (
|
||||
<LabeledList.Item label="Battery Status">
|
||||
<ProgressBar color="green" value={cell_status} />
|
||||
</LabeledList.Item>
|
||||
) : (
|
||||
<Box color="red">Missing Cell</Box>
|
||||
)}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Section title="Heal Charge Status">
|
||||
<LabeledList>
|
||||
<ChargeStatus
|
||||
name="Brute Charge"
|
||||
color="bad"
|
||||
charge={bruteheal_charge}
|
||||
max={tankmax}
|
||||
volume={bruteheal_vol}
|
||||
/>
|
||||
<ChargeStatus
|
||||
name="Burn Charge"
|
||||
color="average"
|
||||
charge={burnheal_charge}
|
||||
max={tankmax}
|
||||
volume={burnheal_vol}
|
||||
/>
|
||||
<ChargeStatus
|
||||
name="Tox Charge"
|
||||
color="good"
|
||||
charge={toxheal_charge}
|
||||
max={tankmax}
|
||||
volume={toxheal_vol}
|
||||
/>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Section fill title="Patient Status">
|
||||
<Stack vertical fill>
|
||||
{patient_health !== null &&
|
||||
patient_brute !== null &&
|
||||
patient_burn !== null &&
|
||||
patient_tox !== null &&
|
||||
patient_oxy !== null ? (
|
||||
<>
|
||||
<Stack.Item>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Name">
|
||||
{patient_name ? (
|
||||
<Stack>
|
||||
<Stack.Item grow>{patient_name}</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => act('cancel_healing')}
|
||||
>
|
||||
Stop Healing
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
) : (
|
||||
'No Target'
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
{!!data.patient_name && (
|
||||
<>
|
||||
<LabeledList.Item label="Total Health">
|
||||
<ProgressBar
|
||||
ranges={{
|
||||
good: [0.5, Infinity],
|
||||
average: [0.25, 0.5],
|
||||
bad: [-Infinity, 0.25],
|
||||
}}
|
||||
value={patient_health}
|
||||
>
|
||||
<Stack>
|
||||
{moduleLevel >= 2 && (
|
||||
<>
|
||||
<Stack.Item grow />
|
||||
{!!organ_damage && (
|
||||
<Stack.Item>
|
||||
<Box bold>Organ Damage!</Box>
|
||||
</Stack.Item>
|
||||
)}
|
||||
{!!patient_status && (
|
||||
<Stack.Item>
|
||||
<Box
|
||||
bold
|
||||
color={statToColor[patient_status]}
|
||||
>
|
||||
{statToString[patient_status]}
|
||||
</Box>
|
||||
</Stack.Item>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<Stack.Item>
|
||||
{`${(patient_health * 100).toFixed()}%`}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
{moduleLevel >= 2 && (
|
||||
<LabeledList.Item label="Blood Volume">
|
||||
{blood_status ? (
|
||||
<ProgressBar
|
||||
color="red"
|
||||
value={
|
||||
blood_status.volume / blood_status.max_volume
|
||||
}
|
||||
>
|
||||
<Stack>
|
||||
<Stack.Item grow />
|
||||
{!!inner_bleeding && (
|
||||
<Stack.Item grow>
|
||||
<Box bold>Inner Bleeding!</Box>
|
||||
</Stack.Item>
|
||||
)}
|
||||
<Stack.Item grow>
|
||||
{`${(
|
||||
(blood_status.volume /
|
||||
blood_status.max_volume) *
|
||||
100
|
||||
).toFixed()}%`}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</ProgressBar>
|
||||
) : (
|
||||
<Box color="red">No Blood Detected</Box>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</LabeledList>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
{!!data.patient_name && moduleLevel >= 2 && (
|
||||
<Stack>
|
||||
<Stack.Item basis="50%">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Brute Damage">
|
||||
<Box color="red">{patient_brute}</Box>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Burn Damage">
|
||||
<Box color="orange">{patient_burn}</Box>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Tox Damage">
|
||||
<Box color="green">{patient_tox}</Box>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Oxy Damage">
|
||||
<Box color="blue">{patient_oxy}</Box>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
)}
|
||||
</Stack.Item>
|
||||
</>
|
||||
) : (
|
||||
<Box color="red">Missing Scanning Module</Box>
|
||||
)}
|
||||
</Stack>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,149 @@
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { Box, Button, LabeledList, Section, Stack } from 'tgui-core/components';
|
||||
import type { BooleanLike } from 'tgui-core/react';
|
||||
import type { ExamineData } from '../types';
|
||||
|
||||
export const MedigunParts = (props: {
|
||||
examineData: ExamineData;
|
||||
maintenance: BooleanLike;
|
||||
}) => {
|
||||
const { act } = useBackend();
|
||||
const { examineData, maintenance } = props;
|
||||
const { smodule, smanipulator, slaser, scapacitor, sbin } = examineData;
|
||||
|
||||
return (
|
||||
<Section
|
||||
fill
|
||||
title="Installed Modules"
|
||||
buttons={
|
||||
<Button
|
||||
onClick={() => act('toggle_maintenance')}
|
||||
selected={maintenance}
|
||||
tooltip="Toggle maintenance mode"
|
||||
icon="wrench"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Stack vertical fill>
|
||||
<Stack.Item>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Scanning Module">
|
||||
{smodule ? (
|
||||
maintenance ? (
|
||||
<Button.Confirm onClick={() => act('rem_smodule')}>
|
||||
Remove Module
|
||||
</Button.Confirm>
|
||||
) : (
|
||||
<Box>
|
||||
{'It has a ' +
|
||||
smodule.name +
|
||||
' installed, device will function within ' +
|
||||
smodule.range +
|
||||
' tiles'}
|
||||
{smodule.rating >= 5 ? ' and' : undefined}
|
||||
{smodule.rating >= 5 ? ' through walls' : undefined}
|
||||
{'.'}
|
||||
</Box>
|
||||
)
|
||||
) : (
|
||||
<Box color="red">Missing</Box>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Manipulator">
|
||||
{smanipulator ? (
|
||||
maintenance ? (
|
||||
<Button.Confirm onClick={() => act('rem_mani')}>
|
||||
Remove Manipulator
|
||||
</Button.Confirm>
|
||||
) : (
|
||||
<Box>
|
||||
{'It has a ' +
|
||||
smanipulator.name +
|
||||
' installed, chem digitizing is '}
|
||||
{smanipulator.rating >= 5
|
||||
? '125% Efficient'
|
||||
: `${(smanipulator.rating / 4) * 100}% Efficient`}
|
||||
{'.'}
|
||||
</Box>
|
||||
)
|
||||
) : (
|
||||
<Box color="red">Missing</Box>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Laser">
|
||||
{slaser ? (
|
||||
maintenance ? (
|
||||
<Button.Confirm onClick={() => act('rem_laser')}>
|
||||
Remove Laser
|
||||
</Button.Confirm>
|
||||
) : (
|
||||
<Box>
|
||||
{'It has a ' +
|
||||
slaser.name +
|
||||
' installed, and can heal ' +
|
||||
slaser.rating +
|
||||
' damage per cycle'}
|
||||
{slaser.rating >= 5 ? ' and will' : undefined}
|
||||
{slaser.rating >= 5 ? ' regenerate blood' : undefined}
|
||||
{slaser.rating >= 5 ? ' while beam is focused' : ''}
|
||||
{'.'}
|
||||
</Box>
|
||||
)
|
||||
) : (
|
||||
<Box color="red">Missing</Box>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Capacitor">
|
||||
{scapacitor ? (
|
||||
maintenance ? (
|
||||
<Button.Confirm onClick={() => act('rem_cap')}>
|
||||
Remove Capacitor
|
||||
</Button.Confirm>
|
||||
) : (
|
||||
<Box>
|
||||
{'It has a ' +
|
||||
scapacitor.name +
|
||||
' installed, battery Capacity is ' +
|
||||
scapacitor.chargecap +
|
||||
' Units'}
|
||||
{scapacitor.rating >= 5
|
||||
? ' the cell will recharge from the local power grid'
|
||||
: ''}
|
||||
{''}
|
||||
{'.'}
|
||||
</Box>
|
||||
)
|
||||
) : (
|
||||
<Box color="red">Missing</Box>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Matter Bin">
|
||||
{sbin ? (
|
||||
maintenance ? (
|
||||
<Button.Confirm onClick={() => act('rem_bin')}>
|
||||
Remove Bin
|
||||
</Button.Confirm>
|
||||
) : (
|
||||
<Box>
|
||||
{'It has a ' +
|
||||
sbin.name +
|
||||
' installed, can hold ' +
|
||||
sbin.tankmax +
|
||||
' charge and ' +
|
||||
sbin.chemcap +
|
||||
' reserve chems'}
|
||||
{sbin.rating >= 5
|
||||
? 'and will slowly generate chems in exchange for power.'
|
||||
: '.'}
|
||||
</Box>
|
||||
)
|
||||
) : (
|
||||
<Box color="red">Missing</Box>
|
||||
)}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
export const powerToColor = ['bad', 'good'];
|
||||
|
||||
export const powerToText = ['Cell Offline', 'Cell Charging'];
|
||||
|
||||
export const gridStatusToColor = ['bad', 'average', 'good'];
|
||||
|
||||
export const gridStatusToText = ['Off Grid', 'Grid Available', 'Using Grid'];
|
||||
|
||||
export const statToString = ['Alive', 'Unconscious', 'Dead'];
|
||||
|
||||
export const statToColor = ['orange', 'red'];
|
||||
@@ -0,0 +1,45 @@
|
||||
import { useState } from 'react';
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { Window } from 'tgui/layouts';
|
||||
import { Stack, Tabs } from 'tgui-core/components';
|
||||
import { MedigunContent } from './MedigunTabs/MedigunContent';
|
||||
import { MedigunParts } from './MedigunTabs/MedigunParts';
|
||||
import type { Data } from './types';
|
||||
|
||||
export const Medigun = (props) => {
|
||||
const { data } = useBackend<Data>();
|
||||
const { maintenance, examine_data } = data;
|
||||
const [selectedTab, setSelectedTab] = useState(0);
|
||||
|
||||
const tab: React.JSX.Element[] = [];
|
||||
tab[0] = <MedigunContent smodule={examine_data.smodule} />;
|
||||
tab[1] = (
|
||||
<MedigunParts examineData={examine_data} maintenance={maintenance} />
|
||||
);
|
||||
|
||||
return (
|
||||
<Window width={450} height={500}>
|
||||
<Window.Content>
|
||||
<Stack vertical fill>
|
||||
<Stack.Item>
|
||||
<Tabs>
|
||||
<Tabs.Tab
|
||||
selected={selectedTab === 0}
|
||||
onClick={() => setSelectedTab(0)}
|
||||
>
|
||||
Medigun Content
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
selected={selectedTab === 1}
|
||||
onClick={() => setSelectedTab(1)}
|
||||
>
|
||||
Medigun Parts
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>{tab[selectedTab]}</Stack.Item>
|
||||
</Stack>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
import type { BooleanLike } from 'tgui-core/react';
|
||||
|
||||
export type Data = {
|
||||
maintenance: BooleanLike;
|
||||
tankmax: number;
|
||||
generator: number;
|
||||
gridstatus: number;
|
||||
power_cell_status: number | null;
|
||||
cell_status: number | null;
|
||||
bruteheal_charge: number | null;
|
||||
burnheal_charge: number | null;
|
||||
toxheal_charge: number | null;
|
||||
bruteheal_vol: number | null;
|
||||
burnheal_vol: number | null;
|
||||
toxheal_vol: number | null;
|
||||
patient_name: string | null;
|
||||
patient_health: number | null;
|
||||
patient_brute: number | null;
|
||||
patient_burn: number | null;
|
||||
patient_tox: number | null;
|
||||
patient_oxy: number | null;
|
||||
blood_status: { volume: number; max_volume: number } | null;
|
||||
patient_status: number | null;
|
||||
organ_damage: BooleanLike;
|
||||
inner_bleeding: BooleanLike;
|
||||
examine_data: ExamineData;
|
||||
};
|
||||
|
||||
export type SModule = { name: string; range: number; rating: number } | null;
|
||||
|
||||
export type ExamineData = {
|
||||
smodule: SModule;
|
||||
smanipulator: { name: string; rating: number } | null;
|
||||
slaser: { name: string; rating: number } | null;
|
||||
scapacitor: {
|
||||
name: string;
|
||||
chargecap: number;
|
||||
rating: number;
|
||||
} | null;
|
||||
sbin: {
|
||||
name: string;
|
||||
chemcap: number;
|
||||
tankmax: number;
|
||||
rating: number;
|
||||
} | null;
|
||||
};
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable react/no-danger */
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { Window } from 'tgui/layouts';
|
||||
import { Box, Section, Stack, Tabs } from 'tgui-core/components';
|
||||
|
||||
@@ -128,6 +128,7 @@
|
||||
#include "code\__defines\matrices.dm"
|
||||
#include "code\__defines\MC.dm"
|
||||
#include "code\__defines\mecha.dm"
|
||||
#include "code\__defines\medigun.dm"
|
||||
#include "code\__defines\misc.dm"
|
||||
#include "code\__defines\misc_ch.dm"
|
||||
#include "code\__defines\mobs.dm"
|
||||
@@ -1948,6 +1949,11 @@
|
||||
#include "code\game\objects\items\weapons\material\twohanded_ch.dm"
|
||||
#include "code\game\objects\items\weapons\material\twohanded_vr.dm"
|
||||
#include "code\game\objects\items\weapons\material\whetstone.dm"
|
||||
#include "code\game\objects\items\weapons\medigun\bork_medigun.dm"
|
||||
#include "code\game\objects\items\weapons\medigun\linked_medigun.dm"
|
||||
#include "code\game\objects\items\weapons\medigun\medigun_backpack.dm"
|
||||
#include "code\game\objects\items\weapons\medigun\medigun_backpack_ui.dm"
|
||||
#include "code\game\objects\items\weapons\medigun\medigun_modifiers.dm"
|
||||
#include "code\game\objects\items\weapons\melee\deflect.dm"
|
||||
#include "code\game\objects\items\weapons\melee\energy.dm"
|
||||
#include "code\game\objects\items\weapons\melee\energy_vr.dm"
|
||||
|
||||
Reference in New Issue
Block a user