mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-10 01:49:19 +00:00
285 lines
8.0 KiB
Plaintext
285 lines
8.0 KiB
Plaintext
#define CHRONO_BEAM_RANGE 3
|
|
#define CHRONO_FRAME_COUNT 22
|
|
/obj/item/chrono_eraser
|
|
name = "Timestream Eradication Device"
|
|
desc = "The result of outlawed time-bluespace research, this device is capable of wiping a being from the timestream. They never are, they never were, they never will be."
|
|
icon = 'icons/obj/chronos.dmi'
|
|
icon_state = "chronobackpack"
|
|
item_state = "backpack"
|
|
lefthand_file = 'icons/mob/inhands/equipment/backpack_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/backpack_righthand.dmi'
|
|
w_class = WEIGHT_CLASS_BULKY
|
|
slot_flags = ITEM_SLOT_BACK
|
|
slowdown = 1
|
|
actions_types = list(/datum/action/item_action/equip_unequip_TED_Gun)
|
|
var/obj/item/gun/energy/chrono_gun/PA = null
|
|
var/list/erased_minds = list() //a collection of minds from the dead
|
|
|
|
/obj/item/chrono_eraser/proc/pass_mind(datum/mind/M)
|
|
erased_minds += M
|
|
|
|
/obj/item/chrono_eraser/dropped(mob/user)
|
|
..()
|
|
if(PA)
|
|
qdel(PA)
|
|
|
|
/obj/item/chrono_eraser/ui_action_click(mob/user)
|
|
if(iscarbon(user))
|
|
var/mob/living/carbon/C = user
|
|
if(C.back == src)
|
|
if(PA)
|
|
qdel(PA)
|
|
else
|
|
PA = new(src)
|
|
user.put_in_hands(PA)
|
|
|
|
/obj/item/chrono_eraser/item_action_slot_check(slot, mob/user, datum/action/A)
|
|
if(slot == ITEM_SLOT_BACK)
|
|
return 1
|
|
|
|
/obj/item/gun/energy/chrono_gun
|
|
name = "T.E.D. Projection Apparatus"
|
|
desc = "It's as if they never existed in the first place."
|
|
icon = 'icons/obj/chronos.dmi'
|
|
icon_state = "chronogun"
|
|
item_state = "chronogun"
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
item_flags = DROPDEL
|
|
ammo_type = list(/obj/item/ammo_casing/energy/chrono_beam)
|
|
can_charge = 0
|
|
fire_delay = 50
|
|
var/obj/item/chrono_eraser/TED = null
|
|
var/obj/effect/chrono_field/field = null
|
|
var/turf/startpos = null
|
|
|
|
/obj/item/gun/energy/chrono_gun/Initialize(mapload)
|
|
. = ..()
|
|
ADD_TRAIT(src, TRAIT_NODROP, CHRONO_GUN_TRAIT)
|
|
if(istype(loc, /obj/item/chrono_eraser))
|
|
TED = loc
|
|
else //admin must have spawned it
|
|
TED = new(src.loc)
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
/obj/item/gun/energy/chrono_gun/ComponentInitialize()
|
|
. = ..()
|
|
AddElement(/datum/element/update_icon_blocker)
|
|
|
|
/obj/item/gun/energy/chrono_gun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
|
|
if(field)
|
|
field_disconnect(field)
|
|
..()
|
|
|
|
/obj/item/gun/energy/chrono_gun/Destroy()
|
|
if(TED)
|
|
TED.PA = null
|
|
TED = null
|
|
if(field)
|
|
field_disconnect(field)
|
|
return ..()
|
|
|
|
/obj/item/gun/energy/chrono_gun/proc/field_connect(obj/effect/chrono_field/F)
|
|
var/mob/living/user = src.loc
|
|
if(F.gun)
|
|
if(isliving(user) && F.captured)
|
|
to_chat(user, "<span class='alert'><b>FAIL: <i>[F.captured]</i> already has an existing connection.</b></span>")
|
|
src.field_disconnect(F)
|
|
else
|
|
startpos = get_turf(src)
|
|
field = F
|
|
F.gun = src
|
|
if(isliving(user) && F.captured)
|
|
to_chat(user, "<span class='notice'>Connection established with target: <b>[F.captured]</b></span>")
|
|
|
|
|
|
/obj/item/gun/energy/chrono_gun/proc/field_disconnect(obj/effect/chrono_field/F)
|
|
if(F && field == F)
|
|
var/mob/living/user = src.loc
|
|
if(F.gun == src)
|
|
F.gun = null
|
|
if(isliving(user) && F.captured)
|
|
to_chat(user, "<span class='alert'>Disconnected from target: <b>[F.captured]</b></span>")
|
|
field = null
|
|
startpos = null
|
|
|
|
/obj/item/gun/energy/chrono_gun/proc/field_check(obj/effect/chrono_field/F)
|
|
if(F)
|
|
if(field == F)
|
|
var/turf/currentpos = get_turf(src)
|
|
var/mob/living/user = src.loc
|
|
if((currentpos == startpos) && (field in view(CHRONO_BEAM_RANGE, currentpos)) && !user.lying && (user.stat == CONSCIOUS))
|
|
return 1
|
|
field_disconnect(F)
|
|
return 0
|
|
|
|
/obj/item/gun/energy/chrono_gun/proc/pass_mind(datum/mind/M)
|
|
if(TED)
|
|
TED.pass_mind(M)
|
|
|
|
|
|
/obj/item/projectile/energy/chrono_beam
|
|
name = "eradication beam"
|
|
icon_state = "chronobolt"
|
|
range = CHRONO_BEAM_RANGE
|
|
nodamage = 1
|
|
var/obj/item/gun/energy/chrono_gun/gun = null
|
|
|
|
/obj/item/projectile/energy/chrono_beam/Initialize(mapload)
|
|
. = ..()
|
|
var/obj/item/ammo_casing/energy/chrono_beam/C = loc
|
|
if(istype(C))
|
|
gun = C.gun
|
|
|
|
/obj/item/projectile/energy/chrono_beam/Destroy()
|
|
gun = null
|
|
return ..()
|
|
|
|
|
|
/obj/item/projectile/energy/chrono_beam/on_hit(atom/target)
|
|
if(target && gun && isliving(target))
|
|
var/obj/effect/chrono_field/F = new(target.loc, target, gun)
|
|
gun.field_connect(F)
|
|
|
|
|
|
/obj/item/ammo_casing/energy/chrono_beam
|
|
name = "eradication beam"
|
|
projectile_type = /obj/item/projectile/energy/chrono_beam
|
|
icon_state = "chronobolt"
|
|
e_cost = 0
|
|
var/obj/item/gun/energy/chrono_gun/gun
|
|
|
|
/obj/item/ammo_casing/energy/chrono_beam/Initialize(mapload)
|
|
if(istype(loc))
|
|
gun = loc
|
|
. = ..()
|
|
|
|
/obj/item/ammo_casing/energy/chrono_beam/Destroy()
|
|
gun = null
|
|
return ..()
|
|
|
|
|
|
|
|
/obj/effect/chrono_field
|
|
name = "eradication field"
|
|
desc = "An aura of time-bluespace energy."
|
|
icon = 'icons/effects/effects.dmi'
|
|
icon_state = "chronofield"
|
|
density = FALSE
|
|
anchored = TRUE
|
|
blend_mode = BLEND_MULTIPLY
|
|
var/mob/living/captured = null
|
|
var/obj/item/gun/energy/chrono_gun/gun = null
|
|
var/tickstokill = 15
|
|
var/mutable_appearance/mob_underlay
|
|
var/preloaded = 0
|
|
var/RPpos = null
|
|
|
|
/obj/effect/chrono_field/New(loc, var/mob/living/target, var/obj/item/gun/energy/chrono_gun/G)
|
|
if(target && isliving(target) && G)
|
|
target.forceMove(src)
|
|
src.captured = target
|
|
var/icon/mob_snapshot = getFlatIcon(target)
|
|
var/icon/cached_icon = new()
|
|
|
|
for(var/i=1, i<=CHRONO_FRAME_COUNT, i++)
|
|
var/icon/removing_frame = icon('icons/obj/chronos.dmi', "erasing", SOUTH, i)
|
|
var/icon/mob_icon = icon(mob_snapshot)
|
|
mob_icon.Blend(removing_frame, ICON_MULTIPLY)
|
|
cached_icon.Insert(mob_icon, "frame[i]")
|
|
|
|
mob_underlay = mutable_appearance(cached_icon, "frame1")
|
|
update_icon()
|
|
|
|
desc = initial(desc) + "<br><span class='info'>It appears to contain [target.name].</span>"
|
|
START_PROCESSING(SSobj, src)
|
|
|
|
/obj/effect/chrono_field/Destroy()
|
|
if(gun && gun.field_check(src))
|
|
gun.field_disconnect(src)
|
|
return ..()
|
|
|
|
/obj/effect/chrono_field/update_icon()
|
|
var/ttk_frame = 1 - (tickstokill / initial(tickstokill))
|
|
ttk_frame = clamp(CEILING(ttk_frame * CHRONO_FRAME_COUNT, 1), 1, CHRONO_FRAME_COUNT)
|
|
if(ttk_frame != RPpos)
|
|
RPpos = ttk_frame
|
|
mob_underlay.icon_state = "frame[RPpos]"
|
|
underlays = list() //hack: BYOND refuses to update the underlay to match the icon_state otherwise
|
|
underlays += mob_underlay
|
|
|
|
/obj/effect/chrono_field/process()
|
|
if(captured)
|
|
if(tickstokill > initial(tickstokill))
|
|
for(var/atom/movable/AM in contents)
|
|
AM.forceMove(drop_location())
|
|
qdel(src)
|
|
else if(tickstokill <= 0)
|
|
to_chat(captured, "<span class='boldnotice'>As the last essence of your being is erased from time, you begin to re-experience your most enjoyable memory. You feel happy...</span>")
|
|
var/mob/dead/observer/ghost = captured.ghostize(1)
|
|
if(captured.mind)
|
|
if(ghost)
|
|
ghost.mind = null
|
|
if(gun)
|
|
gun.pass_mind(captured.mind)
|
|
qdel(captured)
|
|
qdel(src)
|
|
else
|
|
captured.Unconscious(80)
|
|
if(captured.loc != src)
|
|
captured.forceMove(src)
|
|
update_icon()
|
|
if(gun)
|
|
if(gun.field_check(src))
|
|
tickstokill--
|
|
else
|
|
gun = null
|
|
return .()
|
|
else
|
|
tickstokill++
|
|
else
|
|
qdel(src)
|
|
|
|
/obj/effect/chrono_field/bullet_act(obj/item/projectile/P)
|
|
if(istype(P, /obj/item/projectile/energy/chrono_beam))
|
|
var/obj/item/projectile/energy/chrono_beam/beam = P
|
|
var/obj/item/gun/energy/chrono_gun/Pgun = beam.gun
|
|
if(Pgun && istype(Pgun))
|
|
Pgun.field_connect(src)
|
|
else
|
|
return BULLET_ACT_HIT
|
|
|
|
/obj/effect/chrono_field/assume_air()
|
|
return null
|
|
|
|
/obj/effect/chrono_field/assume_air_moles()
|
|
return null
|
|
|
|
/obj/effect/chrono_field/assume_air_ratio()
|
|
return null
|
|
|
|
/obj/effect/chrono_field/return_air() //we always have nominal air and temperature
|
|
var/datum/gas_mixture/GM = new
|
|
GM.set_moles(GAS_O2, MOLES_O2STANDARD)
|
|
GM.set_moles(GAS_N2, MOLES_N2STANDARD)
|
|
GM.set_temperature(T20C)
|
|
return GM
|
|
|
|
/obj/effect/chrono_field/Move()
|
|
return
|
|
|
|
/obj/effect/chrono_field/singularity_act()
|
|
return
|
|
|
|
/obj/effect/chrono_field/singularity_pull()
|
|
return
|
|
|
|
/obj/effect/chrono_field/ex_act(severity, target, origin)
|
|
return
|
|
|
|
/obj/effect/chrono_field/blob_act(obj/structure/blob/B)
|
|
return
|
|
|
|
|
|
#undef CHRONO_BEAM_RANGE
|
|
#undef CHRONO_FRAME_COUNT
|