mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-22 04:28:33 +01:00
Whitespace Standardization [MDB IGNORE] (#15748)
* Update settings * Whitespace changes * Comment out merger hooks in gitattributes Corrupt maps would have to be resolved in repo before hooks could be updated * Revert "Whitespace changes" This reverts commitafbdd1d844. * Whitespace again minus example * Gitignore example changelog * Restore changelog merge setting * Keep older dmi hook attribute until hooks can be updated * update vscode settings too * Renormalize remaining * Revert "Gitignore example changelog" This reverts commitde22ad375d. * Attempt to normalize example.yml (and another file I guess) * Try again
This commit is contained in:
+208
-208
@@ -1,208 +1,208 @@
|
||||
|
||||
|
||||
/atom/movable
|
||||
var/can_buckle = FALSE
|
||||
var/buckle_movable = 0
|
||||
var/buckle_dir = 0
|
||||
var/buckle_lying = -1 //bed-like behavior, forces mob.lying = buckle_lying if != -1
|
||||
var/buckle_require_restraints = 0 //require people to be handcuffed before being able to buckle. eg: pipes
|
||||
// var/mob/living/buckled_mob = null
|
||||
var/list/mob/living/buckled_mobs = null //list()
|
||||
var/max_buckled_mobs = 1
|
||||
|
||||
|
||||
/atom/movable/attack_hand(mob/living/user)
|
||||
. = ..()
|
||||
// if(can_buckle && buckled_mob)
|
||||
// user_unbuckle_mob(user)
|
||||
|
||||
if(can_buckle && has_buckled_mobs())
|
||||
if(buckled_mobs.len > 1)
|
||||
var/unbuckled = tgui_input_list(user, "Who do you wish to unbuckle?","Unbuckle Who?", buckled_mobs)
|
||||
if(user_unbuckle_mob(unbuckled, user))
|
||||
return TRUE
|
||||
else
|
||||
if(user_unbuckle_mob(buckled_mobs[1], user))
|
||||
return TRUE
|
||||
|
||||
/obj/proc/attack_alien(mob/user as mob) //For calling in the event of Xenomorph or other alien checks.
|
||||
return
|
||||
|
||||
/obj/attack_robot(mob/living/user)
|
||||
if(Adjacent(user) && has_buckled_mobs()) //Checks if what we're touching is adjacent to us and has someone buckled to it. This should prevent interacting with anti-robot manual valves among other things.
|
||||
return attack_hand(user) //Process as if we're a normal person touching the object.
|
||||
return ..() //Otherwise, treat this as an AI click like usual.
|
||||
|
||||
/atom/movable/MouseDrop_T(mob/living/M, mob/living/user)
|
||||
. = ..()
|
||||
if(can_buckle && istype(M))
|
||||
if(user_buckle_mob(M, user))
|
||||
return TRUE
|
||||
|
||||
/atom/movable/proc/has_buckled_mobs()
|
||||
return LAZYLEN(buckled_mobs)
|
||||
|
||||
/atom/movable/Destroy()
|
||||
unbuckle_all_mobs()
|
||||
return ..()
|
||||
|
||||
|
||||
/atom/movable/proc/buckle_mob(mob/living/M, forced = FALSE, check_loc = TRUE)
|
||||
if(check_loc && M.loc != loc)
|
||||
return FALSE
|
||||
|
||||
if(!can_buckle_check(M, forced))
|
||||
return FALSE
|
||||
|
||||
if(M == src)
|
||||
stack_trace("Recursive buckle warning: [M] being buckled to self.")
|
||||
return
|
||||
|
||||
M.buckled = src
|
||||
M.facing_dir = null
|
||||
M.set_dir(buckle_dir ? buckle_dir : dir)
|
||||
M.update_canmove()
|
||||
M.update_floating( M.Check_Dense_Object() )
|
||||
// buckled_mob = M
|
||||
buckled_mobs |= M
|
||||
|
||||
//VOREStation Add
|
||||
if(riding_datum)
|
||||
riding_datum.ridden = src
|
||||
riding_datum.handle_vehicle_offsets()
|
||||
M.update_water()
|
||||
//VOREStation Add End
|
||||
|
||||
post_buckle_mob(M)
|
||||
M.throw_alert("buckled", /obj/screen/alert/restrained/buckled, new_master = src)
|
||||
return TRUE
|
||||
|
||||
/atom/movable/proc/unbuckle_mob(mob/living/buckled_mob, force = FALSE)
|
||||
if(!buckled_mob) // If we didn't get told which mob needs to get unbuckled, just assume its the first one on the list.
|
||||
if(has_buckled_mobs())
|
||||
buckled_mob = buckled_mobs[1]
|
||||
else
|
||||
return
|
||||
|
||||
if(buckled_mob && buckled_mob.buckled == src)
|
||||
. = buckled_mob
|
||||
buckled_mob.buckled = null
|
||||
buckled_mob.anchored = initial(buckled_mob.anchored)
|
||||
buckled_mob.update_canmove()
|
||||
buckled_mob.update_floating( buckled_mob.Check_Dense_Object() )
|
||||
buckled_mob.clear_alert("buckled")
|
||||
// buckled_mob = null
|
||||
buckled_mobs -= buckled_mob
|
||||
|
||||
//VOREStation Add
|
||||
buckled_mob.update_water()
|
||||
if(riding_datum)
|
||||
riding_datum.restore_position(buckled_mob)
|
||||
riding_datum.handle_vehicle_offsets() // So the person in back goes to the front.
|
||||
//VOREStation Add End
|
||||
post_buckle_mob(.)
|
||||
|
||||
/atom/movable/proc/unbuckle_all_mobs(force = FALSE)
|
||||
if(!has_buckled_mobs())
|
||||
return
|
||||
for(var/m in buckled_mobs)
|
||||
unbuckle_mob(m, force)
|
||||
|
||||
//Handle any extras after buckling/unbuckling
|
||||
//Called on buckle_mob() and unbuckle_mob()
|
||||
/atom/movable/proc/post_buckle_mob(mob/living/M)
|
||||
return
|
||||
|
||||
//Wrapper procs that handle sanity and user feedback
|
||||
/atom/movable/proc/user_buckle_mob(mob/living/M, mob/user, var/forced = FALSE, var/silent = FALSE)
|
||||
if(!ticker)
|
||||
to_chat(user, "<span class='warning'>You can't buckle anyone in before the game starts.</span>")
|
||||
return FALSE // Is this really needed?
|
||||
if(!user.Adjacent(M) || user.restrained() || user.stat || istype(user, /mob/living/silicon/pai))
|
||||
return FALSE
|
||||
if(M in buckled_mobs)
|
||||
to_chat(user, "<span class='warning'>\The [M] is already buckled to \the [src].</span>")
|
||||
return FALSE
|
||||
if(!can_buckle_check(M, forced))
|
||||
return FALSE
|
||||
|
||||
add_fingerprint(user)
|
||||
// unbuckle_mob()
|
||||
|
||||
//can't buckle unless you share locs so try to move M to the obj.
|
||||
if(M.loc != src.loc)
|
||||
if(M.Adjacent(src) && user.Adjacent(src))
|
||||
M.forceMove(get_turf(src))
|
||||
// step_towards(M, src)
|
||||
|
||||
. = buckle_mob(M, forced)
|
||||
playsound(src, 'sound/effects/seatbelt.ogg', 50, 1)
|
||||
if(.)
|
||||
var/reveal_message = list("buckled_mob" = null, "buckled_to" = null) //VORE EDIT: This being a list and messages existing for the buckle target atom.
|
||||
if(!silent)
|
||||
if(M == user)
|
||||
reveal_message["buckled_mob"] = "<span class='notice'>You come out of hiding and buckle yourself to [src].</span>" //VORE EDIT
|
||||
reveal_message["buckled_to"] = "<span class='notice'>You come out of hiding as [M.name] buckles themselves to you.</span>" //VORE EDIT
|
||||
M.visible_message(\
|
||||
"<span class='notice'>[M.name] buckles themselves to [src].</span>",\
|
||||
"<span class='notice'>You buckle yourself to [src].</span>",\
|
||||
"<span class='notice'>You hear metal clanking.</span>")
|
||||
else
|
||||
reveal_message["buckled_mob"] = "<span class='notice'>You are revealed as you are buckled to [src].</span>" //VORE EDIT
|
||||
reveal_message["buckled_to"] = "<span class='notice'>You are revealed as [M.name] is buckled to you.</span>" //VORE EDIT
|
||||
M.visible_message(\
|
||||
"<span class='danger'>[M.name] is buckled to [src] by [user.name]!</span>",\
|
||||
"<span class='danger'>You are buckled to [src] by [user.name]!</span>",\
|
||||
"<span class='notice'>You hear metal clanking.</span>")
|
||||
|
||||
M.reveal(silent, reveal_message["buckled_mob"]) //Reveal people so they aren't buckled to chairs from behind. //VORE EDIT, list arg instead of simple message var for buckled mob
|
||||
//Vore edit start
|
||||
var/mob/living/L = src
|
||||
if(istype(L))
|
||||
L.reveal(silent, reveal_message["buckled_to"])
|
||||
//Vore edit end
|
||||
|
||||
/atom/movable/proc/user_unbuckle_mob(mob/living/buckled_mob, mob/user)
|
||||
var/mob/living/M = unbuckle_mob(buckled_mob)
|
||||
playsound(src, 'sound/effects/seatbelt.ogg', 50, 1)
|
||||
if(M)
|
||||
if(M != user)
|
||||
M.visible_message(\
|
||||
"<span class='notice'>[M.name] was unbuckled by [user.name]!</span>",\
|
||||
"<span class='notice'>You were unbuckled from [src] by [user.name].</span>",\
|
||||
"<span class='notice'>You hear metal clanking.</span>")
|
||||
else
|
||||
M.visible_message(\
|
||||
"<span class='notice'>[M.name] unbuckled themselves!</span>",\
|
||||
"<span class='notice'>You unbuckle yourself from [src].</span>",\
|
||||
"<span class='notice'>You hear metal clanking.</span>")
|
||||
add_fingerprint(user)
|
||||
return M
|
||||
|
||||
/atom/movable/proc/handle_buckled_mob_movement(atom/old_loc, direct, movetime)
|
||||
for(var/mob/living/L as anything in buckled_mobs)
|
||||
if(!L.Move(loc, direct, movetime))
|
||||
L.forceMove(loc, direct, movetime)
|
||||
L.last_move = last_move
|
||||
L.inertia_dir = last_move
|
||||
|
||||
if(!buckle_dir)
|
||||
L.set_dir(dir)
|
||||
else
|
||||
L.set_dir(buckle_dir)
|
||||
|
||||
/atom/movable/proc/can_buckle_check(mob/living/M, forced = FALSE)
|
||||
if(!buckled_mobs)
|
||||
buckled_mobs = list()
|
||||
|
||||
if(!istype(M))
|
||||
return FALSE
|
||||
|
||||
if((!can_buckle && !forced) || M.buckled || M.pinned.len || (buckled_mobs.len >= max_buckled_mobs) || (buckle_require_restraints && !M.restrained()))
|
||||
return FALSE
|
||||
|
||||
if(has_buckled_mobs() && buckled_mobs.len >= max_buckled_mobs) //Handles trying to buckle yourself to the chair when someone is on it
|
||||
to_chat(M, "<span class='notice'>\The [src] can't buckle anymore people.</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
/atom/movable
|
||||
var/can_buckle = FALSE
|
||||
var/buckle_movable = 0
|
||||
var/buckle_dir = 0
|
||||
var/buckle_lying = -1 //bed-like behavior, forces mob.lying = buckle_lying if != -1
|
||||
var/buckle_require_restraints = 0 //require people to be handcuffed before being able to buckle. eg: pipes
|
||||
// var/mob/living/buckled_mob = null
|
||||
var/list/mob/living/buckled_mobs = null //list()
|
||||
var/max_buckled_mobs = 1
|
||||
|
||||
|
||||
/atom/movable/attack_hand(mob/living/user)
|
||||
. = ..()
|
||||
// if(can_buckle && buckled_mob)
|
||||
// user_unbuckle_mob(user)
|
||||
|
||||
if(can_buckle && has_buckled_mobs())
|
||||
if(buckled_mobs.len > 1)
|
||||
var/unbuckled = tgui_input_list(user, "Who do you wish to unbuckle?","Unbuckle Who?", buckled_mobs)
|
||||
if(user_unbuckle_mob(unbuckled, user))
|
||||
return TRUE
|
||||
else
|
||||
if(user_unbuckle_mob(buckled_mobs[1], user))
|
||||
return TRUE
|
||||
|
||||
/obj/proc/attack_alien(mob/user as mob) //For calling in the event of Xenomorph or other alien checks.
|
||||
return
|
||||
|
||||
/obj/attack_robot(mob/living/user)
|
||||
if(Adjacent(user) && has_buckled_mobs()) //Checks if what we're touching is adjacent to us and has someone buckled to it. This should prevent interacting with anti-robot manual valves among other things.
|
||||
return attack_hand(user) //Process as if we're a normal person touching the object.
|
||||
return ..() //Otherwise, treat this as an AI click like usual.
|
||||
|
||||
/atom/movable/MouseDrop_T(mob/living/M, mob/living/user)
|
||||
. = ..()
|
||||
if(can_buckle && istype(M))
|
||||
if(user_buckle_mob(M, user))
|
||||
return TRUE
|
||||
|
||||
/atom/movable/proc/has_buckled_mobs()
|
||||
return LAZYLEN(buckled_mobs)
|
||||
|
||||
/atom/movable/Destroy()
|
||||
unbuckle_all_mobs()
|
||||
return ..()
|
||||
|
||||
|
||||
/atom/movable/proc/buckle_mob(mob/living/M, forced = FALSE, check_loc = TRUE)
|
||||
if(check_loc && M.loc != loc)
|
||||
return FALSE
|
||||
|
||||
if(!can_buckle_check(M, forced))
|
||||
return FALSE
|
||||
|
||||
if(M == src)
|
||||
stack_trace("Recursive buckle warning: [M] being buckled to self.")
|
||||
return
|
||||
|
||||
M.buckled = src
|
||||
M.facing_dir = null
|
||||
M.set_dir(buckle_dir ? buckle_dir : dir)
|
||||
M.update_canmove()
|
||||
M.update_floating( M.Check_Dense_Object() )
|
||||
// buckled_mob = M
|
||||
buckled_mobs |= M
|
||||
|
||||
//VOREStation Add
|
||||
if(riding_datum)
|
||||
riding_datum.ridden = src
|
||||
riding_datum.handle_vehicle_offsets()
|
||||
M.update_water()
|
||||
//VOREStation Add End
|
||||
|
||||
post_buckle_mob(M)
|
||||
M.throw_alert("buckled", /obj/screen/alert/restrained/buckled, new_master = src)
|
||||
return TRUE
|
||||
|
||||
/atom/movable/proc/unbuckle_mob(mob/living/buckled_mob, force = FALSE)
|
||||
if(!buckled_mob) // If we didn't get told which mob needs to get unbuckled, just assume its the first one on the list.
|
||||
if(has_buckled_mobs())
|
||||
buckled_mob = buckled_mobs[1]
|
||||
else
|
||||
return
|
||||
|
||||
if(buckled_mob && buckled_mob.buckled == src)
|
||||
. = buckled_mob
|
||||
buckled_mob.buckled = null
|
||||
buckled_mob.anchored = initial(buckled_mob.anchored)
|
||||
buckled_mob.update_canmove()
|
||||
buckled_mob.update_floating( buckled_mob.Check_Dense_Object() )
|
||||
buckled_mob.clear_alert("buckled")
|
||||
// buckled_mob = null
|
||||
buckled_mobs -= buckled_mob
|
||||
|
||||
//VOREStation Add
|
||||
buckled_mob.update_water()
|
||||
if(riding_datum)
|
||||
riding_datum.restore_position(buckled_mob)
|
||||
riding_datum.handle_vehicle_offsets() // So the person in back goes to the front.
|
||||
//VOREStation Add End
|
||||
post_buckle_mob(.)
|
||||
|
||||
/atom/movable/proc/unbuckle_all_mobs(force = FALSE)
|
||||
if(!has_buckled_mobs())
|
||||
return
|
||||
for(var/m in buckled_mobs)
|
||||
unbuckle_mob(m, force)
|
||||
|
||||
//Handle any extras after buckling/unbuckling
|
||||
//Called on buckle_mob() and unbuckle_mob()
|
||||
/atom/movable/proc/post_buckle_mob(mob/living/M)
|
||||
return
|
||||
|
||||
//Wrapper procs that handle sanity and user feedback
|
||||
/atom/movable/proc/user_buckle_mob(mob/living/M, mob/user, var/forced = FALSE, var/silent = FALSE)
|
||||
if(!ticker)
|
||||
to_chat(user, "<span class='warning'>You can't buckle anyone in before the game starts.</span>")
|
||||
return FALSE // Is this really needed?
|
||||
if(!user.Adjacent(M) || user.restrained() || user.stat || istype(user, /mob/living/silicon/pai))
|
||||
return FALSE
|
||||
if(M in buckled_mobs)
|
||||
to_chat(user, "<span class='warning'>\The [M] is already buckled to \the [src].</span>")
|
||||
return FALSE
|
||||
if(!can_buckle_check(M, forced))
|
||||
return FALSE
|
||||
|
||||
add_fingerprint(user)
|
||||
// unbuckle_mob()
|
||||
|
||||
//can't buckle unless you share locs so try to move M to the obj.
|
||||
if(M.loc != src.loc)
|
||||
if(M.Adjacent(src) && user.Adjacent(src))
|
||||
M.forceMove(get_turf(src))
|
||||
// step_towards(M, src)
|
||||
|
||||
. = buckle_mob(M, forced)
|
||||
playsound(src, 'sound/effects/seatbelt.ogg', 50, 1)
|
||||
if(.)
|
||||
var/reveal_message = list("buckled_mob" = null, "buckled_to" = null) //VORE EDIT: This being a list and messages existing for the buckle target atom.
|
||||
if(!silent)
|
||||
if(M == user)
|
||||
reveal_message["buckled_mob"] = "<span class='notice'>You come out of hiding and buckle yourself to [src].</span>" //VORE EDIT
|
||||
reveal_message["buckled_to"] = "<span class='notice'>You come out of hiding as [M.name] buckles themselves to you.</span>" //VORE EDIT
|
||||
M.visible_message(\
|
||||
"<span class='notice'>[M.name] buckles themselves to [src].</span>",\
|
||||
"<span class='notice'>You buckle yourself to [src].</span>",\
|
||||
"<span class='notice'>You hear metal clanking.</span>")
|
||||
else
|
||||
reveal_message["buckled_mob"] = "<span class='notice'>You are revealed as you are buckled to [src].</span>" //VORE EDIT
|
||||
reveal_message["buckled_to"] = "<span class='notice'>You are revealed as [M.name] is buckled to you.</span>" //VORE EDIT
|
||||
M.visible_message(\
|
||||
"<span class='danger'>[M.name] is buckled to [src] by [user.name]!</span>",\
|
||||
"<span class='danger'>You are buckled to [src] by [user.name]!</span>",\
|
||||
"<span class='notice'>You hear metal clanking.</span>")
|
||||
|
||||
M.reveal(silent, reveal_message["buckled_mob"]) //Reveal people so they aren't buckled to chairs from behind. //VORE EDIT, list arg instead of simple message var for buckled mob
|
||||
//Vore edit start
|
||||
var/mob/living/L = src
|
||||
if(istype(L))
|
||||
L.reveal(silent, reveal_message["buckled_to"])
|
||||
//Vore edit end
|
||||
|
||||
/atom/movable/proc/user_unbuckle_mob(mob/living/buckled_mob, mob/user)
|
||||
var/mob/living/M = unbuckle_mob(buckled_mob)
|
||||
playsound(src, 'sound/effects/seatbelt.ogg', 50, 1)
|
||||
if(M)
|
||||
if(M != user)
|
||||
M.visible_message(\
|
||||
"<span class='notice'>[M.name] was unbuckled by [user.name]!</span>",\
|
||||
"<span class='notice'>You were unbuckled from [src] by [user.name].</span>",\
|
||||
"<span class='notice'>You hear metal clanking.</span>")
|
||||
else
|
||||
M.visible_message(\
|
||||
"<span class='notice'>[M.name] unbuckled themselves!</span>",\
|
||||
"<span class='notice'>You unbuckle yourself from [src].</span>",\
|
||||
"<span class='notice'>You hear metal clanking.</span>")
|
||||
add_fingerprint(user)
|
||||
return M
|
||||
|
||||
/atom/movable/proc/handle_buckled_mob_movement(atom/old_loc, direct, movetime)
|
||||
for(var/mob/living/L as anything in buckled_mobs)
|
||||
if(!L.Move(loc, direct, movetime))
|
||||
L.forceMove(loc, direct, movetime)
|
||||
L.last_move = last_move
|
||||
L.inertia_dir = last_move
|
||||
|
||||
if(!buckle_dir)
|
||||
L.set_dir(dir)
|
||||
else
|
||||
L.set_dir(buckle_dir)
|
||||
|
||||
/atom/movable/proc/can_buckle_check(mob/living/M, forced = FALSE)
|
||||
if(!buckled_mobs)
|
||||
buckled_mobs = list()
|
||||
|
||||
if(!istype(M))
|
||||
return FALSE
|
||||
|
||||
if((!can_buckle && !forced) || M.buckled || M.pinned.len || (buckled_mobs.len >= max_buckled_mobs) || (buckle_require_restraints && !M.restrained()))
|
||||
return FALSE
|
||||
|
||||
if(has_buckled_mobs() && buckled_mobs.len >= max_buckled_mobs) //Handles trying to buckle yourself to the chair when someone is on it
|
||||
to_chat(M, "<span class='notice'>\The [src] can't buckle anymore people.</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
var/list/obj/effect/bump_teleporter/BUMP_TELEPORTERS = list()
|
||||
|
||||
/obj/effect/bump_teleporter
|
||||
name = "bump-teleporter"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x2"
|
||||
var/id = null //id of this bump_teleporter.
|
||||
var/id_target = null //id of bump_teleporter which this moves you to.
|
||||
invisibility = 101 //nope, can't see this
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
opacity = 0
|
||||
|
||||
/obj/effect/bump_teleporter/New()
|
||||
..()
|
||||
BUMP_TELEPORTERS += src
|
||||
|
||||
/obj/effect/bump_teleporter/Destroy()
|
||||
BUMP_TELEPORTERS -= src
|
||||
return ..()
|
||||
|
||||
/obj/effect/bump_teleporter/Bumped(atom/user)
|
||||
if(!ismob(user))
|
||||
//user.loc = src.loc //Stop at teleporter location
|
||||
return
|
||||
var/mob/M = user //VOREStation edit
|
||||
if(!id_target)
|
||||
//user.loc = src.loc //Stop at teleporter location, there is nowhere to teleport to.
|
||||
return
|
||||
|
||||
for(var/obj/effect/bump_teleporter/BT in BUMP_TELEPORTERS)
|
||||
if(BT.id == src.id_target)
|
||||
M.forceMove(BT.loc) //Teleport to location with correct id. //VOREStation Edit
|
||||
return
|
||||
var/list/obj/effect/bump_teleporter/BUMP_TELEPORTERS = list()
|
||||
|
||||
/obj/effect/bump_teleporter
|
||||
name = "bump-teleporter"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x2"
|
||||
var/id = null //id of this bump_teleporter.
|
||||
var/id_target = null //id of bump_teleporter which this moves you to.
|
||||
invisibility = 101 //nope, can't see this
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
opacity = 0
|
||||
|
||||
/obj/effect/bump_teleporter/New()
|
||||
..()
|
||||
BUMP_TELEPORTERS += src
|
||||
|
||||
/obj/effect/bump_teleporter/Destroy()
|
||||
BUMP_TELEPORTERS -= src
|
||||
return ..()
|
||||
|
||||
/obj/effect/bump_teleporter/Bumped(atom/user)
|
||||
if(!ismob(user))
|
||||
//user.loc = src.loc //Stop at teleporter location
|
||||
return
|
||||
var/mob/M = user //VOREStation edit
|
||||
if(!id_target)
|
||||
//user.loc = src.loc //Stop at teleporter location, there is nowhere to teleport to.
|
||||
return
|
||||
|
||||
for(var/obj/effect/bump_teleporter/BT in BUMP_TELEPORTERS)
|
||||
if(BT.id == src.id_target)
|
||||
M.forceMove(BT.loc) //Teleport to location with correct id. //VOREStation Edit
|
||||
return
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
/obj/effect/decal/cleanable/blood/xeno
|
||||
name = "xeno blood"
|
||||
desc = "It's green and acidic. It looks like... <i>blood?</i>"
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
basecolor = "#05EE05"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno
|
||||
name = "xeno gibs"
|
||||
desc = "Gnarly..."
|
||||
icon_state = "xgib1"
|
||||
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6")
|
||||
basecolor = "#05EE05"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno/update_icon()
|
||||
color = "#FFFFFF"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno/up
|
||||
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6","xgibup1","xgibup1","xgibup1")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno/down
|
||||
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6","xgibdown1","xgibdown1","xgibdown1")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno/body
|
||||
random_icon_states = list("xgibhead", "xgibtorso")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno/limb
|
||||
random_icon_states = list("xgibleg", "xgibarm")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno/core
|
||||
random_icon_states = list("xgibmid1", "xgibmid2", "xgibmid3")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/xtracks
|
||||
/obj/effect/decal/cleanable/blood/xeno
|
||||
name = "xeno blood"
|
||||
desc = "It's green and acidic. It looks like... <i>blood?</i>"
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
basecolor = "#05EE05"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno
|
||||
name = "xeno gibs"
|
||||
desc = "Gnarly..."
|
||||
icon_state = "xgib1"
|
||||
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6")
|
||||
basecolor = "#05EE05"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno/update_icon()
|
||||
color = "#FFFFFF"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno/up
|
||||
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6","xgibup1","xgibup1","xgibup1")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno/down
|
||||
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6","xgibdown1","xgibdown1","xgibdown1")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno/body
|
||||
random_icon_states = list("xgibhead", "xgibtorso")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno/limb
|
||||
random_icon_states = list("xgibleg", "xgibarm")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/xeno/core
|
||||
random_icon_states = list("xgibmid1", "xgibmid2", "xgibmid3")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/xtracks
|
||||
basecolor = "#05EE05"
|
||||
@@ -1,253 +1,253 @@
|
||||
#define DRYING_TIME 5 * 60*10 //for 1 unit of depth in puddle (amount var)
|
||||
|
||||
var/global/list/image/splatter_cache=list()
|
||||
|
||||
/obj/effect/decal/cleanable/blood
|
||||
name = "blood"
|
||||
var/dryname = "dried blood"
|
||||
desc = "It's thick and gooey. Perhaps it's the chef's cooking?"
|
||||
var/drydesc = "It's dry and crusty. Someone is not doing their job."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
plane = BLOOD_PLANE
|
||||
layer = BLOOD_DECAL_LAYER
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "mfloor1"
|
||||
random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7")
|
||||
var/base_icon = 'icons/effects/blood.dmi'
|
||||
blood_DNA = list()
|
||||
var/basecolor="#A10808" // Color when wet.
|
||||
var/synthblood = 0
|
||||
var/list/datum/disease2/disease/virus2 = list()
|
||||
var/amount = 5
|
||||
generic_filth = TRUE
|
||||
persistent = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/blood/reveal_blood()
|
||||
if(!fluorescent)
|
||||
fluorescent = 1
|
||||
basecolor = COLOR_LUMINOL
|
||||
update_icon()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/clean_blood()
|
||||
fluorescent = 0
|
||||
if(invisibility != 100)
|
||||
invisibility = 100
|
||||
amount = 0
|
||||
..(ignore=1)
|
||||
|
||||
/obj/effect/decal/cleanable/blood/New()
|
||||
..()
|
||||
update_icon()
|
||||
if(istype(src, /obj/effect/decal/cleanable/blood/gibs))
|
||||
return
|
||||
if(src.type == /obj/effect/decal/cleanable/blood)
|
||||
if(src.loc && isturf(src.loc))
|
||||
for(var/obj/effect/decal/cleanable/blood/B in src.loc)
|
||||
if(B != src)
|
||||
if (B.blood_DNA)
|
||||
blood_DNA |= B.blood_DNA.Copy()
|
||||
qdel(B)
|
||||
addtimer(CALLBACK(src, PROC_REF(dry)), DRYING_TIME * (amount+1))
|
||||
|
||||
/obj/effect/decal/cleanable/blood/update_icon()
|
||||
if(basecolor == "rainbow") basecolor = get_random_colour(1)
|
||||
color = basecolor
|
||||
|
||||
if(basecolor == SYNTH_BLOOD_COLOUR)
|
||||
name = "oil"
|
||||
desc = "It's quite oily."
|
||||
else if(synthblood)
|
||||
name = "synthetic blood"
|
||||
desc = "It's quite greasy."
|
||||
else
|
||||
name = initial(name)
|
||||
desc = initial(desc)
|
||||
|
||||
/obj/effect/decal/cleanable/blood/Crossed(mob/living/carbon/human/perp)
|
||||
if(perp.is_incorporeal())
|
||||
return
|
||||
if (!istype(perp))
|
||||
return
|
||||
if(amount < 1)
|
||||
return
|
||||
|
||||
var/obj/item/organ/external/l_foot = perp.get_organ("l_foot")
|
||||
var/obj/item/organ/external/r_foot = perp.get_organ("r_foot")
|
||||
var/hasfeet = 1
|
||||
if((!l_foot || l_foot.is_stump()) && (!r_foot || r_foot.is_stump()))
|
||||
hasfeet = 0
|
||||
if(perp.shoes && !perp.buckled)//Adding blood to shoes
|
||||
var/obj/item/clothing/shoes/S = perp.shoes
|
||||
if(istype(S))
|
||||
S.blood_color = basecolor
|
||||
S.track_blood = max(amount,S.track_blood)
|
||||
if(!S.blood_overlay)
|
||||
S.generate_blood_overlay()
|
||||
if(!S.blood_DNA)
|
||||
S.blood_DNA = list()
|
||||
S.blood_overlay.color = basecolor
|
||||
S.add_overlay(S.blood_overlay)
|
||||
if(S.blood_overlay && S.blood_overlay.color != basecolor)
|
||||
S.blood_overlay.color = basecolor
|
||||
S.add_overlay(S.blood_overlay)
|
||||
S.blood_DNA |= blood_DNA.Copy()
|
||||
perp.update_inv_shoes()
|
||||
|
||||
else if (hasfeet)//Or feet
|
||||
perp.feet_blood_color = basecolor
|
||||
perp.track_blood = max(amount,perp.track_blood)
|
||||
LAZYINITLIST(perp.feet_blood_DNA)
|
||||
perp.feet_blood_DNA |= blood_DNA.Copy()
|
||||
perp.update_bloodied()
|
||||
else if (perp.buckled && istype(perp.buckled, /obj/structure/bed/chair/wheelchair))
|
||||
var/obj/structure/bed/chair/wheelchair/W = perp.buckled
|
||||
W.bloodiness = 4
|
||||
|
||||
amount--
|
||||
|
||||
/obj/effect/decal/cleanable/blood/proc/dry()
|
||||
name = dryname
|
||||
desc = drydesc
|
||||
color = adjust_brightness(color, -50)
|
||||
amount = 0
|
||||
|
||||
/obj/effect/decal/cleanable/blood/attack_hand(mob/living/carbon/human/user)
|
||||
..()
|
||||
if (amount && istype(user))
|
||||
add_fingerprint(user)
|
||||
if (user.gloves)
|
||||
return
|
||||
var/taken = rand(1,amount)
|
||||
amount -= taken
|
||||
to_chat(user, "<span class='notice'>You get some of \the [src] on your hands.</span>")
|
||||
if (!user.blood_DNA)
|
||||
user.blood_DNA = list()
|
||||
user.blood_DNA |= blood_DNA.Copy()
|
||||
user.bloody_hands += taken
|
||||
user.hand_blood_color = basecolor
|
||||
user.update_inv_gloves(1)
|
||||
user.verbs += /mob/living/carbon/human/proc/bloody_doodle
|
||||
|
||||
/obj/effect/decal/cleanable/blood/splatter
|
||||
random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5")
|
||||
amount = 2
|
||||
|
||||
/obj/effect/decal/cleanable/blood/drip
|
||||
name = "drips of blood"
|
||||
desc = "It's red."
|
||||
gender = PLURAL
|
||||
icon = 'icons/effects/drip.dmi'
|
||||
icon_state = "1"
|
||||
random_icon_states = list("1","2","3","4","5")
|
||||
amount = 0
|
||||
var/list/drips = list()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/drip/New()
|
||||
..()
|
||||
drips |= icon_state
|
||||
|
||||
/obj/effect/decal/cleanable/blood/writing
|
||||
icon_state = "tracks"
|
||||
desc = "It looks like a writing in blood."
|
||||
gender = NEUTER
|
||||
random_icon_states = list("writing1","writing2","writing3","writing4","writing5")
|
||||
amount = 0
|
||||
var/message
|
||||
|
||||
/obj/effect/decal/cleanable/blood/writing/New()
|
||||
..()
|
||||
if(random_icon_states.len)
|
||||
for(var/obj/effect/decal/cleanable/blood/writing/W in loc)
|
||||
random_icon_states.Remove(W.icon_state)
|
||||
icon_state = pick(random_icon_states)
|
||||
else
|
||||
icon_state = "writing1"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/writing/examine(mob/user)
|
||||
. = ..()
|
||||
. += "It reads: <font color='[basecolor]'>\"[message]\"</font>"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs
|
||||
name = "gibs"
|
||||
desc = "They look bloody and gruesome."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "gibbl5"
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib5", "gib6")
|
||||
var/fleshcolor = "#FFFFFF"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/update_icon()
|
||||
|
||||
var/image/giblets = new(base_icon, "[icon_state]_flesh", dir)
|
||||
if(!fleshcolor || fleshcolor == "rainbow")
|
||||
fleshcolor = get_random_colour(1)
|
||||
giblets.color = fleshcolor
|
||||
|
||||
var/icon/blood = new(base_icon,"[icon_state]",dir)
|
||||
if(basecolor == "rainbow") basecolor = get_random_colour(1)
|
||||
blood.Blend(basecolor,ICON_MULTIPLY)
|
||||
|
||||
icon = blood
|
||||
cut_overlays()
|
||||
add_overlay(giblets)
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/up
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib5", "gib6","gibup1","gibup1","gibup1")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/down
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/body
|
||||
random_icon_states = list("gibhead", "gibtorso")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/limb
|
||||
random_icon_states = list("gibleg", "gibarm")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/core
|
||||
random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
|
||||
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/proc/streak(var/list/directions)
|
||||
spawn (0)
|
||||
var/direction = pick(directions)
|
||||
for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++)
|
||||
sleep(3)
|
||||
if (i > 0)
|
||||
var/obj/effect/decal/cleanable/blood/b = new /obj/effect/decal/cleanable/blood/splatter(src.loc)
|
||||
b.basecolor = src.basecolor
|
||||
b.update_icon()
|
||||
|
||||
if (step_to(src, get_step(src, direction), 0))
|
||||
break
|
||||
|
||||
|
||||
/obj/effect/decal/cleanable/mucus
|
||||
name = "mucus"
|
||||
desc = "Disgusting mucus."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "mucus"
|
||||
random_icon_states = list("mucus")
|
||||
|
||||
var/list/datum/disease2/disease/virus2 = list()
|
||||
var/dry = 0 // Keeps the lag down
|
||||
|
||||
/obj/effect/decal/cleanable/mucus/Initialize()
|
||||
. = ..()
|
||||
VARSET_IN(src, dry, TRUE, DRYING_TIME * 2)
|
||||
|
||||
//This version should be used for admin spawns and pre-mapped virus vectors (e.g. in PoIs), this version does not dry
|
||||
/obj/effect/decal/cleanable/mucus/mapped/Initialize()
|
||||
. = ..()
|
||||
virus2 |= new /datum/disease2/disease
|
||||
virus2[1].makerandom()
|
||||
|
||||
/obj/effect/decal/cleanable/mucus/mapped/Destroy()
|
||||
virus2.Cut()
|
||||
return ..()
|
||||
#define DRYING_TIME 5 * 60*10 //for 1 unit of depth in puddle (amount var)
|
||||
|
||||
var/global/list/image/splatter_cache=list()
|
||||
|
||||
/obj/effect/decal/cleanable/blood
|
||||
name = "blood"
|
||||
var/dryname = "dried blood"
|
||||
desc = "It's thick and gooey. Perhaps it's the chef's cooking?"
|
||||
var/drydesc = "It's dry and crusty. Someone is not doing their job."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
plane = BLOOD_PLANE
|
||||
layer = BLOOD_DECAL_LAYER
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "mfloor1"
|
||||
random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7")
|
||||
var/base_icon = 'icons/effects/blood.dmi'
|
||||
blood_DNA = list()
|
||||
var/basecolor="#A10808" // Color when wet.
|
||||
var/synthblood = 0
|
||||
var/list/datum/disease2/disease/virus2 = list()
|
||||
var/amount = 5
|
||||
generic_filth = TRUE
|
||||
persistent = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/blood/reveal_blood()
|
||||
if(!fluorescent)
|
||||
fluorescent = 1
|
||||
basecolor = COLOR_LUMINOL
|
||||
update_icon()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/clean_blood()
|
||||
fluorescent = 0
|
||||
if(invisibility != 100)
|
||||
invisibility = 100
|
||||
amount = 0
|
||||
..(ignore=1)
|
||||
|
||||
/obj/effect/decal/cleanable/blood/New()
|
||||
..()
|
||||
update_icon()
|
||||
if(istype(src, /obj/effect/decal/cleanable/blood/gibs))
|
||||
return
|
||||
if(src.type == /obj/effect/decal/cleanable/blood)
|
||||
if(src.loc && isturf(src.loc))
|
||||
for(var/obj/effect/decal/cleanable/blood/B in src.loc)
|
||||
if(B != src)
|
||||
if (B.blood_DNA)
|
||||
blood_DNA |= B.blood_DNA.Copy()
|
||||
qdel(B)
|
||||
addtimer(CALLBACK(src, PROC_REF(dry)), DRYING_TIME * (amount+1))
|
||||
|
||||
/obj/effect/decal/cleanable/blood/update_icon()
|
||||
if(basecolor == "rainbow") basecolor = get_random_colour(1)
|
||||
color = basecolor
|
||||
|
||||
if(basecolor == SYNTH_BLOOD_COLOUR)
|
||||
name = "oil"
|
||||
desc = "It's quite oily."
|
||||
else if(synthblood)
|
||||
name = "synthetic blood"
|
||||
desc = "It's quite greasy."
|
||||
else
|
||||
name = initial(name)
|
||||
desc = initial(desc)
|
||||
|
||||
/obj/effect/decal/cleanable/blood/Crossed(mob/living/carbon/human/perp)
|
||||
if(perp.is_incorporeal())
|
||||
return
|
||||
if (!istype(perp))
|
||||
return
|
||||
if(amount < 1)
|
||||
return
|
||||
|
||||
var/obj/item/organ/external/l_foot = perp.get_organ("l_foot")
|
||||
var/obj/item/organ/external/r_foot = perp.get_organ("r_foot")
|
||||
var/hasfeet = 1
|
||||
if((!l_foot || l_foot.is_stump()) && (!r_foot || r_foot.is_stump()))
|
||||
hasfeet = 0
|
||||
if(perp.shoes && !perp.buckled)//Adding blood to shoes
|
||||
var/obj/item/clothing/shoes/S = perp.shoes
|
||||
if(istype(S))
|
||||
S.blood_color = basecolor
|
||||
S.track_blood = max(amount,S.track_blood)
|
||||
if(!S.blood_overlay)
|
||||
S.generate_blood_overlay()
|
||||
if(!S.blood_DNA)
|
||||
S.blood_DNA = list()
|
||||
S.blood_overlay.color = basecolor
|
||||
S.add_overlay(S.blood_overlay)
|
||||
if(S.blood_overlay && S.blood_overlay.color != basecolor)
|
||||
S.blood_overlay.color = basecolor
|
||||
S.add_overlay(S.blood_overlay)
|
||||
S.blood_DNA |= blood_DNA.Copy()
|
||||
perp.update_inv_shoes()
|
||||
|
||||
else if (hasfeet)//Or feet
|
||||
perp.feet_blood_color = basecolor
|
||||
perp.track_blood = max(amount,perp.track_blood)
|
||||
LAZYINITLIST(perp.feet_blood_DNA)
|
||||
perp.feet_blood_DNA |= blood_DNA.Copy()
|
||||
perp.update_bloodied()
|
||||
else if (perp.buckled && istype(perp.buckled, /obj/structure/bed/chair/wheelchair))
|
||||
var/obj/structure/bed/chair/wheelchair/W = perp.buckled
|
||||
W.bloodiness = 4
|
||||
|
||||
amount--
|
||||
|
||||
/obj/effect/decal/cleanable/blood/proc/dry()
|
||||
name = dryname
|
||||
desc = drydesc
|
||||
color = adjust_brightness(color, -50)
|
||||
amount = 0
|
||||
|
||||
/obj/effect/decal/cleanable/blood/attack_hand(mob/living/carbon/human/user)
|
||||
..()
|
||||
if (amount && istype(user))
|
||||
add_fingerprint(user)
|
||||
if (user.gloves)
|
||||
return
|
||||
var/taken = rand(1,amount)
|
||||
amount -= taken
|
||||
to_chat(user, "<span class='notice'>You get some of \the [src] on your hands.</span>")
|
||||
if (!user.blood_DNA)
|
||||
user.blood_DNA = list()
|
||||
user.blood_DNA |= blood_DNA.Copy()
|
||||
user.bloody_hands += taken
|
||||
user.hand_blood_color = basecolor
|
||||
user.update_inv_gloves(1)
|
||||
user.verbs += /mob/living/carbon/human/proc/bloody_doodle
|
||||
|
||||
/obj/effect/decal/cleanable/blood/splatter
|
||||
random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5")
|
||||
amount = 2
|
||||
|
||||
/obj/effect/decal/cleanable/blood/drip
|
||||
name = "drips of blood"
|
||||
desc = "It's red."
|
||||
gender = PLURAL
|
||||
icon = 'icons/effects/drip.dmi'
|
||||
icon_state = "1"
|
||||
random_icon_states = list("1","2","3","4","5")
|
||||
amount = 0
|
||||
var/list/drips = list()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/drip/New()
|
||||
..()
|
||||
drips |= icon_state
|
||||
|
||||
/obj/effect/decal/cleanable/blood/writing
|
||||
icon_state = "tracks"
|
||||
desc = "It looks like a writing in blood."
|
||||
gender = NEUTER
|
||||
random_icon_states = list("writing1","writing2","writing3","writing4","writing5")
|
||||
amount = 0
|
||||
var/message
|
||||
|
||||
/obj/effect/decal/cleanable/blood/writing/New()
|
||||
..()
|
||||
if(random_icon_states.len)
|
||||
for(var/obj/effect/decal/cleanable/blood/writing/W in loc)
|
||||
random_icon_states.Remove(W.icon_state)
|
||||
icon_state = pick(random_icon_states)
|
||||
else
|
||||
icon_state = "writing1"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/writing/examine(mob/user)
|
||||
. = ..()
|
||||
. += "It reads: <font color='[basecolor]'>\"[message]\"</font>"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs
|
||||
name = "gibs"
|
||||
desc = "They look bloody and gruesome."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "gibbl5"
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib5", "gib6")
|
||||
var/fleshcolor = "#FFFFFF"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/update_icon()
|
||||
|
||||
var/image/giblets = new(base_icon, "[icon_state]_flesh", dir)
|
||||
if(!fleshcolor || fleshcolor == "rainbow")
|
||||
fleshcolor = get_random_colour(1)
|
||||
giblets.color = fleshcolor
|
||||
|
||||
var/icon/blood = new(base_icon,"[icon_state]",dir)
|
||||
if(basecolor == "rainbow") basecolor = get_random_colour(1)
|
||||
blood.Blend(basecolor,ICON_MULTIPLY)
|
||||
|
||||
icon = blood
|
||||
cut_overlays()
|
||||
add_overlay(giblets)
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/up
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib5", "gib6","gibup1","gibup1","gibup1")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/down
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/body
|
||||
random_icon_states = list("gibhead", "gibtorso")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/limb
|
||||
random_icon_states = list("gibleg", "gibarm")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/core
|
||||
random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
|
||||
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/proc/streak(var/list/directions)
|
||||
spawn (0)
|
||||
var/direction = pick(directions)
|
||||
for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++)
|
||||
sleep(3)
|
||||
if (i > 0)
|
||||
var/obj/effect/decal/cleanable/blood/b = new /obj/effect/decal/cleanable/blood/splatter(src.loc)
|
||||
b.basecolor = src.basecolor
|
||||
b.update_icon()
|
||||
|
||||
if (step_to(src, get_step(src, direction), 0))
|
||||
break
|
||||
|
||||
|
||||
/obj/effect/decal/cleanable/mucus
|
||||
name = "mucus"
|
||||
desc = "Disgusting mucus."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "mucus"
|
||||
random_icon_states = list("mucus")
|
||||
|
||||
var/list/datum/disease2/disease/virus2 = list()
|
||||
var/dry = 0 // Keeps the lag down
|
||||
|
||||
/obj/effect/decal/cleanable/mucus/Initialize()
|
||||
. = ..()
|
||||
VARSET_IN(src, dry, TRUE, DRYING_TIME * 2)
|
||||
|
||||
//This version should be used for admin spawns and pre-mapped virus vectors (e.g. in PoIs), this version does not dry
|
||||
/obj/effect/decal/cleanable/mucus/mapped/Initialize()
|
||||
. = ..()
|
||||
virus2 |= new /datum/disease2/disease
|
||||
virus2[1].makerandom()
|
||||
|
||||
/obj/effect/decal/cleanable/mucus/mapped/Destroy()
|
||||
virus2.Cut()
|
||||
return ..()
|
||||
|
||||
@@ -1,163 +1,163 @@
|
||||
/obj/effect/decal/cleanable/generic
|
||||
name = "clutter"
|
||||
desc = "Someone should clean that up."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "shards"
|
||||
|
||||
/obj/effect/decal/cleanable/ash
|
||||
name = "ashes"
|
||||
desc = "Ashes to ashes, dust to dust, and into space."
|
||||
gender = PLURAL
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "ash"
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/ash/attack_hand(mob/user as mob)
|
||||
to_chat(user, "<span class='notice'>[src] sifts through your fingers.</span>")
|
||||
var/turf/simulated/floor/F = get_turf(src)
|
||||
if (istype(F))
|
||||
F.dirt += 4
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/decal/cleanable/greenglow
|
||||
|
||||
/obj/effect/decal/cleanable/greenglow/New()
|
||||
..()
|
||||
QDEL_IN(src, 2 MINUTES)
|
||||
|
||||
/obj/effect/decal/cleanable/dirt
|
||||
name = "dirt"
|
||||
desc = "Someone should clean that up."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "dirt"
|
||||
mouse_opacity = 0
|
||||
|
||||
/obj/effect/decal/cleanable/dirt/Initialize(var/mapload, var/_age, var/dirt)
|
||||
.=..()
|
||||
var/turf/simulated/our_turf = src.loc
|
||||
if(our_turf && istype(our_turf) && our_turf.can_dirty)
|
||||
our_turf.dirt = clamp(max(age ? (dirt ? dirt : 101) : our_turf.dirt, our_turf.dirt), 0, 101)
|
||||
var/calcalpha = our_turf.dirt > 50 ? min((our_turf.dirt - 50) * 5, 255) : 0
|
||||
var/alreadyfound = FALSE
|
||||
for (var/obj/effect/decal/cleanable/dirt/alreadythere in our_turf) //in case of multiple
|
||||
if (alreadythere == src)
|
||||
continue
|
||||
else if (alreadyfound)
|
||||
qdel(alreadythere)
|
||||
continue
|
||||
alreadyfound = TRUE
|
||||
alreadythere.alpha = calcalpha //don't need to constantly recalc for all of them in it because it'll just max if a non-persistent dirt overlay gets added, and then the new dirt overlay will be deleted
|
||||
if (alreadyfound)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
alpha = calcalpha
|
||||
|
||||
/obj/effect/decal/cleanable/flour
|
||||
name = "flour"
|
||||
desc = "It's still good. Four second rule!"
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "flour"
|
||||
|
||||
/obj/effect/decal/cleanable/greenglow
|
||||
name = "glowing goo"
|
||||
desc = "Jeez. I hope that's not for lunch."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
light_range = 1
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "greenglow"
|
||||
|
||||
/obj/effect/decal/cleanable/cobweb
|
||||
name = "cobweb"
|
||||
desc = "Somebody should remove that."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
plane = OBJ_PLANE
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "cobweb1"
|
||||
|
||||
/obj/effect/decal/cleanable/molten_item
|
||||
name = "gooey grey mass"
|
||||
desc = "It looks like a melted... something."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
plane = OBJ_PLANE
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "molten"
|
||||
|
||||
/obj/effect/decal/cleanable/cobweb2
|
||||
name = "cobweb"
|
||||
desc = "Somebody should remove that."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
plane = OBJ_PLANE
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "cobweb2"
|
||||
|
||||
//Vomit (sorry)
|
||||
/obj/effect/decal/cleanable/vomit
|
||||
name = "vomit"
|
||||
desc = "Gosh, how unpleasant."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "vomit_1"
|
||||
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
|
||||
var/list/datum/disease2/disease/virus2 = list()
|
||||
|
||||
/obj/effect/decal/cleanable/tomato_smudge
|
||||
name = "tomato smudge"
|
||||
desc = "It's red."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/tomatodecal.dmi'
|
||||
random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3")
|
||||
|
||||
/obj/effect/decal/cleanable/egg_smudge
|
||||
name = "smashed egg"
|
||||
desc = "Seems like this one won't hatch."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/tomatodecal.dmi'
|
||||
random_icon_states = list("smashed_egg1", "smashed_egg2", "smashed_egg3")
|
||||
|
||||
/obj/effect/decal/cleanable/pie_smudge //honk
|
||||
name = "smashed pie"
|
||||
desc = "It's pie cream from a cream pie."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/tomatodecal.dmi'
|
||||
random_icon_states = list("smashed_pie")
|
||||
|
||||
/obj/effect/decal/cleanable/fruit_smudge
|
||||
name = "smudge"
|
||||
desc = "Some kind of fruit smear."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "mfloor1"
|
||||
random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7")
|
||||
|
||||
/obj/effect/decal/cleanable/confetti
|
||||
name = "confetti"
|
||||
desc = "Tiny bits of colored paper thrown about for the janitor to enjoy!"
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "confetti"
|
||||
|
||||
/obj/effect/decal/cleanable/confetti/attack_hand(mob/user)
|
||||
to_chat(user, "<span class='notice'>You start to meticulously pick up the confetti.</span>")
|
||||
if(do_after(user, 60))
|
||||
qdel(src)
|
||||
/obj/effect/decal/cleanable/generic
|
||||
name = "clutter"
|
||||
desc = "Someone should clean that up."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "shards"
|
||||
|
||||
/obj/effect/decal/cleanable/ash
|
||||
name = "ashes"
|
||||
desc = "Ashes to ashes, dust to dust, and into space."
|
||||
gender = PLURAL
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "ash"
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/ash/attack_hand(mob/user as mob)
|
||||
to_chat(user, "<span class='notice'>[src] sifts through your fingers.</span>")
|
||||
var/turf/simulated/floor/F = get_turf(src)
|
||||
if (istype(F))
|
||||
F.dirt += 4
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/decal/cleanable/greenglow
|
||||
|
||||
/obj/effect/decal/cleanable/greenglow/New()
|
||||
..()
|
||||
QDEL_IN(src, 2 MINUTES)
|
||||
|
||||
/obj/effect/decal/cleanable/dirt
|
||||
name = "dirt"
|
||||
desc = "Someone should clean that up."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "dirt"
|
||||
mouse_opacity = 0
|
||||
|
||||
/obj/effect/decal/cleanable/dirt/Initialize(var/mapload, var/_age, var/dirt)
|
||||
.=..()
|
||||
var/turf/simulated/our_turf = src.loc
|
||||
if(our_turf && istype(our_turf) && our_turf.can_dirty)
|
||||
our_turf.dirt = clamp(max(age ? (dirt ? dirt : 101) : our_turf.dirt, our_turf.dirt), 0, 101)
|
||||
var/calcalpha = our_turf.dirt > 50 ? min((our_turf.dirt - 50) * 5, 255) : 0
|
||||
var/alreadyfound = FALSE
|
||||
for (var/obj/effect/decal/cleanable/dirt/alreadythere in our_turf) //in case of multiple
|
||||
if (alreadythere == src)
|
||||
continue
|
||||
else if (alreadyfound)
|
||||
qdel(alreadythere)
|
||||
continue
|
||||
alreadyfound = TRUE
|
||||
alreadythere.alpha = calcalpha //don't need to constantly recalc for all of them in it because it'll just max if a non-persistent dirt overlay gets added, and then the new dirt overlay will be deleted
|
||||
if (alreadyfound)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
alpha = calcalpha
|
||||
|
||||
/obj/effect/decal/cleanable/flour
|
||||
name = "flour"
|
||||
desc = "It's still good. Four second rule!"
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "flour"
|
||||
|
||||
/obj/effect/decal/cleanable/greenglow
|
||||
name = "glowing goo"
|
||||
desc = "Jeez. I hope that's not for lunch."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
light_range = 1
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "greenglow"
|
||||
|
||||
/obj/effect/decal/cleanable/cobweb
|
||||
name = "cobweb"
|
||||
desc = "Somebody should remove that."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
plane = OBJ_PLANE
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "cobweb1"
|
||||
|
||||
/obj/effect/decal/cleanable/molten_item
|
||||
name = "gooey grey mass"
|
||||
desc = "It looks like a melted... something."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
plane = OBJ_PLANE
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "molten"
|
||||
|
||||
/obj/effect/decal/cleanable/cobweb2
|
||||
name = "cobweb"
|
||||
desc = "Somebody should remove that."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
plane = OBJ_PLANE
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "cobweb2"
|
||||
|
||||
//Vomit (sorry)
|
||||
/obj/effect/decal/cleanable/vomit
|
||||
name = "vomit"
|
||||
desc = "Gosh, how unpleasant."
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "vomit_1"
|
||||
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
|
||||
var/list/datum/disease2/disease/virus2 = list()
|
||||
|
||||
/obj/effect/decal/cleanable/tomato_smudge
|
||||
name = "tomato smudge"
|
||||
desc = "It's red."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/tomatodecal.dmi'
|
||||
random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3")
|
||||
|
||||
/obj/effect/decal/cleanable/egg_smudge
|
||||
name = "smashed egg"
|
||||
desc = "Seems like this one won't hatch."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/tomatodecal.dmi'
|
||||
random_icon_states = list("smashed_egg1", "smashed_egg2", "smashed_egg3")
|
||||
|
||||
/obj/effect/decal/cleanable/pie_smudge //honk
|
||||
name = "smashed pie"
|
||||
desc = "It's pie cream from a cream pie."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/tomatodecal.dmi'
|
||||
random_icon_states = list("smashed_pie")
|
||||
|
||||
/obj/effect/decal/cleanable/fruit_smudge
|
||||
name = "smudge"
|
||||
desc = "Some kind of fruit smear."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "mfloor1"
|
||||
random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7")
|
||||
|
||||
/obj/effect/decal/cleanable/confetti
|
||||
name = "confetti"
|
||||
desc = "Tiny bits of colored paper thrown about for the janitor to enjoy!"
|
||||
gender = PLURAL
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "confetti"
|
||||
|
||||
/obj/effect/decal/cleanable/confetti/attack_hand(mob/user)
|
||||
to_chat(user, "<span class='notice'>You start to meticulously pick up the confetti.</span>")
|
||||
if(do_after(user, 60))
|
||||
qdel(src)
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot
|
||||
name = "robot debris"
|
||||
desc = "It's a useless heap of junk... <i>or is it?</i>"
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon_state = "gib1"
|
||||
basecolor = SYNTH_BLOOD_COLOUR
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7")
|
||||
generic_filth = FALSE
|
||||
persistent = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot/update_icon()
|
||||
color = "#FFFFFF"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot/dry() //pieces of robots do not dry up like
|
||||
return
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot/streak(var/list/directions)
|
||||
spawn (0)
|
||||
var/direction = pick(directions)
|
||||
for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++)
|
||||
sleep(3)
|
||||
if (i > 0)
|
||||
if (prob(40))
|
||||
var/obj/effect/decal/cleanable/blood/oil/streak = new(src.loc)
|
||||
streak.update_icon()
|
||||
else if (prob(10))
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
if (step_to(src, get_step(src, direction), 0))
|
||||
break
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot/limb
|
||||
random_icon_states = list("gibarm", "gibleg")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot/up
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibup1","gibup1") //2:7 is close enough to 1:4
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot/down
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibdown1","gibdown1") //2:7 is close enough to 1:4
|
||||
|
||||
/obj/effect/decal/cleanable/blood/oil
|
||||
basecolor = SYNTH_BLOOD_COLOUR
|
||||
generic_filth = FALSE
|
||||
persistent = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/blood/oil/dry()
|
||||
return
|
||||
|
||||
/obj/effect/decal/cleanable/blood/oil/streak
|
||||
random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5")
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot
|
||||
name = "robot debris"
|
||||
desc = "It's a useless heap of junk... <i>or is it?</i>"
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon_state = "gib1"
|
||||
basecolor = SYNTH_BLOOD_COLOUR
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7")
|
||||
generic_filth = FALSE
|
||||
persistent = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot/update_icon()
|
||||
color = "#FFFFFF"
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot/dry() //pieces of robots do not dry up like
|
||||
return
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot/streak(var/list/directions)
|
||||
spawn (0)
|
||||
var/direction = pick(directions)
|
||||
for (var/i = 0, i < pick(1, 200; 2, 150; 3, 50; 4), i++)
|
||||
sleep(3)
|
||||
if (i > 0)
|
||||
if (prob(40))
|
||||
var/obj/effect/decal/cleanable/blood/oil/streak = new(src.loc)
|
||||
streak.update_icon()
|
||||
else if (prob(10))
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
if (step_to(src, get_step(src, direction), 0))
|
||||
break
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot/limb
|
||||
random_icon_states = list("gibarm", "gibleg")
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot/up
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibup1","gibup1") //2:7 is close enough to 1:4
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/robot/down
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibdown1","gibdown1") //2:7 is close enough to 1:4
|
||||
|
||||
/obj/effect/decal/cleanable/blood/oil
|
||||
basecolor = SYNTH_BLOOD_COLOUR
|
||||
generic_filth = FALSE
|
||||
persistent = FALSE
|
||||
|
||||
/obj/effect/decal/cleanable/blood/oil/dry()
|
||||
return
|
||||
|
||||
/obj/effect/decal/cleanable/blood/oil/streak
|
||||
random_icon_states = list("mgibbl1", "mgibbl2", "mgibbl3", "mgibbl4", "mgibbl5")
|
||||
amount = 2
|
||||
@@ -1,38 +1,38 @@
|
||||
/*
|
||||
USAGE NOTE
|
||||
For decals, the var Persistent = 'has already been saved', and is primarily used to prevent duplicate savings of generic filth (filth.dm).
|
||||
This also means 'TRUE' can be used to define a decal as "Do not save at all, even as a generic replacement." if a dirt decal is considered 'too common' to save.
|
||||
generic_filth = TRUE means when the decal is saved, it will be switched out for a generic green 'filth' decal.
|
||||
*/
|
||||
|
||||
/obj/effect/decal/cleanable
|
||||
plane = DIRTY_PLANE
|
||||
layer = DIRTY_LAYER
|
||||
var/persistent = FALSE
|
||||
var/generic_filth = FALSE
|
||||
var/age = 0
|
||||
var/list/random_icon_states = list()
|
||||
|
||||
/obj/effect/decal/cleanable/Initialize(var/mapload, var/_age)
|
||||
if(!isnull(_age))
|
||||
age = _age
|
||||
if(random_icon_states && length(src.random_icon_states) > 0)
|
||||
src.icon_state = pick(src.random_icon_states)
|
||||
if(!mapload || !config.persistence_ignore_mapload)
|
||||
SSpersistence.track_value(src, /datum/persistent/filth)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/decal/cleanable/Destroy()
|
||||
SSpersistence.forget_value(src, /datum/persistent/filth)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/decal/cleanable/clean_blood(var/ignore = 0)
|
||||
if(!ignore)
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/effect/decal/cleanable/New()
|
||||
if (random_icon_states && length(src.random_icon_states) > 0)
|
||||
src.icon_state = pick(src.random_icon_states)
|
||||
..()
|
||||
/*
|
||||
USAGE NOTE
|
||||
For decals, the var Persistent = 'has already been saved', and is primarily used to prevent duplicate savings of generic filth (filth.dm).
|
||||
This also means 'TRUE' can be used to define a decal as "Do not save at all, even as a generic replacement." if a dirt decal is considered 'too common' to save.
|
||||
generic_filth = TRUE means when the decal is saved, it will be switched out for a generic green 'filth' decal.
|
||||
*/
|
||||
|
||||
/obj/effect/decal/cleanable
|
||||
plane = DIRTY_PLANE
|
||||
layer = DIRTY_LAYER
|
||||
var/persistent = FALSE
|
||||
var/generic_filth = FALSE
|
||||
var/age = 0
|
||||
var/list/random_icon_states = list()
|
||||
|
||||
/obj/effect/decal/cleanable/Initialize(var/mapload, var/_age)
|
||||
if(!isnull(_age))
|
||||
age = _age
|
||||
if(random_icon_states && length(src.random_icon_states) > 0)
|
||||
src.icon_state = pick(src.random_icon_states)
|
||||
if(!mapload || !config.persistence_ignore_mapload)
|
||||
SSpersistence.track_value(src, /datum/persistent/filth)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/decal/cleanable/Destroy()
|
||||
SSpersistence.forget_value(src, /datum/persistent/filth)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/decal/cleanable/clean_blood(var/ignore = 0)
|
||||
if(!ignore)
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/effect/decal/cleanable/New()
|
||||
if (random_icon_states && length(src.random_icon_states) > 0)
|
||||
src.icon_state = pick(src.random_icon_states)
|
||||
..()
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
/obj/effect/decal/cleanable/crayon
|
||||
name = "rune"
|
||||
desc = "A rune drawn in crayon."
|
||||
icon = 'icons/obj/rune.dmi'
|
||||
plane = DIRTY_PLANE
|
||||
layer = DIRTY_LAYER
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/crayon/New(location,main = "#FFFFFF",shade = "#000000",var/type = "rune")
|
||||
..()
|
||||
loc = location
|
||||
|
||||
name = type
|
||||
desc = "A [type] drawn in crayon."
|
||||
|
||||
switch(type)
|
||||
if("rune")
|
||||
type = "rune[rand(1,6)]"
|
||||
if("graffiti")
|
||||
type = pick("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa")
|
||||
|
||||
var/icon/mainOverlay = new/icon('icons/effects/crayondecal.dmi',"[type]",2.1)
|
||||
var/icon/shadeOverlay = new/icon('icons/effects/crayondecal.dmi',"[type]s",2.1)
|
||||
|
||||
mainOverlay.Blend(main,ICON_ADD)
|
||||
shadeOverlay.Blend(shade,ICON_ADD)
|
||||
|
||||
add_overlay(mainOverlay)
|
||||
add_overlay(shadeOverlay)
|
||||
|
||||
add_hiddenprint(usr)
|
||||
/obj/effect/decal/cleanable/crayon
|
||||
name = "rune"
|
||||
desc = "A rune drawn in crayon."
|
||||
icon = 'icons/obj/rune.dmi'
|
||||
plane = DIRTY_PLANE
|
||||
layer = DIRTY_LAYER
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/decal/cleanable/crayon/New(location,main = "#FFFFFF",shade = "#000000",var/type = "rune")
|
||||
..()
|
||||
loc = location
|
||||
|
||||
name = type
|
||||
desc = "A [type] drawn in crayon."
|
||||
|
||||
switch(type)
|
||||
if("rune")
|
||||
type = "rune[rand(1,6)]"
|
||||
if("graffiti")
|
||||
type = pick("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa")
|
||||
|
||||
var/icon/mainOverlay = new/icon('icons/effects/crayondecal.dmi',"[type]",2.1)
|
||||
var/icon/shadeOverlay = new/icon('icons/effects/crayondecal.dmi',"[type]s",2.1)
|
||||
|
||||
mainOverlay.Blend(main,ICON_ADD)
|
||||
shadeOverlay.Blend(shade,ICON_ADD)
|
||||
|
||||
add_overlay(mainOverlay)
|
||||
add_overlay(shadeOverlay)
|
||||
|
||||
add_hiddenprint(usr)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/obj/effect/decal/point
|
||||
name = "arrow"
|
||||
desc = "It's an arrow hanging in mid-air. There may be a wizard about."
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "arrow"
|
||||
plane = ABOVE_PLANE
|
||||
anchored = TRUE
|
||||
mouse_opacity = 0
|
||||
|
||||
// Used for spray that you spray at walls, tables, hydrovats etc
|
||||
/obj/effect/decal/spraystill
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
/obj/effect/decal/point
|
||||
name = "arrow"
|
||||
desc = "It's an arrow hanging in mid-air. There may be a wizard about."
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "arrow"
|
||||
plane = ABOVE_PLANE
|
||||
anchored = TRUE
|
||||
mouse_opacity = 0
|
||||
|
||||
// Used for spray that you spray at walls, tables, hydrovats etc
|
||||
/obj/effect/decal/spraystill
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
plane = ABOVE_PLANE
|
||||
@@ -1,70 +1,70 @@
|
||||
/obj/effect/decal/remains
|
||||
name = "remains"
|
||||
gender = PLURAL
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "remains"
|
||||
anchored = FALSE
|
||||
|
||||
/obj/effect/decal/remains/human
|
||||
desc = "They look like human remains. They have a strange aura about them."
|
||||
|
||||
/obj/effect/decal/remains/xeno
|
||||
desc = "They look like the remains of something... alien. They have a strange aura about them."
|
||||
icon_state = "remainsxeno"
|
||||
|
||||
/obj/effect/decal/remains/robot
|
||||
desc = "They look like the remains of something mechanical. They have a strange aura about them."
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon_state = "remainsrobot"
|
||||
|
||||
/obj/effect/decal/remains/mouse
|
||||
desc = "They look like the remains of a small rodent."
|
||||
icon_state = "mouse"
|
||||
|
||||
/obj/effect/decal/remains/lizard
|
||||
desc = "They look like the remains of a small lizard."
|
||||
icon_state = "lizard"
|
||||
|
||||
/obj/effect/decal/remains/unathi
|
||||
desc = "They look like Unathi remains. Pointy."
|
||||
icon_state = "remainsunathi"
|
||||
|
||||
/obj/effect/decal/remains/tajaran
|
||||
desc = "They look like Tajaran remains. They're surprisingly small."
|
||||
icon_state = "remainstajaran"
|
||||
|
||||
/obj/effect/decal/remains/ribcage
|
||||
desc = "They look like animal remains of some sort... You hope."
|
||||
icon_state = "remainsribcage"
|
||||
|
||||
/obj/effect/decal/remains/deer
|
||||
desc = "They look like the remains of a large herbivore, picked clean."
|
||||
icon_state = "remainsdeer"
|
||||
|
||||
/obj/effect/decal/remains/posi
|
||||
desc = "This looks like part of an old FBP. Hopefully it was empty."
|
||||
icon_state = "remainsposi"
|
||||
|
||||
/obj/effect/decal/remains/mummy1
|
||||
name = "mummified remains"
|
||||
desc = "They look like human remains. They've been here a long time."
|
||||
icon_state = "mummified1"
|
||||
|
||||
/obj/effect/decal/remains/mummy2
|
||||
name = "mummified remains"
|
||||
desc = "They look like human remains. They've been here a long time."
|
||||
icon_state = "mummified2"
|
||||
|
||||
/obj/effect/decal/remains/attack_hand(mob/user as mob)
|
||||
to_chat(user, "<span class='notice'>[src] sinks together into a pile of ash.</span>")
|
||||
var/turf/simulated/floor/F = get_turf(src)
|
||||
if(istype(F))
|
||||
new /obj/effect/decal/cleanable/ash(F)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/decal/remains/robot/attack_hand(mob/user as mob)
|
||||
to_chat(user, "<span class='notice'>[src] crumbles down into a pile of debris.</span>")
|
||||
var/turf/simulated/floor/F = get_turf(src)
|
||||
if(istype(F))
|
||||
new /obj/effect/decal/cleanable/blood/gibs/robot(F)
|
||||
qdel(src)
|
||||
/obj/effect/decal/remains
|
||||
name = "remains"
|
||||
gender = PLURAL
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "remains"
|
||||
anchored = FALSE
|
||||
|
||||
/obj/effect/decal/remains/human
|
||||
desc = "They look like human remains. They have a strange aura about them."
|
||||
|
||||
/obj/effect/decal/remains/xeno
|
||||
desc = "They look like the remains of something... alien. They have a strange aura about them."
|
||||
icon_state = "remainsxeno"
|
||||
|
||||
/obj/effect/decal/remains/robot
|
||||
desc = "They look like the remains of something mechanical. They have a strange aura about them."
|
||||
icon = 'icons/mob/robots.dmi'
|
||||
icon_state = "remainsrobot"
|
||||
|
||||
/obj/effect/decal/remains/mouse
|
||||
desc = "They look like the remains of a small rodent."
|
||||
icon_state = "mouse"
|
||||
|
||||
/obj/effect/decal/remains/lizard
|
||||
desc = "They look like the remains of a small lizard."
|
||||
icon_state = "lizard"
|
||||
|
||||
/obj/effect/decal/remains/unathi
|
||||
desc = "They look like Unathi remains. Pointy."
|
||||
icon_state = "remainsunathi"
|
||||
|
||||
/obj/effect/decal/remains/tajaran
|
||||
desc = "They look like Tajaran remains. They're surprisingly small."
|
||||
icon_state = "remainstajaran"
|
||||
|
||||
/obj/effect/decal/remains/ribcage
|
||||
desc = "They look like animal remains of some sort... You hope."
|
||||
icon_state = "remainsribcage"
|
||||
|
||||
/obj/effect/decal/remains/deer
|
||||
desc = "They look like the remains of a large herbivore, picked clean."
|
||||
icon_state = "remainsdeer"
|
||||
|
||||
/obj/effect/decal/remains/posi
|
||||
desc = "This looks like part of an old FBP. Hopefully it was empty."
|
||||
icon_state = "remainsposi"
|
||||
|
||||
/obj/effect/decal/remains/mummy1
|
||||
name = "mummified remains"
|
||||
desc = "They look like human remains. They've been here a long time."
|
||||
icon_state = "mummified1"
|
||||
|
||||
/obj/effect/decal/remains/mummy2
|
||||
name = "mummified remains"
|
||||
desc = "They look like human remains. They've been here a long time."
|
||||
icon_state = "mummified2"
|
||||
|
||||
/obj/effect/decal/remains/attack_hand(mob/user as mob)
|
||||
to_chat(user, "<span class='notice'>[src] sinks together into a pile of ash.</span>")
|
||||
var/turf/simulated/floor/F = get_turf(src)
|
||||
if(istype(F))
|
||||
new /obj/effect/decal/cleanable/ash(F)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/decal/remains/robot/attack_hand(mob/user as mob)
|
||||
to_chat(user, "<span class='notice'>[src] crumbles down into a pile of debris.</span>")
|
||||
var/turf/simulated/floor/F = get_turf(src)
|
||||
if(istype(F))
|
||||
new /obj/effect/decal/cleanable/blood/gibs/robot(F)
|
||||
qdel(src)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/obj/effect/decal/warning_stripes
|
||||
icon = 'icons/effects/warning_stripes.dmi'
|
||||
|
||||
/obj/effect/decal/warning_stripes/Initialize()
|
||||
. = ..()
|
||||
var/turf/T=get_turf(src)
|
||||
var/image/I=image(icon, icon_state = icon_state, dir = dir)
|
||||
I.color=color
|
||||
T.add_overlay(I)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
/obj/effect/decal/warning_stripes
|
||||
icon = 'icons/effects/warning_stripes.dmi'
|
||||
|
||||
/obj/effect/decal/warning_stripes/Initialize()
|
||||
. = ..()
|
||||
var/turf/T=get_turf(src)
|
||||
var/image/I=image(icon, icon_state = icon_state, dir = dir)
|
||||
I.color=color
|
||||
T.add_overlay(I)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,72 +1,72 @@
|
||||
/obj/effect/expl_particles
|
||||
name = "explosive particles"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "explosion_particle"
|
||||
opacity = 1
|
||||
anchored = TRUE
|
||||
mouse_opacity = 0
|
||||
|
||||
/obj/effect/expl_particles/New()
|
||||
..()
|
||||
spawn (15)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/datum/effect/system/expl_particles
|
||||
var/number = 10
|
||||
var/turf/location
|
||||
var/total_particles = 0
|
||||
|
||||
/datum/effect/system/expl_particles/proc/set_up(n = 10, loca)
|
||||
number = n
|
||||
if(istype(loca, /turf/)) location = loca
|
||||
else location = get_turf(loca)
|
||||
|
||||
/datum/effect/system/expl_particles/proc/start()
|
||||
var/i = 0
|
||||
for(i=0, i<src.number, i++)
|
||||
spawn(0)
|
||||
var/obj/effect/expl_particles/expl = new /obj/effect/expl_particles(src.location)
|
||||
var/direct = pick(alldirs)
|
||||
for(i=0, i<pick(1;25,2;50,3,4;200), i++)
|
||||
sleep(1)
|
||||
step(expl,direct)
|
||||
|
||||
/obj/effect/explosion
|
||||
name = "explosive particles"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "explosion"
|
||||
opacity = 1
|
||||
anchored = TRUE
|
||||
mouse_opacity = 0
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
|
||||
/obj/effect/explosion/New()
|
||||
..()
|
||||
spawn (10)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/datum/effect/system/explosion
|
||||
var/turf/location
|
||||
|
||||
/datum/effect/system/explosion/proc/set_up(loca)
|
||||
if(istype(loca, /turf/)) location = loca
|
||||
else location = get_turf(loca)
|
||||
|
||||
/datum/effect/system/explosion/proc/start()
|
||||
new/obj/effect/explosion( location )
|
||||
var/datum/effect/system/expl_particles/P = new/datum/effect/system/expl_particles()
|
||||
P.set_up(10,location)
|
||||
P.start()
|
||||
spawn(5)
|
||||
var/datum/effect/effect/system/smoke_spread/S = new/datum/effect/effect/system/smoke_spread()
|
||||
S.set_up(5,0,location,null)
|
||||
S.start()
|
||||
|
||||
/datum/effect/system/explosion/smokeless/start()
|
||||
new/obj/effect/explosion(location)
|
||||
var/datum/effect/system/expl_particles/P = new/datum/effect/system/expl_particles()
|
||||
P.set_up(10,location)
|
||||
/obj/effect/expl_particles
|
||||
name = "explosive particles"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "explosion_particle"
|
||||
opacity = 1
|
||||
anchored = TRUE
|
||||
mouse_opacity = 0
|
||||
|
||||
/obj/effect/expl_particles/New()
|
||||
..()
|
||||
spawn (15)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/datum/effect/system/expl_particles
|
||||
var/number = 10
|
||||
var/turf/location
|
||||
var/total_particles = 0
|
||||
|
||||
/datum/effect/system/expl_particles/proc/set_up(n = 10, loca)
|
||||
number = n
|
||||
if(istype(loca, /turf/)) location = loca
|
||||
else location = get_turf(loca)
|
||||
|
||||
/datum/effect/system/expl_particles/proc/start()
|
||||
var/i = 0
|
||||
for(i=0, i<src.number, i++)
|
||||
spawn(0)
|
||||
var/obj/effect/expl_particles/expl = new /obj/effect/expl_particles(src.location)
|
||||
var/direct = pick(alldirs)
|
||||
for(i=0, i<pick(1;25,2;50,3,4;200), i++)
|
||||
sleep(1)
|
||||
step(expl,direct)
|
||||
|
||||
/obj/effect/explosion
|
||||
name = "explosive particles"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "explosion"
|
||||
opacity = 1
|
||||
anchored = TRUE
|
||||
mouse_opacity = 0
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
|
||||
/obj/effect/explosion/New()
|
||||
..()
|
||||
spawn (10)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/datum/effect/system/explosion
|
||||
var/turf/location
|
||||
|
||||
/datum/effect/system/explosion/proc/set_up(loca)
|
||||
if(istype(loca, /turf/)) location = loca
|
||||
else location = get_turf(loca)
|
||||
|
||||
/datum/effect/system/explosion/proc/start()
|
||||
new/obj/effect/explosion( location )
|
||||
var/datum/effect/system/expl_particles/P = new/datum/effect/system/expl_particles()
|
||||
P.set_up(10,location)
|
||||
P.start()
|
||||
spawn(5)
|
||||
var/datum/effect/effect/system/smoke_spread/S = new/datum/effect/effect/system/smoke_spread()
|
||||
S.set_up(5,0,location,null)
|
||||
S.start()
|
||||
|
||||
/datum/effect/system/explosion/smokeless/start()
|
||||
new/obj/effect/explosion(location)
|
||||
var/datum/effect/system/expl_particles/P = new/datum/effect/system/expl_particles()
|
||||
P.set_up(10,location)
|
||||
P.start()
|
||||
@@ -1,55 +1,55 @@
|
||||
/proc/gibs(atom/location, var/datum/dna/MobDNA, gibber_type = /obj/effect/gibspawner/generic, var/fleshcolor, var/bloodcolor)
|
||||
new gibber_type(location,MobDNA,fleshcolor,bloodcolor)
|
||||
|
||||
/obj/effect/gibspawner
|
||||
var/sparks = 0 //whether sparks spread on Gib()
|
||||
var/list/gibtypes = list()
|
||||
var/list/gibamounts = list()
|
||||
var/list/gibdirections = list() //of lists
|
||||
var/fleshcolor //Used for gibbed humans.
|
||||
var/bloodcolor //Used for gibbed humans.
|
||||
|
||||
/obj/effect/gibspawner/New(location, var/datum/dna/MobDNA, var/fleshcolor, var/bloodcolor)
|
||||
..()
|
||||
|
||||
if(fleshcolor) src.fleshcolor = fleshcolor
|
||||
if(bloodcolor) src.bloodcolor = bloodcolor
|
||||
Gib(loc,MobDNA)
|
||||
|
||||
/obj/effect/gibspawner/proc/Gib(atom/location, var/datum/dna/MobDNA = null)
|
||||
if(gibtypes.len != gibamounts.len || gibamounts.len != gibdirections.len)
|
||||
to_world("<span class='warning'>Gib list length mismatch!</span>")
|
||||
return
|
||||
|
||||
var/obj/effect/decal/cleanable/blood/gibs/gib = null
|
||||
|
||||
if(sparks)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
s.set_up(2, 1, get_turf(location)) // Not sure if it's safe to pass an arbitrary object to set_up, todo
|
||||
s.start()
|
||||
|
||||
for(var/i = 1, i<= gibtypes.len, i++)
|
||||
if(gibamounts[i])
|
||||
for(var/j = 1, j<= gibamounts[i], j++)
|
||||
var/gibType = gibtypes[i]
|
||||
gib = new gibType(location)
|
||||
|
||||
// Apply human species colouration to masks.
|
||||
if(fleshcolor)
|
||||
gib.fleshcolor = fleshcolor
|
||||
if(bloodcolor)
|
||||
gib.basecolor = bloodcolor
|
||||
|
||||
gib.update_icon()
|
||||
|
||||
gib.blood_DNA = list()
|
||||
if(MobDNA)
|
||||
gib.blood_DNA[MobDNA.unique_enzymes] = MobDNA.b_type
|
||||
else if(istype(src, /obj/effect/gibspawner/human)) // Probably a monkey
|
||||
gib.blood_DNA["Non-human DNA"] = "A+"
|
||||
if(istype(location,/turf/))
|
||||
var/list/directions = gibdirections[i]
|
||||
if(directions.len)
|
||||
gib.streak(directions)
|
||||
|
||||
qdel(src)
|
||||
/proc/gibs(atom/location, var/datum/dna/MobDNA, gibber_type = /obj/effect/gibspawner/generic, var/fleshcolor, var/bloodcolor)
|
||||
new gibber_type(location,MobDNA,fleshcolor,bloodcolor)
|
||||
|
||||
/obj/effect/gibspawner
|
||||
var/sparks = 0 //whether sparks spread on Gib()
|
||||
var/list/gibtypes = list()
|
||||
var/list/gibamounts = list()
|
||||
var/list/gibdirections = list() //of lists
|
||||
var/fleshcolor //Used for gibbed humans.
|
||||
var/bloodcolor //Used for gibbed humans.
|
||||
|
||||
/obj/effect/gibspawner/New(location, var/datum/dna/MobDNA, var/fleshcolor, var/bloodcolor)
|
||||
..()
|
||||
|
||||
if(fleshcolor) src.fleshcolor = fleshcolor
|
||||
if(bloodcolor) src.bloodcolor = bloodcolor
|
||||
Gib(loc,MobDNA)
|
||||
|
||||
/obj/effect/gibspawner/proc/Gib(atom/location, var/datum/dna/MobDNA = null)
|
||||
if(gibtypes.len != gibamounts.len || gibamounts.len != gibdirections.len)
|
||||
to_world("<span class='warning'>Gib list length mismatch!</span>")
|
||||
return
|
||||
|
||||
var/obj/effect/decal/cleanable/blood/gibs/gib = null
|
||||
|
||||
if(sparks)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
s.set_up(2, 1, get_turf(location)) // Not sure if it's safe to pass an arbitrary object to set_up, todo
|
||||
s.start()
|
||||
|
||||
for(var/i = 1, i<= gibtypes.len, i++)
|
||||
if(gibamounts[i])
|
||||
for(var/j = 1, j<= gibamounts[i], j++)
|
||||
var/gibType = gibtypes[i]
|
||||
gib = new gibType(location)
|
||||
|
||||
// Apply human species colouration to masks.
|
||||
if(fleshcolor)
|
||||
gib.fleshcolor = fleshcolor
|
||||
if(bloodcolor)
|
||||
gib.basecolor = bloodcolor
|
||||
|
||||
gib.update_icon()
|
||||
|
||||
gib.blood_DNA = list()
|
||||
if(MobDNA)
|
||||
gib.blood_DNA[MobDNA.unique_enzymes] = MobDNA.b_type
|
||||
else if(istype(src, /obj/effect/gibspawner/human)) // Probably a monkey
|
||||
gib.blood_DNA["Non-human DNA"] = "A+"
|
||||
if(istype(location,/turf/))
|
||||
var/list/directions = gibdirections[i]
|
||||
if(directions.len)
|
||||
gib.streak(directions)
|
||||
|
||||
qdel(src)
|
||||
|
||||
@@ -1,291 +1,291 @@
|
||||
/obj/effect/landmark
|
||||
name = "landmark"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x2"
|
||||
anchored = TRUE
|
||||
unacidable = TRUE
|
||||
simulated = FALSE
|
||||
invisibility = 100
|
||||
var/delete_me = 0
|
||||
|
||||
/obj/effect/landmark/New()
|
||||
..()
|
||||
tag = text("landmark*[]", name)
|
||||
invisibility = 101
|
||||
|
||||
switch(name) //some of these are probably obsolete
|
||||
if("monkey")
|
||||
monkeystart += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("start")
|
||||
newplayer_start += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("JoinLate") // Bit difference, since we need the spawn point to move.
|
||||
latejoin += src
|
||||
simulated = TRUE
|
||||
// delete_me = 1
|
||||
return
|
||||
if("JoinLateGateway")
|
||||
latejoin_gateway += loc
|
||||
latejoin += src //VOREStation Addition
|
||||
delete_me = 1
|
||||
return
|
||||
if("JoinLateElevator")
|
||||
latejoin_elevator += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("JoinLateCryo")
|
||||
latejoin_cryo += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("JoinLateCyborg")
|
||||
latejoin_cyborg += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("prisonwarp")
|
||||
prisonwarp += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("Holding Facility")
|
||||
holdingfacility += loc
|
||||
if("tdome1")
|
||||
tdome1 += loc
|
||||
if("tdome2")
|
||||
tdome2 += loc
|
||||
if("tdomeadmin")
|
||||
tdomeadmin += loc
|
||||
if("tdomeobserve")
|
||||
tdomeobserve += loc
|
||||
if("prisonsecuritywarp")
|
||||
prisonsecuritywarp += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("blobstart")
|
||||
blobstart += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("xeno_spawn")
|
||||
xeno_spawn += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("endgame_exit")
|
||||
endgame_safespawns += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("bluespacerift")
|
||||
endgame_exits += loc
|
||||
delete_me = 1
|
||||
return
|
||||
//VOREStation Add Start
|
||||
if("vinestart")
|
||||
vinestart += loc
|
||||
delete_me = 1
|
||||
return
|
||||
//VORE Station Add End
|
||||
|
||||
landmarks_list += src
|
||||
return 1
|
||||
|
||||
/obj/effect/landmark/proc/delete()
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/Initialize()
|
||||
. = ..()
|
||||
if(delete_me)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/effect/landmark/Destroy(var/force = FALSE)
|
||||
if(delete_me || force)
|
||||
landmarks_list -= src
|
||||
return ..()
|
||||
return QDEL_HINT_LETMELIVE
|
||||
|
||||
/obj/effect/landmark/start
|
||||
name = "start"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/landmark/start/New()
|
||||
..()
|
||||
tag = "start*[name]"
|
||||
invisibility = 101
|
||||
|
||||
return 1
|
||||
|
||||
/obj/effect/landmark/forbidden_level
|
||||
delete_me = 1
|
||||
/obj/effect/landmark/forbidden_level/Initialize()
|
||||
. = ..()
|
||||
if(using_map)
|
||||
using_map.secret_levels |= z
|
||||
else
|
||||
log_error("[type] mapped in but no using_map")
|
||||
|
||||
/obj/effect/landmark/hidden_level
|
||||
delete_me = 1
|
||||
/obj/effect/landmark/hidden_level/Initialize()
|
||||
. = ..()
|
||||
if(using_map)
|
||||
using_map.hidden_levels |= z
|
||||
else
|
||||
log_error("[type] mapped in but no using_map")
|
||||
|
||||
|
||||
/obj/effect/landmark/virtual_reality
|
||||
name = "virtual_reality"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/landmark/virtual_reality/New()
|
||||
..()
|
||||
tag = "virtual_reality*[name]"
|
||||
invisibility = 101
|
||||
return 1
|
||||
|
||||
|
||||
//Costume spawner landmarks
|
||||
/obj/effect/landmark/costume/New() //costume spawner, selects a random subclass and disappears
|
||||
|
||||
var/list/options = typesof(/obj/effect/landmark/costume)
|
||||
var/PICK= options[rand(1,options.len)]
|
||||
new PICK(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
//SUBCLASSES. Spawn a bunch of items and disappear likewise
|
||||
/obj/effect/landmark/costume/chicken/New()
|
||||
new /obj/item/clothing/suit/chickensuit(src.loc)
|
||||
new /obj/item/clothing/head/chicken(src.loc)
|
||||
new /obj/item/weapon/reagent_containers/food/snacks/egg(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/gladiator/New()
|
||||
new /obj/item/clothing/under/gladiator(src.loc)
|
||||
new /obj/item/clothing/head/helmet/gladiator(src.loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/landmark/costume/madscientist/New()
|
||||
new /obj/item/clothing/under/suit_jacket/green(src.loc)
|
||||
new /obj/item/clothing/head/flatcap(src.loc)
|
||||
new /obj/item/clothing/suit/storage/toggle/labcoat/mad(src.loc)
|
||||
new /obj/item/clothing/glasses/gglasses(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/elpresidente/New()
|
||||
new /obj/item/clothing/under/suit_jacket/green(src.loc)
|
||||
new /obj/item/clothing/head/flatcap(src.loc)
|
||||
new /obj/item/clothing/mask/smokable/cigarette/cigar/havana(src.loc)
|
||||
new /obj/item/clothing/shoes/boots/jackboots(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/nyangirl/New()
|
||||
new /obj/item/clothing/under/schoolgirl(src.loc)
|
||||
new /obj/item/clothing/head/kitty(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/maid/New()
|
||||
new /obj/item/clothing/under/skirt(src.loc)
|
||||
var/CHOICE = pick( /obj/item/clothing/head/beret , /obj/item/clothing/head/rabbitears )
|
||||
new CHOICE(src.loc)
|
||||
new /obj/item/clothing/glasses/sunglasses/blindfold(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/butler/New()
|
||||
new /obj/item/clothing/accessory/wcoat(src.loc)
|
||||
new /obj/item/clothing/under/suit_jacket(src.loc)
|
||||
new /obj/item/clothing/head/that(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/scratch/New()
|
||||
new /obj/item/clothing/gloves/white(src.loc)
|
||||
new /obj/item/clothing/shoes/white(src.loc)
|
||||
new /obj/item/clothing/under/scratch(src.loc)
|
||||
if (prob(30))
|
||||
new /obj/item/clothing/head/cueball(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/highlander/New()
|
||||
new /obj/item/clothing/under/kilt(src.loc)
|
||||
new /obj/item/clothing/head/beret(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/prig/New()
|
||||
new /obj/item/clothing/accessory/wcoat(src.loc)
|
||||
new /obj/item/clothing/glasses/monocle(src.loc)
|
||||
var/CHOICE= pick( /obj/item/clothing/head/bowler, /obj/item/clothing/head/that)
|
||||
new CHOICE(src.loc)
|
||||
new /obj/item/clothing/shoes/black(src.loc)
|
||||
new /obj/item/weapon/cane(src.loc)
|
||||
new /obj/item/clothing/under/sl_suit(src.loc)
|
||||
new /obj/item/clothing/mask/fakemoustache(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/plaguedoctor/New()
|
||||
new /obj/item/clothing/suit/bio_suit/plaguedoctorsuit(src.loc)
|
||||
new /obj/item/clothing/head/plaguedoctorhat(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/nightowl/New()
|
||||
new /obj/item/clothing/under/owl(src.loc)
|
||||
new /obj/item/clothing/mask/gas/owl_mask(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/waiter/New()
|
||||
new /obj/item/clothing/under/waiter(src.loc)
|
||||
var/CHOICE= pick( /obj/item/clothing/head/kitty, /obj/item/clothing/head/rabbitears)
|
||||
new CHOICE(src.loc)
|
||||
new /obj/item/clothing/suit/storage/apron(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/pirate/New()
|
||||
new /obj/item/clothing/under/pirate(src.loc)
|
||||
new /obj/item/clothing/suit/pirate(src.loc)
|
||||
var/CHOICE = pick( /obj/item/clothing/head/pirate , /obj/item/clothing/head/bandana )
|
||||
new CHOICE(src.loc)
|
||||
new /obj/item/clothing/glasses/eyepatch(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/commie/New()
|
||||
new /obj/item/clothing/under/soviet(src.loc)
|
||||
new /obj/item/clothing/head/ushanka(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/imperium_monk/New()
|
||||
new /obj/item/clothing/suit/imperium_monk(src.loc)
|
||||
if (prob(25))
|
||||
new /obj/item/clothing/mask/gas/cyborg(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/holiday_priest/New()
|
||||
new /obj/item/clothing/suit/holidaypriest(src.loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/landmark/costume/marisawizard/fake/New()
|
||||
new /obj/item/clothing/head/wizard/marisa/fake(src.loc)
|
||||
new/obj/item/clothing/suit/wizrobe/marisa/fake(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/cutewitch/New()
|
||||
new /obj/item/clothing/under/sundress(src.loc)
|
||||
new /obj/item/clothing/head/witchwig(src.loc)
|
||||
new /obj/item/weapon/staff/broom(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/fakewizard/New()
|
||||
new /obj/item/clothing/suit/wizrobe/fake(src.loc)
|
||||
new /obj/item/clothing/head/wizard/fake(src.loc)
|
||||
new /obj/item/weapon/staff/(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/sexyclown/New()
|
||||
new /obj/item/clothing/mask/gas/sexyclown(src.loc)
|
||||
new /obj/item/clothing/under/sexyclown(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/sexymime/New()
|
||||
new /obj/item/clothing/mask/gas/sexymime(src.loc)
|
||||
new /obj/item/clothing/under/sexymime(src.loc)
|
||||
delete_me = 1
|
||||
/obj/effect/landmark
|
||||
name = "landmark"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x2"
|
||||
anchored = TRUE
|
||||
unacidable = TRUE
|
||||
simulated = FALSE
|
||||
invisibility = 100
|
||||
var/delete_me = 0
|
||||
|
||||
/obj/effect/landmark/New()
|
||||
..()
|
||||
tag = text("landmark*[]", name)
|
||||
invisibility = 101
|
||||
|
||||
switch(name) //some of these are probably obsolete
|
||||
if("monkey")
|
||||
monkeystart += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("start")
|
||||
newplayer_start += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("JoinLate") // Bit difference, since we need the spawn point to move.
|
||||
latejoin += src
|
||||
simulated = TRUE
|
||||
// delete_me = 1
|
||||
return
|
||||
if("JoinLateGateway")
|
||||
latejoin_gateway += loc
|
||||
latejoin += src //VOREStation Addition
|
||||
delete_me = 1
|
||||
return
|
||||
if("JoinLateElevator")
|
||||
latejoin_elevator += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("JoinLateCryo")
|
||||
latejoin_cryo += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("JoinLateCyborg")
|
||||
latejoin_cyborg += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("prisonwarp")
|
||||
prisonwarp += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("Holding Facility")
|
||||
holdingfacility += loc
|
||||
if("tdome1")
|
||||
tdome1 += loc
|
||||
if("tdome2")
|
||||
tdome2 += loc
|
||||
if("tdomeadmin")
|
||||
tdomeadmin += loc
|
||||
if("tdomeobserve")
|
||||
tdomeobserve += loc
|
||||
if("prisonsecuritywarp")
|
||||
prisonsecuritywarp += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("blobstart")
|
||||
blobstart += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("xeno_spawn")
|
||||
xeno_spawn += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("endgame_exit")
|
||||
endgame_safespawns += loc
|
||||
delete_me = 1
|
||||
return
|
||||
if("bluespacerift")
|
||||
endgame_exits += loc
|
||||
delete_me = 1
|
||||
return
|
||||
//VOREStation Add Start
|
||||
if("vinestart")
|
||||
vinestart += loc
|
||||
delete_me = 1
|
||||
return
|
||||
//VORE Station Add End
|
||||
|
||||
landmarks_list += src
|
||||
return 1
|
||||
|
||||
/obj/effect/landmark/proc/delete()
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/Initialize()
|
||||
. = ..()
|
||||
if(delete_me)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/effect/landmark/Destroy(var/force = FALSE)
|
||||
if(delete_me || force)
|
||||
landmarks_list -= src
|
||||
return ..()
|
||||
return QDEL_HINT_LETMELIVE
|
||||
|
||||
/obj/effect/landmark/start
|
||||
name = "start"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/landmark/start/New()
|
||||
..()
|
||||
tag = "start*[name]"
|
||||
invisibility = 101
|
||||
|
||||
return 1
|
||||
|
||||
/obj/effect/landmark/forbidden_level
|
||||
delete_me = 1
|
||||
/obj/effect/landmark/forbidden_level/Initialize()
|
||||
. = ..()
|
||||
if(using_map)
|
||||
using_map.secret_levels |= z
|
||||
else
|
||||
log_error("[type] mapped in but no using_map")
|
||||
|
||||
/obj/effect/landmark/hidden_level
|
||||
delete_me = 1
|
||||
/obj/effect/landmark/hidden_level/Initialize()
|
||||
. = ..()
|
||||
if(using_map)
|
||||
using_map.hidden_levels |= z
|
||||
else
|
||||
log_error("[type] mapped in but no using_map")
|
||||
|
||||
|
||||
/obj/effect/landmark/virtual_reality
|
||||
name = "virtual_reality"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/landmark/virtual_reality/New()
|
||||
..()
|
||||
tag = "virtual_reality*[name]"
|
||||
invisibility = 101
|
||||
return 1
|
||||
|
||||
|
||||
//Costume spawner landmarks
|
||||
/obj/effect/landmark/costume/New() //costume spawner, selects a random subclass and disappears
|
||||
|
||||
var/list/options = typesof(/obj/effect/landmark/costume)
|
||||
var/PICK= options[rand(1,options.len)]
|
||||
new PICK(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
//SUBCLASSES. Spawn a bunch of items and disappear likewise
|
||||
/obj/effect/landmark/costume/chicken/New()
|
||||
new /obj/item/clothing/suit/chickensuit(src.loc)
|
||||
new /obj/item/clothing/head/chicken(src.loc)
|
||||
new /obj/item/weapon/reagent_containers/food/snacks/egg(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/gladiator/New()
|
||||
new /obj/item/clothing/under/gladiator(src.loc)
|
||||
new /obj/item/clothing/head/helmet/gladiator(src.loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/landmark/costume/madscientist/New()
|
||||
new /obj/item/clothing/under/suit_jacket/green(src.loc)
|
||||
new /obj/item/clothing/head/flatcap(src.loc)
|
||||
new /obj/item/clothing/suit/storage/toggle/labcoat/mad(src.loc)
|
||||
new /obj/item/clothing/glasses/gglasses(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/elpresidente/New()
|
||||
new /obj/item/clothing/under/suit_jacket/green(src.loc)
|
||||
new /obj/item/clothing/head/flatcap(src.loc)
|
||||
new /obj/item/clothing/mask/smokable/cigarette/cigar/havana(src.loc)
|
||||
new /obj/item/clothing/shoes/boots/jackboots(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/nyangirl/New()
|
||||
new /obj/item/clothing/under/schoolgirl(src.loc)
|
||||
new /obj/item/clothing/head/kitty(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/maid/New()
|
||||
new /obj/item/clothing/under/skirt(src.loc)
|
||||
var/CHOICE = pick( /obj/item/clothing/head/beret , /obj/item/clothing/head/rabbitears )
|
||||
new CHOICE(src.loc)
|
||||
new /obj/item/clothing/glasses/sunglasses/blindfold(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/butler/New()
|
||||
new /obj/item/clothing/accessory/wcoat(src.loc)
|
||||
new /obj/item/clothing/under/suit_jacket(src.loc)
|
||||
new /obj/item/clothing/head/that(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/scratch/New()
|
||||
new /obj/item/clothing/gloves/white(src.loc)
|
||||
new /obj/item/clothing/shoes/white(src.loc)
|
||||
new /obj/item/clothing/under/scratch(src.loc)
|
||||
if (prob(30))
|
||||
new /obj/item/clothing/head/cueball(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/highlander/New()
|
||||
new /obj/item/clothing/under/kilt(src.loc)
|
||||
new /obj/item/clothing/head/beret(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/prig/New()
|
||||
new /obj/item/clothing/accessory/wcoat(src.loc)
|
||||
new /obj/item/clothing/glasses/monocle(src.loc)
|
||||
var/CHOICE= pick( /obj/item/clothing/head/bowler, /obj/item/clothing/head/that)
|
||||
new CHOICE(src.loc)
|
||||
new /obj/item/clothing/shoes/black(src.loc)
|
||||
new /obj/item/weapon/cane(src.loc)
|
||||
new /obj/item/clothing/under/sl_suit(src.loc)
|
||||
new /obj/item/clothing/mask/fakemoustache(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/plaguedoctor/New()
|
||||
new /obj/item/clothing/suit/bio_suit/plaguedoctorsuit(src.loc)
|
||||
new /obj/item/clothing/head/plaguedoctorhat(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/nightowl/New()
|
||||
new /obj/item/clothing/under/owl(src.loc)
|
||||
new /obj/item/clothing/mask/gas/owl_mask(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/waiter/New()
|
||||
new /obj/item/clothing/under/waiter(src.loc)
|
||||
var/CHOICE= pick( /obj/item/clothing/head/kitty, /obj/item/clothing/head/rabbitears)
|
||||
new CHOICE(src.loc)
|
||||
new /obj/item/clothing/suit/storage/apron(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/pirate/New()
|
||||
new /obj/item/clothing/under/pirate(src.loc)
|
||||
new /obj/item/clothing/suit/pirate(src.loc)
|
||||
var/CHOICE = pick( /obj/item/clothing/head/pirate , /obj/item/clothing/head/bandana )
|
||||
new CHOICE(src.loc)
|
||||
new /obj/item/clothing/glasses/eyepatch(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/commie/New()
|
||||
new /obj/item/clothing/under/soviet(src.loc)
|
||||
new /obj/item/clothing/head/ushanka(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/imperium_monk/New()
|
||||
new /obj/item/clothing/suit/imperium_monk(src.loc)
|
||||
if (prob(25))
|
||||
new /obj/item/clothing/mask/gas/cyborg(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/holiday_priest/New()
|
||||
new /obj/item/clothing/suit/holidaypriest(src.loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/landmark/costume/marisawizard/fake/New()
|
||||
new /obj/item/clothing/head/wizard/marisa/fake(src.loc)
|
||||
new/obj/item/clothing/suit/wizrobe/marisa/fake(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/cutewitch/New()
|
||||
new /obj/item/clothing/under/sundress(src.loc)
|
||||
new /obj/item/clothing/head/witchwig(src.loc)
|
||||
new /obj/item/weapon/staff/broom(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/fakewizard/New()
|
||||
new /obj/item/clothing/suit/wizrobe/fake(src.loc)
|
||||
new /obj/item/clothing/head/wizard/fake(src.loc)
|
||||
new /obj/item/weapon/staff/(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/sexyclown/New()
|
||||
new /obj/item/clothing/mask/gas/sexyclown(src.loc)
|
||||
new /obj/item/clothing/under/sexyclown(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
/obj/effect/landmark/costume/sexymime/New()
|
||||
new /obj/item/clothing/mask/gas/sexymime(src.loc)
|
||||
new /obj/item/clothing/under/sexymime(src.loc)
|
||||
delete_me = 1
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
/obj/effect/manifest
|
||||
name = "manifest"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
unacidable = TRUE//Just to be sure.
|
||||
|
||||
/obj/effect/manifest/New()
|
||||
|
||||
src.invisibility = 101
|
||||
return
|
||||
|
||||
/obj/effect/manifest/proc/manifest()
|
||||
var/dat = "<B>Crew Manifest</B>:<BR>"
|
||||
for(var/mob/living/carbon/human/M in mob_list)
|
||||
dat += text(" <B>[]</B> - []<BR>", M.name, M.get_assignment())
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.loc )
|
||||
P.info = dat
|
||||
P.name = "paper- 'Crew Manifest'"
|
||||
//SN src = null
|
||||
qdel(src)
|
||||
/obj/effect/manifest
|
||||
name = "manifest"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
unacidable = TRUE//Just to be sure.
|
||||
|
||||
/obj/effect/manifest/New()
|
||||
|
||||
src.invisibility = 101
|
||||
return
|
||||
|
||||
/obj/effect/manifest/proc/manifest()
|
||||
var/dat = "<B>Crew Manifest</B>:<BR>"
|
||||
for(var/mob/living/carbon/human/M in mob_list)
|
||||
dat += text(" <B>[]</B> - []<BR>", M.name, M.get_assignment())
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.loc )
|
||||
P.info = dat
|
||||
P.name = "paper- 'Crew Manifest'"
|
||||
//SN src = null
|
||||
qdel(src)
|
||||
return
|
||||
@@ -1,191 +1,191 @@
|
||||
GLOBAL_LIST_EMPTY(all_beam_points)
|
||||
|
||||
// Creates and manages a beam attached to itself and another beam_point.
|
||||
// You can do cool things with these such as moving the beam_point to move the beam, turning them on and off on a timer, triggered by external input, and more.
|
||||
/obj/effect/map_effect/beam_point
|
||||
name = "beam point"
|
||||
icon_state = "beam_point"
|
||||
|
||||
// General variables.
|
||||
var/list/my_beams = list() // Instances of beams. Deleting one will kill the beam.
|
||||
var/id = "A" // Two beam_points must share the same ID to be connected to each other.
|
||||
var/max_beams = 10 // How many concurrent beams to seperate beam_points to have at once. Set to zero to only act as targets for other beam_points.
|
||||
var/seek_range = 7 // How far to look for an end beam_point when not having a beam. Defaults to screen height/width. Make sure this is below beam_max_distance.
|
||||
|
||||
// Controls how and when the beam is created.
|
||||
var/make_beams_on_init = FALSE
|
||||
var/use_timer = FALSE // Sadly not the /tg/ timers.
|
||||
var/list/on_duration = list(2 SECONDS, 2 SECONDS, 2 SECONDS) // How long the beam should stay on for, if use_timer is true. Alternates between each duration in the list.
|
||||
var/list/off_duration = list(3 SECONDS, 0.5 SECOND, 0.5 SECOND) // How long it should stay off for. List length is not needed to be the same as on_duration.
|
||||
var/timer_on_index = 1 // Index to use for on_duration list.
|
||||
var/timer_off_index = 1// Ditto, for off_duration list.
|
||||
var/initial_delay = 0 // How long to wait before first turning on the beam, to sync beam times or create a specific pattern.
|
||||
var/beam_creation_sound = null // Optional sound played when one or more beams are created.
|
||||
var/beam_destruction_sound = null // Optional sound played when a beam is destroyed.
|
||||
|
||||
// Beam datum arguments.
|
||||
var/beam_icon = 'icons/effects/beam.dmi' // Icon file to use for beam visuals.
|
||||
var/beam_icon_state = "b_beam" // Icon state to use for visuals.
|
||||
var/beam_time = INFINITY // How long the beam lasts. By default it will last forever until destroyed.
|
||||
var/beam_max_distance = 10 // If the beam is farther than this, it will be destroyed. Make sure it's higher than seek_range.
|
||||
var/beam_type = /obj/effect/ebeam // The type of beam. Default has no special properties. Some others may do things like hurt things touching it.
|
||||
var/beam_sleep_time = 3 // How often the beam updates visually. Suggested to leave this alone, 3 is already fast.
|
||||
|
||||
/obj/effect/map_effect/beam_point/Initialize()
|
||||
GLOB.all_beam_points += src
|
||||
if(make_beams_on_init)
|
||||
create_beams()
|
||||
if(use_timer)
|
||||
addtimer(CALLBACK(src, PROC_REF(handle_beam_timer)), initial_delay)
|
||||
return ..()
|
||||
|
||||
/obj/effect/map_effect/beam_point/Destroy()
|
||||
destroy_all_beams()
|
||||
use_timer = FALSE
|
||||
GLOB.all_beam_points -= src
|
||||
return ..()
|
||||
|
||||
// This is the top level proc to make the magic happen.
|
||||
/obj/effect/map_effect/beam_point/proc/create_beams()
|
||||
if(my_beams.len >= max_beams)
|
||||
return
|
||||
var/beams_to_fill = max_beams - my_beams.len
|
||||
for(var/i = 1 to beams_to_fill)
|
||||
var/obj/effect/map_effect/beam_point/point = seek_beam_point()
|
||||
if(!point)
|
||||
break // No more points could be found, no point checking repeatively.
|
||||
build_beam(point)
|
||||
|
||||
// Finds a suitable beam point.
|
||||
/obj/effect/map_effect/beam_point/proc/seek_beam_point()
|
||||
for(var/obj/effect/map_effect/beam_point/point in GLOB.all_beam_points)
|
||||
if(id != point.id)
|
||||
continue // Not linked together by ID.
|
||||
if(has_active_beam(point))
|
||||
continue // Already got one.
|
||||
if(point.z != src.z)
|
||||
continue // Not on same z-level. get_dist() ignores z-levels by design according to docs.
|
||||
if(get_dist(src, point) > seek_range)
|
||||
continue // Too far.
|
||||
return point
|
||||
|
||||
// Checks if the two points have an active beam between them.
|
||||
// Used to make sure two points don't have more than one beam.
|
||||
/obj/effect/map_effect/beam_point/proc/has_active_beam(var/obj/effect/map_effect/beam_point/them)
|
||||
// First, check our beams.
|
||||
for(var/datum/beam/B in my_beams)
|
||||
if(B.target == them)
|
||||
return TRUE
|
||||
if(B.origin == them) // This shouldn't be needed unless the beam gets built backwards but why not.
|
||||
return TRUE
|
||||
|
||||
// Now check theirs, to see if they have a beam on us.
|
||||
for(var/datum/beam/B in them.my_beams)
|
||||
if(B.target == src)
|
||||
return TRUE
|
||||
if(B.origin == src) // Same story as above.
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/obj/effect/map_effect/beam_point/proc/build_beam(var/atom/beam_target)
|
||||
if(!beam_target)
|
||||
log_debug("[src] ([src.type] \[[x],[y],[z]\]) failed to build its beam due to not having a target.")
|
||||
return FALSE
|
||||
|
||||
var/datum/beam/new_beam = Beam(beam_target, beam_icon_state, beam_icon, beam_time, beam_max_distance, beam_type, beam_sleep_time)
|
||||
my_beams += new_beam
|
||||
if(beam_creation_sound)
|
||||
playsound(src, beam_creation_sound, 70, 1)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/effect/map_effect/beam_point/proc/destroy_beam(var/datum/beam/B)
|
||||
if(!B)
|
||||
log_debug("[src] ([src.type] \[[x],[y],[z]\]) was asked to destroy a beam that does not exist.")
|
||||
return FALSE
|
||||
|
||||
if(!(B in my_beams))
|
||||
log_debug("[src] ([src.type] \[[x],[y],[z]\]) was asked to destroy a beam it did not own.")
|
||||
return FALSE
|
||||
|
||||
my_beams -= B
|
||||
qdel(B)
|
||||
if(beam_destruction_sound)
|
||||
playsound(src, beam_destruction_sound, 70, 1)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/effect/map_effect/beam_point/proc/destroy_all_beams()
|
||||
for(var/datum/beam/B in my_beams)
|
||||
destroy_beam(B)
|
||||
return TRUE
|
||||
|
||||
// This code makes me sad.
|
||||
/obj/effect/map_effect/beam_point/proc/handle_beam_timer()
|
||||
if(!use_timer || QDELETED(src))
|
||||
return
|
||||
|
||||
if(my_beams.len) // Currently on.
|
||||
destroy_all_beams()
|
||||
color = "#FF0000"
|
||||
|
||||
timer_off_index++
|
||||
if(timer_off_index > off_duration.len)
|
||||
timer_off_index = 1
|
||||
|
||||
spawn(off_duration[timer_off_index])
|
||||
.()
|
||||
|
||||
else // Currently off.
|
||||
// If nobody's around, keep the beams off to avoid wasteful beam process(), if they have one.
|
||||
if(!always_run && !check_for_player_proximity(src, proximity_needed, ignore_ghosts, ignore_afk))
|
||||
spawn(retry_delay)
|
||||
.()
|
||||
return
|
||||
|
||||
create_beams()
|
||||
color = "#00FF00"
|
||||
|
||||
timer_on_index++
|
||||
if(timer_on_index > on_duration.len)
|
||||
timer_on_index = 1
|
||||
|
||||
spawn(on_duration[timer_on_index])
|
||||
.()
|
||||
|
||||
|
||||
|
||||
// Subtypes to use in maps and adminbuse.
|
||||
// Remember, beam_points ONLY connect to other beam_points with the same id variable.
|
||||
|
||||
// Creates the beam when instantiated and stays on until told otherwise.
|
||||
/obj/effect/map_effect/beam_point/instant
|
||||
make_beams_on_init = TRUE
|
||||
|
||||
/obj/effect/map_effect/beam_point/instant/electric
|
||||
beam_icon_state = "nzcrentrs_power"
|
||||
beam_type = /obj/effect/ebeam/reactive/electric
|
||||
beam_creation_sound = 'sound/effects/lightningshock.ogg'
|
||||
beam_destruction_sound = "sparks"
|
||||
|
||||
// Turns on and off on a timer.
|
||||
/obj/effect/map_effect/beam_point/timer
|
||||
use_timer = TRUE
|
||||
|
||||
// Shocks people who touch the beam while it's on. Flicks on and off on a specific pattern.
|
||||
/obj/effect/map_effect/beam_point/timer/electric
|
||||
beam_icon_state = "nzcrentrs_power"
|
||||
beam_type = /obj/effect/ebeam/reactive/electric
|
||||
beam_creation_sound = 'sound/effects/lightningshock.ogg'
|
||||
beam_destruction_sound = "sparks"
|
||||
seek_range = 3
|
||||
|
||||
// Is only a target for other beams to connect to.
|
||||
/obj/effect/map_effect/beam_point/end
|
||||
max_beams = 0
|
||||
|
||||
// Can only have one beam.
|
||||
/obj/effect/map_effect/beam_point/mono
|
||||
make_beams_on_init = TRUE
|
||||
max_beams = 1
|
||||
GLOBAL_LIST_EMPTY(all_beam_points)
|
||||
|
||||
// Creates and manages a beam attached to itself and another beam_point.
|
||||
// You can do cool things with these such as moving the beam_point to move the beam, turning them on and off on a timer, triggered by external input, and more.
|
||||
/obj/effect/map_effect/beam_point
|
||||
name = "beam point"
|
||||
icon_state = "beam_point"
|
||||
|
||||
// General variables.
|
||||
var/list/my_beams = list() // Instances of beams. Deleting one will kill the beam.
|
||||
var/id = "A" // Two beam_points must share the same ID to be connected to each other.
|
||||
var/max_beams = 10 // How many concurrent beams to seperate beam_points to have at once. Set to zero to only act as targets for other beam_points.
|
||||
var/seek_range = 7 // How far to look for an end beam_point when not having a beam. Defaults to screen height/width. Make sure this is below beam_max_distance.
|
||||
|
||||
// Controls how and when the beam is created.
|
||||
var/make_beams_on_init = FALSE
|
||||
var/use_timer = FALSE // Sadly not the /tg/ timers.
|
||||
var/list/on_duration = list(2 SECONDS, 2 SECONDS, 2 SECONDS) // How long the beam should stay on for, if use_timer is true. Alternates between each duration in the list.
|
||||
var/list/off_duration = list(3 SECONDS, 0.5 SECOND, 0.5 SECOND) // How long it should stay off for. List length is not needed to be the same as on_duration.
|
||||
var/timer_on_index = 1 // Index to use for on_duration list.
|
||||
var/timer_off_index = 1// Ditto, for off_duration list.
|
||||
var/initial_delay = 0 // How long to wait before first turning on the beam, to sync beam times or create a specific pattern.
|
||||
var/beam_creation_sound = null // Optional sound played when one or more beams are created.
|
||||
var/beam_destruction_sound = null // Optional sound played when a beam is destroyed.
|
||||
|
||||
// Beam datum arguments.
|
||||
var/beam_icon = 'icons/effects/beam.dmi' // Icon file to use for beam visuals.
|
||||
var/beam_icon_state = "b_beam" // Icon state to use for visuals.
|
||||
var/beam_time = INFINITY // How long the beam lasts. By default it will last forever until destroyed.
|
||||
var/beam_max_distance = 10 // If the beam is farther than this, it will be destroyed. Make sure it's higher than seek_range.
|
||||
var/beam_type = /obj/effect/ebeam // The type of beam. Default has no special properties. Some others may do things like hurt things touching it.
|
||||
var/beam_sleep_time = 3 // How often the beam updates visually. Suggested to leave this alone, 3 is already fast.
|
||||
|
||||
/obj/effect/map_effect/beam_point/Initialize()
|
||||
GLOB.all_beam_points += src
|
||||
if(make_beams_on_init)
|
||||
create_beams()
|
||||
if(use_timer)
|
||||
addtimer(CALLBACK(src, PROC_REF(handle_beam_timer)), initial_delay)
|
||||
return ..()
|
||||
|
||||
/obj/effect/map_effect/beam_point/Destroy()
|
||||
destroy_all_beams()
|
||||
use_timer = FALSE
|
||||
GLOB.all_beam_points -= src
|
||||
return ..()
|
||||
|
||||
// This is the top level proc to make the magic happen.
|
||||
/obj/effect/map_effect/beam_point/proc/create_beams()
|
||||
if(my_beams.len >= max_beams)
|
||||
return
|
||||
var/beams_to_fill = max_beams - my_beams.len
|
||||
for(var/i = 1 to beams_to_fill)
|
||||
var/obj/effect/map_effect/beam_point/point = seek_beam_point()
|
||||
if(!point)
|
||||
break // No more points could be found, no point checking repeatively.
|
||||
build_beam(point)
|
||||
|
||||
// Finds a suitable beam point.
|
||||
/obj/effect/map_effect/beam_point/proc/seek_beam_point()
|
||||
for(var/obj/effect/map_effect/beam_point/point in GLOB.all_beam_points)
|
||||
if(id != point.id)
|
||||
continue // Not linked together by ID.
|
||||
if(has_active_beam(point))
|
||||
continue // Already got one.
|
||||
if(point.z != src.z)
|
||||
continue // Not on same z-level. get_dist() ignores z-levels by design according to docs.
|
||||
if(get_dist(src, point) > seek_range)
|
||||
continue // Too far.
|
||||
return point
|
||||
|
||||
// Checks if the two points have an active beam between them.
|
||||
// Used to make sure two points don't have more than one beam.
|
||||
/obj/effect/map_effect/beam_point/proc/has_active_beam(var/obj/effect/map_effect/beam_point/them)
|
||||
// First, check our beams.
|
||||
for(var/datum/beam/B in my_beams)
|
||||
if(B.target == them)
|
||||
return TRUE
|
||||
if(B.origin == them) // This shouldn't be needed unless the beam gets built backwards but why not.
|
||||
return TRUE
|
||||
|
||||
// Now check theirs, to see if they have a beam on us.
|
||||
for(var/datum/beam/B in them.my_beams)
|
||||
if(B.target == src)
|
||||
return TRUE
|
||||
if(B.origin == src) // Same story as above.
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/obj/effect/map_effect/beam_point/proc/build_beam(var/atom/beam_target)
|
||||
if(!beam_target)
|
||||
log_debug("[src] ([src.type] \[[x],[y],[z]\]) failed to build its beam due to not having a target.")
|
||||
return FALSE
|
||||
|
||||
var/datum/beam/new_beam = Beam(beam_target, beam_icon_state, beam_icon, beam_time, beam_max_distance, beam_type, beam_sleep_time)
|
||||
my_beams += new_beam
|
||||
if(beam_creation_sound)
|
||||
playsound(src, beam_creation_sound, 70, 1)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/effect/map_effect/beam_point/proc/destroy_beam(var/datum/beam/B)
|
||||
if(!B)
|
||||
log_debug("[src] ([src.type] \[[x],[y],[z]\]) was asked to destroy a beam that does not exist.")
|
||||
return FALSE
|
||||
|
||||
if(!(B in my_beams))
|
||||
log_debug("[src] ([src.type] \[[x],[y],[z]\]) was asked to destroy a beam it did not own.")
|
||||
return FALSE
|
||||
|
||||
my_beams -= B
|
||||
qdel(B)
|
||||
if(beam_destruction_sound)
|
||||
playsound(src, beam_destruction_sound, 70, 1)
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/effect/map_effect/beam_point/proc/destroy_all_beams()
|
||||
for(var/datum/beam/B in my_beams)
|
||||
destroy_beam(B)
|
||||
return TRUE
|
||||
|
||||
// This code makes me sad.
|
||||
/obj/effect/map_effect/beam_point/proc/handle_beam_timer()
|
||||
if(!use_timer || QDELETED(src))
|
||||
return
|
||||
|
||||
if(my_beams.len) // Currently on.
|
||||
destroy_all_beams()
|
||||
color = "#FF0000"
|
||||
|
||||
timer_off_index++
|
||||
if(timer_off_index > off_duration.len)
|
||||
timer_off_index = 1
|
||||
|
||||
spawn(off_duration[timer_off_index])
|
||||
.()
|
||||
|
||||
else // Currently off.
|
||||
// If nobody's around, keep the beams off to avoid wasteful beam process(), if they have one.
|
||||
if(!always_run && !check_for_player_proximity(src, proximity_needed, ignore_ghosts, ignore_afk))
|
||||
spawn(retry_delay)
|
||||
.()
|
||||
return
|
||||
|
||||
create_beams()
|
||||
color = "#00FF00"
|
||||
|
||||
timer_on_index++
|
||||
if(timer_on_index > on_duration.len)
|
||||
timer_on_index = 1
|
||||
|
||||
spawn(on_duration[timer_on_index])
|
||||
.()
|
||||
|
||||
|
||||
|
||||
// Subtypes to use in maps and adminbuse.
|
||||
// Remember, beam_points ONLY connect to other beam_points with the same id variable.
|
||||
|
||||
// Creates the beam when instantiated and stays on until told otherwise.
|
||||
/obj/effect/map_effect/beam_point/instant
|
||||
make_beams_on_init = TRUE
|
||||
|
||||
/obj/effect/map_effect/beam_point/instant/electric
|
||||
beam_icon_state = "nzcrentrs_power"
|
||||
beam_type = /obj/effect/ebeam/reactive/electric
|
||||
beam_creation_sound = 'sound/effects/lightningshock.ogg'
|
||||
beam_destruction_sound = "sparks"
|
||||
|
||||
// Turns on and off on a timer.
|
||||
/obj/effect/map_effect/beam_point/timer
|
||||
use_timer = TRUE
|
||||
|
||||
// Shocks people who touch the beam while it's on. Flicks on and off on a specific pattern.
|
||||
/obj/effect/map_effect/beam_point/timer/electric
|
||||
beam_icon_state = "nzcrentrs_power"
|
||||
beam_type = /obj/effect/ebeam/reactive/electric
|
||||
beam_creation_sound = 'sound/effects/lightningshock.ogg'
|
||||
beam_destruction_sound = "sparks"
|
||||
seek_range = 3
|
||||
|
||||
// Is only a target for other beams to connect to.
|
||||
/obj/effect/map_effect/beam_point/end
|
||||
max_beams = 0
|
||||
|
||||
// Can only have one beam.
|
||||
/obj/effect/map_effect/beam_point/mono
|
||||
make_beams_on_init = TRUE
|
||||
max_beams = 1
|
||||
|
||||
@@ -1,69 +1,69 @@
|
||||
// These are objects you can use inside special maps (like PoIs), or for adminbuse.
|
||||
// Players cannot see or interact with these.
|
||||
/obj/effect/map_effect
|
||||
anchored = TRUE
|
||||
invisibility = 99 // So a badmin can go view these by changing their see_invisible.
|
||||
icon = 'icons/effects/map_effects.dmi'
|
||||
|
||||
// Below vars concern check_for_player_proximity() and is used to not waste effort if nobody is around to appreciate the effects.
|
||||
var/always_run = FALSE // If true, the game will not try to suppress this from firing if nobody is around to see it.
|
||||
var/proximity_needed = 12 // How many tiles a mob with a client must be for this to run.
|
||||
var/ignore_ghosts = FALSE // If true, ghosts won't satisfy the above requirement.
|
||||
var/ignore_afk = TRUE // If true, AFK people (5 minutes) won't satisfy it as well.
|
||||
var/retry_delay = 5 SECONDS // How long until we check for players again.
|
||||
var/next_attempt = 0 // Next time we're going to do ACTUAL WORK
|
||||
|
||||
/obj/effect/map_effect/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/map_effect/singularity_pull()
|
||||
return
|
||||
|
||||
/obj/effect/map_effect/singularity_act()
|
||||
return
|
||||
|
||||
// Base type for effects that run on variable intervals.
|
||||
/obj/effect/map_effect/interval
|
||||
var/interval_lower_bound = 5 SECONDS // Lower number for how often the map_effect will trigger.
|
||||
var/interval_upper_bound = 5 SECONDS // Higher number for above.
|
||||
|
||||
/obj/effect/map_effect/interval/Initialize()
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/effect/map_effect/interval/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
// Override this for the specific thing to do.
|
||||
/obj/effect/map_effect/interval/proc/trigger()
|
||||
return
|
||||
|
||||
// Handles the delay and making sure it doesn't run when it would be bad.
|
||||
/obj/effect/map_effect/interval/process()
|
||||
//Not yet!
|
||||
if(world.time < next_attempt)
|
||||
return
|
||||
|
||||
// Check to see if we're useful first.
|
||||
if(!always_run && !check_for_player_proximity(src, proximity_needed, ignore_ghosts, ignore_afk))
|
||||
next_attempt = world.time + retry_delay
|
||||
// Hey there's someone nearby.
|
||||
else
|
||||
next_attempt = world.time + rand(interval_lower_bound, interval_upper_bound)
|
||||
trigger()
|
||||
|
||||
// Helper proc to optimize the use of effects by making sure they do not run if nobody is around to perceive it.
|
||||
/proc/check_for_player_proximity(var/atom/proximity_to, var/radius = 12, var/ignore_ghosts = FALSE, var/ignore_afk = TRUE)
|
||||
if(!proximity_to)
|
||||
return FALSE
|
||||
|
||||
for(var/thing in player_list)
|
||||
var/mob/M = thing // Avoiding typechecks for more speed, player_list will only contain mobs anyways.
|
||||
if(ignore_ghosts && isobserver(M))
|
||||
continue
|
||||
if(ignore_afk && M.client && M.client.is_afk(5 MINUTES))
|
||||
continue
|
||||
if(M.z == proximity_to.z && get_dist(M, proximity_to) <= radius)
|
||||
return TRUE
|
||||
return FALSE
|
||||
// These are objects you can use inside special maps (like PoIs), or for adminbuse.
|
||||
// Players cannot see or interact with these.
|
||||
/obj/effect/map_effect
|
||||
anchored = TRUE
|
||||
invisibility = 99 // So a badmin can go view these by changing their see_invisible.
|
||||
icon = 'icons/effects/map_effects.dmi'
|
||||
|
||||
// Below vars concern check_for_player_proximity() and is used to not waste effort if nobody is around to appreciate the effects.
|
||||
var/always_run = FALSE // If true, the game will not try to suppress this from firing if nobody is around to see it.
|
||||
var/proximity_needed = 12 // How many tiles a mob with a client must be for this to run.
|
||||
var/ignore_ghosts = FALSE // If true, ghosts won't satisfy the above requirement.
|
||||
var/ignore_afk = TRUE // If true, AFK people (5 minutes) won't satisfy it as well.
|
||||
var/retry_delay = 5 SECONDS // How long until we check for players again.
|
||||
var/next_attempt = 0 // Next time we're going to do ACTUAL WORK
|
||||
|
||||
/obj/effect/map_effect/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/map_effect/singularity_pull()
|
||||
return
|
||||
|
||||
/obj/effect/map_effect/singularity_act()
|
||||
return
|
||||
|
||||
// Base type for effects that run on variable intervals.
|
||||
/obj/effect/map_effect/interval
|
||||
var/interval_lower_bound = 5 SECONDS // Lower number for how often the map_effect will trigger.
|
||||
var/interval_upper_bound = 5 SECONDS // Higher number for above.
|
||||
|
||||
/obj/effect/map_effect/interval/Initialize()
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/effect/map_effect/interval/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
// Override this for the specific thing to do.
|
||||
/obj/effect/map_effect/interval/proc/trigger()
|
||||
return
|
||||
|
||||
// Handles the delay and making sure it doesn't run when it would be bad.
|
||||
/obj/effect/map_effect/interval/process()
|
||||
//Not yet!
|
||||
if(world.time < next_attempt)
|
||||
return
|
||||
|
||||
// Check to see if we're useful first.
|
||||
if(!always_run && !check_for_player_proximity(src, proximity_needed, ignore_ghosts, ignore_afk))
|
||||
next_attempt = world.time + retry_delay
|
||||
// Hey there's someone nearby.
|
||||
else
|
||||
next_attempt = world.time + rand(interval_lower_bound, interval_upper_bound)
|
||||
trigger()
|
||||
|
||||
// Helper proc to optimize the use of effects by making sure they do not run if nobody is around to perceive it.
|
||||
/proc/check_for_player_proximity(var/atom/proximity_to, var/radius = 12, var/ignore_ghosts = FALSE, var/ignore_afk = TRUE)
|
||||
if(!proximity_to)
|
||||
return FALSE
|
||||
|
||||
for(var/thing in player_list)
|
||||
var/mob/M = thing // Avoiding typechecks for more speed, player_list will only contain mobs anyways.
|
||||
if(ignore_ghosts && isobserver(M))
|
||||
continue
|
||||
if(ignore_afk && M.client && M.client.is_afk(5 MINUTES))
|
||||
continue
|
||||
if(M.z == proximity_to.z && get_dist(M, proximity_to) <= radius)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
// Emits light forever with magic. Useful for mood lighting in Points of Interest.
|
||||
// Be sure to check how it looks ingame, and fiddle with the settings until it looks right.
|
||||
/obj/effect/map_effect/perma_light
|
||||
name = "permanent light"
|
||||
icon_state = "permalight"
|
||||
|
||||
light_range = 3
|
||||
light_power = 1
|
||||
light_color = "#FFFFFF"
|
||||
light_on = TRUE
|
||||
|
||||
/obj/effect/map_effect/perma_light/brighter
|
||||
name = "permanent light (bright)"
|
||||
icon_state = "permalight"
|
||||
|
||||
light_range = 5
|
||||
light_power = 3
|
||||
light_color = "#FFFFFF"
|
||||
|
||||
/obj/effect/map_effect/perma_light/concentrated
|
||||
name = "permanent light (concentrated)"
|
||||
|
||||
light_range = 2
|
||||
light_power = 5
|
||||
|
||||
/obj/effect/map_effect/perma_light/concentrated/incandescent
|
||||
name = "permanent light (concentrated incandescent)"
|
||||
|
||||
light_color = LIGHT_COLOR_INCANDESCENT_TUBE
|
||||
|
||||
// VOREStation Addition Start
|
||||
/obj/effect/map_effect/perma_light/gateway
|
||||
name = "permanent light (gateway)"
|
||||
icon_state = "permalight"
|
||||
|
||||
light_range = 10
|
||||
light_power = 5
|
||||
light_color = "#b6cdff"
|
||||
// Emits light forever with magic. Useful for mood lighting in Points of Interest.
|
||||
// Be sure to check how it looks ingame, and fiddle with the settings until it looks right.
|
||||
/obj/effect/map_effect/perma_light
|
||||
name = "permanent light"
|
||||
icon_state = "permalight"
|
||||
|
||||
light_range = 3
|
||||
light_power = 1
|
||||
light_color = "#FFFFFF"
|
||||
light_on = TRUE
|
||||
|
||||
/obj/effect/map_effect/perma_light/brighter
|
||||
name = "permanent light (bright)"
|
||||
icon_state = "permalight"
|
||||
|
||||
light_range = 5
|
||||
light_power = 3
|
||||
light_color = "#FFFFFF"
|
||||
|
||||
/obj/effect/map_effect/perma_light/concentrated
|
||||
name = "permanent light (concentrated)"
|
||||
|
||||
light_range = 2
|
||||
light_power = 5
|
||||
|
||||
/obj/effect/map_effect/perma_light/concentrated/incandescent
|
||||
name = "permanent light (concentrated incandescent)"
|
||||
|
||||
light_color = LIGHT_COLOR_INCANDESCENT_TUBE
|
||||
|
||||
// VOREStation Addition Start
|
||||
/obj/effect/map_effect/perma_light/gateway
|
||||
name = "permanent light (gateway)"
|
||||
icon_state = "permalight"
|
||||
|
||||
light_range = 10
|
||||
light_power = 5
|
||||
light_color = "#b6cdff"
|
||||
// VOREStation Addition End
|
||||
@@ -1,19 +1,19 @@
|
||||
// Constantly emites radiation from the tile it's placed on.
|
||||
/obj/effect/map_effect/radiation_emitter
|
||||
name = "radiation emitter"
|
||||
icon_state = "radiation_emitter"
|
||||
var/radiation_power = 30 // Bigger numbers means more radiation.
|
||||
|
||||
/obj/effect/map_effect/radiation_emitter/Initialize()
|
||||
START_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/map_effect/radiation_emitter/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/map_effect/radiation_emitter/process()
|
||||
SSradiation.radiate(src, radiation_power)
|
||||
|
||||
// Constantly emites radiation from the tile it's placed on.
|
||||
/obj/effect/map_effect/radiation_emitter
|
||||
name = "radiation emitter"
|
||||
icon_state = "radiation_emitter"
|
||||
var/radiation_power = 30 // Bigger numbers means more radiation.
|
||||
|
||||
/obj/effect/map_effect/radiation_emitter/Initialize()
|
||||
START_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/map_effect/radiation_emitter/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/map_effect/radiation_emitter/process()
|
||||
SSradiation.radiate(src, radiation_power)
|
||||
|
||||
/obj/effect/map_effect/radiation_emitter/strong
|
||||
radiation_power = 100
|
||||
@@ -1,17 +1,17 @@
|
||||
// Makes the screen shake for nearby players every so often.
|
||||
/obj/effect/map_effect/interval/screen_shaker
|
||||
name = "screen shaker"
|
||||
icon_state = "screen_shaker"
|
||||
|
||||
interval_lower_bound = 1 SECOND
|
||||
interval_upper_bound = 2 SECONDS
|
||||
|
||||
var/shake_radius = 7 // How far the shaking effect extends to. By default it is one screen length.
|
||||
var/shake_duration = 2 // How long the shaking lasts.
|
||||
var/shake_strength = 1 // How much it shakes.
|
||||
|
||||
/obj/effect/map_effect/interval/screen_shaker/trigger()
|
||||
for(var/mob/M as anything in player_list)
|
||||
if(M.z == src.z && get_dist(src, M) <= shake_radius)
|
||||
shake_camera(M, shake_duration, shake_strength)
|
||||
// Makes the screen shake for nearby players every so often.
|
||||
/obj/effect/map_effect/interval/screen_shaker
|
||||
name = "screen shaker"
|
||||
icon_state = "screen_shaker"
|
||||
|
||||
interval_lower_bound = 1 SECOND
|
||||
interval_upper_bound = 2 SECONDS
|
||||
|
||||
var/shake_radius = 7 // How far the shaking effect extends to. By default it is one screen length.
|
||||
var/shake_duration = 2 // How long the shaking lasts.
|
||||
var/shake_strength = 1 // How much it shakes.
|
||||
|
||||
/obj/effect/map_effect/interval/screen_shaker/trigger()
|
||||
for(var/mob/M as anything in player_list)
|
||||
if(M.z == src.z && get_dist(src, M) <= shake_radius)
|
||||
shake_camera(M, shake_duration, shake_strength)
|
||||
..()
|
||||
+404
-404
@@ -1,404 +1,404 @@
|
||||
/obj/effect/mine
|
||||
name = "land mine" //The name and description are deliberately NOT modified, so you can't game the mines you find.
|
||||
desc = "A small explosive land mine."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "landmine"
|
||||
var/triggered = 0
|
||||
var/smoke_strength = 3
|
||||
var/obj/item/weapon/mine/mineitemtype = /obj/item/weapon/mine
|
||||
var/panel_open = FALSE
|
||||
var/datum/wires/mines/wires = null
|
||||
var/camo_net = FALSE // Will the mine 'cloak' on deployment?
|
||||
|
||||
// The trap item will be triggered in some manner when detonating. Default only checks for grenades.
|
||||
var/obj/item/trap = null
|
||||
|
||||
/obj/effect/mine/Initialize()
|
||||
icon_state = "landmine_armed"
|
||||
wires = new(src)
|
||||
. = ..()
|
||||
if(ispath(trap))
|
||||
trap = new trap(src)
|
||||
register_dangerous_to_step()
|
||||
if(camo_net)
|
||||
alpha = 50
|
||||
|
||||
/obj/effect/mine/Destroy()
|
||||
unregister_dangerous_to_step()
|
||||
if(trap)
|
||||
QDEL_NULL(trap)
|
||||
qdel_null(wires)
|
||||
return ..()
|
||||
|
||||
/obj/effect/mine/Moved(atom/oldloc)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/turf/old_turf = get_turf(oldloc)
|
||||
var/turf/new_turf = get_turf(src)
|
||||
if(old_turf != new_turf)
|
||||
old_turf.unregister_dangerous_object(src)
|
||||
new_turf.register_dangerous_object(src)
|
||||
|
||||
/obj/effect/mine/proc/explode(var/mob/living/M)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
triggered = 1
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
|
||||
if(trap)
|
||||
trigger_trap(M)
|
||||
visible_message("\The [src.name] flashes as it is triggered!")
|
||||
|
||||
else
|
||||
explosion(loc, 0, 2, 3, 4) //land mines are dangerous, folks.
|
||||
visible_message("\The [src.name] detonates!")
|
||||
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/proc/trigger_trap(var/mob/living/victim)
|
||||
if(istype(trap, /obj/item/weapon/grenade))
|
||||
var/obj/item/weapon/grenade/G = trap
|
||||
trap = null
|
||||
G.forceMove(get_turf(src))
|
||||
if(victim.ckey)
|
||||
msg_admin_attack("[key_name_admin(victim)] stepped on \a [src.name], triggering [trap]")
|
||||
G.activate()
|
||||
|
||||
if(istype(trap, /obj/item/device/transfer_valve))
|
||||
var/obj/item/device/transfer_valve/TV = trap
|
||||
trap = null
|
||||
TV.forceMove(get_turf(src))
|
||||
TV.toggle_valve()
|
||||
|
||||
/obj/effect/mine/bullet_act()
|
||||
if(prob(50))
|
||||
explode()
|
||||
|
||||
/obj/effect/mine/ex_act(severity)
|
||||
if(severity <= 2 || prob(50))
|
||||
explode()
|
||||
..()
|
||||
|
||||
/obj/effect/mine/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
Bumped(AM)
|
||||
|
||||
/obj/effect/mine/Bumped(mob/M as mob|obj)
|
||||
|
||||
if(triggered)
|
||||
return
|
||||
|
||||
if(istype(M, /obj/mecha))
|
||||
explode(M)
|
||||
|
||||
if(istype(M, /mob/living/))
|
||||
var/mob/living/mob = M
|
||||
if(!mob.hovering || !mob.flying)
|
||||
explode(M)
|
||||
|
||||
/obj/effect/mine/attackby(obj/item/W as obj, mob/living/user as mob)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
panel_open = !panel_open
|
||||
user.visible_message("<span class='warning'>[user] very carefully screws the mine's panel [panel_open ? "open" : "closed"].</span>",
|
||||
"<span class='notice'>You very carefully screw the mine's panel [panel_open ? "open" : "closed"].</span>")
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
|
||||
// Panel open, stay uncloaked, or uncloak if already cloaked. If you don't cloak on place, ignore it and just be normal alpha.
|
||||
alpha = camo_net ? (panel_open ? 255 : 50) : 255
|
||||
|
||||
else if((W.has_tool_quality(TOOL_WIRECUTTER) || istype(W, /obj/item/device/multitool)) && panel_open)
|
||||
interact(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/effect/mine/interact(mob/living/user as mob)
|
||||
if(!panel_open || istype(user, /mob/living/silicon/ai))
|
||||
return
|
||||
user.set_machine(src)
|
||||
wires.Interact(user)
|
||||
|
||||
/obj/effect/mine/camo
|
||||
camo_net = TRUE
|
||||
|
||||
/obj/effect/mine/dnascramble
|
||||
mineitemtype = /obj/item/weapon/mine/dnascramble
|
||||
|
||||
/obj/effect/mine/dnascramble/explode(var/mob/living/M)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
triggered = 1
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
if(istype(M))
|
||||
M.radiation += 50
|
||||
randmutb(M)
|
||||
domutcheck(M,null)
|
||||
visible_message("\The [src.name] flashes violently before disintegrating!")
|
||||
spawn(0)
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/stun
|
||||
mineitemtype = /obj/item/weapon/mine/stun
|
||||
|
||||
/obj/effect/mine/stun/explode(var/mob/living/M)
|
||||
triggered = 1
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
if(istype(M))
|
||||
M.Stun(30)
|
||||
visible_message("\The [src.name] flashes violently before disintegrating!")
|
||||
spawn(0)
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/n2o
|
||||
mineitemtype = /obj/item/weapon/mine/n2o
|
||||
|
||||
/obj/effect/mine/n2o/explode(var/mob/living/M)
|
||||
triggered = 1
|
||||
for (var/turf/simulated/floor/target in range(1,src))
|
||||
if(!target.blocks_air)
|
||||
target.assume_gas("nitrous_oxide", 30)
|
||||
visible_message("\The [src.name] detonates!")
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/phoron
|
||||
mineitemtype = /obj/item/weapon/mine/phoron
|
||||
|
||||
/obj/effect/mine/phoron/explode(var/mob/living/M)
|
||||
triggered = 1
|
||||
for (var/turf/simulated/floor/target in range(1,src))
|
||||
if(!target.blocks_air)
|
||||
target.assume_gas("phoron", 30)
|
||||
target.hotspot_expose(1000, CELL_VOLUME)
|
||||
visible_message("\The [src.name] detonates!")
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/kick
|
||||
mineitemtype = /obj/item/weapon/mine/kick
|
||||
|
||||
/obj/effect/mine/kick/explode(var/mob/living/M)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
triggered = 1
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
if(istype(M, /obj/mecha))
|
||||
var/obj/mecha/E = M
|
||||
M = E.occupant
|
||||
if(istype(M))
|
||||
qdel(M.client)
|
||||
spawn(0)
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/frag
|
||||
mineitemtype = /obj/item/weapon/mine/frag
|
||||
var/fragment_types = list(/obj/item/projectile/bullet/pellet/fragment)
|
||||
var/num_fragments = 20 //total number of fragments produced by the grenade
|
||||
//The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern
|
||||
var/spread_range = 7
|
||||
|
||||
/obj/effect/mine/frag/explode(var/mob/living/M)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
triggered = 1
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
var/turf/O = get_turf(src)
|
||||
if(!O)
|
||||
return
|
||||
src.fragmentate(O, 20, 7, list(/obj/item/projectile/bullet/pellet/fragment)) //only 20 weak fragments because you're stepping directly on it
|
||||
visible_message("\The [src.name] detonates!")
|
||||
spawn(0)
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/training //Name and Desc commented out so it's possible to trick people with the training mines
|
||||
// name = "training mine"
|
||||
// desc = "A mine with its payload removed, for EOD training and demonstrations."
|
||||
mineitemtype = /obj/item/weapon/mine/training
|
||||
|
||||
/obj/effect/mine/training/explode(var/mob/living/M)
|
||||
triggered = 1
|
||||
visible_message("\The [src.name]'s light flashes rapidly as it 'explodes'.")
|
||||
new src.mineitemtype(get_turf(src))
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/emp
|
||||
mineitemtype = /obj/item/weapon/mine/emp
|
||||
|
||||
/obj/effect/mine/emp/explode(var/mob/living/M)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
visible_message("\The [src.name] flashes violently before disintegrating!")
|
||||
empulse(loc, 2, 4, 7, 10, 1) // As strong as an EMP grenade
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/emp/camo
|
||||
camo_net = TRUE
|
||||
|
||||
/obj/effect/mine/incendiary
|
||||
mineitemtype = /obj/item/weapon/mine/incendiary
|
||||
|
||||
/obj/effect/mine/incendiary/explode(var/mob/living/M)
|
||||
triggered = 1
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
if(istype(M))
|
||||
M.adjust_fire_stacks(5)
|
||||
M.fire_act()
|
||||
visible_message("\The [src.name] bursts into flames!")
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/gadget
|
||||
mineitemtype = /obj/item/weapon/mine/gadget
|
||||
|
||||
/obj/effect/mine/gadget/explode(var/mob/living/M)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
triggered = 1
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
|
||||
if(trap)
|
||||
trigger_trap(M)
|
||||
visible_message("\The [src.name] flashes as it is triggered!")
|
||||
|
||||
else
|
||||
explosion(loc, 0, 0, 2, 2)
|
||||
visible_message("\The [src.name] detonates!")
|
||||
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// The held item version of the above mines
|
||||
/////////////////////////////////////////////
|
||||
/obj/item/weapon/mine
|
||||
name = "mine"
|
||||
desc = "A small explosive mine with 'HE' and a grenade symbol on the side."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "uglymine"
|
||||
var/countdown = 10
|
||||
var/minetype = /obj/effect/mine //This MUST be an /obj/effect/mine type, or it'll runtime.
|
||||
|
||||
var/obj/item/trap = null
|
||||
|
||||
var/list/allowed_gadgets = null
|
||||
|
||||
/obj/item/weapon/mine/attack_self(mob/user as mob) // You do not want to move or throw a land mine while priming it... Explosives + Sudden Movement = Bad Times
|
||||
add_fingerprint(user)
|
||||
msg_admin_attack("[key_name_admin(user)] primed \a [src]")
|
||||
user.visible_message("[user] starts priming \the [src.name].", "You start priming \the [src.name]. Hold still!")
|
||||
if(do_after(user, 10 SECONDS))
|
||||
playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
|
||||
prime(user)
|
||||
else
|
||||
visible_message("[user] triggers \the [src.name]!", "You accidentally trigger \the [src.name]!")
|
||||
prime(user, TRUE)
|
||||
return
|
||||
|
||||
/obj/item/weapon/mine/attackby(obj/item/W as obj, mob/living/user as mob)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER) && trap)
|
||||
to_chat(user, "<span class='notice'>You begin removing \the [trap].</span>")
|
||||
if(do_after(user, 10 SECONDS))
|
||||
to_chat(user, "<span class='notice'>You finish disconnecting the mine's trigger.</span>")
|
||||
trap.forceMove(get_turf(src))
|
||||
trap = null
|
||||
return
|
||||
|
||||
if(LAZYLEN(allowed_gadgets) && !trap)
|
||||
var/allowed = FALSE
|
||||
|
||||
for(var/path in allowed_gadgets)
|
||||
if(istype(W, path))
|
||||
allowed = TRUE
|
||||
break
|
||||
|
||||
if(allowed)
|
||||
user.drop_from_inventory(W)
|
||||
W.forceMove(src)
|
||||
trap = W
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/weapon/mine/proc/prime(mob/user as mob, var/explode_now = FALSE)
|
||||
visible_message("\The [src.name] beeps as the priming sequence completes.")
|
||||
var/obj/effect/mine/R = new minetype(get_turf(src))
|
||||
src.transfer_fingerprints_to(R)
|
||||
R.add_fingerprint(user)
|
||||
if(trap)
|
||||
R.trap = trap
|
||||
trap = null
|
||||
R.trap.forceMove(R)
|
||||
if(explode_now)
|
||||
R.explode(user)
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/mine/dnascramble
|
||||
name = "radiation mine"
|
||||
desc = "A small explosive mine with a radiation symbol on the side."
|
||||
minetype = /obj/effect/mine/dnascramble
|
||||
|
||||
/obj/item/weapon/mine/phoron
|
||||
name = "incendiary mine"
|
||||
desc = "A small explosive mine with a fire symbol on the side."
|
||||
minetype = /obj/effect/mine/phoron
|
||||
|
||||
/obj/item/weapon/mine/kick
|
||||
name = "kick mine"
|
||||
desc = "Concentrated war crimes. Handle with care."
|
||||
minetype = /obj/effect/mine/kick
|
||||
|
||||
/obj/item/weapon/mine/n2o
|
||||
name = "nitrous oxide mine"
|
||||
desc = "A small explosive mine with three Z's on the side."
|
||||
minetype = /obj/effect/mine/n2o
|
||||
|
||||
/obj/item/weapon/mine/stun
|
||||
name = "stun mine"
|
||||
desc = "A small explosive mine with a lightning bolt symbol on the side."
|
||||
minetype = /obj/effect/mine/stun
|
||||
|
||||
/obj/item/weapon/mine/frag
|
||||
name = "fragmentation mine"
|
||||
desc = "A small explosive mine with 'FRAG' and a grenade symbol on the side."
|
||||
minetype = /obj/effect/mine/frag
|
||||
|
||||
/obj/item/weapon/mine/training
|
||||
name = "training mine"
|
||||
desc = "A mine with its payload removed, for EOD training and demonstrations."
|
||||
minetype = /obj/effect/mine/training
|
||||
|
||||
/obj/item/weapon/mine/emp
|
||||
name = "emp mine"
|
||||
desc = "A small explosive mine with a lightning bolt symbol on the side."
|
||||
minetype = /obj/effect/mine/emp
|
||||
|
||||
/obj/item/weapon/mine/incendiary
|
||||
name = "incendiary mine"
|
||||
desc = "A small explosive mine with a fire symbol on the side."
|
||||
minetype = /obj/effect/mine/incendiary
|
||||
|
||||
/obj/item/weapon/mine/gadget
|
||||
name = "gadget mine"
|
||||
desc = "A small pressure-triggered device. If no component is added, the internal release bolts will detonate in unison when triggered."
|
||||
|
||||
allowed_gadgets = list(/obj/item/weapon/grenade, /obj/item/device/transfer_valve)
|
||||
|
||||
// This tells AI mobs to not be dumb and step on mines willingly.
|
||||
/obj/item/weapon/mine/is_safe_to_step(mob/living/L)
|
||||
if(!L.hovering || !L.flying)
|
||||
return FALSE
|
||||
return ..()
|
||||
/obj/effect/mine
|
||||
name = "land mine" //The name and description are deliberately NOT modified, so you can't game the mines you find.
|
||||
desc = "A small explosive land mine."
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "landmine"
|
||||
var/triggered = 0
|
||||
var/smoke_strength = 3
|
||||
var/obj/item/weapon/mine/mineitemtype = /obj/item/weapon/mine
|
||||
var/panel_open = FALSE
|
||||
var/datum/wires/mines/wires = null
|
||||
var/camo_net = FALSE // Will the mine 'cloak' on deployment?
|
||||
|
||||
// The trap item will be triggered in some manner when detonating. Default only checks for grenades.
|
||||
var/obj/item/trap = null
|
||||
|
||||
/obj/effect/mine/Initialize()
|
||||
icon_state = "landmine_armed"
|
||||
wires = new(src)
|
||||
. = ..()
|
||||
if(ispath(trap))
|
||||
trap = new trap(src)
|
||||
register_dangerous_to_step()
|
||||
if(camo_net)
|
||||
alpha = 50
|
||||
|
||||
/obj/effect/mine/Destroy()
|
||||
unregister_dangerous_to_step()
|
||||
if(trap)
|
||||
QDEL_NULL(trap)
|
||||
qdel_null(wires)
|
||||
return ..()
|
||||
|
||||
/obj/effect/mine/Moved(atom/oldloc)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/turf/old_turf = get_turf(oldloc)
|
||||
var/turf/new_turf = get_turf(src)
|
||||
if(old_turf != new_turf)
|
||||
old_turf.unregister_dangerous_object(src)
|
||||
new_turf.register_dangerous_object(src)
|
||||
|
||||
/obj/effect/mine/proc/explode(var/mob/living/M)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
triggered = 1
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
|
||||
if(trap)
|
||||
trigger_trap(M)
|
||||
visible_message("\The [src.name] flashes as it is triggered!")
|
||||
|
||||
else
|
||||
explosion(loc, 0, 2, 3, 4) //land mines are dangerous, folks.
|
||||
visible_message("\The [src.name] detonates!")
|
||||
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/proc/trigger_trap(var/mob/living/victim)
|
||||
if(istype(trap, /obj/item/weapon/grenade))
|
||||
var/obj/item/weapon/grenade/G = trap
|
||||
trap = null
|
||||
G.forceMove(get_turf(src))
|
||||
if(victim.ckey)
|
||||
msg_admin_attack("[key_name_admin(victim)] stepped on \a [src.name], triggering [trap]")
|
||||
G.activate()
|
||||
|
||||
if(istype(trap, /obj/item/device/transfer_valve))
|
||||
var/obj/item/device/transfer_valve/TV = trap
|
||||
trap = null
|
||||
TV.forceMove(get_turf(src))
|
||||
TV.toggle_valve()
|
||||
|
||||
/obj/effect/mine/bullet_act()
|
||||
if(prob(50))
|
||||
explode()
|
||||
|
||||
/obj/effect/mine/ex_act(severity)
|
||||
if(severity <= 2 || prob(50))
|
||||
explode()
|
||||
..()
|
||||
|
||||
/obj/effect/mine/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
Bumped(AM)
|
||||
|
||||
/obj/effect/mine/Bumped(mob/M as mob|obj)
|
||||
|
||||
if(triggered)
|
||||
return
|
||||
|
||||
if(istype(M, /obj/mecha))
|
||||
explode(M)
|
||||
|
||||
if(istype(M, /mob/living/))
|
||||
var/mob/living/mob = M
|
||||
if(!mob.hovering || !mob.flying)
|
||||
explode(M)
|
||||
|
||||
/obj/effect/mine/attackby(obj/item/W as obj, mob/living/user as mob)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
panel_open = !panel_open
|
||||
user.visible_message("<span class='warning'>[user] very carefully screws the mine's panel [panel_open ? "open" : "closed"].</span>",
|
||||
"<span class='notice'>You very carefully screw the mine's panel [panel_open ? "open" : "closed"].</span>")
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
|
||||
// Panel open, stay uncloaked, or uncloak if already cloaked. If you don't cloak on place, ignore it and just be normal alpha.
|
||||
alpha = camo_net ? (panel_open ? 255 : 50) : 255
|
||||
|
||||
else if((W.has_tool_quality(TOOL_WIRECUTTER) || istype(W, /obj/item/device/multitool)) && panel_open)
|
||||
interact(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/effect/mine/interact(mob/living/user as mob)
|
||||
if(!panel_open || istype(user, /mob/living/silicon/ai))
|
||||
return
|
||||
user.set_machine(src)
|
||||
wires.Interact(user)
|
||||
|
||||
/obj/effect/mine/camo
|
||||
camo_net = TRUE
|
||||
|
||||
/obj/effect/mine/dnascramble
|
||||
mineitemtype = /obj/item/weapon/mine/dnascramble
|
||||
|
||||
/obj/effect/mine/dnascramble/explode(var/mob/living/M)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
triggered = 1
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
if(istype(M))
|
||||
M.radiation += 50
|
||||
randmutb(M)
|
||||
domutcheck(M,null)
|
||||
visible_message("\The [src.name] flashes violently before disintegrating!")
|
||||
spawn(0)
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/stun
|
||||
mineitemtype = /obj/item/weapon/mine/stun
|
||||
|
||||
/obj/effect/mine/stun/explode(var/mob/living/M)
|
||||
triggered = 1
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
if(istype(M))
|
||||
M.Stun(30)
|
||||
visible_message("\The [src.name] flashes violently before disintegrating!")
|
||||
spawn(0)
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/n2o
|
||||
mineitemtype = /obj/item/weapon/mine/n2o
|
||||
|
||||
/obj/effect/mine/n2o/explode(var/mob/living/M)
|
||||
triggered = 1
|
||||
for (var/turf/simulated/floor/target in range(1,src))
|
||||
if(!target.blocks_air)
|
||||
target.assume_gas("nitrous_oxide", 30)
|
||||
visible_message("\The [src.name] detonates!")
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/phoron
|
||||
mineitemtype = /obj/item/weapon/mine/phoron
|
||||
|
||||
/obj/effect/mine/phoron/explode(var/mob/living/M)
|
||||
triggered = 1
|
||||
for (var/turf/simulated/floor/target in range(1,src))
|
||||
if(!target.blocks_air)
|
||||
target.assume_gas("phoron", 30)
|
||||
target.hotspot_expose(1000, CELL_VOLUME)
|
||||
visible_message("\The [src.name] detonates!")
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/kick
|
||||
mineitemtype = /obj/item/weapon/mine/kick
|
||||
|
||||
/obj/effect/mine/kick/explode(var/mob/living/M)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
triggered = 1
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
if(istype(M, /obj/mecha))
|
||||
var/obj/mecha/E = M
|
||||
M = E.occupant
|
||||
if(istype(M))
|
||||
qdel(M.client)
|
||||
spawn(0)
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/frag
|
||||
mineitemtype = /obj/item/weapon/mine/frag
|
||||
var/fragment_types = list(/obj/item/projectile/bullet/pellet/fragment)
|
||||
var/num_fragments = 20 //total number of fragments produced by the grenade
|
||||
//The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern
|
||||
var/spread_range = 7
|
||||
|
||||
/obj/effect/mine/frag/explode(var/mob/living/M)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
triggered = 1
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
var/turf/O = get_turf(src)
|
||||
if(!O)
|
||||
return
|
||||
src.fragmentate(O, 20, 7, list(/obj/item/projectile/bullet/pellet/fragment)) //only 20 weak fragments because you're stepping directly on it
|
||||
visible_message("\The [src.name] detonates!")
|
||||
spawn(0)
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/training //Name and Desc commented out so it's possible to trick people with the training mines
|
||||
// name = "training mine"
|
||||
// desc = "A mine with its payload removed, for EOD training and demonstrations."
|
||||
mineitemtype = /obj/item/weapon/mine/training
|
||||
|
||||
/obj/effect/mine/training/explode(var/mob/living/M)
|
||||
triggered = 1
|
||||
visible_message("\The [src.name]'s light flashes rapidly as it 'explodes'.")
|
||||
new src.mineitemtype(get_turf(src))
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/emp
|
||||
mineitemtype = /obj/item/weapon/mine/emp
|
||||
|
||||
/obj/effect/mine/emp/explode(var/mob/living/M)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
visible_message("\The [src.name] flashes violently before disintegrating!")
|
||||
empulse(loc, 2, 4, 7, 10, 1) // As strong as an EMP grenade
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/emp/camo
|
||||
camo_net = TRUE
|
||||
|
||||
/obj/effect/mine/incendiary
|
||||
mineitemtype = /obj/item/weapon/mine/incendiary
|
||||
|
||||
/obj/effect/mine/incendiary/explode(var/mob/living/M)
|
||||
triggered = 1
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
if(istype(M))
|
||||
M.adjust_fire_stacks(5)
|
||||
M.fire_act()
|
||||
visible_message("\The [src.name] bursts into flames!")
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/gadget
|
||||
mineitemtype = /obj/item/weapon/mine/gadget
|
||||
|
||||
/obj/effect/mine/gadget/explode(var/mob/living/M)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread()
|
||||
triggered = 1
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
|
||||
if(trap)
|
||||
trigger_trap(M)
|
||||
visible_message("\The [src.name] flashes as it is triggered!")
|
||||
|
||||
else
|
||||
explosion(loc, 0, 0, 2, 2)
|
||||
visible_message("\The [src.name] detonates!")
|
||||
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// The held item version of the above mines
|
||||
/////////////////////////////////////////////
|
||||
/obj/item/weapon/mine
|
||||
name = "mine"
|
||||
desc = "A small explosive mine with 'HE' and a grenade symbol on the side."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "uglymine"
|
||||
var/countdown = 10
|
||||
var/minetype = /obj/effect/mine //This MUST be an /obj/effect/mine type, or it'll runtime.
|
||||
|
||||
var/obj/item/trap = null
|
||||
|
||||
var/list/allowed_gadgets = null
|
||||
|
||||
/obj/item/weapon/mine/attack_self(mob/user as mob) // You do not want to move or throw a land mine while priming it... Explosives + Sudden Movement = Bad Times
|
||||
add_fingerprint(user)
|
||||
msg_admin_attack("[key_name_admin(user)] primed \a [src]")
|
||||
user.visible_message("[user] starts priming \the [src.name].", "You start priming \the [src.name]. Hold still!")
|
||||
if(do_after(user, 10 SECONDS))
|
||||
playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
|
||||
prime(user)
|
||||
else
|
||||
visible_message("[user] triggers \the [src.name]!", "You accidentally trigger \the [src.name]!")
|
||||
prime(user, TRUE)
|
||||
return
|
||||
|
||||
/obj/item/weapon/mine/attackby(obj/item/W as obj, mob/living/user as mob)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER) && trap)
|
||||
to_chat(user, "<span class='notice'>You begin removing \the [trap].</span>")
|
||||
if(do_after(user, 10 SECONDS))
|
||||
to_chat(user, "<span class='notice'>You finish disconnecting the mine's trigger.</span>")
|
||||
trap.forceMove(get_turf(src))
|
||||
trap = null
|
||||
return
|
||||
|
||||
if(LAZYLEN(allowed_gadgets) && !trap)
|
||||
var/allowed = FALSE
|
||||
|
||||
for(var/path in allowed_gadgets)
|
||||
if(istype(W, path))
|
||||
allowed = TRUE
|
||||
break
|
||||
|
||||
if(allowed)
|
||||
user.drop_from_inventory(W)
|
||||
W.forceMove(src)
|
||||
trap = W
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/weapon/mine/proc/prime(mob/user as mob, var/explode_now = FALSE)
|
||||
visible_message("\The [src.name] beeps as the priming sequence completes.")
|
||||
var/obj/effect/mine/R = new minetype(get_turf(src))
|
||||
src.transfer_fingerprints_to(R)
|
||||
R.add_fingerprint(user)
|
||||
if(trap)
|
||||
R.trap = trap
|
||||
trap = null
|
||||
R.trap.forceMove(R)
|
||||
if(explode_now)
|
||||
R.explode(user)
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/mine/dnascramble
|
||||
name = "radiation mine"
|
||||
desc = "A small explosive mine with a radiation symbol on the side."
|
||||
minetype = /obj/effect/mine/dnascramble
|
||||
|
||||
/obj/item/weapon/mine/phoron
|
||||
name = "incendiary mine"
|
||||
desc = "A small explosive mine with a fire symbol on the side."
|
||||
minetype = /obj/effect/mine/phoron
|
||||
|
||||
/obj/item/weapon/mine/kick
|
||||
name = "kick mine"
|
||||
desc = "Concentrated war crimes. Handle with care."
|
||||
minetype = /obj/effect/mine/kick
|
||||
|
||||
/obj/item/weapon/mine/n2o
|
||||
name = "nitrous oxide mine"
|
||||
desc = "A small explosive mine with three Z's on the side."
|
||||
minetype = /obj/effect/mine/n2o
|
||||
|
||||
/obj/item/weapon/mine/stun
|
||||
name = "stun mine"
|
||||
desc = "A small explosive mine with a lightning bolt symbol on the side."
|
||||
minetype = /obj/effect/mine/stun
|
||||
|
||||
/obj/item/weapon/mine/frag
|
||||
name = "fragmentation mine"
|
||||
desc = "A small explosive mine with 'FRAG' and a grenade symbol on the side."
|
||||
minetype = /obj/effect/mine/frag
|
||||
|
||||
/obj/item/weapon/mine/training
|
||||
name = "training mine"
|
||||
desc = "A mine with its payload removed, for EOD training and demonstrations."
|
||||
minetype = /obj/effect/mine/training
|
||||
|
||||
/obj/item/weapon/mine/emp
|
||||
name = "emp mine"
|
||||
desc = "A small explosive mine with a lightning bolt symbol on the side."
|
||||
minetype = /obj/effect/mine/emp
|
||||
|
||||
/obj/item/weapon/mine/incendiary
|
||||
name = "incendiary mine"
|
||||
desc = "A small explosive mine with a fire symbol on the side."
|
||||
minetype = /obj/effect/mine/incendiary
|
||||
|
||||
/obj/item/weapon/mine/gadget
|
||||
name = "gadget mine"
|
||||
desc = "A small pressure-triggered device. If no component is added, the internal release bolts will detonate in unison when triggered."
|
||||
|
||||
allowed_gadgets = list(/obj/item/weapon/grenade, /obj/item/device/transfer_valve)
|
||||
|
||||
// This tells AI mobs to not be dumb and step on mines willingly.
|
||||
/obj/item/weapon/mine/is_safe_to_step(mob/living/L)
|
||||
if(!L.hovering || !L.flying)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
+152
-152
@@ -1,152 +1,152 @@
|
||||
//The effect when you wrap a dead body in gift wrap
|
||||
/obj/effect/spresent
|
||||
name = "strange present"
|
||||
desc = "It's a ... present?"
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "strangepresent"
|
||||
density = TRUE
|
||||
anchored = FALSE
|
||||
|
||||
/obj/effect/temporary_effect
|
||||
name = "self deleting effect"
|
||||
desc = "How are you examining what which cannot be seen?"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
invisibility = 0
|
||||
var/time_to_die = 10 SECONDS // Afer which, it will delete itself.
|
||||
|
||||
/obj/effect/temporary_effect/Initialize()
|
||||
. = ..()
|
||||
if(time_to_die)
|
||||
QDEL_IN(src, time_to_die)
|
||||
|
||||
// Shown really briefly when attacking with axes.
|
||||
/obj/effect/temporary_effect/cleave_attack
|
||||
name = "cleaving attack"
|
||||
desc = "Something swinging really wide."
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "cleave"
|
||||
plane = ABOVE_MOB_PLANE
|
||||
layer = ABOVE_MOB_LAYER
|
||||
time_to_die = 6
|
||||
alpha = 140
|
||||
mouse_opacity = 0
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
|
||||
/obj/effect/temporary_effect/cleave_attack/Initialize() // Makes the slash fade smoothly. When completely transparent it should qdel itself.
|
||||
. = ..()
|
||||
animate(src, alpha = 0, time = time_to_die - 1)
|
||||
|
||||
/obj/effect/temporary_effect/shuttle_landing
|
||||
name = "shuttle landing"
|
||||
desc = "You better move if you don't want to go splat!"
|
||||
//VOREStation Edit Start
|
||||
icon = 'icons/goonstation/featherzone.dmi'
|
||||
icon_state = "hazard-corners"
|
||||
time_to_die = 5 SECONDS
|
||||
plane = PLANE_LIGHTING_ABOVE
|
||||
//VOREStation Edit End
|
||||
|
||||
// The manifestation of Zeus's might. Or just a really unlucky day.
|
||||
// This is purely a visual effect, this isn't the part of the code that hurts things.
|
||||
/obj/effect/temporary_effect/lightning_strike
|
||||
name = "lightning"
|
||||
desc = "How <i>shocked</i> you must be, to see this text. You must have <i>lightning</i> reflexes. \
|
||||
The humor in this description is just so <i>electrifying</i>."
|
||||
icon = 'icons/effects/96x256.dmi'
|
||||
icon_state = "lightning_strike"
|
||||
plane = PLANE_LIGHTING_ABOVE
|
||||
time_to_die = 1 SECOND
|
||||
pixel_x = -32
|
||||
|
||||
/obj/effect/temporary_effect/lightning_strike/Initialize()
|
||||
icon_state += "[rand(1,2)]" // To have two variants of lightning sprites.
|
||||
animate(src, alpha = 0, time = time_to_die - 1)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/dummy/lighting_obj
|
||||
name = "lighting fx obj"
|
||||
desc = "Tell a coder if you're seeing this."
|
||||
icon_state = "nothing"
|
||||
light_system = MOVABLE_LIGHT
|
||||
light_range = MINIMUM_USEFUL_LIGHT_RANGE
|
||||
light_color = COLOR_WHITE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
light_on = TRUE
|
||||
blocks_emissive = FALSE
|
||||
|
||||
/obj/effect/dummy/lighting_obj/Initialize(mapload, _range, _power, _color, _duration)
|
||||
. = ..()
|
||||
if(!isnull(_range))
|
||||
set_light_range(_range)
|
||||
if(!isnull(_power))
|
||||
set_light_power(_power)
|
||||
if(!isnull(_color))
|
||||
set_light_color(_color)
|
||||
if(_duration)
|
||||
QDEL_IN(src, _duration)
|
||||
|
||||
/obj/effect/dummy/lighting_obj/moblight
|
||||
name = "mob lighting fx"
|
||||
|
||||
/obj/effect/dummy/lighting_obj/moblight/Initialize(mapload, _color, _range, _power, _duration)
|
||||
. = ..()
|
||||
if(!ismob(loc))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/effect/dummy/lighting_obj/moblight/fire
|
||||
name = "fire"
|
||||
light_color = LIGHT_COLOR_FIRE
|
||||
light_range = LIGHT_RANGE_FIRE
|
||||
|
||||
/obj/effect/abstract
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
plane = ABOVE_MOB_PLANE
|
||||
|
||||
/obj/effect/abstract/light_spot
|
||||
icon = 'icons/effects/eris_flashlight.dmi'
|
||||
icon_state = "medium"
|
||||
pixel_x = -16
|
||||
pixel_y = -16
|
||||
|
||||
/obj/effect/abstract/directional_lighting
|
||||
var/obj/effect/abstract/light_spot/light_spot = new
|
||||
var/trans_angle
|
||||
var/icon_dist
|
||||
|
||||
/obj/effect/abstract/directional_lighting/Initialize()
|
||||
. = ..()
|
||||
vis_contents += light_spot
|
||||
|
||||
/obj/effect/abstract/directional_lighting/proc/face_light(atom/movable/source, angle, distance)
|
||||
if(!loc) // We're in nullspace
|
||||
return
|
||||
|
||||
// Save ourselves some matrix math
|
||||
if(angle != trans_angle)
|
||||
trans_angle = angle
|
||||
// Doing this in one operation (tn = turn(initial(tn), angle)) has strange results...
|
||||
light_spot.transform = initial(light_spot.transform)
|
||||
light_spot.transform = turn(light_spot.transform, angle)
|
||||
|
||||
if(icon_dist != distance)
|
||||
icon_dist = distance
|
||||
switch(distance)
|
||||
if(0)
|
||||
light_spot.icon_state = "vclose"
|
||||
if(1)
|
||||
light_spot.icon_state = "close"
|
||||
if(2)
|
||||
light_spot.icon_state = "medium"
|
||||
if(3 to INFINITY)
|
||||
light_spot.icon_state = "far"
|
||||
|
||||
/obj/effect/abstract/directional_lighting/Destroy(force)
|
||||
if(!force)
|
||||
stack_trace("Directional light atom deleted, but not by our component")
|
||||
return QDEL_HINT_LETMELIVE
|
||||
|
||||
vis_contents.Cut()
|
||||
qdel_null(light_spot)
|
||||
|
||||
return ..()
|
||||
//The effect when you wrap a dead body in gift wrap
|
||||
/obj/effect/spresent
|
||||
name = "strange present"
|
||||
desc = "It's a ... present?"
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "strangepresent"
|
||||
density = TRUE
|
||||
anchored = FALSE
|
||||
|
||||
/obj/effect/temporary_effect
|
||||
name = "self deleting effect"
|
||||
desc = "How are you examining what which cannot be seen?"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
invisibility = 0
|
||||
var/time_to_die = 10 SECONDS // Afer which, it will delete itself.
|
||||
|
||||
/obj/effect/temporary_effect/Initialize()
|
||||
. = ..()
|
||||
if(time_to_die)
|
||||
QDEL_IN(src, time_to_die)
|
||||
|
||||
// Shown really briefly when attacking with axes.
|
||||
/obj/effect/temporary_effect/cleave_attack
|
||||
name = "cleaving attack"
|
||||
desc = "Something swinging really wide."
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "cleave"
|
||||
plane = ABOVE_MOB_PLANE
|
||||
layer = ABOVE_MOB_LAYER
|
||||
time_to_die = 6
|
||||
alpha = 140
|
||||
mouse_opacity = 0
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
|
||||
/obj/effect/temporary_effect/cleave_attack/Initialize() // Makes the slash fade smoothly. When completely transparent it should qdel itself.
|
||||
. = ..()
|
||||
animate(src, alpha = 0, time = time_to_die - 1)
|
||||
|
||||
/obj/effect/temporary_effect/shuttle_landing
|
||||
name = "shuttle landing"
|
||||
desc = "You better move if you don't want to go splat!"
|
||||
//VOREStation Edit Start
|
||||
icon = 'icons/goonstation/featherzone.dmi'
|
||||
icon_state = "hazard-corners"
|
||||
time_to_die = 5 SECONDS
|
||||
plane = PLANE_LIGHTING_ABOVE
|
||||
//VOREStation Edit End
|
||||
|
||||
// The manifestation of Zeus's might. Or just a really unlucky day.
|
||||
// This is purely a visual effect, this isn't the part of the code that hurts things.
|
||||
/obj/effect/temporary_effect/lightning_strike
|
||||
name = "lightning"
|
||||
desc = "How <i>shocked</i> you must be, to see this text. You must have <i>lightning</i> reflexes. \
|
||||
The humor in this description is just so <i>electrifying</i>."
|
||||
icon = 'icons/effects/96x256.dmi'
|
||||
icon_state = "lightning_strike"
|
||||
plane = PLANE_LIGHTING_ABOVE
|
||||
time_to_die = 1 SECOND
|
||||
pixel_x = -32
|
||||
|
||||
/obj/effect/temporary_effect/lightning_strike/Initialize()
|
||||
icon_state += "[rand(1,2)]" // To have two variants of lightning sprites.
|
||||
animate(src, alpha = 0, time = time_to_die - 1)
|
||||
. = ..()
|
||||
|
||||
/obj/effect/dummy/lighting_obj
|
||||
name = "lighting fx obj"
|
||||
desc = "Tell a coder if you're seeing this."
|
||||
icon_state = "nothing"
|
||||
light_system = MOVABLE_LIGHT
|
||||
light_range = MINIMUM_USEFUL_LIGHT_RANGE
|
||||
light_color = COLOR_WHITE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
light_on = TRUE
|
||||
blocks_emissive = FALSE
|
||||
|
||||
/obj/effect/dummy/lighting_obj/Initialize(mapload, _range, _power, _color, _duration)
|
||||
. = ..()
|
||||
if(!isnull(_range))
|
||||
set_light_range(_range)
|
||||
if(!isnull(_power))
|
||||
set_light_power(_power)
|
||||
if(!isnull(_color))
|
||||
set_light_color(_color)
|
||||
if(_duration)
|
||||
QDEL_IN(src, _duration)
|
||||
|
||||
/obj/effect/dummy/lighting_obj/moblight
|
||||
name = "mob lighting fx"
|
||||
|
||||
/obj/effect/dummy/lighting_obj/moblight/Initialize(mapload, _color, _range, _power, _duration)
|
||||
. = ..()
|
||||
if(!ismob(loc))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/effect/dummy/lighting_obj/moblight/fire
|
||||
name = "fire"
|
||||
light_color = LIGHT_COLOR_FIRE
|
||||
light_range = LIGHT_RANGE_FIRE
|
||||
|
||||
/obj/effect/abstract
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
plane = ABOVE_MOB_PLANE
|
||||
|
||||
/obj/effect/abstract/light_spot
|
||||
icon = 'icons/effects/eris_flashlight.dmi'
|
||||
icon_state = "medium"
|
||||
pixel_x = -16
|
||||
pixel_y = -16
|
||||
|
||||
/obj/effect/abstract/directional_lighting
|
||||
var/obj/effect/abstract/light_spot/light_spot = new
|
||||
var/trans_angle
|
||||
var/icon_dist
|
||||
|
||||
/obj/effect/abstract/directional_lighting/Initialize()
|
||||
. = ..()
|
||||
vis_contents += light_spot
|
||||
|
||||
/obj/effect/abstract/directional_lighting/proc/face_light(atom/movable/source, angle, distance)
|
||||
if(!loc) // We're in nullspace
|
||||
return
|
||||
|
||||
// Save ourselves some matrix math
|
||||
if(angle != trans_angle)
|
||||
trans_angle = angle
|
||||
// Doing this in one operation (tn = turn(initial(tn), angle)) has strange results...
|
||||
light_spot.transform = initial(light_spot.transform)
|
||||
light_spot.transform = turn(light_spot.transform, angle)
|
||||
|
||||
if(icon_dist != distance)
|
||||
icon_dist = distance
|
||||
switch(distance)
|
||||
if(0)
|
||||
light_spot.icon_state = "vclose"
|
||||
if(1)
|
||||
light_spot.icon_state = "close"
|
||||
if(2)
|
||||
light_spot.icon_state = "medium"
|
||||
if(3 to INFINITY)
|
||||
light_spot.icon_state = "far"
|
||||
|
||||
/obj/effect/abstract/directional_lighting/Destroy(force)
|
||||
if(!force)
|
||||
stack_trace("Directional light atom deleted, but not by our component")
|
||||
return QDEL_HINT_LETMELIVE
|
||||
|
||||
vis_contents.Cut()
|
||||
qdel_null(light_spot)
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -1,191 +1,191 @@
|
||||
/obj/effect/overlay
|
||||
name = "overlay"
|
||||
unacidable = TRUE
|
||||
var/i_attached//Added for possible image attachments to objects. For hallucinations and the like.
|
||||
|
||||
/obj/effect/overlay/beam//Not actually a projectile, just an effect.
|
||||
name="beam"
|
||||
icon='icons/effects/beam.dmi'
|
||||
icon_state="b_beam"
|
||||
plane = ABOVE_OBJ_PLANE
|
||||
var/tmp/atom/BeamSource
|
||||
|
||||
/obj/effect/overlay/beam/New()
|
||||
..()
|
||||
spawn(10) qdel(src)
|
||||
|
||||
/obj/effect/overlay/palmtree_r
|
||||
name = "Palm tree"
|
||||
icon = 'icons/misc/beach2.dmi'
|
||||
icon_state = "palm1"
|
||||
density = TRUE
|
||||
plane = MOB_PLANE
|
||||
layer = ABOVE_MOB_LAYER
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/overlay/palmtree_l
|
||||
name = "Palm tree"
|
||||
icon = 'icons/misc/beach2.dmi'
|
||||
icon_state = "palm2"
|
||||
density = TRUE
|
||||
plane = MOB_PLANE
|
||||
layer = ABOVE_MOB_LAYER
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/overlay/coconut
|
||||
name = "Coconuts"
|
||||
icon = 'icons/misc/beach.dmi'
|
||||
icon_state = "coconuts"
|
||||
|
||||
/obj/effect/overlay/bluespacify
|
||||
name = "Bluespace"
|
||||
icon = 'icons/turf/space_vr.dmi' //VOREStation Edit
|
||||
icon_state = "bluespacify"
|
||||
plane = ABOVE_PLANE
|
||||
|
||||
/obj/effect/overlay/wallrot
|
||||
name = "wallrot"
|
||||
desc = "Ick..."
|
||||
icon = 'icons/effects/wallrot.dmi'
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
plane = MOB_PLANE
|
||||
layer = ABOVE_MOB_LAYER
|
||||
mouse_opacity = 0
|
||||
|
||||
/obj/effect/overlay/wallrot/New()
|
||||
..()
|
||||
pixel_x += rand(-10, 10)
|
||||
pixel_y += rand(-10, 10)
|
||||
|
||||
/obj/effect/overlay/snow
|
||||
name = "snow"
|
||||
icon = 'icons/turf/overlays.dmi'
|
||||
icon_state = "snow"
|
||||
anchored = TRUE
|
||||
plane = TURF_PLANE
|
||||
|
||||
// Todo: Add a version that gradually reaccumulates over time by means of alpha transparency. -Spades
|
||||
/obj/effect/overlay/snow/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (istype(W, /obj/item/weapon/shovel))
|
||||
user.visible_message("<span class='notice'>[user] begins to shovel away \the [src].</span>")
|
||||
if(do_after(user, 40))
|
||||
to_chat(user, "<span class='notice'>You have finished shoveling!</span>")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/effect/overlay/snow/floor
|
||||
icon_state = "snowfloor"
|
||||
plane = TURF_PLANE
|
||||
layer = ABOVE_TURF_LAYER
|
||||
mouse_opacity = 0 //Don't block underlying tile interactions
|
||||
|
||||
/obj/effect/overlay/snow/floor/edges
|
||||
icon_state = "snow_edges"
|
||||
|
||||
/obj/effect/overlay/snow/floor/surround
|
||||
icon_state = "snow_surround"
|
||||
|
||||
/obj/effect/overlay/snow/airlock
|
||||
icon_state = "snowairlock"
|
||||
layer = DOOR_CLOSED_LAYER+0.01
|
||||
|
||||
/obj/effect/overlay/snow/floor/pointy
|
||||
icon_state = "snowfloorpointy"
|
||||
|
||||
/obj/effect/overlay/snow/wall
|
||||
icon_state = "snowwall"
|
||||
plane = MOB_PLANE
|
||||
layer = ABOVE_MOB_LAYER
|
||||
|
||||
/obj/effect/overlay/holographic
|
||||
mouse_opacity = FALSE
|
||||
anchored = TRUE
|
||||
plane = ABOVE_PLANE
|
||||
|
||||
// Similar to the tesla ball but doesn't actually do anything and is purely visual.
|
||||
/obj/effect/overlay/energy_ball
|
||||
name = "energy ball"
|
||||
desc = "An energy ball."
|
||||
icon = 'icons/obj/tesla_engine/energy_ball.dmi'
|
||||
icon_state = "energy_ball"
|
||||
plane = PLANE_LIGHTING_ABOVE
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
|
||||
/obj/effect/overlay/vis
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
anchored = TRUE
|
||||
vis_flags = VIS_INHERIT_DIR
|
||||
///When detected to be unused it gets set to world.time, after a while it gets removed
|
||||
var/unused = 0
|
||||
///overlays which go unused for this amount of time get cleaned up
|
||||
var/cache_expiration = 2 MINUTES
|
||||
|
||||
/*
|
||||
/obj/effect/overlay/atmos_excited
|
||||
name = "excited group"
|
||||
icon = null
|
||||
icon_state = null
|
||||
anchored = TRUE // should only appear in vis_contents, but to be safe
|
||||
appearance_flags = RESET_TRANSFORM | TILE_BOUND
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
plane = ATMOS_GROUP_PLANE
|
||||
*/
|
||||
|
||||
/obj/effect/overlay/light_visible
|
||||
name = ""
|
||||
icon = 'icons/effects/light_overlays/light_32.dmi'
|
||||
icon_state = "light"
|
||||
plane = PLANE_O_LIGHTING_VISUAL
|
||||
appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
alpha = 0
|
||||
vis_flags = NONE
|
||||
blocks_emissive = FALSE
|
||||
|
||||
/obj/effect/overlay/light_visible/Destroy(force)
|
||||
if(!force)
|
||||
stack_trace("Movable light visible mask deleted, but not by our component")
|
||||
return QDEL_HINT_LETMELIVE
|
||||
return ..()
|
||||
|
||||
/obj/effect/overlay/light_cone
|
||||
name = ""
|
||||
icon = 'icons/effects/light_overlays/light_cone.dmi'
|
||||
icon_state = "light"
|
||||
plane = PLANE_O_LIGHTING_VISUAL
|
||||
appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
vis_flags = NONE
|
||||
alpha = 110
|
||||
blocks_emissive = FALSE
|
||||
|
||||
var/static/matrix/normal_transform
|
||||
|
||||
/obj/effect/overlay/light_cone/Initialize()
|
||||
. = ..()
|
||||
apply_standard_transform()
|
||||
|
||||
/obj/effect/overlay/light_cone/proc/reset_transform(apply_standard)
|
||||
transform = initial(transform)
|
||||
if(apply_standard)
|
||||
apply_standard_transform()
|
||||
|
||||
/obj/effect/overlay/light_cone/proc/apply_standard_transform()
|
||||
transform = transform.Translate(-32, -32)
|
||||
|
||||
/obj/effect/overlay/light_cone/Destroy(force)
|
||||
if(!force)
|
||||
stack_trace("Directional light cone deleted, but not by our component")
|
||||
return QDEL_HINT_LETMELIVE
|
||||
return ..()
|
||||
|
||||
/obj/effect/overlay/closet_door
|
||||
anchored = TRUE
|
||||
plane = FLOAT_PLANE
|
||||
layer = FLOAT_LAYER
|
||||
vis_flags = VIS_INHERIT_ID
|
||||
appearance_flags = KEEP_TOGETHER | LONG_GLIDE | PIXEL_SCALE
|
||||
/obj/effect/overlay
|
||||
name = "overlay"
|
||||
unacidable = TRUE
|
||||
var/i_attached//Added for possible image attachments to objects. For hallucinations and the like.
|
||||
|
||||
/obj/effect/overlay/beam//Not actually a projectile, just an effect.
|
||||
name="beam"
|
||||
icon='icons/effects/beam.dmi'
|
||||
icon_state="b_beam"
|
||||
plane = ABOVE_OBJ_PLANE
|
||||
var/tmp/atom/BeamSource
|
||||
|
||||
/obj/effect/overlay/beam/New()
|
||||
..()
|
||||
spawn(10) qdel(src)
|
||||
|
||||
/obj/effect/overlay/palmtree_r
|
||||
name = "Palm tree"
|
||||
icon = 'icons/misc/beach2.dmi'
|
||||
icon_state = "palm1"
|
||||
density = TRUE
|
||||
plane = MOB_PLANE
|
||||
layer = ABOVE_MOB_LAYER
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/overlay/palmtree_l
|
||||
name = "Palm tree"
|
||||
icon = 'icons/misc/beach2.dmi'
|
||||
icon_state = "palm2"
|
||||
density = TRUE
|
||||
plane = MOB_PLANE
|
||||
layer = ABOVE_MOB_LAYER
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/overlay/coconut
|
||||
name = "Coconuts"
|
||||
icon = 'icons/misc/beach.dmi'
|
||||
icon_state = "coconuts"
|
||||
|
||||
/obj/effect/overlay/bluespacify
|
||||
name = "Bluespace"
|
||||
icon = 'icons/turf/space_vr.dmi' //VOREStation Edit
|
||||
icon_state = "bluespacify"
|
||||
plane = ABOVE_PLANE
|
||||
|
||||
/obj/effect/overlay/wallrot
|
||||
name = "wallrot"
|
||||
desc = "Ick..."
|
||||
icon = 'icons/effects/wallrot.dmi'
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
plane = MOB_PLANE
|
||||
layer = ABOVE_MOB_LAYER
|
||||
mouse_opacity = 0
|
||||
|
||||
/obj/effect/overlay/wallrot/New()
|
||||
..()
|
||||
pixel_x += rand(-10, 10)
|
||||
pixel_y += rand(-10, 10)
|
||||
|
||||
/obj/effect/overlay/snow
|
||||
name = "snow"
|
||||
icon = 'icons/turf/overlays.dmi'
|
||||
icon_state = "snow"
|
||||
anchored = TRUE
|
||||
plane = TURF_PLANE
|
||||
|
||||
// Todo: Add a version that gradually reaccumulates over time by means of alpha transparency. -Spades
|
||||
/obj/effect/overlay/snow/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (istype(W, /obj/item/weapon/shovel))
|
||||
user.visible_message("<span class='notice'>[user] begins to shovel away \the [src].</span>")
|
||||
if(do_after(user, 40))
|
||||
to_chat(user, "<span class='notice'>You have finished shoveling!</span>")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/effect/overlay/snow/floor
|
||||
icon_state = "snowfloor"
|
||||
plane = TURF_PLANE
|
||||
layer = ABOVE_TURF_LAYER
|
||||
mouse_opacity = 0 //Don't block underlying tile interactions
|
||||
|
||||
/obj/effect/overlay/snow/floor/edges
|
||||
icon_state = "snow_edges"
|
||||
|
||||
/obj/effect/overlay/snow/floor/surround
|
||||
icon_state = "snow_surround"
|
||||
|
||||
/obj/effect/overlay/snow/airlock
|
||||
icon_state = "snowairlock"
|
||||
layer = DOOR_CLOSED_LAYER+0.01
|
||||
|
||||
/obj/effect/overlay/snow/floor/pointy
|
||||
icon_state = "snowfloorpointy"
|
||||
|
||||
/obj/effect/overlay/snow/wall
|
||||
icon_state = "snowwall"
|
||||
plane = MOB_PLANE
|
||||
layer = ABOVE_MOB_LAYER
|
||||
|
||||
/obj/effect/overlay/holographic
|
||||
mouse_opacity = FALSE
|
||||
anchored = TRUE
|
||||
plane = ABOVE_PLANE
|
||||
|
||||
// Similar to the tesla ball but doesn't actually do anything and is purely visual.
|
||||
/obj/effect/overlay/energy_ball
|
||||
name = "energy ball"
|
||||
desc = "An energy ball."
|
||||
icon = 'icons/obj/tesla_engine/energy_ball.dmi'
|
||||
icon_state = "energy_ball"
|
||||
plane = PLANE_LIGHTING_ABOVE
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
|
||||
/obj/effect/overlay/vis
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
anchored = TRUE
|
||||
vis_flags = VIS_INHERIT_DIR
|
||||
///When detected to be unused it gets set to world.time, after a while it gets removed
|
||||
var/unused = 0
|
||||
///overlays which go unused for this amount of time get cleaned up
|
||||
var/cache_expiration = 2 MINUTES
|
||||
|
||||
/*
|
||||
/obj/effect/overlay/atmos_excited
|
||||
name = "excited group"
|
||||
icon = null
|
||||
icon_state = null
|
||||
anchored = TRUE // should only appear in vis_contents, but to be safe
|
||||
appearance_flags = RESET_TRANSFORM | TILE_BOUND
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
plane = ATMOS_GROUP_PLANE
|
||||
*/
|
||||
|
||||
/obj/effect/overlay/light_visible
|
||||
name = ""
|
||||
icon = 'icons/effects/light_overlays/light_32.dmi'
|
||||
icon_state = "light"
|
||||
plane = PLANE_O_LIGHTING_VISUAL
|
||||
appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
alpha = 0
|
||||
vis_flags = NONE
|
||||
blocks_emissive = FALSE
|
||||
|
||||
/obj/effect/overlay/light_visible/Destroy(force)
|
||||
if(!force)
|
||||
stack_trace("Movable light visible mask deleted, but not by our component")
|
||||
return QDEL_HINT_LETMELIVE
|
||||
return ..()
|
||||
|
||||
/obj/effect/overlay/light_cone
|
||||
name = ""
|
||||
icon = 'icons/effects/light_overlays/light_cone.dmi'
|
||||
icon_state = "light"
|
||||
plane = PLANE_O_LIGHTING_VISUAL
|
||||
appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
vis_flags = NONE
|
||||
alpha = 110
|
||||
blocks_emissive = FALSE
|
||||
|
||||
var/static/matrix/normal_transform
|
||||
|
||||
/obj/effect/overlay/light_cone/Initialize()
|
||||
. = ..()
|
||||
apply_standard_transform()
|
||||
|
||||
/obj/effect/overlay/light_cone/proc/reset_transform(apply_standard)
|
||||
transform = initial(transform)
|
||||
if(apply_standard)
|
||||
apply_standard_transform()
|
||||
|
||||
/obj/effect/overlay/light_cone/proc/apply_standard_transform()
|
||||
transform = transform.Translate(-32, -32)
|
||||
|
||||
/obj/effect/overlay/light_cone/Destroy(force)
|
||||
if(!force)
|
||||
stack_trace("Directional light cone deleted, but not by our component")
|
||||
return QDEL_HINT_LETMELIVE
|
||||
return ..()
|
||||
|
||||
/obj/effect/overlay/closet_door
|
||||
anchored = TRUE
|
||||
plane = FLOAT_PLANE
|
||||
layer = FLOAT_LAYER
|
||||
vis_flags = VIS_INHERIT_ID
|
||||
appearance_flags = KEEP_TOGETHER | LONG_GLIDE | PIXEL_SCALE
|
||||
|
||||
@@ -1,69 +1,69 @@
|
||||
GLOBAL_LIST_BOILERPLATE(all_portals, /obj/effect/portal)
|
||||
|
||||
/obj/effect/portal
|
||||
name = "portal"
|
||||
desc = "Looks unstable. Best to test it with the clown."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "portal"
|
||||
density = TRUE
|
||||
unacidable = TRUE//Can't destroy energy portals.
|
||||
var/failchance = 5
|
||||
var/obj/item/target = null
|
||||
var/creator = null
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/portal/Bumped(mob/M as mob|obj)
|
||||
if(istype(M,/mob) && !(istype(M,/mob/living)))
|
||||
return //do not send ghosts, zshadows, ai eyes, etc
|
||||
spawn(0)
|
||||
src.teleport(M)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/effect/portal/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
if(istype(AM,/mob) && !(istype(AM,/mob/living)))
|
||||
return //do not send ghosts, zshadows, ai eyes, etc
|
||||
spawn(0)
|
||||
src.teleport(AM)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/effect/portal/attack_hand(mob/user as mob)
|
||||
if(istype(user) && !(istype(user,/mob/living)))
|
||||
return //do not send ghosts, zshadows, ai eyes, etc
|
||||
spawn(0)
|
||||
src.teleport(user)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/effect/portal/Initialize()
|
||||
. = ..()
|
||||
QDEL_IN(src, 30 SECONDS)
|
||||
|
||||
/obj/effect/portal/proc/teleport(atom/movable/M as mob|obj)
|
||||
if(istype(M, /obj/effect)) //sparks don't teleport
|
||||
return
|
||||
if (M.anchored&&istype(M, /obj/mecha))
|
||||
return
|
||||
if (icon_state == "portal1")
|
||||
return
|
||||
if (!( target ))
|
||||
qdel(src)
|
||||
return
|
||||
if (istype(M, /atom/movable))
|
||||
//VOREStation Addition Start: Prevent taurriding abuse
|
||||
if(istype(M, /mob/living))
|
||||
var/mob/living/L = M
|
||||
if(LAZYLEN(L.buckled_mobs))
|
||||
var/datum/riding/R = L.riding_datum
|
||||
for(var/rider in L.buckled_mobs)
|
||||
R.force_dismount(rider)
|
||||
//VOREStation Addition End: Prevent taurriding abuse
|
||||
if(prob(failchance)) //oh dear a problem, put em in deep space
|
||||
src.icon_state = "portal1"
|
||||
do_teleport(M, locate(rand(5, world.maxx - 5), rand(5, world.maxy -5), 3), 0)
|
||||
else
|
||||
do_teleport(M, target, 1) ///You will appear adjacent to the beacon
|
||||
|
||||
GLOBAL_LIST_BOILERPLATE(all_portals, /obj/effect/portal)
|
||||
|
||||
/obj/effect/portal
|
||||
name = "portal"
|
||||
desc = "Looks unstable. Best to test it with the clown."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "portal"
|
||||
density = TRUE
|
||||
unacidable = TRUE//Can't destroy energy portals.
|
||||
var/failchance = 5
|
||||
var/obj/item/target = null
|
||||
var/creator = null
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/portal/Bumped(mob/M as mob|obj)
|
||||
if(istype(M,/mob) && !(istype(M,/mob/living)))
|
||||
return //do not send ghosts, zshadows, ai eyes, etc
|
||||
spawn(0)
|
||||
src.teleport(M)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/effect/portal/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
if(istype(AM,/mob) && !(istype(AM,/mob/living)))
|
||||
return //do not send ghosts, zshadows, ai eyes, etc
|
||||
spawn(0)
|
||||
src.teleport(AM)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/effect/portal/attack_hand(mob/user as mob)
|
||||
if(istype(user) && !(istype(user,/mob/living)))
|
||||
return //do not send ghosts, zshadows, ai eyes, etc
|
||||
spawn(0)
|
||||
src.teleport(user)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/effect/portal/Initialize()
|
||||
. = ..()
|
||||
QDEL_IN(src, 30 SECONDS)
|
||||
|
||||
/obj/effect/portal/proc/teleport(atom/movable/M as mob|obj)
|
||||
if(istype(M, /obj/effect)) //sparks don't teleport
|
||||
return
|
||||
if (M.anchored&&istype(M, /obj/mecha))
|
||||
return
|
||||
if (icon_state == "portal1")
|
||||
return
|
||||
if (!( target ))
|
||||
qdel(src)
|
||||
return
|
||||
if (istype(M, /atom/movable))
|
||||
//VOREStation Addition Start: Prevent taurriding abuse
|
||||
if(istype(M, /mob/living))
|
||||
var/mob/living/L = M
|
||||
if(LAZYLEN(L.buckled_mobs))
|
||||
var/datum/riding/R = L.riding_datum
|
||||
for(var/rider in L.buckled_mobs)
|
||||
R.force_dismount(rider)
|
||||
//VOREStation Addition End: Prevent taurriding abuse
|
||||
if(prob(failchance)) //oh dear a problem, put em in deep space
|
||||
src.icon_state = "portal1"
|
||||
do_teleport(M, locate(rand(5, world.maxx - 5), rand(5, world.maxy -5), 3), 0)
|
||||
else
|
||||
do_teleport(M, target, 1) ///You will appear adjacent to the beacon
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,143 +1,143 @@
|
||||
/client/proc/spawn_tanktransferbomb()
|
||||
set category = "Debug"
|
||||
set desc = "Spawn a tank transfer valve bomb"
|
||||
set name = "Instant TTV"
|
||||
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/obj/effect/spawner/newbomb/proto = /obj/effect/spawner/newbomb/radio/custom
|
||||
|
||||
var/p = tgui_input_number(usr, "Enter phoron amount (mol):","Phoron", initial(proto.phoron_amt))
|
||||
if(p == null) return
|
||||
|
||||
var/o = tgui_input_number(usr, "Enter oxygen amount (mol):","Oxygen", initial(proto.oxygen_amt))
|
||||
if(o == null) return
|
||||
|
||||
var/c = tgui_input_number(usr, "Enter carbon dioxide amount (mol):","Carbon Dioxide", initial(proto.carbon_amt))
|
||||
if(c == null) return
|
||||
|
||||
new /obj/effect/spawner/newbomb/radio/custom(get_turf(mob), p, o, c)
|
||||
|
||||
/obj/effect/spawner/newbomb
|
||||
name = "TTV bomb"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
|
||||
var/assembly_type = /obj/item/device/assembly/signaler
|
||||
|
||||
//Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
|
||||
var/phoron_amt = 12
|
||||
var/oxygen_amt = 18
|
||||
var/carbon_amt = 0
|
||||
|
||||
/obj/effect/spawner/newbomb/timer
|
||||
name = "TTV bomb - timer"
|
||||
assembly_type = /obj/item/device/assembly/timer
|
||||
|
||||
/obj/effect/spawner/newbomb/timer/syndicate
|
||||
name = "TTV bomb - merc"
|
||||
//High yield bombs. Yes, it is possible to make these with toxins
|
||||
phoron_amt = 18.5
|
||||
oxygen_amt = 28.5
|
||||
|
||||
/obj/effect/spawner/newbomb/proximity
|
||||
name = "TTV bomb - proximity"
|
||||
assembly_type = /obj/item/device/assembly/prox_sensor
|
||||
|
||||
/obj/effect/spawner/newbomb/radio/custom/New(var/newloc, ph, ox, co)
|
||||
if(ph != null) phoron_amt = ph
|
||||
if(ox != null) oxygen_amt = ox
|
||||
if(co != null) carbon_amt = co
|
||||
..()
|
||||
|
||||
/obj/effect/spawner/newbomb/Initialize(newloc)
|
||||
..(newloc)
|
||||
var/obj/item/device/transfer_valve/V = new(src.loc)
|
||||
var/obj/item/weapon/tank/phoron/PT = new(V)
|
||||
var/obj/item/weapon/tank/oxygen/OT = new(V)
|
||||
|
||||
V.tank_one = PT
|
||||
V.tank_two = OT
|
||||
|
||||
PT.master = V
|
||||
OT.master = V
|
||||
|
||||
PT.valve_welded = 1
|
||||
PT.air_contents.gas["phoron"] = phoron_amt
|
||||
PT.air_contents.gas["carbon_dioxide"] = carbon_amt
|
||||
PT.air_contents.total_moles = phoron_amt + carbon_amt
|
||||
PT.air_contents.temperature = PHORON_MINIMUM_BURN_TEMPERATURE+1
|
||||
PT.air_contents.update_values()
|
||||
|
||||
OT.valve_welded = 1
|
||||
OT.air_contents.gas["oxygen"] = oxygen_amt
|
||||
OT.air_contents.total_moles = oxygen_amt
|
||||
OT.air_contents.temperature = PHORON_MINIMUM_BURN_TEMPERATURE+1
|
||||
OT.air_contents.update_values()
|
||||
|
||||
var/obj/item/device/assembly/S = new assembly_type(V)
|
||||
V.attached_device = S
|
||||
|
||||
S.holder = V
|
||||
S.toggle_secure()
|
||||
|
||||
V.update_icon()
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
|
||||
///////////////////////
|
||||
//One Tank Bombs, WOOOOOOO! -Luke
|
||||
///////////////////////
|
||||
|
||||
/obj/effect/spawner/onetankbomb
|
||||
name = "Single-tank bomb"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
|
||||
// var/assembly_type = /obj/item/device/assembly/signaler
|
||||
|
||||
//Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
|
||||
var/phoron_amt = 0
|
||||
var/oxygen_amt = 0
|
||||
|
||||
/obj/effect/spawner/onetankbomb/New(newloc) //just needs an assembly.
|
||||
..(newloc)
|
||||
|
||||
var/type = pick(/obj/item/weapon/tank/phoron/onetankbomb, /obj/item/weapon/tank/oxygen/onetankbomb)
|
||||
new type(src.loc)
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spawner/onetankbomb/full
|
||||
name = "Single-tank bomb"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
|
||||
// var/assembly_type = /obj/item/device/assembly/signaler
|
||||
|
||||
//Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
|
||||
/obj/effect/spawner/onetankbomb/full/New(newloc) //just needs an assembly.
|
||||
..(newloc)
|
||||
|
||||
var/type = pick(/obj/item/weapon/tank/phoron/onetankbomb/full, /obj/item/weapon/tank/oxygen/onetankbomb/full)
|
||||
new type(src.loc)
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spawner/onetankbomb/frag
|
||||
name = "Single-tank bomb"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
|
||||
// var/assembly_type = /obj/item/device/assembly/signaler
|
||||
|
||||
//Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
|
||||
/obj/effect/spawner/onetankbomb/full/New(newloc) //just needs an assembly.
|
||||
..(newloc)
|
||||
|
||||
var/type = pick(/obj/item/weapon/tank/phoron/onetankbomb/full, /obj/item/weapon/tank/oxygen/onetankbomb/full)
|
||||
new type(src.loc)
|
||||
|
||||
qdel(src)
|
||||
|
||||
|
||||
/client/proc/spawn_tanktransferbomb()
|
||||
set category = "Debug"
|
||||
set desc = "Spawn a tank transfer valve bomb"
|
||||
set name = "Instant TTV"
|
||||
|
||||
if(!check_rights(R_SPAWN)) return
|
||||
|
||||
var/obj/effect/spawner/newbomb/proto = /obj/effect/spawner/newbomb/radio/custom
|
||||
|
||||
var/p = tgui_input_number(usr, "Enter phoron amount (mol):","Phoron", initial(proto.phoron_amt))
|
||||
if(p == null) return
|
||||
|
||||
var/o = tgui_input_number(usr, "Enter oxygen amount (mol):","Oxygen", initial(proto.oxygen_amt))
|
||||
if(o == null) return
|
||||
|
||||
var/c = tgui_input_number(usr, "Enter carbon dioxide amount (mol):","Carbon Dioxide", initial(proto.carbon_amt))
|
||||
if(c == null) return
|
||||
|
||||
new /obj/effect/spawner/newbomb/radio/custom(get_turf(mob), p, o, c)
|
||||
|
||||
/obj/effect/spawner/newbomb
|
||||
name = "TTV bomb"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
|
||||
var/assembly_type = /obj/item/device/assembly/signaler
|
||||
|
||||
//Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
|
||||
var/phoron_amt = 12
|
||||
var/oxygen_amt = 18
|
||||
var/carbon_amt = 0
|
||||
|
||||
/obj/effect/spawner/newbomb/timer
|
||||
name = "TTV bomb - timer"
|
||||
assembly_type = /obj/item/device/assembly/timer
|
||||
|
||||
/obj/effect/spawner/newbomb/timer/syndicate
|
||||
name = "TTV bomb - merc"
|
||||
//High yield bombs. Yes, it is possible to make these with toxins
|
||||
phoron_amt = 18.5
|
||||
oxygen_amt = 28.5
|
||||
|
||||
/obj/effect/spawner/newbomb/proximity
|
||||
name = "TTV bomb - proximity"
|
||||
assembly_type = /obj/item/device/assembly/prox_sensor
|
||||
|
||||
/obj/effect/spawner/newbomb/radio/custom/New(var/newloc, ph, ox, co)
|
||||
if(ph != null) phoron_amt = ph
|
||||
if(ox != null) oxygen_amt = ox
|
||||
if(co != null) carbon_amt = co
|
||||
..()
|
||||
|
||||
/obj/effect/spawner/newbomb/Initialize(newloc)
|
||||
..(newloc)
|
||||
var/obj/item/device/transfer_valve/V = new(src.loc)
|
||||
var/obj/item/weapon/tank/phoron/PT = new(V)
|
||||
var/obj/item/weapon/tank/oxygen/OT = new(V)
|
||||
|
||||
V.tank_one = PT
|
||||
V.tank_two = OT
|
||||
|
||||
PT.master = V
|
||||
OT.master = V
|
||||
|
||||
PT.valve_welded = 1
|
||||
PT.air_contents.gas["phoron"] = phoron_amt
|
||||
PT.air_contents.gas["carbon_dioxide"] = carbon_amt
|
||||
PT.air_contents.total_moles = phoron_amt + carbon_amt
|
||||
PT.air_contents.temperature = PHORON_MINIMUM_BURN_TEMPERATURE+1
|
||||
PT.air_contents.update_values()
|
||||
|
||||
OT.valve_welded = 1
|
||||
OT.air_contents.gas["oxygen"] = oxygen_amt
|
||||
OT.air_contents.total_moles = oxygen_amt
|
||||
OT.air_contents.temperature = PHORON_MINIMUM_BURN_TEMPERATURE+1
|
||||
OT.air_contents.update_values()
|
||||
|
||||
var/obj/item/device/assembly/S = new assembly_type(V)
|
||||
V.attached_device = S
|
||||
|
||||
S.holder = V
|
||||
S.toggle_secure()
|
||||
|
||||
V.update_icon()
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
|
||||
///////////////////////
|
||||
//One Tank Bombs, WOOOOOOO! -Luke
|
||||
///////////////////////
|
||||
|
||||
/obj/effect/spawner/onetankbomb
|
||||
name = "Single-tank bomb"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
|
||||
// var/assembly_type = /obj/item/device/assembly/signaler
|
||||
|
||||
//Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
|
||||
var/phoron_amt = 0
|
||||
var/oxygen_amt = 0
|
||||
|
||||
/obj/effect/spawner/onetankbomb/New(newloc) //just needs an assembly.
|
||||
..(newloc)
|
||||
|
||||
var/type = pick(/obj/item/weapon/tank/phoron/onetankbomb, /obj/item/weapon/tank/oxygen/onetankbomb)
|
||||
new type(src.loc)
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spawner/onetankbomb/full
|
||||
name = "Single-tank bomb"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
|
||||
// var/assembly_type = /obj/item/device/assembly/signaler
|
||||
|
||||
//Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
|
||||
/obj/effect/spawner/onetankbomb/full/New(newloc) //just needs an assembly.
|
||||
..(newloc)
|
||||
|
||||
var/type = pick(/obj/item/weapon/tank/phoron/onetankbomb/full, /obj/item/weapon/tank/oxygen/onetankbomb/full)
|
||||
new type(src.loc)
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spawner/onetankbomb/frag
|
||||
name = "Single-tank bomb"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
icon_state = "x"
|
||||
|
||||
// var/assembly_type = /obj/item/device/assembly/signaler
|
||||
|
||||
//Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
|
||||
/obj/effect/spawner/onetankbomb/full/New(newloc) //just needs an assembly.
|
||||
..(newloc)
|
||||
|
||||
var/type = pick(/obj/item/weapon/tank/phoron/onetankbomb/full, /obj/item/weapon/tank/oxygen/onetankbomb/full)
|
||||
new type(src.loc)
|
||||
|
||||
qdel(src)
|
||||
|
||||
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/obj/effect/gibspawner/generic
|
||||
gibtypes = list(/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/core)
|
||||
gibamounts = list(2,2,1)
|
||||
|
||||
/obj/effect/gibspawner/generic/New()
|
||||
gibdirections = list(list(WEST, NORTHWEST, SOUTHWEST, NORTH),list(EAST, NORTHEAST, SOUTHEAST, SOUTH), list())
|
||||
..()
|
||||
|
||||
/obj/effect/gibspawner/human
|
||||
gibtypes = list(/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/down,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/core)
|
||||
gibamounts = list(1,1,1,1,1,1,1)
|
||||
|
||||
/obj/effect/gibspawner/human/New()
|
||||
gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs, list())
|
||||
gibamounts[6] = pick(0,1,2)
|
||||
..()
|
||||
|
||||
/obj/effect/gibspawner/robot
|
||||
sparks = 1
|
||||
gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/robot/up,/obj/effect/decal/cleanable/blood/gibs/robot/down,/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/gibs/robot/limb)
|
||||
gibamounts = list(1,1,1,1,1,1)
|
||||
|
||||
/obj/effect/gibspawner/robot/New()
|
||||
gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs)
|
||||
gibamounts[6] = pick(0,1,2)
|
||||
/obj/effect/gibspawner/generic
|
||||
gibtypes = list(/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/core)
|
||||
gibamounts = list(2,2,1)
|
||||
|
||||
/obj/effect/gibspawner/generic/New()
|
||||
gibdirections = list(list(WEST, NORTHWEST, SOUTHWEST, NORTH),list(EAST, NORTHEAST, SOUTHEAST, SOUTH), list())
|
||||
..()
|
||||
|
||||
/obj/effect/gibspawner/human
|
||||
gibtypes = list(/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/down,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs,/obj/effect/decal/cleanable/blood/gibs/core)
|
||||
gibamounts = list(1,1,1,1,1,1,1)
|
||||
|
||||
/obj/effect/gibspawner/human/New()
|
||||
gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs, list())
|
||||
gibamounts[6] = pick(0,1,2)
|
||||
..()
|
||||
|
||||
/obj/effect/gibspawner/robot
|
||||
sparks = 1
|
||||
gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/robot/up,/obj/effect/decal/cleanable/blood/gibs/robot/down,/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/gibs/robot,/obj/effect/decal/cleanable/blood/gibs/robot/limb)
|
||||
gibamounts = list(1,1,1,1,1,1)
|
||||
|
||||
/obj/effect/gibspawner/robot/New()
|
||||
gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs)
|
||||
gibamounts[6] = pick(0,1,2)
|
||||
..()
|
||||
@@ -1,324 +1,324 @@
|
||||
//generic procs copied from obj/effect/alien
|
||||
/obj/effect/spider
|
||||
name = "web"
|
||||
desc = "it's stringy and sticky"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
var/health = 15
|
||||
|
||||
//similar to weeds, but only barfed out by nurses manually
|
||||
/obj/effect/spider/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
qdel(src)
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
qdel(src)
|
||||
if(3.0)
|
||||
if (prob(5))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/effect/spider/attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
user.setClickCooldown(user.get_attack_speed(W))
|
||||
|
||||
if(LAZYLEN(W.attack_verb))
|
||||
visible_message("<span class='warning'>\The [src] has been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>\The [src] has been attacked with \the [W][(user ? " by [user]." : ".")]</span>")
|
||||
|
||||
var/damage = W.force / 4.0
|
||||
|
||||
if(W.has_tool_quality(TOOL_WELDER))
|
||||
var/obj/item/weapon/weldingtool/WT = W.get_welder()
|
||||
|
||||
if(WT.remove_fuel(0, user))
|
||||
damage = 15
|
||||
playsound(src, W.usesound, 100, 1)
|
||||
|
||||
health -= damage
|
||||
healthcheck()
|
||||
|
||||
/obj/effect/spider/spiderling/attack_hand(mob/living/user)
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
user.do_attack_animation(src)
|
||||
if(prob(20))
|
||||
visible_message("<span class='warning'>\The [user] tries to stomp on \the [src], but misses!</span>")
|
||||
var/list/nearby = oview(2, src)
|
||||
if(length(nearby))
|
||||
walk_to(src, pick(nearby), 2)
|
||||
return
|
||||
visible_message("<span class='warning'>\The [user] stomps \the [src] dead!</span>")
|
||||
die()
|
||||
|
||||
/obj/effect/spider/bullet_act(var/obj/item/projectile/Proj)
|
||||
..()
|
||||
health -= Proj.get_structure_damage()
|
||||
healthcheck()
|
||||
|
||||
/obj/effect/spider/proc/die()
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spider/proc/healthcheck()
|
||||
if(health <= 0)
|
||||
die()
|
||||
|
||||
/obj/effect/spider/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(exposed_temperature > 300 + T0C)
|
||||
health -= 5
|
||||
healthcheck()
|
||||
|
||||
/obj/effect/spider/stickyweb
|
||||
icon_state = "stickyweb1"
|
||||
|
||||
/obj/effect/spider/stickyweb/Initialize()
|
||||
if(prob(50))
|
||||
icon_state = "stickyweb2"
|
||||
return ..()
|
||||
|
||||
/obj/effect/spider/stickyweb/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /mob/living/simple_mob/animal/giant_spider))
|
||||
return TRUE
|
||||
else if(istype(mover, /mob/living))
|
||||
if(prob(50))
|
||||
to_chat(mover, span("warning", "You get stuck in \the [src] for a moment."))
|
||||
return FALSE
|
||||
else if(istype(mover, /obj/item/projectile))
|
||||
return prob(30)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/spider/eggcluster
|
||||
name = "egg cluster"
|
||||
desc = "They seem to pulse slightly with an inner life"
|
||||
icon_state = "eggs"
|
||||
var/amount_grown = 0
|
||||
var/spiders_min = 6
|
||||
var/spiders_max = 24
|
||||
var/spider_type = /obj/effect/spider/spiderling
|
||||
var/faction = "spiders"
|
||||
|
||||
/obj/effect/spider/eggcluster/Initialize()
|
||||
pixel_x = rand(3,-3)
|
||||
pixel_y = rand(3,-3)
|
||||
START_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/spider/eggcluster/New(var/location, var/atom/parent)
|
||||
get_light_and_color(parent)
|
||||
..()
|
||||
|
||||
/obj/effect/spider/eggcluster/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
if(istype(loc, /obj/item/organ/external))
|
||||
var/obj/item/organ/external/O = loc
|
||||
O.implants -= src
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/effect/spider/eggcluster/process()
|
||||
amount_grown += rand(0,2)
|
||||
if(amount_grown >= 100)
|
||||
var/num = rand(spiders_min, spiders_max)
|
||||
var/obj/item/organ/external/O = null
|
||||
if(istype(loc, /obj/item/organ/external))
|
||||
O = loc
|
||||
|
||||
for(var/i=0, i<num, i++)
|
||||
var/obj/effect/spider/spiderling/spiderling = new spider_type(src.loc, src)
|
||||
if(O)
|
||||
O.implants += spiderling
|
||||
spiderling.faction = faction
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spider/eggcluster/small
|
||||
spiders_min = 1
|
||||
spiders_max = 3
|
||||
|
||||
/obj/effect/spider/eggcluster/small/frost
|
||||
spider_type = /obj/effect/spider/spiderling/frost
|
||||
|
||||
/obj/effect/spider/eggcluster/royal
|
||||
spiders_min = 2
|
||||
spiders_max = 5
|
||||
spider_type = /obj/effect/spider/spiderling/varied
|
||||
|
||||
/obj/effect/spider/spiderling
|
||||
name = "spiderling"
|
||||
desc = "It never stays still for long."
|
||||
icon_state = "spiderling"
|
||||
anchored = FALSE
|
||||
layer = HIDING_LAYER
|
||||
health = 3
|
||||
var/last_itch = 0
|
||||
var/amount_grown = 0
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/entry_vent
|
||||
var/travelling_in_vent = 0
|
||||
var/list/grow_as = list(/mob/living/simple_mob/animal/giant_spider, /mob/living/simple_mob/animal/giant_spider/hunter)
|
||||
var/faction = "spiders"
|
||||
|
||||
var/stunted = FALSE
|
||||
|
||||
/obj/effect/spider/spiderling/frost
|
||||
grow_as = list(/mob/living/simple_mob/animal/giant_spider/frost)
|
||||
|
||||
/obj/effect/spider/spiderling/varied
|
||||
grow_as = list(/mob/living/simple_mob/animal/giant_spider, /mob/living/simple_mob/animal/giant_spider/nurse, /mob/living/simple_mob/animal/giant_spider/hunter,
|
||||
/mob/living/simple_mob/animal/giant_spider/frost, /mob/living/simple_mob/animal/giant_spider/electric, /mob/living/simple_mob/animal/giant_spider/lurker,
|
||||
/mob/living/simple_mob/animal/giant_spider/pepper, /mob/living/simple_mob/animal/giant_spider/thermic, /mob/living/simple_mob/animal/giant_spider/tunneler,
|
||||
/mob/living/simple_mob/animal/giant_spider/webslinger, /mob/living/simple_mob/animal/giant_spider/phorogenic, /mob/living/simple_mob/animal/giant_spider/carrier,
|
||||
/mob/living/simple_mob/animal/giant_spider/ion)
|
||||
|
||||
/obj/effect/spider/spiderling/New(var/location, var/atom/parent)
|
||||
pixel_x = rand(6,-6)
|
||||
pixel_y = rand(6,-6)
|
||||
START_PROCESSING(SSobj, src)
|
||||
//50% chance to grow up
|
||||
if(amount_grown != -1 && prob(50))
|
||||
amount_grown = 1
|
||||
get_light_and_color(parent)
|
||||
..()
|
||||
|
||||
/obj/effect/spider/spiderling/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
walk(src, 0) // Because we might have called walk_to, we must stop the walk loop or BYOND keeps an internal reference to us forever.
|
||||
return ..()
|
||||
|
||||
/obj/effect/spider/spiderling/Bump(atom/user)
|
||||
if(istype(user, /obj/structure/table))
|
||||
src.loc = user.loc
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/effect/spider/spiderling/die()
|
||||
visible_message("<span class='alert'>[src] dies!</span>")
|
||||
new /obj/effect/decal/cleanable/spiderling_remains(src.loc)
|
||||
..()
|
||||
|
||||
/obj/effect/spider/spiderling/healthcheck()
|
||||
if(health <= 0)
|
||||
die()
|
||||
|
||||
/obj/effect/spider/spiderling/process()
|
||||
healthcheck()
|
||||
if(travelling_in_vent)
|
||||
if(istype(src.loc, /turf))
|
||||
travelling_in_vent = 0
|
||||
entry_vent = null
|
||||
else if(entry_vent)
|
||||
if(get_dist(src, entry_vent) <= 1)
|
||||
//VOREStation Edit Start
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/exit_vent = get_safe_ventcrawl_target(entry_vent)
|
||||
if(!exit_vent)
|
||||
return
|
||||
spawn(rand(20,60))
|
||||
loc = exit_vent
|
||||
var/travel_time = round(get_dist(loc, exit_vent.loc) / 2)
|
||||
spawn(travel_time)
|
||||
|
||||
if(!exit_vent || exit_vent.welded)
|
||||
loc = entry_vent
|
||||
entry_vent = null
|
||||
return
|
||||
|
||||
if(prob(50))
|
||||
src.visible_message("<span class='notice'>You hear something squeezing through the ventilation ducts.</span>",2)
|
||||
sleep(travel_time)
|
||||
|
||||
if(!exit_vent || exit_vent.welded)
|
||||
loc = entry_vent
|
||||
entry_vent = null
|
||||
return
|
||||
loc = exit_vent.loc
|
||||
entry_vent = null
|
||||
var/area/new_area = get_area(loc)
|
||||
if(new_area)
|
||||
new_area.Entered(src)
|
||||
//VOREStation Edit End
|
||||
//=================
|
||||
|
||||
if(isturf(loc))
|
||||
skitter()
|
||||
|
||||
else if(isorgan(loc))
|
||||
if(amount_grown < 0) amount_grown = 1
|
||||
var/obj/item/organ/external/O = loc
|
||||
if(!O.owner || O.owner.stat == DEAD || amount_grown > 80)
|
||||
O.implants -= src
|
||||
src.loc = O.owner ? O.owner.loc : O.loc
|
||||
src.visible_message("<span class='warning'>\A [src] makes its way out of [O.owner ? "[O.owner]'s [O.name]" : "\the [O]"]!</span>")
|
||||
if(O.owner)
|
||||
O.owner.apply_damage(1, BRUTE, O.organ_tag)
|
||||
else if(prob(1))
|
||||
O.owner.apply_damage(1, TOX, O.organ_tag)
|
||||
if(world.time > last_itch + 30 SECONDS)
|
||||
last_itch = world.time
|
||||
to_chat(O.owner, "<span class='notice'>Your [O.name] itches...</span>")
|
||||
else if(prob(1))
|
||||
src.visible_message("<b>\The [src]</b> skitters.")
|
||||
|
||||
if(amount_grown >= 0)
|
||||
amount_grown += rand(0,2)
|
||||
|
||||
/obj/effect/spider/spiderling/proc/skitter()
|
||||
if(isturf(loc))
|
||||
if(prob(25))
|
||||
var/list/nearby = trange(5, src) - loc
|
||||
if(nearby.len)
|
||||
var/target_atom = pick(nearby)
|
||||
walk_to(src, target_atom, 5)
|
||||
if(prob(25))
|
||||
src.visible_message("<span class='notice'>\The [src] skitters[pick(" away"," around","")].</span>")
|
||||
else if(amount_grown < 75 && prob(5))
|
||||
//vent crawl!
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src))
|
||||
if(!v.welded)
|
||||
entry_vent = v
|
||||
walk_to(src, entry_vent, 5)
|
||||
break
|
||||
if(amount_grown >= 100)
|
||||
var/spawn_type = pick(grow_as)
|
||||
var/mob/living/simple_mob/animal/giant_spider/GS = new spawn_type(src.loc, src)
|
||||
GS.faction = faction
|
||||
if(stunted)
|
||||
spawn(2)
|
||||
GS.make_spiderling()
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spider/spiderling/stunted
|
||||
stunted = TRUE
|
||||
|
||||
grow_as = list(/mob/living/simple_mob/animal/giant_spider, /mob/living/simple_mob/animal/giant_spider/hunter)
|
||||
|
||||
/obj/effect/spider/spiderling/non_growing
|
||||
amount_grown = -1
|
||||
|
||||
/obj/effect/spider/spiderling/princess
|
||||
name = "royal spiderling"
|
||||
desc = "There's a special aura about this one."
|
||||
grow_as = list(/mob/living/simple_mob/animal/giant_spider/nurse/queen)
|
||||
|
||||
/obj/effect/spider/spiderling/princess/New(var/location, var/atom/parent)
|
||||
..()
|
||||
amount_grown = 50
|
||||
|
||||
/obj/effect/decal/cleanable/spiderling_remains
|
||||
name = "spiderling remains"
|
||||
desc = "Green squishy mess."
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "greenshatter"
|
||||
|
||||
/obj/effect/spider/cocoon
|
||||
name = "cocoon"
|
||||
desc = "Something wrapped in silky spider web"
|
||||
icon_state = "cocoon1"
|
||||
health = 60
|
||||
|
||||
/obj/effect/spider/cocoon/New()
|
||||
icon_state = pick("cocoon1","cocoon2","cocoon3")
|
||||
|
||||
/obj/effect/spider/cocoon/Destroy()
|
||||
src.visible_message("<span class='warning'>\The [src] splits open.</span>")
|
||||
for(var/atom/movable/A in contents)
|
||||
A.loc = src.loc
|
||||
return ..()
|
||||
//generic procs copied from obj/effect/alien
|
||||
/obj/effect/spider
|
||||
name = "web"
|
||||
desc = "it's stringy and sticky"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
var/health = 15
|
||||
|
||||
//similar to weeds, but only barfed out by nurses manually
|
||||
/obj/effect/spider/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
qdel(src)
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
qdel(src)
|
||||
if(3.0)
|
||||
if (prob(5))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/effect/spider/attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
user.setClickCooldown(user.get_attack_speed(W))
|
||||
|
||||
if(LAZYLEN(W.attack_verb))
|
||||
visible_message("<span class='warning'>\The [src] has been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>\The [src] has been attacked with \the [W][(user ? " by [user]." : ".")]</span>")
|
||||
|
||||
var/damage = W.force / 4.0
|
||||
|
||||
if(W.has_tool_quality(TOOL_WELDER))
|
||||
var/obj/item/weapon/weldingtool/WT = W.get_welder()
|
||||
|
||||
if(WT.remove_fuel(0, user))
|
||||
damage = 15
|
||||
playsound(src, W.usesound, 100, 1)
|
||||
|
||||
health -= damage
|
||||
healthcheck()
|
||||
|
||||
/obj/effect/spider/spiderling/attack_hand(mob/living/user)
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
user.do_attack_animation(src)
|
||||
if(prob(20))
|
||||
visible_message("<span class='warning'>\The [user] tries to stomp on \the [src], but misses!</span>")
|
||||
var/list/nearby = oview(2, src)
|
||||
if(length(nearby))
|
||||
walk_to(src, pick(nearby), 2)
|
||||
return
|
||||
visible_message("<span class='warning'>\The [user] stomps \the [src] dead!</span>")
|
||||
die()
|
||||
|
||||
/obj/effect/spider/bullet_act(var/obj/item/projectile/Proj)
|
||||
..()
|
||||
health -= Proj.get_structure_damage()
|
||||
healthcheck()
|
||||
|
||||
/obj/effect/spider/proc/die()
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spider/proc/healthcheck()
|
||||
if(health <= 0)
|
||||
die()
|
||||
|
||||
/obj/effect/spider/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(exposed_temperature > 300 + T0C)
|
||||
health -= 5
|
||||
healthcheck()
|
||||
|
||||
/obj/effect/spider/stickyweb
|
||||
icon_state = "stickyweb1"
|
||||
|
||||
/obj/effect/spider/stickyweb/Initialize()
|
||||
if(prob(50))
|
||||
icon_state = "stickyweb2"
|
||||
return ..()
|
||||
|
||||
/obj/effect/spider/stickyweb/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /mob/living/simple_mob/animal/giant_spider))
|
||||
return TRUE
|
||||
else if(istype(mover, /mob/living))
|
||||
if(prob(50))
|
||||
to_chat(mover, span("warning", "You get stuck in \the [src] for a moment."))
|
||||
return FALSE
|
||||
else if(istype(mover, /obj/item/projectile))
|
||||
return prob(30)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/spider/eggcluster
|
||||
name = "egg cluster"
|
||||
desc = "They seem to pulse slightly with an inner life"
|
||||
icon_state = "eggs"
|
||||
var/amount_grown = 0
|
||||
var/spiders_min = 6
|
||||
var/spiders_max = 24
|
||||
var/spider_type = /obj/effect/spider/spiderling
|
||||
var/faction = "spiders"
|
||||
|
||||
/obj/effect/spider/eggcluster/Initialize()
|
||||
pixel_x = rand(3,-3)
|
||||
pixel_y = rand(3,-3)
|
||||
START_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/spider/eggcluster/New(var/location, var/atom/parent)
|
||||
get_light_and_color(parent)
|
||||
..()
|
||||
|
||||
/obj/effect/spider/eggcluster/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
if(istype(loc, /obj/item/organ/external))
|
||||
var/obj/item/organ/external/O = loc
|
||||
O.implants -= src
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/effect/spider/eggcluster/process()
|
||||
amount_grown += rand(0,2)
|
||||
if(amount_grown >= 100)
|
||||
var/num = rand(spiders_min, spiders_max)
|
||||
var/obj/item/organ/external/O = null
|
||||
if(istype(loc, /obj/item/organ/external))
|
||||
O = loc
|
||||
|
||||
for(var/i=0, i<num, i++)
|
||||
var/obj/effect/spider/spiderling/spiderling = new spider_type(src.loc, src)
|
||||
if(O)
|
||||
O.implants += spiderling
|
||||
spiderling.faction = faction
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spider/eggcluster/small
|
||||
spiders_min = 1
|
||||
spiders_max = 3
|
||||
|
||||
/obj/effect/spider/eggcluster/small/frost
|
||||
spider_type = /obj/effect/spider/spiderling/frost
|
||||
|
||||
/obj/effect/spider/eggcluster/royal
|
||||
spiders_min = 2
|
||||
spiders_max = 5
|
||||
spider_type = /obj/effect/spider/spiderling/varied
|
||||
|
||||
/obj/effect/spider/spiderling
|
||||
name = "spiderling"
|
||||
desc = "It never stays still for long."
|
||||
icon_state = "spiderling"
|
||||
anchored = FALSE
|
||||
layer = HIDING_LAYER
|
||||
health = 3
|
||||
var/last_itch = 0
|
||||
var/amount_grown = 0
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/entry_vent
|
||||
var/travelling_in_vent = 0
|
||||
var/list/grow_as = list(/mob/living/simple_mob/animal/giant_spider, /mob/living/simple_mob/animal/giant_spider/hunter)
|
||||
var/faction = "spiders"
|
||||
|
||||
var/stunted = FALSE
|
||||
|
||||
/obj/effect/spider/spiderling/frost
|
||||
grow_as = list(/mob/living/simple_mob/animal/giant_spider/frost)
|
||||
|
||||
/obj/effect/spider/spiderling/varied
|
||||
grow_as = list(/mob/living/simple_mob/animal/giant_spider, /mob/living/simple_mob/animal/giant_spider/nurse, /mob/living/simple_mob/animal/giant_spider/hunter,
|
||||
/mob/living/simple_mob/animal/giant_spider/frost, /mob/living/simple_mob/animal/giant_spider/electric, /mob/living/simple_mob/animal/giant_spider/lurker,
|
||||
/mob/living/simple_mob/animal/giant_spider/pepper, /mob/living/simple_mob/animal/giant_spider/thermic, /mob/living/simple_mob/animal/giant_spider/tunneler,
|
||||
/mob/living/simple_mob/animal/giant_spider/webslinger, /mob/living/simple_mob/animal/giant_spider/phorogenic, /mob/living/simple_mob/animal/giant_spider/carrier,
|
||||
/mob/living/simple_mob/animal/giant_spider/ion)
|
||||
|
||||
/obj/effect/spider/spiderling/New(var/location, var/atom/parent)
|
||||
pixel_x = rand(6,-6)
|
||||
pixel_y = rand(6,-6)
|
||||
START_PROCESSING(SSobj, src)
|
||||
//50% chance to grow up
|
||||
if(amount_grown != -1 && prob(50))
|
||||
amount_grown = 1
|
||||
get_light_and_color(parent)
|
||||
..()
|
||||
|
||||
/obj/effect/spider/spiderling/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
walk(src, 0) // Because we might have called walk_to, we must stop the walk loop or BYOND keeps an internal reference to us forever.
|
||||
return ..()
|
||||
|
||||
/obj/effect/spider/spiderling/Bump(atom/user)
|
||||
if(istype(user, /obj/structure/table))
|
||||
src.loc = user.loc
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/effect/spider/spiderling/die()
|
||||
visible_message("<span class='alert'>[src] dies!</span>")
|
||||
new /obj/effect/decal/cleanable/spiderling_remains(src.loc)
|
||||
..()
|
||||
|
||||
/obj/effect/spider/spiderling/healthcheck()
|
||||
if(health <= 0)
|
||||
die()
|
||||
|
||||
/obj/effect/spider/spiderling/process()
|
||||
healthcheck()
|
||||
if(travelling_in_vent)
|
||||
if(istype(src.loc, /turf))
|
||||
travelling_in_vent = 0
|
||||
entry_vent = null
|
||||
else if(entry_vent)
|
||||
if(get_dist(src, entry_vent) <= 1)
|
||||
//VOREStation Edit Start
|
||||
var/obj/machinery/atmospherics/unary/vent_pump/exit_vent = get_safe_ventcrawl_target(entry_vent)
|
||||
if(!exit_vent)
|
||||
return
|
||||
spawn(rand(20,60))
|
||||
loc = exit_vent
|
||||
var/travel_time = round(get_dist(loc, exit_vent.loc) / 2)
|
||||
spawn(travel_time)
|
||||
|
||||
if(!exit_vent || exit_vent.welded)
|
||||
loc = entry_vent
|
||||
entry_vent = null
|
||||
return
|
||||
|
||||
if(prob(50))
|
||||
src.visible_message("<span class='notice'>You hear something squeezing through the ventilation ducts.</span>",2)
|
||||
sleep(travel_time)
|
||||
|
||||
if(!exit_vent || exit_vent.welded)
|
||||
loc = entry_vent
|
||||
entry_vent = null
|
||||
return
|
||||
loc = exit_vent.loc
|
||||
entry_vent = null
|
||||
var/area/new_area = get_area(loc)
|
||||
if(new_area)
|
||||
new_area.Entered(src)
|
||||
//VOREStation Edit End
|
||||
//=================
|
||||
|
||||
if(isturf(loc))
|
||||
skitter()
|
||||
|
||||
else if(isorgan(loc))
|
||||
if(amount_grown < 0) amount_grown = 1
|
||||
var/obj/item/organ/external/O = loc
|
||||
if(!O.owner || O.owner.stat == DEAD || amount_grown > 80)
|
||||
O.implants -= src
|
||||
src.loc = O.owner ? O.owner.loc : O.loc
|
||||
src.visible_message("<span class='warning'>\A [src] makes its way out of [O.owner ? "[O.owner]'s [O.name]" : "\the [O]"]!</span>")
|
||||
if(O.owner)
|
||||
O.owner.apply_damage(1, BRUTE, O.organ_tag)
|
||||
else if(prob(1))
|
||||
O.owner.apply_damage(1, TOX, O.organ_tag)
|
||||
if(world.time > last_itch + 30 SECONDS)
|
||||
last_itch = world.time
|
||||
to_chat(O.owner, "<span class='notice'>Your [O.name] itches...</span>")
|
||||
else if(prob(1))
|
||||
src.visible_message("<b>\The [src]</b> skitters.")
|
||||
|
||||
if(amount_grown >= 0)
|
||||
amount_grown += rand(0,2)
|
||||
|
||||
/obj/effect/spider/spiderling/proc/skitter()
|
||||
if(isturf(loc))
|
||||
if(prob(25))
|
||||
var/list/nearby = trange(5, src) - loc
|
||||
if(nearby.len)
|
||||
var/target_atom = pick(nearby)
|
||||
walk_to(src, target_atom, 5)
|
||||
if(prob(25))
|
||||
src.visible_message("<span class='notice'>\The [src] skitters[pick(" away"," around","")].</span>")
|
||||
else if(amount_grown < 75 && prob(5))
|
||||
//vent crawl!
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src))
|
||||
if(!v.welded)
|
||||
entry_vent = v
|
||||
walk_to(src, entry_vent, 5)
|
||||
break
|
||||
if(amount_grown >= 100)
|
||||
var/spawn_type = pick(grow_as)
|
||||
var/mob/living/simple_mob/animal/giant_spider/GS = new spawn_type(src.loc, src)
|
||||
GS.faction = faction
|
||||
if(stunted)
|
||||
spawn(2)
|
||||
GS.make_spiderling()
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/spider/spiderling/stunted
|
||||
stunted = TRUE
|
||||
|
||||
grow_as = list(/mob/living/simple_mob/animal/giant_spider, /mob/living/simple_mob/animal/giant_spider/hunter)
|
||||
|
||||
/obj/effect/spider/spiderling/non_growing
|
||||
amount_grown = -1
|
||||
|
||||
/obj/effect/spider/spiderling/princess
|
||||
name = "royal spiderling"
|
||||
desc = "There's a special aura about this one."
|
||||
grow_as = list(/mob/living/simple_mob/animal/giant_spider/nurse/queen)
|
||||
|
||||
/obj/effect/spider/spiderling/princess/New(var/location, var/atom/parent)
|
||||
..()
|
||||
amount_grown = 50
|
||||
|
||||
/obj/effect/decal/cleanable/spiderling_remains
|
||||
name = "spiderling remains"
|
||||
desc = "Green squishy mess."
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "greenshatter"
|
||||
|
||||
/obj/effect/spider/cocoon
|
||||
name = "cocoon"
|
||||
desc = "Something wrapped in silky spider web"
|
||||
icon_state = "cocoon1"
|
||||
health = 60
|
||||
|
||||
/obj/effect/spider/cocoon/New()
|
||||
icon_state = pick("cocoon1","cocoon2","cocoon3")
|
||||
|
||||
/obj/effect/spider/cocoon/Destroy()
|
||||
src.visible_message("<span class='warning'>\The [src] splits open.</span>")
|
||||
for(var/atom/movable/A in contents)
|
||||
A.loc = src.loc
|
||||
return ..()
|
||||
|
||||
@@ -1,74 +1,74 @@
|
||||
// Uncomment this define to check for possible lengthy processing of emp_act()s.
|
||||
// If emp_act() takes more than defined deciseconds (1/10 seconds) an admin message and log is created.
|
||||
// I do not recommend having this uncommented on main server, it probably causes a bit more lag, espicially with larger EMPs.
|
||||
|
||||
// #define EMPDEBUG 10
|
||||
|
||||
/proc/empulse(turf/epicenter, first_range, second_range, third_range, fourth_range, log=0)
|
||||
if(!epicenter) return
|
||||
|
||||
if(!istype(epicenter, /turf))
|
||||
epicenter = get_turf(epicenter.loc)
|
||||
|
||||
if(log)
|
||||
message_admins("EMP with size ([first_range], [second_range], [third_range], [fourth_range]) in area [epicenter.loc.name] ")
|
||||
log_game("EMP with size ([first_range], [second_range], [third_range], [fourth_range]) in area [epicenter.loc.name] ")
|
||||
|
||||
if(first_range > 1)
|
||||
var/obj/effect/overlay/pulse = new /obj/effect/overlay(epicenter)
|
||||
pulse.icon = 'icons/effects/effects.dmi'
|
||||
pulse.icon_state = "emppulse"
|
||||
pulse.name = "emp pulse"
|
||||
pulse.anchored = TRUE
|
||||
spawn(20)
|
||||
qdel(pulse)
|
||||
|
||||
if(first_range > second_range)
|
||||
second_range = first_range
|
||||
if(second_range > third_range)
|
||||
third_range = second_range
|
||||
if(third_range > fourth_range)
|
||||
fourth_range = third_range
|
||||
|
||||
for(var/mob/M in range(first_range, epicenter))
|
||||
M << 'sound/effects/EMPulse.ogg'
|
||||
|
||||
for(var/atom/T in range(fourth_range, epicenter))
|
||||
#ifdef EMPDEBUG
|
||||
var/time = world.timeofday
|
||||
#endif
|
||||
var/distance = get_dist(epicenter, T)
|
||||
if(distance < 0)
|
||||
distance = 0
|
||||
//Worst effects, really hurts
|
||||
if(distance < first_range)
|
||||
T.emp_act(1)
|
||||
else if(distance == first_range)
|
||||
if(prob(50))
|
||||
T.emp_act(1)
|
||||
else
|
||||
T.emp_act(2)
|
||||
//Slightly less painful
|
||||
else if(distance <= second_range)
|
||||
T.emp_act(2)
|
||||
else if(distance == second_range)
|
||||
if(prob(50))
|
||||
T.emp_act(2)
|
||||
else
|
||||
T.emp_act(3)
|
||||
//Even less slightly less painful
|
||||
else if(distance <= third_range)
|
||||
T.emp_act(3)
|
||||
else if(distance == third_range)
|
||||
if(prob(50))
|
||||
T.emp_act(2)
|
||||
else
|
||||
T.emp_act(3)
|
||||
//This should be more or less harmless
|
||||
else if(distance <= fourth_range)
|
||||
T.emp_act(4)
|
||||
#ifdef EMPDEBUG
|
||||
if((world.timeofday - time) >= EMPDEBUG)
|
||||
log_and_message_admins("EMPDEBUG: [T.name] - [T.type] - took [world.timeofday - time]ds to process emp_act()!")
|
||||
#endif
|
||||
// Uncomment this define to check for possible lengthy processing of emp_act()s.
|
||||
// If emp_act() takes more than defined deciseconds (1/10 seconds) an admin message and log is created.
|
||||
// I do not recommend having this uncommented on main server, it probably causes a bit more lag, espicially with larger EMPs.
|
||||
|
||||
// #define EMPDEBUG 10
|
||||
|
||||
/proc/empulse(turf/epicenter, first_range, second_range, third_range, fourth_range, log=0)
|
||||
if(!epicenter) return
|
||||
|
||||
if(!istype(epicenter, /turf))
|
||||
epicenter = get_turf(epicenter.loc)
|
||||
|
||||
if(log)
|
||||
message_admins("EMP with size ([first_range], [second_range], [third_range], [fourth_range]) in area [epicenter.loc.name] ")
|
||||
log_game("EMP with size ([first_range], [second_range], [third_range], [fourth_range]) in area [epicenter.loc.name] ")
|
||||
|
||||
if(first_range > 1)
|
||||
var/obj/effect/overlay/pulse = new /obj/effect/overlay(epicenter)
|
||||
pulse.icon = 'icons/effects/effects.dmi'
|
||||
pulse.icon_state = "emppulse"
|
||||
pulse.name = "emp pulse"
|
||||
pulse.anchored = TRUE
|
||||
spawn(20)
|
||||
qdel(pulse)
|
||||
|
||||
if(first_range > second_range)
|
||||
second_range = first_range
|
||||
if(second_range > third_range)
|
||||
third_range = second_range
|
||||
if(third_range > fourth_range)
|
||||
fourth_range = third_range
|
||||
|
||||
for(var/mob/M in range(first_range, epicenter))
|
||||
M << 'sound/effects/EMPulse.ogg'
|
||||
|
||||
for(var/atom/T in range(fourth_range, epicenter))
|
||||
#ifdef EMPDEBUG
|
||||
var/time = world.timeofday
|
||||
#endif
|
||||
var/distance = get_dist(epicenter, T)
|
||||
if(distance < 0)
|
||||
distance = 0
|
||||
//Worst effects, really hurts
|
||||
if(distance < first_range)
|
||||
T.emp_act(1)
|
||||
else if(distance == first_range)
|
||||
if(prob(50))
|
||||
T.emp_act(1)
|
||||
else
|
||||
T.emp_act(2)
|
||||
//Slightly less painful
|
||||
else if(distance <= second_range)
|
||||
T.emp_act(2)
|
||||
else if(distance == second_range)
|
||||
if(prob(50))
|
||||
T.emp_act(2)
|
||||
else
|
||||
T.emp_act(3)
|
||||
//Even less slightly less painful
|
||||
else if(distance <= third_range)
|
||||
T.emp_act(3)
|
||||
else if(distance == third_range)
|
||||
if(prob(50))
|
||||
T.emp_act(2)
|
||||
else
|
||||
T.emp_act(3)
|
||||
//This should be more or less harmless
|
||||
else if(distance <= fourth_range)
|
||||
T.emp_act(4)
|
||||
#ifdef EMPDEBUG
|
||||
if((world.timeofday - time) >= EMPDEBUG)
|
||||
log_and_message_admins("EMPDEBUG: [T.name] - [T.type] - took [world.timeofday - time]ds to process emp_act()!")
|
||||
#endif
|
||||
return 1
|
||||
+112
-112
@@ -1,112 +1,112 @@
|
||||
//TODO: Flash range does nothing currently
|
||||
|
||||
/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = UP|DOWN, shaped)
|
||||
var/multi_z_scalar = config.multi_z_explosion_scalar
|
||||
spawn(0)
|
||||
var/start = world.timeofday
|
||||
epicenter = get_turf(epicenter)
|
||||
if(!epicenter) return
|
||||
|
||||
// Handles recursive propagation of explosions.
|
||||
if(z_transfer && multi_z_scalar)
|
||||
var/adj_dev = max(0, (multi_z_scalar * devastation_range) - (shaped ? 2 : 0) )
|
||||
var/adj_heavy = max(0, (multi_z_scalar * heavy_impact_range) - (shaped ? 2 : 0) )
|
||||
var/adj_light = max(0, (multi_z_scalar * light_impact_range) - (shaped ? 2 : 0) )
|
||||
var/adj_flash = max(0, (multi_z_scalar * flash_range) - (shaped ? 2 : 0) )
|
||||
|
||||
|
||||
if(adj_dev > 0 || adj_heavy > 0)
|
||||
if(HasAbove(epicenter.z) && z_transfer & UP)
|
||||
explosion(GetAbove(epicenter), round(adj_dev), round(adj_heavy), round(adj_light), round(adj_flash), 0, UP, shaped)
|
||||
if(HasBelow(epicenter.z) && z_transfer & DOWN)
|
||||
explosion(GetBelow(epicenter), round(adj_dev), round(adj_heavy), round(adj_light), round(adj_flash), 0, DOWN, shaped)
|
||||
|
||||
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flash_range)
|
||||
|
||||
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
|
||||
// Stereo users will also hear the direction of the explosion!
|
||||
// Calculate far explosion sound range. Only allow the sound effect for heavy/devastating explosions.
|
||||
// 3/7/14 will calculate to 80 + 35
|
||||
var/far_dist = 0
|
||||
far_dist += heavy_impact_range * 5
|
||||
far_dist += devastation_range * 20
|
||||
var/frequency = get_rand_frequency()
|
||||
for(var/mob/M in player_list)
|
||||
if(M.z == epicenter.z)
|
||||
var/turf/M_turf = get_turf(M)
|
||||
var/dist = get_dist(M_turf, epicenter)
|
||||
// If inside the blast radius + world.view - 2
|
||||
if(dist <= round(max_range + world.view - 2, 1))
|
||||
M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound
|
||||
else if(dist <= far_dist)
|
||||
var/far_volume = CLAMP(far_dist, 30, 50) // Volume is based on explosion size and dist
|
||||
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
|
||||
M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
|
||||
|
||||
var/close = range(world.view+round(devastation_range,1), epicenter)
|
||||
// to all distanced mobs play a different sound
|
||||
for(var/mob/M in player_list)
|
||||
if(M.z == epicenter.z)
|
||||
if(!(M in close))
|
||||
// check if the mob can hear
|
||||
if(M.ear_deaf <= 0 || !M.ear_deaf)
|
||||
if(!istype(M.loc,/turf/space))
|
||||
M << 'sound/effects/explosionfar.ogg'
|
||||
|
||||
if(adminlog)
|
||||
message_admins("Explosion with [shaped ? "shaped" : "non-shaped"] size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (<A HREF='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[epicenter.x];Y=[epicenter.y];Z=[epicenter.z]'>JMP</a>)")
|
||||
log_game("Explosion with [shaped ? "shaped" : "non-shaped"] size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ")
|
||||
|
||||
var/approximate_intensity = (devastation_range * 3) + (heavy_impact_range * 2) + light_impact_range
|
||||
var/powernet_rebuild_was_deferred_already = defer_powernet_rebuild
|
||||
// Large enough explosion. For performance reasons, powernets will be rebuilt manually
|
||||
if(!defer_powernet_rebuild && (approximate_intensity > 25))
|
||||
defer_powernet_rebuild = 1
|
||||
|
||||
if(heavy_impact_range > 1)
|
||||
var/datum/effect/system/explosion/E = new/datum/effect/system/explosion()
|
||||
E.set_up(epicenter)
|
||||
E.start()
|
||||
|
||||
var/x0 = epicenter.x
|
||||
var/y0 = epicenter.y
|
||||
var/z0 = epicenter.z
|
||||
if(config.use_recursive_explosions)
|
||||
var/power = devastation_range * 2 + heavy_impact_range + light_impact_range //The ranges add up, ie light 14 includes both heavy 7 and devestation 3. So this calculation means devestation counts for 4, heavy for 2 and light for 1 power, giving us a cap of 27 power.
|
||||
explosion_rec(epicenter, power, shaped)
|
||||
else
|
||||
for(var/turf/T in trange(max_range, epicenter))
|
||||
var/dist = sqrt((T.x - x0)**2 + (T.y - y0)**2)
|
||||
|
||||
if(dist < devastation_range) dist = 1
|
||||
else if(dist < heavy_impact_range) dist = 2
|
||||
else if(dist < light_impact_range) dist = 3
|
||||
else continue
|
||||
|
||||
if(!T)
|
||||
T = locate(x0,y0,z0)
|
||||
for(var/atom_movable in T.contents) //bypass type checking since only atom/movable can be contained by turfs anyway
|
||||
var/atom/movable/AM = atom_movable
|
||||
if(AM && AM.simulated) AM.ex_act(dist)
|
||||
|
||||
T.ex_act(dist)
|
||||
|
||||
var/took = (world.timeofday-start)/10
|
||||
//You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
|
||||
if(Debug2) to_world_log("## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds.")
|
||||
|
||||
//Machines which report explosions.
|
||||
for(var/i,i<=doppler_arrays.len,i++)
|
||||
var/obj/machinery/doppler_array/Array = doppler_arrays[i]
|
||||
if(Array)
|
||||
Array.sense_explosion(x0,y0,z0,devastation_range,heavy_impact_range,light_impact_range,took)
|
||||
sleep(8)
|
||||
|
||||
if(!powernet_rebuild_was_deferred_already && defer_powernet_rebuild)
|
||||
SSmachines.makepowernets()
|
||||
defer_powernet_rebuild = 0
|
||||
return 1
|
||||
|
||||
/proc/secondaryexplosion(turf/epicenter, range)
|
||||
for(var/turf/tile in range(range, epicenter))
|
||||
tile.ex_act(2)
|
||||
//TODO: Flash range does nothing currently
|
||||
|
||||
/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, z_transfer = UP|DOWN, shaped)
|
||||
var/multi_z_scalar = config.multi_z_explosion_scalar
|
||||
spawn(0)
|
||||
var/start = world.timeofday
|
||||
epicenter = get_turf(epicenter)
|
||||
if(!epicenter) return
|
||||
|
||||
// Handles recursive propagation of explosions.
|
||||
if(z_transfer && multi_z_scalar)
|
||||
var/adj_dev = max(0, (multi_z_scalar * devastation_range) - (shaped ? 2 : 0) )
|
||||
var/adj_heavy = max(0, (multi_z_scalar * heavy_impact_range) - (shaped ? 2 : 0) )
|
||||
var/adj_light = max(0, (multi_z_scalar * light_impact_range) - (shaped ? 2 : 0) )
|
||||
var/adj_flash = max(0, (multi_z_scalar * flash_range) - (shaped ? 2 : 0) )
|
||||
|
||||
|
||||
if(adj_dev > 0 || adj_heavy > 0)
|
||||
if(HasAbove(epicenter.z) && z_transfer & UP)
|
||||
explosion(GetAbove(epicenter), round(adj_dev), round(adj_heavy), round(adj_light), round(adj_flash), 0, UP, shaped)
|
||||
if(HasBelow(epicenter.z) && z_transfer & DOWN)
|
||||
explosion(GetBelow(epicenter), round(adj_dev), round(adj_heavy), round(adj_light), round(adj_flash), 0, DOWN, shaped)
|
||||
|
||||
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flash_range)
|
||||
|
||||
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
|
||||
// Stereo users will also hear the direction of the explosion!
|
||||
// Calculate far explosion sound range. Only allow the sound effect for heavy/devastating explosions.
|
||||
// 3/7/14 will calculate to 80 + 35
|
||||
var/far_dist = 0
|
||||
far_dist += heavy_impact_range * 5
|
||||
far_dist += devastation_range * 20
|
||||
var/frequency = get_rand_frequency()
|
||||
for(var/mob/M in player_list)
|
||||
if(M.z == epicenter.z)
|
||||
var/turf/M_turf = get_turf(M)
|
||||
var/dist = get_dist(M_turf, epicenter)
|
||||
// If inside the blast radius + world.view - 2
|
||||
if(dist <= round(max_range + world.view - 2, 1))
|
||||
M.playsound_local(epicenter, get_sfx("explosion"), 100, 1, frequency, falloff = 5) // get_sfx() is so that everyone gets the same sound
|
||||
else if(dist <= far_dist)
|
||||
var/far_volume = CLAMP(far_dist, 30, 50) // Volume is based on explosion size and dist
|
||||
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
|
||||
M.playsound_local(epicenter, 'sound/effects/explosionfar.ogg', far_volume, 1, frequency, falloff = 5)
|
||||
|
||||
var/close = range(world.view+round(devastation_range,1), epicenter)
|
||||
// to all distanced mobs play a different sound
|
||||
for(var/mob/M in player_list)
|
||||
if(M.z == epicenter.z)
|
||||
if(!(M in close))
|
||||
// check if the mob can hear
|
||||
if(M.ear_deaf <= 0 || !M.ear_deaf)
|
||||
if(!istype(M.loc,/turf/space))
|
||||
M << 'sound/effects/explosionfar.ogg'
|
||||
|
||||
if(adminlog)
|
||||
message_admins("Explosion with [shaped ? "shaped" : "non-shaped"] size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (<A HREF='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[epicenter.x];Y=[epicenter.y];Z=[epicenter.z]'>JMP</a>)")
|
||||
log_game("Explosion with [shaped ? "shaped" : "non-shaped"] size ([devastation_range], [heavy_impact_range], [light_impact_range]) in area [epicenter.loc.name] ")
|
||||
|
||||
var/approximate_intensity = (devastation_range * 3) + (heavy_impact_range * 2) + light_impact_range
|
||||
var/powernet_rebuild_was_deferred_already = defer_powernet_rebuild
|
||||
// Large enough explosion. For performance reasons, powernets will be rebuilt manually
|
||||
if(!defer_powernet_rebuild && (approximate_intensity > 25))
|
||||
defer_powernet_rebuild = 1
|
||||
|
||||
if(heavy_impact_range > 1)
|
||||
var/datum/effect/system/explosion/E = new/datum/effect/system/explosion()
|
||||
E.set_up(epicenter)
|
||||
E.start()
|
||||
|
||||
var/x0 = epicenter.x
|
||||
var/y0 = epicenter.y
|
||||
var/z0 = epicenter.z
|
||||
if(config.use_recursive_explosions)
|
||||
var/power = devastation_range * 2 + heavy_impact_range + light_impact_range //The ranges add up, ie light 14 includes both heavy 7 and devestation 3. So this calculation means devestation counts for 4, heavy for 2 and light for 1 power, giving us a cap of 27 power.
|
||||
explosion_rec(epicenter, power, shaped)
|
||||
else
|
||||
for(var/turf/T in trange(max_range, epicenter))
|
||||
var/dist = sqrt((T.x - x0)**2 + (T.y - y0)**2)
|
||||
|
||||
if(dist < devastation_range) dist = 1
|
||||
else if(dist < heavy_impact_range) dist = 2
|
||||
else if(dist < light_impact_range) dist = 3
|
||||
else continue
|
||||
|
||||
if(!T)
|
||||
T = locate(x0,y0,z0)
|
||||
for(var/atom_movable in T.contents) //bypass type checking since only atom/movable can be contained by turfs anyway
|
||||
var/atom/movable/AM = atom_movable
|
||||
if(AM && AM.simulated) AM.ex_act(dist)
|
||||
|
||||
T.ex_act(dist)
|
||||
|
||||
var/took = (world.timeofday-start)/10
|
||||
//You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
|
||||
if(Debug2) to_world_log("## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds.")
|
||||
|
||||
//Machines which report explosions.
|
||||
for(var/i,i<=doppler_arrays.len,i++)
|
||||
var/obj/machinery/doppler_array/Array = doppler_arrays[i]
|
||||
if(Array)
|
||||
Array.sense_explosion(x0,y0,z0,devastation_range,heavy_impact_range,light_impact_range,took)
|
||||
sleep(8)
|
||||
|
||||
if(!powernet_rebuild_was_deferred_already && defer_powernet_rebuild)
|
||||
SSmachines.makepowernets()
|
||||
defer_powernet_rebuild = 0
|
||||
return 1
|
||||
|
||||
/proc/secondaryexplosion(turf/epicenter, range)
|
||||
for(var/turf/tile in range(range, epicenter))
|
||||
tile.ex_act(2)
|
||||
|
||||
@@ -1,114 +1,114 @@
|
||||
/client/proc/kaboom()
|
||||
var/power = tgui_input_number(src, "power?", "power?")
|
||||
var/turf/T = get_turf(src.mob)
|
||||
explosion_rec(T, power)
|
||||
|
||||
/obj
|
||||
var/explosion_resistance
|
||||
|
||||
/proc/explosion_rec(turf/epicenter, power)
|
||||
var/list/explosion_turfs = list()
|
||||
var/explosion_in_progress = 0
|
||||
|
||||
var/loopbreak = 0
|
||||
while(explosion_in_progress)
|
||||
if(loopbreak >= 15) return
|
||||
spawn(10)
|
||||
loopbreak++
|
||||
|
||||
if(power <= 0) return
|
||||
epicenter = get_turf(epicenter)
|
||||
if(!epicenter) return
|
||||
|
||||
message_admins("Explosion with size ([power]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z])")
|
||||
log_game("Explosion with size ([power]) in area [epicenter.loc.name] ")
|
||||
|
||||
playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(power*2,1) )
|
||||
playsound(epicenter, "explosion", 100, 1, round(power,1) )
|
||||
|
||||
explosion_in_progress = 1
|
||||
explosion_turfs = list()
|
||||
|
||||
explosion_turfs[epicenter] = power
|
||||
|
||||
//This steap handles the gathering of turfs which will be ex_act() -ed in the next step. It also ensures each turf gets the maximum possible amount of power dealt to it.
|
||||
for(var/direction in cardinal)
|
||||
var/turf/T = get_step(epicenter, direction)
|
||||
T.explosion_spread(power - epicenter.explosion_resistance, direction, explosion_turfs)
|
||||
|
||||
//This step applies the ex_act effects for the explosion, as planned in the previous step.
|
||||
for(var/turf/T in explosion_turfs)
|
||||
if(explosion_turfs[T] <= 0) continue
|
||||
if(!T) continue
|
||||
|
||||
//Wow severity looks confusing to calculate... Fret not, I didn't leave you with any additional instructions or help. (just kidding, see the line under the calculation)
|
||||
var/severity = 4 - round(max(min( 3, ((explosion_turfs[T] - T.explosion_resistance) / (max(3,(power/3)))) ) ,1), 1) //sanity effective power on tile divided by either 3 or one third the total explosion power
|
||||
// One third because there are three power levels and I
|
||||
// want each one to take up a third of the crater
|
||||
var/x = T.x
|
||||
var/y = T.y
|
||||
var/z = T.z
|
||||
T.ex_act(severity)
|
||||
if(!T)
|
||||
T = locate(x,y,z)
|
||||
for(var/atom_movable in T.contents)
|
||||
var/atom/movable/AM = atom_movable
|
||||
if(AM && AM.simulated)
|
||||
AM.ex_act(severity)
|
||||
|
||||
explosion_in_progress = 0
|
||||
|
||||
/turf
|
||||
var/explosion_resistance
|
||||
|
||||
/turf/space
|
||||
explosion_resistance = 3
|
||||
|
||||
/turf/simulated/open
|
||||
explosion_resistance = 3
|
||||
|
||||
/turf/simulated/floor
|
||||
explosion_resistance = 1
|
||||
|
||||
/turf/simulated/mineral
|
||||
explosion_resistance = 2
|
||||
|
||||
/turf/simulated/shuttle/floor
|
||||
explosion_resistance = 1
|
||||
|
||||
/turf/simulated/shuttle/floor4
|
||||
explosion_resistance = 1
|
||||
|
||||
/turf/simulated/shuttle/plating
|
||||
explosion_resistance = 1
|
||||
|
||||
/turf/simulated/shuttle/wall
|
||||
explosion_resistance = 10
|
||||
|
||||
/turf/simulated/wall
|
||||
explosion_resistance = 10
|
||||
|
||||
//Code-wise, a safe value for power is something up to ~25 or ~30.. This does quite a bit of damage to the station.
|
||||
//direction is the direction that the spread took to come to this tile. So it is pointing in the main blast direction - meaning where this tile should spread most of it's force.
|
||||
/turf/proc/explosion_spread(power, direction, var/list/explosion_turfs)
|
||||
if(power <= 0)
|
||||
return
|
||||
if(src in explosion_turfs)
|
||||
if(explosion_turfs[src] >= power)
|
||||
return //The turf already sustained and spread a power greated than what we are dealing with. No point spreading again.
|
||||
explosion_turfs[src] = power
|
||||
|
||||
var/spread_power = power - src.explosion_resistance //This is the amount of power that will be spread to the tile in the direction of the blast
|
||||
for(var/obj/O in src)
|
||||
if(O.explosion_resistance)
|
||||
spread_power -= O.explosion_resistance
|
||||
|
||||
var/turf/T = get_step(src, direction)
|
||||
T.explosion_spread(spread_power, direction, explosion_turfs)
|
||||
T = get_step(src, turn(direction,90))
|
||||
T.explosion_spread(spread_power, turn(direction,90), explosion_turfs)
|
||||
T = get_step(src, turn(direction,-90))
|
||||
T.explosion_spread(spread_power, turn(direction,-90), explosion_turfs)
|
||||
|
||||
/turf/unsimulated/explosion_spread(power)
|
||||
return //So it doesn't get to the parent proc, which simulates explosions
|
||||
/client/proc/kaboom()
|
||||
var/power = tgui_input_number(src, "power?", "power?")
|
||||
var/turf/T = get_turf(src.mob)
|
||||
explosion_rec(T, power)
|
||||
|
||||
/obj
|
||||
var/explosion_resistance
|
||||
|
||||
/proc/explosion_rec(turf/epicenter, power)
|
||||
var/list/explosion_turfs = list()
|
||||
var/explosion_in_progress = 0
|
||||
|
||||
var/loopbreak = 0
|
||||
while(explosion_in_progress)
|
||||
if(loopbreak >= 15) return
|
||||
spawn(10)
|
||||
loopbreak++
|
||||
|
||||
if(power <= 0) return
|
||||
epicenter = get_turf(epicenter)
|
||||
if(!epicenter) return
|
||||
|
||||
message_admins("Explosion with size ([power]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z])")
|
||||
log_game("Explosion with size ([power]) in area [epicenter.loc.name] ")
|
||||
|
||||
playsound(epicenter, 'sound/effects/explosionfar.ogg', 100, 1, round(power*2,1) )
|
||||
playsound(epicenter, "explosion", 100, 1, round(power,1) )
|
||||
|
||||
explosion_in_progress = 1
|
||||
explosion_turfs = list()
|
||||
|
||||
explosion_turfs[epicenter] = power
|
||||
|
||||
//This steap handles the gathering of turfs which will be ex_act() -ed in the next step. It also ensures each turf gets the maximum possible amount of power dealt to it.
|
||||
for(var/direction in cardinal)
|
||||
var/turf/T = get_step(epicenter, direction)
|
||||
T.explosion_spread(power - epicenter.explosion_resistance, direction, explosion_turfs)
|
||||
|
||||
//This step applies the ex_act effects for the explosion, as planned in the previous step.
|
||||
for(var/turf/T in explosion_turfs)
|
||||
if(explosion_turfs[T] <= 0) continue
|
||||
if(!T) continue
|
||||
|
||||
//Wow severity looks confusing to calculate... Fret not, I didn't leave you with any additional instructions or help. (just kidding, see the line under the calculation)
|
||||
var/severity = 4 - round(max(min( 3, ((explosion_turfs[T] - T.explosion_resistance) / (max(3,(power/3)))) ) ,1), 1) //sanity effective power on tile divided by either 3 or one third the total explosion power
|
||||
// One third because there are three power levels and I
|
||||
// want each one to take up a third of the crater
|
||||
var/x = T.x
|
||||
var/y = T.y
|
||||
var/z = T.z
|
||||
T.ex_act(severity)
|
||||
if(!T)
|
||||
T = locate(x,y,z)
|
||||
for(var/atom_movable in T.contents)
|
||||
var/atom/movable/AM = atom_movable
|
||||
if(AM && AM.simulated)
|
||||
AM.ex_act(severity)
|
||||
|
||||
explosion_in_progress = 0
|
||||
|
||||
/turf
|
||||
var/explosion_resistance
|
||||
|
||||
/turf/space
|
||||
explosion_resistance = 3
|
||||
|
||||
/turf/simulated/open
|
||||
explosion_resistance = 3
|
||||
|
||||
/turf/simulated/floor
|
||||
explosion_resistance = 1
|
||||
|
||||
/turf/simulated/mineral
|
||||
explosion_resistance = 2
|
||||
|
||||
/turf/simulated/shuttle/floor
|
||||
explosion_resistance = 1
|
||||
|
||||
/turf/simulated/shuttle/floor4
|
||||
explosion_resistance = 1
|
||||
|
||||
/turf/simulated/shuttle/plating
|
||||
explosion_resistance = 1
|
||||
|
||||
/turf/simulated/shuttle/wall
|
||||
explosion_resistance = 10
|
||||
|
||||
/turf/simulated/wall
|
||||
explosion_resistance = 10
|
||||
|
||||
//Code-wise, a safe value for power is something up to ~25 or ~30.. This does quite a bit of damage to the station.
|
||||
//direction is the direction that the spread took to come to this tile. So it is pointing in the main blast direction - meaning where this tile should spread most of it's force.
|
||||
/turf/proc/explosion_spread(power, direction, var/list/explosion_turfs)
|
||||
if(power <= 0)
|
||||
return
|
||||
if(src in explosion_turfs)
|
||||
if(explosion_turfs[src] >= power)
|
||||
return //The turf already sustained and spread a power greated than what we are dealing with. No point spreading again.
|
||||
explosion_turfs[src] = power
|
||||
|
||||
var/spread_power = power - src.explosion_resistance //This is the amount of power that will be spread to the tile in the direction of the blast
|
||||
for(var/obj/O in src)
|
||||
if(O.explosion_resistance)
|
||||
spread_power -= O.explosion_resistance
|
||||
|
||||
var/turf/T = get_step(src, direction)
|
||||
T.explosion_spread(spread_power, direction, explosion_turfs)
|
||||
T = get_step(src, turn(direction,90))
|
||||
T.explosion_spread(spread_power, turn(direction,90), explosion_turfs)
|
||||
T = get_step(src, turn(direction,-90))
|
||||
T.explosion_spread(spread_power, turn(direction,-90), explosion_turfs)
|
||||
|
||||
/turf/unsimulated/explosion_spread(power)
|
||||
return //So it doesn't get to the parent proc, which simulates explosions
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
// APC HULL
|
||||
|
||||
/obj/item/frame/apc
|
||||
name = "\improper APC frame"
|
||||
desc = "Used for repairing or building APCs"
|
||||
icon = 'icons/obj/apc_repair.dmi'
|
||||
icon_state = "apc_frame"
|
||||
refund_amt = 2
|
||||
build_wall_only = TRUE
|
||||
matter = list(MAT_STEEL = 100, MAT_GLASS = 30)
|
||||
|
||||
/obj/item/frame/apc/try_build(turf/on_wall, mob/user as mob)
|
||||
if (get_dist(on_wall, user)>1)
|
||||
return
|
||||
var/ndir = get_dir(user, on_wall)
|
||||
if (!(ndir in cardinal))
|
||||
return
|
||||
var/turf/loc = get_turf(user)
|
||||
var/area/A = loc.loc
|
||||
if (!istype(loc, /turf/simulated/floor))
|
||||
to_chat(user, "<span class='warning'>APC cannot be placed on this spot.</span>")
|
||||
return
|
||||
if (A.requires_power == 0 || istype(A, /area/space))
|
||||
to_chat(user, "<span class='warning'>APC cannot be placed in this area.</span>")
|
||||
return
|
||||
if (A.get_apc())
|
||||
to_chat(user, "<span class='warning'>This area already has an APC.</span>")
|
||||
return //only one APC per area
|
||||
for(var/obj/machinery/power/terminal/T in loc)
|
||||
if (T.master)
|
||||
to_chat(user, "<span class='warning'>There is another network terminal here.</span>")
|
||||
return
|
||||
else
|
||||
new /obj/item/stack/cable_coil(loc, 10)
|
||||
to_chat(user, "You cut the cables and disassemble the unused power terminal.")
|
||||
qdel(T)
|
||||
new /obj/machinery/power/apc(loc, ndir, 1)
|
||||
qdel(src)
|
||||
// APC HULL
|
||||
|
||||
/obj/item/frame/apc
|
||||
name = "\improper APC frame"
|
||||
desc = "Used for repairing or building APCs"
|
||||
icon = 'icons/obj/apc_repair.dmi'
|
||||
icon_state = "apc_frame"
|
||||
refund_amt = 2
|
||||
build_wall_only = TRUE
|
||||
matter = list(MAT_STEEL = 100, MAT_GLASS = 30)
|
||||
|
||||
/obj/item/frame/apc/try_build(turf/on_wall, mob/user as mob)
|
||||
if (get_dist(on_wall, user)>1)
|
||||
return
|
||||
var/ndir = get_dir(user, on_wall)
|
||||
if (!(ndir in cardinal))
|
||||
return
|
||||
var/turf/loc = get_turf(user)
|
||||
var/area/A = loc.loc
|
||||
if (!istype(loc, /turf/simulated/floor))
|
||||
to_chat(user, "<span class='warning'>APC cannot be placed on this spot.</span>")
|
||||
return
|
||||
if (A.requires_power == 0 || istype(A, /area/space))
|
||||
to_chat(user, "<span class='warning'>APC cannot be placed in this area.</span>")
|
||||
return
|
||||
if (A.get_apc())
|
||||
to_chat(user, "<span class='warning'>This area already has an APC.</span>")
|
||||
return //only one APC per area
|
||||
for(var/obj/machinery/power/terminal/T in loc)
|
||||
if (T.master)
|
||||
to_chat(user, "<span class='warning'>There is another network terminal here.</span>")
|
||||
return
|
||||
else
|
||||
new /obj/item/stack/cable_coil(loc, 10)
|
||||
to_chat(user, "You cut the cables and disassemble the unused power terminal.")
|
||||
qdel(T)
|
||||
new /obj/machinery/power/apc(loc, ndir, 1)
|
||||
qdel(src)
|
||||
|
||||
+263
-263
@@ -1,263 +1,263 @@
|
||||
//Also contains /obj/structure/closet/body_bag because I doubt anyone would think to look for bodybags in /object/structures
|
||||
|
||||
/obj/item/bodybag
|
||||
name = "body bag"
|
||||
desc = "A folded bag designed for the storage and transportation of cadavers."
|
||||
icon = 'icons/obj/closets/bodybag.dmi'
|
||||
icon_state = "bodybag_folded"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
|
||||
/obj/item/bodybag/attack_self(mob/user)
|
||||
var/obj/structure/closet/body_bag/R = new /obj/structure/closet/body_bag(user.loc)
|
||||
R.add_fingerprint(user)
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/item/weapon/storage/box/bodybags
|
||||
name = "body bags"
|
||||
desc = "This box contains body bags."
|
||||
icon_state = "bodybags"
|
||||
starts_with = list(/obj/item/bodybag = 7)
|
||||
|
||||
/obj/structure/closet/body_bag
|
||||
name = "body bag"
|
||||
desc = "A plastic bag designed for the storage and transportation of cadavers."
|
||||
icon = 'icons/obj/closets/bodybag.dmi'
|
||||
closet_appearance = null
|
||||
open_sound = 'sound/items/zip.ogg'
|
||||
close_sound = 'sound/items/zip.ogg'
|
||||
var/item_path = /obj/item/bodybag
|
||||
density = FALSE
|
||||
storage_capacity = (MOB_MEDIUM * 2) - 1
|
||||
var/contains_body = 0
|
||||
|
||||
/obj/structure/closet/body_bag/attackby(var/obj/item/W as obj, mob/user as mob)
|
||||
if (istype(W, /obj/item/weapon/pen))
|
||||
var/t = tgui_input_text(user, "What would you like the label to be?", text("[]", src.name), null, MAX_NAME_LEN )
|
||||
if (user.get_active_hand() != W)
|
||||
return
|
||||
if (!in_range(src, user) && src.loc != user)
|
||||
return
|
||||
t = sanitizeSafe(t, MAX_NAME_LEN)
|
||||
if (t)
|
||||
src.name = "body bag - "
|
||||
src.name += t
|
||||
add_overlay("bodybag_label")
|
||||
else
|
||||
src.name = "body bag"
|
||||
//..() //Doesn't need to run the parent. Since when can fucking bodybags be welded shut? -Agouri
|
||||
return
|
||||
else if(W.has_tool_quality(TOOL_WIRECUTTER))
|
||||
to_chat(user, "You cut the tag off the bodybag")
|
||||
src.name = "body bag"
|
||||
cut_overlays()
|
||||
return
|
||||
|
||||
/obj/structure/closet/body_bag/store_mobs(var/stored_units)
|
||||
contains_body = ..()
|
||||
return contains_body
|
||||
|
||||
/obj/structure/closet/body_bag/close()
|
||||
if(..())
|
||||
density = FALSE
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/structure/closet/body_bag/MouseDrop(over_object, src_location, over_location)
|
||||
..()
|
||||
if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src))))
|
||||
if(!ishuman(usr)) return 0
|
||||
if(opened) return 0
|
||||
if(contents.len) return 0
|
||||
visible_message("[usr] folds up the [src.name]")
|
||||
var/folded = new item_path(get_turf(src))
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
return folded
|
||||
|
||||
/obj/structure/closet/body_bag/relaymove(mob/user,direction)
|
||||
if(src.loc != get_turf(src))
|
||||
src.loc.relaymove(user,direction)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/structure/closet/body_bag/proc/get_occupants()
|
||||
var/list/occupants = list()
|
||||
for(var/mob/living/carbon/human/H in contents)
|
||||
occupants += H
|
||||
return occupants
|
||||
|
||||
/obj/structure/closet/body_bag/proc/update(var/broadcast=0)
|
||||
if(istype(loc, /obj/structure/morgue))
|
||||
var/obj/structure/morgue/M = loc
|
||||
M.update(broadcast)
|
||||
|
||||
/obj/structure/closet/body_bag/update_icon()
|
||||
if(opened)
|
||||
icon_state = "open"
|
||||
else
|
||||
icon_state = "closed_unlocked"
|
||||
|
||||
cut_overlays()
|
||||
/* Ours don't have toetags
|
||||
if(has_label)
|
||||
add_overlay("bodybag_label")
|
||||
*/
|
||||
|
||||
|
||||
/obj/item/bodybag/cryobag
|
||||
name = "stasis bag"
|
||||
desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \
|
||||
especially useful if short on time or in a hostile enviroment."
|
||||
icon = 'icons/obj/closets/cryobag.dmi'
|
||||
icon_state = "bodybag_folded"
|
||||
item_state = "bodybag_cryo_folded"
|
||||
origin_tech = list(TECH_BIO = 4)
|
||||
var/obj/item/weapon/reagent_containers/syringe/syringe
|
||||
|
||||
/obj/item/bodybag/cryobag/attack_self(mob/user)
|
||||
var/obj/structure/closet/body_bag/cryobag/R = new /obj/structure/closet/body_bag/cryobag(user.loc)
|
||||
R.add_fingerprint(user)
|
||||
if(syringe)
|
||||
R.syringe = syringe
|
||||
syringe = null
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag
|
||||
name = "stasis bag"
|
||||
desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \
|
||||
especially useful if short on time or in a hostile enviroment."
|
||||
icon = 'icons/obj/closets/cryobag.dmi'
|
||||
item_path = /obj/item/bodybag/cryobag
|
||||
store_misc = 0
|
||||
store_items = 0
|
||||
var/used = 0
|
||||
var/obj/item/weapon/tank/tank = null
|
||||
var/tank_type = /obj/item/weapon/tank/stasis/oxygen
|
||||
var/stasis_level = 3 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1)
|
||||
var/obj/item/weapon/reagent_containers/syringe/syringe
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/Initialize()
|
||||
tank = new tank_type(null) //It's in nullspace to prevent ejection when the bag is opened.
|
||||
..()
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/Destroy()
|
||||
QDEL_NULL(syringe)
|
||||
QDEL_NULL(tank)
|
||||
return ..()
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/attack_hand(mob/living/user)
|
||||
if(used)
|
||||
var/confirm = tgui_alert(user, "Are you sure you want to open \the [src]? \The [src] will expire upon opening it.", "Confirm Opening", list("No", "Yes"))
|
||||
if(confirm == "Yes")
|
||||
..() // Will call `toggle()` and open the bag.
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/open()
|
||||
. = ..()
|
||||
if(used)
|
||||
new /obj/item/usedcryobag(loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
var/image/I = image(icon, "indicator[opened]")
|
||||
I.appearance_flags = RESET_COLOR
|
||||
I.color = COLOR_LIME
|
||||
add_overlay(I)
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/MouseDrop(over_object, src_location, over_location)
|
||||
. = ..()
|
||||
if(. && syringe)
|
||||
var/obj/item/bodybag/cryobag/folded = .
|
||||
folded.syringe = syringe
|
||||
syringe = null
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/Entered(atom/movable/AM)
|
||||
if(ishuman(AM))
|
||||
var/mob/living/carbon/human/H = AM
|
||||
H.Stasis(stasis_level)
|
||||
src.used = 1
|
||||
inject_occupant(H)
|
||||
|
||||
if(istype(AM, /obj/item/organ))
|
||||
var/obj/item/organ/O = AM
|
||||
O.preserved = 1
|
||||
for(var/obj/item/organ/organ in O)
|
||||
organ.preserved = 1
|
||||
..()
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/Exited(atom/movable/AM)
|
||||
if(ishuman(AM))
|
||||
var/mob/living/carbon/human/H = AM
|
||||
H.Stasis(0)
|
||||
|
||||
if(istype(AM, /obj/item/organ))
|
||||
var/obj/item/organ/O = AM
|
||||
O.preserved = 0
|
||||
for(var/obj/item/organ/organ in O)
|
||||
organ.preserved = 0
|
||||
..()
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/return_air() //Used to make stasis bags protect from vacuum.
|
||||
if(tank)
|
||||
return tank.air_contents
|
||||
..()
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/proc/inject_occupant(var/mob/living/carbon/human/H)
|
||||
if(!syringe)
|
||||
return
|
||||
|
||||
if(H.reagents)
|
||||
syringe.reagents.trans_to_mob(H, 30, CHEM_BLOOD)
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/examine(mob/user)
|
||||
. = ..()
|
||||
if(Adjacent(user)) //The bag's rather thick and opaque from a distance.
|
||||
. += "<span class='info'>You peer into \the [src].</span>"
|
||||
if(syringe)
|
||||
. += "<span class='info'>It has a syringe added to it.</span>"
|
||||
for(var/mob/living/L in contents)
|
||||
. += L.examine(user)
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/attackby(obj/item/W, mob/user)
|
||||
if(opened)
|
||||
..()
|
||||
else //Allows the bag to respond to a health analyzer by analyzing the mob inside without needing to open it.
|
||||
if(istype(W,/obj/item/device/healthanalyzer))
|
||||
var/obj/item/device/healthanalyzer/analyzer = W
|
||||
for(var/mob/living/L in contents)
|
||||
analyzer.attack(L,user)
|
||||
|
||||
else if(istype(W,/obj/item/weapon/reagent_containers/syringe))
|
||||
if(syringe)
|
||||
to_chat(user,"<span class='warning'>\The [src] already has an injector! Remove it first.</span>")
|
||||
else
|
||||
var/obj/item/weapon/reagent_containers/syringe/syringe = W
|
||||
to_chat(user,"<span class='info'>You insert \the [syringe] into \the [src], and it locks into place.</span>")
|
||||
user.unEquip(syringe)
|
||||
src.syringe = syringe
|
||||
syringe.loc = null
|
||||
for(var/mob/living/carbon/human/H in contents)
|
||||
inject_occupant(H)
|
||||
break
|
||||
|
||||
else if(W.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
if(syringe)
|
||||
if(used)
|
||||
to_chat(user,"<span class='warning'>The injector cannot be removed now that the stasis bag has been used!</span>")
|
||||
else
|
||||
syringe.forceMove(src.loc)
|
||||
to_chat(user,"<span class='info'>You pry \the [syringe] out of \the [src].</span>")
|
||||
syringe = null
|
||||
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/usedcryobag
|
||||
name = "used stasis bag"
|
||||
desc = "Pretty useless now.."
|
||||
icon_state = "bodybag_used"
|
||||
icon = 'icons/obj/closets/cryobag.dmi'
|
||||
//Also contains /obj/structure/closet/body_bag because I doubt anyone would think to look for bodybags in /object/structures
|
||||
|
||||
/obj/item/bodybag
|
||||
name = "body bag"
|
||||
desc = "A folded bag designed for the storage and transportation of cadavers."
|
||||
icon = 'icons/obj/closets/bodybag.dmi'
|
||||
icon_state = "bodybag_folded"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
|
||||
/obj/item/bodybag/attack_self(mob/user)
|
||||
var/obj/structure/closet/body_bag/R = new /obj/structure/closet/body_bag(user.loc)
|
||||
R.add_fingerprint(user)
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/item/weapon/storage/box/bodybags
|
||||
name = "body bags"
|
||||
desc = "This box contains body bags."
|
||||
icon_state = "bodybags"
|
||||
starts_with = list(/obj/item/bodybag = 7)
|
||||
|
||||
/obj/structure/closet/body_bag
|
||||
name = "body bag"
|
||||
desc = "A plastic bag designed for the storage and transportation of cadavers."
|
||||
icon = 'icons/obj/closets/bodybag.dmi'
|
||||
closet_appearance = null
|
||||
open_sound = 'sound/items/zip.ogg'
|
||||
close_sound = 'sound/items/zip.ogg'
|
||||
var/item_path = /obj/item/bodybag
|
||||
density = FALSE
|
||||
storage_capacity = (MOB_MEDIUM * 2) - 1
|
||||
var/contains_body = 0
|
||||
|
||||
/obj/structure/closet/body_bag/attackby(var/obj/item/W as obj, mob/user as mob)
|
||||
if (istype(W, /obj/item/weapon/pen))
|
||||
var/t = tgui_input_text(user, "What would you like the label to be?", text("[]", src.name), null, MAX_NAME_LEN )
|
||||
if (user.get_active_hand() != W)
|
||||
return
|
||||
if (!in_range(src, user) && src.loc != user)
|
||||
return
|
||||
t = sanitizeSafe(t, MAX_NAME_LEN)
|
||||
if (t)
|
||||
src.name = "body bag - "
|
||||
src.name += t
|
||||
add_overlay("bodybag_label")
|
||||
else
|
||||
src.name = "body bag"
|
||||
//..() //Doesn't need to run the parent. Since when can fucking bodybags be welded shut? -Agouri
|
||||
return
|
||||
else if(W.has_tool_quality(TOOL_WIRECUTTER))
|
||||
to_chat(user, "You cut the tag off the bodybag")
|
||||
src.name = "body bag"
|
||||
cut_overlays()
|
||||
return
|
||||
|
||||
/obj/structure/closet/body_bag/store_mobs(var/stored_units)
|
||||
contains_body = ..()
|
||||
return contains_body
|
||||
|
||||
/obj/structure/closet/body_bag/close()
|
||||
if(..())
|
||||
density = FALSE
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/structure/closet/body_bag/MouseDrop(over_object, src_location, over_location)
|
||||
..()
|
||||
if((over_object == usr && (in_range(src, usr) || usr.contents.Find(src))))
|
||||
if(!ishuman(usr)) return 0
|
||||
if(opened) return 0
|
||||
if(contents.len) return 0
|
||||
visible_message("[usr] folds up the [src.name]")
|
||||
var/folded = new item_path(get_turf(src))
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
return folded
|
||||
|
||||
/obj/structure/closet/body_bag/relaymove(mob/user,direction)
|
||||
if(src.loc != get_turf(src))
|
||||
src.loc.relaymove(user,direction)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/structure/closet/body_bag/proc/get_occupants()
|
||||
var/list/occupants = list()
|
||||
for(var/mob/living/carbon/human/H in contents)
|
||||
occupants += H
|
||||
return occupants
|
||||
|
||||
/obj/structure/closet/body_bag/proc/update(var/broadcast=0)
|
||||
if(istype(loc, /obj/structure/morgue))
|
||||
var/obj/structure/morgue/M = loc
|
||||
M.update(broadcast)
|
||||
|
||||
/obj/structure/closet/body_bag/update_icon()
|
||||
if(opened)
|
||||
icon_state = "open"
|
||||
else
|
||||
icon_state = "closed_unlocked"
|
||||
|
||||
cut_overlays()
|
||||
/* Ours don't have toetags
|
||||
if(has_label)
|
||||
add_overlay("bodybag_label")
|
||||
*/
|
||||
|
||||
|
||||
/obj/item/bodybag/cryobag
|
||||
name = "stasis bag"
|
||||
desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \
|
||||
especially useful if short on time or in a hostile enviroment."
|
||||
icon = 'icons/obj/closets/cryobag.dmi'
|
||||
icon_state = "bodybag_folded"
|
||||
item_state = "bodybag_cryo_folded"
|
||||
origin_tech = list(TECH_BIO = 4)
|
||||
var/obj/item/weapon/reagent_containers/syringe/syringe
|
||||
|
||||
/obj/item/bodybag/cryobag/attack_self(mob/user)
|
||||
var/obj/structure/closet/body_bag/cryobag/R = new /obj/structure/closet/body_bag/cryobag(user.loc)
|
||||
R.add_fingerprint(user)
|
||||
if(syringe)
|
||||
R.syringe = syringe
|
||||
syringe = null
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag
|
||||
name = "stasis bag"
|
||||
desc = "A non-reusable plastic bag designed to slow down bodily functions such as circulation and breathing, \
|
||||
especially useful if short on time or in a hostile enviroment."
|
||||
icon = 'icons/obj/closets/cryobag.dmi'
|
||||
item_path = /obj/item/bodybag/cryobag
|
||||
store_misc = 0
|
||||
store_items = 0
|
||||
var/used = 0
|
||||
var/obj/item/weapon/tank/tank = null
|
||||
var/tank_type = /obj/item/weapon/tank/stasis/oxygen
|
||||
var/stasis_level = 3 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1)
|
||||
var/obj/item/weapon/reagent_containers/syringe/syringe
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/Initialize()
|
||||
tank = new tank_type(null) //It's in nullspace to prevent ejection when the bag is opened.
|
||||
..()
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/Destroy()
|
||||
QDEL_NULL(syringe)
|
||||
QDEL_NULL(tank)
|
||||
return ..()
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/attack_hand(mob/living/user)
|
||||
if(used)
|
||||
var/confirm = tgui_alert(user, "Are you sure you want to open \the [src]? \The [src] will expire upon opening it.", "Confirm Opening", list("No", "Yes"))
|
||||
if(confirm == "Yes")
|
||||
..() // Will call `toggle()` and open the bag.
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/open()
|
||||
. = ..()
|
||||
if(used)
|
||||
new /obj/item/usedcryobag(loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
var/image/I = image(icon, "indicator[opened]")
|
||||
I.appearance_flags = RESET_COLOR
|
||||
I.color = COLOR_LIME
|
||||
add_overlay(I)
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/MouseDrop(over_object, src_location, over_location)
|
||||
. = ..()
|
||||
if(. && syringe)
|
||||
var/obj/item/bodybag/cryobag/folded = .
|
||||
folded.syringe = syringe
|
||||
syringe = null
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/Entered(atom/movable/AM)
|
||||
if(ishuman(AM))
|
||||
var/mob/living/carbon/human/H = AM
|
||||
H.Stasis(stasis_level)
|
||||
src.used = 1
|
||||
inject_occupant(H)
|
||||
|
||||
if(istype(AM, /obj/item/organ))
|
||||
var/obj/item/organ/O = AM
|
||||
O.preserved = 1
|
||||
for(var/obj/item/organ/organ in O)
|
||||
organ.preserved = 1
|
||||
..()
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/Exited(atom/movable/AM)
|
||||
if(ishuman(AM))
|
||||
var/mob/living/carbon/human/H = AM
|
||||
H.Stasis(0)
|
||||
|
||||
if(istype(AM, /obj/item/organ))
|
||||
var/obj/item/organ/O = AM
|
||||
O.preserved = 0
|
||||
for(var/obj/item/organ/organ in O)
|
||||
organ.preserved = 0
|
||||
..()
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/return_air() //Used to make stasis bags protect from vacuum.
|
||||
if(tank)
|
||||
return tank.air_contents
|
||||
..()
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/proc/inject_occupant(var/mob/living/carbon/human/H)
|
||||
if(!syringe)
|
||||
return
|
||||
|
||||
if(H.reagents)
|
||||
syringe.reagents.trans_to_mob(H, 30, CHEM_BLOOD)
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/examine(mob/user)
|
||||
. = ..()
|
||||
if(Adjacent(user)) //The bag's rather thick and opaque from a distance.
|
||||
. += "<span class='info'>You peer into \the [src].</span>"
|
||||
if(syringe)
|
||||
. += "<span class='info'>It has a syringe added to it.</span>"
|
||||
for(var/mob/living/L in contents)
|
||||
. += L.examine(user)
|
||||
|
||||
/obj/structure/closet/body_bag/cryobag/attackby(obj/item/W, mob/user)
|
||||
if(opened)
|
||||
..()
|
||||
else //Allows the bag to respond to a health analyzer by analyzing the mob inside without needing to open it.
|
||||
if(istype(W,/obj/item/device/healthanalyzer))
|
||||
var/obj/item/device/healthanalyzer/analyzer = W
|
||||
for(var/mob/living/L in contents)
|
||||
analyzer.attack(L,user)
|
||||
|
||||
else if(istype(W,/obj/item/weapon/reagent_containers/syringe))
|
||||
if(syringe)
|
||||
to_chat(user,"<span class='warning'>\The [src] already has an injector! Remove it first.</span>")
|
||||
else
|
||||
var/obj/item/weapon/reagent_containers/syringe/syringe = W
|
||||
to_chat(user,"<span class='info'>You insert \the [syringe] into \the [src], and it locks into place.</span>")
|
||||
user.unEquip(syringe)
|
||||
src.syringe = syringe
|
||||
syringe.loc = null
|
||||
for(var/mob/living/carbon/human/H in contents)
|
||||
inject_occupant(H)
|
||||
break
|
||||
|
||||
else if(W.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
if(syringe)
|
||||
if(used)
|
||||
to_chat(user,"<span class='warning'>The injector cannot be removed now that the stasis bag has been used!</span>")
|
||||
else
|
||||
syringe.forceMove(src.loc)
|
||||
to_chat(user,"<span class='info'>You pry \the [syringe] out of \the [src].</span>")
|
||||
syringe = null
|
||||
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/usedcryobag
|
||||
name = "used stasis bag"
|
||||
desc = "Pretty useless now.."
|
||||
icon_state = "bodybag_used"
|
||||
icon = 'icons/obj/closets/cryobag.dmi'
|
||||
|
||||
+214
-214
@@ -1,214 +1,214 @@
|
||||
/obj/item/weapon/pen/crayon/red
|
||||
icon_state = "crayonred"
|
||||
colour = "#DA0000"
|
||||
shadeColour = "#810C0C"
|
||||
colourName = "red"
|
||||
|
||||
/obj/item/weapon/pen/crayon/orange
|
||||
icon_state = "crayonorange"
|
||||
colour = "#FF9300"
|
||||
shadeColour = "#A55403"
|
||||
colourName = "orange"
|
||||
|
||||
/obj/item/weapon/pen/crayon/yellow
|
||||
icon_state = "crayonyellow"
|
||||
colour = "#FFF200"
|
||||
shadeColour = "#886422"
|
||||
colourName = "yellow"
|
||||
|
||||
/obj/item/weapon/pen/crayon/green
|
||||
icon_state = "crayongreen"
|
||||
colour = "#A8E61D"
|
||||
shadeColour = "#61840F"
|
||||
colourName = "green"
|
||||
|
||||
/obj/item/weapon/pen/crayon/blue
|
||||
icon_state = "crayonblue"
|
||||
colour = "#00B7EF"
|
||||
shadeColour = "#0082A8"
|
||||
colourName = "blue"
|
||||
|
||||
/obj/item/weapon/pen/crayon/purple
|
||||
icon_state = "crayonpurple"
|
||||
colour = "#DA00FF"
|
||||
shadeColour = "#810CFF"
|
||||
colourName = "purple"
|
||||
|
||||
/obj/item/weapon/pen/crayon/mime
|
||||
icon_state = "crayonmime"
|
||||
desc = "A very sad-looking crayon."
|
||||
colour = "#FFFFFF"
|
||||
shadeColour = "#000000"
|
||||
colourName = "mime"
|
||||
uses = 0
|
||||
|
||||
/obj/item/weapon/pen/crayon/mime/attack_self(mob/living/user as mob) //inversion
|
||||
if(colour != "#FFFFFF" && shadeColour != "#000000")
|
||||
colour = "#FFFFFF"
|
||||
shadeColour = "#000000"
|
||||
to_chat(user, "You will now draw in white and black with this crayon.")
|
||||
else
|
||||
colour = "#000000"
|
||||
shadeColour = "#FFFFFF"
|
||||
to_chat(user, "You will now draw in black and white with this crayon.")
|
||||
return
|
||||
|
||||
/obj/item/weapon/pen/crayon/rainbow
|
||||
icon_state = "crayonrainbow"
|
||||
colour = "#FFF000"
|
||||
shadeColour = "#000FFF"
|
||||
colourName = "rainbow"
|
||||
uses = 0
|
||||
|
||||
/obj/item/weapon/pen/crayon/rainbow/attack_self(mob/living/user as mob)
|
||||
colour = input(user, "Please select the main colour.", "Crayon colour") as color
|
||||
shadeColour = input(user, "Please select the shade colour.", "Crayon colour") as color
|
||||
return
|
||||
|
||||
/obj/item/weapon/pen/crayon/afterattack(atom/target, mob/user as mob, proximity)
|
||||
if(!proximity) return
|
||||
if(istype(target,/turf/simulated/floor))
|
||||
var/drawtype = tgui_input_list(user, "Choose what you'd like to draw.", "Crayon scribbles", list("graffiti","rune","letter","arrow"))
|
||||
if(!drawtype)
|
||||
return
|
||||
if(get_dist(target, user) > 1 || !(user.z == target.z))
|
||||
return
|
||||
switch(drawtype)
|
||||
if("letter")
|
||||
drawtype = tgui_input_list(user, "Choose the letter.", "Crayon scribbles", list("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"))
|
||||
if(!drawtype || get_dist(target, user) > 1 || !(user.z == target.z))
|
||||
return
|
||||
to_chat(user, "You start drawing a letter on the [target.name].")
|
||||
if("graffiti")
|
||||
drawtype = tgui_input_list(user, "Choose the graffiti.", "Crayon scribbles", list("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa"))
|
||||
if(!drawtype || get_dist(target, user) > 1 || !(user.z == target.z))
|
||||
return
|
||||
to_chat(user, "You start drawing graffiti on the [target.name].")
|
||||
if("rune")
|
||||
drawtype = tgui_input_list(user, "Choose the rune.", "Crayon scribbles", list("rune1", "rune2", "rune3", "rune4", "rune5", "rune6"))
|
||||
if(!drawtype || get_dist(target, user) > 1 || !(user.z == target.z))
|
||||
return
|
||||
to_chat(user, "You start drawing a rune on the [target.name].")
|
||||
if("arrow")
|
||||
drawtype = tgui_input_list(user, "Choose the arrow.", "Crayon scribbles", list("left", "right", "up", "down"))
|
||||
if(!drawtype || get_dist(target, user) > 1 || !(user.z == target.z))
|
||||
return
|
||||
to_chat(user, "You start drawing an arrow on the [target.name].")
|
||||
if(instant || do_after(user, 50))
|
||||
new /obj/effect/decal/cleanable/crayon(target,colour,shadeColour,drawtype)
|
||||
to_chat(user, "You finish drawing.")
|
||||
|
||||
var/msg = "[user.client.key] ([user]) has drawn [drawtype] (with [src]) at [target.x],[target.y],[target.z]."
|
||||
if(config.log_graffiti)
|
||||
message_admins(msg)
|
||||
log_game(msg) //We will log it anyways.
|
||||
|
||||
target.add_fingerprint(user) // Adds their fingerprints to the floor the crayon is drawn on.
|
||||
if(uses)
|
||||
uses--
|
||||
if(!uses)
|
||||
to_chat(user, "<span class='warning'>You used up your crayon!</span>")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/pen/crayon/attack(mob/living/M as mob, mob/living/user as mob)
|
||||
if(M == user)
|
||||
to_chat(user, "You take a bite of the crayon and swallow it.")
|
||||
user.nutrition += 1
|
||||
user.reagents.add_reagent("crayon_dust",min(5,uses)/3)
|
||||
if(uses)
|
||||
uses -= 5
|
||||
if(uses <= 0)
|
||||
to_chat(user, "<span class='warning'>You ate your crayon!</span>")
|
||||
qdel(src)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/black
|
||||
icon_state = "markerblack"
|
||||
colour = "#2D2D2D"
|
||||
shadeColour = "#000000"
|
||||
colourName = "black"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/red
|
||||
icon_state = "markerred"
|
||||
colour = "#DA0000"
|
||||
shadeColour = "#810C0C"
|
||||
colourName = "red"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/orange
|
||||
icon_state = "markerorange"
|
||||
colour = "#FF9300"
|
||||
shadeColour = "#A55403"
|
||||
colourName = "orange"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/yellow
|
||||
icon_state = "markeryellow"
|
||||
colour = "#FFF200"
|
||||
shadeColour = "#886422"
|
||||
colourName = "yellow"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/green
|
||||
icon_state = "markergreen"
|
||||
colour = "#A8E61D"
|
||||
shadeColour = "#61840F"
|
||||
colourName = "green"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/blue
|
||||
icon_state = "markerblue"
|
||||
colour = "#00B7EF"
|
||||
shadeColour = "#0082A8"
|
||||
colourName = "blue"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/purple
|
||||
icon_state = "markerpurple"
|
||||
colour = "#DA00FF"
|
||||
shadeColour = "#810CFF"
|
||||
colourName = "purple"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/mime
|
||||
icon_state = "markermime"
|
||||
desc = "A very sad-looking marker."
|
||||
colour = "#FFFFFF"
|
||||
shadeColour = "#000000"
|
||||
colourName = "mime"
|
||||
uses = 0
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/mime/attack_self(mob/living/user as mob) //inversion
|
||||
if(colour != "#FFFFFF" && shadeColour != "#000000")
|
||||
colour = "#FFFFFF"
|
||||
shadeColour = "#000000"
|
||||
to_chat(user, "You will now draw in white and black with this marker.")
|
||||
else
|
||||
colour = "#000000"
|
||||
shadeColour = "#FFFFFF"
|
||||
to_chat(user, "You will now draw in black and white with this marker.")
|
||||
return
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/rainbow
|
||||
icon_state = "markerrainbow"
|
||||
colour = "#FFF000"
|
||||
shadeColour = "#000FFF"
|
||||
colourName = "rainbow"
|
||||
uses = 0
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/rainbow/attack_self(mob/living/user as mob)
|
||||
colour = input(user, "Please select the main colour.", "Marker colour") as color
|
||||
shadeColour = input(user, "Please select the shade colour.", "Marker colour") as color
|
||||
return
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/attack(mob/living/M as mob, mob/living/user as mob)
|
||||
if(M == user)
|
||||
to_chat(user, "You take a bite of the marker and swallow it.")
|
||||
user.nutrition += 1
|
||||
user.reagents.add_reagent("marker_ink",6)
|
||||
if(uses)
|
||||
uses -= 5
|
||||
if(uses <= 0)
|
||||
to_chat(user, "<span class='warning'>You ate the marker!</span>")
|
||||
qdel(src)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/pen/crayon/attack_self(var/mob/user)
|
||||
return
|
||||
/obj/item/weapon/pen/crayon/red
|
||||
icon_state = "crayonred"
|
||||
colour = "#DA0000"
|
||||
shadeColour = "#810C0C"
|
||||
colourName = "red"
|
||||
|
||||
/obj/item/weapon/pen/crayon/orange
|
||||
icon_state = "crayonorange"
|
||||
colour = "#FF9300"
|
||||
shadeColour = "#A55403"
|
||||
colourName = "orange"
|
||||
|
||||
/obj/item/weapon/pen/crayon/yellow
|
||||
icon_state = "crayonyellow"
|
||||
colour = "#FFF200"
|
||||
shadeColour = "#886422"
|
||||
colourName = "yellow"
|
||||
|
||||
/obj/item/weapon/pen/crayon/green
|
||||
icon_state = "crayongreen"
|
||||
colour = "#A8E61D"
|
||||
shadeColour = "#61840F"
|
||||
colourName = "green"
|
||||
|
||||
/obj/item/weapon/pen/crayon/blue
|
||||
icon_state = "crayonblue"
|
||||
colour = "#00B7EF"
|
||||
shadeColour = "#0082A8"
|
||||
colourName = "blue"
|
||||
|
||||
/obj/item/weapon/pen/crayon/purple
|
||||
icon_state = "crayonpurple"
|
||||
colour = "#DA00FF"
|
||||
shadeColour = "#810CFF"
|
||||
colourName = "purple"
|
||||
|
||||
/obj/item/weapon/pen/crayon/mime
|
||||
icon_state = "crayonmime"
|
||||
desc = "A very sad-looking crayon."
|
||||
colour = "#FFFFFF"
|
||||
shadeColour = "#000000"
|
||||
colourName = "mime"
|
||||
uses = 0
|
||||
|
||||
/obj/item/weapon/pen/crayon/mime/attack_self(mob/living/user as mob) //inversion
|
||||
if(colour != "#FFFFFF" && shadeColour != "#000000")
|
||||
colour = "#FFFFFF"
|
||||
shadeColour = "#000000"
|
||||
to_chat(user, "You will now draw in white and black with this crayon.")
|
||||
else
|
||||
colour = "#000000"
|
||||
shadeColour = "#FFFFFF"
|
||||
to_chat(user, "You will now draw in black and white with this crayon.")
|
||||
return
|
||||
|
||||
/obj/item/weapon/pen/crayon/rainbow
|
||||
icon_state = "crayonrainbow"
|
||||
colour = "#FFF000"
|
||||
shadeColour = "#000FFF"
|
||||
colourName = "rainbow"
|
||||
uses = 0
|
||||
|
||||
/obj/item/weapon/pen/crayon/rainbow/attack_self(mob/living/user as mob)
|
||||
colour = input(user, "Please select the main colour.", "Crayon colour") as color
|
||||
shadeColour = input(user, "Please select the shade colour.", "Crayon colour") as color
|
||||
return
|
||||
|
||||
/obj/item/weapon/pen/crayon/afterattack(atom/target, mob/user as mob, proximity)
|
||||
if(!proximity) return
|
||||
if(istype(target,/turf/simulated/floor))
|
||||
var/drawtype = tgui_input_list(user, "Choose what you'd like to draw.", "Crayon scribbles", list("graffiti","rune","letter","arrow"))
|
||||
if(!drawtype)
|
||||
return
|
||||
if(get_dist(target, user) > 1 || !(user.z == target.z))
|
||||
return
|
||||
switch(drawtype)
|
||||
if("letter")
|
||||
drawtype = tgui_input_list(user, "Choose the letter.", "Crayon scribbles", list("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"))
|
||||
if(!drawtype || get_dist(target, user) > 1 || !(user.z == target.z))
|
||||
return
|
||||
to_chat(user, "You start drawing a letter on the [target.name].")
|
||||
if("graffiti")
|
||||
drawtype = tgui_input_list(user, "Choose the graffiti.", "Crayon scribbles", list("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa"))
|
||||
if(!drawtype || get_dist(target, user) > 1 || !(user.z == target.z))
|
||||
return
|
||||
to_chat(user, "You start drawing graffiti on the [target.name].")
|
||||
if("rune")
|
||||
drawtype = tgui_input_list(user, "Choose the rune.", "Crayon scribbles", list("rune1", "rune2", "rune3", "rune4", "rune5", "rune6"))
|
||||
if(!drawtype || get_dist(target, user) > 1 || !(user.z == target.z))
|
||||
return
|
||||
to_chat(user, "You start drawing a rune on the [target.name].")
|
||||
if("arrow")
|
||||
drawtype = tgui_input_list(user, "Choose the arrow.", "Crayon scribbles", list("left", "right", "up", "down"))
|
||||
if(!drawtype || get_dist(target, user) > 1 || !(user.z == target.z))
|
||||
return
|
||||
to_chat(user, "You start drawing an arrow on the [target.name].")
|
||||
if(instant || do_after(user, 50))
|
||||
new /obj/effect/decal/cleanable/crayon(target,colour,shadeColour,drawtype)
|
||||
to_chat(user, "You finish drawing.")
|
||||
|
||||
var/msg = "[user.client.key] ([user]) has drawn [drawtype] (with [src]) at [target.x],[target.y],[target.z]."
|
||||
if(config.log_graffiti)
|
||||
message_admins(msg)
|
||||
log_game(msg) //We will log it anyways.
|
||||
|
||||
target.add_fingerprint(user) // Adds their fingerprints to the floor the crayon is drawn on.
|
||||
if(uses)
|
||||
uses--
|
||||
if(!uses)
|
||||
to_chat(user, "<span class='warning'>You used up your crayon!</span>")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/pen/crayon/attack(mob/living/M as mob, mob/living/user as mob)
|
||||
if(M == user)
|
||||
to_chat(user, "You take a bite of the crayon and swallow it.")
|
||||
user.nutrition += 1
|
||||
user.reagents.add_reagent("crayon_dust",min(5,uses)/3)
|
||||
if(uses)
|
||||
uses -= 5
|
||||
if(uses <= 0)
|
||||
to_chat(user, "<span class='warning'>You ate your crayon!</span>")
|
||||
qdel(src)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/black
|
||||
icon_state = "markerblack"
|
||||
colour = "#2D2D2D"
|
||||
shadeColour = "#000000"
|
||||
colourName = "black"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/red
|
||||
icon_state = "markerred"
|
||||
colour = "#DA0000"
|
||||
shadeColour = "#810C0C"
|
||||
colourName = "red"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/orange
|
||||
icon_state = "markerorange"
|
||||
colour = "#FF9300"
|
||||
shadeColour = "#A55403"
|
||||
colourName = "orange"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/yellow
|
||||
icon_state = "markeryellow"
|
||||
colour = "#FFF200"
|
||||
shadeColour = "#886422"
|
||||
colourName = "yellow"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/green
|
||||
icon_state = "markergreen"
|
||||
colour = "#A8E61D"
|
||||
shadeColour = "#61840F"
|
||||
colourName = "green"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/blue
|
||||
icon_state = "markerblue"
|
||||
colour = "#00B7EF"
|
||||
shadeColour = "#0082A8"
|
||||
colourName = "blue"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/purple
|
||||
icon_state = "markerpurple"
|
||||
colour = "#DA00FF"
|
||||
shadeColour = "#810CFF"
|
||||
colourName = "purple"
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/mime
|
||||
icon_state = "markermime"
|
||||
desc = "A very sad-looking marker."
|
||||
colour = "#FFFFFF"
|
||||
shadeColour = "#000000"
|
||||
colourName = "mime"
|
||||
uses = 0
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/mime/attack_self(mob/living/user as mob) //inversion
|
||||
if(colour != "#FFFFFF" && shadeColour != "#000000")
|
||||
colour = "#FFFFFF"
|
||||
shadeColour = "#000000"
|
||||
to_chat(user, "You will now draw in white and black with this marker.")
|
||||
else
|
||||
colour = "#000000"
|
||||
shadeColour = "#FFFFFF"
|
||||
to_chat(user, "You will now draw in black and white with this marker.")
|
||||
return
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/rainbow
|
||||
icon_state = "markerrainbow"
|
||||
colour = "#FFF000"
|
||||
shadeColour = "#000FFF"
|
||||
colourName = "rainbow"
|
||||
uses = 0
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/rainbow/attack_self(mob/living/user as mob)
|
||||
colour = input(user, "Please select the main colour.", "Marker colour") as color
|
||||
shadeColour = input(user, "Please select the shade colour.", "Marker colour") as color
|
||||
return
|
||||
|
||||
/obj/item/weapon/pen/crayon/marker/attack(mob/living/M as mob, mob/living/user as mob)
|
||||
if(M == user)
|
||||
to_chat(user, "You take a bite of the marker and swallow it.")
|
||||
user.nutrition += 1
|
||||
user.reagents.add_reagent("marker_ink",6)
|
||||
if(uses)
|
||||
uses -= 5
|
||||
if(uses <= 0)
|
||||
to_chat(user, "<span class='warning'>You ate the marker!</span>")
|
||||
qdel(src)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/pen/crayon/attack_self(var/mob/user)
|
||||
return
|
||||
|
||||
@@ -1,185 +1,185 @@
|
||||
/obj/item/device/aicard
|
||||
name = "intelliCore"
|
||||
desc = "Used to preserve and transport an AI."
|
||||
icon = 'icons/obj/pda.dmi'
|
||||
icon_state = "aicard" // aicard-full
|
||||
item_state = "aicard"
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
slot_flags = SLOT_BELT
|
||||
show_messages = 0
|
||||
preserve_item = 1
|
||||
|
||||
var/flush = null
|
||||
origin_tech = list(TECH_DATA = 4, TECH_MATERIAL = 4)
|
||||
|
||||
var/mob/living/silicon/ai/carded_ai
|
||||
|
||||
/obj/item/device/aicard/attack(mob/living/silicon/decoy/M as mob, mob/user as mob)
|
||||
if (!istype (M, /mob/living/silicon/decoy))
|
||||
return ..()
|
||||
else
|
||||
M.death()
|
||||
to_chat(user, "<b>ERROR ERROR ERROR</b>")
|
||||
|
||||
/obj/item/device/aicard/attack_self(mob/user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/item/device/aicard/tgui_interact(mob/user, datum/tgui/ui = null, datum/tgui_state/custom_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "AICard", "[name]") // 600, 394
|
||||
ui.open()
|
||||
if(custom_state)
|
||||
ui.set_state(custom_state)
|
||||
|
||||
/obj/item/device/aicard/tgui_state(mob/user)
|
||||
return GLOB.tgui_inventory_state
|
||||
|
||||
/obj/item/device/aicard/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
|
||||
data["has_ai"] = carded_ai != null
|
||||
if(carded_ai)
|
||||
data["name"] = carded_ai.name
|
||||
data["integrity"] = carded_ai.hardware_integrity()
|
||||
data["backup_capacitor"] = carded_ai.backup_capacitor()
|
||||
data["radio"] = !carded_ai.aiRadio.disabledAi
|
||||
data["wireless"] = !carded_ai.control_disabled
|
||||
data["operational"] = carded_ai.stat != DEAD
|
||||
data["flushing"] = flush
|
||||
|
||||
var/laws[0]
|
||||
for(var/datum/ai_law/law in carded_ai.laws.all_laws())
|
||||
if(law in carded_ai.laws.ion_laws) // If we're an ion law, give it an ion index code
|
||||
laws.Add(ionnum() + ". " + law.law)
|
||||
else
|
||||
laws.Add(num2text(law.get_index()) + ". " + law.law)
|
||||
data["laws"] = laws
|
||||
data["has_laws"] = length(carded_ai.laws.all_laws())
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/device/aicard/tgui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
if(!carded_ai)
|
||||
return
|
||||
|
||||
var/user = usr
|
||||
switch(action)
|
||||
if("wipe")
|
||||
msg_admin_attack("[key_name_admin(user)] wiped [key_name_admin(AI)] with \the [src].")
|
||||
add_attack_logs(user,carded_ai,"Purged from AI Card")
|
||||
INVOKE_ASYNC(src, PROC_REF(wipe_ai))
|
||||
if("radio")
|
||||
carded_ai.aiRadio.disabledAi = !carded_ai.aiRadio.disabledAi
|
||||
to_chat(carded_ai, "<span class='warning'>Your Subspace Transceiver has been [carded_ai.aiRadio.disabledAi ? "disabled" : "enabled"]!</span>")
|
||||
to_chat(user, "<span class='notice'>You [carded_ai.aiRadio.disabledAi ? "disable" : "enable"] the AI's Subspace Transceiver.</span>")
|
||||
if("wireless")
|
||||
carded_ai.control_disabled = !carded_ai.control_disabled
|
||||
to_chat(carded_ai, "<span class='warning'>Your wireless interface has been [carded_ai.control_disabled ? "disabled" : "enabled"]!</span>")
|
||||
to_chat(user, "<span class='notice'>You [carded_ai.control_disabled ? "disable" : "enable"] the AI's wireless interface.</span>")
|
||||
if(carded_ai.control_disabled && carded_ai.deployed_shell)
|
||||
carded_ai.disconnect_shell("Disconnecting from remote shell due to [src] wireless access interface being disabled.")
|
||||
update_icon()
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/device/aicard/update_icon()
|
||||
cut_overlays()
|
||||
if(carded_ai)
|
||||
if (!carded_ai.control_disabled)
|
||||
add_overlay("aicard-on")
|
||||
if(carded_ai.stat)
|
||||
icon_state = "aicard-404"
|
||||
else
|
||||
icon_state = "aicard-full"
|
||||
else
|
||||
icon_state = "aicard"
|
||||
|
||||
/obj/item/device/aicard/proc/grab_ai(var/mob/living/silicon/ai/ai, var/mob/living/user)
|
||||
if(!ai.client && !ai.deployed_shell)
|
||||
to_chat(user, "<span class='danger'>ERROR:</span> AI [ai.name] is offline. Unable to transfer.")
|
||||
return 0
|
||||
|
||||
if(carded_ai)
|
||||
to_chat(user, "<span class='danger'>Transfer failed:</span> Existing AI found on remote device. Remove existing AI to install a new one.")
|
||||
return 0
|
||||
|
||||
if(!user.IsAdvancedToolUser() && isanimal(user))
|
||||
var/mob/living/simple_mob/S = user
|
||||
if(!S.IsHumanoidToolUser(src))
|
||||
return 0
|
||||
|
||||
user.visible_message("\The [user] starts transferring \the [ai] into \the [src]...", "You start transferring \the [ai] into \the [src]...")
|
||||
show_message(span("critical", "\The [user] is transferring you into \the [src]!"))
|
||||
|
||||
if(do_after(user, 100))
|
||||
if(carded_ai)
|
||||
to_chat(user, "<span class='danger'>Transfer failed:</span> Existing AI found on remote device. Remove existing AI to install a new one.")
|
||||
return 0
|
||||
if(istype(ai.loc, /turf/))
|
||||
new /obj/structure/AIcore/deactivated(get_turf(ai))
|
||||
|
||||
ai.carded = 1
|
||||
add_attack_logs(user,ai,"Extracted into AI Card")
|
||||
src.name = "[initial(name)] - [ai.name]"
|
||||
|
||||
ai.loc = src
|
||||
ai.destroy_eyeobj(src)
|
||||
ai.cancel_camera()
|
||||
ai.control_disabled = 1
|
||||
ai.aiRestorePowerRoutine = 0
|
||||
carded_ai = ai
|
||||
ai.disconnect_shell("Disconnected from remote shell due to core intelligence transfer.") //If the AI is controlling a borg, force the player back to core!
|
||||
|
||||
if(ai.client)
|
||||
to_chat(ai, "You have been transferred into a mobile core. Remote access lost.")
|
||||
if(user.client)
|
||||
to_chat(ai, "<span class='notice'><b>Transfer successful:</b></span> [ai.name] extracted from current device and placed within mobile core.")
|
||||
|
||||
ai.canmove = 1
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
/obj/item/device/aicard/proc/clear()
|
||||
if(carded_ai && istype(carded_ai.loc, /turf))
|
||||
carded_ai.canmove = 0
|
||||
carded_ai.carded = 0
|
||||
name = initial(name)
|
||||
carded_ai = null
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/aicard/see_emote(mob/living/M, text)
|
||||
if(carded_ai && carded_ai.client)
|
||||
var/rendered = "<span class='message'>[text]</span>"
|
||||
carded_ai.show_message(rendered, 2)
|
||||
..()
|
||||
|
||||
/obj/item/device/aicard/show_message(msg, type, alt, alt_type)
|
||||
if(carded_ai && carded_ai.client)
|
||||
var/rendered = "<span class='message'>[msg]</span>"
|
||||
carded_ai.show_message(rendered, type)
|
||||
..()
|
||||
|
||||
/obj/item/device/aicard/relaymove(var/mob/user, var/direction)
|
||||
if(user.stat || user.stunned)
|
||||
return
|
||||
var/obj/item/weapon/rig/rig = src.get_rig()
|
||||
if(istype(rig))
|
||||
rig.forced_move(direction, user)
|
||||
|
||||
/obj/item/device/aicard/proc/wipe_ai()
|
||||
var/mob/living/silicon/ai/AI = carded_ai
|
||||
flush = TRUE
|
||||
AI.suiciding = TRUE
|
||||
to_chat(AI, "Your power has been disabled!")
|
||||
while(AI && AI.stat != DEAD)
|
||||
// This is absolutely evil and I love it.
|
||||
if(AI.deployed_shell && prob(AI.oxyloss)) //You feel it creeping? Eventually will reach 100, resulting in the second half of the AI's remaining life being lonely.
|
||||
AI.disconnect_shell("Disconnecting from remote shell due to insufficent power.")
|
||||
AI.adjustOxyLoss(2)
|
||||
AI.updatehealth()
|
||||
sleep(10)
|
||||
flush = FALSE
|
||||
/obj/item/device/aicard
|
||||
name = "intelliCore"
|
||||
desc = "Used to preserve and transport an AI."
|
||||
icon = 'icons/obj/pda.dmi'
|
||||
icon_state = "aicard" // aicard-full
|
||||
item_state = "aicard"
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
slot_flags = SLOT_BELT
|
||||
show_messages = 0
|
||||
preserve_item = 1
|
||||
|
||||
var/flush = null
|
||||
origin_tech = list(TECH_DATA = 4, TECH_MATERIAL = 4)
|
||||
|
||||
var/mob/living/silicon/ai/carded_ai
|
||||
|
||||
/obj/item/device/aicard/attack(mob/living/silicon/decoy/M as mob, mob/user as mob)
|
||||
if (!istype (M, /mob/living/silicon/decoy))
|
||||
return ..()
|
||||
else
|
||||
M.death()
|
||||
to_chat(user, "<b>ERROR ERROR ERROR</b>")
|
||||
|
||||
/obj/item/device/aicard/attack_self(mob/user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/item/device/aicard/tgui_interact(mob/user, datum/tgui/ui = null, datum/tgui_state/custom_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "AICard", "[name]") // 600, 394
|
||||
ui.open()
|
||||
if(custom_state)
|
||||
ui.set_state(custom_state)
|
||||
|
||||
/obj/item/device/aicard/tgui_state(mob/user)
|
||||
return GLOB.tgui_inventory_state
|
||||
|
||||
/obj/item/device/aicard/tgui_data(mob/user)
|
||||
var/data[0]
|
||||
|
||||
data["has_ai"] = carded_ai != null
|
||||
if(carded_ai)
|
||||
data["name"] = carded_ai.name
|
||||
data["integrity"] = carded_ai.hardware_integrity()
|
||||
data["backup_capacitor"] = carded_ai.backup_capacitor()
|
||||
data["radio"] = !carded_ai.aiRadio.disabledAi
|
||||
data["wireless"] = !carded_ai.control_disabled
|
||||
data["operational"] = carded_ai.stat != DEAD
|
||||
data["flushing"] = flush
|
||||
|
||||
var/laws[0]
|
||||
for(var/datum/ai_law/law in carded_ai.laws.all_laws())
|
||||
if(law in carded_ai.laws.ion_laws) // If we're an ion law, give it an ion index code
|
||||
laws.Add(ionnum() + ". " + law.law)
|
||||
else
|
||||
laws.Add(num2text(law.get_index()) + ". " + law.law)
|
||||
data["laws"] = laws
|
||||
data["has_laws"] = length(carded_ai.laws.all_laws())
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/device/aicard/tgui_act(action, params)
|
||||
if(..())
|
||||
return TRUE
|
||||
|
||||
if(!carded_ai)
|
||||
return
|
||||
|
||||
var/user = usr
|
||||
switch(action)
|
||||
if("wipe")
|
||||
msg_admin_attack("[key_name_admin(user)] wiped [key_name_admin(AI)] with \the [src].")
|
||||
add_attack_logs(user,carded_ai,"Purged from AI Card")
|
||||
INVOKE_ASYNC(src, PROC_REF(wipe_ai))
|
||||
if("radio")
|
||||
carded_ai.aiRadio.disabledAi = !carded_ai.aiRadio.disabledAi
|
||||
to_chat(carded_ai, "<span class='warning'>Your Subspace Transceiver has been [carded_ai.aiRadio.disabledAi ? "disabled" : "enabled"]!</span>")
|
||||
to_chat(user, "<span class='notice'>You [carded_ai.aiRadio.disabledAi ? "disable" : "enable"] the AI's Subspace Transceiver.</span>")
|
||||
if("wireless")
|
||||
carded_ai.control_disabled = !carded_ai.control_disabled
|
||||
to_chat(carded_ai, "<span class='warning'>Your wireless interface has been [carded_ai.control_disabled ? "disabled" : "enabled"]!</span>")
|
||||
to_chat(user, "<span class='notice'>You [carded_ai.control_disabled ? "disable" : "enable"] the AI's wireless interface.</span>")
|
||||
if(carded_ai.control_disabled && carded_ai.deployed_shell)
|
||||
carded_ai.disconnect_shell("Disconnecting from remote shell due to [src] wireless access interface being disabled.")
|
||||
update_icon()
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/device/aicard/update_icon()
|
||||
cut_overlays()
|
||||
if(carded_ai)
|
||||
if (!carded_ai.control_disabled)
|
||||
add_overlay("aicard-on")
|
||||
if(carded_ai.stat)
|
||||
icon_state = "aicard-404"
|
||||
else
|
||||
icon_state = "aicard-full"
|
||||
else
|
||||
icon_state = "aicard"
|
||||
|
||||
/obj/item/device/aicard/proc/grab_ai(var/mob/living/silicon/ai/ai, var/mob/living/user)
|
||||
if(!ai.client && !ai.deployed_shell)
|
||||
to_chat(user, "<span class='danger'>ERROR:</span> AI [ai.name] is offline. Unable to transfer.")
|
||||
return 0
|
||||
|
||||
if(carded_ai)
|
||||
to_chat(user, "<span class='danger'>Transfer failed:</span> Existing AI found on remote device. Remove existing AI to install a new one.")
|
||||
return 0
|
||||
|
||||
if(!user.IsAdvancedToolUser() && isanimal(user))
|
||||
var/mob/living/simple_mob/S = user
|
||||
if(!S.IsHumanoidToolUser(src))
|
||||
return 0
|
||||
|
||||
user.visible_message("\The [user] starts transferring \the [ai] into \the [src]...", "You start transferring \the [ai] into \the [src]...")
|
||||
show_message(span("critical", "\The [user] is transferring you into \the [src]!"))
|
||||
|
||||
if(do_after(user, 100))
|
||||
if(carded_ai)
|
||||
to_chat(user, "<span class='danger'>Transfer failed:</span> Existing AI found on remote device. Remove existing AI to install a new one.")
|
||||
return 0
|
||||
if(istype(ai.loc, /turf/))
|
||||
new /obj/structure/AIcore/deactivated(get_turf(ai))
|
||||
|
||||
ai.carded = 1
|
||||
add_attack_logs(user,ai,"Extracted into AI Card")
|
||||
src.name = "[initial(name)] - [ai.name]"
|
||||
|
||||
ai.loc = src
|
||||
ai.destroy_eyeobj(src)
|
||||
ai.cancel_camera()
|
||||
ai.control_disabled = 1
|
||||
ai.aiRestorePowerRoutine = 0
|
||||
carded_ai = ai
|
||||
ai.disconnect_shell("Disconnected from remote shell due to core intelligence transfer.") //If the AI is controlling a borg, force the player back to core!
|
||||
|
||||
if(ai.client)
|
||||
to_chat(ai, "You have been transferred into a mobile core. Remote access lost.")
|
||||
if(user.client)
|
||||
to_chat(ai, "<span class='notice'><b>Transfer successful:</b></span> [ai.name] extracted from current device and placed within mobile core.")
|
||||
|
||||
ai.canmove = 1
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
/obj/item/device/aicard/proc/clear()
|
||||
if(carded_ai && istype(carded_ai.loc, /turf))
|
||||
carded_ai.canmove = 0
|
||||
carded_ai.carded = 0
|
||||
name = initial(name)
|
||||
carded_ai = null
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/aicard/see_emote(mob/living/M, text)
|
||||
if(carded_ai && carded_ai.client)
|
||||
var/rendered = "<span class='message'>[text]</span>"
|
||||
carded_ai.show_message(rendered, 2)
|
||||
..()
|
||||
|
||||
/obj/item/device/aicard/show_message(msg, type, alt, alt_type)
|
||||
if(carded_ai && carded_ai.client)
|
||||
var/rendered = "<span class='message'>[msg]</span>"
|
||||
carded_ai.show_message(rendered, type)
|
||||
..()
|
||||
|
||||
/obj/item/device/aicard/relaymove(var/mob/user, var/direction)
|
||||
if(user.stat || user.stunned)
|
||||
return
|
||||
var/obj/item/weapon/rig/rig = src.get_rig()
|
||||
if(istype(rig))
|
||||
rig.forced_move(direction, user)
|
||||
|
||||
/obj/item/device/aicard/proc/wipe_ai()
|
||||
var/mob/living/silicon/ai/AI = carded_ai
|
||||
flush = TRUE
|
||||
AI.suiciding = TRUE
|
||||
to_chat(AI, "Your power has been disabled!")
|
||||
while(AI && AI.stat != DEAD)
|
||||
// This is absolutely evil and I love it.
|
||||
if(AI.deployed_shell && prob(AI.oxyloss)) //You feel it creeping? Eventually will reach 100, resulting in the second half of the AI's remaining life being lonely.
|
||||
AI.disconnect_shell("Disconnecting from remote shell due to insufficent power.")
|
||||
AI.adjustOxyLoss(2)
|
||||
AI.updatehealth()
|
||||
sleep(10)
|
||||
flush = FALSE
|
||||
|
||||
@@ -1,147 +1,147 @@
|
||||
/obj/item/device/chameleon
|
||||
name = "chameleon projector"
|
||||
icon_state = "shield0"
|
||||
slot_flags = SLOT_BELT
|
||||
item_state = "electronic"
|
||||
throwforce = 5.0
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_SMALL
|
||||
origin_tech = list(TECH_ILLEGAL = 4, TECH_MAGNET = 4)
|
||||
var/can_use = 1
|
||||
var/obj/effect/dummy/chameleon/active_dummy = null
|
||||
var/saved_item = /obj/item/trash/cigbutt
|
||||
var/saved_icon = 'icons/inventory/face/item.dmi'
|
||||
var/saved_icon_state = "cigbutt"
|
||||
var/saved_overlays
|
||||
|
||||
/obj/item/device/chameleon/dropped()
|
||||
disrupt()
|
||||
..()
|
||||
|
||||
/obj/item/device/chameleon/equipped()
|
||||
..()
|
||||
disrupt()
|
||||
..()
|
||||
|
||||
/obj/item/device/chameleon/attack_self()
|
||||
toggle()
|
||||
|
||||
/obj/item/device/chameleon/afterattack(atom/target, mob/user , proximity)
|
||||
if(!proximity) return
|
||||
if(!active_dummy)
|
||||
if(istype(target,/obj/item) && !istype(target, /obj/item/weapon/disk/nuclear))
|
||||
playsound(src, 'sound/weapons/flash.ogg', 100, 1, -6)
|
||||
to_chat(user, "<span class='notice'>Scanned [target].</span>")
|
||||
saved_item = target.type
|
||||
saved_icon = target.icon
|
||||
saved_icon_state = target.icon_state
|
||||
saved_overlays = target.overlays
|
||||
|
||||
/obj/item/device/chameleon/proc/toggle()
|
||||
if(!can_use || !saved_item) return
|
||||
if(active_dummy)
|
||||
eject_all()
|
||||
playsound(src, 'sound/effects/pop.ogg', 100, 1, -6)
|
||||
qdel(active_dummy)
|
||||
active_dummy = null
|
||||
to_chat(usr, "<span class='notice'>You deactivate the [src].</span>")
|
||||
var/obj/effect/overlay/T = new /obj/effect/overlay(get_turf(src))
|
||||
T.icon = 'icons/effects/effects.dmi'
|
||||
flick("emppulse",T)
|
||||
spawn(8) qdel(T)
|
||||
else
|
||||
playsound(src, 'sound/effects/pop.ogg', 100, 1, -6)
|
||||
var/obj/O = new saved_item(src)
|
||||
if(!O) return
|
||||
var/obj/effect/dummy/chameleon/C = new /obj/effect/dummy/chameleon(usr.loc)
|
||||
C.activate(O, usr, saved_icon, saved_icon_state, saved_overlays, src)
|
||||
qdel(O)
|
||||
to_chat(usr, "<span class='notice'>You activate the [src].</span>")
|
||||
var/obj/effect/overlay/T = new/obj/effect/overlay(get_turf(src))
|
||||
T.icon = 'icons/effects/effects.dmi'
|
||||
flick("emppulse",T)
|
||||
spawn(8) qdel(T)
|
||||
|
||||
/obj/item/device/chameleon/proc/disrupt(var/delete_dummy = 1)
|
||||
if(active_dummy)
|
||||
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
spark_system.start()
|
||||
eject_all()
|
||||
if(delete_dummy)
|
||||
qdel(active_dummy)
|
||||
active_dummy = null
|
||||
can_use = 0
|
||||
spawn(50) can_use = 1
|
||||
|
||||
/obj/item/device/chameleon/proc/eject_all()
|
||||
for(var/atom/movable/A in active_dummy)
|
||||
A.loc = active_dummy.loc
|
||||
if(ismob(A))
|
||||
var/mob/M = A
|
||||
M.reset_view(null)
|
||||
|
||||
/obj/effect/dummy/chameleon
|
||||
name = ""
|
||||
desc = ""
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
var/can_move = 1
|
||||
var/obj/item/device/chameleon/master = null
|
||||
|
||||
/obj/effect/dummy/chameleon/proc/activate(var/obj/O, var/mob/M, new_icon, new_iconstate, new_overlays, var/obj/item/device/chameleon/C)
|
||||
name = O.name
|
||||
desc = O.desc
|
||||
icon = new_icon
|
||||
icon_state = new_iconstate
|
||||
overlays = new_overlays
|
||||
set_dir(O.dir)
|
||||
M.loc = src
|
||||
master = C
|
||||
master.active_dummy = src
|
||||
|
||||
/obj/effect/dummy/chameleon/attackby()
|
||||
for(var/mob/M in src)
|
||||
to_chat(M, "<span class='warning'>Your chameleon-projector deactivates.</span>")
|
||||
master.disrupt()
|
||||
|
||||
/obj/effect/dummy/chameleon/attack_hand()
|
||||
for(var/mob/M in src)
|
||||
to_chat(M, "<span class='warning'>Your chameleon-projector deactivates.</span>")
|
||||
master.disrupt()
|
||||
|
||||
/obj/effect/dummy/chameleon/ex_act()
|
||||
for(var/mob/M in src)
|
||||
to_chat(M, "<span class='warning'>Your chameleon-projector deactivates.</span>")
|
||||
master.disrupt()
|
||||
|
||||
/obj/effect/dummy/chameleon/bullet_act()
|
||||
for(var/mob/M in src)
|
||||
to_chat(M, "<span class='warning'>Your chameleon-projector deactivates.</span>")
|
||||
..()
|
||||
master.disrupt()
|
||||
|
||||
/obj/effect/dummy/chameleon/relaymove(var/mob/user, direction)
|
||||
if(istype(loc, /turf/space)) return //No magical space movement!
|
||||
|
||||
if(can_move)
|
||||
can_move = 0
|
||||
switch(user.bodytemperature)
|
||||
if(300 to INFINITY)
|
||||
spawn(10) can_move = 1
|
||||
if(295 to 300)
|
||||
spawn(13) can_move = 1
|
||||
if(280 to 295)
|
||||
spawn(16) can_move = 1
|
||||
if(260 to 280)
|
||||
spawn(20) can_move = 1
|
||||
else
|
||||
spawn(25) can_move = 1
|
||||
step(src, direction)
|
||||
return
|
||||
|
||||
/obj/effect/dummy/chameleon/Destroy()
|
||||
master.disrupt(0)
|
||||
..()
|
||||
/obj/item/device/chameleon
|
||||
name = "chameleon projector"
|
||||
icon_state = "shield0"
|
||||
slot_flags = SLOT_BELT
|
||||
item_state = "electronic"
|
||||
throwforce = 5.0
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_SMALL
|
||||
origin_tech = list(TECH_ILLEGAL = 4, TECH_MAGNET = 4)
|
||||
var/can_use = 1
|
||||
var/obj/effect/dummy/chameleon/active_dummy = null
|
||||
var/saved_item = /obj/item/trash/cigbutt
|
||||
var/saved_icon = 'icons/inventory/face/item.dmi'
|
||||
var/saved_icon_state = "cigbutt"
|
||||
var/saved_overlays
|
||||
|
||||
/obj/item/device/chameleon/dropped()
|
||||
disrupt()
|
||||
..()
|
||||
|
||||
/obj/item/device/chameleon/equipped()
|
||||
..()
|
||||
disrupt()
|
||||
..()
|
||||
|
||||
/obj/item/device/chameleon/attack_self()
|
||||
toggle()
|
||||
|
||||
/obj/item/device/chameleon/afterattack(atom/target, mob/user , proximity)
|
||||
if(!proximity) return
|
||||
if(!active_dummy)
|
||||
if(istype(target,/obj/item) && !istype(target, /obj/item/weapon/disk/nuclear))
|
||||
playsound(src, 'sound/weapons/flash.ogg', 100, 1, -6)
|
||||
to_chat(user, "<span class='notice'>Scanned [target].</span>")
|
||||
saved_item = target.type
|
||||
saved_icon = target.icon
|
||||
saved_icon_state = target.icon_state
|
||||
saved_overlays = target.overlays
|
||||
|
||||
/obj/item/device/chameleon/proc/toggle()
|
||||
if(!can_use || !saved_item) return
|
||||
if(active_dummy)
|
||||
eject_all()
|
||||
playsound(src, 'sound/effects/pop.ogg', 100, 1, -6)
|
||||
qdel(active_dummy)
|
||||
active_dummy = null
|
||||
to_chat(usr, "<span class='notice'>You deactivate the [src].</span>")
|
||||
var/obj/effect/overlay/T = new /obj/effect/overlay(get_turf(src))
|
||||
T.icon = 'icons/effects/effects.dmi'
|
||||
flick("emppulse",T)
|
||||
spawn(8) qdel(T)
|
||||
else
|
||||
playsound(src, 'sound/effects/pop.ogg', 100, 1, -6)
|
||||
var/obj/O = new saved_item(src)
|
||||
if(!O) return
|
||||
var/obj/effect/dummy/chameleon/C = new /obj/effect/dummy/chameleon(usr.loc)
|
||||
C.activate(O, usr, saved_icon, saved_icon_state, saved_overlays, src)
|
||||
qdel(O)
|
||||
to_chat(usr, "<span class='notice'>You activate the [src].</span>")
|
||||
var/obj/effect/overlay/T = new/obj/effect/overlay(get_turf(src))
|
||||
T.icon = 'icons/effects/effects.dmi'
|
||||
flick("emppulse",T)
|
||||
spawn(8) qdel(T)
|
||||
|
||||
/obj/item/device/chameleon/proc/disrupt(var/delete_dummy = 1)
|
||||
if(active_dummy)
|
||||
var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
spark_system.start()
|
||||
eject_all()
|
||||
if(delete_dummy)
|
||||
qdel(active_dummy)
|
||||
active_dummy = null
|
||||
can_use = 0
|
||||
spawn(50) can_use = 1
|
||||
|
||||
/obj/item/device/chameleon/proc/eject_all()
|
||||
for(var/atom/movable/A in active_dummy)
|
||||
A.loc = active_dummy.loc
|
||||
if(ismob(A))
|
||||
var/mob/M = A
|
||||
M.reset_view(null)
|
||||
|
||||
/obj/effect/dummy/chameleon
|
||||
name = ""
|
||||
desc = ""
|
||||
density = FALSE
|
||||
anchored = TRUE
|
||||
var/can_move = 1
|
||||
var/obj/item/device/chameleon/master = null
|
||||
|
||||
/obj/effect/dummy/chameleon/proc/activate(var/obj/O, var/mob/M, new_icon, new_iconstate, new_overlays, var/obj/item/device/chameleon/C)
|
||||
name = O.name
|
||||
desc = O.desc
|
||||
icon = new_icon
|
||||
icon_state = new_iconstate
|
||||
overlays = new_overlays
|
||||
set_dir(O.dir)
|
||||
M.loc = src
|
||||
master = C
|
||||
master.active_dummy = src
|
||||
|
||||
/obj/effect/dummy/chameleon/attackby()
|
||||
for(var/mob/M in src)
|
||||
to_chat(M, "<span class='warning'>Your chameleon-projector deactivates.</span>")
|
||||
master.disrupt()
|
||||
|
||||
/obj/effect/dummy/chameleon/attack_hand()
|
||||
for(var/mob/M in src)
|
||||
to_chat(M, "<span class='warning'>Your chameleon-projector deactivates.</span>")
|
||||
master.disrupt()
|
||||
|
||||
/obj/effect/dummy/chameleon/ex_act()
|
||||
for(var/mob/M in src)
|
||||
to_chat(M, "<span class='warning'>Your chameleon-projector deactivates.</span>")
|
||||
master.disrupt()
|
||||
|
||||
/obj/effect/dummy/chameleon/bullet_act()
|
||||
for(var/mob/M in src)
|
||||
to_chat(M, "<span class='warning'>Your chameleon-projector deactivates.</span>")
|
||||
..()
|
||||
master.disrupt()
|
||||
|
||||
/obj/effect/dummy/chameleon/relaymove(var/mob/user, direction)
|
||||
if(istype(loc, /turf/space)) return //No magical space movement!
|
||||
|
||||
if(can_move)
|
||||
can_move = 0
|
||||
switch(user.bodytemperature)
|
||||
if(300 to INFINITY)
|
||||
spawn(10) can_move = 1
|
||||
if(295 to 300)
|
||||
spawn(13) can_move = 1
|
||||
if(280 to 295)
|
||||
spawn(16) can_move = 1
|
||||
if(260 to 280)
|
||||
spawn(20) can_move = 1
|
||||
else
|
||||
spawn(25) can_move = 1
|
||||
step(src, direction)
|
||||
return
|
||||
|
||||
/obj/effect/dummy/chameleon/Destroy()
|
||||
master.disrupt(0)
|
||||
..()
|
||||
|
||||
@@ -1,97 +1,97 @@
|
||||
/obj/item/device/communicator/proc/analyze_air()
|
||||
var/list/results = list()
|
||||
var/turf/T = get_turf(src.loc)
|
||||
if(!isnull(T))
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
var/pressure = environment.return_pressure()
|
||||
var/total_moles = environment.total_moles
|
||||
if (total_moles)
|
||||
var/o2_level = environment.gas["oxygen"]/total_moles
|
||||
var/n2_level = environment.gas["nitrogen"]/total_moles
|
||||
var/co2_level = environment.gas["carbon_dioxide"]/total_moles
|
||||
var/phoron_level = environment.gas["phoron"]/total_moles
|
||||
var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level)
|
||||
|
||||
// Label is what the entry is describing
|
||||
// Type identifies which unit or other special characters to use
|
||||
// Val is the information reported
|
||||
// Bad_high/_low are the values outside of which the entry reports as dangerous
|
||||
// Poor_high/_low are the values outside of which the entry reports as unideal
|
||||
// Values were extracted from the template itself
|
||||
results = list(
|
||||
list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80),
|
||||
list("entry" = "Temperature", "units" = "\u00B0" + "C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5),
|
||||
list("entry" = "Oxygen", "units" = "kPa", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17),
|
||||
list("entry" = "Nitrogen", "units" = "kPa", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40),
|
||||
list("entry" = "Carbon Dioxide", "units" = "kPa", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0),
|
||||
list("entry" = "Phoron", "units" = "kPa", "val" = "[round(phoron_level*100,0.01)]", "bad_high" = 0.5, "poor_high" = 0, "poor_low" = 0, "bad_low" = 0),
|
||||
list("entry" = "Other", "units" = "kPa", "val" = "[round(unknown_level, 0.01)]", "bad_high" = 1, "poor_high" = 0.5, "poor_low" = 0, "bad_low" = 0)
|
||||
)
|
||||
|
||||
if(isnull(results))
|
||||
results = list(list("entry" = "pressure", "units" = "kPa", "val" = "0", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80))
|
||||
return results
|
||||
|
||||
|
||||
// Proc - compile_news()
|
||||
// Parameters - none
|
||||
// Description - Returns the list of newsfeeds, compiled for template processing
|
||||
/obj/item/device/communicator/proc/compile_news()
|
||||
var/list/feeds = list()
|
||||
for(var/datum/feed_channel/channel in news_network.network_channels)
|
||||
var/list/messages = list()
|
||||
if(!channel.censored && channel.channel_name != "Vir News Network") //Do not load the 'IC news' channel as it is simply too long.
|
||||
var/index = 0
|
||||
for(var/datum/feed_message/FM in channel.messages)
|
||||
index++
|
||||
var/list/msgdata = list(
|
||||
"author" = FM.author,
|
||||
"body" = FM.body,
|
||||
"img" = null,
|
||||
"message_type" = FM.message_type,
|
||||
"time_stamp" = FM.time_stamp,
|
||||
"caption" = FM.caption,
|
||||
"index" = index
|
||||
)
|
||||
if(FM.img)
|
||||
msgdata["img"] = icon2base64(FM.img)
|
||||
messages[++messages.len] = msgdata
|
||||
|
||||
feeds[++feeds.len] = list(
|
||||
"name" = channel.channel_name,
|
||||
"censored" = channel.censored,
|
||||
"author" = channel.author,
|
||||
"messages" = messages,
|
||||
"index" = feeds.len + 1 // actually align them, since I guess the population of the list doesn't occur until after the evaluation of the new entry's contents
|
||||
)
|
||||
return feeds
|
||||
|
||||
// Proc - get_recent_news()
|
||||
// Parameters - none
|
||||
// Description - Returns the latest three newscasts, compiled for template processing
|
||||
/obj/item/device/communicator/proc/get_recent_news()
|
||||
var/list/news = list()
|
||||
|
||||
// Compile all the newscasts
|
||||
for(var/datum/feed_channel/channel in news_network.network_channels)
|
||||
if(!channel.censored)
|
||||
for(var/datum/feed_message/FM in channel.messages)
|
||||
var/body = replacetext(FM.body, "\n", "<br>")
|
||||
news[++news.len] = list(
|
||||
"channel" = channel.channel_name,
|
||||
"author" = FM.author,
|
||||
"body" = body,
|
||||
"message_type" = FM.message_type,
|
||||
"time_stamp" = FM.time_stamp,
|
||||
"has_image" = (FM.img != null),
|
||||
"caption" = FM.caption,
|
||||
"time" = FM.post_time
|
||||
)
|
||||
|
||||
// Cut out all but the youngest three
|
||||
if(news.len > 3)
|
||||
sortByKey(news, "time")
|
||||
news.Cut(1, news.len - 2) // Last three have largest timestamps, youngest posts
|
||||
news.Swap(1, 3) // List is sorted in ascending order of timestamp, we want descending
|
||||
|
||||
return news
|
||||
/obj/item/device/communicator/proc/analyze_air()
|
||||
var/list/results = list()
|
||||
var/turf/T = get_turf(src.loc)
|
||||
if(!isnull(T))
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
var/pressure = environment.return_pressure()
|
||||
var/total_moles = environment.total_moles
|
||||
if (total_moles)
|
||||
var/o2_level = environment.gas["oxygen"]/total_moles
|
||||
var/n2_level = environment.gas["nitrogen"]/total_moles
|
||||
var/co2_level = environment.gas["carbon_dioxide"]/total_moles
|
||||
var/phoron_level = environment.gas["phoron"]/total_moles
|
||||
var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level)
|
||||
|
||||
// Label is what the entry is describing
|
||||
// Type identifies which unit or other special characters to use
|
||||
// Val is the information reported
|
||||
// Bad_high/_low are the values outside of which the entry reports as dangerous
|
||||
// Poor_high/_low are the values outside of which the entry reports as unideal
|
||||
// Values were extracted from the template itself
|
||||
results = list(
|
||||
list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80),
|
||||
list("entry" = "Temperature", "units" = "\u00B0" + "C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5),
|
||||
list("entry" = "Oxygen", "units" = "kPa", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17),
|
||||
list("entry" = "Nitrogen", "units" = "kPa", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40),
|
||||
list("entry" = "Carbon Dioxide", "units" = "kPa", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0),
|
||||
list("entry" = "Phoron", "units" = "kPa", "val" = "[round(phoron_level*100,0.01)]", "bad_high" = 0.5, "poor_high" = 0, "poor_low" = 0, "bad_low" = 0),
|
||||
list("entry" = "Other", "units" = "kPa", "val" = "[round(unknown_level, 0.01)]", "bad_high" = 1, "poor_high" = 0.5, "poor_low" = 0, "bad_low" = 0)
|
||||
)
|
||||
|
||||
if(isnull(results))
|
||||
results = list(list("entry" = "pressure", "units" = "kPa", "val" = "0", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80))
|
||||
return results
|
||||
|
||||
|
||||
// Proc - compile_news()
|
||||
// Parameters - none
|
||||
// Description - Returns the list of newsfeeds, compiled for template processing
|
||||
/obj/item/device/communicator/proc/compile_news()
|
||||
var/list/feeds = list()
|
||||
for(var/datum/feed_channel/channel in news_network.network_channels)
|
||||
var/list/messages = list()
|
||||
if(!channel.censored && channel.channel_name != "Vir News Network") //Do not load the 'IC news' channel as it is simply too long.
|
||||
var/index = 0
|
||||
for(var/datum/feed_message/FM in channel.messages)
|
||||
index++
|
||||
var/list/msgdata = list(
|
||||
"author" = FM.author,
|
||||
"body" = FM.body,
|
||||
"img" = null,
|
||||
"message_type" = FM.message_type,
|
||||
"time_stamp" = FM.time_stamp,
|
||||
"caption" = FM.caption,
|
||||
"index" = index
|
||||
)
|
||||
if(FM.img)
|
||||
msgdata["img"] = icon2base64(FM.img)
|
||||
messages[++messages.len] = msgdata
|
||||
|
||||
feeds[++feeds.len] = list(
|
||||
"name" = channel.channel_name,
|
||||
"censored" = channel.censored,
|
||||
"author" = channel.author,
|
||||
"messages" = messages,
|
||||
"index" = feeds.len + 1 // actually align them, since I guess the population of the list doesn't occur until after the evaluation of the new entry's contents
|
||||
)
|
||||
return feeds
|
||||
|
||||
// Proc - get_recent_news()
|
||||
// Parameters - none
|
||||
// Description - Returns the latest three newscasts, compiled for template processing
|
||||
/obj/item/device/communicator/proc/get_recent_news()
|
||||
var/list/news = list()
|
||||
|
||||
// Compile all the newscasts
|
||||
for(var/datum/feed_channel/channel in news_network.network_channels)
|
||||
if(!channel.censored)
|
||||
for(var/datum/feed_message/FM in channel.messages)
|
||||
var/body = replacetext(FM.body, "\n", "<br>")
|
||||
news[++news.len] = list(
|
||||
"channel" = channel.channel_name,
|
||||
"author" = FM.author,
|
||||
"body" = body,
|
||||
"message_type" = FM.message_type,
|
||||
"time_stamp" = FM.time_stamp,
|
||||
"has_image" = (FM.img != null),
|
||||
"caption" = FM.caption,
|
||||
"time" = FM.post_time
|
||||
)
|
||||
|
||||
// Cut out all but the youngest three
|
||||
if(news.len > 3)
|
||||
sortByKey(news, "time")
|
||||
news.Cut(1, news.len - 2) // Last three have largest timestamps, youngest posts
|
||||
news.Swap(1, 3) // List is sorted in ascending order of timestamp, we want descending
|
||||
|
||||
return news
|
||||
|
||||
@@ -1,185 +1,185 @@
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 4 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received,
|
||||
// text - message text to send if message is of type "text")
|
||||
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response and IM function.
|
||||
/obj/item/device/communicator/receive_exonet_message(var/atom/origin_atom, origin_address, message, text)
|
||||
if(message == "voice")
|
||||
if(isobserver(origin_atom) || istype(origin_atom, /obj/item/device/communicator))
|
||||
if(origin_atom in voice_invites)
|
||||
var/user = null
|
||||
if(ismob(origin_atom.loc))
|
||||
user = origin_atom.loc
|
||||
open_connection(user, origin_atom)
|
||||
return
|
||||
else if(origin_atom in voice_requests)
|
||||
return //Spam prevention
|
||||
else
|
||||
request(origin_atom)
|
||||
if(message == "ping")
|
||||
if(network_visibility)
|
||||
var/random = rand(200,350)
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
if(message == "text")
|
||||
request_im(origin_atom, origin_address, text)
|
||||
return
|
||||
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 3 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received)
|
||||
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response.
|
||||
/mob/observer/dead/receive_exonet_message(origin_atom, origin_address, message, text)
|
||||
if(message == "voice")
|
||||
if(istype(origin_atom, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = origin_atom
|
||||
if(src in comm.voice_invites)
|
||||
comm.open_connection(src)
|
||||
return
|
||||
to_chat(src, "<span class='notice'>\icon[origin_atom][bicon(origin_atom)] Receiving communicator request from [origin_atom]. To answer, use the <b>Call Communicator</b> \
|
||||
verb, and select that name to answer the call.</span>")
|
||||
src << 'sound/machines/defib_SafetyOn.ogg'
|
||||
comm.voice_invites |= src
|
||||
if(message == "ping")
|
||||
if(client && client.prefs.communicator_visibility)
|
||||
var/random = rand(450,700)
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
if(message == "text")
|
||||
to_chat(src, "<span class='notice'>\icon[origin_atom][bicon(origin_atom)] Received text message from [origin_atom]: <b>\"[text]\"</b></span>")
|
||||
src << 'sound/machines/defib_safetyOff.ogg'
|
||||
exonet_messages.Add("<b>From [origin_atom]:</b><br>[text]")
|
||||
return
|
||||
|
||||
// Proc: request_im()
|
||||
// Parameters: 3 (candidate - the communicator wanting to message the device, origin_address - the address of the sender, text - the message)
|
||||
// Description: Response to a communicator trying to message the device.
|
||||
// Adds them to the list of people that have messaged this device and adds the message to the message list.
|
||||
/obj/item/device/communicator/proc/request_im(var/atom/candidate, var/origin_address, var/text)
|
||||
var/who = null
|
||||
if(isobserver(candidate))
|
||||
var/mob/observer/dead/ghost = candidate
|
||||
who = ghost.name
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
who = comm.owner
|
||||
comm.im_contacts |= src
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else if(istype(candidate, /obj/item/integrated_circuit))
|
||||
var/obj/item/integrated_circuit/CIRC = candidate
|
||||
who = CIRC
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else return
|
||||
|
||||
im_contacts |= candidate
|
||||
|
||||
if(!who)
|
||||
return
|
||||
|
||||
if(ringer)
|
||||
var/S
|
||||
if(ttone in ttone_sound)
|
||||
S = ttone_sound[ttone]
|
||||
else
|
||||
S = 'sound/machines/twobeep.ogg'
|
||||
|
||||
playsound(src, S, 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src][bicon(src)] *[ttone]*"))
|
||||
|
||||
alert_called = 1
|
||||
update_icon()
|
||||
|
||||
//Search for holder of the device.
|
||||
var/mob/living/L = null
|
||||
if(loc && isliving(loc))
|
||||
L = loc
|
||||
|
||||
if(L)
|
||||
to_chat(L, "<span class='notice'>\icon[src][bicon(src)] Message from [who]: <b>\"[text]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[candidate]'>Reply</a>)</span>")
|
||||
|
||||
// This is the only Topic the communicators really uses
|
||||
/obj/item/device/communicator/Topic(href, href_list)
|
||||
switch(href_list["action"])
|
||||
if("Reply")
|
||||
var/obj/item/device/communicator/comm = locate(href_list["target"])
|
||||
var/message = tgui_input_text(usr, "Enter your message below.", "Reply")
|
||||
|
||||
if(message)
|
||||
exonet.send_message(comm.exonet.address, "text", message)
|
||||
im_list += list(list("address" = exonet.address, "to_address" = comm.exonet.address, "im" = message))
|
||||
log_pda("(COMM: [src]) sent \"[message]\" to [exonet.get_atom_from_address(comm.exonet.address)]", usr)
|
||||
to_chat(usr, "<span class='notice'>\icon[src][bicon(src)] Sent message to [istype(comm, /obj/item/device/communicator) ? comm.owner : comm.name], <b>\"[message]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[exonet.get_atom_from_address(comm.exonet.address)]'>Reply</a>)</span>")
|
||||
|
||||
// Verb: text_communicator()
|
||||
// Parameters: None
|
||||
// Description: Allows a ghost to send a text message to a communicator.
|
||||
/mob/observer/dead/verb/text_communicator()
|
||||
set category = "Ghost"
|
||||
set name = "Text Communicator"
|
||||
set desc = "If there is a communicator available, send a text message to it."
|
||||
|
||||
if(ticker.current_state < GAME_STATE_PLAYING)
|
||||
to_chat(src, "<span class='danger'>The game hasn't started yet!</span>")
|
||||
return
|
||||
|
||||
if (!src.stat)
|
||||
return
|
||||
|
||||
if (usr != src)
|
||||
return //something is terribly wrong
|
||||
|
||||
for(var/mob/living/L in mob_list) //Simple check so you don't have dead people calling.
|
||||
if(src.client.prefs.real_name == L.real_name)
|
||||
to_chat(src, "<span class='danger'>Your identity is already present in the game world. Please load in a different character first.</span>")
|
||||
return
|
||||
|
||||
var/obj/machinery/exonet_node/E = get_exonet_node()
|
||||
if(!E || !E.on || !E.allow_external_communicators)
|
||||
to_chat(src, "<span class='danger'>The Exonet node at telecommunications is down at the moment, or is actively blocking you, \
|
||||
so your call can't go through.</span>")
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/obj/item/device/communicator/comm in all_communicators)
|
||||
if(!comm.network_visibility || !comm.exonet || !comm.exonet.address)
|
||||
continue
|
||||
choices.Add(comm)
|
||||
|
||||
if(!choices.len)
|
||||
to_chat(src, "<span class='danger'>There are no available communicators, sorry.</span>")
|
||||
return
|
||||
|
||||
var/choice = tgui_input_list(src,"Send a text message to whom?", "Recipient Choice", choices)
|
||||
if(choice)
|
||||
var/obj/item/device/communicator/chosen_communicator = choice
|
||||
var/mob/observer/dead/O = src
|
||||
var/text_message = sanitize(tgui_input_text(src, "What do you want the message to say?", multiline = TRUE))
|
||||
if(text_message && O.exonet)
|
||||
O.exonet.send_message(chosen_communicator.exonet.address, "text", text_message)
|
||||
|
||||
to_chat(src, "<span class='notice'>You have sent '[text_message]' to [chosen_communicator].</span>")
|
||||
exonet_messages.Add("<b>To [chosen_communicator]:</b><br>[text_message]")
|
||||
log_pda("(DCOMM: [src]) sent \"[text_message]\" to [chosen_communicator]", src)
|
||||
for(var/mob/M in player_list)
|
||||
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
|
||||
if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat)
|
||||
continue
|
||||
if(M == src)
|
||||
continue
|
||||
M.show_message("Comm IM - [src] -> [chosen_communicator]: [text_message]")
|
||||
|
||||
|
||||
|
||||
// Verb: show_text_messages()
|
||||
// Parameters: None
|
||||
// Description: Lets ghosts review messages they've sent or received.
|
||||
/mob/observer/dead/verb/show_text_messages()
|
||||
set category = "Ghost"
|
||||
set name = "Show Text Messages"
|
||||
set desc = "Allows you to see exonet text messages you've sent and received."
|
||||
|
||||
var/HTML = "<html><head><title>Exonet Message Log</title></head><body>"
|
||||
for(var/line in exonet_messages)
|
||||
HTML += line + "<br>"
|
||||
HTML +="</body></html>"
|
||||
usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0")
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 4 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received,
|
||||
// text - message text to send if message is of type "text")
|
||||
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response and IM function.
|
||||
/obj/item/device/communicator/receive_exonet_message(var/atom/origin_atom, origin_address, message, text)
|
||||
if(message == "voice")
|
||||
if(isobserver(origin_atom) || istype(origin_atom, /obj/item/device/communicator))
|
||||
if(origin_atom in voice_invites)
|
||||
var/user = null
|
||||
if(ismob(origin_atom.loc))
|
||||
user = origin_atom.loc
|
||||
open_connection(user, origin_atom)
|
||||
return
|
||||
else if(origin_atom in voice_requests)
|
||||
return //Spam prevention
|
||||
else
|
||||
request(origin_atom)
|
||||
if(message == "ping")
|
||||
if(network_visibility)
|
||||
var/random = rand(200,350)
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
if(message == "text")
|
||||
request_im(origin_atom, origin_address, text)
|
||||
return
|
||||
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 3 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received)
|
||||
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response.
|
||||
/mob/observer/dead/receive_exonet_message(origin_atom, origin_address, message, text)
|
||||
if(message == "voice")
|
||||
if(istype(origin_atom, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = origin_atom
|
||||
if(src in comm.voice_invites)
|
||||
comm.open_connection(src)
|
||||
return
|
||||
to_chat(src, "<span class='notice'>\icon[origin_atom][bicon(origin_atom)] Receiving communicator request from [origin_atom]. To answer, use the <b>Call Communicator</b> \
|
||||
verb, and select that name to answer the call.</span>")
|
||||
src << 'sound/machines/defib_SafetyOn.ogg'
|
||||
comm.voice_invites |= src
|
||||
if(message == "ping")
|
||||
if(client && client.prefs.communicator_visibility)
|
||||
var/random = rand(450,700)
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
if(message == "text")
|
||||
to_chat(src, "<span class='notice'>\icon[origin_atom][bicon(origin_atom)] Received text message from [origin_atom]: <b>\"[text]\"</b></span>")
|
||||
src << 'sound/machines/defib_safetyOff.ogg'
|
||||
exonet_messages.Add("<b>From [origin_atom]:</b><br>[text]")
|
||||
return
|
||||
|
||||
// Proc: request_im()
|
||||
// Parameters: 3 (candidate - the communicator wanting to message the device, origin_address - the address of the sender, text - the message)
|
||||
// Description: Response to a communicator trying to message the device.
|
||||
// Adds them to the list of people that have messaged this device and adds the message to the message list.
|
||||
/obj/item/device/communicator/proc/request_im(var/atom/candidate, var/origin_address, var/text)
|
||||
var/who = null
|
||||
if(isobserver(candidate))
|
||||
var/mob/observer/dead/ghost = candidate
|
||||
who = ghost.name
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
who = comm.owner
|
||||
comm.im_contacts |= src
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else if(istype(candidate, /obj/item/integrated_circuit))
|
||||
var/obj/item/integrated_circuit/CIRC = candidate
|
||||
who = CIRC
|
||||
im_list += list(list("address" = origin_address, "to_address" = exonet.address, "im" = text))
|
||||
else return
|
||||
|
||||
im_contacts |= candidate
|
||||
|
||||
if(!who)
|
||||
return
|
||||
|
||||
if(ringer)
|
||||
var/S
|
||||
if(ttone in ttone_sound)
|
||||
S = ttone_sound[ttone]
|
||||
else
|
||||
S = 'sound/machines/twobeep.ogg'
|
||||
|
||||
playsound(src, S, 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src][bicon(src)] *[ttone]*"))
|
||||
|
||||
alert_called = 1
|
||||
update_icon()
|
||||
|
||||
//Search for holder of the device.
|
||||
var/mob/living/L = null
|
||||
if(loc && isliving(loc))
|
||||
L = loc
|
||||
|
||||
if(L)
|
||||
to_chat(L, "<span class='notice'>\icon[src][bicon(src)] Message from [who]: <b>\"[text]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[candidate]'>Reply</a>)</span>")
|
||||
|
||||
// This is the only Topic the communicators really uses
|
||||
/obj/item/device/communicator/Topic(href, href_list)
|
||||
switch(href_list["action"])
|
||||
if("Reply")
|
||||
var/obj/item/device/communicator/comm = locate(href_list["target"])
|
||||
var/message = tgui_input_text(usr, "Enter your message below.", "Reply")
|
||||
|
||||
if(message)
|
||||
exonet.send_message(comm.exonet.address, "text", message)
|
||||
im_list += list(list("address" = exonet.address, "to_address" = comm.exonet.address, "im" = message))
|
||||
log_pda("(COMM: [src]) sent \"[message]\" to [exonet.get_atom_from_address(comm.exonet.address)]", usr)
|
||||
to_chat(usr, "<span class='notice'>\icon[src][bicon(src)] Sent message to [istype(comm, /obj/item/device/communicator) ? comm.owner : comm.name], <b>\"[message]\"</b> (<a href='?src=\ref[src];action=Reply;target=\ref[exonet.get_atom_from_address(comm.exonet.address)]'>Reply</a>)</span>")
|
||||
|
||||
// Verb: text_communicator()
|
||||
// Parameters: None
|
||||
// Description: Allows a ghost to send a text message to a communicator.
|
||||
/mob/observer/dead/verb/text_communicator()
|
||||
set category = "Ghost"
|
||||
set name = "Text Communicator"
|
||||
set desc = "If there is a communicator available, send a text message to it."
|
||||
|
||||
if(ticker.current_state < GAME_STATE_PLAYING)
|
||||
to_chat(src, "<span class='danger'>The game hasn't started yet!</span>")
|
||||
return
|
||||
|
||||
if (!src.stat)
|
||||
return
|
||||
|
||||
if (usr != src)
|
||||
return //something is terribly wrong
|
||||
|
||||
for(var/mob/living/L in mob_list) //Simple check so you don't have dead people calling.
|
||||
if(src.client.prefs.real_name == L.real_name)
|
||||
to_chat(src, "<span class='danger'>Your identity is already present in the game world. Please load in a different character first.</span>")
|
||||
return
|
||||
|
||||
var/obj/machinery/exonet_node/E = get_exonet_node()
|
||||
if(!E || !E.on || !E.allow_external_communicators)
|
||||
to_chat(src, "<span class='danger'>The Exonet node at telecommunications is down at the moment, or is actively blocking you, \
|
||||
so your call can't go through.</span>")
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/obj/item/device/communicator/comm in all_communicators)
|
||||
if(!comm.network_visibility || !comm.exonet || !comm.exonet.address)
|
||||
continue
|
||||
choices.Add(comm)
|
||||
|
||||
if(!choices.len)
|
||||
to_chat(src, "<span class='danger'>There are no available communicators, sorry.</span>")
|
||||
return
|
||||
|
||||
var/choice = tgui_input_list(src,"Send a text message to whom?", "Recipient Choice", choices)
|
||||
if(choice)
|
||||
var/obj/item/device/communicator/chosen_communicator = choice
|
||||
var/mob/observer/dead/O = src
|
||||
var/text_message = sanitize(tgui_input_text(src, "What do you want the message to say?", multiline = TRUE))
|
||||
if(text_message && O.exonet)
|
||||
O.exonet.send_message(chosen_communicator.exonet.address, "text", text_message)
|
||||
|
||||
to_chat(src, "<span class='notice'>You have sent '[text_message]' to [chosen_communicator].</span>")
|
||||
exonet_messages.Add("<b>To [chosen_communicator]:</b><br>[text_message]")
|
||||
log_pda("(DCOMM: [src]) sent \"[text_message]\" to [chosen_communicator]", src)
|
||||
for(var/mob/M in player_list)
|
||||
if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears))
|
||||
if(istype(M, /mob/new_player) || M.forbid_seeing_deadchat)
|
||||
continue
|
||||
if(M == src)
|
||||
continue
|
||||
M.show_message("Comm IM - [src] -> [chosen_communicator]: [text_message]")
|
||||
|
||||
|
||||
|
||||
// Verb: show_text_messages()
|
||||
// Parameters: None
|
||||
// Description: Lets ghosts review messages they've sent or received.
|
||||
/mob/observer/dead/verb/show_text_messages()
|
||||
set category = "Ghost"
|
||||
set name = "Show Text Messages"
|
||||
set desc = "Allows you to see exonet text messages you've sent and received."
|
||||
|
||||
var/HTML = "<html><head><title>Exonet Message Log</title></head><body>"
|
||||
for(var/line in exonet_messages)
|
||||
HTML += line + "<br>"
|
||||
HTML +="</body></html>"
|
||||
usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0")
|
||||
|
||||
@@ -1,366 +1,366 @@
|
||||
// Proc: add_communicating()
|
||||
// Parameters: 1 (comm - the communicator to add to communicating)
|
||||
// Description: Used when this communicator gets a new communicator to relay say/me messages to
|
||||
/obj/item/device/communicator/proc/add_communicating(obj/item/device/communicator/comm)
|
||||
if(!comm || !istype(comm)) return
|
||||
|
||||
communicating |= comm
|
||||
listening_objects |= src
|
||||
update_icon()
|
||||
|
||||
// Proc: del_communicating()
|
||||
// Parameters: 1 (comm - the communicator to remove from communicating)
|
||||
// Description: Used when this communicator is being asked to stop relaying say/me messages to another
|
||||
/obj/item/device/communicator/proc/del_communicating(obj/item/device/communicator/comm)
|
||||
if(!comm || !istype(comm)) return
|
||||
|
||||
communicating.Remove(comm)
|
||||
update_icon()
|
||||
|
||||
// Proc: open_connection()
|
||||
// Parameters: 2 (user - the person who initiated the connecting being opened, candidate - the communicator or observer that will connect to the device)
|
||||
// Description: Typechecks the candidate, then calls the correct proc for further connecting.
|
||||
/obj/item/device/communicator/proc/open_connection(mob/user, var/atom/candidate)
|
||||
if(isobserver(candidate))
|
||||
voice_invites.Remove(candidate)
|
||||
open_connection_to_ghost(user, candidate)
|
||||
else
|
||||
if(istype(candidate, /obj/item/device/communicator))
|
||||
open_connection_to_communicator(user, candidate)
|
||||
|
||||
// Proc: open_connection_to_communicator()
|
||||
// Parameters: 2 (user - the person who initiated this and will be receiving feedback information, candidate - someone else's communicator)
|
||||
// Description: Adds the candidate and src to each other's communicating lists, allowing messages seen by the devices to be relayed.
|
||||
/obj/item/device/communicator/proc/open_connection_to_communicator(mob/user, var/atom/candidate)
|
||||
if(!istype(candidate, /obj/item/device/communicator))
|
||||
return
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
voice_invites.Remove(candidate)
|
||||
comm.voice_requests.Remove(src)
|
||||
|
||||
if(user)
|
||||
comm.visible_message("<span class='notice'>\icon[src][bicon(src)] Connecting to [src].</span>")
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Attempting to call [comm].</span>")
|
||||
sleep(10)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Dialing internally from [station_name()], [system_name()].</span>")
|
||||
sleep(20) //If they don't have an exonet something is very wrong and we want a runtime.
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connection re-routed to [comm] at [comm.exonet.address].</span>")
|
||||
sleep(40)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connection to [comm] at [comm.exonet.address] established.</span>")
|
||||
comm.visible_message("<span class='notice'>\icon[src][bicon(src)] Connection to [src] at [exonet.address] established.</span>")
|
||||
sleep(20)
|
||||
|
||||
src.add_communicating(comm)
|
||||
comm.add_communicating(src)
|
||||
|
||||
// Proc: open_connection_to_ghost()
|
||||
// Parameters: 2 (user - the person who initiated this, candidate - the ghost that will be turned into a voice mob)
|
||||
// Description: Pulls the candidate ghost from deadchat, makes a new voice mob, transfers their identity, then their client.
|
||||
/obj/item/device/communicator/proc/open_connection_to_ghost(mob/user, var/mob/candidate)
|
||||
if(!isobserver(candidate))
|
||||
return
|
||||
//Handle moving the ghost into the new shell.
|
||||
announce_ghost_joinleave(candidate, 0, "They are occupying a personal communications device now.")
|
||||
voice_requests.Remove(candidate)
|
||||
voice_invites.Remove(candidate)
|
||||
var/mob/living/voice/new_voice = new /mob/living/voice(src) //Make the voice mob the ghost is going to be.
|
||||
new_voice.transfer_identity(candidate) //Now make the voice mob load from the ghost's active character in preferences.
|
||||
//Do some simple logging since this is a tad risky as a concept.
|
||||
var/msg = "[candidate && candidate.client ? "[candidate.client.key]" : "*no key*"] ([candidate]) has entered [src], triggered by \
|
||||
[user && user.client ? "[user.client.key]" : "*no key*"] ([user ? "[user]" : "*null*"]) at [x],[y],[z]. They have joined as [new_voice.name]."
|
||||
message_admins(msg)
|
||||
log_game(msg)
|
||||
new_voice.mind = candidate.mind //Transfer the mind, if any.
|
||||
new_voice.ckey = candidate.ckey //Finally, bring the client over.
|
||||
voice_mobs.Add(new_voice)
|
||||
listening_objects |= src
|
||||
|
||||
var/obj/screen/blackness = new() //Makes a black screen, so the candidate can't see what's going on before actually 'connecting' to the communicator.
|
||||
blackness.screen_loc = ui_entire_screen
|
||||
blackness.icon = 'icons/effects/effects.dmi'
|
||||
blackness.icon_state = "1"
|
||||
blackness.mouse_opacity = 2 //Can't see anything!
|
||||
new_voice.client.screen.Add(blackness)
|
||||
|
||||
update_icon()
|
||||
|
||||
//Now for some connection fluff.
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connecting to [candidate].</span>")
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Attempting to call [src].</span>")
|
||||
sleep(10)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Dialing to [station_name()], Kara Subsystem, [system_name()].</span>")
|
||||
sleep(20)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connecting to [station_name()] telecommunications array.</span>")
|
||||
sleep(40)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connection to [station_name()] telecommunications array established. Redirecting signal to [src].</span>")
|
||||
sleep(20)
|
||||
|
||||
//We're connected, no need to hide everything.
|
||||
new_voice.client.screen.Remove(blackness)
|
||||
qdel(blackness)
|
||||
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connection to [src] established.</span>")
|
||||
to_chat(new_voice, "<b>To talk to the person on the other end of the call, just talk normally.</b>")
|
||||
to_chat(new_voice, "<b>If you want to end the call, use the 'Hang Up' verb. The other person can also hang up at any time.</b>")
|
||||
to_chat(new_voice, "<b>Remember, your character does not know anything you've learned from observing!</b>")
|
||||
if(new_voice.mind)
|
||||
new_voice.mind.assigned_role = "Disembodied Voice"
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Your communicator is now connected to [candidate]'s communicator.</span>")
|
||||
|
||||
// Proc: close_connection()
|
||||
// Parameters: 3 (user - the user who initiated the disconnect, target - the mob or device being disconnected, reason - string shown when disconnected)
|
||||
// Description: Deletes specific voice_mobs or disconnects communicators, and shows a message to everyone when doing so. If target is null, all communicators
|
||||
// and voice mobs are removed.
|
||||
/obj/item/device/communicator/proc/close_connection(mob/user, var/atom/target, var/reason)
|
||||
if(voice_mobs.len == 0 && communicating.len == 0)
|
||||
return
|
||||
|
||||
for(var/mob/living/voice/voice in voice_mobs) //Handle ghost-callers
|
||||
if(target && voice != target) //If no target is inputted, it deletes all of them.
|
||||
continue
|
||||
to_chat(voice, "<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
voice_mobs.Remove(voice)
|
||||
qdel(voice)
|
||||
update_icon()
|
||||
|
||||
for(var/obj/item/device/communicator/comm in communicating) //Now we handle real communicators.
|
||||
if(target && comm != target)
|
||||
continue
|
||||
src.del_communicating(comm)
|
||||
comm.del_communicating(src)
|
||||
comm.visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
if(comm.camera && video_source == comm.camera) //We hung up on the person on video
|
||||
end_video()
|
||||
if(camera && comm.video_source == camera) //We hung up on them while they were watching us
|
||||
comm.end_video()
|
||||
|
||||
if(voice_mobs.len == 0 && communicating.len == 0)
|
||||
listening_objects.Remove(src)
|
||||
|
||||
// Proc: request()
|
||||
// Parameters: 1 (candidate - the ghost or communicator wanting to call the device)
|
||||
// Description: Response to a communicator or observer trying to call the device. Adds them to the list of requesters
|
||||
/obj/item/device/communicator/proc/request(var/atom/candidate)
|
||||
if(candidate in voice_requests)
|
||||
return
|
||||
var/who = null
|
||||
if(isobserver(candidate))
|
||||
who = candidate.name
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
who = comm.owner
|
||||
comm.voice_invites |= src
|
||||
|
||||
if(!who)
|
||||
return
|
||||
|
||||
voice_requests |= candidate
|
||||
|
||||
if(ringer)
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src][bicon(src)] *beep*"))
|
||||
|
||||
alert_called = 1
|
||||
update_icon()
|
||||
|
||||
//Search for holder of the device.
|
||||
var/mob/living/L = null
|
||||
if(loc && isliving(loc))
|
||||
L = loc
|
||||
|
||||
if(L)
|
||||
to_chat(L, "<span class='notice'>\icon[src][bicon(src)] Communications request from [who].</span>")
|
||||
|
||||
// Proc: del_request()
|
||||
// Parameters: 1 (candidate - the ghost or communicator to be declined)
|
||||
// Description: Declines a request and cleans up both ends
|
||||
/obj/item/device/communicator/proc/del_request(var/atom/candidate)
|
||||
if(!(candidate in voice_requests))
|
||||
return
|
||||
|
||||
if(isobserver(candidate))
|
||||
to_chat(candidate, "<span class='warning'>Your communicator call request was declined.</span>")
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
comm.voice_invites -= src
|
||||
|
||||
voice_requests -= candidate
|
||||
|
||||
//Search for holder of our device.
|
||||
var/mob/living/us = null
|
||||
if(loc && isliving(loc))
|
||||
us = loc
|
||||
|
||||
if(us)
|
||||
to_chat(us, "<span class='notice'>\icon[src][bicon(src)] Declined request.</span>")
|
||||
|
||||
// Proc: see_emote()
|
||||
// Parameters: 2 (M - the mob the emote originated from, text - the emote's contents)
|
||||
// Description: Relays the emote to all linked communicators.
|
||||
/obj/item/device/communicator/see_emote(mob/living/M, text)
|
||||
var/rendered = "\icon[src][bicon(src)] <span class='message'>[text]</span>"
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
//VOREStation Edit Start for commlinks
|
||||
var/list/mobs_to_relay
|
||||
if(istype(comm,/obj/item/device/communicator/commlink))
|
||||
var/obj/item/device/communicator/commlink/CL = comm
|
||||
mobs_to_relay = list(CL.nif.human)
|
||||
else
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0) //Range of 3 since it's a tiny video display
|
||||
mobs_to_relay = in_range["mobs"]
|
||||
//VOREStation Edit End
|
||||
|
||||
for(var/mob/mob in mobs_to_relay) //We can't use visible_message(), or else we will get an infinite loop if two communicators hear each other.
|
||||
var/dst = get_dist(get_turf(mob),get_turf(comm))
|
||||
if(dst <= video_range)
|
||||
mob.show_message(rendered)
|
||||
else
|
||||
to_chat(mob, "You can barely see some movement on \the [src]'s display.")
|
||||
|
||||
..()
|
||||
|
||||
// Proc: hear_talk()
|
||||
// Parameters: 3 (M - the mob the speech originated from,
|
||||
// list/message_pieces - what is being said w/ baked languages,
|
||||
// verb - the word used to describe how text is being said)
|
||||
// Description: Relays the speech to all linked communicators.
|
||||
/obj/item/device/communicator/hear_talk(mob/M, list/message_pieces, verb)
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
//VOREStation Edit Start for commlinks
|
||||
var/list/mobs_to_relay
|
||||
if(istype(comm,/obj/item/device/communicator/commlink))
|
||||
var/obj/item/device/communicator/commlink/CL = comm
|
||||
mobs_to_relay = list(CL.nif.human)
|
||||
else
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0) //Range of 3 since it's a tiny video display
|
||||
mobs_to_relay = in_range["mobs"]
|
||||
//VOREStation Edit End
|
||||
|
||||
for(var/mob/mob in mobs_to_relay)
|
||||
var/list/combined = mob.combine_message(message_pieces, verb, M)
|
||||
var/message = combined["formatted"]
|
||||
var/name_used = M.GetVoice()
|
||||
var/rendered = null
|
||||
rendered = "<span class='game say'>\icon[src][bicon(src)] <span class='name'>[name_used]</span> [message]</span>"
|
||||
mob.show_message(rendered, 2)
|
||||
|
||||
// Proc: show_message()
|
||||
// Parameters: 4 (msg - the message, type - number to determine if message is visible or audible, alt - unknown, alt_type - unknown)
|
||||
// Description: Relays the message to all linked communicators.
|
||||
/obj/item/device/communicator/show_message(msg, type, alt, alt_type)
|
||||
var/rendered = "\icon[src][bicon(src)] <span class='message'>[msg]</span>"
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0)
|
||||
var/list/mobs_to_relay = in_range["mobs"]
|
||||
|
||||
for(var/mob/mob in mobs_to_relay)
|
||||
mob.show_message(rendered)
|
||||
..()
|
||||
|
||||
// Verb: join_as_voice()
|
||||
// Parameters: None
|
||||
// Description: Allows ghosts to call communicators, if they meet all the requirements.
|
||||
/mob/observer/dead/verb/join_as_voice()
|
||||
set category = "Ghost"
|
||||
set name = "Call Communicator"
|
||||
set desc = "If there is a communicator available, send a request to speak through it. This will reset your respawn timer, if someone picks up."
|
||||
|
||||
if(ticker.current_state < GAME_STATE_PLAYING)
|
||||
to_chat(src, "<span class='danger'>The game hasn't started yet!</span>")
|
||||
return
|
||||
|
||||
if (!src.stat)
|
||||
return
|
||||
|
||||
if (usr != src)
|
||||
return //something is terribly wrong
|
||||
|
||||
var/confirm = tgui_alert(src, "Would you like to talk as [src.client.prefs.real_name], over a communicator? This will reset your respawn timer, if someone answers.", "Join as Voice?", list("Yes","No"))
|
||||
if(confirm == "No")
|
||||
return
|
||||
|
||||
if(config.antag_hud_restricted && has_enabled_antagHUD == 1)
|
||||
to_chat(src, "<span class='danger'>You have used the antagHUD and cannot respawn or use communicators!</span>")
|
||||
return
|
||||
|
||||
for(var/mob/living/L in mob_list) //Simple check so you don't have dead people calling.
|
||||
if(src.client.prefs.real_name == L.real_name)
|
||||
to_chat(src, "<span class='danger'>Your identity is already present in the game world. Please load in a different character first.</span>")
|
||||
return
|
||||
|
||||
var/obj/machinery/exonet_node/E = get_exonet_node()
|
||||
if(!E || !E.on || !E.allow_external_communicators)
|
||||
to_chat(src, "<span class='danger'>The Exonet node at telecommunications is down at the moment, or is actively blocking you, \
|
||||
so your call can't go through.</span>")
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/obj/item/device/communicator/comm in all_communicators)
|
||||
if(!comm.network_visibility || !comm.exonet || !comm.exonet.address)
|
||||
continue
|
||||
choices.Add(comm)
|
||||
|
||||
if(!choices.len)
|
||||
to_chat(src , "<span class='danger'>There are no available communicators, sorry.</span>")
|
||||
return
|
||||
|
||||
var/choice = tgui_input_list(src,"Send a voice request to whom?", "Recipient Choice", choices)
|
||||
if(choice)
|
||||
var/obj/item/device/communicator/chosen_communicator = choice
|
||||
var/mob/observer/dead/O = src
|
||||
if(O.exonet)
|
||||
O.exonet.send_message(chosen_communicator.exonet.address, "voice")
|
||||
|
||||
to_chat(src, "A communications request has been sent to [chosen_communicator]. Now you need to wait until someone answers.")
|
||||
|
||||
// Proc: connect_video()
|
||||
// Parameters: user - the mob doing the viewing of video, comm - the communicator at the far end
|
||||
// Description: Sets up a videocall and puts the first view into it using watch_video, and updates the icon
|
||||
/obj/item/device/communicator/proc/connect_video(mob/user,obj/item/device/communicator/comm)
|
||||
if((!user) || (!comm) || user.stat) return //KO or dead, or already in a video
|
||||
|
||||
if(video_source) //Already in a video
|
||||
to_chat(user, "<span class='danger'>You are already connected to a video call!</span>")
|
||||
return
|
||||
|
||||
if(user.blinded) //User is blinded
|
||||
to_chat(user, "<span class='danger'>You cannot see well enough to do that!</span>")
|
||||
return
|
||||
|
||||
if(!(src in comm.communicating) || !comm.camera) //You called someone with a broken communicator or one that's fake or yourself or something
|
||||
to_chat(user, "<span class='danger'>\icon[src][bicon(src)]ERROR: Video failed. Either bandwidth is too low, or the other communicator is malfunctioning.</span>")
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Attempting to start video over existing call.</span>")
|
||||
sleep(30)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Please wait...</span>")
|
||||
|
||||
video_source = comm.camera
|
||||
comm.visible_message("<span class='danger'>\icon[src][bicon(src)] New video connection from [comm].</span>")
|
||||
update_active_camera_screen()
|
||||
GLOB.moved_event.register(video_source, src, PROC_REF(update_active_camera_screen))
|
||||
update_icon()
|
||||
|
||||
// Proc: end_video()
|
||||
// Parameters: reason - the text reason to print for why it ended
|
||||
// Description: Ends the video call by clearing video_source
|
||||
/obj/item/device/communicator/proc/end_video(var/reason)
|
||||
GLOB.moved_event.unregister(video_source, src, PROC_REF(update_active_camera_screen))
|
||||
show_static()
|
||||
video_source = null
|
||||
|
||||
. = "<span class='danger'>\icon[src][bicon(src)] [reason ? reason : "Video session ended"].</span>"
|
||||
|
||||
visible_message(.)
|
||||
update_icon()
|
||||
// Proc: add_communicating()
|
||||
// Parameters: 1 (comm - the communicator to add to communicating)
|
||||
// Description: Used when this communicator gets a new communicator to relay say/me messages to
|
||||
/obj/item/device/communicator/proc/add_communicating(obj/item/device/communicator/comm)
|
||||
if(!comm || !istype(comm)) return
|
||||
|
||||
communicating |= comm
|
||||
listening_objects |= src
|
||||
update_icon()
|
||||
|
||||
// Proc: del_communicating()
|
||||
// Parameters: 1 (comm - the communicator to remove from communicating)
|
||||
// Description: Used when this communicator is being asked to stop relaying say/me messages to another
|
||||
/obj/item/device/communicator/proc/del_communicating(obj/item/device/communicator/comm)
|
||||
if(!comm || !istype(comm)) return
|
||||
|
||||
communicating.Remove(comm)
|
||||
update_icon()
|
||||
|
||||
// Proc: open_connection()
|
||||
// Parameters: 2 (user - the person who initiated the connecting being opened, candidate - the communicator or observer that will connect to the device)
|
||||
// Description: Typechecks the candidate, then calls the correct proc for further connecting.
|
||||
/obj/item/device/communicator/proc/open_connection(mob/user, var/atom/candidate)
|
||||
if(isobserver(candidate))
|
||||
voice_invites.Remove(candidate)
|
||||
open_connection_to_ghost(user, candidate)
|
||||
else
|
||||
if(istype(candidate, /obj/item/device/communicator))
|
||||
open_connection_to_communicator(user, candidate)
|
||||
|
||||
// Proc: open_connection_to_communicator()
|
||||
// Parameters: 2 (user - the person who initiated this and will be receiving feedback information, candidate - someone else's communicator)
|
||||
// Description: Adds the candidate and src to each other's communicating lists, allowing messages seen by the devices to be relayed.
|
||||
/obj/item/device/communicator/proc/open_connection_to_communicator(mob/user, var/atom/candidate)
|
||||
if(!istype(candidate, /obj/item/device/communicator))
|
||||
return
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
voice_invites.Remove(candidate)
|
||||
comm.voice_requests.Remove(src)
|
||||
|
||||
if(user)
|
||||
comm.visible_message("<span class='notice'>\icon[src][bicon(src)] Connecting to [src].</span>")
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Attempting to call [comm].</span>")
|
||||
sleep(10)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Dialing internally from [station_name()], [system_name()].</span>")
|
||||
sleep(20) //If they don't have an exonet something is very wrong and we want a runtime.
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connection re-routed to [comm] at [comm.exonet.address].</span>")
|
||||
sleep(40)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connection to [comm] at [comm.exonet.address] established.</span>")
|
||||
comm.visible_message("<span class='notice'>\icon[src][bicon(src)] Connection to [src] at [exonet.address] established.</span>")
|
||||
sleep(20)
|
||||
|
||||
src.add_communicating(comm)
|
||||
comm.add_communicating(src)
|
||||
|
||||
// Proc: open_connection_to_ghost()
|
||||
// Parameters: 2 (user - the person who initiated this, candidate - the ghost that will be turned into a voice mob)
|
||||
// Description: Pulls the candidate ghost from deadchat, makes a new voice mob, transfers their identity, then their client.
|
||||
/obj/item/device/communicator/proc/open_connection_to_ghost(mob/user, var/mob/candidate)
|
||||
if(!isobserver(candidate))
|
||||
return
|
||||
//Handle moving the ghost into the new shell.
|
||||
announce_ghost_joinleave(candidate, 0, "They are occupying a personal communications device now.")
|
||||
voice_requests.Remove(candidate)
|
||||
voice_invites.Remove(candidate)
|
||||
var/mob/living/voice/new_voice = new /mob/living/voice(src) //Make the voice mob the ghost is going to be.
|
||||
new_voice.transfer_identity(candidate) //Now make the voice mob load from the ghost's active character in preferences.
|
||||
//Do some simple logging since this is a tad risky as a concept.
|
||||
var/msg = "[candidate && candidate.client ? "[candidate.client.key]" : "*no key*"] ([candidate]) has entered [src], triggered by \
|
||||
[user && user.client ? "[user.client.key]" : "*no key*"] ([user ? "[user]" : "*null*"]) at [x],[y],[z]. They have joined as [new_voice.name]."
|
||||
message_admins(msg)
|
||||
log_game(msg)
|
||||
new_voice.mind = candidate.mind //Transfer the mind, if any.
|
||||
new_voice.ckey = candidate.ckey //Finally, bring the client over.
|
||||
voice_mobs.Add(new_voice)
|
||||
listening_objects |= src
|
||||
|
||||
var/obj/screen/blackness = new() //Makes a black screen, so the candidate can't see what's going on before actually 'connecting' to the communicator.
|
||||
blackness.screen_loc = ui_entire_screen
|
||||
blackness.icon = 'icons/effects/effects.dmi'
|
||||
blackness.icon_state = "1"
|
||||
blackness.mouse_opacity = 2 //Can't see anything!
|
||||
new_voice.client.screen.Add(blackness)
|
||||
|
||||
update_icon()
|
||||
|
||||
//Now for some connection fluff.
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Connecting to [candidate].</span>")
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Attempting to call [src].</span>")
|
||||
sleep(10)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Dialing to [station_name()], Kara Subsystem, [system_name()].</span>")
|
||||
sleep(20)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connecting to [station_name()] telecommunications array.</span>")
|
||||
sleep(40)
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connection to [station_name()] telecommunications array established. Redirecting signal to [src].</span>")
|
||||
sleep(20)
|
||||
|
||||
//We're connected, no need to hide everything.
|
||||
new_voice.client.screen.Remove(blackness)
|
||||
qdel(blackness)
|
||||
|
||||
to_chat(new_voice, "<span class='notice'>\icon[src][bicon(src)] Connection to [src] established.</span>")
|
||||
to_chat(new_voice, "<b>To talk to the person on the other end of the call, just talk normally.</b>")
|
||||
to_chat(new_voice, "<b>If you want to end the call, use the 'Hang Up' verb. The other person can also hang up at any time.</b>")
|
||||
to_chat(new_voice, "<b>Remember, your character does not know anything you've learned from observing!</b>")
|
||||
if(new_voice.mind)
|
||||
new_voice.mind.assigned_role = "Disembodied Voice"
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Your communicator is now connected to [candidate]'s communicator.</span>")
|
||||
|
||||
// Proc: close_connection()
|
||||
// Parameters: 3 (user - the user who initiated the disconnect, target - the mob or device being disconnected, reason - string shown when disconnected)
|
||||
// Description: Deletes specific voice_mobs or disconnects communicators, and shows a message to everyone when doing so. If target is null, all communicators
|
||||
// and voice mobs are removed.
|
||||
/obj/item/device/communicator/proc/close_connection(mob/user, var/atom/target, var/reason)
|
||||
if(voice_mobs.len == 0 && communicating.len == 0)
|
||||
return
|
||||
|
||||
for(var/mob/living/voice/voice in voice_mobs) //Handle ghost-callers
|
||||
if(target && voice != target) //If no target is inputted, it deletes all of them.
|
||||
continue
|
||||
to_chat(voice, "<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
voice_mobs.Remove(voice)
|
||||
qdel(voice)
|
||||
update_icon()
|
||||
|
||||
for(var/obj/item/device/communicator/comm in communicating) //Now we handle real communicators.
|
||||
if(target && comm != target)
|
||||
continue
|
||||
src.del_communicating(comm)
|
||||
comm.del_communicating(src)
|
||||
comm.visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
visible_message("<span class='danger'>\icon[src][bicon(src)] [reason].</span>")
|
||||
if(comm.camera && video_source == comm.camera) //We hung up on the person on video
|
||||
end_video()
|
||||
if(camera && comm.video_source == camera) //We hung up on them while they were watching us
|
||||
comm.end_video()
|
||||
|
||||
if(voice_mobs.len == 0 && communicating.len == 0)
|
||||
listening_objects.Remove(src)
|
||||
|
||||
// Proc: request()
|
||||
// Parameters: 1 (candidate - the ghost or communicator wanting to call the device)
|
||||
// Description: Response to a communicator or observer trying to call the device. Adds them to the list of requesters
|
||||
/obj/item/device/communicator/proc/request(var/atom/candidate)
|
||||
if(candidate in voice_requests)
|
||||
return
|
||||
var/who = null
|
||||
if(isobserver(candidate))
|
||||
who = candidate.name
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
who = comm.owner
|
||||
comm.voice_invites |= src
|
||||
|
||||
if(!who)
|
||||
return
|
||||
|
||||
voice_requests |= candidate
|
||||
|
||||
if(ringer)
|
||||
playsound(src, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
O.show_message(text("\icon[src][bicon(src)] *beep*"))
|
||||
|
||||
alert_called = 1
|
||||
update_icon()
|
||||
|
||||
//Search for holder of the device.
|
||||
var/mob/living/L = null
|
||||
if(loc && isliving(loc))
|
||||
L = loc
|
||||
|
||||
if(L)
|
||||
to_chat(L, "<span class='notice'>\icon[src][bicon(src)] Communications request from [who].</span>")
|
||||
|
||||
// Proc: del_request()
|
||||
// Parameters: 1 (candidate - the ghost or communicator to be declined)
|
||||
// Description: Declines a request and cleans up both ends
|
||||
/obj/item/device/communicator/proc/del_request(var/atom/candidate)
|
||||
if(!(candidate in voice_requests))
|
||||
return
|
||||
|
||||
if(isobserver(candidate))
|
||||
to_chat(candidate, "<span class='warning'>Your communicator call request was declined.</span>")
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
comm.voice_invites -= src
|
||||
|
||||
voice_requests -= candidate
|
||||
|
||||
//Search for holder of our device.
|
||||
var/mob/living/us = null
|
||||
if(loc && isliving(loc))
|
||||
us = loc
|
||||
|
||||
if(us)
|
||||
to_chat(us, "<span class='notice'>\icon[src][bicon(src)] Declined request.</span>")
|
||||
|
||||
// Proc: see_emote()
|
||||
// Parameters: 2 (M - the mob the emote originated from, text - the emote's contents)
|
||||
// Description: Relays the emote to all linked communicators.
|
||||
/obj/item/device/communicator/see_emote(mob/living/M, text)
|
||||
var/rendered = "\icon[src][bicon(src)] <span class='message'>[text]</span>"
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
//VOREStation Edit Start for commlinks
|
||||
var/list/mobs_to_relay
|
||||
if(istype(comm,/obj/item/device/communicator/commlink))
|
||||
var/obj/item/device/communicator/commlink/CL = comm
|
||||
mobs_to_relay = list(CL.nif.human)
|
||||
else
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0) //Range of 3 since it's a tiny video display
|
||||
mobs_to_relay = in_range["mobs"]
|
||||
//VOREStation Edit End
|
||||
|
||||
for(var/mob/mob in mobs_to_relay) //We can't use visible_message(), or else we will get an infinite loop if two communicators hear each other.
|
||||
var/dst = get_dist(get_turf(mob),get_turf(comm))
|
||||
if(dst <= video_range)
|
||||
mob.show_message(rendered)
|
||||
else
|
||||
to_chat(mob, "You can barely see some movement on \the [src]'s display.")
|
||||
|
||||
..()
|
||||
|
||||
// Proc: hear_talk()
|
||||
// Parameters: 3 (M - the mob the speech originated from,
|
||||
// list/message_pieces - what is being said w/ baked languages,
|
||||
// verb - the word used to describe how text is being said)
|
||||
// Description: Relays the speech to all linked communicators.
|
||||
/obj/item/device/communicator/hear_talk(mob/M, list/message_pieces, verb)
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
//VOREStation Edit Start for commlinks
|
||||
var/list/mobs_to_relay
|
||||
if(istype(comm,/obj/item/device/communicator/commlink))
|
||||
var/obj/item/device/communicator/commlink/CL = comm
|
||||
mobs_to_relay = list(CL.nif.human)
|
||||
else
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0) //Range of 3 since it's a tiny video display
|
||||
mobs_to_relay = in_range["mobs"]
|
||||
//VOREStation Edit End
|
||||
|
||||
for(var/mob/mob in mobs_to_relay)
|
||||
var/list/combined = mob.combine_message(message_pieces, verb, M)
|
||||
var/message = combined["formatted"]
|
||||
var/name_used = M.GetVoice()
|
||||
var/rendered = null
|
||||
rendered = "<span class='game say'>\icon[src][bicon(src)] <span class='name'>[name_used]</span> [message]</span>"
|
||||
mob.show_message(rendered, 2)
|
||||
|
||||
// Proc: show_message()
|
||||
// Parameters: 4 (msg - the message, type - number to determine if message is visible or audible, alt - unknown, alt_type - unknown)
|
||||
// Description: Relays the message to all linked communicators.
|
||||
/obj/item/device/communicator/show_message(msg, type, alt, alt_type)
|
||||
var/rendered = "\icon[src][bicon(src)] <span class='message'>[msg]</span>"
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/turf/T = get_turf(comm)
|
||||
if(!T) return
|
||||
var/list/in_range = get_mobs_and_objs_in_view_fast(T,world.view,0)
|
||||
var/list/mobs_to_relay = in_range["mobs"]
|
||||
|
||||
for(var/mob/mob in mobs_to_relay)
|
||||
mob.show_message(rendered)
|
||||
..()
|
||||
|
||||
// Verb: join_as_voice()
|
||||
// Parameters: None
|
||||
// Description: Allows ghosts to call communicators, if they meet all the requirements.
|
||||
/mob/observer/dead/verb/join_as_voice()
|
||||
set category = "Ghost"
|
||||
set name = "Call Communicator"
|
||||
set desc = "If there is a communicator available, send a request to speak through it. This will reset your respawn timer, if someone picks up."
|
||||
|
||||
if(ticker.current_state < GAME_STATE_PLAYING)
|
||||
to_chat(src, "<span class='danger'>The game hasn't started yet!</span>")
|
||||
return
|
||||
|
||||
if (!src.stat)
|
||||
return
|
||||
|
||||
if (usr != src)
|
||||
return //something is terribly wrong
|
||||
|
||||
var/confirm = tgui_alert(src, "Would you like to talk as [src.client.prefs.real_name], over a communicator? This will reset your respawn timer, if someone answers.", "Join as Voice?", list("Yes","No"))
|
||||
if(confirm == "No")
|
||||
return
|
||||
|
||||
if(config.antag_hud_restricted && has_enabled_antagHUD == 1)
|
||||
to_chat(src, "<span class='danger'>You have used the antagHUD and cannot respawn or use communicators!</span>")
|
||||
return
|
||||
|
||||
for(var/mob/living/L in mob_list) //Simple check so you don't have dead people calling.
|
||||
if(src.client.prefs.real_name == L.real_name)
|
||||
to_chat(src, "<span class='danger'>Your identity is already present in the game world. Please load in a different character first.</span>")
|
||||
return
|
||||
|
||||
var/obj/machinery/exonet_node/E = get_exonet_node()
|
||||
if(!E || !E.on || !E.allow_external_communicators)
|
||||
to_chat(src, "<span class='danger'>The Exonet node at telecommunications is down at the moment, or is actively blocking you, \
|
||||
so your call can't go through.</span>")
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/obj/item/device/communicator/comm in all_communicators)
|
||||
if(!comm.network_visibility || !comm.exonet || !comm.exonet.address)
|
||||
continue
|
||||
choices.Add(comm)
|
||||
|
||||
if(!choices.len)
|
||||
to_chat(src , "<span class='danger'>There are no available communicators, sorry.</span>")
|
||||
return
|
||||
|
||||
var/choice = tgui_input_list(src,"Send a voice request to whom?", "Recipient Choice", choices)
|
||||
if(choice)
|
||||
var/obj/item/device/communicator/chosen_communicator = choice
|
||||
var/mob/observer/dead/O = src
|
||||
if(O.exonet)
|
||||
O.exonet.send_message(chosen_communicator.exonet.address, "voice")
|
||||
|
||||
to_chat(src, "A communications request has been sent to [chosen_communicator]. Now you need to wait until someone answers.")
|
||||
|
||||
// Proc: connect_video()
|
||||
// Parameters: user - the mob doing the viewing of video, comm - the communicator at the far end
|
||||
// Description: Sets up a videocall and puts the first view into it using watch_video, and updates the icon
|
||||
/obj/item/device/communicator/proc/connect_video(mob/user,obj/item/device/communicator/comm)
|
||||
if((!user) || (!comm) || user.stat) return //KO or dead, or already in a video
|
||||
|
||||
if(video_source) //Already in a video
|
||||
to_chat(user, "<span class='danger'>You are already connected to a video call!</span>")
|
||||
return
|
||||
|
||||
if(user.blinded) //User is blinded
|
||||
to_chat(user, "<span class='danger'>You cannot see well enough to do that!</span>")
|
||||
return
|
||||
|
||||
if(!(src in comm.communicating) || !comm.camera) //You called someone with a broken communicator or one that's fake or yourself or something
|
||||
to_chat(user, "<span class='danger'>\icon[src][bicon(src)]ERROR: Video failed. Either bandwidth is too low, or the other communicator is malfunctioning.</span>")
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Attempting to start video over existing call.</span>")
|
||||
sleep(30)
|
||||
to_chat(user, "<span class='notice'>\icon[src][bicon(src)] Please wait...</span>")
|
||||
|
||||
video_source = comm.camera
|
||||
comm.visible_message("<span class='danger'>\icon[src][bicon(src)] New video connection from [comm].</span>")
|
||||
update_active_camera_screen()
|
||||
GLOB.moved_event.register(video_source, src, PROC_REF(update_active_camera_screen))
|
||||
update_icon()
|
||||
|
||||
// Proc: end_video()
|
||||
// Parameters: reason - the text reason to print for why it ended
|
||||
// Description: Ends the video call by clearing video_source
|
||||
/obj/item/device/communicator/proc/end_video(var/reason)
|
||||
GLOB.moved_event.unregister(video_source, src, PROC_REF(update_active_camera_screen))
|
||||
show_static()
|
||||
video_source = null
|
||||
|
||||
. = "<span class='danger'>\icon[src][bicon(src)] [reason ? reason : "Video session ended"].</span>"
|
||||
|
||||
visible_message(.)
|
||||
update_icon()
|
||||
|
||||
@@ -1,45 +1,45 @@
|
||||
/**
|
||||
* Multitool -- A multitool is used for hacking electronic devices.
|
||||
* TO-DO -- Using it as a power measurement tool for cables etc. Nannek.
|
||||
*
|
||||
*/
|
||||
|
||||
/obj/item/device/debugger
|
||||
name = "debugger"
|
||||
desc = "Used to debug electronic equipment."
|
||||
icon = 'icons/obj/hacktool.dmi'
|
||||
icon_state = "hacktool-g"
|
||||
force = 5.0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throwforce = 5.0
|
||||
throw_range = 15
|
||||
throw_speed = 3
|
||||
desc = "You can use this on airlocks or APCs to try to hack them without cutting wires."
|
||||
|
||||
matter = list(MAT_STEEL = 50,MAT_GLASS = 20)
|
||||
|
||||
origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1)
|
||||
var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage
|
||||
|
||||
/obj/item/device/debugger/is_used_on(obj/O, mob/user)
|
||||
if(istype(O, /obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/A = O
|
||||
if(A.emagged || A.hacker)
|
||||
to_chat(user, "<span class='warning'>There is a software error with the device.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The device's software appears to be fine.</span>")
|
||||
return 1
|
||||
if(istype(O, /obj/machinery/door))
|
||||
var/obj/machinery/door/D = O
|
||||
if(D.operating == -1)
|
||||
to_chat(user, "<span class='warning'>There is a software error with the device.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The device's software appears to be fine.</span>")
|
||||
return 1
|
||||
else if(istype(O, /obj/machinery))
|
||||
var/obj/machinery/A = O
|
||||
if(A.emagged)
|
||||
to_chat(user, "<span class='warning'>There is a software error with the device.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The device's software appears to be fine.</span>")
|
||||
return 1
|
||||
/**
|
||||
* Multitool -- A multitool is used for hacking electronic devices.
|
||||
* TO-DO -- Using it as a power measurement tool for cables etc. Nannek.
|
||||
*
|
||||
*/
|
||||
|
||||
/obj/item/device/debugger
|
||||
name = "debugger"
|
||||
desc = "Used to debug electronic equipment."
|
||||
icon = 'icons/obj/hacktool.dmi'
|
||||
icon_state = "hacktool-g"
|
||||
force = 5.0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throwforce = 5.0
|
||||
throw_range = 15
|
||||
throw_speed = 3
|
||||
desc = "You can use this on airlocks or APCs to try to hack them without cutting wires."
|
||||
|
||||
matter = list(MAT_STEEL = 50,MAT_GLASS = 20)
|
||||
|
||||
origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1)
|
||||
var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage
|
||||
|
||||
/obj/item/device/debugger/is_used_on(obj/O, mob/user)
|
||||
if(istype(O, /obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/A = O
|
||||
if(A.emagged || A.hacker)
|
||||
to_chat(user, "<span class='warning'>There is a software error with the device.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The device's software appears to be fine.</span>")
|
||||
return 1
|
||||
if(istype(O, /obj/machinery/door))
|
||||
var/obj/machinery/door/D = O
|
||||
if(D.operating == -1)
|
||||
to_chat(user, "<span class='warning'>There is a software error with the device.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The device's software appears to be fine.</span>")
|
||||
return 1
|
||||
else if(istype(O, /obj/machinery))
|
||||
var/obj/machinery/A = O
|
||||
if(A.emagged)
|
||||
to_chat(user, "<span class='warning'>There is a software error with the device.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The device's software appears to be fine.</span>")
|
||||
return 1
|
||||
|
||||
@@ -1,321 +1,321 @@
|
||||
/obj/item/device/flash
|
||||
name = "flash"
|
||||
desc = "Used for blinding and disorienting."
|
||||
icon_state = "flash"
|
||||
item_state = "flashtool"
|
||||
throwforce = 5
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throw_speed = 4
|
||||
throw_range = 10
|
||||
origin_tech = list(TECH_MAGNET = 2, TECH_COMBAT = 1)
|
||||
|
||||
var/times_used = 0 //Number of times it's been used.
|
||||
var/broken = FALSE //Is the flash burnt out?
|
||||
var/last_used = 0 //last world.time it was used.
|
||||
var/max_flashes = 10 // How many times the flash can be used before needing to self recharge.
|
||||
var/halloss_per_flash = 30
|
||||
var/break_mod = 3 // The percent to break increased by every use on the flash.
|
||||
|
||||
var/can_break = TRUE // Can the flash break?
|
||||
var/can_repair = FALSE // Can you repair the flash?
|
||||
var/repairing = FALSE // Are we repairing right now?
|
||||
|
||||
var/safe_flashes = 2 // How many flashes are kept in 1% breakchance?
|
||||
|
||||
var/charge_only = FALSE // Does the flash run purely on charge?
|
||||
|
||||
var/base_icon = "flash"
|
||||
|
||||
var/obj/item/weapon/cell/power_supply //What type of power cell this uses
|
||||
var/charge_cost = 30 //How much energy is needed to flash.
|
||||
var/use_external_power = FALSE // Do we use charge from an external source?
|
||||
|
||||
var/cell_type = /obj/item/weapon/cell/device
|
||||
|
||||
/obj/item/device/flash/Initialize()
|
||||
. = ..()
|
||||
power_supply = new cell_type(src)
|
||||
|
||||
/obj/item/device/flash/attackby(var/obj/item/W, var/mob/user)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER) && broken)
|
||||
if(repairing)
|
||||
to_chat(user, "<span class='notice'>\The [src] is already being repaired!</span>")
|
||||
return
|
||||
user.visible_message("<b>\The [user]</b> starts trying to repair \the [src]'s bulb.")
|
||||
repairing = TRUE
|
||||
if(do_after(user, (40 SECONDS + rand(0, 20 SECONDS)) * W.toolspeed) && can_repair)
|
||||
if(prob(30))
|
||||
user.visible_message("<span class='notice'>\The [user] successfully repairs \the [src]!</span>")
|
||||
broken = FALSE
|
||||
update_icon()
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
else
|
||||
user.visible_message("<b>\The [user]</b> fails to repair \the [src].")
|
||||
repairing = FALSE
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/flash/update_icon()
|
||||
var/obj/item/weapon/cell/battery = power_supply
|
||||
|
||||
if(use_external_power)
|
||||
battery = get_external_power_supply()
|
||||
|
||||
if(broken || !battery || battery.charge < charge_cost)
|
||||
icon_state = "[base_icon]burnt"
|
||||
else
|
||||
icon_state = "[base_icon]"
|
||||
return
|
||||
|
||||
/obj/item/device/flash/get_cell()
|
||||
return power_supply
|
||||
|
||||
/obj/item/device/flash/proc/get_external_power_supply()
|
||||
if(isrobot(src.loc))
|
||||
var/mob/living/silicon/robot/R = src.loc
|
||||
return R.cell
|
||||
if(istype(src.loc, /obj/item/rig_module))
|
||||
var/obj/item/rig_module/module = src.loc
|
||||
if(module.holder && module.holder.wearer)
|
||||
var/mob/living/carbon/human/H = module.holder.wearer
|
||||
if(istype(H) && H.get_rig())
|
||||
var/obj/item/weapon/rig/suit = H.get_rig()
|
||||
if(istype(suit))
|
||||
return suit.cell
|
||||
return null
|
||||
|
||||
/obj/item/device/flash/proc/clown_check(var/mob/user)
|
||||
if(user && (CLUMSY in user.mutations) && prob(50))
|
||||
to_chat(user, "<span class='warning'>\The [src] slips out of your hand.</span>")
|
||||
user.drop_item()
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/device/flash/proc/flash_recharge()
|
||||
//Every ten seconds the flash doesn't get used, the times_used variable goes down by one, making the flash less likely to burn out,
|
||||
// as well as being able to flash more before reaching max_flashes cap.
|
||||
for(var/i=0, i < max_flashes, i++)
|
||||
if(last_used + 10 SECONDS > world.time)
|
||||
break
|
||||
|
||||
else if(use_external_power)
|
||||
var/obj/item/weapon/cell/external = get_external_power_supply()
|
||||
if(!external || !external.use(charge_cost)) //Take power from the borg or rig!
|
||||
break
|
||||
|
||||
else if(!power_supply || !power_supply.checked_use(charge_cost))
|
||||
break
|
||||
|
||||
last_used += 10 SECONDS
|
||||
times_used--
|
||||
|
||||
last_used = world.time
|
||||
times_used = max(0,round(times_used)) //sanity
|
||||
update_icon()
|
||||
|
||||
// Returns true if the device can flash.
|
||||
/obj/item/device/flash/proc/check_capacitor(var/mob/user)
|
||||
//spamming the flash before it's fully charged (60 seconds) increases the chance of it breaking
|
||||
//It will never break on the first use.
|
||||
var/obj/item/weapon/cell/battery = power_supply
|
||||
|
||||
if(use_external_power)
|
||||
battery = get_external_power_supply()
|
||||
|
||||
if(times_used <= max_flashes && battery && battery.charge >= charge_cost)
|
||||
last_used = world.time
|
||||
if(prob( max(0, times_used - safe_flashes) * 2 + (times_used >= safe_flashes)) && can_break) //if you use it 10 times in a minute it has a 30% chance to break.
|
||||
broken = TRUE
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>The bulb has burnt out!</span>")
|
||||
update_icon()
|
||||
return FALSE
|
||||
else
|
||||
times_used++
|
||||
update_icon()
|
||||
return TRUE
|
||||
else if(!charge_only) //can only use it 10 times a minute, unless it runs purely on charge.
|
||||
if(user)
|
||||
update_icon()
|
||||
to_chat(user, "<span class='warning'><i>click</i></span>")
|
||||
playsound(src, 'sound/weapons/empty.ogg', 80, 1)
|
||||
return FALSE
|
||||
else if(battery && battery.checked_use(charge_cost + (round(charge_cost / 4) * max(0, times_used - max_flashes)))) // Using over your maximum flashes starts taking more charge per added flash.
|
||||
times_used++
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
//attack_as_weapon
|
||||
/obj/item/device/flash/attack(mob/living/M, mob/living/user, var/target_zone)
|
||||
if(!user || !M) return //sanity
|
||||
|
||||
add_attack_logs(user,M,"Flashed (attempt) with [src]")
|
||||
|
||||
user.setClickCooldown(user.get_attack_speed(src))
|
||||
user.do_attack_animation(M)
|
||||
|
||||
if(!clown_check(user)) return
|
||||
if(broken)
|
||||
to_chat(user, "<span class='warning'>\The [src] is broken.</span>")
|
||||
return
|
||||
|
||||
flash_recharge()
|
||||
|
||||
if(!check_capacitor(user))
|
||||
return
|
||||
|
||||
playsound(src, 'sound/weapons/flash.ogg', 100, 1)
|
||||
var/flashfail = 0
|
||||
|
||||
//VOREStation Add - NIF
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.nif && H.nif.flag_check(NIF_V_FLASHPROT,NIF_FLAGS_VISION))
|
||||
flashfail = 1
|
||||
H.nif.notify("High intensity light detected, and blocked!",TRUE)
|
||||
//VOREStation Add End
|
||||
|
||||
if(iscarbon(M) && !flashfail) //VOREStation Add - NIF
|
||||
var/mob/living/carbon/C = M
|
||||
if(C.stat != DEAD)
|
||||
var/safety = C.eyecheck()
|
||||
if(safety <= 0)
|
||||
var/flash_strength = 10 //Vorestation edit, making flashes behave the same as flash rounds
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
flash_strength *= H.species.flash_mod
|
||||
|
||||
if(flash_strength > 0)
|
||||
H.Confuse(flash_strength + 5)
|
||||
H.Blind(flash_strength)
|
||||
H.eye_blurry = max(H.eye_blurry, flash_strength + 5)
|
||||
H.flash_eyes()
|
||||
H.adjustHalLoss(halloss_per_flash * (flash_strength / 5)) // Should take four flashes to stun.
|
||||
H.apply_damage(flash_strength * H.species.flash_burn/5, BURN, BP_HEAD, 0, 0, "Photon burns")
|
||||
|
||||
else
|
||||
flashfail = 1
|
||||
|
||||
else if(issilicon(M))
|
||||
flashfail = 0
|
||||
var/mob/living/silicon/S = M
|
||||
if(isrobot(S))
|
||||
var/mob/living/silicon/robot/R = S
|
||||
if(R.has_active_type(/obj/item/borg/combat/shield))
|
||||
var/obj/item/borg/combat/shield/shield = locate() in R
|
||||
if(shield)
|
||||
if(shield.active)
|
||||
shield.adjust_flash_count(R, 1)
|
||||
flashfail = 1
|
||||
else
|
||||
flashfail = 1
|
||||
|
||||
if(isrobot(user))
|
||||
spawn(0)
|
||||
var/atom/movable/overlay/animation = new(user.loc)
|
||||
animation.layer = user.layer + 1
|
||||
animation.icon_state = "blank"
|
||||
animation.icon = 'icons/mob/mob.dmi'
|
||||
animation.master = user
|
||||
flick("blspell", animation)
|
||||
sleep(5)
|
||||
qdel(animation)
|
||||
|
||||
if(!flashfail)
|
||||
flick("flash2", src)
|
||||
if(!issilicon(M))
|
||||
|
||||
user.visible_message("<span class='disarm'>[user] blinds [M] with the flash!</span>")
|
||||
else
|
||||
|
||||
user.visible_message("<span class='notice'>[user] overloads [M]'s sensors with the flash!</span>")
|
||||
M.Weaken(rand(5,10))
|
||||
else
|
||||
|
||||
user.visible_message("<span class='notice'>[user] fails to blind [M] with the flash!</span>")
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/item/device/flash/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0)
|
||||
if(!user || !clown_check(user)) return
|
||||
|
||||
user.setClickCooldown(user.get_attack_speed(src))
|
||||
|
||||
if(broken)
|
||||
user.show_message("<span class='warning'>The [src.name] is broken</span>", 2)
|
||||
return
|
||||
|
||||
flash_recharge()
|
||||
|
||||
if(!check_capacitor(user))
|
||||
return
|
||||
|
||||
playsound(src, 'sound/weapons/flash.ogg', 100, 1)
|
||||
flick("flash2", src)
|
||||
if(user && isrobot(user))
|
||||
spawn(0)
|
||||
var/atom/movable/overlay/animation = new(user.loc)
|
||||
animation.layer = user.layer + 1
|
||||
animation.icon_state = "blank"
|
||||
animation.icon = 'icons/mob/mob.dmi'
|
||||
animation.master = user
|
||||
flick("blspell", animation)
|
||||
sleep(5)
|
||||
qdel(animation)
|
||||
|
||||
for(var/mob/living/carbon/C in oviewers(3, null))
|
||||
var/safety = C.eyecheck()
|
||||
if(!safety)
|
||||
if(!C.blinded)
|
||||
C.flash_eyes()
|
||||
|
||||
return
|
||||
|
||||
/obj/item/device/flash/emp_act(severity)
|
||||
if(broken) return
|
||||
flash_recharge()
|
||||
if(!check_capacitor())
|
||||
return
|
||||
|
||||
if(istype(loc, /mob/living/carbon))
|
||||
var/mob/living/carbon/C = loc
|
||||
var/safety = C.eyecheck()
|
||||
if(safety <= 0)
|
||||
C.adjustHalLoss(halloss_per_flash)
|
||||
//C.Weaken(10)
|
||||
C.flash_eyes()
|
||||
for(var/mob/M in viewers(C, null))
|
||||
M.show_message("<span class='disarm'>[C] is blinded by the flash!</span>")
|
||||
..()
|
||||
|
||||
/obj/item/device/flash/synthetic
|
||||
name = "synthetic flash"
|
||||
desc = "When a problem arises, SCIENCE is the solution."
|
||||
icon_state = "sflash"
|
||||
origin_tech = list(TECH_MAGNET = 2, TECH_COMBAT = 1)
|
||||
base_icon = "sflash"
|
||||
can_repair = FALSE
|
||||
|
||||
//attack_as_weapon
|
||||
/obj/item/device/flash/synthetic/attack(mob/living/M, mob/living/user, var/target_zone)
|
||||
..()
|
||||
if(!broken)
|
||||
broken = 1
|
||||
to_chat(user, "<span class='warning'>The bulb has burnt out!</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/flash/synthetic/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0)
|
||||
..()
|
||||
if(!broken)
|
||||
broken = 1
|
||||
to_chat(user, "<span class='warning'>The bulb has burnt out!</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/flash/robot
|
||||
name = "mounted flash"
|
||||
can_break = FALSE
|
||||
use_external_power = TRUE
|
||||
charge_only = TRUE
|
||||
/obj/item/device/flash
|
||||
name = "flash"
|
||||
desc = "Used for blinding and disorienting."
|
||||
icon_state = "flash"
|
||||
item_state = "flashtool"
|
||||
throwforce = 5
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throw_speed = 4
|
||||
throw_range = 10
|
||||
origin_tech = list(TECH_MAGNET = 2, TECH_COMBAT = 1)
|
||||
|
||||
var/times_used = 0 //Number of times it's been used.
|
||||
var/broken = FALSE //Is the flash burnt out?
|
||||
var/last_used = 0 //last world.time it was used.
|
||||
var/max_flashes = 10 // How many times the flash can be used before needing to self recharge.
|
||||
var/halloss_per_flash = 30
|
||||
var/break_mod = 3 // The percent to break increased by every use on the flash.
|
||||
|
||||
var/can_break = TRUE // Can the flash break?
|
||||
var/can_repair = FALSE // Can you repair the flash?
|
||||
var/repairing = FALSE // Are we repairing right now?
|
||||
|
||||
var/safe_flashes = 2 // How many flashes are kept in 1% breakchance?
|
||||
|
||||
var/charge_only = FALSE // Does the flash run purely on charge?
|
||||
|
||||
var/base_icon = "flash"
|
||||
|
||||
var/obj/item/weapon/cell/power_supply //What type of power cell this uses
|
||||
var/charge_cost = 30 //How much energy is needed to flash.
|
||||
var/use_external_power = FALSE // Do we use charge from an external source?
|
||||
|
||||
var/cell_type = /obj/item/weapon/cell/device
|
||||
|
||||
/obj/item/device/flash/Initialize()
|
||||
. = ..()
|
||||
power_supply = new cell_type(src)
|
||||
|
||||
/obj/item/device/flash/attackby(var/obj/item/W, var/mob/user)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER) && broken)
|
||||
if(repairing)
|
||||
to_chat(user, "<span class='notice'>\The [src] is already being repaired!</span>")
|
||||
return
|
||||
user.visible_message("<b>\The [user]</b> starts trying to repair \the [src]'s bulb.")
|
||||
repairing = TRUE
|
||||
if(do_after(user, (40 SECONDS + rand(0, 20 SECONDS)) * W.toolspeed) && can_repair)
|
||||
if(prob(30))
|
||||
user.visible_message("<span class='notice'>\The [user] successfully repairs \the [src]!</span>")
|
||||
broken = FALSE
|
||||
update_icon()
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
else
|
||||
user.visible_message("<b>\The [user]</b> fails to repair \the [src].")
|
||||
repairing = FALSE
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/flash/update_icon()
|
||||
var/obj/item/weapon/cell/battery = power_supply
|
||||
|
||||
if(use_external_power)
|
||||
battery = get_external_power_supply()
|
||||
|
||||
if(broken || !battery || battery.charge < charge_cost)
|
||||
icon_state = "[base_icon]burnt"
|
||||
else
|
||||
icon_state = "[base_icon]"
|
||||
return
|
||||
|
||||
/obj/item/device/flash/get_cell()
|
||||
return power_supply
|
||||
|
||||
/obj/item/device/flash/proc/get_external_power_supply()
|
||||
if(isrobot(src.loc))
|
||||
var/mob/living/silicon/robot/R = src.loc
|
||||
return R.cell
|
||||
if(istype(src.loc, /obj/item/rig_module))
|
||||
var/obj/item/rig_module/module = src.loc
|
||||
if(module.holder && module.holder.wearer)
|
||||
var/mob/living/carbon/human/H = module.holder.wearer
|
||||
if(istype(H) && H.get_rig())
|
||||
var/obj/item/weapon/rig/suit = H.get_rig()
|
||||
if(istype(suit))
|
||||
return suit.cell
|
||||
return null
|
||||
|
||||
/obj/item/device/flash/proc/clown_check(var/mob/user)
|
||||
if(user && (CLUMSY in user.mutations) && prob(50))
|
||||
to_chat(user, "<span class='warning'>\The [src] slips out of your hand.</span>")
|
||||
user.drop_item()
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/device/flash/proc/flash_recharge()
|
||||
//Every ten seconds the flash doesn't get used, the times_used variable goes down by one, making the flash less likely to burn out,
|
||||
// as well as being able to flash more before reaching max_flashes cap.
|
||||
for(var/i=0, i < max_flashes, i++)
|
||||
if(last_used + 10 SECONDS > world.time)
|
||||
break
|
||||
|
||||
else if(use_external_power)
|
||||
var/obj/item/weapon/cell/external = get_external_power_supply()
|
||||
if(!external || !external.use(charge_cost)) //Take power from the borg or rig!
|
||||
break
|
||||
|
||||
else if(!power_supply || !power_supply.checked_use(charge_cost))
|
||||
break
|
||||
|
||||
last_used += 10 SECONDS
|
||||
times_used--
|
||||
|
||||
last_used = world.time
|
||||
times_used = max(0,round(times_used)) //sanity
|
||||
update_icon()
|
||||
|
||||
// Returns true if the device can flash.
|
||||
/obj/item/device/flash/proc/check_capacitor(var/mob/user)
|
||||
//spamming the flash before it's fully charged (60 seconds) increases the chance of it breaking
|
||||
//It will never break on the first use.
|
||||
var/obj/item/weapon/cell/battery = power_supply
|
||||
|
||||
if(use_external_power)
|
||||
battery = get_external_power_supply()
|
||||
|
||||
if(times_used <= max_flashes && battery && battery.charge >= charge_cost)
|
||||
last_used = world.time
|
||||
if(prob( max(0, times_used - safe_flashes) * 2 + (times_used >= safe_flashes)) && can_break) //if you use it 10 times in a minute it has a 30% chance to break.
|
||||
broken = TRUE
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>The bulb has burnt out!</span>")
|
||||
update_icon()
|
||||
return FALSE
|
||||
else
|
||||
times_used++
|
||||
update_icon()
|
||||
return TRUE
|
||||
else if(!charge_only) //can only use it 10 times a minute, unless it runs purely on charge.
|
||||
if(user)
|
||||
update_icon()
|
||||
to_chat(user, "<span class='warning'><i>click</i></span>")
|
||||
playsound(src, 'sound/weapons/empty.ogg', 80, 1)
|
||||
return FALSE
|
||||
else if(battery && battery.checked_use(charge_cost + (round(charge_cost / 4) * max(0, times_used - max_flashes)))) // Using over your maximum flashes starts taking more charge per added flash.
|
||||
times_used++
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
//attack_as_weapon
|
||||
/obj/item/device/flash/attack(mob/living/M, mob/living/user, var/target_zone)
|
||||
if(!user || !M) return //sanity
|
||||
|
||||
add_attack_logs(user,M,"Flashed (attempt) with [src]")
|
||||
|
||||
user.setClickCooldown(user.get_attack_speed(src))
|
||||
user.do_attack_animation(M)
|
||||
|
||||
if(!clown_check(user)) return
|
||||
if(broken)
|
||||
to_chat(user, "<span class='warning'>\The [src] is broken.</span>")
|
||||
return
|
||||
|
||||
flash_recharge()
|
||||
|
||||
if(!check_capacitor(user))
|
||||
return
|
||||
|
||||
playsound(src, 'sound/weapons/flash.ogg', 100, 1)
|
||||
var/flashfail = 0
|
||||
|
||||
//VOREStation Add - NIF
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.nif && H.nif.flag_check(NIF_V_FLASHPROT,NIF_FLAGS_VISION))
|
||||
flashfail = 1
|
||||
H.nif.notify("High intensity light detected, and blocked!",TRUE)
|
||||
//VOREStation Add End
|
||||
|
||||
if(iscarbon(M) && !flashfail) //VOREStation Add - NIF
|
||||
var/mob/living/carbon/C = M
|
||||
if(C.stat != DEAD)
|
||||
var/safety = C.eyecheck()
|
||||
if(safety <= 0)
|
||||
var/flash_strength = 10 //Vorestation edit, making flashes behave the same as flash rounds
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
flash_strength *= H.species.flash_mod
|
||||
|
||||
if(flash_strength > 0)
|
||||
H.Confuse(flash_strength + 5)
|
||||
H.Blind(flash_strength)
|
||||
H.eye_blurry = max(H.eye_blurry, flash_strength + 5)
|
||||
H.flash_eyes()
|
||||
H.adjustHalLoss(halloss_per_flash * (flash_strength / 5)) // Should take four flashes to stun.
|
||||
H.apply_damage(flash_strength * H.species.flash_burn/5, BURN, BP_HEAD, 0, 0, "Photon burns")
|
||||
|
||||
else
|
||||
flashfail = 1
|
||||
|
||||
else if(issilicon(M))
|
||||
flashfail = 0
|
||||
var/mob/living/silicon/S = M
|
||||
if(isrobot(S))
|
||||
var/mob/living/silicon/robot/R = S
|
||||
if(R.has_active_type(/obj/item/borg/combat/shield))
|
||||
var/obj/item/borg/combat/shield/shield = locate() in R
|
||||
if(shield)
|
||||
if(shield.active)
|
||||
shield.adjust_flash_count(R, 1)
|
||||
flashfail = 1
|
||||
else
|
||||
flashfail = 1
|
||||
|
||||
if(isrobot(user))
|
||||
spawn(0)
|
||||
var/atom/movable/overlay/animation = new(user.loc)
|
||||
animation.layer = user.layer + 1
|
||||
animation.icon_state = "blank"
|
||||
animation.icon = 'icons/mob/mob.dmi'
|
||||
animation.master = user
|
||||
flick("blspell", animation)
|
||||
sleep(5)
|
||||
qdel(animation)
|
||||
|
||||
if(!flashfail)
|
||||
flick("flash2", src)
|
||||
if(!issilicon(M))
|
||||
|
||||
user.visible_message("<span class='disarm'>[user] blinds [M] with the flash!</span>")
|
||||
else
|
||||
|
||||
user.visible_message("<span class='notice'>[user] overloads [M]'s sensors with the flash!</span>")
|
||||
M.Weaken(rand(5,10))
|
||||
else
|
||||
|
||||
user.visible_message("<span class='notice'>[user] fails to blind [M] with the flash!</span>")
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/item/device/flash/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0)
|
||||
if(!user || !clown_check(user)) return
|
||||
|
||||
user.setClickCooldown(user.get_attack_speed(src))
|
||||
|
||||
if(broken)
|
||||
user.show_message("<span class='warning'>The [src.name] is broken</span>", 2)
|
||||
return
|
||||
|
||||
flash_recharge()
|
||||
|
||||
if(!check_capacitor(user))
|
||||
return
|
||||
|
||||
playsound(src, 'sound/weapons/flash.ogg', 100, 1)
|
||||
flick("flash2", src)
|
||||
if(user && isrobot(user))
|
||||
spawn(0)
|
||||
var/atom/movable/overlay/animation = new(user.loc)
|
||||
animation.layer = user.layer + 1
|
||||
animation.icon_state = "blank"
|
||||
animation.icon = 'icons/mob/mob.dmi'
|
||||
animation.master = user
|
||||
flick("blspell", animation)
|
||||
sleep(5)
|
||||
qdel(animation)
|
||||
|
||||
for(var/mob/living/carbon/C in oviewers(3, null))
|
||||
var/safety = C.eyecheck()
|
||||
if(!safety)
|
||||
if(!C.blinded)
|
||||
C.flash_eyes()
|
||||
|
||||
return
|
||||
|
||||
/obj/item/device/flash/emp_act(severity)
|
||||
if(broken) return
|
||||
flash_recharge()
|
||||
if(!check_capacitor())
|
||||
return
|
||||
|
||||
if(istype(loc, /mob/living/carbon))
|
||||
var/mob/living/carbon/C = loc
|
||||
var/safety = C.eyecheck()
|
||||
if(safety <= 0)
|
||||
C.adjustHalLoss(halloss_per_flash)
|
||||
//C.Weaken(10)
|
||||
C.flash_eyes()
|
||||
for(var/mob/M in viewers(C, null))
|
||||
M.show_message("<span class='disarm'>[C] is blinded by the flash!</span>")
|
||||
..()
|
||||
|
||||
/obj/item/device/flash/synthetic
|
||||
name = "synthetic flash"
|
||||
desc = "When a problem arises, SCIENCE is the solution."
|
||||
icon_state = "sflash"
|
||||
origin_tech = list(TECH_MAGNET = 2, TECH_COMBAT = 1)
|
||||
base_icon = "sflash"
|
||||
can_repair = FALSE
|
||||
|
||||
//attack_as_weapon
|
||||
/obj/item/device/flash/synthetic/attack(mob/living/M, mob/living/user, var/target_zone)
|
||||
..()
|
||||
if(!broken)
|
||||
broken = 1
|
||||
to_chat(user, "<span class='warning'>The bulb has burnt out!</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/flash/synthetic/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0)
|
||||
..()
|
||||
if(!broken)
|
||||
broken = 1
|
||||
to_chat(user, "<span class='warning'>The bulb has burnt out!</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/flash/robot
|
||||
name = "mounted flash"
|
||||
can_break = FALSE
|
||||
use_external_power = TRUE
|
||||
charge_only = TRUE
|
||||
|
||||
@@ -1,493 +1,493 @@
|
||||
/*
|
||||
* Contains:
|
||||
* Flashlights
|
||||
* Lamps
|
||||
* Flares
|
||||
* Chemlights
|
||||
* Slime Extract
|
||||
*/
|
||||
|
||||
/*
|
||||
* Flashlights
|
||||
*/
|
||||
|
||||
/obj/item/device/flashlight
|
||||
name = "flashlight"
|
||||
desc = "A hand-held emergency light."
|
||||
icon = 'icons/obj/lighting.dmi'
|
||||
icon_state = "flashlight"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
slot_flags = SLOT_BELT
|
||||
matter = list(MAT_STEEL = 50,MAT_GLASS = 20)
|
||||
action_button_name = "Toggle Flashlight"
|
||||
|
||||
light_system = MOVABLE_LIGHT_DIRECTIONAL
|
||||
light_range = 4 //luminosity when on
|
||||
light_power = 0.8 //lighting power when on
|
||||
light_color = "#FFFFFF" //LIGHT_COLOR_INCANDESCENT_FLASHLIGHT //lighting colour when on
|
||||
light_cone_y_offset = -7
|
||||
|
||||
var/on = 0
|
||||
|
||||
var/obj/item/weapon/cell/cell
|
||||
var/cell_type = /obj/item/weapon/cell/device
|
||||
var/power_usage = 1
|
||||
var/power_use = 1
|
||||
|
||||
/obj/item/device/flashlight/Initialize()
|
||||
. = ..()
|
||||
|
||||
if(power_use && cell_type)
|
||||
cell = new cell_type(src)
|
||||
|
||||
update_brightness()
|
||||
|
||||
/obj/item/device/flashlight/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
qdel_null(cell)
|
||||
return ..()
|
||||
|
||||
/obj/item/device/flashlight/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/item/device/flashlight/process()
|
||||
if(!on || !cell)
|
||||
return PROCESS_KILL
|
||||
|
||||
if(power_usage)
|
||||
if(cell.use(power_usage) != power_usage) // we weren't able to use our full power_usage amount!
|
||||
visible_message("<span class='warning'>\The [src] flickers before going dull.</span>")
|
||||
playsound(src, 'sound/effects/sparks3.ogg', 10, 1, -3) //Small cue that your light went dull in your pocket. //VOREStation Edit
|
||||
on = 0
|
||||
update_brightness()
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/item/device/flashlight/proc/update_brightness()
|
||||
if(on)
|
||||
icon_state = "[initial(icon_state)]-on"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
set_light_on(on)
|
||||
if(light_system == STATIC_LIGHT)
|
||||
update_light()
|
||||
|
||||
/obj/item/device/flashlight/examine(mob/user)
|
||||
. = ..()
|
||||
if(power_use && cell)
|
||||
. += "\The [src] has a \the [cell] attached."
|
||||
|
||||
if(cell.charge <= cell.maxcharge*0.25)
|
||||
. += "It appears to have a low amount of power remaining."
|
||||
else if(cell.charge > cell.maxcharge*0.25 && cell.charge <= cell.maxcharge*0.5)
|
||||
. += "It appears to have an average amount of power remaining."
|
||||
else if(cell.charge > cell.maxcharge*0.5 && cell.charge <= cell.maxcharge*0.75)
|
||||
. += "It appears to have an above average amount of power remaining."
|
||||
else if(cell.charge > cell.maxcharge*0.75 && cell.charge <= cell.maxcharge)
|
||||
. += "It appears to have a high amount of power remaining."
|
||||
|
||||
/obj/item/device/flashlight/attack_self(mob/user)
|
||||
if(power_use)
|
||||
if(!isturf(user.loc))
|
||||
to_chat(user, "You cannot turn the light on while in this [user.loc].") //To prevent some lighting anomalities.
|
||||
return 0
|
||||
if(!cell || cell.charge == 0)
|
||||
to_chat(user, "You flick the switch on [src], but nothing happens.")
|
||||
return 0
|
||||
on = !on
|
||||
if(on && power_use)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else if(power_use)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
playsound(src, 'sound/weapons/empty.ogg', 15, 1, -3) // VOREStation Edit
|
||||
update_brightness()
|
||||
user.update_action_buttons()
|
||||
return 1
|
||||
|
||||
/obj/item/device/flashlight/emp_act(severity)
|
||||
for(var/obj/O in contents)
|
||||
O.emp_act(severity)
|
||||
..()
|
||||
|
||||
/obj/item/device/flashlight/attack(mob/living/M as mob, mob/living/user as mob)
|
||||
add_fingerprint(user)
|
||||
if(on && user.zone_sel.selecting == O_EYES)
|
||||
|
||||
if((CLUMSY in user.mutations) && prob(50)) //too dumb to use flashlight properly
|
||||
return ..() //just hit them in the head
|
||||
|
||||
var/mob/living/carbon/human/H = M //mob has protective eyewear
|
||||
if(istype(H))
|
||||
for(var/obj/item/clothing/C in list(H.head,H.wear_mask,H.glasses))
|
||||
if(istype(C) && (C.body_parts_covered & EYES))
|
||||
to_chat(user, "<span class='warning'>You're going to need to remove [C.name] first.</span>")
|
||||
return
|
||||
|
||||
var/obj/item/organ/vision
|
||||
if(H.species.vision_organ)
|
||||
vision = H.internal_organs_by_name[H.species.vision_organ]
|
||||
if(!vision)
|
||||
user.visible_message("<b>\The [user]</b> directs [src] at [M]'s face.", \
|
||||
"<span class='notice'>You direct [src] at [M]'s face.</span>")
|
||||
to_chat(user, "<span class='warning'>You can't find any [H.species.vision_organ ? H.species.vision_organ : "eyes"] on [H]!</span>")
|
||||
user.setClickCooldown(user.get_attack_speed(src))
|
||||
return
|
||||
|
||||
user.visible_message("<b>\The [user]</b> directs [src] to [M]'s eyes.", \
|
||||
"<span class='notice'>You direct [src] to [M]'s eyes.</span>")
|
||||
if(H != user) //can't look into your own eyes buster
|
||||
if(M.stat == DEAD || M.blinded) //mob is dead or fully blind
|
||||
to_chat(user, "<span class='warning'>\The [M]'s pupils do not react to the light!</span>")
|
||||
return
|
||||
if(XRAY in M.mutations)
|
||||
to_chat(user, "<span class='notice'>\The [M] pupils give an eerie glow!</span>")
|
||||
if(vision.is_bruised())
|
||||
to_chat(user, "<span class='warning'>There's visible damage to [M]'s [vision.name]!</span>")
|
||||
else if(M.eye_blurry)
|
||||
to_chat(user, "<span class='notice'>\The [M]'s pupils react slower than normally.</span>")
|
||||
if(M.getBrainLoss() > 15)
|
||||
to_chat(user, "<span class='notice'>There's visible lag between left and right pupils' reactions.</span>")
|
||||
|
||||
var/list/pinpoint = list("oxycodone"=1,"tramadol"=5)
|
||||
var/list/dilating = list("bliss"=5,"ambrosia_extract"=5,"mindbreaker"=1)
|
||||
if(M.reagents.has_any_reagent(pinpoint) || H.ingested.has_any_reagent(pinpoint))
|
||||
to_chat(user, "<span class='notice'>\The [M]'s pupils are already pinpoint and cannot narrow any more.</span>")
|
||||
else if(M.reagents.has_any_reagent(dilating) || H.ingested.has_any_reagent(dilating))
|
||||
to_chat(user, "<span class='notice'>\The [M]'s pupils narrow slightly, but are still very dilated.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>\The [M]'s pupils narrow.</span>")
|
||||
|
||||
user.setClickCooldown(user.get_attack_speed(src)) //can be used offensively
|
||||
M.flash_eyes()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/device/flashlight/attack_hand(mob/user as mob)
|
||||
if(user.get_inactive_hand() == src)
|
||||
if(cell)
|
||||
cell.update_icon()
|
||||
user.put_in_hands(cell)
|
||||
cell = null
|
||||
to_chat(user, "<span class='notice'>You remove the cell from the [src].</span>")
|
||||
playsound(src, 'sound/machines/button.ogg', 30, 1, 0)
|
||||
on = 0
|
||||
update_brightness()
|
||||
return
|
||||
..()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/device/flashlight/MouseDrop(obj/over_object as obj)
|
||||
if(!canremove)
|
||||
return
|
||||
|
||||
if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist
|
||||
|
||||
if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why?
|
||||
return
|
||||
|
||||
if (!( istype(over_object, /obj/screen) ))
|
||||
return ..()
|
||||
|
||||
//makes sure that the thing is equipped, so that we can't drag it into our hand from miles away.
|
||||
//there's got to be a better way of doing this.
|
||||
if (!(src.loc == usr) || (src.loc && src.loc.loc == usr))
|
||||
return
|
||||
|
||||
if (( usr.restrained() ) || ( usr.stat ))
|
||||
return
|
||||
|
||||
if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src))
|
||||
return
|
||||
|
||||
switch(over_object.name)
|
||||
if("r_hand")
|
||||
usr.u_equip(src)
|
||||
usr.put_in_r_hand(src)
|
||||
if("l_hand")
|
||||
usr.u_equip(src)
|
||||
usr.put_in_l_hand(src)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
/obj/item/device/flashlight/attackby(obj/item/weapon/W, mob/user as mob)
|
||||
if(power_use)
|
||||
if(istype(W, /obj/item/weapon/cell))
|
||||
if(istype(W, /obj/item/weapon/cell/device))
|
||||
if(!cell)
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
cell = W
|
||||
to_chat(user, "<span class='notice'>You install a cell in \the [src].</span>")
|
||||
playsound(src, 'sound/machines/button.ogg', 30, 1, 0)
|
||||
update_brightness()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>\The [src] already has a cell.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>\The [src] cannot use that type of cell.</span>")
|
||||
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/flashlight/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!on)
|
||||
return
|
||||
if(light_system == MOVABLE_LIGHT_DIRECTIONAL)
|
||||
var/datum/component/overlay_lighting/OL = GetComponent(/datum/component/overlay_lighting)
|
||||
if(!OL)
|
||||
return
|
||||
var/turf/T = get_turf(target)
|
||||
OL.place_directional_light(T)
|
||||
|
||||
/obj/item/device/flashlight/pen
|
||||
name = "penlight"
|
||||
desc = "A pen-sized light, used by medical staff."
|
||||
icon_state = "penlight"
|
||||
item_state = "pen"
|
||||
drop_sound = 'sound/items/drop/accessory.ogg'
|
||||
pickup_sound = 'sound/items/pickup/accessory.ogg'
|
||||
slot_flags = SLOT_EARS
|
||||
light_range = 2
|
||||
w_class = ITEMSIZE_TINY
|
||||
power_use = 0
|
||||
|
||||
/obj/item/device/flashlight/color //Default color is blue
|
||||
name = "blue flashlight"
|
||||
desc = "A small flashlight. This one is blue."
|
||||
icon_state = "flashlight_blue"
|
||||
|
||||
/obj/item/device/flashlight/color/green
|
||||
name = "green flashlight"
|
||||
desc = "A small flashlight. This one is green."
|
||||
icon_state = "flashlight_green"
|
||||
|
||||
/obj/item/device/flashlight/color/purple
|
||||
name = "purple flashlight"
|
||||
desc = "A small flashlight. This one is purple."
|
||||
icon_state = "flashlight_purple"
|
||||
|
||||
/obj/item/device/flashlight/color/red
|
||||
name = "red flashlight"
|
||||
desc = "A small flashlight. This one is red."
|
||||
icon_state = "flashlight_red"
|
||||
|
||||
/obj/item/device/flashlight/color/orange
|
||||
name = "orange flashlight"
|
||||
desc = "A small flashlight. This one is orange."
|
||||
icon_state = "flashlight_orange"
|
||||
|
||||
/obj/item/device/flashlight/color/yellow
|
||||
name = "yellow flashlight"
|
||||
desc = "A small flashlight. This one is yellow."
|
||||
icon_state = "flashlight_yellow"
|
||||
|
||||
/obj/item/device/flashlight/maglight
|
||||
name = "maglight"
|
||||
desc = "A very, very heavy duty flashlight."
|
||||
icon_state = "maglight"
|
||||
light_color = LIGHT_COLOR_FLUORESCENT_FLASHLIGHT
|
||||
force = 10
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = ITEMSIZE_SMALL
|
||||
attack_verb = list ("smacked", "thwacked", "thunked")
|
||||
matter = list(MAT_STEEL = 200,MAT_GLASS = 50)
|
||||
hitsound = "swing_hit"
|
||||
|
||||
/obj/item/device/flashlight/drone
|
||||
name = "low-power flashlight"
|
||||
desc = "A miniature lamp, that might be used by small robots."
|
||||
icon_state = "penlight"
|
||||
item_state = null
|
||||
light_range = 2
|
||||
w_class = ITEMSIZE_TINY
|
||||
power_use = 0
|
||||
|
||||
/*
|
||||
* Lamps
|
||||
*/
|
||||
|
||||
// pixar desk lamp
|
||||
/obj/item/device/flashlight/lamp
|
||||
name = "desk lamp"
|
||||
desc = "A desk lamp with an adjustable mount."
|
||||
icon_state = "lamp"
|
||||
force = 10
|
||||
center_of_mass = list("x" = 13,"y" = 11)
|
||||
light_range = 5
|
||||
w_class = ITEMSIZE_LARGE
|
||||
power_use = 0
|
||||
on = 1
|
||||
light_system = STATIC_LIGHT
|
||||
|
||||
/obj/item/device/flashlight/lamp/verb/toggle_light()
|
||||
set name = "Toggle light"
|
||||
set category = "Object"
|
||||
set src in oview(1)
|
||||
|
||||
if(!usr.stat)
|
||||
attack_self(usr)
|
||||
|
||||
// green-shaded desk lamp
|
||||
/obj/item/device/flashlight/lamp/green
|
||||
desc = "A classic green-shaded desk lamp."
|
||||
icon_state = "lampgreen"
|
||||
center_of_mass = list("x" = 15,"y" = 11)
|
||||
light_color = "#FFC58F"
|
||||
|
||||
// clown lamp
|
||||
/obj/item/device/flashlight/lamp/clown
|
||||
desc = "A whacky banana peel shaped lamp."
|
||||
icon_state = "bananalamp"
|
||||
center_of_mass = list("x" = 15,"y" = 11)
|
||||
|
||||
|
||||
/*
|
||||
* Flares
|
||||
*/
|
||||
|
||||
/obj/item/device/flashlight/flare
|
||||
name = "flare"
|
||||
desc = "A red standard-issue flare. There are instructions on the side reading 'pull cord, make light'."
|
||||
w_class = ITEMSIZE_SMALL
|
||||
light_range = 8 // Pretty bright.
|
||||
light_power = 0.8
|
||||
light_color = LIGHT_COLOR_FLARE
|
||||
icon_state = "flare"
|
||||
item_state = "flare"
|
||||
action_button_name = null //just pull it manually, neckbeard.
|
||||
var/fuel = 0
|
||||
var/on_damage = 7
|
||||
var/produce_heat = 1500
|
||||
power_use = 0
|
||||
drop_sound = 'sound/items/drop/gloves.ogg'
|
||||
pickup_sound = 'sound/items/pickup/gloves.ogg'
|
||||
light_system = MOVABLE_LIGHT
|
||||
|
||||
/obj/item/device/flashlight/flare/New()
|
||||
fuel = rand(800, 1000) // Sorry for changing this so much but I keep under-estimating how long X number of ticks last in seconds.
|
||||
..()
|
||||
|
||||
/obj/item/device/flashlight/flare/process()
|
||||
var/turf/pos = get_turf(src)
|
||||
if(pos)
|
||||
pos.hotspot_expose(produce_heat, 5)
|
||||
fuel = max(fuel - 1, 0)
|
||||
if(!fuel || !on)
|
||||
turn_off()
|
||||
if(!fuel)
|
||||
src.icon_state = "[initial(icon_state)]-empty"
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/device/flashlight/flare/proc/turn_off()
|
||||
on = 0
|
||||
src.force = initial(src.force)
|
||||
src.damtype = initial(src.damtype)
|
||||
update_brightness()
|
||||
|
||||
/obj/item/device/flashlight/flare/attack_self(mob/user)
|
||||
|
||||
// Usual checks
|
||||
if(!fuel)
|
||||
to_chat(user, "<span class='notice'>It's out of fuel.</span>")
|
||||
return
|
||||
if(on)
|
||||
return
|
||||
|
||||
. = ..()
|
||||
// All good, turn it on.
|
||||
if(.)
|
||||
user.visible_message("<span class='notice'>[user] activates the flare.</span>", "<span class='notice'>You pull the cord on the flare, activating it!</span>")
|
||||
src.force = on_damage
|
||||
src.damtype = "fire"
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/device/flashlight/flare/proc/ignite() //Used for flare launchers.
|
||||
on = !on
|
||||
update_brightness()
|
||||
force = on_damage
|
||||
damtype = "fire"
|
||||
START_PROCESSING(SSobj, src)
|
||||
return 1
|
||||
|
||||
/*
|
||||
* Chemlights
|
||||
*/
|
||||
|
||||
/obj/item/device/flashlight/glowstick
|
||||
name = "green glowstick"
|
||||
desc = "A green military-grade chemical light."
|
||||
w_class = ITEMSIZE_SMALL
|
||||
light_system = MOVABLE_LIGHT
|
||||
light_range = 4
|
||||
light_power = 0.9
|
||||
light_color = "#49F37C"
|
||||
icon_state = "glowstick_green"
|
||||
item_state = "glowstick_green"
|
||||
var/fuel = 0
|
||||
power_use = 0
|
||||
|
||||
/obj/item/device/flashlight/glowstick/New()
|
||||
fuel = rand(1600, 2000)
|
||||
..()
|
||||
|
||||
/obj/item/device/flashlight/glowstick/process()
|
||||
fuel = max(fuel - 1, 0)
|
||||
if(!fuel || !on)
|
||||
turn_off()
|
||||
if(!fuel)
|
||||
src.icon_state = "[initial(icon_state)]-empty"
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/device/flashlight/glowstick/proc/turn_off()
|
||||
on = 0
|
||||
update_brightness()
|
||||
|
||||
/obj/item/device/flashlight/glowstick/attack_self(mob/user)
|
||||
|
||||
if(!fuel)
|
||||
to_chat(user, "<span class='notice'>The glowstick has already been turned on.</span>")
|
||||
return
|
||||
if(on)
|
||||
return
|
||||
|
||||
. = ..()
|
||||
if(.)
|
||||
user.visible_message("<span class='notice'>[user] cracks and shakes \the [name].</span>", "<span class='notice'>You crack and shake \the [src], turning it on!</span>")
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/device/flashlight/glowstick/red
|
||||
name = "red glowstick"
|
||||
desc = "A red military-grade chemical light."
|
||||
light_color = "#FC0F29"
|
||||
icon_state = "glowstick_red"
|
||||
item_state = "glowstick_red"
|
||||
|
||||
/obj/item/device/flashlight/glowstick/blue
|
||||
name = "blue glowstick"
|
||||
desc = "A blue military-grade chemical light."
|
||||
light_color = "#599DFF"
|
||||
icon_state = "glowstick_blue"
|
||||
item_state = "glowstick_blue"
|
||||
|
||||
/obj/item/device/flashlight/glowstick/orange
|
||||
name = "orange glowstick"
|
||||
desc = "A orange military-grade chemical light."
|
||||
light_color = "#FA7C0B"
|
||||
icon_state = "glowstick_orange"
|
||||
item_state = "glowstick_orange"
|
||||
|
||||
/obj/item/device/flashlight/glowstick/yellow
|
||||
name = "yellow glowstick"
|
||||
desc = "A yellow military-grade chemical light."
|
||||
light_color = "#FEF923"
|
||||
icon_state = "glowstick_yellow"
|
||||
item_state = "glowstick_yellow"
|
||||
|
||||
/obj/item/device/flashlight/glowstick/radioisotope
|
||||
name = "radioisotope glowstick"
|
||||
desc = "A radioisotope powered chemical light. Escaping particles light up the area far brighter on similar levels to flares and for longer"
|
||||
icon_state = "glowstick_isotope"
|
||||
item_state = "glowstick_isotope"
|
||||
|
||||
light_range = 8
|
||||
light_power = 0.1
|
||||
light_color = "#49F37C"
|
||||
/*
|
||||
* Contains:
|
||||
* Flashlights
|
||||
* Lamps
|
||||
* Flares
|
||||
* Chemlights
|
||||
* Slime Extract
|
||||
*/
|
||||
|
||||
/*
|
||||
* Flashlights
|
||||
*/
|
||||
|
||||
/obj/item/device/flashlight
|
||||
name = "flashlight"
|
||||
desc = "A hand-held emergency light."
|
||||
icon = 'icons/obj/lighting.dmi'
|
||||
icon_state = "flashlight"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
slot_flags = SLOT_BELT
|
||||
matter = list(MAT_STEEL = 50,MAT_GLASS = 20)
|
||||
action_button_name = "Toggle Flashlight"
|
||||
|
||||
light_system = MOVABLE_LIGHT_DIRECTIONAL
|
||||
light_range = 4 //luminosity when on
|
||||
light_power = 0.8 //lighting power when on
|
||||
light_color = "#FFFFFF" //LIGHT_COLOR_INCANDESCENT_FLASHLIGHT //lighting colour when on
|
||||
light_cone_y_offset = -7
|
||||
|
||||
var/on = 0
|
||||
|
||||
var/obj/item/weapon/cell/cell
|
||||
var/cell_type = /obj/item/weapon/cell/device
|
||||
var/power_usage = 1
|
||||
var/power_use = 1
|
||||
|
||||
/obj/item/device/flashlight/Initialize()
|
||||
. = ..()
|
||||
|
||||
if(power_use && cell_type)
|
||||
cell = new cell_type(src)
|
||||
|
||||
update_brightness()
|
||||
|
||||
/obj/item/device/flashlight/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
qdel_null(cell)
|
||||
return ..()
|
||||
|
||||
/obj/item/device/flashlight/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/item/device/flashlight/process()
|
||||
if(!on || !cell)
|
||||
return PROCESS_KILL
|
||||
|
||||
if(power_usage)
|
||||
if(cell.use(power_usage) != power_usage) // we weren't able to use our full power_usage amount!
|
||||
visible_message("<span class='warning'>\The [src] flickers before going dull.</span>")
|
||||
playsound(src, 'sound/effects/sparks3.ogg', 10, 1, -3) //Small cue that your light went dull in your pocket. //VOREStation Edit
|
||||
on = 0
|
||||
update_brightness()
|
||||
return PROCESS_KILL
|
||||
|
||||
/obj/item/device/flashlight/proc/update_brightness()
|
||||
if(on)
|
||||
icon_state = "[initial(icon_state)]-on"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
set_light_on(on)
|
||||
if(light_system == STATIC_LIGHT)
|
||||
update_light()
|
||||
|
||||
/obj/item/device/flashlight/examine(mob/user)
|
||||
. = ..()
|
||||
if(power_use && cell)
|
||||
. += "\The [src] has a \the [cell] attached."
|
||||
|
||||
if(cell.charge <= cell.maxcharge*0.25)
|
||||
. += "It appears to have a low amount of power remaining."
|
||||
else if(cell.charge > cell.maxcharge*0.25 && cell.charge <= cell.maxcharge*0.5)
|
||||
. += "It appears to have an average amount of power remaining."
|
||||
else if(cell.charge > cell.maxcharge*0.5 && cell.charge <= cell.maxcharge*0.75)
|
||||
. += "It appears to have an above average amount of power remaining."
|
||||
else if(cell.charge > cell.maxcharge*0.75 && cell.charge <= cell.maxcharge)
|
||||
. += "It appears to have a high amount of power remaining."
|
||||
|
||||
/obj/item/device/flashlight/attack_self(mob/user)
|
||||
if(power_use)
|
||||
if(!isturf(user.loc))
|
||||
to_chat(user, "You cannot turn the light on while in this [user.loc].") //To prevent some lighting anomalities.
|
||||
return 0
|
||||
if(!cell || cell.charge == 0)
|
||||
to_chat(user, "You flick the switch on [src], but nothing happens.")
|
||||
return 0
|
||||
on = !on
|
||||
if(on && power_use)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else if(power_use)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
playsound(src, 'sound/weapons/empty.ogg', 15, 1, -3) // VOREStation Edit
|
||||
update_brightness()
|
||||
user.update_action_buttons()
|
||||
return 1
|
||||
|
||||
/obj/item/device/flashlight/emp_act(severity)
|
||||
for(var/obj/O in contents)
|
||||
O.emp_act(severity)
|
||||
..()
|
||||
|
||||
/obj/item/device/flashlight/attack(mob/living/M as mob, mob/living/user as mob)
|
||||
add_fingerprint(user)
|
||||
if(on && user.zone_sel.selecting == O_EYES)
|
||||
|
||||
if((CLUMSY in user.mutations) && prob(50)) //too dumb to use flashlight properly
|
||||
return ..() //just hit them in the head
|
||||
|
||||
var/mob/living/carbon/human/H = M //mob has protective eyewear
|
||||
if(istype(H))
|
||||
for(var/obj/item/clothing/C in list(H.head,H.wear_mask,H.glasses))
|
||||
if(istype(C) && (C.body_parts_covered & EYES))
|
||||
to_chat(user, "<span class='warning'>You're going to need to remove [C.name] first.</span>")
|
||||
return
|
||||
|
||||
var/obj/item/organ/vision
|
||||
if(H.species.vision_organ)
|
||||
vision = H.internal_organs_by_name[H.species.vision_organ]
|
||||
if(!vision)
|
||||
user.visible_message("<b>\The [user]</b> directs [src] at [M]'s face.", \
|
||||
"<span class='notice'>You direct [src] at [M]'s face.</span>")
|
||||
to_chat(user, "<span class='warning'>You can't find any [H.species.vision_organ ? H.species.vision_organ : "eyes"] on [H]!</span>")
|
||||
user.setClickCooldown(user.get_attack_speed(src))
|
||||
return
|
||||
|
||||
user.visible_message("<b>\The [user]</b> directs [src] to [M]'s eyes.", \
|
||||
"<span class='notice'>You direct [src] to [M]'s eyes.</span>")
|
||||
if(H != user) //can't look into your own eyes buster
|
||||
if(M.stat == DEAD || M.blinded) //mob is dead or fully blind
|
||||
to_chat(user, "<span class='warning'>\The [M]'s pupils do not react to the light!</span>")
|
||||
return
|
||||
if(XRAY in M.mutations)
|
||||
to_chat(user, "<span class='notice'>\The [M] pupils give an eerie glow!</span>")
|
||||
if(vision.is_bruised())
|
||||
to_chat(user, "<span class='warning'>There's visible damage to [M]'s [vision.name]!</span>")
|
||||
else if(M.eye_blurry)
|
||||
to_chat(user, "<span class='notice'>\The [M]'s pupils react slower than normally.</span>")
|
||||
if(M.getBrainLoss() > 15)
|
||||
to_chat(user, "<span class='notice'>There's visible lag between left and right pupils' reactions.</span>")
|
||||
|
||||
var/list/pinpoint = list("oxycodone"=1,"tramadol"=5)
|
||||
var/list/dilating = list("bliss"=5,"ambrosia_extract"=5,"mindbreaker"=1)
|
||||
if(M.reagents.has_any_reagent(pinpoint) || H.ingested.has_any_reagent(pinpoint))
|
||||
to_chat(user, "<span class='notice'>\The [M]'s pupils are already pinpoint and cannot narrow any more.</span>")
|
||||
else if(M.reagents.has_any_reagent(dilating) || H.ingested.has_any_reagent(dilating))
|
||||
to_chat(user, "<span class='notice'>\The [M]'s pupils narrow slightly, but are still very dilated.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>\The [M]'s pupils narrow.</span>")
|
||||
|
||||
user.setClickCooldown(user.get_attack_speed(src)) //can be used offensively
|
||||
M.flash_eyes()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/device/flashlight/attack_hand(mob/user as mob)
|
||||
if(user.get_inactive_hand() == src)
|
||||
if(cell)
|
||||
cell.update_icon()
|
||||
user.put_in_hands(cell)
|
||||
cell = null
|
||||
to_chat(user, "<span class='notice'>You remove the cell from the [src].</span>")
|
||||
playsound(src, 'sound/machines/button.ogg', 30, 1, 0)
|
||||
on = 0
|
||||
update_brightness()
|
||||
return
|
||||
..()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/device/flashlight/MouseDrop(obj/over_object as obj)
|
||||
if(!canremove)
|
||||
return
|
||||
|
||||
if (ishuman(usr) || issmall(usr)) //so monkeys can take off their backpacks -- Urist
|
||||
|
||||
if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech. why?
|
||||
return
|
||||
|
||||
if (!( istype(over_object, /obj/screen) ))
|
||||
return ..()
|
||||
|
||||
//makes sure that the thing is equipped, so that we can't drag it into our hand from miles away.
|
||||
//there's got to be a better way of doing this.
|
||||
if (!(src.loc == usr) || (src.loc && src.loc.loc == usr))
|
||||
return
|
||||
|
||||
if (( usr.restrained() ) || ( usr.stat ))
|
||||
return
|
||||
|
||||
if ((src.loc == usr) && !(istype(over_object, /obj/screen)) && !usr.unEquip(src))
|
||||
return
|
||||
|
||||
switch(over_object.name)
|
||||
if("r_hand")
|
||||
usr.u_equip(src)
|
||||
usr.put_in_r_hand(src)
|
||||
if("l_hand")
|
||||
usr.u_equip(src)
|
||||
usr.put_in_l_hand(src)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
/obj/item/device/flashlight/attackby(obj/item/weapon/W, mob/user as mob)
|
||||
if(power_use)
|
||||
if(istype(W, /obj/item/weapon/cell))
|
||||
if(istype(W, /obj/item/weapon/cell/device))
|
||||
if(!cell)
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
cell = W
|
||||
to_chat(user, "<span class='notice'>You install a cell in \the [src].</span>")
|
||||
playsound(src, 'sound/machines/button.ogg', 30, 1, 0)
|
||||
update_brightness()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>\The [src] already has a cell.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>\The [src] cannot use that type of cell.</span>")
|
||||
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/flashlight/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!on)
|
||||
return
|
||||
if(light_system == MOVABLE_LIGHT_DIRECTIONAL)
|
||||
var/datum/component/overlay_lighting/OL = GetComponent(/datum/component/overlay_lighting)
|
||||
if(!OL)
|
||||
return
|
||||
var/turf/T = get_turf(target)
|
||||
OL.place_directional_light(T)
|
||||
|
||||
/obj/item/device/flashlight/pen
|
||||
name = "penlight"
|
||||
desc = "A pen-sized light, used by medical staff."
|
||||
icon_state = "penlight"
|
||||
item_state = "pen"
|
||||
drop_sound = 'sound/items/drop/accessory.ogg'
|
||||
pickup_sound = 'sound/items/pickup/accessory.ogg'
|
||||
slot_flags = SLOT_EARS
|
||||
light_range = 2
|
||||
w_class = ITEMSIZE_TINY
|
||||
power_use = 0
|
||||
|
||||
/obj/item/device/flashlight/color //Default color is blue
|
||||
name = "blue flashlight"
|
||||
desc = "A small flashlight. This one is blue."
|
||||
icon_state = "flashlight_blue"
|
||||
|
||||
/obj/item/device/flashlight/color/green
|
||||
name = "green flashlight"
|
||||
desc = "A small flashlight. This one is green."
|
||||
icon_state = "flashlight_green"
|
||||
|
||||
/obj/item/device/flashlight/color/purple
|
||||
name = "purple flashlight"
|
||||
desc = "A small flashlight. This one is purple."
|
||||
icon_state = "flashlight_purple"
|
||||
|
||||
/obj/item/device/flashlight/color/red
|
||||
name = "red flashlight"
|
||||
desc = "A small flashlight. This one is red."
|
||||
icon_state = "flashlight_red"
|
||||
|
||||
/obj/item/device/flashlight/color/orange
|
||||
name = "orange flashlight"
|
||||
desc = "A small flashlight. This one is orange."
|
||||
icon_state = "flashlight_orange"
|
||||
|
||||
/obj/item/device/flashlight/color/yellow
|
||||
name = "yellow flashlight"
|
||||
desc = "A small flashlight. This one is yellow."
|
||||
icon_state = "flashlight_yellow"
|
||||
|
||||
/obj/item/device/flashlight/maglight
|
||||
name = "maglight"
|
||||
desc = "A very, very heavy duty flashlight."
|
||||
icon_state = "maglight"
|
||||
light_color = LIGHT_COLOR_FLUORESCENT_FLASHLIGHT
|
||||
force = 10
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = ITEMSIZE_SMALL
|
||||
attack_verb = list ("smacked", "thwacked", "thunked")
|
||||
matter = list(MAT_STEEL = 200,MAT_GLASS = 50)
|
||||
hitsound = "swing_hit"
|
||||
|
||||
/obj/item/device/flashlight/drone
|
||||
name = "low-power flashlight"
|
||||
desc = "A miniature lamp, that might be used by small robots."
|
||||
icon_state = "penlight"
|
||||
item_state = null
|
||||
light_range = 2
|
||||
w_class = ITEMSIZE_TINY
|
||||
power_use = 0
|
||||
|
||||
/*
|
||||
* Lamps
|
||||
*/
|
||||
|
||||
// pixar desk lamp
|
||||
/obj/item/device/flashlight/lamp
|
||||
name = "desk lamp"
|
||||
desc = "A desk lamp with an adjustable mount."
|
||||
icon_state = "lamp"
|
||||
force = 10
|
||||
center_of_mass = list("x" = 13,"y" = 11)
|
||||
light_range = 5
|
||||
w_class = ITEMSIZE_LARGE
|
||||
power_use = 0
|
||||
on = 1
|
||||
light_system = STATIC_LIGHT
|
||||
|
||||
/obj/item/device/flashlight/lamp/verb/toggle_light()
|
||||
set name = "Toggle light"
|
||||
set category = "Object"
|
||||
set src in oview(1)
|
||||
|
||||
if(!usr.stat)
|
||||
attack_self(usr)
|
||||
|
||||
// green-shaded desk lamp
|
||||
/obj/item/device/flashlight/lamp/green
|
||||
desc = "A classic green-shaded desk lamp."
|
||||
icon_state = "lampgreen"
|
||||
center_of_mass = list("x" = 15,"y" = 11)
|
||||
light_color = "#FFC58F"
|
||||
|
||||
// clown lamp
|
||||
/obj/item/device/flashlight/lamp/clown
|
||||
desc = "A whacky banana peel shaped lamp."
|
||||
icon_state = "bananalamp"
|
||||
center_of_mass = list("x" = 15,"y" = 11)
|
||||
|
||||
|
||||
/*
|
||||
* Flares
|
||||
*/
|
||||
|
||||
/obj/item/device/flashlight/flare
|
||||
name = "flare"
|
||||
desc = "A red standard-issue flare. There are instructions on the side reading 'pull cord, make light'."
|
||||
w_class = ITEMSIZE_SMALL
|
||||
light_range = 8 // Pretty bright.
|
||||
light_power = 0.8
|
||||
light_color = LIGHT_COLOR_FLARE
|
||||
icon_state = "flare"
|
||||
item_state = "flare"
|
||||
action_button_name = null //just pull it manually, neckbeard.
|
||||
var/fuel = 0
|
||||
var/on_damage = 7
|
||||
var/produce_heat = 1500
|
||||
power_use = 0
|
||||
drop_sound = 'sound/items/drop/gloves.ogg'
|
||||
pickup_sound = 'sound/items/pickup/gloves.ogg'
|
||||
light_system = MOVABLE_LIGHT
|
||||
|
||||
/obj/item/device/flashlight/flare/New()
|
||||
fuel = rand(800, 1000) // Sorry for changing this so much but I keep under-estimating how long X number of ticks last in seconds.
|
||||
..()
|
||||
|
||||
/obj/item/device/flashlight/flare/process()
|
||||
var/turf/pos = get_turf(src)
|
||||
if(pos)
|
||||
pos.hotspot_expose(produce_heat, 5)
|
||||
fuel = max(fuel - 1, 0)
|
||||
if(!fuel || !on)
|
||||
turn_off()
|
||||
if(!fuel)
|
||||
src.icon_state = "[initial(icon_state)]-empty"
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/device/flashlight/flare/proc/turn_off()
|
||||
on = 0
|
||||
src.force = initial(src.force)
|
||||
src.damtype = initial(src.damtype)
|
||||
update_brightness()
|
||||
|
||||
/obj/item/device/flashlight/flare/attack_self(mob/user)
|
||||
|
||||
// Usual checks
|
||||
if(!fuel)
|
||||
to_chat(user, "<span class='notice'>It's out of fuel.</span>")
|
||||
return
|
||||
if(on)
|
||||
return
|
||||
|
||||
. = ..()
|
||||
// All good, turn it on.
|
||||
if(.)
|
||||
user.visible_message("<span class='notice'>[user] activates the flare.</span>", "<span class='notice'>You pull the cord on the flare, activating it!</span>")
|
||||
src.force = on_damage
|
||||
src.damtype = "fire"
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/device/flashlight/flare/proc/ignite() //Used for flare launchers.
|
||||
on = !on
|
||||
update_brightness()
|
||||
force = on_damage
|
||||
damtype = "fire"
|
||||
START_PROCESSING(SSobj, src)
|
||||
return 1
|
||||
|
||||
/*
|
||||
* Chemlights
|
||||
*/
|
||||
|
||||
/obj/item/device/flashlight/glowstick
|
||||
name = "green glowstick"
|
||||
desc = "A green military-grade chemical light."
|
||||
w_class = ITEMSIZE_SMALL
|
||||
light_system = MOVABLE_LIGHT
|
||||
light_range = 4
|
||||
light_power = 0.9
|
||||
light_color = "#49F37C"
|
||||
icon_state = "glowstick_green"
|
||||
item_state = "glowstick_green"
|
||||
var/fuel = 0
|
||||
power_use = 0
|
||||
|
||||
/obj/item/device/flashlight/glowstick/New()
|
||||
fuel = rand(1600, 2000)
|
||||
..()
|
||||
|
||||
/obj/item/device/flashlight/glowstick/process()
|
||||
fuel = max(fuel - 1, 0)
|
||||
if(!fuel || !on)
|
||||
turn_off()
|
||||
if(!fuel)
|
||||
src.icon_state = "[initial(icon_state)]-empty"
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/device/flashlight/glowstick/proc/turn_off()
|
||||
on = 0
|
||||
update_brightness()
|
||||
|
||||
/obj/item/device/flashlight/glowstick/attack_self(mob/user)
|
||||
|
||||
if(!fuel)
|
||||
to_chat(user, "<span class='notice'>The glowstick has already been turned on.</span>")
|
||||
return
|
||||
if(on)
|
||||
return
|
||||
|
||||
. = ..()
|
||||
if(.)
|
||||
user.visible_message("<span class='notice'>[user] cracks and shakes \the [name].</span>", "<span class='notice'>You crack and shake \the [src], turning it on!</span>")
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/device/flashlight/glowstick/red
|
||||
name = "red glowstick"
|
||||
desc = "A red military-grade chemical light."
|
||||
light_color = "#FC0F29"
|
||||
icon_state = "glowstick_red"
|
||||
item_state = "glowstick_red"
|
||||
|
||||
/obj/item/device/flashlight/glowstick/blue
|
||||
name = "blue glowstick"
|
||||
desc = "A blue military-grade chemical light."
|
||||
light_color = "#599DFF"
|
||||
icon_state = "glowstick_blue"
|
||||
item_state = "glowstick_blue"
|
||||
|
||||
/obj/item/device/flashlight/glowstick/orange
|
||||
name = "orange glowstick"
|
||||
desc = "A orange military-grade chemical light."
|
||||
light_color = "#FA7C0B"
|
||||
icon_state = "glowstick_orange"
|
||||
item_state = "glowstick_orange"
|
||||
|
||||
/obj/item/device/flashlight/glowstick/yellow
|
||||
name = "yellow glowstick"
|
||||
desc = "A yellow military-grade chemical light."
|
||||
light_color = "#FEF923"
|
||||
icon_state = "glowstick_yellow"
|
||||
item_state = "glowstick_yellow"
|
||||
|
||||
/obj/item/device/flashlight/glowstick/radioisotope
|
||||
name = "radioisotope glowstick"
|
||||
desc = "A radioisotope powered chemical light. Escaping particles light up the area far brighter on similar levels to flares and for longer"
|
||||
icon_state = "glowstick_isotope"
|
||||
item_state = "glowstick_isotope"
|
||||
|
||||
light_range = 8
|
||||
light_power = 0.1
|
||||
light_color = "#49F37C"
|
||||
|
||||
@@ -1,130 +1,130 @@
|
||||
/obj/item/device/multitool/hacktool
|
||||
var/is_hacking = 0
|
||||
var/max_known_targets
|
||||
var/hackspeed = 1
|
||||
var/max_level = 4 //what's the max door security_level we can handle?
|
||||
var/full_override = FALSE //can we override door bolts too? defaults to false for event/safety reasons
|
||||
|
||||
var/in_hack_mode = 0
|
||||
var/list/known_targets
|
||||
var/list/supported_types
|
||||
var/datum/tgui_state/default/must_hack/hack_state
|
||||
|
||||
/obj/item/device/multitool/hacktool/override
|
||||
hackspeed = 0.75
|
||||
max_level = 5
|
||||
full_override = TRUE
|
||||
|
||||
/obj/item/device/multitool/hacktool/New()
|
||||
..()
|
||||
known_targets = list()
|
||||
max_known_targets = 5 + rand(1,3)
|
||||
supported_types = list(/obj/machinery/door/airlock)
|
||||
hack_state = new(src)
|
||||
|
||||
/obj/item/device/multitool/hacktool/Destroy()
|
||||
for(var/atom/target as anything in known_targets)
|
||||
target.unregister(OBSERVER_EVENT_DESTROY, src)
|
||||
known_targets.Cut()
|
||||
qdel(hack_state)
|
||||
hack_state = null
|
||||
return ..()
|
||||
|
||||
/obj/item/device/multitool/hacktool/attackby(var/obj/item/W, var/mob/user)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
in_hack_mode = !in_hack_mode
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/multitool/hacktool/afterattack(atom/A, mob/user)
|
||||
sanity_check()
|
||||
|
||||
if(!in_hack_mode)
|
||||
return ..()
|
||||
|
||||
if(!attempt_hack(user, A))
|
||||
return 0
|
||||
|
||||
// Note, if you ever want to expand supported_types, you must manually add the custom state argument to their tgui_interact
|
||||
// DISABLED: too fancy, too high-effort // A.tgui_interact(user, custom_state = hack_state)
|
||||
// Just brute-force it
|
||||
if(istype(A, /obj/machinery/door/airlock))
|
||||
var/obj/machinery/door/airlock/D = A
|
||||
if(!D.arePowerSystemsOn())
|
||||
to_chat(user, "<span class='warning'>No response from remote, check door power.</span>")
|
||||
else if(D.locked == TRUE && full_override == FALSE)
|
||||
to_chat(user, "<span class='warning'>Unable to override door bolts!</span>")
|
||||
else if(D.locked == TRUE && full_override == TRUE && D.arePowerSystemsOn())
|
||||
to_chat(user, "<span class='notice'>Door bolts overridden.</span>")
|
||||
D.unlock()
|
||||
else if(D.density == TRUE && D.locked == FALSE)
|
||||
to_chat(user, "<span class='notice'>Overriding access. Door opening.</span>")
|
||||
D.open()
|
||||
else if(D.density == FALSE && D.locked == FALSE)
|
||||
to_chat(user, "<span class='notice'>Overriding access. Door closing.</span>")
|
||||
D.close()
|
||||
return 1
|
||||
|
||||
/obj/item/device/multitool/hacktool/proc/attempt_hack(var/mob/user, var/atom/target)
|
||||
if(is_hacking)
|
||||
to_chat(user, "<span class='warning'>You are already hacking!</span>")
|
||||
return 0
|
||||
if(!is_type_in_list(target, supported_types))
|
||||
to_chat(user, "\icon[src][bicon(src)] <span class='warning'>Unable to hack this target, invalid target type.</span>")
|
||||
return 0
|
||||
|
||||
var/obj/machinery/door/airlock/D = target
|
||||
if(D.security_level > max_level)
|
||||
to_chat(user, "\icon[src][bicon(src)] <span class='warning'>Target's electronic security is too complex.</span>")
|
||||
return 0
|
||||
|
||||
var/found = known_targets.Find(D)
|
||||
if(found)
|
||||
known_targets.Swap(1, found) // Move the last hacked item first
|
||||
return 1
|
||||
to_chat(user, "<span class='notice'>You begin hacking \the [D]...</span>")
|
||||
is_hacking = 1
|
||||
// On average hackin takes ~15 seconds. Fairly small random span to avoid people simply aborting and trying again
|
||||
// Reduced hack duration to compensate for the reduced functionality, multiplied by door sec level
|
||||
var/hack_result = do_after(user, (((10 SECONDS + rand(0, 10 SECONDS) + rand(0, 10 SECONDS))*hackspeed)*D.security_level))
|
||||
is_hacking = 0
|
||||
|
||||
if(hack_result && in_hack_mode)
|
||||
to_chat(user, "<span class='notice'>Your hacking attempt was succesful!</span>")
|
||||
user.playsound_local(get_turf(src), 'sound/instruments/piano/An6.ogg', 50)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Your hacking attempt failed!</span>")
|
||||
return 0
|
||||
|
||||
known_targets.Insert(1, D) // Insert the newly hacked target first,
|
||||
D.register(OBSERVER_EVENT_DESTROY, src, /obj/item/device/multitool/hacktool/proc/on_target_destroy)
|
||||
return 1
|
||||
|
||||
/obj/item/device/multitool/hacktool/proc/sanity_check()
|
||||
if(max_known_targets < 1) max_known_targets = 1
|
||||
// Cut away the oldest items if the capacity has been reached
|
||||
if(known_targets.len > max_known_targets)
|
||||
for(var/i = (max_known_targets + 1) to known_targets.len)
|
||||
var/atom/A = known_targets[i]
|
||||
A.unregister(OBSERVER_EVENT_DESTROY, src)
|
||||
known_targets.Cut(max_known_targets + 1)
|
||||
|
||||
/obj/item/device/multitool/hacktool/proc/on_target_destroy(var/target)
|
||||
known_targets -= target
|
||||
|
||||
/datum/tgui_state/default/must_hack
|
||||
var/obj/item/device/multitool/hacktool/hacktool
|
||||
|
||||
/datum/tgui_state/default/must_hack/New(var/hacktool)
|
||||
src.hacktool = hacktool
|
||||
..()
|
||||
|
||||
/datum/tgui_state/default/must_hack/Destroy()
|
||||
hacktool = null
|
||||
return ..()
|
||||
|
||||
/datum/tgui_state/default/must_hack/can_use_topic(src_object, mob/user)
|
||||
if(!hacktool || !hacktool.in_hack_mode || !(src_object in hacktool.known_targets))
|
||||
return STATUS_CLOSE
|
||||
return ..()
|
||||
/obj/item/device/multitool/hacktool
|
||||
var/is_hacking = 0
|
||||
var/max_known_targets
|
||||
var/hackspeed = 1
|
||||
var/max_level = 4 //what's the max door security_level we can handle?
|
||||
var/full_override = FALSE //can we override door bolts too? defaults to false for event/safety reasons
|
||||
|
||||
var/in_hack_mode = 0
|
||||
var/list/known_targets
|
||||
var/list/supported_types
|
||||
var/datum/tgui_state/default/must_hack/hack_state
|
||||
|
||||
/obj/item/device/multitool/hacktool/override
|
||||
hackspeed = 0.75
|
||||
max_level = 5
|
||||
full_override = TRUE
|
||||
|
||||
/obj/item/device/multitool/hacktool/New()
|
||||
..()
|
||||
known_targets = list()
|
||||
max_known_targets = 5 + rand(1,3)
|
||||
supported_types = list(/obj/machinery/door/airlock)
|
||||
hack_state = new(src)
|
||||
|
||||
/obj/item/device/multitool/hacktool/Destroy()
|
||||
for(var/atom/target as anything in known_targets)
|
||||
target.unregister(OBSERVER_EVENT_DESTROY, src)
|
||||
known_targets.Cut()
|
||||
qdel(hack_state)
|
||||
hack_state = null
|
||||
return ..()
|
||||
|
||||
/obj/item/device/multitool/hacktool/attackby(var/obj/item/W, var/mob/user)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
in_hack_mode = !in_hack_mode
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/multitool/hacktool/afterattack(atom/A, mob/user)
|
||||
sanity_check()
|
||||
|
||||
if(!in_hack_mode)
|
||||
return ..()
|
||||
|
||||
if(!attempt_hack(user, A))
|
||||
return 0
|
||||
|
||||
// Note, if you ever want to expand supported_types, you must manually add the custom state argument to their tgui_interact
|
||||
// DISABLED: too fancy, too high-effort // A.tgui_interact(user, custom_state = hack_state)
|
||||
// Just brute-force it
|
||||
if(istype(A, /obj/machinery/door/airlock))
|
||||
var/obj/machinery/door/airlock/D = A
|
||||
if(!D.arePowerSystemsOn())
|
||||
to_chat(user, "<span class='warning'>No response from remote, check door power.</span>")
|
||||
else if(D.locked == TRUE && full_override == FALSE)
|
||||
to_chat(user, "<span class='warning'>Unable to override door bolts!</span>")
|
||||
else if(D.locked == TRUE && full_override == TRUE && D.arePowerSystemsOn())
|
||||
to_chat(user, "<span class='notice'>Door bolts overridden.</span>")
|
||||
D.unlock()
|
||||
else if(D.density == TRUE && D.locked == FALSE)
|
||||
to_chat(user, "<span class='notice'>Overriding access. Door opening.</span>")
|
||||
D.open()
|
||||
else if(D.density == FALSE && D.locked == FALSE)
|
||||
to_chat(user, "<span class='notice'>Overriding access. Door closing.</span>")
|
||||
D.close()
|
||||
return 1
|
||||
|
||||
/obj/item/device/multitool/hacktool/proc/attempt_hack(var/mob/user, var/atom/target)
|
||||
if(is_hacking)
|
||||
to_chat(user, "<span class='warning'>You are already hacking!</span>")
|
||||
return 0
|
||||
if(!is_type_in_list(target, supported_types))
|
||||
to_chat(user, "\icon[src][bicon(src)] <span class='warning'>Unable to hack this target, invalid target type.</span>")
|
||||
return 0
|
||||
|
||||
var/obj/machinery/door/airlock/D = target
|
||||
if(D.security_level > max_level)
|
||||
to_chat(user, "\icon[src][bicon(src)] <span class='warning'>Target's electronic security is too complex.</span>")
|
||||
return 0
|
||||
|
||||
var/found = known_targets.Find(D)
|
||||
if(found)
|
||||
known_targets.Swap(1, found) // Move the last hacked item first
|
||||
return 1
|
||||
to_chat(user, "<span class='notice'>You begin hacking \the [D]...</span>")
|
||||
is_hacking = 1
|
||||
// On average hackin takes ~15 seconds. Fairly small random span to avoid people simply aborting and trying again
|
||||
// Reduced hack duration to compensate for the reduced functionality, multiplied by door sec level
|
||||
var/hack_result = do_after(user, (((10 SECONDS + rand(0, 10 SECONDS) + rand(0, 10 SECONDS))*hackspeed)*D.security_level))
|
||||
is_hacking = 0
|
||||
|
||||
if(hack_result && in_hack_mode)
|
||||
to_chat(user, "<span class='notice'>Your hacking attempt was succesful!</span>")
|
||||
user.playsound_local(get_turf(src), 'sound/instruments/piano/An6.ogg', 50)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Your hacking attempt failed!</span>")
|
||||
return 0
|
||||
|
||||
known_targets.Insert(1, D) // Insert the newly hacked target first,
|
||||
D.register(OBSERVER_EVENT_DESTROY, src, /obj/item/device/multitool/hacktool/proc/on_target_destroy)
|
||||
return 1
|
||||
|
||||
/obj/item/device/multitool/hacktool/proc/sanity_check()
|
||||
if(max_known_targets < 1) max_known_targets = 1
|
||||
// Cut away the oldest items if the capacity has been reached
|
||||
if(known_targets.len > max_known_targets)
|
||||
for(var/i = (max_known_targets + 1) to known_targets.len)
|
||||
var/atom/A = known_targets[i]
|
||||
A.unregister(OBSERVER_EVENT_DESTROY, src)
|
||||
known_targets.Cut(max_known_targets + 1)
|
||||
|
||||
/obj/item/device/multitool/hacktool/proc/on_target_destroy(var/target)
|
||||
known_targets -= target
|
||||
|
||||
/datum/tgui_state/default/must_hack
|
||||
var/obj/item/device/multitool/hacktool/hacktool
|
||||
|
||||
/datum/tgui_state/default/must_hack/New(var/hacktool)
|
||||
src.hacktool = hacktool
|
||||
..()
|
||||
|
||||
/datum/tgui_state/default/must_hack/Destroy()
|
||||
hacktool = null
|
||||
return ..()
|
||||
|
||||
/datum/tgui_state/default/must_hack/can_use_topic(src_object, mob/user)
|
||||
if(!hacktool || !hacktool.in_hack_mode || !(src_object in hacktool.known_targets))
|
||||
return STATUS_CLOSE
|
||||
return ..()
|
||||
|
||||
@@ -1,230 +1,230 @@
|
||||
|
||||
// Light Replacer (LR)
|
||||
//
|
||||
// ABOUT THE DEVICE
|
||||
//
|
||||
// This is a device supposedly to be used by Janitors and Janitor Cyborgs which will
|
||||
// allow them to easily replace lights. This was mostly designed for Janitor Cyborgs since
|
||||
// they don't have hands or a way to replace lightbulbs.
|
||||
//
|
||||
// HOW IT WORKS
|
||||
//
|
||||
// You attack a light fixture with it, if the light fixture is broken it will replace the
|
||||
// light fixture with a working light; the broken light is then placed on the floor for the
|
||||
// user to then pickup with a trash bag. If it's empty then it will just place a light in the fixture.
|
||||
//
|
||||
// HOW TO REFILL THE DEVICE
|
||||
//
|
||||
// It can be manually refilled or by clicking on a storage item containing lights.
|
||||
// If it's part of a robot module, it will charge when the Robot is inside a Recharge Station.
|
||||
//
|
||||
// EMAGGED FEATURES
|
||||
//
|
||||
// NOTICE: The Cyborg cannot use the emagged Light Replacer and the light's explosion was nerfed. It cannot create holes in the station anymore.
|
||||
//
|
||||
// I'm not sure everyone will react the emag's features so please say what your opinions are of it.
|
||||
//
|
||||
// When emagged it will rig every light it replaces, which will explode when the light is on.
|
||||
// This is VERY noticable, even the device's name changes when you emag it so if anyone
|
||||
// examines you when you're holding it in your hand, you will be discovered.
|
||||
// It will also be very obvious who is setting all these lights off, since only Janitor Borgs and Janitors have easy
|
||||
// access to them, and only one of them can emag their device.
|
||||
//
|
||||
// The explosion cannot insta-kill anyone with 30% or more health.
|
||||
|
||||
#define LIGHT_OK 0
|
||||
#define LIGHT_EMPTY 1
|
||||
#define LIGHT_BROKEN 2
|
||||
#define LIGHT_BURNED 3
|
||||
|
||||
|
||||
/obj/item/device/lightreplacer
|
||||
|
||||
name = "light replacer"
|
||||
desc = "A device to automatically replace lights. Refill with working lightbulbs or sheets of glass."
|
||||
force = 8
|
||||
icon = 'icons/obj/janitor.dmi'
|
||||
icon_state = "lightreplacer0"
|
||||
slot_flags = SLOT_BELT
|
||||
origin_tech = list(TECH_MAGNET = 3, TECH_MATERIAL = 2)
|
||||
|
||||
var/max_uses = 32
|
||||
var/uses = 32
|
||||
var/emagged = 0
|
||||
var/failmsg = ""
|
||||
var/charge = 0
|
||||
var/selected_color = LIGHT_COLOR_INCANDESCENT_TUBE //Default color!
|
||||
|
||||
// Eating used bulbs gives us bulb shards
|
||||
var/bulb_shards = 0
|
||||
// when we get this many shards, we get a free bulb.
|
||||
var/shards_required = 4
|
||||
|
||||
/obj/item/device/lightreplacer/New()
|
||||
failmsg = "The [name]'s refill light blinks red."
|
||||
..()
|
||||
|
||||
/obj/item/device/lightreplacer/examine(mob/user)
|
||||
. = ..()
|
||||
if(get_dist(user, src) <= 2)
|
||||
. += "It has [uses] lights remaining."
|
||||
|
||||
/obj/item/device/lightreplacer/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/stack/material) && W.get_material_name() == "glass")
|
||||
var/obj/item/stack/G = W
|
||||
if(uses >= max_uses)
|
||||
to_chat(user, "<span class='warning'>[src.name] is full.</span>")
|
||||
return
|
||||
else if(G.use(1))
|
||||
add_uses(16) //Autolathe converts 1 sheet into 16 lights.
|
||||
to_chat(user, "<span class='notice'>You insert a piece of glass into \the [src.name]. You have [uses] light\s remaining.</span>")
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need one sheet of glass to replace lights.</span>")
|
||||
|
||||
if(istype(W, /obj/item/weapon/light))
|
||||
var/new_bulbs = 0
|
||||
var/obj/item/weapon/light/L = W
|
||||
if(L.status == 0) // LIGHT OKAY
|
||||
if(uses < max_uses)
|
||||
if(!user.unEquip(W))
|
||||
return
|
||||
add_uses(1)
|
||||
qdel(L)
|
||||
else
|
||||
if(!user.unEquip(W))
|
||||
return
|
||||
new_bulbs += AddShards(1)
|
||||
qdel(L)
|
||||
if(new_bulbs != 0)
|
||||
playsound(src, 'sound/machines/ding.ogg', 50, 1)
|
||||
to_chat(user, "You insert \the [L.name] into \the [src.name]. You have [uses] light\s remaining.")
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/weapon/storage))
|
||||
var/obj/item/weapon/storage/S = W
|
||||
var/found_lightbulbs = FALSE
|
||||
var/replaced_something = TRUE
|
||||
|
||||
for(var/obj/item/I in S.contents)
|
||||
if(istype(I,/obj/item/weapon/light))
|
||||
var/obj/item/weapon/light/L = I
|
||||
found_lightbulbs = TRUE
|
||||
if(src.uses >= max_uses)
|
||||
break
|
||||
if(L.status == LIGHT_OK)
|
||||
replaced_something = TRUE
|
||||
add_uses(1)
|
||||
qdel(L)
|
||||
|
||||
else if(L.status == LIGHT_BROKEN || L.status == LIGHT_BURNED)
|
||||
replaced_something = TRUE
|
||||
AddShards(1)
|
||||
qdel(L)
|
||||
|
||||
if(!found_lightbulbs)
|
||||
to_chat(user, "<span class='warning'>\The [S] contains no bulbs.</span>")
|
||||
return
|
||||
|
||||
if(!replaced_something && src.uses == max_uses)
|
||||
to_chat(user, "<span class='warning'>\The [src] is full!</span>")
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You fill \the [src] with lights from \the [S].</span>")
|
||||
|
||||
/obj/item/device/lightreplacer/attack_self(mob/user)
|
||||
/* // This would probably be a bit OP. If you want it though, uncomment the code.
|
||||
if(isrobot(user))
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(R.emagged)
|
||||
src.Emag()
|
||||
to_chat(usr, You short circuit the [src].")
|
||||
return
|
||||
*/
|
||||
to_chat(usr, "It has [uses] lights remaining.")
|
||||
var/new_color = input(usr, "Choose a color to set the light to! (Default is [LIGHT_COLOR_INCANDESCENT_TUBE])", "", selected_color) as color|null
|
||||
if(new_color)
|
||||
selected_color = new_color
|
||||
to_chat(usr, "The light color has been changed.")
|
||||
|
||||
/obj/item/device/lightreplacer/update_icon()
|
||||
icon_state = "lightreplacer[emagged]"
|
||||
|
||||
|
||||
/obj/item/device/lightreplacer/proc/Use(var/mob/user)
|
||||
|
||||
playsound(src, 'sound/machines/click.ogg', 50, 1)
|
||||
add_uses(-1)
|
||||
return 1
|
||||
|
||||
// Negative numbers will subtract
|
||||
/obj/item/device/lightreplacer/proc/add_uses(var/amount = 1)
|
||||
uses = min(max(uses + amount, 0), max_uses)
|
||||
|
||||
|
||||
/obj/item/device/lightreplacer/proc/AddShards(amount = 1)
|
||||
bulb_shards += amount
|
||||
var/new_bulbs = round(bulb_shards / shards_required)
|
||||
if(new_bulbs > 0)
|
||||
add_uses(new_bulbs)
|
||||
bulb_shards = bulb_shards % shards_required
|
||||
return new_bulbs
|
||||
|
||||
/obj/item/device/lightreplacer/proc/Charge(var/mob/user, var/amount = 1)
|
||||
charge += amount
|
||||
if(charge > 6)
|
||||
add_uses(1)
|
||||
charge = 0
|
||||
|
||||
/obj/item/device/lightreplacer/proc/ReplaceLight(var/obj/machinery/light/target, var/mob/living/U)
|
||||
|
||||
if(target.status != LIGHT_OK)
|
||||
if(CanUse(U))
|
||||
if(!Use(U)) return
|
||||
to_chat(U, "<span class='notice'>You replace the [target.get_fitting_name()] with the [src].</span>")
|
||||
|
||||
if(target.status != LIGHT_EMPTY)
|
||||
var/new_bulbs = AddShards(1)
|
||||
if(new_bulbs != 0)
|
||||
to_chat(U, "<span class='notice'>\The [src] has fabricated a new bulb from the broken bulbs it has stored. It now has [uses] uses.</span>")
|
||||
playsound(src, 'sound/machines/ding.ogg', 50, 1)
|
||||
target.status = LIGHT_EMPTY
|
||||
target.installed_light = null //Remove the light!
|
||||
target.update()
|
||||
|
||||
var/obj/item/weapon/light/L2 = new target.light_type()
|
||||
L2.brightness_color = selected_color
|
||||
target.insert_bulb(L2) //Call the insertion proc.
|
||||
target.update()
|
||||
|
||||
if(target.on && target.rigged)
|
||||
target.explode()
|
||||
return
|
||||
|
||||
else
|
||||
to_chat(U, failmsg)
|
||||
return
|
||||
else
|
||||
to_chat(U, "There is a working [target.get_fitting_name()] already inserted.")
|
||||
return
|
||||
|
||||
/obj/item/device/lightreplacer/emag_act(var/remaining_charges, var/mob/user)
|
||||
emagged = !emagged
|
||||
playsound(src, "sparks", 100, 1)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
//Can you use it?
|
||||
|
||||
/obj/item/device/lightreplacer/proc/CanUse(var/mob/living/user)
|
||||
src.add_fingerprint(user)
|
||||
//Not sure what else to check for. Maybe if clumsy?
|
||||
if(uses > 0)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
#undef LIGHT_OK
|
||||
#undef LIGHT_EMPTY
|
||||
#undef LIGHT_BROKEN
|
||||
|
||||
// Light Replacer (LR)
|
||||
//
|
||||
// ABOUT THE DEVICE
|
||||
//
|
||||
// This is a device supposedly to be used by Janitors and Janitor Cyborgs which will
|
||||
// allow them to easily replace lights. This was mostly designed for Janitor Cyborgs since
|
||||
// they don't have hands or a way to replace lightbulbs.
|
||||
//
|
||||
// HOW IT WORKS
|
||||
//
|
||||
// You attack a light fixture with it, if the light fixture is broken it will replace the
|
||||
// light fixture with a working light; the broken light is then placed on the floor for the
|
||||
// user to then pickup with a trash bag. If it's empty then it will just place a light in the fixture.
|
||||
//
|
||||
// HOW TO REFILL THE DEVICE
|
||||
//
|
||||
// It can be manually refilled or by clicking on a storage item containing lights.
|
||||
// If it's part of a robot module, it will charge when the Robot is inside a Recharge Station.
|
||||
//
|
||||
// EMAGGED FEATURES
|
||||
//
|
||||
// NOTICE: The Cyborg cannot use the emagged Light Replacer and the light's explosion was nerfed. It cannot create holes in the station anymore.
|
||||
//
|
||||
// I'm not sure everyone will react the emag's features so please say what your opinions are of it.
|
||||
//
|
||||
// When emagged it will rig every light it replaces, which will explode when the light is on.
|
||||
// This is VERY noticable, even the device's name changes when you emag it so if anyone
|
||||
// examines you when you're holding it in your hand, you will be discovered.
|
||||
// It will also be very obvious who is setting all these lights off, since only Janitor Borgs and Janitors have easy
|
||||
// access to them, and only one of them can emag their device.
|
||||
//
|
||||
// The explosion cannot insta-kill anyone with 30% or more health.
|
||||
|
||||
#define LIGHT_OK 0
|
||||
#define LIGHT_EMPTY 1
|
||||
#define LIGHT_BROKEN 2
|
||||
#define LIGHT_BURNED 3
|
||||
|
||||
|
||||
/obj/item/device/lightreplacer
|
||||
|
||||
name = "light replacer"
|
||||
desc = "A device to automatically replace lights. Refill with working lightbulbs or sheets of glass."
|
||||
force = 8
|
||||
icon = 'icons/obj/janitor.dmi'
|
||||
icon_state = "lightreplacer0"
|
||||
slot_flags = SLOT_BELT
|
||||
origin_tech = list(TECH_MAGNET = 3, TECH_MATERIAL = 2)
|
||||
|
||||
var/max_uses = 32
|
||||
var/uses = 32
|
||||
var/emagged = 0
|
||||
var/failmsg = ""
|
||||
var/charge = 0
|
||||
var/selected_color = LIGHT_COLOR_INCANDESCENT_TUBE //Default color!
|
||||
|
||||
// Eating used bulbs gives us bulb shards
|
||||
var/bulb_shards = 0
|
||||
// when we get this many shards, we get a free bulb.
|
||||
var/shards_required = 4
|
||||
|
||||
/obj/item/device/lightreplacer/New()
|
||||
failmsg = "The [name]'s refill light blinks red."
|
||||
..()
|
||||
|
||||
/obj/item/device/lightreplacer/examine(mob/user)
|
||||
. = ..()
|
||||
if(get_dist(user, src) <= 2)
|
||||
. += "It has [uses] lights remaining."
|
||||
|
||||
/obj/item/device/lightreplacer/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/stack/material) && W.get_material_name() == "glass")
|
||||
var/obj/item/stack/G = W
|
||||
if(uses >= max_uses)
|
||||
to_chat(user, "<span class='warning'>[src.name] is full.</span>")
|
||||
return
|
||||
else if(G.use(1))
|
||||
add_uses(16) //Autolathe converts 1 sheet into 16 lights.
|
||||
to_chat(user, "<span class='notice'>You insert a piece of glass into \the [src.name]. You have [uses] light\s remaining.</span>")
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need one sheet of glass to replace lights.</span>")
|
||||
|
||||
if(istype(W, /obj/item/weapon/light))
|
||||
var/new_bulbs = 0
|
||||
var/obj/item/weapon/light/L = W
|
||||
if(L.status == 0) // LIGHT OKAY
|
||||
if(uses < max_uses)
|
||||
if(!user.unEquip(W))
|
||||
return
|
||||
add_uses(1)
|
||||
qdel(L)
|
||||
else
|
||||
if(!user.unEquip(W))
|
||||
return
|
||||
new_bulbs += AddShards(1)
|
||||
qdel(L)
|
||||
if(new_bulbs != 0)
|
||||
playsound(src, 'sound/machines/ding.ogg', 50, 1)
|
||||
to_chat(user, "You insert \the [L.name] into \the [src.name]. You have [uses] light\s remaining.")
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/weapon/storage))
|
||||
var/obj/item/weapon/storage/S = W
|
||||
var/found_lightbulbs = FALSE
|
||||
var/replaced_something = TRUE
|
||||
|
||||
for(var/obj/item/I in S.contents)
|
||||
if(istype(I,/obj/item/weapon/light))
|
||||
var/obj/item/weapon/light/L = I
|
||||
found_lightbulbs = TRUE
|
||||
if(src.uses >= max_uses)
|
||||
break
|
||||
if(L.status == LIGHT_OK)
|
||||
replaced_something = TRUE
|
||||
add_uses(1)
|
||||
qdel(L)
|
||||
|
||||
else if(L.status == LIGHT_BROKEN || L.status == LIGHT_BURNED)
|
||||
replaced_something = TRUE
|
||||
AddShards(1)
|
||||
qdel(L)
|
||||
|
||||
if(!found_lightbulbs)
|
||||
to_chat(user, "<span class='warning'>\The [S] contains no bulbs.</span>")
|
||||
return
|
||||
|
||||
if(!replaced_something && src.uses == max_uses)
|
||||
to_chat(user, "<span class='warning'>\The [src] is full!</span>")
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You fill \the [src] with lights from \the [S].</span>")
|
||||
|
||||
/obj/item/device/lightreplacer/attack_self(mob/user)
|
||||
/* // This would probably be a bit OP. If you want it though, uncomment the code.
|
||||
if(isrobot(user))
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(R.emagged)
|
||||
src.Emag()
|
||||
to_chat(usr, You short circuit the [src].")
|
||||
return
|
||||
*/
|
||||
to_chat(usr, "It has [uses] lights remaining.")
|
||||
var/new_color = input(usr, "Choose a color to set the light to! (Default is [LIGHT_COLOR_INCANDESCENT_TUBE])", "", selected_color) as color|null
|
||||
if(new_color)
|
||||
selected_color = new_color
|
||||
to_chat(usr, "The light color has been changed.")
|
||||
|
||||
/obj/item/device/lightreplacer/update_icon()
|
||||
icon_state = "lightreplacer[emagged]"
|
||||
|
||||
|
||||
/obj/item/device/lightreplacer/proc/Use(var/mob/user)
|
||||
|
||||
playsound(src, 'sound/machines/click.ogg', 50, 1)
|
||||
add_uses(-1)
|
||||
return 1
|
||||
|
||||
// Negative numbers will subtract
|
||||
/obj/item/device/lightreplacer/proc/add_uses(var/amount = 1)
|
||||
uses = min(max(uses + amount, 0), max_uses)
|
||||
|
||||
|
||||
/obj/item/device/lightreplacer/proc/AddShards(amount = 1)
|
||||
bulb_shards += amount
|
||||
var/new_bulbs = round(bulb_shards / shards_required)
|
||||
if(new_bulbs > 0)
|
||||
add_uses(new_bulbs)
|
||||
bulb_shards = bulb_shards % shards_required
|
||||
return new_bulbs
|
||||
|
||||
/obj/item/device/lightreplacer/proc/Charge(var/mob/user, var/amount = 1)
|
||||
charge += amount
|
||||
if(charge > 6)
|
||||
add_uses(1)
|
||||
charge = 0
|
||||
|
||||
/obj/item/device/lightreplacer/proc/ReplaceLight(var/obj/machinery/light/target, var/mob/living/U)
|
||||
|
||||
if(target.status != LIGHT_OK)
|
||||
if(CanUse(U))
|
||||
if(!Use(U)) return
|
||||
to_chat(U, "<span class='notice'>You replace the [target.get_fitting_name()] with the [src].</span>")
|
||||
|
||||
if(target.status != LIGHT_EMPTY)
|
||||
var/new_bulbs = AddShards(1)
|
||||
if(new_bulbs != 0)
|
||||
to_chat(U, "<span class='notice'>\The [src] has fabricated a new bulb from the broken bulbs it has stored. It now has [uses] uses.</span>")
|
||||
playsound(src, 'sound/machines/ding.ogg', 50, 1)
|
||||
target.status = LIGHT_EMPTY
|
||||
target.installed_light = null //Remove the light!
|
||||
target.update()
|
||||
|
||||
var/obj/item/weapon/light/L2 = new target.light_type()
|
||||
L2.brightness_color = selected_color
|
||||
target.insert_bulb(L2) //Call the insertion proc.
|
||||
target.update()
|
||||
|
||||
if(target.on && target.rigged)
|
||||
target.explode()
|
||||
return
|
||||
|
||||
else
|
||||
to_chat(U, failmsg)
|
||||
return
|
||||
else
|
||||
to_chat(U, "There is a working [target.get_fitting_name()] already inserted.")
|
||||
return
|
||||
|
||||
/obj/item/device/lightreplacer/emag_act(var/remaining_charges, var/mob/user)
|
||||
emagged = !emagged
|
||||
playsound(src, "sparks", 100, 1)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
//Can you use it?
|
||||
|
||||
/obj/item/device/lightreplacer/proc/CanUse(var/mob/living/user)
|
||||
src.add_fingerprint(user)
|
||||
//Not sure what else to check for. Maybe if clumsy?
|
||||
if(uses > 0)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
#undef LIGHT_OK
|
||||
#undef LIGHT_EMPTY
|
||||
#undef LIGHT_BROKEN
|
||||
#undef LIGHT_BURNED
|
||||
@@ -1,95 +1,95 @@
|
||||
/**
|
||||
* Multitool -- A multitool is used for hacking electronic devices.
|
||||
* TO-DO -- Using it as a power measurement tool for cables etc. Nannek.
|
||||
*
|
||||
*/
|
||||
|
||||
/obj/item/device/multitool
|
||||
name = "multitool"
|
||||
desc = "Used for pulsing wires to test which to cut. Not recommended by doctors."
|
||||
description_info = "You can use this on airlocks or APCs to try to hack them without cutting wires."
|
||||
icon_state = "multitool"
|
||||
force = 5.0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throwforce = 5.0
|
||||
throw_range = 15
|
||||
throw_speed = 3
|
||||
drop_sound = 'sound/items/drop/multitool.ogg'
|
||||
pickup_sound = 'sound/items/pickup/multitool.ogg'
|
||||
|
||||
matter = list(MAT_STEEL = 50,MAT_GLASS = 20)
|
||||
|
||||
var/mode_index = 1
|
||||
var/toolmode = MULTITOOL_MODE_STANDARD
|
||||
var/list/modes = list(MULTITOOL_MODE_STANDARD, MULTITOOL_MODE_INTCIRCUITS)
|
||||
|
||||
origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1)
|
||||
var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage
|
||||
var/obj/machinery/clonepod/connecting //same for cryopod linkage
|
||||
var/obj/machinery/connectable //Used to connect machinery.
|
||||
var/weakref_wiring //Used to store weak references for integrated circuitry. This is now the Omnitool.
|
||||
toolspeed = 1
|
||||
tool_qualities = list(TOOL_MULTITOOL)
|
||||
|
||||
/obj/item/device/multitool/attack_self(mob/living/user)
|
||||
var/choice = tgui_alert(usr, "What do you want to do with \the [src]?", "Multitool Menu", list("Switch Mode", "Clear Buffers", "Cancel"))
|
||||
switch(choice)
|
||||
if("Cancel")
|
||||
to_chat(user,"<span class='notice'>You lower \the [src].</span>")
|
||||
return
|
||||
if("Clear Buffers")
|
||||
to_chat(user,"<span class='notice'>You clear \the [src]'s memory.</span>")
|
||||
buffer = null
|
||||
connecting = null
|
||||
connectable = null
|
||||
weakref_wiring = null
|
||||
accepting_refs = 0
|
||||
if(toolmode == MULTITOOL_MODE_INTCIRCUITS)
|
||||
accepting_refs = 1
|
||||
if("Switch Mode")
|
||||
mode_switch(user)
|
||||
|
||||
update_icon()
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/device/multitool/proc/mode_switch(mob/living/user)
|
||||
if(mode_index + 1 > modes.len) mode_index = 1
|
||||
|
||||
else
|
||||
mode_index += 1
|
||||
|
||||
toolmode = modes[mode_index]
|
||||
to_chat(user,"<span class='notice'>\The [src] is now set to [toolmode].</span>")
|
||||
|
||||
accepting_refs = (toolmode == MULTITOOL_MODE_INTCIRCUITS)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/device/multitool/cyborg
|
||||
name = "multitool"
|
||||
desc = "Optimised and stripped-down version of a regular multitool."
|
||||
toolspeed = 0.5
|
||||
|
||||
|
||||
|
||||
/datum/category_item/catalogue/anomalous/precursor_a/alien_multitool
|
||||
name = "Precursor Alpha Object - Pulse Tool"
|
||||
desc = "This ancient object appears to be an electrical tool. \
|
||||
It has a simple mechanism at the handle, which will cause a pulse of \
|
||||
energy to be emitted from the head of the tool. This can be used on a \
|
||||
conductive object such as a wire, in order to send a pulse signal through it.\
|
||||
<br><br>\
|
||||
These qualities make this object somewhat similar in purpose to the common \
|
||||
multitool, and can probably be used for tasks such as direct interfacing with \
|
||||
an airlock, if one knows how."
|
||||
value = CATALOGUER_REWARD_EASY
|
||||
|
||||
/obj/item/device/multitool/alien
|
||||
name = "alien multitool"
|
||||
desc = "An omni-technological interface."
|
||||
catalogue_data = list(/datum/category_item/catalogue/anomalous/precursor_a/alien_multitool)
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "multitool"
|
||||
toolspeed = 0.1
|
||||
origin_tech = list(TECH_MAGNET = 5, TECH_ENGINEERING = 5)
|
||||
/**
|
||||
* Multitool -- A multitool is used for hacking electronic devices.
|
||||
* TO-DO -- Using it as a power measurement tool for cables etc. Nannek.
|
||||
*
|
||||
*/
|
||||
|
||||
/obj/item/device/multitool
|
||||
name = "multitool"
|
||||
desc = "Used for pulsing wires to test which to cut. Not recommended by doctors."
|
||||
description_info = "You can use this on airlocks or APCs to try to hack them without cutting wires."
|
||||
icon_state = "multitool"
|
||||
force = 5.0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throwforce = 5.0
|
||||
throw_range = 15
|
||||
throw_speed = 3
|
||||
drop_sound = 'sound/items/drop/multitool.ogg'
|
||||
pickup_sound = 'sound/items/pickup/multitool.ogg'
|
||||
|
||||
matter = list(MAT_STEEL = 50,MAT_GLASS = 20)
|
||||
|
||||
var/mode_index = 1
|
||||
var/toolmode = MULTITOOL_MODE_STANDARD
|
||||
var/list/modes = list(MULTITOOL_MODE_STANDARD, MULTITOOL_MODE_INTCIRCUITS)
|
||||
|
||||
origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1)
|
||||
var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage
|
||||
var/obj/machinery/clonepod/connecting //same for cryopod linkage
|
||||
var/obj/machinery/connectable //Used to connect machinery.
|
||||
var/weakref_wiring //Used to store weak references for integrated circuitry. This is now the Omnitool.
|
||||
toolspeed = 1
|
||||
tool_qualities = list(TOOL_MULTITOOL)
|
||||
|
||||
/obj/item/device/multitool/attack_self(mob/living/user)
|
||||
var/choice = tgui_alert(usr, "What do you want to do with \the [src]?", "Multitool Menu", list("Switch Mode", "Clear Buffers", "Cancel"))
|
||||
switch(choice)
|
||||
if("Cancel")
|
||||
to_chat(user,"<span class='notice'>You lower \the [src].</span>")
|
||||
return
|
||||
if("Clear Buffers")
|
||||
to_chat(user,"<span class='notice'>You clear \the [src]'s memory.</span>")
|
||||
buffer = null
|
||||
connecting = null
|
||||
connectable = null
|
||||
weakref_wiring = null
|
||||
accepting_refs = 0
|
||||
if(toolmode == MULTITOOL_MODE_INTCIRCUITS)
|
||||
accepting_refs = 1
|
||||
if("Switch Mode")
|
||||
mode_switch(user)
|
||||
|
||||
update_icon()
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/device/multitool/proc/mode_switch(mob/living/user)
|
||||
if(mode_index + 1 > modes.len) mode_index = 1
|
||||
|
||||
else
|
||||
mode_index += 1
|
||||
|
||||
toolmode = modes[mode_index]
|
||||
to_chat(user,"<span class='notice'>\The [src] is now set to [toolmode].</span>")
|
||||
|
||||
accepting_refs = (toolmode == MULTITOOL_MODE_INTCIRCUITS)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/device/multitool/cyborg
|
||||
name = "multitool"
|
||||
desc = "Optimised and stripped-down version of a regular multitool."
|
||||
toolspeed = 0.5
|
||||
|
||||
|
||||
|
||||
/datum/category_item/catalogue/anomalous/precursor_a/alien_multitool
|
||||
name = "Precursor Alpha Object - Pulse Tool"
|
||||
desc = "This ancient object appears to be an electrical tool. \
|
||||
It has a simple mechanism at the handle, which will cause a pulse of \
|
||||
energy to be emitted from the head of the tool. This can be used on a \
|
||||
conductive object such as a wire, in order to send a pulse signal through it.\
|
||||
<br><br>\
|
||||
These qualities make this object somewhat similar in purpose to the common \
|
||||
multitool, and can probably be used for tasks such as direct interfacing with \
|
||||
an airlock, if one knows how."
|
||||
value = CATALOGUER_REWARD_EASY
|
||||
|
||||
/obj/item/device/multitool/alien
|
||||
name = "alien multitool"
|
||||
desc = "An omni-technological interface."
|
||||
catalogue_data = list(/datum/category_item/catalogue/anomalous/precursor_a/alien_multitool)
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "multitool"
|
||||
toolspeed = 0.1
|
||||
origin_tech = list(TECH_MAGNET = 5, TECH_ENGINEERING = 5)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,134 +1,134 @@
|
||||
// Powersink - used to drain station power
|
||||
|
||||
/obj/item/device/powersink
|
||||
name = "power sink"
|
||||
desc = "A nulling power sink which drains energy from electrical systems."
|
||||
icon_state = "powersink0"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
w_class = ITEMSIZE_LARGE
|
||||
throwforce = 5
|
||||
throw_speed = 1
|
||||
throw_range = 2
|
||||
|
||||
matter = list(MAT_STEEL = 750)
|
||||
|
||||
origin_tech = list(TECH_POWER = 3, TECH_ILLEGAL = 5)
|
||||
var/drain_rate = 1500000 // amount of power to drain per tick
|
||||
var/apc_drain_rate = 5000 // Max. amount drained from single APC. In Watts.
|
||||
var/dissipation_rate = 20000 // Passive dissipation of drained power. In Watts.
|
||||
var/power_drained = 0 // Amount of power drained.
|
||||
var/max_power = 1e9 // Detonation point.
|
||||
var/mode = 0 // 0 = off, 1=clamped (off), 2=operating
|
||||
var/drained_this_tick = 0 // This is unfortunately necessary to ensure we process powersinks BEFORE other machinery such as APCs.
|
||||
|
||||
var/datum/powernet/PN // Our powernet
|
||||
var/obj/structure/cable/attached // the attached cable
|
||||
|
||||
/obj/item/device/powersink/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
STOP_PROCESSING_POWER_OBJECT(src)
|
||||
..()
|
||||
|
||||
/obj/item/device/powersink/attackby(var/obj/item/I, var/mob/user)
|
||||
if(I.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
if(mode == 0)
|
||||
var/turf/T = loc
|
||||
if(isturf(T) && !!T.is_plating())
|
||||
attached = locate() in T
|
||||
if(!attached)
|
||||
to_chat(user, "No exposed cable here to attach to.")
|
||||
return
|
||||
else
|
||||
anchored = TRUE
|
||||
mode = 1
|
||||
src.visible_message("<span class='notice'>[user] attaches [src] to the cable!</span>")
|
||||
playsound(src, I.usesound, 50, 1)
|
||||
return
|
||||
else
|
||||
to_chat(user, "Device must be placed over an exposed cable to attach to it.")
|
||||
return
|
||||
else
|
||||
if (mode == 2)
|
||||
STOP_PROCESSING(SSobj, src) // Now the power sink actually stops draining the station's power if you unhook it. --NeoFite
|
||||
STOP_PROCESSING_POWER_OBJECT(src)
|
||||
anchored = FALSE
|
||||
mode = 0
|
||||
src.visible_message("<span class='notice'>[user] detaches [src] from the cable!</span>")
|
||||
set_light(0)
|
||||
playsound(src, I.usesound, 50, 1)
|
||||
icon_state = "powersink0"
|
||||
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/powersink/attack_ai()
|
||||
return
|
||||
|
||||
/obj/item/device/powersink/attack_hand(var/mob/user)
|
||||
switch(mode)
|
||||
if(0)
|
||||
..()
|
||||
if(1)
|
||||
src.visible_message("<span class='notice'>[user] activates [src]!</span>")
|
||||
mode = 2
|
||||
icon_state = "powersink1"
|
||||
START_PROCESSING(SSobj, src)
|
||||
datum_flags &= ~DF_ISPROCESSING // Have to reset this flag so that PROCESSING_POWER_OBJECT can re-add it. It fails if the flag is already present. - Ater
|
||||
START_PROCESSING_POWER_OBJECT(src)
|
||||
if(2) //This switch option wasn't originally included. It exists now. --NeoFite
|
||||
src.visible_message("<span class='notice'>[user] deactivates [src]!</span>")
|
||||
mode = 1
|
||||
set_light(0)
|
||||
icon_state = "powersink0"
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
STOP_PROCESSING_POWER_OBJECT(src)
|
||||
|
||||
/obj/item/device/powersink/pwr_drain()
|
||||
if(!attached)
|
||||
return 0
|
||||
|
||||
if(drained_this_tick)
|
||||
return 1
|
||||
drained_this_tick = 1
|
||||
|
||||
var/drained = 0
|
||||
|
||||
if(!PN)
|
||||
return 1
|
||||
|
||||
set_light(12)
|
||||
PN.trigger_warning()
|
||||
// found a powernet, so drain up to max power from it
|
||||
drained = PN.draw_power(drain_rate)
|
||||
// if tried to drain more than available on powernet
|
||||
// now look for APCs and drain their cells
|
||||
if(drained < drain_rate)
|
||||
for(var/obj/machinery/power/terminal/T in PN.nodes)
|
||||
// Enough power drained this tick, no need to torture more APCs
|
||||
if(drained >= drain_rate)
|
||||
break
|
||||
if(istype(T.master, /obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/A = T.master
|
||||
if(A.operating && A.cell)
|
||||
var/cur_charge = A.cell.charge / CELLRATE
|
||||
var/drain_val = min(apc_drain_rate, cur_charge)
|
||||
A.cell.use(drain_val * CELLRATE)
|
||||
drained += drain_val
|
||||
power_drained += drained
|
||||
return 1
|
||||
|
||||
|
||||
/obj/item/device/powersink/process()
|
||||
drained_this_tick = 0
|
||||
power_drained -= min(dissipation_rate, power_drained)
|
||||
if(power_drained > max_power * 0.95)
|
||||
playsound(src, 'sound/effects/screech.ogg', 100, 1, 1)
|
||||
if(power_drained >= max_power)
|
||||
explosion(src.loc, 3,6,9,12)
|
||||
qdel(src)
|
||||
return
|
||||
if(attached && attached.powernet)
|
||||
PN = attached.powernet
|
||||
else
|
||||
PN = null
|
||||
// Powersink - used to drain station power
|
||||
|
||||
/obj/item/device/powersink
|
||||
name = "power sink"
|
||||
desc = "A nulling power sink which drains energy from electrical systems."
|
||||
icon_state = "powersink0"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
w_class = ITEMSIZE_LARGE
|
||||
throwforce = 5
|
||||
throw_speed = 1
|
||||
throw_range = 2
|
||||
|
||||
matter = list(MAT_STEEL = 750)
|
||||
|
||||
origin_tech = list(TECH_POWER = 3, TECH_ILLEGAL = 5)
|
||||
var/drain_rate = 1500000 // amount of power to drain per tick
|
||||
var/apc_drain_rate = 5000 // Max. amount drained from single APC. In Watts.
|
||||
var/dissipation_rate = 20000 // Passive dissipation of drained power. In Watts.
|
||||
var/power_drained = 0 // Amount of power drained.
|
||||
var/max_power = 1e9 // Detonation point.
|
||||
var/mode = 0 // 0 = off, 1=clamped (off), 2=operating
|
||||
var/drained_this_tick = 0 // This is unfortunately necessary to ensure we process powersinks BEFORE other machinery such as APCs.
|
||||
|
||||
var/datum/powernet/PN // Our powernet
|
||||
var/obj/structure/cable/attached // the attached cable
|
||||
|
||||
/obj/item/device/powersink/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
STOP_PROCESSING_POWER_OBJECT(src)
|
||||
..()
|
||||
|
||||
/obj/item/device/powersink/attackby(var/obj/item/I, var/mob/user)
|
||||
if(I.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
if(mode == 0)
|
||||
var/turf/T = loc
|
||||
if(isturf(T) && !!T.is_plating())
|
||||
attached = locate() in T
|
||||
if(!attached)
|
||||
to_chat(user, "No exposed cable here to attach to.")
|
||||
return
|
||||
else
|
||||
anchored = TRUE
|
||||
mode = 1
|
||||
src.visible_message("<span class='notice'>[user] attaches [src] to the cable!</span>")
|
||||
playsound(src, I.usesound, 50, 1)
|
||||
return
|
||||
else
|
||||
to_chat(user, "Device must be placed over an exposed cable to attach to it.")
|
||||
return
|
||||
else
|
||||
if (mode == 2)
|
||||
STOP_PROCESSING(SSobj, src) // Now the power sink actually stops draining the station's power if you unhook it. --NeoFite
|
||||
STOP_PROCESSING_POWER_OBJECT(src)
|
||||
anchored = FALSE
|
||||
mode = 0
|
||||
src.visible_message("<span class='notice'>[user] detaches [src] from the cable!</span>")
|
||||
set_light(0)
|
||||
playsound(src, I.usesound, 50, 1)
|
||||
icon_state = "powersink0"
|
||||
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/powersink/attack_ai()
|
||||
return
|
||||
|
||||
/obj/item/device/powersink/attack_hand(var/mob/user)
|
||||
switch(mode)
|
||||
if(0)
|
||||
..()
|
||||
if(1)
|
||||
src.visible_message("<span class='notice'>[user] activates [src]!</span>")
|
||||
mode = 2
|
||||
icon_state = "powersink1"
|
||||
START_PROCESSING(SSobj, src)
|
||||
datum_flags &= ~DF_ISPROCESSING // Have to reset this flag so that PROCESSING_POWER_OBJECT can re-add it. It fails if the flag is already present. - Ater
|
||||
START_PROCESSING_POWER_OBJECT(src)
|
||||
if(2) //This switch option wasn't originally included. It exists now. --NeoFite
|
||||
src.visible_message("<span class='notice'>[user] deactivates [src]!</span>")
|
||||
mode = 1
|
||||
set_light(0)
|
||||
icon_state = "powersink0"
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
STOP_PROCESSING_POWER_OBJECT(src)
|
||||
|
||||
/obj/item/device/powersink/pwr_drain()
|
||||
if(!attached)
|
||||
return 0
|
||||
|
||||
if(drained_this_tick)
|
||||
return 1
|
||||
drained_this_tick = 1
|
||||
|
||||
var/drained = 0
|
||||
|
||||
if(!PN)
|
||||
return 1
|
||||
|
||||
set_light(12)
|
||||
PN.trigger_warning()
|
||||
// found a powernet, so drain up to max power from it
|
||||
drained = PN.draw_power(drain_rate)
|
||||
// if tried to drain more than available on powernet
|
||||
// now look for APCs and drain their cells
|
||||
if(drained < drain_rate)
|
||||
for(var/obj/machinery/power/terminal/T in PN.nodes)
|
||||
// Enough power drained this tick, no need to torture more APCs
|
||||
if(drained >= drain_rate)
|
||||
break
|
||||
if(istype(T.master, /obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/A = T.master
|
||||
if(A.operating && A.cell)
|
||||
var/cur_charge = A.cell.charge / CELLRATE
|
||||
var/drain_val = min(apc_drain_rate, cur_charge)
|
||||
A.cell.use(drain_val * CELLRATE)
|
||||
drained += drain_val
|
||||
power_drained += drained
|
||||
return 1
|
||||
|
||||
|
||||
/obj/item/device/powersink/process()
|
||||
drained_this_tick = 0
|
||||
power_drained -= min(dissipation_rate, power_drained)
|
||||
if(power_drained > max_power * 0.95)
|
||||
playsound(src, 'sound/effects/screech.ogg', 100, 1, 1)
|
||||
if(power_drained >= max_power)
|
||||
explosion(src.loc, 3,6,9,12)
|
||||
qdel(src)
|
||||
return
|
||||
if(attached && attached.powernet)
|
||||
PN = attached.powernet
|
||||
else
|
||||
PN = null
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
/obj/item/device/radio/beacon
|
||||
name = "tracking beacon"
|
||||
desc = "A beacon used by a teleporter."
|
||||
icon_state = "beacon"
|
||||
item_state = "signaler"
|
||||
var/code = "electronic"
|
||||
origin_tech = list(TECH_BLUESPACE = 1)
|
||||
|
||||
GLOBAL_LIST_BOILERPLATE(all_beacons, /obj/item/device/radio/beacon)
|
||||
|
||||
/obj/item/device/radio/beacon/hear_talk()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/device/radio/beacon/send_hear()
|
||||
return null
|
||||
|
||||
|
||||
/obj/item/device/radio/beacon/verb/alter_signal(t as text)
|
||||
set name = "Alter Beacon's Signal"
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
|
||||
if ((usr.canmove && !( usr.restrained() )))
|
||||
src.code = t
|
||||
if (!( src.code ))
|
||||
src.code = "beacon"
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
// SINGULO BEACON SPAWNER
|
||||
|
||||
/obj/item/device/radio/beacon/syndicate
|
||||
name = "suspicious beacon"
|
||||
desc = "A label on it reads: <i>Activate to have a singularity beacon teleported to your location</i>."
|
||||
origin_tech = list(TECH_BLUESPACE = 1, TECH_ILLEGAL = 7)
|
||||
|
||||
/obj/item/device/radio/beacon/syndicate/attack_self(mob/user as mob)
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>Locked In</span>")
|
||||
new /obj/machinery/power/singularity_beacon/syndicate( user.loc )
|
||||
playsound(src, 'sound/effects/pop.ogg', 100, 1, 1)
|
||||
qdel(src)
|
||||
return
|
||||
/obj/item/device/radio/beacon
|
||||
name = "tracking beacon"
|
||||
desc = "A beacon used by a teleporter."
|
||||
icon_state = "beacon"
|
||||
item_state = "signaler"
|
||||
var/code = "electronic"
|
||||
origin_tech = list(TECH_BLUESPACE = 1)
|
||||
|
||||
GLOBAL_LIST_BOILERPLATE(all_beacons, /obj/item/device/radio/beacon)
|
||||
|
||||
/obj/item/device/radio/beacon/hear_talk()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/device/radio/beacon/send_hear()
|
||||
return null
|
||||
|
||||
|
||||
/obj/item/device/radio/beacon/verb/alter_signal(t as text)
|
||||
set name = "Alter Beacon's Signal"
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
|
||||
if ((usr.canmove && !( usr.restrained() )))
|
||||
src.code = t
|
||||
if (!( src.code ))
|
||||
src.code = "beacon"
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
// SINGULO BEACON SPAWNER
|
||||
|
||||
/obj/item/device/radio/beacon/syndicate
|
||||
name = "suspicious beacon"
|
||||
desc = "A label on it reads: <i>Activate to have a singularity beacon teleported to your location</i>."
|
||||
origin_tech = list(TECH_BLUESPACE = 1, TECH_ILLEGAL = 7)
|
||||
|
||||
/obj/item/device/radio/beacon/syndicate/attack_self(mob/user as mob)
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>Locked In</span>")
|
||||
new /obj/machinery/power/singularity_beacon/syndicate( user.loc )
|
||||
playsound(src, 'sound/effects/pop.ogg', 100, 1, 1)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
@@ -1,131 +1,131 @@
|
||||
/obj/item/device/radio/electropack
|
||||
name = "electropack"
|
||||
desc = "Dance my monkeys! DANCE!!!"
|
||||
icon_state = "electropack0"
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_storage.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_storage.dmi',
|
||||
)
|
||||
item_state = "electropack"
|
||||
frequency = 1449
|
||||
slot_flags = SLOT_BACK
|
||||
w_class = ITEMSIZE_HUGE
|
||||
|
||||
matter = list(MAT_STEEL = 10000,MAT_GLASS = 2500)
|
||||
|
||||
var/code = 2
|
||||
|
||||
/obj/item/device/radio/electropack/attack_hand(mob/living/user as mob)
|
||||
if(src == user.back)
|
||||
to_chat(user, "<span class='notice'>You need help taking this off!</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/device/radio/electropack/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
..()
|
||||
if(istype(W, /obj/item/clothing/head/helmet))
|
||||
if(!b_stat)
|
||||
to_chat(user, "<span class='notice'>[src] is not ready to be attached!</span>")
|
||||
return
|
||||
var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit( user )
|
||||
A.icon = 'icons/obj/assemblies.dmi'
|
||||
|
||||
user.drop_from_inventory(W)
|
||||
W.loc = A
|
||||
W.master = A
|
||||
A.part1 = W
|
||||
|
||||
user.drop_from_inventory(src)
|
||||
loc = A
|
||||
master = A
|
||||
A.part2 = src
|
||||
|
||||
user.put_in_hands(A)
|
||||
A.add_fingerprint(user)
|
||||
|
||||
/obj/item/device/radio/electropack/Topic(href, href_list)
|
||||
//..()
|
||||
if(usr.stat || usr.restrained())
|
||||
return
|
||||
if(((istype(usr, /mob/living/carbon/human) && ((!( ticker ) || (ticker && ticker.mode != "monkey")) && usr.contents.Find(src))) || (usr.contents.Find(master) || (in_range(src, usr) && istype(loc, /turf)))))
|
||||
usr.set_machine(src)
|
||||
if(href_list["freq"])
|
||||
var/new_frequency = sanitize_frequency(frequency + text2num(href_list["freq"]))
|
||||
set_frequency(new_frequency)
|
||||
else
|
||||
if(href_list["code"])
|
||||
code += text2num(href_list["code"])
|
||||
code = round(code)
|
||||
code = min(100, code)
|
||||
code = max(1, code)
|
||||
else
|
||||
if(href_list["power"])
|
||||
on = !( on )
|
||||
icon_state = "electropack[on]"
|
||||
if(!( master ))
|
||||
if(istype(loc, /mob))
|
||||
attack_self(loc)
|
||||
else
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if(M.client)
|
||||
attack_self(M)
|
||||
else
|
||||
if(istype(master.loc, /mob))
|
||||
attack_self(master.loc)
|
||||
else
|
||||
for(var/mob/M in viewers(1, master))
|
||||
if(M.client)
|
||||
attack_self(M)
|
||||
else
|
||||
usr << browse(null, "window=radio")
|
||||
return
|
||||
return
|
||||
|
||||
/obj/item/device/radio/electropack/receive_signal(datum/signal/signal)
|
||||
if(!signal || signal.encryption != code)
|
||||
return
|
||||
|
||||
if(ismob(loc) && on)
|
||||
var/mob/M = loc
|
||||
var/turf/T = M.loc
|
||||
if(istype(T, /turf))
|
||||
if(!M.moved_recently && M.last_move)
|
||||
M.moved_recently = 1
|
||||
step(M, M.last_move)
|
||||
sleep(50)
|
||||
if(M)
|
||||
M.moved_recently = 0
|
||||
to_chat(M, "<span class='danger'>You feel a sharp shock!</span>")
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, M)
|
||||
s.start()
|
||||
|
||||
M.Weaken(10)
|
||||
|
||||
if(master && wires & 1)
|
||||
master.receive_signal()
|
||||
return
|
||||
|
||||
/obj/item/device/radio/electropack/attack_self(mob/user as mob, flag1)
|
||||
|
||||
if(!istype(user, /mob/living/carbon/human))
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/dat = {"<TT>
|
||||
<A href='?src=\ref[src];power=1'>Turn [on ? "Off" : "On"]</A><BR>
|
||||
<B>Frequency/Code</B> for electropack:<BR>
|
||||
Frequency:
|
||||
<A href='byond://?src=\ref[src];freq=-10'>-</A>
|
||||
<A href='byond://?src=\ref[src];freq=-2'>-</A> [format_frequency(frequency)]
|
||||
<A href='byond://?src=\ref[src];freq=2'>+</A>
|
||||
<A href='byond://?src=\ref[src];freq=10'>+</A><BR>
|
||||
|
||||
Code:
|
||||
<A href='byond://?src=\ref[src];code=-5'>-</A>
|
||||
<A href='byond://?src=\ref[src];code=-1'>-</A> [code]
|
||||
<A href='byond://?src=\ref[src];code=1'>+</A>
|
||||
<A href='byond://?src=\ref[src];code=5'>+</A><BR>
|
||||
</TT>"}
|
||||
user << browse(dat, "window=radio")
|
||||
onclose(user, "radio")
|
||||
return
|
||||
/obj/item/device/radio/electropack
|
||||
name = "electropack"
|
||||
desc = "Dance my monkeys! DANCE!!!"
|
||||
icon_state = "electropack0"
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_storage.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_storage.dmi',
|
||||
)
|
||||
item_state = "electropack"
|
||||
frequency = 1449
|
||||
slot_flags = SLOT_BACK
|
||||
w_class = ITEMSIZE_HUGE
|
||||
|
||||
matter = list(MAT_STEEL = 10000,MAT_GLASS = 2500)
|
||||
|
||||
var/code = 2
|
||||
|
||||
/obj/item/device/radio/electropack/attack_hand(mob/living/user as mob)
|
||||
if(src == user.back)
|
||||
to_chat(user, "<span class='notice'>You need help taking this off!</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/device/radio/electropack/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
..()
|
||||
if(istype(W, /obj/item/clothing/head/helmet))
|
||||
if(!b_stat)
|
||||
to_chat(user, "<span class='notice'>[src] is not ready to be attached!</span>")
|
||||
return
|
||||
var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit( user )
|
||||
A.icon = 'icons/obj/assemblies.dmi'
|
||||
|
||||
user.drop_from_inventory(W)
|
||||
W.loc = A
|
||||
W.master = A
|
||||
A.part1 = W
|
||||
|
||||
user.drop_from_inventory(src)
|
||||
loc = A
|
||||
master = A
|
||||
A.part2 = src
|
||||
|
||||
user.put_in_hands(A)
|
||||
A.add_fingerprint(user)
|
||||
|
||||
/obj/item/device/radio/electropack/Topic(href, href_list)
|
||||
//..()
|
||||
if(usr.stat || usr.restrained())
|
||||
return
|
||||
if(((istype(usr, /mob/living/carbon/human) && ((!( ticker ) || (ticker && ticker.mode != "monkey")) && usr.contents.Find(src))) || (usr.contents.Find(master) || (in_range(src, usr) && istype(loc, /turf)))))
|
||||
usr.set_machine(src)
|
||||
if(href_list["freq"])
|
||||
var/new_frequency = sanitize_frequency(frequency + text2num(href_list["freq"]))
|
||||
set_frequency(new_frequency)
|
||||
else
|
||||
if(href_list["code"])
|
||||
code += text2num(href_list["code"])
|
||||
code = round(code)
|
||||
code = min(100, code)
|
||||
code = max(1, code)
|
||||
else
|
||||
if(href_list["power"])
|
||||
on = !( on )
|
||||
icon_state = "electropack[on]"
|
||||
if(!( master ))
|
||||
if(istype(loc, /mob))
|
||||
attack_self(loc)
|
||||
else
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if(M.client)
|
||||
attack_self(M)
|
||||
else
|
||||
if(istype(master.loc, /mob))
|
||||
attack_self(master.loc)
|
||||
else
|
||||
for(var/mob/M in viewers(1, master))
|
||||
if(M.client)
|
||||
attack_self(M)
|
||||
else
|
||||
usr << browse(null, "window=radio")
|
||||
return
|
||||
return
|
||||
|
||||
/obj/item/device/radio/electropack/receive_signal(datum/signal/signal)
|
||||
if(!signal || signal.encryption != code)
|
||||
return
|
||||
|
||||
if(ismob(loc) && on)
|
||||
var/mob/M = loc
|
||||
var/turf/T = M.loc
|
||||
if(istype(T, /turf))
|
||||
if(!M.moved_recently && M.last_move)
|
||||
M.moved_recently = 1
|
||||
step(M, M.last_move)
|
||||
sleep(50)
|
||||
if(M)
|
||||
M.moved_recently = 0
|
||||
to_chat(M, "<span class='danger'>You feel a sharp shock!</span>")
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, M)
|
||||
s.start()
|
||||
|
||||
M.Weaken(10)
|
||||
|
||||
if(master && wires & 1)
|
||||
master.receive_signal()
|
||||
return
|
||||
|
||||
/obj/item/device/radio/electropack/attack_self(mob/user as mob, flag1)
|
||||
|
||||
if(!istype(user, /mob/living/carbon/human))
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/dat = {"<TT>
|
||||
<A href='?src=\ref[src];power=1'>Turn [on ? "Off" : "On"]</A><BR>
|
||||
<B>Frequency/Code</B> for electropack:<BR>
|
||||
Frequency:
|
||||
<A href='byond://?src=\ref[src];freq=-10'>-</A>
|
||||
<A href='byond://?src=\ref[src];freq=-2'>-</A> [format_frequency(frequency)]
|
||||
<A href='byond://?src=\ref[src];freq=2'>+</A>
|
||||
<A href='byond://?src=\ref[src];freq=10'>+</A><BR>
|
||||
|
||||
Code:
|
||||
<A href='byond://?src=\ref[src];code=-5'>-</A>
|
||||
<A href='byond://?src=\ref[src];code=-1'>-</A> [code]
|
||||
<A href='byond://?src=\ref[src];code=1'>+</A>
|
||||
<A href='byond://?src=\ref[src];code=5'>+</A><BR>
|
||||
</TT>"}
|
||||
user << browse(dat, "window=radio")
|
||||
onclose(user, "radio")
|
||||
return
|
||||
|
||||
@@ -1,455 +1,455 @@
|
||||
/obj/item/device/radio/headset
|
||||
name = "radio headset"
|
||||
desc = "An updated, modular intercom that fits over the head. Takes encryption keys"
|
||||
var/radio_desc = ""
|
||||
icon_state = "headset"
|
||||
item_state = null //To remove the radio's state
|
||||
matter = list(MAT_STEEL = 75)
|
||||
subspace_transmission = 1
|
||||
canhear_range = 0 // can't hear headsets from very far away
|
||||
slot_flags = SLOT_EARS
|
||||
sprite_sheets = list(SPECIES_TESHARI = 'icons/inventory/ears/mob_teshari.dmi')
|
||||
|
||||
var/translate_binary = 0
|
||||
var/translate_hive = 0
|
||||
var/obj/item/device/encryptionkey/keyslot1 = null
|
||||
var/obj/item/device/encryptionkey/keyslot2 = null
|
||||
var/ks1type = null
|
||||
var/ks2type = null
|
||||
|
||||
drop_sound = 'sound/items/drop/component.ogg'
|
||||
pickup_sound = 'sound/items/pickup/component.ogg'
|
||||
|
||||
/obj/item/device/radio/headset/New()
|
||||
..()
|
||||
internal_channels.Cut()
|
||||
if(ks1type)
|
||||
keyslot1 = new ks1type(src)
|
||||
if(ks2type)
|
||||
keyslot2 = new ks2type(src)
|
||||
recalculateChannels(1)
|
||||
|
||||
/obj/item/device/radio/headset/Destroy()
|
||||
qdel(keyslot1)
|
||||
qdel(keyslot2)
|
||||
keyslot1 = null
|
||||
keyslot2 = null
|
||||
return ..()
|
||||
|
||||
/obj/item/device/radio/headset/list_channels(var/mob/user)
|
||||
return list_secure_channels()
|
||||
|
||||
/obj/item/device/radio/headset/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
if(radio_desc && Adjacent(user))
|
||||
. += "The following channels are available:"
|
||||
. += radio_desc
|
||||
|
||||
/obj/item/device/radio/headset/handle_message_mode(mob/living/M as mob, list/message_pieces, channel)
|
||||
if(channel == "special")
|
||||
if(translate_binary)
|
||||
var/datum/language/binary = GLOB.all_languages["Robot Talk"]
|
||||
binary.broadcast(M, M.strip_prefixes(multilingual_to_message(message_pieces)))
|
||||
return RADIO_CONNECTION_NON_SUBSPACE
|
||||
if(translate_hive)
|
||||
var/datum/language/hivemind = GLOB.all_languages["Hivemind"]
|
||||
hivemind.broadcast(M, M.strip_prefixes(multilingual_to_message(message_pieces)))
|
||||
return RADIO_CONNECTION_NON_SUBSPACE
|
||||
return RADIO_CONNECTION_FAIL
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/device/radio/headset/receive_range(freq, level, aiOverride = 0)
|
||||
if (aiOverride)
|
||||
//playsound(loc, 'sound/effects/radio_common.ogg', 20, 1, 1, preference = /datum/client_preference/radio_sounds)
|
||||
return ..(freq, level)
|
||||
if(ishuman(src.loc))
|
||||
var/mob/living/carbon/human/H = src.loc
|
||||
if(H.l_ear == src || H.r_ear == src)
|
||||
//playsound(loc, 'sound/effects/radio_common.ogg', 20, 1, 1, preference = /datum/client_preference/radio_sounds)
|
||||
return ..(freq, level)
|
||||
return -1
|
||||
|
||||
/obj/item/device/radio/headset/get_worn_icon_state(var/slot_name)
|
||||
var/append = ""
|
||||
if(icon_override)
|
||||
switch(slot_name)
|
||||
if(slot_l_ear_str)
|
||||
append = "_l"
|
||||
if(slot_r_ear_str)
|
||||
append = "_r"
|
||||
|
||||
return "[..()][append]"
|
||||
|
||||
/obj/item/device/radio/headset/tgui_state(mob/user)
|
||||
return GLOB.tgui_inventory_state
|
||||
|
||||
/obj/item/device/radio/headset/syndicate
|
||||
origin_tech = list(TECH_ILLEGAL = 3)
|
||||
syndie = 1
|
||||
ks1type = /obj/item/device/encryptionkey/syndicate
|
||||
|
||||
/obj/item/device/radio/headset/syndicate/alt
|
||||
icon_state = "syndie_headset"
|
||||
item_state = "headset"
|
||||
origin_tech = list(TECH_ILLEGAL = 3)
|
||||
syndie = 1
|
||||
ks1type = /obj/item/device/encryptionkey/syndicate
|
||||
|
||||
/obj/item/device/radio/headset/raider
|
||||
origin_tech = list(TECH_ILLEGAL = 2)
|
||||
syndie = 1
|
||||
ks1type = /obj/item/device/encryptionkey/raider
|
||||
|
||||
/obj/item/device/radio/headset/raider/Initialize()
|
||||
. = ..()
|
||||
set_frequency(RAID_FREQ)
|
||||
|
||||
/obj/item/device/radio/headset/binary
|
||||
origin_tech = list(TECH_ILLEGAL = 3)
|
||||
ks1type = /obj/item/device/encryptionkey/binary
|
||||
|
||||
/obj/item/device/radio/headset/headset_sec
|
||||
name = "security radio headset"
|
||||
desc = "This is used by your elite security force."
|
||||
icon_state = "sec_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_sec
|
||||
|
||||
/obj/item/device/radio/headset/headset_sec/alt
|
||||
name = "security bowman headset"
|
||||
desc = "This is used by your elite security force."
|
||||
icon_state = "sec_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_sec
|
||||
|
||||
/obj/item/device/radio/headset/headset_eng
|
||||
name = "engineering radio headset"
|
||||
desc = "When the engineers wish to chat like girls."
|
||||
icon_state = "eng_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_eng
|
||||
|
||||
/obj/item/device/radio/headset/headset_eng/alt
|
||||
name = "engineering bowman headset"
|
||||
desc = "When the engineers wish to chat like girls."
|
||||
icon_state = "eng_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_eng
|
||||
|
||||
/obj/item/device/radio/headset/headset_rob
|
||||
name = "robotics radio headset"
|
||||
desc = "Made specifically for the roboticists who cannot decide between departments."
|
||||
icon_state = "rob_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_rob
|
||||
|
||||
/obj/item/device/radio/headset/headset_med
|
||||
name = "medical radio headset"
|
||||
desc = "A headset for the trained staff of the medbay."
|
||||
icon_state = "med_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_med
|
||||
|
||||
/obj/item/device/radio/headset/headset_med/alt
|
||||
name = "medical bowman headset"
|
||||
desc = "A headset for the trained staff of the medbay."
|
||||
icon_state = "med_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_med
|
||||
|
||||
/obj/item/device/radio/headset/headset_sci
|
||||
name = "science radio headset"
|
||||
desc = "A sciency headset. Like usual."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_sci
|
||||
|
||||
/obj/item/device/radio/headset/headset_medsci
|
||||
name = "medical research radio headset"
|
||||
desc = "A headset that is a result of the mating between medical and science."
|
||||
icon_state = "med_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_medsci
|
||||
|
||||
/obj/item/device/radio/headset/headset_com
|
||||
name = "command radio headset"
|
||||
desc = "A headset with a commanding channel."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_com
|
||||
|
||||
/obj/item/device/radio/headset/headset_com/alt
|
||||
name = "command bowman headset"
|
||||
desc = "A headset with a commanding channel."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_com
|
||||
|
||||
|
||||
/obj/item/device/radio/headset/heads/captain
|
||||
name = "site manager's headset"
|
||||
desc = "The headset of the boss."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/captain
|
||||
|
||||
/obj/item/device/radio/headset/heads/captain/alt
|
||||
name = "site manager's bowman headset"
|
||||
desc = "The headset of the boss."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/captain
|
||||
|
||||
/obj/item/device/radio/headset/heads/captain/sfr
|
||||
name = "SFR headset"
|
||||
desc = "A headset belonging to a Sif Free Radio DJ. SFR, best tunes in the wilderness."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/captain
|
||||
|
||||
/obj/item/device/radio/headset/heads/ai_integrated //No need to care about icons, it should be hidden inside the AI anyway.
|
||||
name = "\improper AI subspace transceiver"
|
||||
desc = "Integrated AI radio transceiver."
|
||||
icon = 'icons/obj/robot_component.dmi'
|
||||
icon_state = "radio"
|
||||
item_state = "headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/ai_integrated
|
||||
var/myAi = null // Atlantis: Reference back to the AI which has this radio.
|
||||
var/disabledAi = 0 // Atlantis: Used to manually disable AI's integrated radio via intellicard menu.
|
||||
|
||||
/obj/item/device/radio/headset/heads/ai_integrated/receive_range(freq, level)
|
||||
if (disabledAi)
|
||||
return -1 //Transciever Disabled.
|
||||
return ..(freq, level, 1)
|
||||
|
||||
/obj/item/device/radio/headset/heads/rd
|
||||
name = "research director's headset"
|
||||
desc = "Headset of the eccentric-in-chief."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/rd
|
||||
|
||||
/obj/item/device/radio/headset/heads/rd/alt
|
||||
name = "research director's bowman headset"
|
||||
desc = "Headset of the eccentric-in-chief."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/rd
|
||||
|
||||
/obj/item/device/radio/headset/heads/hos
|
||||
name = "head of security's headset"
|
||||
desc = "The headset of the hardass who protects your worthless lives."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/hos
|
||||
|
||||
/obj/item/device/radio/headset/heads/hos/alt
|
||||
name = "head of security's bowman headset"
|
||||
desc = "The headset of the hardass who protects your worthless lives."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/hos
|
||||
|
||||
/obj/item/device/radio/headset/heads/ce
|
||||
name = "chief engineer's headset"
|
||||
desc = "The headset of the clown who is in charge of the circus."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/ce
|
||||
|
||||
/obj/item/device/radio/headset/heads/ce/alt
|
||||
name = "chief engineer's bowman headset"
|
||||
desc = "The headset of the clown who is in charge of the circus."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/ce
|
||||
|
||||
/obj/item/device/radio/headset/heads/cmo
|
||||
name = "chief medical officer's headset"
|
||||
desc = "The headset of the highly trained medical chief."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/cmo
|
||||
|
||||
/obj/item/device/radio/headset/heads/cmo/alt
|
||||
name = "chief medical officer's bowman headset"
|
||||
desc = "The headset of the highly trained medical chief."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/cmo
|
||||
|
||||
/obj/item/device/radio/headset/heads/hop
|
||||
name = "head of personnel's headset"
|
||||
desc = "The headset of the poor fool who will one day be Site Manager."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/hop
|
||||
|
||||
/obj/item/device/radio/headset/heads/hop/alt
|
||||
name = "head of personnel's bowman headset"
|
||||
desc = "The headset of the poor fool who will one day be Site Manager."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/hop
|
||||
|
||||
/obj/item/device/radio/headset/headset_mine
|
||||
name = "mining radio headset"
|
||||
desc = "Headset used by miners. Has inbuilt short-band radio for when comms are down."
|
||||
icon_state = "mine_headset"
|
||||
adhoc_fallback = TRUE
|
||||
ks2type = /obj/item/device/encryptionkey/headset_cargo
|
||||
|
||||
/obj/item/device/radio/headset/headset_cargo
|
||||
name = "supply radio headset"
|
||||
desc = "A headset used by the QM and their cronies."
|
||||
icon_state = "cargo_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_cargo
|
||||
|
||||
/obj/item/device/radio/headset/headset_cargo/alt
|
||||
name = "supply bowman headset"
|
||||
desc = "A bowman headset used by the QM and their cronies."
|
||||
icon_state = "cargo_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_cargo
|
||||
|
||||
/obj/item/device/radio/headset/headset_service
|
||||
name = "service radio headset"
|
||||
desc = "Headset used by the service staff, tasked with keeping the station full, happy and clean."
|
||||
icon_state = "srv_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_service
|
||||
|
||||
/obj/item/device/radio/headset/ert
|
||||
name = "emergency response team radio headset"
|
||||
desc = "The headset of the boss's boss."
|
||||
icon_state = "com_headset"
|
||||
centComm = 1
|
||||
// freerange = 1
|
||||
ks2type = /obj/item/device/encryptionkey/ert
|
||||
|
||||
/obj/item/device/radio/headset/ert/alt
|
||||
name = "emergency response team bowman headset"
|
||||
desc = "The headset of the boss's boss."
|
||||
icon_state = "com_headset_alt"
|
||||
// freerange = 1
|
||||
ks2type = /obj/item/device/encryptionkey/ert
|
||||
|
||||
/obj/item/device/radio/headset/omni //Only for the admin intercoms
|
||||
ks2type = /obj/item/device/encryptionkey/omni
|
||||
|
||||
/obj/item/device/radio/headset/ia
|
||||
name = "internal affair's headset"
|
||||
desc = "The headset of your worst enemy."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/hos
|
||||
|
||||
/obj/item/device/radio/headset/mmi_radio
|
||||
name = "brain-integrated radio"
|
||||
desc = "MMIs and synthetic brains are often equipped with these."
|
||||
icon = 'icons/obj/robot_component.dmi'
|
||||
icon_state = "radio"
|
||||
item_state = "headset"
|
||||
var/mmiowner = null
|
||||
var/radio_enabled = 1
|
||||
|
||||
/obj/item/device/radio/headset/mmi_radio/receive_range(freq, level)
|
||||
if (!radio_enabled || istype(src.loc.loc, /mob/living/silicon) || istype(src.loc.loc, /obj/item/organ/internal))
|
||||
return -1 //Transciever Disabled.
|
||||
return ..(freq, level, 1)
|
||||
|
||||
/obj/item/device/radio/headset/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
// ..()
|
||||
user.set_machine(src)
|
||||
if(!(W.has_tool_quality(TOOL_SCREWDRIVER) || istype(W, /obj/item/device/encryptionkey)))
|
||||
return
|
||||
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
if(keyslot1 || keyslot2)
|
||||
|
||||
|
||||
for(var/ch_name in channels)
|
||||
radio_controller.remove_object(src, radiochannels[ch_name])
|
||||
secure_radio_connections[ch_name] = null
|
||||
|
||||
|
||||
if(keyslot1)
|
||||
var/turf/T = get_turf(user)
|
||||
if(T)
|
||||
keyslot1.loc = T
|
||||
keyslot1 = null
|
||||
|
||||
|
||||
|
||||
if(keyslot2)
|
||||
var/turf/T = get_turf(user)
|
||||
if(T)
|
||||
keyslot2.loc = T
|
||||
keyslot2 = null
|
||||
|
||||
recalculateChannels()
|
||||
to_chat(user, "You pop out the encryption keys in the headset!")
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
|
||||
else
|
||||
to_chat(user, "This headset doesn't have any encryption keys! How useless...")
|
||||
|
||||
if(istype(W, /obj/item/device/encryptionkey/))
|
||||
if(keyslot1 && keyslot2)
|
||||
to_chat(user, "The headset can't hold another key!")
|
||||
return
|
||||
|
||||
if(!keyslot1)
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
keyslot1 = W
|
||||
|
||||
else
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
keyslot2 = W
|
||||
|
||||
|
||||
recalculateChannels()
|
||||
|
||||
return
|
||||
|
||||
|
||||
/obj/item/device/radio/headset/recalculateChannels(var/setDescription = 0)
|
||||
src.channels = list()
|
||||
src.translate_binary = 0
|
||||
src.translate_hive = 0
|
||||
src.syndie = 0
|
||||
|
||||
if(keyslot1)
|
||||
for(var/ch_name in keyslot1.channels)
|
||||
if(ch_name in src.channels)
|
||||
continue
|
||||
src.channels += ch_name
|
||||
src.channels[ch_name] = keyslot1.channels[ch_name]
|
||||
|
||||
if(keyslot1.translate_binary)
|
||||
src.translate_binary = 1
|
||||
|
||||
if(keyslot1.translate_hive)
|
||||
src.translate_hive = 1
|
||||
|
||||
if(keyslot1.syndie)
|
||||
src.syndie = 1
|
||||
|
||||
if(keyslot2)
|
||||
for(var/ch_name in keyslot2.channels)
|
||||
if(ch_name in src.channels)
|
||||
continue
|
||||
src.channels += ch_name
|
||||
src.channels[ch_name] = keyslot2.channels[ch_name]
|
||||
|
||||
if(keyslot2.translate_binary)
|
||||
src.translate_binary = 1
|
||||
|
||||
if(keyslot2.translate_hive)
|
||||
src.translate_hive = 1
|
||||
|
||||
if(keyslot2.syndie)
|
||||
src.syndie = 1
|
||||
|
||||
|
||||
for (var/ch_name in channels)
|
||||
if(!radio_controller)
|
||||
sleep(30) // Waiting for the radio_controller to be created.
|
||||
if(!radio_controller)
|
||||
src.name = "broken radio headset"
|
||||
return
|
||||
|
||||
secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
|
||||
|
||||
if(setDescription)
|
||||
setupRadioDescription()
|
||||
|
||||
return
|
||||
|
||||
/obj/item/device/radio/headset/proc/setupRadioDescription()
|
||||
var/radio_text = ""
|
||||
for(var/i = 1 to channels.len)
|
||||
var/channel = channels[i]
|
||||
var/key = get_radio_key_from_channel(channel)
|
||||
radio_text += "[key] - [channel]"
|
||||
if(i != channels.len)
|
||||
radio_text += ", "
|
||||
|
||||
radio_desc = radio_text
|
||||
/obj/item/device/radio/headset
|
||||
name = "radio headset"
|
||||
desc = "An updated, modular intercom that fits over the head. Takes encryption keys"
|
||||
var/radio_desc = ""
|
||||
icon_state = "headset"
|
||||
item_state = null //To remove the radio's state
|
||||
matter = list(MAT_STEEL = 75)
|
||||
subspace_transmission = 1
|
||||
canhear_range = 0 // can't hear headsets from very far away
|
||||
slot_flags = SLOT_EARS
|
||||
sprite_sheets = list(SPECIES_TESHARI = 'icons/inventory/ears/mob_teshari.dmi')
|
||||
|
||||
var/translate_binary = 0
|
||||
var/translate_hive = 0
|
||||
var/obj/item/device/encryptionkey/keyslot1 = null
|
||||
var/obj/item/device/encryptionkey/keyslot2 = null
|
||||
var/ks1type = null
|
||||
var/ks2type = null
|
||||
|
||||
drop_sound = 'sound/items/drop/component.ogg'
|
||||
pickup_sound = 'sound/items/pickup/component.ogg'
|
||||
|
||||
/obj/item/device/radio/headset/New()
|
||||
..()
|
||||
internal_channels.Cut()
|
||||
if(ks1type)
|
||||
keyslot1 = new ks1type(src)
|
||||
if(ks2type)
|
||||
keyslot2 = new ks2type(src)
|
||||
recalculateChannels(1)
|
||||
|
||||
/obj/item/device/radio/headset/Destroy()
|
||||
qdel(keyslot1)
|
||||
qdel(keyslot2)
|
||||
keyslot1 = null
|
||||
keyslot2 = null
|
||||
return ..()
|
||||
|
||||
/obj/item/device/radio/headset/list_channels(var/mob/user)
|
||||
return list_secure_channels()
|
||||
|
||||
/obj/item/device/radio/headset/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
if(radio_desc && Adjacent(user))
|
||||
. += "The following channels are available:"
|
||||
. += radio_desc
|
||||
|
||||
/obj/item/device/radio/headset/handle_message_mode(mob/living/M as mob, list/message_pieces, channel)
|
||||
if(channel == "special")
|
||||
if(translate_binary)
|
||||
var/datum/language/binary = GLOB.all_languages["Robot Talk"]
|
||||
binary.broadcast(M, M.strip_prefixes(multilingual_to_message(message_pieces)))
|
||||
return RADIO_CONNECTION_NON_SUBSPACE
|
||||
if(translate_hive)
|
||||
var/datum/language/hivemind = GLOB.all_languages["Hivemind"]
|
||||
hivemind.broadcast(M, M.strip_prefixes(multilingual_to_message(message_pieces)))
|
||||
return RADIO_CONNECTION_NON_SUBSPACE
|
||||
return RADIO_CONNECTION_FAIL
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/device/radio/headset/receive_range(freq, level, aiOverride = 0)
|
||||
if (aiOverride)
|
||||
//playsound(loc, 'sound/effects/radio_common.ogg', 20, 1, 1, preference = /datum/client_preference/radio_sounds)
|
||||
return ..(freq, level)
|
||||
if(ishuman(src.loc))
|
||||
var/mob/living/carbon/human/H = src.loc
|
||||
if(H.l_ear == src || H.r_ear == src)
|
||||
//playsound(loc, 'sound/effects/radio_common.ogg', 20, 1, 1, preference = /datum/client_preference/radio_sounds)
|
||||
return ..(freq, level)
|
||||
return -1
|
||||
|
||||
/obj/item/device/radio/headset/get_worn_icon_state(var/slot_name)
|
||||
var/append = ""
|
||||
if(icon_override)
|
||||
switch(slot_name)
|
||||
if(slot_l_ear_str)
|
||||
append = "_l"
|
||||
if(slot_r_ear_str)
|
||||
append = "_r"
|
||||
|
||||
return "[..()][append]"
|
||||
|
||||
/obj/item/device/radio/headset/tgui_state(mob/user)
|
||||
return GLOB.tgui_inventory_state
|
||||
|
||||
/obj/item/device/radio/headset/syndicate
|
||||
origin_tech = list(TECH_ILLEGAL = 3)
|
||||
syndie = 1
|
||||
ks1type = /obj/item/device/encryptionkey/syndicate
|
||||
|
||||
/obj/item/device/radio/headset/syndicate/alt
|
||||
icon_state = "syndie_headset"
|
||||
item_state = "headset"
|
||||
origin_tech = list(TECH_ILLEGAL = 3)
|
||||
syndie = 1
|
||||
ks1type = /obj/item/device/encryptionkey/syndicate
|
||||
|
||||
/obj/item/device/radio/headset/raider
|
||||
origin_tech = list(TECH_ILLEGAL = 2)
|
||||
syndie = 1
|
||||
ks1type = /obj/item/device/encryptionkey/raider
|
||||
|
||||
/obj/item/device/radio/headset/raider/Initialize()
|
||||
. = ..()
|
||||
set_frequency(RAID_FREQ)
|
||||
|
||||
/obj/item/device/radio/headset/binary
|
||||
origin_tech = list(TECH_ILLEGAL = 3)
|
||||
ks1type = /obj/item/device/encryptionkey/binary
|
||||
|
||||
/obj/item/device/radio/headset/headset_sec
|
||||
name = "security radio headset"
|
||||
desc = "This is used by your elite security force."
|
||||
icon_state = "sec_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_sec
|
||||
|
||||
/obj/item/device/radio/headset/headset_sec/alt
|
||||
name = "security bowman headset"
|
||||
desc = "This is used by your elite security force."
|
||||
icon_state = "sec_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_sec
|
||||
|
||||
/obj/item/device/radio/headset/headset_eng
|
||||
name = "engineering radio headset"
|
||||
desc = "When the engineers wish to chat like girls."
|
||||
icon_state = "eng_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_eng
|
||||
|
||||
/obj/item/device/radio/headset/headset_eng/alt
|
||||
name = "engineering bowman headset"
|
||||
desc = "When the engineers wish to chat like girls."
|
||||
icon_state = "eng_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_eng
|
||||
|
||||
/obj/item/device/radio/headset/headset_rob
|
||||
name = "robotics radio headset"
|
||||
desc = "Made specifically for the roboticists who cannot decide between departments."
|
||||
icon_state = "rob_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_rob
|
||||
|
||||
/obj/item/device/radio/headset/headset_med
|
||||
name = "medical radio headset"
|
||||
desc = "A headset for the trained staff of the medbay."
|
||||
icon_state = "med_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_med
|
||||
|
||||
/obj/item/device/radio/headset/headset_med/alt
|
||||
name = "medical bowman headset"
|
||||
desc = "A headset for the trained staff of the medbay."
|
||||
icon_state = "med_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_med
|
||||
|
||||
/obj/item/device/radio/headset/headset_sci
|
||||
name = "science radio headset"
|
||||
desc = "A sciency headset. Like usual."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_sci
|
||||
|
||||
/obj/item/device/radio/headset/headset_medsci
|
||||
name = "medical research radio headset"
|
||||
desc = "A headset that is a result of the mating between medical and science."
|
||||
icon_state = "med_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_medsci
|
||||
|
||||
/obj/item/device/radio/headset/headset_com
|
||||
name = "command radio headset"
|
||||
desc = "A headset with a commanding channel."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_com
|
||||
|
||||
/obj/item/device/radio/headset/headset_com/alt
|
||||
name = "command bowman headset"
|
||||
desc = "A headset with a commanding channel."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_com
|
||||
|
||||
|
||||
/obj/item/device/radio/headset/heads/captain
|
||||
name = "site manager's headset"
|
||||
desc = "The headset of the boss."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/captain
|
||||
|
||||
/obj/item/device/radio/headset/heads/captain/alt
|
||||
name = "site manager's bowman headset"
|
||||
desc = "The headset of the boss."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/captain
|
||||
|
||||
/obj/item/device/radio/headset/heads/captain/sfr
|
||||
name = "SFR headset"
|
||||
desc = "A headset belonging to a Sif Free Radio DJ. SFR, best tunes in the wilderness."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/captain
|
||||
|
||||
/obj/item/device/radio/headset/heads/ai_integrated //No need to care about icons, it should be hidden inside the AI anyway.
|
||||
name = "\improper AI subspace transceiver"
|
||||
desc = "Integrated AI radio transceiver."
|
||||
icon = 'icons/obj/robot_component.dmi'
|
||||
icon_state = "radio"
|
||||
item_state = "headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/ai_integrated
|
||||
var/myAi = null // Atlantis: Reference back to the AI which has this radio.
|
||||
var/disabledAi = 0 // Atlantis: Used to manually disable AI's integrated radio via intellicard menu.
|
||||
|
||||
/obj/item/device/radio/headset/heads/ai_integrated/receive_range(freq, level)
|
||||
if (disabledAi)
|
||||
return -1 //Transciever Disabled.
|
||||
return ..(freq, level, 1)
|
||||
|
||||
/obj/item/device/radio/headset/heads/rd
|
||||
name = "research director's headset"
|
||||
desc = "Headset of the eccentric-in-chief."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/rd
|
||||
|
||||
/obj/item/device/radio/headset/heads/rd/alt
|
||||
name = "research director's bowman headset"
|
||||
desc = "Headset of the eccentric-in-chief."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/rd
|
||||
|
||||
/obj/item/device/radio/headset/heads/hos
|
||||
name = "head of security's headset"
|
||||
desc = "The headset of the hardass who protects your worthless lives."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/hos
|
||||
|
||||
/obj/item/device/radio/headset/heads/hos/alt
|
||||
name = "head of security's bowman headset"
|
||||
desc = "The headset of the hardass who protects your worthless lives."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/hos
|
||||
|
||||
/obj/item/device/radio/headset/heads/ce
|
||||
name = "chief engineer's headset"
|
||||
desc = "The headset of the clown who is in charge of the circus."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/ce
|
||||
|
||||
/obj/item/device/radio/headset/heads/ce/alt
|
||||
name = "chief engineer's bowman headset"
|
||||
desc = "The headset of the clown who is in charge of the circus."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/ce
|
||||
|
||||
/obj/item/device/radio/headset/heads/cmo
|
||||
name = "chief medical officer's headset"
|
||||
desc = "The headset of the highly trained medical chief."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/cmo
|
||||
|
||||
/obj/item/device/radio/headset/heads/cmo/alt
|
||||
name = "chief medical officer's bowman headset"
|
||||
desc = "The headset of the highly trained medical chief."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/cmo
|
||||
|
||||
/obj/item/device/radio/headset/heads/hop
|
||||
name = "head of personnel's headset"
|
||||
desc = "The headset of the poor fool who will one day be Site Manager."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/hop
|
||||
|
||||
/obj/item/device/radio/headset/heads/hop/alt
|
||||
name = "head of personnel's bowman headset"
|
||||
desc = "The headset of the poor fool who will one day be Site Manager."
|
||||
icon_state = "com_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/hop
|
||||
|
||||
/obj/item/device/radio/headset/headset_mine
|
||||
name = "mining radio headset"
|
||||
desc = "Headset used by miners. Has inbuilt short-band radio for when comms are down."
|
||||
icon_state = "mine_headset"
|
||||
adhoc_fallback = TRUE
|
||||
ks2type = /obj/item/device/encryptionkey/headset_cargo
|
||||
|
||||
/obj/item/device/radio/headset/headset_cargo
|
||||
name = "supply radio headset"
|
||||
desc = "A headset used by the QM and their cronies."
|
||||
icon_state = "cargo_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_cargo
|
||||
|
||||
/obj/item/device/radio/headset/headset_cargo/alt
|
||||
name = "supply bowman headset"
|
||||
desc = "A bowman headset used by the QM and their cronies."
|
||||
icon_state = "cargo_headset_alt"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_cargo
|
||||
|
||||
/obj/item/device/radio/headset/headset_service
|
||||
name = "service radio headset"
|
||||
desc = "Headset used by the service staff, tasked with keeping the station full, happy and clean."
|
||||
icon_state = "srv_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/headset_service
|
||||
|
||||
/obj/item/device/radio/headset/ert
|
||||
name = "emergency response team radio headset"
|
||||
desc = "The headset of the boss's boss."
|
||||
icon_state = "com_headset"
|
||||
centComm = 1
|
||||
// freerange = 1
|
||||
ks2type = /obj/item/device/encryptionkey/ert
|
||||
|
||||
/obj/item/device/radio/headset/ert/alt
|
||||
name = "emergency response team bowman headset"
|
||||
desc = "The headset of the boss's boss."
|
||||
icon_state = "com_headset_alt"
|
||||
// freerange = 1
|
||||
ks2type = /obj/item/device/encryptionkey/ert
|
||||
|
||||
/obj/item/device/radio/headset/omni //Only for the admin intercoms
|
||||
ks2type = /obj/item/device/encryptionkey/omni
|
||||
|
||||
/obj/item/device/radio/headset/ia
|
||||
name = "internal affair's headset"
|
||||
desc = "The headset of your worst enemy."
|
||||
icon_state = "com_headset"
|
||||
ks2type = /obj/item/device/encryptionkey/heads/hos
|
||||
|
||||
/obj/item/device/radio/headset/mmi_radio
|
||||
name = "brain-integrated radio"
|
||||
desc = "MMIs and synthetic brains are often equipped with these."
|
||||
icon = 'icons/obj/robot_component.dmi'
|
||||
icon_state = "radio"
|
||||
item_state = "headset"
|
||||
var/mmiowner = null
|
||||
var/radio_enabled = 1
|
||||
|
||||
/obj/item/device/radio/headset/mmi_radio/receive_range(freq, level)
|
||||
if (!radio_enabled || istype(src.loc.loc, /mob/living/silicon) || istype(src.loc.loc, /obj/item/organ/internal))
|
||||
return -1 //Transciever Disabled.
|
||||
return ..(freq, level, 1)
|
||||
|
||||
/obj/item/device/radio/headset/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
// ..()
|
||||
user.set_machine(src)
|
||||
if(!(W.has_tool_quality(TOOL_SCREWDRIVER) || istype(W, /obj/item/device/encryptionkey)))
|
||||
return
|
||||
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
if(keyslot1 || keyslot2)
|
||||
|
||||
|
||||
for(var/ch_name in channels)
|
||||
radio_controller.remove_object(src, radiochannels[ch_name])
|
||||
secure_radio_connections[ch_name] = null
|
||||
|
||||
|
||||
if(keyslot1)
|
||||
var/turf/T = get_turf(user)
|
||||
if(T)
|
||||
keyslot1.loc = T
|
||||
keyslot1 = null
|
||||
|
||||
|
||||
|
||||
if(keyslot2)
|
||||
var/turf/T = get_turf(user)
|
||||
if(T)
|
||||
keyslot2.loc = T
|
||||
keyslot2 = null
|
||||
|
||||
recalculateChannels()
|
||||
to_chat(user, "You pop out the encryption keys in the headset!")
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
|
||||
else
|
||||
to_chat(user, "This headset doesn't have any encryption keys! How useless...")
|
||||
|
||||
if(istype(W, /obj/item/device/encryptionkey/))
|
||||
if(keyslot1 && keyslot2)
|
||||
to_chat(user, "The headset can't hold another key!")
|
||||
return
|
||||
|
||||
if(!keyslot1)
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
keyslot1 = W
|
||||
|
||||
else
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
keyslot2 = W
|
||||
|
||||
|
||||
recalculateChannels()
|
||||
|
||||
return
|
||||
|
||||
|
||||
/obj/item/device/radio/headset/recalculateChannels(var/setDescription = 0)
|
||||
src.channels = list()
|
||||
src.translate_binary = 0
|
||||
src.translate_hive = 0
|
||||
src.syndie = 0
|
||||
|
||||
if(keyslot1)
|
||||
for(var/ch_name in keyslot1.channels)
|
||||
if(ch_name in src.channels)
|
||||
continue
|
||||
src.channels += ch_name
|
||||
src.channels[ch_name] = keyslot1.channels[ch_name]
|
||||
|
||||
if(keyslot1.translate_binary)
|
||||
src.translate_binary = 1
|
||||
|
||||
if(keyslot1.translate_hive)
|
||||
src.translate_hive = 1
|
||||
|
||||
if(keyslot1.syndie)
|
||||
src.syndie = 1
|
||||
|
||||
if(keyslot2)
|
||||
for(var/ch_name in keyslot2.channels)
|
||||
if(ch_name in src.channels)
|
||||
continue
|
||||
src.channels += ch_name
|
||||
src.channels[ch_name] = keyslot2.channels[ch_name]
|
||||
|
||||
if(keyslot2.translate_binary)
|
||||
src.translate_binary = 1
|
||||
|
||||
if(keyslot2.translate_hive)
|
||||
src.translate_hive = 1
|
||||
|
||||
if(keyslot2.syndie)
|
||||
src.syndie = 1
|
||||
|
||||
|
||||
for (var/ch_name in channels)
|
||||
if(!radio_controller)
|
||||
sleep(30) // Waiting for the radio_controller to be created.
|
||||
if(!radio_controller)
|
||||
src.name = "broken radio headset"
|
||||
return
|
||||
|
||||
secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
|
||||
|
||||
if(setDescription)
|
||||
setupRadioDescription()
|
||||
|
||||
return
|
||||
|
||||
/obj/item/device/radio/headset/proc/setupRadioDescription()
|
||||
var/radio_text = ""
|
||||
for(var/i = 1 to channels.len)
|
||||
var/channel = channels[i]
|
||||
var/key = get_radio_key_from_channel(channel)
|
||||
radio_text += "[key] - [channel]"
|
||||
if(i != channels.len)
|
||||
radio_text += ", "
|
||||
|
||||
radio_desc = radio_text
|
||||
|
||||
@@ -1,229 +1,229 @@
|
||||
/obj/item/device/radio/intercom
|
||||
name = "station intercom (General)"
|
||||
desc = "Talk through this."
|
||||
icon = 'icons/obj/radio_vr.dmi' //VOREStation Edit - New Icon
|
||||
icon_state = "intercom"
|
||||
layer = ABOVE_WINDOW_LAYER
|
||||
anchored = TRUE
|
||||
w_class = ITEMSIZE_LARGE
|
||||
canhear_range = 7 //VOREStation Edit
|
||||
flags = NOBLOODY
|
||||
light_color = "#00ff00"
|
||||
light_power = 0.25
|
||||
blocks_emissive = NONE
|
||||
vis_flags = VIS_HIDE // They have an emissive that looks bad in openspace due to their wall-mounted nature
|
||||
var/circuit = /obj/item/weapon/circuitboard/intercom
|
||||
var/number = 0
|
||||
var/wiresexposed = 0
|
||||
|
||||
/obj/item/device/radio/intercom/Initialize()
|
||||
. = ..()
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
GLOB.apc_event.register(A, src, /atom/proc/update_icon)
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/radio/intercom/Destroy()
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
GLOB.apc_event.unregister(A, src, /atom/proc/update_icon)
|
||||
return ..()
|
||||
|
||||
/obj/item/device/radio/intercom/custom
|
||||
name = "station intercom (Custom)"
|
||||
broadcasting = 0
|
||||
listening = 0
|
||||
|
||||
/obj/item/device/radio/intercom/interrogation
|
||||
name = "station intercom (Interrogation)"
|
||||
frequency = 1449
|
||||
|
||||
/obj/item/device/radio/intercom/private
|
||||
name = "station intercom (Private)"
|
||||
frequency = AI_FREQ
|
||||
|
||||
/obj/item/device/radio/intercom/specops
|
||||
name = "\improper Spec Ops intercom"
|
||||
frequency = ERT_FREQ
|
||||
subspace_transmission = 1
|
||||
centComm = 1
|
||||
|
||||
/obj/item/device/radio/intercom/department
|
||||
canhear_range = 5
|
||||
broadcasting = 0
|
||||
listening = 1
|
||||
|
||||
/obj/item/device/radio/intercom/department/medbay
|
||||
name = "station intercom (Medbay)"
|
||||
icon_state = "medintercom"
|
||||
light_color = "#00aaff"
|
||||
frequency = MED_I_FREQ
|
||||
|
||||
/obj/item/device/radio/intercom/department/security
|
||||
name = "station intercom (Security)"
|
||||
icon_state = "secintercom"
|
||||
light_color = "#ff0000"
|
||||
frequency = SEC_I_FREQ
|
||||
|
||||
/obj/item/device/radio/intercom/entertainment
|
||||
name = "entertainment intercom"
|
||||
frequency = ENT_FREQ
|
||||
|
||||
/obj/item/device/radio/intercom/omni
|
||||
name = "global announcer"
|
||||
/obj/item/device/radio/intercom/omni/Initialize()
|
||||
channels = radiochannels.Copy()
|
||||
return ..()
|
||||
|
||||
/obj/item/device/radio/intercom/New()
|
||||
..()
|
||||
circuit = new circuit(src)
|
||||
|
||||
/obj/item/device/radio/intercom/department/medbay/New()
|
||||
..()
|
||||
internal_channels = default_medbay_channels.Copy()
|
||||
|
||||
/obj/item/device/radio/intercom/department/security/New()
|
||||
..()
|
||||
internal_channels = list(
|
||||
num2text(PUB_FREQ) = list(),
|
||||
num2text(SEC_I_FREQ) = list(access_security)
|
||||
)
|
||||
|
||||
/obj/item/device/radio/intercom/entertainment/New()
|
||||
..()
|
||||
internal_channels = list(
|
||||
num2text(PUB_FREQ) = list(),
|
||||
num2text(ENT_FREQ) = list()
|
||||
)
|
||||
|
||||
/obj/item/device/radio/intercom/syndicate
|
||||
name = "illicit intercom"
|
||||
desc = "Talk through this. Evilly"
|
||||
frequency = SYND_FREQ
|
||||
subspace_transmission = 1
|
||||
syndie = 1
|
||||
|
||||
/obj/item/device/radio/intercom/syndicate/New()
|
||||
..()
|
||||
internal_channels[num2text(SYND_FREQ)] = list(access_syndicate)
|
||||
|
||||
/obj/item/device/radio/intercom/raider
|
||||
name = "illicit intercom"
|
||||
desc = "Pirate radio, but not in the usual sense of the word."
|
||||
frequency = RAID_FREQ
|
||||
subspace_transmission = 1
|
||||
syndie = 1
|
||||
|
||||
/obj/item/device/radio/intercom/raider/New()
|
||||
..()
|
||||
internal_channels[num2text(RAID_FREQ)] = list(access_syndicate)
|
||||
|
||||
/obj/item/device/radio/intercom/attack_ai(mob/user as mob)
|
||||
src.add_fingerprint(user)
|
||||
spawn (0)
|
||||
attack_self(user)
|
||||
|
||||
/obj/item/device/radio/intercom/attack_hand(mob/user as mob)
|
||||
src.add_fingerprint(user)
|
||||
spawn (0)
|
||||
attack_self(user)
|
||||
|
||||
/obj/item/device/radio/intercom/attackby(obj/item/W as obj, mob/user as mob)
|
||||
add_fingerprint(user)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER)) // Opening the intercom up.
|
||||
wiresexposed = !wiresexposed
|
||||
to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]")
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
update_icon()
|
||||
else if(wiresexposed && W.has_tool_quality(TOOL_WIRECUTTER))
|
||||
user.visible_message("<span class='warning'>[user] has cut the wires inside \the [src]!</span>", "You have cut the wires inside \the [src].")
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
new/obj/item/stack/cable_coil(get_turf(src), 5)
|
||||
var/obj/structure/frame/A = new /obj/structure/frame(src.loc)
|
||||
var/obj/item/weapon/circuitboard/M = circuit
|
||||
A.frame_type = M.board_type
|
||||
A.pixel_x = pixel_x
|
||||
A.pixel_y = pixel_y
|
||||
A.circuit = M
|
||||
A.set_dir(dir)
|
||||
A.anchored = TRUE
|
||||
A.state = 2
|
||||
A.update_icon()
|
||||
M.deconstruct(src)
|
||||
qdel(src)
|
||||
else
|
||||
src.attack_hand(user)
|
||||
|
||||
/obj/item/device/radio/intercom/receive_range(freq, level)
|
||||
if (!on)
|
||||
return -1
|
||||
if(!(0 in level))
|
||||
var/turf/position = get_turf(src)
|
||||
if(isnull(position) || !(position.z in level))
|
||||
return -1
|
||||
if (!src.listening)
|
||||
return -1
|
||||
if(freq in ANTAG_FREQS)
|
||||
if(!(src.syndie))
|
||||
return -1//Prevents broadcast of messages over devices lacking the encryption
|
||||
|
||||
return canhear_range
|
||||
|
||||
/obj/item/device/radio/intercom/update_icon()
|
||||
var/area/A = get_area(src)
|
||||
on = A?.powered(EQUIP)
|
||||
|
||||
cut_overlays()
|
||||
|
||||
if(!on)
|
||||
set_light(0)
|
||||
set_light_on(FALSE)
|
||||
if(wiresexposed)
|
||||
icon_state = "intercom-p_open"
|
||||
else
|
||||
icon_state = "intercom-p"
|
||||
else
|
||||
if(wiresexposed)
|
||||
icon_state = "intercom_open"
|
||||
set_light(0)
|
||||
set_light_on(FALSE)
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
add_overlay(mutable_appearance(icon, "[icon_state]_ov"))
|
||||
add_overlay(emissive_appearance(icon, "[icon_state]_ov"))
|
||||
set_light(2)
|
||||
set_light_on(TRUE)
|
||||
|
||||
//VOREStation Add Start
|
||||
/obj/item/device/radio/intercom/AICtrlClick(var/mob/user)
|
||||
ToggleBroadcast()
|
||||
to_chat(user, "<span class='notice'>\The [src]'s microphone is now <b>[broadcasting ? "enabled" : "disabled"]</b>.</span>")
|
||||
|
||||
/obj/item/device/radio/intercom/AIAltClick(var/mob/user)
|
||||
if(frequency == AI_FREQ)
|
||||
set_frequency(initial(frequency))
|
||||
to_chat(user, "<span class='notice'>\The [src]'s frequency is now set to [span_green("<b>Default</b>")].</span>")
|
||||
else
|
||||
set_frequency(AI_FREQ)
|
||||
to_chat(user, "<span class='notice'>\The [src]'s frequency is now set to [span_pink("<b>AI Private</b>")].</span>")
|
||||
//VOREStation Add End
|
||||
/obj/item/device/radio/intercom/locked
|
||||
var/locked_frequency
|
||||
|
||||
/obj/item/device/radio/intercom/locked/set_frequency(var/frequency)
|
||||
if(frequency == locked_frequency)
|
||||
..(locked_frequency)
|
||||
|
||||
/obj/item/device/radio/intercom/locked/list_channels()
|
||||
return ""
|
||||
|
||||
/obj/item/device/radio/intercom/locked/ai_private
|
||||
name = "\improper AI intercom"
|
||||
frequency = AI_FREQ
|
||||
broadcasting = 1
|
||||
listening = 1
|
||||
|
||||
/obj/item/device/radio/intercom/locked/confessional
|
||||
name = "confessional intercom"
|
||||
frequency = 1480
|
||||
/obj/item/device/radio/intercom
|
||||
name = "station intercom (General)"
|
||||
desc = "Talk through this."
|
||||
icon = 'icons/obj/radio_vr.dmi' //VOREStation Edit - New Icon
|
||||
icon_state = "intercom"
|
||||
layer = ABOVE_WINDOW_LAYER
|
||||
anchored = TRUE
|
||||
w_class = ITEMSIZE_LARGE
|
||||
canhear_range = 7 //VOREStation Edit
|
||||
flags = NOBLOODY
|
||||
light_color = "#00ff00"
|
||||
light_power = 0.25
|
||||
blocks_emissive = NONE
|
||||
vis_flags = VIS_HIDE // They have an emissive that looks bad in openspace due to their wall-mounted nature
|
||||
var/circuit = /obj/item/weapon/circuitboard/intercom
|
||||
var/number = 0
|
||||
var/wiresexposed = 0
|
||||
|
||||
/obj/item/device/radio/intercom/Initialize()
|
||||
. = ..()
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
GLOB.apc_event.register(A, src, /atom/proc/update_icon)
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/radio/intercom/Destroy()
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
GLOB.apc_event.unregister(A, src, /atom/proc/update_icon)
|
||||
return ..()
|
||||
|
||||
/obj/item/device/radio/intercom/custom
|
||||
name = "station intercom (Custom)"
|
||||
broadcasting = 0
|
||||
listening = 0
|
||||
|
||||
/obj/item/device/radio/intercom/interrogation
|
||||
name = "station intercom (Interrogation)"
|
||||
frequency = 1449
|
||||
|
||||
/obj/item/device/radio/intercom/private
|
||||
name = "station intercom (Private)"
|
||||
frequency = AI_FREQ
|
||||
|
||||
/obj/item/device/radio/intercom/specops
|
||||
name = "\improper Spec Ops intercom"
|
||||
frequency = ERT_FREQ
|
||||
subspace_transmission = 1
|
||||
centComm = 1
|
||||
|
||||
/obj/item/device/radio/intercom/department
|
||||
canhear_range = 5
|
||||
broadcasting = 0
|
||||
listening = 1
|
||||
|
||||
/obj/item/device/radio/intercom/department/medbay
|
||||
name = "station intercom (Medbay)"
|
||||
icon_state = "medintercom"
|
||||
light_color = "#00aaff"
|
||||
frequency = MED_I_FREQ
|
||||
|
||||
/obj/item/device/radio/intercom/department/security
|
||||
name = "station intercom (Security)"
|
||||
icon_state = "secintercom"
|
||||
light_color = "#ff0000"
|
||||
frequency = SEC_I_FREQ
|
||||
|
||||
/obj/item/device/radio/intercom/entertainment
|
||||
name = "entertainment intercom"
|
||||
frequency = ENT_FREQ
|
||||
|
||||
/obj/item/device/radio/intercom/omni
|
||||
name = "global announcer"
|
||||
/obj/item/device/radio/intercom/omni/Initialize()
|
||||
channels = radiochannels.Copy()
|
||||
return ..()
|
||||
|
||||
/obj/item/device/radio/intercom/New()
|
||||
..()
|
||||
circuit = new circuit(src)
|
||||
|
||||
/obj/item/device/radio/intercom/department/medbay/New()
|
||||
..()
|
||||
internal_channels = default_medbay_channels.Copy()
|
||||
|
||||
/obj/item/device/radio/intercom/department/security/New()
|
||||
..()
|
||||
internal_channels = list(
|
||||
num2text(PUB_FREQ) = list(),
|
||||
num2text(SEC_I_FREQ) = list(access_security)
|
||||
)
|
||||
|
||||
/obj/item/device/radio/intercom/entertainment/New()
|
||||
..()
|
||||
internal_channels = list(
|
||||
num2text(PUB_FREQ) = list(),
|
||||
num2text(ENT_FREQ) = list()
|
||||
)
|
||||
|
||||
/obj/item/device/radio/intercom/syndicate
|
||||
name = "illicit intercom"
|
||||
desc = "Talk through this. Evilly"
|
||||
frequency = SYND_FREQ
|
||||
subspace_transmission = 1
|
||||
syndie = 1
|
||||
|
||||
/obj/item/device/radio/intercom/syndicate/New()
|
||||
..()
|
||||
internal_channels[num2text(SYND_FREQ)] = list(access_syndicate)
|
||||
|
||||
/obj/item/device/radio/intercom/raider
|
||||
name = "illicit intercom"
|
||||
desc = "Pirate radio, but not in the usual sense of the word."
|
||||
frequency = RAID_FREQ
|
||||
subspace_transmission = 1
|
||||
syndie = 1
|
||||
|
||||
/obj/item/device/radio/intercom/raider/New()
|
||||
..()
|
||||
internal_channels[num2text(RAID_FREQ)] = list(access_syndicate)
|
||||
|
||||
/obj/item/device/radio/intercom/attack_ai(mob/user as mob)
|
||||
src.add_fingerprint(user)
|
||||
spawn (0)
|
||||
attack_self(user)
|
||||
|
||||
/obj/item/device/radio/intercom/attack_hand(mob/user as mob)
|
||||
src.add_fingerprint(user)
|
||||
spawn (0)
|
||||
attack_self(user)
|
||||
|
||||
/obj/item/device/radio/intercom/attackby(obj/item/W as obj, mob/user as mob)
|
||||
add_fingerprint(user)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER)) // Opening the intercom up.
|
||||
wiresexposed = !wiresexposed
|
||||
to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]")
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
update_icon()
|
||||
else if(wiresexposed && W.has_tool_quality(TOOL_WIRECUTTER))
|
||||
user.visible_message("<span class='warning'>[user] has cut the wires inside \the [src]!</span>", "You have cut the wires inside \the [src].")
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
new/obj/item/stack/cable_coil(get_turf(src), 5)
|
||||
var/obj/structure/frame/A = new /obj/structure/frame(src.loc)
|
||||
var/obj/item/weapon/circuitboard/M = circuit
|
||||
A.frame_type = M.board_type
|
||||
A.pixel_x = pixel_x
|
||||
A.pixel_y = pixel_y
|
||||
A.circuit = M
|
||||
A.set_dir(dir)
|
||||
A.anchored = TRUE
|
||||
A.state = 2
|
||||
A.update_icon()
|
||||
M.deconstruct(src)
|
||||
qdel(src)
|
||||
else
|
||||
src.attack_hand(user)
|
||||
|
||||
/obj/item/device/radio/intercom/receive_range(freq, level)
|
||||
if (!on)
|
||||
return -1
|
||||
if(!(0 in level))
|
||||
var/turf/position = get_turf(src)
|
||||
if(isnull(position) || !(position.z in level))
|
||||
return -1
|
||||
if (!src.listening)
|
||||
return -1
|
||||
if(freq in ANTAG_FREQS)
|
||||
if(!(src.syndie))
|
||||
return -1//Prevents broadcast of messages over devices lacking the encryption
|
||||
|
||||
return canhear_range
|
||||
|
||||
/obj/item/device/radio/intercom/update_icon()
|
||||
var/area/A = get_area(src)
|
||||
on = A?.powered(EQUIP)
|
||||
|
||||
cut_overlays()
|
||||
|
||||
if(!on)
|
||||
set_light(0)
|
||||
set_light_on(FALSE)
|
||||
if(wiresexposed)
|
||||
icon_state = "intercom-p_open"
|
||||
else
|
||||
icon_state = "intercom-p"
|
||||
else
|
||||
if(wiresexposed)
|
||||
icon_state = "intercom_open"
|
||||
set_light(0)
|
||||
set_light_on(FALSE)
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
add_overlay(mutable_appearance(icon, "[icon_state]_ov"))
|
||||
add_overlay(emissive_appearance(icon, "[icon_state]_ov"))
|
||||
set_light(2)
|
||||
set_light_on(TRUE)
|
||||
|
||||
//VOREStation Add Start
|
||||
/obj/item/device/radio/intercom/AICtrlClick(var/mob/user)
|
||||
ToggleBroadcast()
|
||||
to_chat(user, "<span class='notice'>\The [src]'s microphone is now <b>[broadcasting ? "enabled" : "disabled"]</b>.</span>")
|
||||
|
||||
/obj/item/device/radio/intercom/AIAltClick(var/mob/user)
|
||||
if(frequency == AI_FREQ)
|
||||
set_frequency(initial(frequency))
|
||||
to_chat(user, "<span class='notice'>\The [src]'s frequency is now set to [span_green("<b>Default</b>")].</span>")
|
||||
else
|
||||
set_frequency(AI_FREQ)
|
||||
to_chat(user, "<span class='notice'>\The [src]'s frequency is now set to [span_pink("<b>AI Private</b>")].</span>")
|
||||
//VOREStation Add End
|
||||
/obj/item/device/radio/intercom/locked
|
||||
var/locked_frequency
|
||||
|
||||
/obj/item/device/radio/intercom/locked/set_frequency(var/frequency)
|
||||
if(frequency == locked_frequency)
|
||||
..(locked_frequency)
|
||||
|
||||
/obj/item/device/radio/intercom/locked/list_channels()
|
||||
return ""
|
||||
|
||||
/obj/item/device/radio/intercom/locked/ai_private
|
||||
name = "\improper AI intercom"
|
||||
frequency = AI_FREQ
|
||||
broadcasting = 1
|
||||
listening = 1
|
||||
|
||||
/obj/item/device/radio/intercom/locked/confessional
|
||||
name = "confessional intercom"
|
||||
frequency = 1480
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,275 +1,275 @@
|
||||
/obj/item/device/camerabug
|
||||
name = "mobile camera pod"
|
||||
desc = "A camera pod used by tactical operators. Must be linked to a camera scanner unit."
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "camgrenade"
|
||||
item_state = "empgrenade"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
force = 0
|
||||
throwforce = 5.0
|
||||
throw_range = 15
|
||||
throw_speed = 3
|
||||
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1)
|
||||
var/obj/item/device/bug_monitor/linkedmonitor
|
||||
var/brokentype = /obj/item/brokenbug
|
||||
|
||||
// var/obj/item/device/radio/bug/radio
|
||||
var/obj/machinery/camera/bug/camera
|
||||
var/camtype = /obj/machinery/camera/bug
|
||||
|
||||
/obj/item/device/camerabug/New()
|
||||
..()
|
||||
// radio = new(src)
|
||||
camera = new camtype(src)
|
||||
|
||||
/obj/item/device/camerabug/attack_self(mob/user)
|
||||
if(user.a_intent == I_HURT)
|
||||
to_chat(user, "<span class='notice'>You crush the [src] under your foot, breaking it.</span>")
|
||||
visible_message("[user.name] crushes the [src] under their foot, breaking it!</span>")
|
||||
new brokentype(get_turf(src))
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
/* else
|
||||
user.set_machine(radio)
|
||||
radio.interact(user)
|
||||
*/
|
||||
/obj/item/device/camerabug/verb/reset()
|
||||
set name = "Reset camera bug"
|
||||
set category = "Object"
|
||||
if(linkedmonitor)
|
||||
linkedmonitor.unpair(src)
|
||||
linkedmonitor = null
|
||||
qdel(camera)
|
||||
camera = new camtype(src)
|
||||
to_chat(usr, "<span class='notice'>You turn the [src] off and on again, delinking it from any monitors.")
|
||||
|
||||
/obj/item/brokenbug
|
||||
name = "broken mobile camera pod"
|
||||
desc = "A camera pod formerly used by tactical operators. The lens is smashed, and the circuits are damaged beyond repair."
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "camgrenadebroken"
|
||||
item_state = "empgrenade"
|
||||
force = 5.0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throwforce = 5.0
|
||||
throw_range = 15
|
||||
throw_speed = 3
|
||||
origin_tech = list(TECH_ENGINEERING = 1)
|
||||
|
||||
/obj/item/brokenbug/spy
|
||||
name = "broken bug"
|
||||
desc = "" //Even when it's broken it's inconspicuous
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "eshield"
|
||||
item_state = "nothing"
|
||||
layer = TURF_LAYER+0.2
|
||||
w_class = ITEMSIZE_TINY
|
||||
slot_flags = SLOT_EARS
|
||||
origin_tech = list(TECH_ENGINEERING = 1, TECH_ILLEGAL = 3) //crush it and you lose the data
|
||||
force = 0
|
||||
throwforce = 5.0
|
||||
throw_range = 15
|
||||
throw_speed = 3
|
||||
|
||||
/obj/item/device/camerabug/spy
|
||||
name = "bug"
|
||||
desc = "" //Nothing to see here
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "eshield"
|
||||
item_state = "nothing"
|
||||
layer = TURF_LAYER+0.2
|
||||
w_class = ITEMSIZE_TINY
|
||||
slot_flags = SLOT_EARS
|
||||
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1, TECH_ILLEGAL = 3)
|
||||
camtype = /obj/machinery/camera/bug/spy
|
||||
|
||||
/obj/item/device/camerabug/examine(mob/user)
|
||||
. = ..()
|
||||
if(get_dist(user, src) == 0)
|
||||
. += "It has a tiny camera inside. Needs to be both configured and brought in contact with monitor device to be fully functional."
|
||||
|
||||
/obj/item/device/camerabug/update_icon()
|
||||
..()
|
||||
|
||||
if(anchored) // Standard versions are relatively obvious if not hidden in a container. Anchoring them is advised, to disguise them.
|
||||
alpha = 50
|
||||
else
|
||||
alpha = 255
|
||||
|
||||
/obj/item/device/camerabug/attackby(obj/item/W as obj, mob/living/user as mob)
|
||||
if(istype(W, /obj/item/device/bug_monitor))
|
||||
var/obj/item/device/bug_monitor/SM = W
|
||||
if(!linkedmonitor)
|
||||
to_chat(user, "<span class='notice'>\The [src] has been paired with \the [SM].</span>")
|
||||
SM.pair(src)
|
||||
linkedmonitor = SM
|
||||
else if (linkedmonitor == SM)
|
||||
to_chat(user, "<span class='notice'>\The [src] has been unpaired from \the [SM].</span>")
|
||||
linkedmonitor.unpair(src)
|
||||
linkedmonitor = null
|
||||
else
|
||||
to_chat(user, "Error: The device is linked to another monitor.")
|
||||
|
||||
else if(W.has_tool_quality(TOOL_WRENCH) && user.a_intent != I_HURT)
|
||||
if(isturf(loc))
|
||||
anchored = !anchored
|
||||
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "" : "un"]secure \the [src].</span>")
|
||||
|
||||
update_icon()
|
||||
return
|
||||
else
|
||||
if(W.force >= 5)
|
||||
visible_message("\The [src] lens shatters!")
|
||||
new brokentype(get_turf(src))
|
||||
if(linkedmonitor)
|
||||
linkedmonitor.unpair(src)
|
||||
linkedmonitor = null
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
..()
|
||||
|
||||
/obj/item/device/camerabug/bullet_act()
|
||||
visible_message("The [src] lens shatters!")
|
||||
new brokentype(get_turf(src))
|
||||
if(linkedmonitor)
|
||||
linkedmonitor.unpair(src)
|
||||
linkedmonitor = null
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/device/camerabug/Destroy()
|
||||
if(linkedmonitor)
|
||||
linkedmonitor.unpair(src)
|
||||
linkedmonitor = null
|
||||
..()
|
||||
|
||||
/obj/item/device/bug_monitor
|
||||
name = "mobile camera pod monitor"
|
||||
desc = "A portable camera console designed to work with mobile camera pods."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "forensic0"
|
||||
item_state = "electronic"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1)
|
||||
|
||||
var/operating = 0
|
||||
// var/obj/item/device/radio/bug/radio
|
||||
var/obj/machinery/camera/bug/selected_camera
|
||||
var/list/obj/machinery/camera/bug/cameras = new()
|
||||
/*
|
||||
/obj/item/device/bug_monitor/New()
|
||||
radio = new(src)
|
||||
*/
|
||||
/obj/item/device/bug_monitor/attack_self(mob/user)
|
||||
if(operating)
|
||||
return
|
||||
|
||||
// radio.attack_self(user)
|
||||
view_cameras(user)
|
||||
|
||||
/obj/item/device/bug_monitor/attackby(obj/item/W as obj, mob/living/user as mob)
|
||||
if(istype(W, /obj/item/device/camerabug))
|
||||
W.attackby(src, user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/device/bug_monitor/proc/unpair(var/obj/item/device/camerabug/SB)
|
||||
if(SB.camera in cameras)
|
||||
cameras -= SB.camera
|
||||
|
||||
/obj/item/device/bug_monitor/proc/pair(var/obj/item/device/camerabug/SB)
|
||||
cameras += SB.camera
|
||||
|
||||
/obj/item/device/bug_monitor/proc/view_cameras(mob/user)
|
||||
if(!can_use_cam(user))
|
||||
return
|
||||
|
||||
selected_camera = cameras[1]
|
||||
user.reset_view(selected_camera)
|
||||
view_camera(user)
|
||||
|
||||
operating = 1
|
||||
while(selected_camera && Adjacent(user))
|
||||
selected_camera = tgui_input_list(usr, "Select camera to view.", "Camera Choice", cameras)
|
||||
selected_camera = null
|
||||
operating = 0
|
||||
|
||||
/obj/item/device/bug_monitor/proc/view_camera(mob/user)
|
||||
spawn(0)
|
||||
while(selected_camera && Adjacent(user))
|
||||
var/turf/T = get_turf(selected_camera)
|
||||
if(!T || !is_on_same_plane_or_station(T.z, user.z) || !selected_camera.can_use())
|
||||
user.unset_machine()
|
||||
user.reset_view(null)
|
||||
to_chat(user, "<span class='notice'>Link to [selected_camera] has been lost.</span>")
|
||||
src.unpair(selected_camera.loc)
|
||||
sleep(90)
|
||||
else
|
||||
user.set_machine(selected_camera)
|
||||
user.reset_view(selected_camera)
|
||||
sleep(10)
|
||||
user.unset_machine()
|
||||
user.reset_view(null)
|
||||
|
||||
/obj/item/device/bug_monitor/proc/can_use_cam(mob/user)
|
||||
if(operating)
|
||||
return
|
||||
|
||||
if(!cameras.len)
|
||||
to_chat(user, "<span class='warning'>No paired cameras detected!</span>")
|
||||
to_chat(user, "<span class='warning'>Bring a camera in contact with this device to pair the camera.</span>")
|
||||
return
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/device/bug_monitor/spy
|
||||
name = "\improper PDA"
|
||||
desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge."
|
||||
icon = 'icons/obj/pda.dmi'
|
||||
icon_state = "pda"
|
||||
item_state = "electronic"
|
||||
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1, TECH_ILLEGAL = 3)
|
||||
|
||||
/obj/item/device/bug_monitor/spy/examine(mob/user)
|
||||
. = ..()
|
||||
if(Adjacent(user))
|
||||
. += "The time '12:00' is blinking in the corner of the screen and \the [src] looks very cheaply made."
|
||||
|
||||
/obj/machinery/camera/bug/check_eye(var/mob/user as mob)
|
||||
return 0
|
||||
|
||||
/obj/machinery/camera/bug
|
||||
network = list(NETWORK_SECURITY)
|
||||
|
||||
/obj/machinery/camera/bug/New()
|
||||
..()
|
||||
name = "Camera #[rand(1000,9999)]"
|
||||
c_tag = name
|
||||
|
||||
/obj/machinery/camera/bug/spy
|
||||
// These cheap toys are accessible from the mercenary camera console as well - only the antag ones though!
|
||||
network = list(NETWORK_MERCENARY)
|
||||
|
||||
/obj/machinery/camera/bug/spy/New()
|
||||
..()
|
||||
name = "DV-136ZB #[rand(1000,9999)]"
|
||||
c_tag = name
|
||||
|
||||
/* //These were originally supposed to have radios in them. Doesn't work.
|
||||
/obj/item/device/radio/bug
|
||||
listening = 0 //turn it on first
|
||||
frequency = 1359 //sec comms
|
||||
broadcasting = 0
|
||||
canhear_range = 1
|
||||
name = "camera bug device"
|
||||
icon_state = "syn_cypherkey"
|
||||
|
||||
/obj/item/device/radio/bug/spy
|
||||
listening = 0
|
||||
frequency = 1473
|
||||
broadcasting = 0
|
||||
canhear_range = 1
|
||||
name = "spy device"
|
||||
icon_state = "syn_cypherkey"
|
||||
/obj/item/device/camerabug
|
||||
name = "mobile camera pod"
|
||||
desc = "A camera pod used by tactical operators. Must be linked to a camera scanner unit."
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "camgrenade"
|
||||
item_state = "empgrenade"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
force = 0
|
||||
throwforce = 5.0
|
||||
throw_range = 15
|
||||
throw_speed = 3
|
||||
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1)
|
||||
var/obj/item/device/bug_monitor/linkedmonitor
|
||||
var/brokentype = /obj/item/brokenbug
|
||||
|
||||
// var/obj/item/device/radio/bug/radio
|
||||
var/obj/machinery/camera/bug/camera
|
||||
var/camtype = /obj/machinery/camera/bug
|
||||
|
||||
/obj/item/device/camerabug/New()
|
||||
..()
|
||||
// radio = new(src)
|
||||
camera = new camtype(src)
|
||||
|
||||
/obj/item/device/camerabug/attack_self(mob/user)
|
||||
if(user.a_intent == I_HURT)
|
||||
to_chat(user, "<span class='notice'>You crush the [src] under your foot, breaking it.</span>")
|
||||
visible_message("[user.name] crushes the [src] under their foot, breaking it!</span>")
|
||||
new brokentype(get_turf(src))
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
/* else
|
||||
user.set_machine(radio)
|
||||
radio.interact(user)
|
||||
*/
|
||||
/obj/item/device/camerabug/verb/reset()
|
||||
set name = "Reset camera bug"
|
||||
set category = "Object"
|
||||
if(linkedmonitor)
|
||||
linkedmonitor.unpair(src)
|
||||
linkedmonitor = null
|
||||
qdel(camera)
|
||||
camera = new camtype(src)
|
||||
to_chat(usr, "<span class='notice'>You turn the [src] off and on again, delinking it from any monitors.")
|
||||
|
||||
/obj/item/brokenbug
|
||||
name = "broken mobile camera pod"
|
||||
desc = "A camera pod formerly used by tactical operators. The lens is smashed, and the circuits are damaged beyond repair."
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "camgrenadebroken"
|
||||
item_state = "empgrenade"
|
||||
force = 5.0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throwforce = 5.0
|
||||
throw_range = 15
|
||||
throw_speed = 3
|
||||
origin_tech = list(TECH_ENGINEERING = 1)
|
||||
|
||||
/obj/item/brokenbug/spy
|
||||
name = "broken bug"
|
||||
desc = "" //Even when it's broken it's inconspicuous
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "eshield"
|
||||
item_state = "nothing"
|
||||
layer = TURF_LAYER+0.2
|
||||
w_class = ITEMSIZE_TINY
|
||||
slot_flags = SLOT_EARS
|
||||
origin_tech = list(TECH_ENGINEERING = 1, TECH_ILLEGAL = 3) //crush it and you lose the data
|
||||
force = 0
|
||||
throwforce = 5.0
|
||||
throw_range = 15
|
||||
throw_speed = 3
|
||||
|
||||
/obj/item/device/camerabug/spy
|
||||
name = "bug"
|
||||
desc = "" //Nothing to see here
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "eshield"
|
||||
item_state = "nothing"
|
||||
layer = TURF_LAYER+0.2
|
||||
w_class = ITEMSIZE_TINY
|
||||
slot_flags = SLOT_EARS
|
||||
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1, TECH_ILLEGAL = 3)
|
||||
camtype = /obj/machinery/camera/bug/spy
|
||||
|
||||
/obj/item/device/camerabug/examine(mob/user)
|
||||
. = ..()
|
||||
if(get_dist(user, src) == 0)
|
||||
. += "It has a tiny camera inside. Needs to be both configured and brought in contact with monitor device to be fully functional."
|
||||
|
||||
/obj/item/device/camerabug/update_icon()
|
||||
..()
|
||||
|
||||
if(anchored) // Standard versions are relatively obvious if not hidden in a container. Anchoring them is advised, to disguise them.
|
||||
alpha = 50
|
||||
else
|
||||
alpha = 255
|
||||
|
||||
/obj/item/device/camerabug/attackby(obj/item/W as obj, mob/living/user as mob)
|
||||
if(istype(W, /obj/item/device/bug_monitor))
|
||||
var/obj/item/device/bug_monitor/SM = W
|
||||
if(!linkedmonitor)
|
||||
to_chat(user, "<span class='notice'>\The [src] has been paired with \the [SM].</span>")
|
||||
SM.pair(src)
|
||||
linkedmonitor = SM
|
||||
else if (linkedmonitor == SM)
|
||||
to_chat(user, "<span class='notice'>\The [src] has been unpaired from \the [SM].</span>")
|
||||
linkedmonitor.unpair(src)
|
||||
linkedmonitor = null
|
||||
else
|
||||
to_chat(user, "Error: The device is linked to another monitor.")
|
||||
|
||||
else if(W.has_tool_quality(TOOL_WRENCH) && user.a_intent != I_HURT)
|
||||
if(isturf(loc))
|
||||
anchored = !anchored
|
||||
|
||||
to_chat(user, "<span class='notice'>You [anchored ? "" : "un"]secure \the [src].</span>")
|
||||
|
||||
update_icon()
|
||||
return
|
||||
else
|
||||
if(W.force >= 5)
|
||||
visible_message("\The [src] lens shatters!")
|
||||
new brokentype(get_turf(src))
|
||||
if(linkedmonitor)
|
||||
linkedmonitor.unpair(src)
|
||||
linkedmonitor = null
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
..()
|
||||
|
||||
/obj/item/device/camerabug/bullet_act()
|
||||
visible_message("The [src] lens shatters!")
|
||||
new brokentype(get_turf(src))
|
||||
if(linkedmonitor)
|
||||
linkedmonitor.unpair(src)
|
||||
linkedmonitor = null
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/device/camerabug/Destroy()
|
||||
if(linkedmonitor)
|
||||
linkedmonitor.unpair(src)
|
||||
linkedmonitor = null
|
||||
..()
|
||||
|
||||
/obj/item/device/bug_monitor
|
||||
name = "mobile camera pod monitor"
|
||||
desc = "A portable camera console designed to work with mobile camera pods."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "forensic0"
|
||||
item_state = "electronic"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1)
|
||||
|
||||
var/operating = 0
|
||||
// var/obj/item/device/radio/bug/radio
|
||||
var/obj/machinery/camera/bug/selected_camera
|
||||
var/list/obj/machinery/camera/bug/cameras = new()
|
||||
/*
|
||||
/obj/item/device/bug_monitor/New()
|
||||
radio = new(src)
|
||||
*/
|
||||
/obj/item/device/bug_monitor/attack_self(mob/user)
|
||||
if(operating)
|
||||
return
|
||||
|
||||
// radio.attack_self(user)
|
||||
view_cameras(user)
|
||||
|
||||
/obj/item/device/bug_monitor/attackby(obj/item/W as obj, mob/living/user as mob)
|
||||
if(istype(W, /obj/item/device/camerabug))
|
||||
W.attackby(src, user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/device/bug_monitor/proc/unpair(var/obj/item/device/camerabug/SB)
|
||||
if(SB.camera in cameras)
|
||||
cameras -= SB.camera
|
||||
|
||||
/obj/item/device/bug_monitor/proc/pair(var/obj/item/device/camerabug/SB)
|
||||
cameras += SB.camera
|
||||
|
||||
/obj/item/device/bug_monitor/proc/view_cameras(mob/user)
|
||||
if(!can_use_cam(user))
|
||||
return
|
||||
|
||||
selected_camera = cameras[1]
|
||||
user.reset_view(selected_camera)
|
||||
view_camera(user)
|
||||
|
||||
operating = 1
|
||||
while(selected_camera && Adjacent(user))
|
||||
selected_camera = tgui_input_list(usr, "Select camera to view.", "Camera Choice", cameras)
|
||||
selected_camera = null
|
||||
operating = 0
|
||||
|
||||
/obj/item/device/bug_monitor/proc/view_camera(mob/user)
|
||||
spawn(0)
|
||||
while(selected_camera && Adjacent(user))
|
||||
var/turf/T = get_turf(selected_camera)
|
||||
if(!T || !is_on_same_plane_or_station(T.z, user.z) || !selected_camera.can_use())
|
||||
user.unset_machine()
|
||||
user.reset_view(null)
|
||||
to_chat(user, "<span class='notice'>Link to [selected_camera] has been lost.</span>")
|
||||
src.unpair(selected_camera.loc)
|
||||
sleep(90)
|
||||
else
|
||||
user.set_machine(selected_camera)
|
||||
user.reset_view(selected_camera)
|
||||
sleep(10)
|
||||
user.unset_machine()
|
||||
user.reset_view(null)
|
||||
|
||||
/obj/item/device/bug_monitor/proc/can_use_cam(mob/user)
|
||||
if(operating)
|
||||
return
|
||||
|
||||
if(!cameras.len)
|
||||
to_chat(user, "<span class='warning'>No paired cameras detected!</span>")
|
||||
to_chat(user, "<span class='warning'>Bring a camera in contact with this device to pair the camera.</span>")
|
||||
return
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/device/bug_monitor/spy
|
||||
name = "\improper PDA"
|
||||
desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge."
|
||||
icon = 'icons/obj/pda.dmi'
|
||||
icon_state = "pda"
|
||||
item_state = "electronic"
|
||||
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1, TECH_ILLEGAL = 3)
|
||||
|
||||
/obj/item/device/bug_monitor/spy/examine(mob/user)
|
||||
. = ..()
|
||||
if(Adjacent(user))
|
||||
. += "The time '12:00' is blinking in the corner of the screen and \the [src] looks very cheaply made."
|
||||
|
||||
/obj/machinery/camera/bug/check_eye(var/mob/user as mob)
|
||||
return 0
|
||||
|
||||
/obj/machinery/camera/bug
|
||||
network = list(NETWORK_SECURITY)
|
||||
|
||||
/obj/machinery/camera/bug/New()
|
||||
..()
|
||||
name = "Camera #[rand(1000,9999)]"
|
||||
c_tag = name
|
||||
|
||||
/obj/machinery/camera/bug/spy
|
||||
// These cheap toys are accessible from the mercenary camera console as well - only the antag ones though!
|
||||
network = list(NETWORK_MERCENARY)
|
||||
|
||||
/obj/machinery/camera/bug/spy/New()
|
||||
..()
|
||||
name = "DV-136ZB #[rand(1000,9999)]"
|
||||
c_tag = name
|
||||
|
||||
/* //These were originally supposed to have radios in them. Doesn't work.
|
||||
/obj/item/device/radio/bug
|
||||
listening = 0 //turn it on first
|
||||
frequency = 1359 //sec comms
|
||||
broadcasting = 0
|
||||
canhear_range = 1
|
||||
name = "camera bug device"
|
||||
icon_state = "syn_cypherkey"
|
||||
|
||||
/obj/item/device/radio/bug/spy
|
||||
listening = 0
|
||||
frequency = 1473
|
||||
broadcasting = 0
|
||||
canhear_range = 1
|
||||
name = "spy device"
|
||||
icon_state = "syn_cypherkey"
|
||||
*/
|
||||
@@ -1,150 +1,150 @@
|
||||
#define OVERLAY_CACHE_LEN 50
|
||||
|
||||
/obj/item/device/t_scanner
|
||||
name = "\improper T-ray scanner"
|
||||
desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
|
||||
icon_state = "t-ray0"
|
||||
item_state = "t-ray"
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = ITEMSIZE_SMALL
|
||||
matter = list(MAT_STEEL = 150)
|
||||
origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1)
|
||||
|
||||
var/scan_range = 1
|
||||
|
||||
var/on = 0
|
||||
var/list/active_scanned = list() //assoc list of objects being scanned, mapped to their overlay
|
||||
var/client/user_client //since making sure overlays are properly added and removed is pretty important, so we track the current user explicitly
|
||||
var/flicker = 0
|
||||
|
||||
var/global/list/overlay_cache = list() //cache recent overlays
|
||||
|
||||
/obj/item/device/t_scanner/update_icon()
|
||||
icon_state = "t-ray[on]"
|
||||
|
||||
/obj/item/device/t_scanner/attack_self(mob/user)
|
||||
set_active(!on)
|
||||
|
||||
/obj/item/device/t_scanner/proc/set_active(var/active)
|
||||
on = active
|
||||
if(on)
|
||||
START_PROCESSING(SSobj, src)
|
||||
flicker = 0
|
||||
else
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
set_user_client(null)
|
||||
update_icon()
|
||||
|
||||
//If reset is set, then assume the client has none of our overlays, otherwise we only send new overlays.
|
||||
/obj/item/device/t_scanner/process()
|
||||
if(!on) return
|
||||
|
||||
//handle clients changing
|
||||
var/client/loc_client = null
|
||||
if(ismob(src.loc))
|
||||
var/mob/M = src.loc
|
||||
loc_client = M.client
|
||||
set_user_client(loc_client)
|
||||
|
||||
//no sense processing if no-one is going to see it.
|
||||
if(!user_client) return
|
||||
|
||||
//get all objects in scan range
|
||||
var/list/scanned = get_scanned_objects(scan_range)
|
||||
var/list/update_add = scanned - active_scanned
|
||||
var/list/update_remove = active_scanned - scanned
|
||||
|
||||
//Add new overlays
|
||||
for(var/obj/O in update_add)
|
||||
var/image/overlay = get_overlay(O)
|
||||
active_scanned[O] = overlay
|
||||
user_client.images += overlay
|
||||
|
||||
//Remove stale overlays
|
||||
for(var/obj/O in update_remove)
|
||||
user_client.images -= active_scanned[O]
|
||||
active_scanned -= O
|
||||
|
||||
//Flicker effect
|
||||
for(var/obj/O in active_scanned)
|
||||
var/image/overlay = active_scanned[O]
|
||||
if(flicker)
|
||||
overlay.alpha = 0
|
||||
else
|
||||
overlay.alpha = 128
|
||||
flicker = !flicker
|
||||
|
||||
//creates a new overlay for a scanned object
|
||||
/obj/item/device/t_scanner/proc/get_overlay(obj/scanned)
|
||||
//Use a cache so we don't create a whole bunch of new images just because someone's walking back and forth in a room.
|
||||
//Also means that images are reused if multiple people are using t-rays to look at the same objects.
|
||||
if(scanned in overlay_cache)
|
||||
. = overlay_cache[scanned]
|
||||
else
|
||||
var/image/I = image(loc = scanned, icon = scanned.icon, icon_state = scanned.icon_state, layer = HUD_LAYER)
|
||||
|
||||
//Pipes are special
|
||||
if(istype(scanned, /obj/machinery/atmospherics/pipe))
|
||||
var/obj/machinery/atmospherics/pipe/P = scanned
|
||||
I.color = P.pipe_color
|
||||
I.add_overlay(P.overlays)
|
||||
|
||||
I.alpha = 128
|
||||
I.mouse_opacity = 0
|
||||
. = I
|
||||
|
||||
// Add it to cache, cutting old entries if the list is too long
|
||||
overlay_cache[scanned] = .
|
||||
if(overlay_cache.len > OVERLAY_CACHE_LEN)
|
||||
overlay_cache.Cut(1, overlay_cache.len-OVERLAY_CACHE_LEN-1)
|
||||
|
||||
/obj/item/device/t_scanner/proc/get_scanned_objects(var/scan_dist)
|
||||
. = list()
|
||||
|
||||
var/turf/center = get_turf(src.loc)
|
||||
if(!center) return
|
||||
|
||||
for(var/turf/T in range(scan_range, center))
|
||||
if(!!T.is_plating())
|
||||
continue
|
||||
|
||||
for(var/obj/O in T.contents)
|
||||
if(O.level != 1)
|
||||
continue
|
||||
if(!O.invisibility)
|
||||
continue //if it's already visible don't need an overlay for it
|
||||
. += O
|
||||
|
||||
/obj/item/device/t_scanner/proc/set_user_client(var/client/new_client)
|
||||
if(new_client == user_client)
|
||||
return
|
||||
if(user_client)
|
||||
for(var/scanned in active_scanned)
|
||||
user_client.images -= active_scanned[scanned]
|
||||
if(new_client)
|
||||
for(var/scanned in active_scanned)
|
||||
new_client.images += active_scanned[scanned]
|
||||
else
|
||||
active_scanned.Cut()
|
||||
|
||||
user_client = new_client
|
||||
|
||||
/obj/item/device/t_scanner/dropped(mob/user)
|
||||
set_user_client(null)
|
||||
|
||||
/obj/item/device/t_scanner/upgraded
|
||||
name = "Upgraded T-ray Scanner"
|
||||
desc = "An upgraded version of the terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
|
||||
matter = list(MAT_STEEL = 500, PHORON = 150)
|
||||
origin_tech = list(TECH_MAGNET = 4, TECH_ENGINEERING = 5)
|
||||
scan_range = 3
|
||||
|
||||
/obj/item/device/t_scanner/advanced
|
||||
name = "Advanced T-ray Scanner"
|
||||
desc = "An advanced version of the terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
|
||||
matter = list(MAT_STEEL = 1500, PHORON = 200, SILVER = 250)
|
||||
origin_tech = list(TECH_MAGNET = 7, TECH_ENGINEERING = 7, TECH_MATERIAL = 6)
|
||||
scan_range = 7
|
||||
|
||||
|
||||
#define OVERLAY_CACHE_LEN 50
|
||||
|
||||
/obj/item/device/t_scanner
|
||||
name = "\improper T-ray scanner"
|
||||
desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
|
||||
icon_state = "t-ray0"
|
||||
item_state = "t-ray"
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = ITEMSIZE_SMALL
|
||||
matter = list(MAT_STEEL = 150)
|
||||
origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1)
|
||||
|
||||
var/scan_range = 1
|
||||
|
||||
var/on = 0
|
||||
var/list/active_scanned = list() //assoc list of objects being scanned, mapped to their overlay
|
||||
var/client/user_client //since making sure overlays are properly added and removed is pretty important, so we track the current user explicitly
|
||||
var/flicker = 0
|
||||
|
||||
var/global/list/overlay_cache = list() //cache recent overlays
|
||||
|
||||
/obj/item/device/t_scanner/update_icon()
|
||||
icon_state = "t-ray[on]"
|
||||
|
||||
/obj/item/device/t_scanner/attack_self(mob/user)
|
||||
set_active(!on)
|
||||
|
||||
/obj/item/device/t_scanner/proc/set_active(var/active)
|
||||
on = active
|
||||
if(on)
|
||||
START_PROCESSING(SSobj, src)
|
||||
flicker = 0
|
||||
else
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
set_user_client(null)
|
||||
update_icon()
|
||||
|
||||
//If reset is set, then assume the client has none of our overlays, otherwise we only send new overlays.
|
||||
/obj/item/device/t_scanner/process()
|
||||
if(!on) return
|
||||
|
||||
//handle clients changing
|
||||
var/client/loc_client = null
|
||||
if(ismob(src.loc))
|
||||
var/mob/M = src.loc
|
||||
loc_client = M.client
|
||||
set_user_client(loc_client)
|
||||
|
||||
//no sense processing if no-one is going to see it.
|
||||
if(!user_client) return
|
||||
|
||||
//get all objects in scan range
|
||||
var/list/scanned = get_scanned_objects(scan_range)
|
||||
var/list/update_add = scanned - active_scanned
|
||||
var/list/update_remove = active_scanned - scanned
|
||||
|
||||
//Add new overlays
|
||||
for(var/obj/O in update_add)
|
||||
var/image/overlay = get_overlay(O)
|
||||
active_scanned[O] = overlay
|
||||
user_client.images += overlay
|
||||
|
||||
//Remove stale overlays
|
||||
for(var/obj/O in update_remove)
|
||||
user_client.images -= active_scanned[O]
|
||||
active_scanned -= O
|
||||
|
||||
//Flicker effect
|
||||
for(var/obj/O in active_scanned)
|
||||
var/image/overlay = active_scanned[O]
|
||||
if(flicker)
|
||||
overlay.alpha = 0
|
||||
else
|
||||
overlay.alpha = 128
|
||||
flicker = !flicker
|
||||
|
||||
//creates a new overlay for a scanned object
|
||||
/obj/item/device/t_scanner/proc/get_overlay(obj/scanned)
|
||||
//Use a cache so we don't create a whole bunch of new images just because someone's walking back and forth in a room.
|
||||
//Also means that images are reused if multiple people are using t-rays to look at the same objects.
|
||||
if(scanned in overlay_cache)
|
||||
. = overlay_cache[scanned]
|
||||
else
|
||||
var/image/I = image(loc = scanned, icon = scanned.icon, icon_state = scanned.icon_state, layer = HUD_LAYER)
|
||||
|
||||
//Pipes are special
|
||||
if(istype(scanned, /obj/machinery/atmospherics/pipe))
|
||||
var/obj/machinery/atmospherics/pipe/P = scanned
|
||||
I.color = P.pipe_color
|
||||
I.add_overlay(P.overlays)
|
||||
|
||||
I.alpha = 128
|
||||
I.mouse_opacity = 0
|
||||
. = I
|
||||
|
||||
// Add it to cache, cutting old entries if the list is too long
|
||||
overlay_cache[scanned] = .
|
||||
if(overlay_cache.len > OVERLAY_CACHE_LEN)
|
||||
overlay_cache.Cut(1, overlay_cache.len-OVERLAY_CACHE_LEN-1)
|
||||
|
||||
/obj/item/device/t_scanner/proc/get_scanned_objects(var/scan_dist)
|
||||
. = list()
|
||||
|
||||
var/turf/center = get_turf(src.loc)
|
||||
if(!center) return
|
||||
|
||||
for(var/turf/T in range(scan_range, center))
|
||||
if(!!T.is_plating())
|
||||
continue
|
||||
|
||||
for(var/obj/O in T.contents)
|
||||
if(O.level != 1)
|
||||
continue
|
||||
if(!O.invisibility)
|
||||
continue //if it's already visible don't need an overlay for it
|
||||
. += O
|
||||
|
||||
/obj/item/device/t_scanner/proc/set_user_client(var/client/new_client)
|
||||
if(new_client == user_client)
|
||||
return
|
||||
if(user_client)
|
||||
for(var/scanned in active_scanned)
|
||||
user_client.images -= active_scanned[scanned]
|
||||
if(new_client)
|
||||
for(var/scanned in active_scanned)
|
||||
new_client.images += active_scanned[scanned]
|
||||
else
|
||||
active_scanned.Cut()
|
||||
|
||||
user_client = new_client
|
||||
|
||||
/obj/item/device/t_scanner/dropped(mob/user)
|
||||
set_user_client(null)
|
||||
|
||||
/obj/item/device/t_scanner/upgraded
|
||||
name = "Upgraded T-ray Scanner"
|
||||
desc = "An upgraded version of the terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
|
||||
matter = list(MAT_STEEL = 500, PHORON = 150)
|
||||
origin_tech = list(TECH_MAGNET = 4, TECH_ENGINEERING = 5)
|
||||
scan_range = 3
|
||||
|
||||
/obj/item/device/t_scanner/advanced
|
||||
name = "Advanced T-ray Scanner"
|
||||
desc = "An advanced version of the terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
|
||||
matter = list(MAT_STEEL = 1500, PHORON = 200, SILVER = 250)
|
||||
origin_tech = list(TECH_MAGNET = 7, TECH_ENGINEERING = 7, TECH_MATERIAL = 6)
|
||||
scan_range = 7
|
||||
|
||||
|
||||
#undef OVERLAY_CACHE_LEN
|
||||
@@ -1,436 +1,436 @@
|
||||
/obj/item/device/taperecorder
|
||||
name = "universal recorder"
|
||||
desc = "A device that can record to cassette tapes, and play them. It automatically translates the content in playback."
|
||||
icon_state = "taperecorder_empty"
|
||||
item_state = "analyzer"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
|
||||
matter = list(MAT_STEEL = 60,MAT_GLASS = 30)
|
||||
|
||||
var/emagged = 0.0
|
||||
var/recording = 0.0
|
||||
var/playing = 0.0
|
||||
var/playsleepseconds = 0.0
|
||||
var/obj/item/device/tape/mytape = /obj/item/device/tape/random
|
||||
var/canprint = 1
|
||||
slot_flags = SLOT_BELT
|
||||
throwforce = 2
|
||||
throw_speed = 4
|
||||
throw_range = 20
|
||||
|
||||
/obj/item/device/taperecorder/New()
|
||||
..()
|
||||
if(ispath(mytape))
|
||||
mytape = new mytape(src)
|
||||
update_icon()
|
||||
listening_objects += src
|
||||
|
||||
/obj/item/device/taperecorder/empty
|
||||
mytape = null
|
||||
|
||||
/obj/item/device/taperecorder/Destroy()
|
||||
listening_objects -= src
|
||||
if(mytape)
|
||||
qdel(mytape)
|
||||
mytape = null
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/device/tape))
|
||||
if(mytape)
|
||||
to_chat(user, "<span class='notice'>There's already a tape inside.</span>")
|
||||
return
|
||||
if(!user.unEquip(I))
|
||||
return
|
||||
I.forceMove(src)
|
||||
mytape = I
|
||||
to_chat(user, "<span class='notice'>You insert [I] into [src].</span>")
|
||||
update_icon()
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/fire_act()
|
||||
if(mytape)
|
||||
mytape.ruin() //Fires destroy the tape
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/attack_hand(mob/user)
|
||||
if(user.get_inactive_hand() == src)
|
||||
if(mytape)
|
||||
eject()
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/verb/eject()
|
||||
set name = "Eject Tape"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(!mytape)
|
||||
to_chat(usr, "<span class='notice'>There's no tape in \the [src].</span>")
|
||||
return
|
||||
if(emagged)
|
||||
to_chat(usr, "<span class='notice'>The tape seems to be stuck inside.</span>")
|
||||
return
|
||||
|
||||
if(playing || recording)
|
||||
stop()
|
||||
to_chat(usr, "<span class='notice'>You remove [mytape] from [src].</span>")
|
||||
usr.put_in_hands(mytape)
|
||||
mytape = null
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/hear_talk(mob/M, list/message_pieces, verb)
|
||||
var/msg = multilingual_to_message(message_pieces, requires_machine_understands = TRUE, with_capitalization = TRUE)
|
||||
var/voice = M.GetVoice() //Defined on living, returns name for normal mobs/
|
||||
if(mytape && recording)
|
||||
mytape.record_speech("[voice] [verb], \"[msg]\"")
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/see_emote(mob/M as mob, text, var/emote_type)
|
||||
if(emote_type != 2) //only hearable emotes
|
||||
return
|
||||
if(mytape && recording)
|
||||
mytape.record_speech("[strip_html_properly(text)]")
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/show_message(msg, type, alt, alt_type)
|
||||
var/recordedtext
|
||||
if (msg && type == 2) //must be hearable
|
||||
recordedtext = msg
|
||||
else if (alt && alt_type == 2)
|
||||
recordedtext = alt
|
||||
else
|
||||
return
|
||||
if(mytape && recording)
|
||||
mytape.record_noise("[strip_html_properly(recordedtext)]")
|
||||
|
||||
/obj/item/device/taperecorder/emag_act(var/remaining_charges, var/mob/user)
|
||||
if(emagged == 0)
|
||||
emagged = 1
|
||||
recording = 0
|
||||
to_chat(user, "<span class='warning'>PZZTTPFFFT</span>")
|
||||
update_icon()
|
||||
return 1
|
||||
else
|
||||
to_chat(user, "<span class='warning'>It is already emagged!</span>")
|
||||
|
||||
/obj/item/device/taperecorder/proc/explode()
|
||||
var/turf/T = get_turf(loc)
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
to_chat(M, "<span class='danger'>\The [src] explodes!</span>")
|
||||
if(T)
|
||||
T.hotspot_expose(700,125)
|
||||
explosion(T, -1, -1, 0, 4)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/device/taperecorder/verb/record()
|
||||
set name = "Start Recording"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(!mytape)
|
||||
to_chat(usr, "<span class='notice'>There's no tape!</span>")
|
||||
return
|
||||
if(mytape.ruined)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(recording)
|
||||
to_chat(usr, "<span class='notice'>You're already recording!</span>")
|
||||
return
|
||||
if(playing)
|
||||
to_chat(usr, "<span class='notice'>You can't record when playing!</span>")
|
||||
return
|
||||
if(emagged)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(mytape.used_capacity < mytape.max_capacity)
|
||||
to_chat(usr, "<span class='notice'>Recording started.</span>")
|
||||
recording = 1
|
||||
update_icon()
|
||||
|
||||
mytape.record_speech("Recording started.")
|
||||
|
||||
//count seconds until full, or recording is stopped
|
||||
while(mytape && recording && mytape.used_capacity < mytape.max_capacity)
|
||||
sleep(10)
|
||||
mytape.used_capacity++
|
||||
if(mytape.used_capacity >= mytape.max_capacity)
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
to_chat(M, "<span class='notice'>The tape is full.</span>")
|
||||
stop_recording()
|
||||
|
||||
|
||||
update_icon()
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>The tape is full.</span>")
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/proc/stop_recording()
|
||||
//Sanity checks skipped, should not be called unless actually recording
|
||||
recording = 0
|
||||
update_icon()
|
||||
mytape.record_speech("Recording stopped.")
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
to_chat(M, "<span class='notice'>Recording stopped.</span>")
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/verb/stop()
|
||||
set name = "Stop"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(recording)
|
||||
stop_recording()
|
||||
return
|
||||
else if(playing)
|
||||
playing = 0
|
||||
update_icon()
|
||||
to_chat(usr, "<span class='notice'>Playback stopped.</span>")
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>Stop what?</span>")
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/verb/wipe_tape()
|
||||
set name = "Wipe Tape"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(emagged)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(mytape.ruined)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(recording || playing)
|
||||
to_chat(usr, "<span class='notice'>You can't wipe the tape while playing or recording!</span>")
|
||||
return
|
||||
else
|
||||
if(mytape.storedinfo) mytape.storedinfo.Cut()
|
||||
if(mytape.timestamp) mytape.timestamp.Cut()
|
||||
mytape.used_capacity = 0
|
||||
to_chat(usr, "<span class='notice'>You wipe the tape.</span>")
|
||||
return
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/verb/playback_memory()
|
||||
set name = "Playback Tape"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(!mytape)
|
||||
to_chat(usr, "<span class='notice'>There's no tape!</span>")
|
||||
return
|
||||
if(mytape.ruined)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(recording)
|
||||
to_chat(usr, "<span class='notice'>You can't playback when recording!</span>")
|
||||
return
|
||||
if(playing)
|
||||
to_chat(usr, "<span class='notice'>You're already playing!</span>")
|
||||
return
|
||||
playing = 1
|
||||
update_icon()
|
||||
to_chat(usr, "<span class='notice'>Playing started.</span>")
|
||||
for(var/i=1 , i < mytape.max_capacity , i++)
|
||||
if(!mytape || !playing)
|
||||
break
|
||||
if(mytape.storedinfo.len < i)
|
||||
break
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
var/playedmessage = mytape.storedinfo[i]
|
||||
if (findtextEx(playedmessage,"*",1,2)) //remove marker for action sounds
|
||||
playedmessage = copytext(playedmessage,2)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: [playedmessage]"), runemessage = playedmessage)
|
||||
|
||||
if(mytape.storedinfo.len < i+1)
|
||||
playsleepseconds = 1
|
||||
sleep(10)
|
||||
T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: End of recording."), runemessage = "click")
|
||||
break
|
||||
else
|
||||
playsleepseconds = mytape.timestamp[i+1] - mytape.timestamp[i]
|
||||
|
||||
if(playsleepseconds > 14)
|
||||
sleep(10)
|
||||
T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: Skipping [playsleepseconds] seconds of silence"), runemessage = "tape winding")
|
||||
playsleepseconds = 1
|
||||
sleep(10 * playsleepseconds)
|
||||
|
||||
|
||||
playing = 0
|
||||
update_icon()
|
||||
|
||||
if(emagged)
|
||||
var/turf/T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: This tape recorder will self-destruct in... Five."), runemessage = "beep beep")
|
||||
sleep(10)
|
||||
T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: Four."))
|
||||
sleep(10)
|
||||
T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: Three."))
|
||||
sleep(10)
|
||||
T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: Two."))
|
||||
sleep(10)
|
||||
T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: One."))
|
||||
sleep(10)
|
||||
explode()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/verb/print_transcript()
|
||||
set name = "Print Transcript"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(!mytape)
|
||||
to_chat(usr, "<span class='notice'>There's no tape!</span>")
|
||||
return
|
||||
if(mytape.ruined)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(emagged)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(!canprint)
|
||||
to_chat(usr, "<span class='notice'>The recorder can't print that fast!</span>")
|
||||
return
|
||||
if(recording || playing)
|
||||
to_chat(usr, "<span class='notice'>You can't print the transcript while playing or recording!</span>")
|
||||
return
|
||||
|
||||
to_chat(usr, "<span class='notice'>Transcript printed.</span>")
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(src))
|
||||
var/t1 = "<B>Transcript:</B><BR><BR>"
|
||||
for(var/i=1,mytape.storedinfo.len >= i,i++)
|
||||
var/printedmessage = mytape.storedinfo[i]
|
||||
if (findtextEx(printedmessage,"*",1,2)) //replace action sounds
|
||||
printedmessage = "\[[time2text(mytape.timestamp[i]*10,"mm:ss")]\] (Unrecognized sound)"
|
||||
t1 += "[printedmessage]<BR>"
|
||||
P.info = t1
|
||||
P.name = "Transcript"
|
||||
canprint = 0
|
||||
sleep(300)
|
||||
canprint = 1
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/attack_self(mob/user)
|
||||
if(recording || playing)
|
||||
stop()
|
||||
else
|
||||
record()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/update_icon()
|
||||
if(!mytape)
|
||||
icon_state = "taperecorder_empty"
|
||||
else if(recording)
|
||||
icon_state = "taperecorder_recording"
|
||||
else if(playing)
|
||||
icon_state = "taperecorder_playing"
|
||||
else
|
||||
icon_state = "taperecorder_idle"
|
||||
|
||||
|
||||
|
||||
/obj/item/device/tape
|
||||
name = "tape"
|
||||
desc = "A magnetic tape that can hold up to ten minutes of content."
|
||||
icon_state = "tape_white"
|
||||
item_state = "analyzer"
|
||||
w_class = ITEMSIZE_TINY
|
||||
matter = list(MAT_STEEL=20, MAT_GLASS=5)
|
||||
force = 1
|
||||
throwforce = 0
|
||||
var/max_capacity = 1800
|
||||
var/used_capacity = 0
|
||||
var/list/storedinfo = new/list()
|
||||
var/list/timestamp = new/list()
|
||||
var/ruined = 0
|
||||
|
||||
|
||||
/obj/item/device/tape/update_icon()
|
||||
cut_overlays()
|
||||
if(ruined)
|
||||
add_overlay("ribbonoverlay")
|
||||
|
||||
|
||||
/obj/item/device/tape/fire_act()
|
||||
ruin()
|
||||
|
||||
/obj/item/device/tape/attack_self(mob/user)
|
||||
if(!ruined)
|
||||
to_chat(user, "<span class='notice'>You pull out all the tape!</span>")
|
||||
ruin()
|
||||
|
||||
|
||||
/obj/item/device/tape/proc/ruin()
|
||||
ruined = 1
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/item/device/tape/proc/fix()
|
||||
ruined = 0
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/item/device/tape/proc/record_speech(text)
|
||||
timestamp += used_capacity
|
||||
storedinfo += "\[[time2text(used_capacity*10,"mm:ss")]\] [text]"
|
||||
|
||||
|
||||
//shows up on the printed transcript as (Unrecognized sound)
|
||||
/obj/item/device/tape/proc/record_noise(text)
|
||||
timestamp += used_capacity
|
||||
storedinfo += "*\[[time2text(used_capacity*10,"mm:ss")]\] [text]"
|
||||
|
||||
|
||||
/obj/item/device/tape/attackby(obj/item/I, mob/user, params)
|
||||
if(ruined && I.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
to_chat(user, "<span class='notice'>You start winding the tape back in...</span>")
|
||||
playsound(src, I.usesound, 50, 1)
|
||||
if(do_after(user, 120 * I.toolspeed, target = src))
|
||||
to_chat(user, "<span class='notice'>You wound the tape back in.</span>")
|
||||
fix()
|
||||
return
|
||||
else if(istype(I, /obj/item/weapon/pen))
|
||||
if(loc == user && !user.incapacitated())
|
||||
var/new_name = tgui_input_text(user, "What would you like to label the tape?", "Tape labeling")
|
||||
if(isnull(new_name)) return
|
||||
new_name = sanitizeSafe(new_name)
|
||||
if(new_name)
|
||||
name = "tape - '[new_name]'"
|
||||
to_chat(user, "<span class='notice'>You label the tape '[new_name]'.</span>")
|
||||
else
|
||||
name = "tape"
|
||||
to_chat(user, "<span class='notice'>You scratch off the label.</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
//Random colour tapes
|
||||
/obj/item/device/tape/random/New()
|
||||
icon_state = "tape_[pick("white", "blue", "red", "yellow", "purple")]"
|
||||
/obj/item/device/taperecorder
|
||||
name = "universal recorder"
|
||||
desc = "A device that can record to cassette tapes, and play them. It automatically translates the content in playback."
|
||||
icon_state = "taperecorder_empty"
|
||||
item_state = "analyzer"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
|
||||
matter = list(MAT_STEEL = 60,MAT_GLASS = 30)
|
||||
|
||||
var/emagged = 0.0
|
||||
var/recording = 0.0
|
||||
var/playing = 0.0
|
||||
var/playsleepseconds = 0.0
|
||||
var/obj/item/device/tape/mytape = /obj/item/device/tape/random
|
||||
var/canprint = 1
|
||||
slot_flags = SLOT_BELT
|
||||
throwforce = 2
|
||||
throw_speed = 4
|
||||
throw_range = 20
|
||||
|
||||
/obj/item/device/taperecorder/New()
|
||||
..()
|
||||
if(ispath(mytape))
|
||||
mytape = new mytape(src)
|
||||
update_icon()
|
||||
listening_objects += src
|
||||
|
||||
/obj/item/device/taperecorder/empty
|
||||
mytape = null
|
||||
|
||||
/obj/item/device/taperecorder/Destroy()
|
||||
listening_objects -= src
|
||||
if(mytape)
|
||||
qdel(mytape)
|
||||
mytape = null
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/device/tape))
|
||||
if(mytape)
|
||||
to_chat(user, "<span class='notice'>There's already a tape inside.</span>")
|
||||
return
|
||||
if(!user.unEquip(I))
|
||||
return
|
||||
I.forceMove(src)
|
||||
mytape = I
|
||||
to_chat(user, "<span class='notice'>You insert [I] into [src].</span>")
|
||||
update_icon()
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/fire_act()
|
||||
if(mytape)
|
||||
mytape.ruin() //Fires destroy the tape
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/attack_hand(mob/user)
|
||||
if(user.get_inactive_hand() == src)
|
||||
if(mytape)
|
||||
eject()
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/verb/eject()
|
||||
set name = "Eject Tape"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(!mytape)
|
||||
to_chat(usr, "<span class='notice'>There's no tape in \the [src].</span>")
|
||||
return
|
||||
if(emagged)
|
||||
to_chat(usr, "<span class='notice'>The tape seems to be stuck inside.</span>")
|
||||
return
|
||||
|
||||
if(playing || recording)
|
||||
stop()
|
||||
to_chat(usr, "<span class='notice'>You remove [mytape] from [src].</span>")
|
||||
usr.put_in_hands(mytape)
|
||||
mytape = null
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/hear_talk(mob/M, list/message_pieces, verb)
|
||||
var/msg = multilingual_to_message(message_pieces, requires_machine_understands = TRUE, with_capitalization = TRUE)
|
||||
var/voice = M.GetVoice() //Defined on living, returns name for normal mobs/
|
||||
if(mytape && recording)
|
||||
mytape.record_speech("[voice] [verb], \"[msg]\"")
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/see_emote(mob/M as mob, text, var/emote_type)
|
||||
if(emote_type != 2) //only hearable emotes
|
||||
return
|
||||
if(mytape && recording)
|
||||
mytape.record_speech("[strip_html_properly(text)]")
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/show_message(msg, type, alt, alt_type)
|
||||
var/recordedtext
|
||||
if (msg && type == 2) //must be hearable
|
||||
recordedtext = msg
|
||||
else if (alt && alt_type == 2)
|
||||
recordedtext = alt
|
||||
else
|
||||
return
|
||||
if(mytape && recording)
|
||||
mytape.record_noise("[strip_html_properly(recordedtext)]")
|
||||
|
||||
/obj/item/device/taperecorder/emag_act(var/remaining_charges, var/mob/user)
|
||||
if(emagged == 0)
|
||||
emagged = 1
|
||||
recording = 0
|
||||
to_chat(user, "<span class='warning'>PZZTTPFFFT</span>")
|
||||
update_icon()
|
||||
return 1
|
||||
else
|
||||
to_chat(user, "<span class='warning'>It is already emagged!</span>")
|
||||
|
||||
/obj/item/device/taperecorder/proc/explode()
|
||||
var/turf/T = get_turf(loc)
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
to_chat(M, "<span class='danger'>\The [src] explodes!</span>")
|
||||
if(T)
|
||||
T.hotspot_expose(700,125)
|
||||
explosion(T, -1, -1, 0, 4)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/device/taperecorder/verb/record()
|
||||
set name = "Start Recording"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(!mytape)
|
||||
to_chat(usr, "<span class='notice'>There's no tape!</span>")
|
||||
return
|
||||
if(mytape.ruined)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(recording)
|
||||
to_chat(usr, "<span class='notice'>You're already recording!</span>")
|
||||
return
|
||||
if(playing)
|
||||
to_chat(usr, "<span class='notice'>You can't record when playing!</span>")
|
||||
return
|
||||
if(emagged)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(mytape.used_capacity < mytape.max_capacity)
|
||||
to_chat(usr, "<span class='notice'>Recording started.</span>")
|
||||
recording = 1
|
||||
update_icon()
|
||||
|
||||
mytape.record_speech("Recording started.")
|
||||
|
||||
//count seconds until full, or recording is stopped
|
||||
while(mytape && recording && mytape.used_capacity < mytape.max_capacity)
|
||||
sleep(10)
|
||||
mytape.used_capacity++
|
||||
if(mytape.used_capacity >= mytape.max_capacity)
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
to_chat(M, "<span class='notice'>The tape is full.</span>")
|
||||
stop_recording()
|
||||
|
||||
|
||||
update_icon()
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>The tape is full.</span>")
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/proc/stop_recording()
|
||||
//Sanity checks skipped, should not be called unless actually recording
|
||||
recording = 0
|
||||
update_icon()
|
||||
mytape.record_speech("Recording stopped.")
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
to_chat(M, "<span class='notice'>Recording stopped.</span>")
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/verb/stop()
|
||||
set name = "Stop"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(recording)
|
||||
stop_recording()
|
||||
return
|
||||
else if(playing)
|
||||
playing = 0
|
||||
update_icon()
|
||||
to_chat(usr, "<span class='notice'>Playback stopped.</span>")
|
||||
return
|
||||
else
|
||||
to_chat(usr, "<span class='notice'>Stop what?</span>")
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/verb/wipe_tape()
|
||||
set name = "Wipe Tape"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(emagged)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(mytape.ruined)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(recording || playing)
|
||||
to_chat(usr, "<span class='notice'>You can't wipe the tape while playing or recording!</span>")
|
||||
return
|
||||
else
|
||||
if(mytape.storedinfo) mytape.storedinfo.Cut()
|
||||
if(mytape.timestamp) mytape.timestamp.Cut()
|
||||
mytape.used_capacity = 0
|
||||
to_chat(usr, "<span class='notice'>You wipe the tape.</span>")
|
||||
return
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/verb/playback_memory()
|
||||
set name = "Playback Tape"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(!mytape)
|
||||
to_chat(usr, "<span class='notice'>There's no tape!</span>")
|
||||
return
|
||||
if(mytape.ruined)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(recording)
|
||||
to_chat(usr, "<span class='notice'>You can't playback when recording!</span>")
|
||||
return
|
||||
if(playing)
|
||||
to_chat(usr, "<span class='notice'>You're already playing!</span>")
|
||||
return
|
||||
playing = 1
|
||||
update_icon()
|
||||
to_chat(usr, "<span class='notice'>Playing started.</span>")
|
||||
for(var/i=1 , i < mytape.max_capacity , i++)
|
||||
if(!mytape || !playing)
|
||||
break
|
||||
if(mytape.storedinfo.len < i)
|
||||
break
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
var/playedmessage = mytape.storedinfo[i]
|
||||
if (findtextEx(playedmessage,"*",1,2)) //remove marker for action sounds
|
||||
playedmessage = copytext(playedmessage,2)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: [playedmessage]"), runemessage = playedmessage)
|
||||
|
||||
if(mytape.storedinfo.len < i+1)
|
||||
playsleepseconds = 1
|
||||
sleep(10)
|
||||
T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: End of recording."), runemessage = "click")
|
||||
break
|
||||
else
|
||||
playsleepseconds = mytape.timestamp[i+1] - mytape.timestamp[i]
|
||||
|
||||
if(playsleepseconds > 14)
|
||||
sleep(10)
|
||||
T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: Skipping [playsleepseconds] seconds of silence"), runemessage = "tape winding")
|
||||
playsleepseconds = 1
|
||||
sleep(10 * playsleepseconds)
|
||||
|
||||
|
||||
playing = 0
|
||||
update_icon()
|
||||
|
||||
if(emagged)
|
||||
var/turf/T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: This tape recorder will self-destruct in... Five."), runemessage = "beep beep")
|
||||
sleep(10)
|
||||
T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: Four."))
|
||||
sleep(10)
|
||||
T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: Three."))
|
||||
sleep(10)
|
||||
T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: Two."))
|
||||
sleep(10)
|
||||
T = get_turf(src)
|
||||
T.audible_message(span_maroon("<B>Tape Recorder</B>: One."))
|
||||
sleep(10)
|
||||
explode()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/verb/print_transcript()
|
||||
set name = "Print Transcript"
|
||||
set category = "Object"
|
||||
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(!mytape)
|
||||
to_chat(usr, "<span class='notice'>There's no tape!</span>")
|
||||
return
|
||||
if(mytape.ruined)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(emagged)
|
||||
to_chat(usr, "<span class='warning'>The tape recorder makes a scratchy noise.</span>")
|
||||
return
|
||||
if(!canprint)
|
||||
to_chat(usr, "<span class='notice'>The recorder can't print that fast!</span>")
|
||||
return
|
||||
if(recording || playing)
|
||||
to_chat(usr, "<span class='notice'>You can't print the transcript while playing or recording!</span>")
|
||||
return
|
||||
|
||||
to_chat(usr, "<span class='notice'>Transcript printed.</span>")
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(src))
|
||||
var/t1 = "<B>Transcript:</B><BR><BR>"
|
||||
for(var/i=1,mytape.storedinfo.len >= i,i++)
|
||||
var/printedmessage = mytape.storedinfo[i]
|
||||
if (findtextEx(printedmessage,"*",1,2)) //replace action sounds
|
||||
printedmessage = "\[[time2text(mytape.timestamp[i]*10,"mm:ss")]\] (Unrecognized sound)"
|
||||
t1 += "[printedmessage]<BR>"
|
||||
P.info = t1
|
||||
P.name = "Transcript"
|
||||
canprint = 0
|
||||
sleep(300)
|
||||
canprint = 1
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/attack_self(mob/user)
|
||||
if(recording || playing)
|
||||
stop()
|
||||
else
|
||||
record()
|
||||
|
||||
|
||||
/obj/item/device/taperecorder/update_icon()
|
||||
if(!mytape)
|
||||
icon_state = "taperecorder_empty"
|
||||
else if(recording)
|
||||
icon_state = "taperecorder_recording"
|
||||
else if(playing)
|
||||
icon_state = "taperecorder_playing"
|
||||
else
|
||||
icon_state = "taperecorder_idle"
|
||||
|
||||
|
||||
|
||||
/obj/item/device/tape
|
||||
name = "tape"
|
||||
desc = "A magnetic tape that can hold up to ten minutes of content."
|
||||
icon_state = "tape_white"
|
||||
item_state = "analyzer"
|
||||
w_class = ITEMSIZE_TINY
|
||||
matter = list(MAT_STEEL=20, MAT_GLASS=5)
|
||||
force = 1
|
||||
throwforce = 0
|
||||
var/max_capacity = 1800
|
||||
var/used_capacity = 0
|
||||
var/list/storedinfo = new/list()
|
||||
var/list/timestamp = new/list()
|
||||
var/ruined = 0
|
||||
|
||||
|
||||
/obj/item/device/tape/update_icon()
|
||||
cut_overlays()
|
||||
if(ruined)
|
||||
add_overlay("ribbonoverlay")
|
||||
|
||||
|
||||
/obj/item/device/tape/fire_act()
|
||||
ruin()
|
||||
|
||||
/obj/item/device/tape/attack_self(mob/user)
|
||||
if(!ruined)
|
||||
to_chat(user, "<span class='notice'>You pull out all the tape!</span>")
|
||||
ruin()
|
||||
|
||||
|
||||
/obj/item/device/tape/proc/ruin()
|
||||
ruined = 1
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/item/device/tape/proc/fix()
|
||||
ruined = 0
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/item/device/tape/proc/record_speech(text)
|
||||
timestamp += used_capacity
|
||||
storedinfo += "\[[time2text(used_capacity*10,"mm:ss")]\] [text]"
|
||||
|
||||
|
||||
//shows up on the printed transcript as (Unrecognized sound)
|
||||
/obj/item/device/tape/proc/record_noise(text)
|
||||
timestamp += used_capacity
|
||||
storedinfo += "*\[[time2text(used_capacity*10,"mm:ss")]\] [text]"
|
||||
|
||||
|
||||
/obj/item/device/tape/attackby(obj/item/I, mob/user, params)
|
||||
if(ruined && I.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
to_chat(user, "<span class='notice'>You start winding the tape back in...</span>")
|
||||
playsound(src, I.usesound, 50, 1)
|
||||
if(do_after(user, 120 * I.toolspeed, target = src))
|
||||
to_chat(user, "<span class='notice'>You wound the tape back in.</span>")
|
||||
fix()
|
||||
return
|
||||
else if(istype(I, /obj/item/weapon/pen))
|
||||
if(loc == user && !user.incapacitated())
|
||||
var/new_name = tgui_input_text(user, "What would you like to label the tape?", "Tape labeling")
|
||||
if(isnull(new_name)) return
|
||||
new_name = sanitizeSafe(new_name)
|
||||
if(new_name)
|
||||
name = "tape - '[new_name]'"
|
||||
to_chat(user, "<span class='notice'>You label the tape '[new_name]'.</span>")
|
||||
else
|
||||
name = "tape"
|
||||
to_chat(user, "<span class='notice'>You scratch off the label.</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
//Random colour tapes
|
||||
/obj/item/device/tape/random/New()
|
||||
icon_state = "tape_[pick("white", "blue", "red", "yellow", "purple")]"
|
||||
|
||||
@@ -1,218 +1,218 @@
|
||||
/obj/item/device/transfer_valve
|
||||
name = "tank transfer valve"
|
||||
desc = "Regulates the transfer of air between two tanks"
|
||||
icon = 'icons/obj/assemblies.dmi'
|
||||
icon_state = "valve_1"
|
||||
var/obj/item/weapon/tank/tank_one
|
||||
var/obj/item/weapon/tank/tank_two
|
||||
var/obj/item/device/assembly/attached_device
|
||||
var/mob/attacher = null
|
||||
var/valve_open = 0
|
||||
var/toggle = 1
|
||||
|
||||
/obj/item/device/transfer_valve/attackby(obj/item/item, mob/user)
|
||||
var/turf/location = get_turf(src) // For admin logs
|
||||
if(istype(item, /obj/item/weapon/tank))
|
||||
if(tank_one && tank_two)
|
||||
to_chat(user, "<span class='warning'>There are already two tanks attached, remove one first.</span>")
|
||||
return
|
||||
|
||||
if(!tank_one)
|
||||
tank_one = item
|
||||
user.drop_item()
|
||||
item.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You attach the tank to the transfer valve.</span>")
|
||||
else if(!tank_two)
|
||||
tank_two = item
|
||||
user.drop_item()
|
||||
item.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You attach the tank to the transfer valve.</span>")
|
||||
message_admins("[key_name_admin(user)] attached both tanks to a transfer valve. [ADMIN_JMP(location)]")
|
||||
log_game("[key_name_admin(user)] attached both tanks to a transfer valve.")
|
||||
|
||||
update_icon()
|
||||
SStgui.update_uis(src) // update all UIs attached to src
|
||||
//TODO: Have this take an assemblyholder
|
||||
else if(isassembly(item))
|
||||
var/obj/item/device/assembly/A = item
|
||||
if(A.secured)
|
||||
to_chat(user, "<span class='notice'>The device is secured.</span>")
|
||||
return
|
||||
if(attached_device)
|
||||
to_chat(user, "<span class='warning'>There is already an device attached to the valve, remove it first.</span>")
|
||||
return
|
||||
user.remove_from_mob(item)
|
||||
attached_device = A
|
||||
A.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You attach the [item] to the valve controls and secure it.</span>")
|
||||
A.holder = src
|
||||
A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb).
|
||||
|
||||
bombers += "[key_name(user)] attached a [item] to a transfer valve."
|
||||
message_admins("[key_name_admin(user)] attached a [item] to a transfer valve. [ADMIN_JMP(location)]")
|
||||
log_game("[key_name_admin(user)] attached a [item] to a transfer valve.")
|
||||
attacher = user
|
||||
SStgui.update_uis(src) // update all UIs attached to src
|
||||
return
|
||||
|
||||
|
||||
/obj/item/device/transfer_valve/HasProximity(turf/T, atom/movable/AM, old_loc)
|
||||
attached_device?.HasProximity(T, AM, old_loc)
|
||||
|
||||
/obj/item/device/transfer_valve/Moved(old_loc, direction, forced)
|
||||
. = ..()
|
||||
if(isturf(old_loc))
|
||||
unsense_proximity(callback = /atom/proc/HasProximity, center = old_loc)
|
||||
if(isturf(loc))
|
||||
sense_proximity(callback = /atom/proc/HasProximity)
|
||||
|
||||
/obj/item/device/transfer_valve/attack_self(mob/user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/item/device/transfer_valve/tgui_state(mob/user)
|
||||
return GLOB.tgui_inventory_state
|
||||
|
||||
/obj/item/device/transfer_valve/tgui_interact(mob/user, datum/tgui/ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "TransferValve", name) // 460, 320
|
||||
ui.open()
|
||||
|
||||
/obj/item/device/transfer_valve/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["tank_one"] = tank_one ? tank_one.name : null
|
||||
data["tank_two"] = tank_two ? tank_two.name : null
|
||||
data["attached_device"] = attached_device ? attached_device.name : null
|
||||
data["valve"] = valve_open
|
||||
return data
|
||||
|
||||
/obj/item/device/transfer_valve/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("tankone")
|
||||
remove_tank(tank_one)
|
||||
if("tanktwo")
|
||||
remove_tank(tank_two)
|
||||
if("toggle")
|
||||
toggle_valve()
|
||||
if("device")
|
||||
if(attached_device)
|
||||
attached_device.attack_self(usr)
|
||||
if("remove_device")
|
||||
if(attached_device)
|
||||
attached_device.forceMove(get_turf(src))
|
||||
attached_device.holder = null
|
||||
attached_device = null
|
||||
update_icon()
|
||||
else
|
||||
. = FALSE
|
||||
if(.)
|
||||
update_icon()
|
||||
add_fingerprint(usr)
|
||||
|
||||
/obj/item/device/transfer_valve/proc/process_activation(var/obj/item/device/D)
|
||||
if(toggle)
|
||||
toggle = FALSE
|
||||
toggle_valve()
|
||||
VARSET_IN(src, toggle, TRUE, 5 SECONDS)
|
||||
|
||||
/obj/item/device/transfer_valve/update_icon()
|
||||
cut_overlays()
|
||||
underlays = null
|
||||
|
||||
if(!tank_one && !tank_two && !attached_device)
|
||||
icon_state = "valve_1"
|
||||
return
|
||||
icon_state = "valve"
|
||||
|
||||
if(tank_one)
|
||||
add_overlay("[tank_one.icon_state]")
|
||||
if(tank_two)
|
||||
var/icon/J = new(icon, icon_state = "[tank_two.icon_state]")
|
||||
J.Shift(WEST, 13)
|
||||
underlays += J
|
||||
if(attached_device)
|
||||
add_overlay("device")
|
||||
|
||||
/obj/item/device/transfer_valve/proc/remove_tank(obj/item/weapon/tank/T)
|
||||
if(tank_one == T)
|
||||
split_gases()
|
||||
tank_one = null
|
||||
else if(tank_two == T)
|
||||
split_gases()
|
||||
tank_two = null
|
||||
else
|
||||
return
|
||||
|
||||
T.forceMove(get_turf(src))
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/transfer_valve/proc/merge_gases()
|
||||
if(valve_open)
|
||||
return
|
||||
tank_two.air_contents.volume += tank_one.air_contents.volume
|
||||
var/datum/gas_mixture/temp
|
||||
temp = tank_one.air_contents.remove_ratio(1)
|
||||
tank_two.air_contents.merge(temp)
|
||||
valve_open = 1
|
||||
|
||||
/obj/item/device/transfer_valve/proc/split_gases()
|
||||
if(!valve_open)
|
||||
return
|
||||
|
||||
valve_open = 0
|
||||
|
||||
if(QDELETED(tank_one) || QDELETED(tank_two))
|
||||
return
|
||||
|
||||
var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume
|
||||
var/datum/gas_mixture/temp
|
||||
temp = tank_two.air_contents.remove_ratio(ratio1)
|
||||
tank_one.air_contents.merge(temp)
|
||||
tank_two.air_contents.volume -= tank_one.air_contents.volume
|
||||
|
||||
|
||||
/*
|
||||
Exadv1: I know this isn't how it's going to work, but this was just to check
|
||||
it explodes properly when it gets a signal (and it does).
|
||||
*/
|
||||
|
||||
/obj/item/device/transfer_valve/proc/toggle_valve()
|
||||
if(!valve_open && (tank_one && tank_two))
|
||||
var/turf/bombturf = get_turf(src)
|
||||
var/area/A = get_area(bombturf)
|
||||
|
||||
var/attacher_name = ""
|
||||
if(!attacher)
|
||||
attacher_name = "Unknown"
|
||||
else
|
||||
attacher_name = "[attacher.name]([attacher.ckey])"
|
||||
|
||||
var/log_str = "Bomb valve opened in <A HREF='?_src_=holder;[HrefToken(TRUE)];adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name]</a> "
|
||||
log_str += "with [attached_device ? attached_device : "no device"] attacher: [attacher_name]"
|
||||
|
||||
if(attacher)
|
||||
log_str += ADMIN_QUE(attacher)
|
||||
|
||||
var/mob/mob = get_mob_by_key(src.fingerprintslast)
|
||||
var/last_touch_info = ""
|
||||
if(mob)
|
||||
last_touch_info = ADMIN_QUE(mob)
|
||||
|
||||
log_str += " Last touched by: [src.fingerprintslast][last_touch_info]"
|
||||
bombers += log_str
|
||||
message_admins(log_str, 0, 1)
|
||||
log_game(log_str)
|
||||
merge_gases()
|
||||
|
||||
else if(valve_open==1 && (tank_one && tank_two))
|
||||
split_gases()
|
||||
|
||||
src.update_icon()
|
||||
|
||||
// this doesn't do anything but the timer etc. expects it to be here
|
||||
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
|
||||
/obj/item/device/transfer_valve/proc/c_state()
|
||||
return
|
||||
/obj/item/device/transfer_valve
|
||||
name = "tank transfer valve"
|
||||
desc = "Regulates the transfer of air between two tanks"
|
||||
icon = 'icons/obj/assemblies.dmi'
|
||||
icon_state = "valve_1"
|
||||
var/obj/item/weapon/tank/tank_one
|
||||
var/obj/item/weapon/tank/tank_two
|
||||
var/obj/item/device/assembly/attached_device
|
||||
var/mob/attacher = null
|
||||
var/valve_open = 0
|
||||
var/toggle = 1
|
||||
|
||||
/obj/item/device/transfer_valve/attackby(obj/item/item, mob/user)
|
||||
var/turf/location = get_turf(src) // For admin logs
|
||||
if(istype(item, /obj/item/weapon/tank))
|
||||
if(tank_one && tank_two)
|
||||
to_chat(user, "<span class='warning'>There are already two tanks attached, remove one first.</span>")
|
||||
return
|
||||
|
||||
if(!tank_one)
|
||||
tank_one = item
|
||||
user.drop_item()
|
||||
item.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You attach the tank to the transfer valve.</span>")
|
||||
else if(!tank_two)
|
||||
tank_two = item
|
||||
user.drop_item()
|
||||
item.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You attach the tank to the transfer valve.</span>")
|
||||
message_admins("[key_name_admin(user)] attached both tanks to a transfer valve. [ADMIN_JMP(location)]")
|
||||
log_game("[key_name_admin(user)] attached both tanks to a transfer valve.")
|
||||
|
||||
update_icon()
|
||||
SStgui.update_uis(src) // update all UIs attached to src
|
||||
//TODO: Have this take an assemblyholder
|
||||
else if(isassembly(item))
|
||||
var/obj/item/device/assembly/A = item
|
||||
if(A.secured)
|
||||
to_chat(user, "<span class='notice'>The device is secured.</span>")
|
||||
return
|
||||
if(attached_device)
|
||||
to_chat(user, "<span class='warning'>There is already an device attached to the valve, remove it first.</span>")
|
||||
return
|
||||
user.remove_from_mob(item)
|
||||
attached_device = A
|
||||
A.forceMove(src)
|
||||
to_chat(user, "<span class='notice'>You attach the [item] to the valve controls and secure it.</span>")
|
||||
A.holder = src
|
||||
A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb).
|
||||
|
||||
bombers += "[key_name(user)] attached a [item] to a transfer valve."
|
||||
message_admins("[key_name_admin(user)] attached a [item] to a transfer valve. [ADMIN_JMP(location)]")
|
||||
log_game("[key_name_admin(user)] attached a [item] to a transfer valve.")
|
||||
attacher = user
|
||||
SStgui.update_uis(src) // update all UIs attached to src
|
||||
return
|
||||
|
||||
|
||||
/obj/item/device/transfer_valve/HasProximity(turf/T, atom/movable/AM, old_loc)
|
||||
attached_device?.HasProximity(T, AM, old_loc)
|
||||
|
||||
/obj/item/device/transfer_valve/Moved(old_loc, direction, forced)
|
||||
. = ..()
|
||||
if(isturf(old_loc))
|
||||
unsense_proximity(callback = /atom/proc/HasProximity, center = old_loc)
|
||||
if(isturf(loc))
|
||||
sense_proximity(callback = /atom/proc/HasProximity)
|
||||
|
||||
/obj/item/device/transfer_valve/attack_self(mob/user)
|
||||
tgui_interact(user)
|
||||
|
||||
/obj/item/device/transfer_valve/tgui_state(mob/user)
|
||||
return GLOB.tgui_inventory_state
|
||||
|
||||
/obj/item/device/transfer_valve/tgui_interact(mob/user, datum/tgui/ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "TransferValve", name) // 460, 320
|
||||
ui.open()
|
||||
|
||||
/obj/item/device/transfer_valve/tgui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["tank_one"] = tank_one ? tank_one.name : null
|
||||
data["tank_two"] = tank_two ? tank_two.name : null
|
||||
data["attached_device"] = attached_device ? attached_device.name : null
|
||||
data["valve"] = valve_open
|
||||
return data
|
||||
|
||||
/obj/item/device/transfer_valve/tgui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("tankone")
|
||||
remove_tank(tank_one)
|
||||
if("tanktwo")
|
||||
remove_tank(tank_two)
|
||||
if("toggle")
|
||||
toggle_valve()
|
||||
if("device")
|
||||
if(attached_device)
|
||||
attached_device.attack_self(usr)
|
||||
if("remove_device")
|
||||
if(attached_device)
|
||||
attached_device.forceMove(get_turf(src))
|
||||
attached_device.holder = null
|
||||
attached_device = null
|
||||
update_icon()
|
||||
else
|
||||
. = FALSE
|
||||
if(.)
|
||||
update_icon()
|
||||
add_fingerprint(usr)
|
||||
|
||||
/obj/item/device/transfer_valve/proc/process_activation(var/obj/item/device/D)
|
||||
if(toggle)
|
||||
toggle = FALSE
|
||||
toggle_valve()
|
||||
VARSET_IN(src, toggle, TRUE, 5 SECONDS)
|
||||
|
||||
/obj/item/device/transfer_valve/update_icon()
|
||||
cut_overlays()
|
||||
underlays = null
|
||||
|
||||
if(!tank_one && !tank_two && !attached_device)
|
||||
icon_state = "valve_1"
|
||||
return
|
||||
icon_state = "valve"
|
||||
|
||||
if(tank_one)
|
||||
add_overlay("[tank_one.icon_state]")
|
||||
if(tank_two)
|
||||
var/icon/J = new(icon, icon_state = "[tank_two.icon_state]")
|
||||
J.Shift(WEST, 13)
|
||||
underlays += J
|
||||
if(attached_device)
|
||||
add_overlay("device")
|
||||
|
||||
/obj/item/device/transfer_valve/proc/remove_tank(obj/item/weapon/tank/T)
|
||||
if(tank_one == T)
|
||||
split_gases()
|
||||
tank_one = null
|
||||
else if(tank_two == T)
|
||||
split_gases()
|
||||
tank_two = null
|
||||
else
|
||||
return
|
||||
|
||||
T.forceMove(get_turf(src))
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/transfer_valve/proc/merge_gases()
|
||||
if(valve_open)
|
||||
return
|
||||
tank_two.air_contents.volume += tank_one.air_contents.volume
|
||||
var/datum/gas_mixture/temp
|
||||
temp = tank_one.air_contents.remove_ratio(1)
|
||||
tank_two.air_contents.merge(temp)
|
||||
valve_open = 1
|
||||
|
||||
/obj/item/device/transfer_valve/proc/split_gases()
|
||||
if(!valve_open)
|
||||
return
|
||||
|
||||
valve_open = 0
|
||||
|
||||
if(QDELETED(tank_one) || QDELETED(tank_two))
|
||||
return
|
||||
|
||||
var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume
|
||||
var/datum/gas_mixture/temp
|
||||
temp = tank_two.air_contents.remove_ratio(ratio1)
|
||||
tank_one.air_contents.merge(temp)
|
||||
tank_two.air_contents.volume -= tank_one.air_contents.volume
|
||||
|
||||
|
||||
/*
|
||||
Exadv1: I know this isn't how it's going to work, but this was just to check
|
||||
it explodes properly when it gets a signal (and it does).
|
||||
*/
|
||||
|
||||
/obj/item/device/transfer_valve/proc/toggle_valve()
|
||||
if(!valve_open && (tank_one && tank_two))
|
||||
var/turf/bombturf = get_turf(src)
|
||||
var/area/A = get_area(bombturf)
|
||||
|
||||
var/attacher_name = ""
|
||||
if(!attacher)
|
||||
attacher_name = "Unknown"
|
||||
else
|
||||
attacher_name = "[attacher.name]([attacher.ckey])"
|
||||
|
||||
var/log_str = "Bomb valve opened in <A HREF='?_src_=holder;[HrefToken(TRUE)];adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name]</a> "
|
||||
log_str += "with [attached_device ? attached_device : "no device"] attacher: [attacher_name]"
|
||||
|
||||
if(attacher)
|
||||
log_str += ADMIN_QUE(attacher)
|
||||
|
||||
var/mob/mob = get_mob_by_key(src.fingerprintslast)
|
||||
var/last_touch_info = ""
|
||||
if(mob)
|
||||
last_touch_info = ADMIN_QUE(mob)
|
||||
|
||||
log_str += " Last touched by: [src.fingerprintslast][last_touch_info]"
|
||||
bombers += log_str
|
||||
message_admins(log_str, 0, 1)
|
||||
log_game(log_str)
|
||||
merge_gases()
|
||||
|
||||
else if(valve_open==1 && (tank_one && tank_two))
|
||||
split_gases()
|
||||
|
||||
src.update_icon()
|
||||
|
||||
// this doesn't do anything but the timer etc. expects it to be here
|
||||
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
|
||||
/obj/item/device/transfer_valve/proc/c_state()
|
||||
return
|
||||
|
||||
@@ -1,118 +1,118 @@
|
||||
var/datum/uplink_random_selection/default_uplink_selection = new/datum/uplink_random_selection/default()
|
||||
var/datum/uplink_random_selection/all_uplink_selection = new/datum/uplink_random_selection/all()
|
||||
|
||||
/datum/uplink_random_item
|
||||
var/uplink_item // The uplink item
|
||||
var/keep_probability // The probability we'll decide to keep this item if selected
|
||||
var/reselect_probability // Probability that we'll decide to keep this item if previously selected.
|
||||
// Is done together with the keep_probability check. Being selected more than once does not affect this probability.
|
||||
|
||||
/datum/uplink_random_item/New(var/uplink_item, var/keep_probability = 100, var/reselect_propbability = 33)
|
||||
..()
|
||||
src.uplink_item = uplink_item
|
||||
src.keep_probability = keep_probability
|
||||
src.reselect_probability = reselect_probability
|
||||
|
||||
/datum/uplink_random_selection
|
||||
var/list/datum/uplink_random_item/items
|
||||
var/list/datum/uplink_random_item/all_items
|
||||
|
||||
/datum/uplink_random_selection/New()
|
||||
..()
|
||||
items = list()
|
||||
all_items = list()
|
||||
|
||||
/datum/uplink_random_selection/proc/get_random_item(var/telecrystals, obj/item/device/uplink/U, var/list/bought_items, var/items_override = 0)
|
||||
var/const/attempts = 50
|
||||
|
||||
for(var/i = 0; i < attempts; i++)
|
||||
var/datum/uplink_random_item/RI
|
||||
if(items_override)
|
||||
RI = pick(all_items)
|
||||
else
|
||||
RI = pick(items)
|
||||
if(!prob(RI.keep_probability))
|
||||
continue
|
||||
var/datum/uplink_item/I = uplink.items_assoc[RI.uplink_item]
|
||||
if(I.cost(U) > telecrystals)
|
||||
continue
|
||||
if(bought_items && (I in bought_items) && !prob(RI.reselect_probability))
|
||||
continue
|
||||
if(U && !I.can_buy(U, telecrystals))
|
||||
continue
|
||||
return I
|
||||
|
||||
/datum/uplink_random_selection/all/New()
|
||||
..()
|
||||
for(var/datum/uplink_item/item in uplink.items)
|
||||
if(item.blacklisted)
|
||||
continue
|
||||
else
|
||||
all_items += new/datum/uplink_random_item(item.type)
|
||||
|
||||
/datum/uplink_random_selection/default/New()
|
||||
..()
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/silenced_45)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/ammo/mc9mm)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/revolver)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/ammo/a357)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/heavysnipermerc, 15, 0)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/ammo/sniperammo, 15, 0)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/grenades/emp, 50)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/crossbow, 33)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/energy_sword, 75)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/soap, 5, 100)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/concealed_cane, 50, 10)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/detomatix, 20, 10)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/parapen)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/cigarette_kit)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/id)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/spy)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/chameleon_kit)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/chameleon_projector)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/voice)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/armor/heavy_vest)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/armor/combat)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/toolbox, reselect_propbability = 10)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/plastique)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/encryptionkey_radio)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/encryptionkey_binary)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/emag, 100, 50)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/clerical)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/space_suit, 50, 10)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/thermal)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/powersink, 10, 10)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/ai_module, 25, 0)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/teleporter, 10, 0)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_freedom)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_compress)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_explosive)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/medical/sinpockets, reselect_propbability = 20)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/medical/surgery, reselect_propbability = 10)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/medical/combat, reselect_propbability = 10)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/thermal, reselect_propbability = 15)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/energy_net, reselect_propbability = 15)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/ewar_voice, reselect_propbability = 15)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/maneuvering_jets, reselect_propbability = 15)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/egun, reselect_propbability = 15)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/power_sink, reselect_propbability = 15)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/laser_canon, reselect_propbability = 5)
|
||||
|
||||
#ifdef DEBUG
|
||||
/proc/debug_uplink_purchage_log()
|
||||
for(var/antag_type in all_antag_types)
|
||||
var/datum/antagonist/A = all_antag_types[antag_type]
|
||||
A.print_player_summary()
|
||||
|
||||
/proc/debug_uplink_item_assoc_list()
|
||||
for(var/key in uplink.items_assoc)
|
||||
to_world("[key] - [uplink.items_assoc[key]]")
|
||||
#endif
|
||||
var/datum/uplink_random_selection/default_uplink_selection = new/datum/uplink_random_selection/default()
|
||||
var/datum/uplink_random_selection/all_uplink_selection = new/datum/uplink_random_selection/all()
|
||||
|
||||
/datum/uplink_random_item
|
||||
var/uplink_item // The uplink item
|
||||
var/keep_probability // The probability we'll decide to keep this item if selected
|
||||
var/reselect_probability // Probability that we'll decide to keep this item if previously selected.
|
||||
// Is done together with the keep_probability check. Being selected more than once does not affect this probability.
|
||||
|
||||
/datum/uplink_random_item/New(var/uplink_item, var/keep_probability = 100, var/reselect_propbability = 33)
|
||||
..()
|
||||
src.uplink_item = uplink_item
|
||||
src.keep_probability = keep_probability
|
||||
src.reselect_probability = reselect_probability
|
||||
|
||||
/datum/uplink_random_selection
|
||||
var/list/datum/uplink_random_item/items
|
||||
var/list/datum/uplink_random_item/all_items
|
||||
|
||||
/datum/uplink_random_selection/New()
|
||||
..()
|
||||
items = list()
|
||||
all_items = list()
|
||||
|
||||
/datum/uplink_random_selection/proc/get_random_item(var/telecrystals, obj/item/device/uplink/U, var/list/bought_items, var/items_override = 0)
|
||||
var/const/attempts = 50
|
||||
|
||||
for(var/i = 0; i < attempts; i++)
|
||||
var/datum/uplink_random_item/RI
|
||||
if(items_override)
|
||||
RI = pick(all_items)
|
||||
else
|
||||
RI = pick(items)
|
||||
if(!prob(RI.keep_probability))
|
||||
continue
|
||||
var/datum/uplink_item/I = uplink.items_assoc[RI.uplink_item]
|
||||
if(I.cost(U) > telecrystals)
|
||||
continue
|
||||
if(bought_items && (I in bought_items) && !prob(RI.reselect_probability))
|
||||
continue
|
||||
if(U && !I.can_buy(U, telecrystals))
|
||||
continue
|
||||
return I
|
||||
|
||||
/datum/uplink_random_selection/all/New()
|
||||
..()
|
||||
for(var/datum/uplink_item/item in uplink.items)
|
||||
if(item.blacklisted)
|
||||
continue
|
||||
else
|
||||
all_items += new/datum/uplink_random_item(item.type)
|
||||
|
||||
/datum/uplink_random_selection/default/New()
|
||||
..()
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/silenced_45)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/ammo/mc9mm)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/revolver)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/ammo/a357)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/heavysnipermerc, 15, 0)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/ammo/sniperammo, 15, 0)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/grenades/emp, 50)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/crossbow, 33)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/visible_weapons/energy_sword, 75)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/soap, 5, 100)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/concealed_cane, 50, 10)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/detomatix, 20, 10)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/parapen)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealthy_weapons/cigarette_kit)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/id)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/spy)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/chameleon_kit)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/chameleon_projector)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/stealth_items/voice)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/armor/heavy_vest)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/armor/combat)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/toolbox, reselect_propbability = 10)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/plastique)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/encryptionkey_radio)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/encryptionkey_binary)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/emag, 100, 50)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/clerical)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/space_suit, 50, 10)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/thermal)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/powersink, 10, 10)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/ai_module, 25, 0)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/tools/teleporter, 10, 0)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_freedom)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_compress)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/implants/imp_explosive)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/medical/sinpockets, reselect_propbability = 20)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/medical/surgery, reselect_propbability = 10)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/medical/combat, reselect_propbability = 10)
|
||||
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/thermal, reselect_propbability = 15)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/energy_net, reselect_propbability = 15)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/ewar_voice, reselect_propbability = 15)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/maneuvering_jets, reselect_propbability = 15)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/egun, reselect_propbability = 15)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/power_sink, reselect_propbability = 15)
|
||||
items += new/datum/uplink_random_item(/datum/uplink_item/item/hardsuit_modules/laser_canon, reselect_propbability = 5)
|
||||
|
||||
#ifdef DEBUG
|
||||
/proc/debug_uplink_purchage_log()
|
||||
for(var/antag_type in all_antag_types)
|
||||
var/datum/antagonist/A = all_antag_types[antag_type]
|
||||
A.print_player_summary()
|
||||
|
||||
/proc/debug_uplink_item_assoc_list()
|
||||
for(var/key in uplink.items_assoc)
|
||||
to_world("[key] - [uplink.items_assoc[key]]")
|
||||
#endif
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
/obj/item/latexballon
|
||||
name = "latex glove"
|
||||
desc = "A latex glove, usually used as a balloon."
|
||||
icon_state = "latexballon"
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_gloves.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_gloves.dmi',
|
||||
)
|
||||
item_state = "lgloves"
|
||||
force = 0
|
||||
throwforce = 0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throw_speed = 1
|
||||
throw_range = 15
|
||||
var/state
|
||||
var/datum/gas_mixture/air_contents = null
|
||||
|
||||
/obj/item/latexballon/proc/blow(obj/item/weapon/tank/tank)
|
||||
if (icon_state == "latexballon_bursted")
|
||||
return
|
||||
src.air_contents = tank.remove_air_volume(3)
|
||||
icon_state = "latexballon_blow"
|
||||
item_state = "latexballon"
|
||||
|
||||
/obj/item/latexballon/proc/burst()
|
||||
if (!air_contents)
|
||||
return
|
||||
playsound(src, 'sound/weapons/Gunshot_old.ogg', 100, 1)
|
||||
icon_state = "latexballon_bursted"
|
||||
item_state = "lgloves"
|
||||
loc.assume_air(air_contents)
|
||||
|
||||
/obj/item/latexballon/ex_act(severity)
|
||||
burst()
|
||||
switch(severity)
|
||||
if (1)
|
||||
qdel(src)
|
||||
if (2)
|
||||
if (prob(50))
|
||||
qdel(src)
|
||||
|
||||
/obj/item/latexballon/bullet_act()
|
||||
burst()
|
||||
|
||||
/obj/item/latexballon/fire_act(datum/gas_mixture/air, temperature, volume)
|
||||
if(temperature > T0C+100)
|
||||
burst()
|
||||
return
|
||||
|
||||
/obj/item/latexballon/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (can_puncture(W))
|
||||
burst()
|
||||
|
||||
/*
|
||||
/obj/item/latexballon/nitrile
|
||||
name = "nitrile glove"
|
||||
desc = "A nitrile glove, usually used as a balloon."
|
||||
icon_state = "nitrileballon"
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_gloves.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_gloves.dmi',
|
||||
)
|
||||
item_state = "ngloves"
|
||||
/obj/item/latexballon
|
||||
name = "latex glove"
|
||||
desc = "A latex glove, usually used as a balloon."
|
||||
icon_state = "latexballon"
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_gloves.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_gloves.dmi',
|
||||
)
|
||||
item_state = "lgloves"
|
||||
force = 0
|
||||
throwforce = 0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throw_speed = 1
|
||||
throw_range = 15
|
||||
var/state
|
||||
var/datum/gas_mixture/air_contents = null
|
||||
|
||||
/obj/item/latexballon/proc/blow(obj/item/weapon/tank/tank)
|
||||
if (icon_state == "latexballon_bursted")
|
||||
return
|
||||
src.air_contents = tank.remove_air_volume(3)
|
||||
icon_state = "latexballon_blow"
|
||||
item_state = "latexballon"
|
||||
|
||||
/obj/item/latexballon/proc/burst()
|
||||
if (!air_contents)
|
||||
return
|
||||
playsound(src, 'sound/weapons/Gunshot_old.ogg', 100, 1)
|
||||
icon_state = "latexballon_bursted"
|
||||
item_state = "lgloves"
|
||||
loc.assume_air(air_contents)
|
||||
|
||||
/obj/item/latexballon/ex_act(severity)
|
||||
burst()
|
||||
switch(severity)
|
||||
if (1)
|
||||
qdel(src)
|
||||
if (2)
|
||||
if (prob(50))
|
||||
qdel(src)
|
||||
|
||||
/obj/item/latexballon/bullet_act()
|
||||
burst()
|
||||
|
||||
/obj/item/latexballon/fire_act(datum/gas_mixture/air, temperature, volume)
|
||||
if(temperature > T0C+100)
|
||||
burst()
|
||||
return
|
||||
|
||||
/obj/item/latexballon/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (can_puncture(W))
|
||||
burst()
|
||||
|
||||
/*
|
||||
/obj/item/latexballon/nitrile
|
||||
name = "nitrile glove"
|
||||
desc = "A nitrile glove, usually used as a balloon."
|
||||
icon_state = "nitrileballon"
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_gloves.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_gloves.dmi',
|
||||
)
|
||||
item_state = "ngloves"
|
||||
*/
|
||||
+332
-332
@@ -1,332 +1,332 @@
|
||||
/obj/item/device/kit
|
||||
icon_state = "modkit"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
w_class = ITEMSIZE_SMALL
|
||||
var/new_name = "custom item"
|
||||
var/new_desc = "A custom item."
|
||||
var/new_icon
|
||||
var/new_icon_file
|
||||
var/new_icon_override_file
|
||||
var/uses = 1 // Uses before the kit deletes itself.
|
||||
var/list/allowed_types = list()
|
||||
|
||||
/obj/item/device/kit/examine()
|
||||
. = ..()
|
||||
. += "It has [uses] use\s left."
|
||||
|
||||
/obj/item/device/kit/proc/use(var/amt, var/mob/user)
|
||||
uses -= amt
|
||||
playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
if(uses<1)
|
||||
user.drop_item()
|
||||
qdel(src)
|
||||
|
||||
/obj/item/device/kit/proc/can_customize(var/obj/item/I)
|
||||
return is_type_in_list(I, allowed_types)
|
||||
|
||||
/obj/item/device/kit/proc/set_info(var/kit_name, var/kit_desc, var/kit_icon, var/kit_icon_file = CUSTOM_ITEM_OBJ, var/kit_icon_override_file = CUSTOM_ITEM_MOB, var/additional_data)
|
||||
new_name = kit_name
|
||||
new_desc = kit_desc
|
||||
new_icon = kit_icon
|
||||
new_icon_file = kit_icon_file
|
||||
new_icon_override_file = kit_icon_override_file
|
||||
|
||||
for(var/path in splittext(additional_data, ", "))
|
||||
allowed_types |= text2path(path)
|
||||
|
||||
/obj/item/device/kit/proc/customize(var/obj/item/I, var/mob/user)
|
||||
if(can_customize(I))
|
||||
I.name = new_name ? new_name : I.name
|
||||
I.desc = new_desc ? new_desc : I.desc
|
||||
I.icon = new_icon_file ? new_icon_file : I.icon
|
||||
I.icon_override = new_icon_override_file ? new_icon_override_file : I.icon_override
|
||||
if(new_icon)
|
||||
I.icon_state = new_icon
|
||||
var/obj/item/clothing/under/U = I
|
||||
if(istype(U))
|
||||
U.worn_state = I.icon_state
|
||||
U.update_rolldown_status()
|
||||
use(1, user)
|
||||
|
||||
// Generic use
|
||||
/obj/item/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/device/kit))
|
||||
var/obj/item/device/kit/K = W
|
||||
K.customize(src, user)
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
// Root hardsuit kit defines.
|
||||
// Icons for modified hardsuits need to be in the proper .dmis because suit cyclers may cock them up.
|
||||
/obj/item/device/kit/suit
|
||||
name = "voidsuit modification kit"
|
||||
desc = "A kit for modifying a voidsuit."
|
||||
uses = 2
|
||||
var/new_light_overlay
|
||||
|
||||
/obj/item/device/kit/suit/can_customize(var/obj/item/I)
|
||||
return istype(I, /obj/item/clothing/head/helmet/space/void) || istype(I, /obj/item/clothing/suit/space/void) || istype(I, /obj/item/clothing/suit/storage/hooded)
|
||||
|
||||
/obj/item/device/kit/suit/set_info(var/kit_name, var/kit_desc, var/kit_icon, var/kit_icon_file = CUSTOM_ITEM_OBJ, var/kit_icon_override_file = CUSTOM_ITEM_MOB, var/additional_data)
|
||||
..()
|
||||
|
||||
new_light_overlay = additional_data
|
||||
|
||||
|
||||
/obj/item/device/kit/suit/customize(var/obj/item/I, var/mob/user)
|
||||
if(can_customize(I))
|
||||
if(istype(I, /obj/item/clothing/head/helmet/space/void))
|
||||
var/obj/item/clothing/head/helmet/space/void/helmet = I
|
||||
helmet.name = "[new_name] suit helmet"
|
||||
helmet.desc = new_desc
|
||||
helmet.icon_state = "[new_icon]_helmet"
|
||||
helmet.item_state = "[new_icon]_helmet"
|
||||
if(new_icon_file)
|
||||
helmet.icon = new_icon_file
|
||||
if(new_icon_override_file)
|
||||
helmet.icon_override = new_icon_override_file
|
||||
if(new_light_overlay)
|
||||
helmet.light_overlay = new_light_overlay
|
||||
to_chat(user, "You set about modifying the helmet into [helmet].")
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(istype(H))
|
||||
helmet.species_restricted = list(H.species.get_bodytype(H))
|
||||
else if(istype(I, /obj/item/clothing/suit/storage/hooded))
|
||||
var/obj/item/clothing/suit/storage/hooded/suit = I
|
||||
suit.name = "[new_name] suit"
|
||||
suit.desc = new_desc
|
||||
suit.icon_state = "[new_icon]_suit"
|
||||
suit.toggleicon = "[new_icon]_suit"
|
||||
var/obj/item/clothing/head/hood/S = suit.hood
|
||||
S.icon_state = "[new_icon]_helmet"
|
||||
if(new_icon_file)
|
||||
suit.icon = new_icon_file
|
||||
S.icon = new_icon_file
|
||||
if(new_icon_override_file)
|
||||
suit.icon_override = new_icon_override_file
|
||||
S.icon_override = new_icon_override_file
|
||||
to_chat(user, "You set about modifying the suit into [suit].")
|
||||
// var/mob/living/carbon/human/H = user
|
||||
// if(istype(H))
|
||||
// suit.species_restricted = list(H.species.get_bodytype(H)) Does not quite make sense for something usually very pliable.
|
||||
else
|
||||
var/obj/item/clothing/suit/space/void/suit = I
|
||||
suit.name = "[new_name] voidsuit"
|
||||
suit.desc = new_desc
|
||||
suit.icon_state = "[new_icon]_suit"
|
||||
suit.item_state = "[new_icon]_suit"
|
||||
if(new_icon_file)
|
||||
suit.icon = new_icon_file
|
||||
if(new_icon_override_file)
|
||||
suit.icon_override = new_icon_override_file
|
||||
to_chat(user, "You set about modifying the suit into [suit].")
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(istype(H))
|
||||
suit.species_restricted = list(H.species.get_bodytype(H))
|
||||
use(1,user)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/void/attackby(var/obj/item/O, var/mob/user)
|
||||
if(istype(O,/obj/item/device/kit/suit))
|
||||
var/obj/item/device/kit/suit/kit = O
|
||||
kit.customize(src, user)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/suit/space/void/attackby(var/obj/item/O, var/mob/user)
|
||||
if(istype(O,/obj/item/device/kit/suit))
|
||||
var/obj/item/device/kit/suit/kit = O
|
||||
kit.customize(src, user)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/suit/storage/hooded/attackby(var/obj/item/O, var/mob/user)
|
||||
if(istype(O,/obj/item/device/kit/suit))
|
||||
var/obj/item/device/kit/suit/kit = O
|
||||
kit.customize(src, user)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/device/kit/suit/rig
|
||||
name = "rig modification kit"
|
||||
desc = "A kit for modifying a rigsuit."
|
||||
uses = 1
|
||||
|
||||
/obj/item/device/kit/suit/rig/customize(var/obj/item/I, var/mob/user)
|
||||
var/obj/item/weapon/rig/RIG = I
|
||||
RIG.suit_state = new_icon
|
||||
RIG.item_state = new_icon
|
||||
RIG.suit_type = "customized [initial(RIG.suit_type)]"
|
||||
RIG.name = "[new_name]"
|
||||
RIG.desc = new_desc
|
||||
RIG.icon = new_icon_file
|
||||
RIG.icon_state = new_icon
|
||||
RIG.icon_override = new_icon_override_file
|
||||
for(var/obj/item/piece in list(RIG.gloves,RIG.helmet,RIG.boots,RIG.chest))
|
||||
if(!istype(piece))
|
||||
continue
|
||||
piece.name = "[RIG.suit_type] [initial(piece.name)]"
|
||||
piece.desc = "It seems to be part of a [RIG.name]."
|
||||
piece.icon_state = "[RIG.suit_state]"
|
||||
if(istype(piece, /obj/item/clothing/shoes))
|
||||
piece.icon = 'icons/mob/custom_items_rig_boots.dmi'
|
||||
piece.icon_override = 'icons/mob/custom_items_rig_boots.dmi'
|
||||
if(istype(piece, /obj/item/clothing/suit))
|
||||
piece.icon = 'icons/mob/custom_items_rig_suit.dmi'
|
||||
piece.icon_override = 'icons/mob/custom_items_rig_suit.dmi'
|
||||
if(istype(piece, /obj/item/clothing/head))
|
||||
piece.icon = 'icons/mob/custom_items_rig_helmet.dmi'
|
||||
piece.icon_override = 'icons/mob/custom_items_rig_helmet.dmi'
|
||||
if(istype(piece, /obj/item/clothing/gloves))
|
||||
piece.icon = 'icons/mob/custom_items_rig_gloves.dmi'
|
||||
piece.icon_override = 'icons/mob/custom_items_rig_gloves.dmi'
|
||||
if(RIG.helmet && istype(RIG.helmet, /obj/item/clothing/head/helmet) && new_light_overlay)
|
||||
var/obj/item/clothing/head/helmet/H = RIG.helmet
|
||||
H.light_overlay = new_light_overlay
|
||||
use(1,user)
|
||||
|
||||
/obj/item/device/kit/suit/rig/can_customize(var/obj/item/I)
|
||||
return istype(I, /obj/item/weapon/rig)
|
||||
|
||||
/obj/item/weapon/rig/attackby(var/obj/item/O, var/mob/user)
|
||||
if(istype(O,/obj/item/device/kit/suit))
|
||||
var/obj/item/device/kit/suit/rig/kit = O
|
||||
kit.customize(src, user)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/device/kit/suit/rig/debug/Initialize()
|
||||
set_info("debug suit", "This is a test", "debug", CUSTOM_ITEM_OBJ, CUSTOM_ITEM_MOB)
|
||||
|
||||
/obj/item/device/kit/paint
|
||||
name = "mecha customisation kit"
|
||||
desc = "A kit containing all the needed tools and parts to repaint a mech."
|
||||
var/removable = null
|
||||
|
||||
/obj/item/device/kit/paint/can_customize(var/obj/mecha/M)
|
||||
if(!istype(M))
|
||||
return 0
|
||||
|
||||
for(var/type in allowed_types)
|
||||
if(type == M.initial_icon)
|
||||
return 1
|
||||
|
||||
/obj/item/device/kit/paint/set_info(var/kit_name, var/kit_desc, var/kit_icon, var/kit_icon_file = CUSTOM_ITEM_OBJ, var/kit_icon_override_file = CUSTOM_ITEM_MOB, var/additional_data)
|
||||
..()
|
||||
|
||||
allowed_types = splittext(additional_data, ", ")
|
||||
|
||||
|
||||
/obj/item/device/kit/paint/examine()
|
||||
. = ..()
|
||||
. += "This kit will convert an exosuit into: [new_name]."
|
||||
. += "This kit can be used on the following exosuit models:"
|
||||
for(var/exotype in allowed_types)
|
||||
. += "- [capitalize(exotype)]"
|
||||
|
||||
/obj/item/device/kit/paint/customize(var/obj/mecha/M, var/mob/user)
|
||||
if(!can_customize(M))
|
||||
to_chat(user, "That kit isn't meant for use on this class of exosuit.")
|
||||
return
|
||||
|
||||
if(M.occupant)
|
||||
to_chat(user, "You can't customize a mech while someone is piloting it - that would be unsafe!")
|
||||
return
|
||||
|
||||
user.visible_message("[user] opens [src] and spends some quality time customising [M].")
|
||||
M.name = new_name
|
||||
M.desc = new_desc
|
||||
M.initial_icon = new_icon
|
||||
if(new_icon_file)
|
||||
M.icon = new_icon_file
|
||||
M.update_icon()
|
||||
use(1, user)
|
||||
|
||||
/obj/mecha/attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
if(istype(W, /obj/item/device/kit/paint))
|
||||
var/obj/item/device/kit/paint/P = W
|
||||
P.customize(src, user)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
//Ripley APLU kits.
|
||||
/obj/item/device/kit/paint/ripley
|
||||
name = "\"Classic\" APLU customisation kit"
|
||||
new_name = "APLU \"Classic\""
|
||||
new_desc = "A very retro APLU unit; didn't they retire these back in 2303?"
|
||||
new_icon = "ripley-old"
|
||||
allowed_types = list("ripley")
|
||||
var/showpilot = TRUE
|
||||
var/showpilot_lift = 5
|
||||
|
||||
/obj/item/device/kit/paint/ripley/customize(obj/mecha/M, mob/user)
|
||||
if(showpilot)
|
||||
M.show_pilot = TRUE
|
||||
M.pilot_lift = 5
|
||||
else
|
||||
M.show_pilot = FALSE
|
||||
M.pilot_lift = 0
|
||||
. = ..()
|
||||
|
||||
/obj/item/device/kit/paint/ripley/death
|
||||
name = "\"Reaper\" APLU customisation kit"
|
||||
new_name = "APLU \"Reaper\""
|
||||
new_desc = "A terrifying, grim power loader. Why do those clamps have spikes?"
|
||||
new_icon = "deathripley"
|
||||
allowed_types = list("ripley","firefighter")
|
||||
showpilot = FALSE
|
||||
|
||||
/obj/item/device/kit/paint/ripley/flames_red
|
||||
name = "\"Firestarter\" APLU customisation kit"
|
||||
new_name = "APLU \"Firestarter\""
|
||||
new_desc = "A standard APLU exosuit with stylish orange flame decals."
|
||||
new_icon = "ripley_flames_red"
|
||||
showpilot = FALSE
|
||||
|
||||
/obj/item/device/kit/paint/ripley/flames_blue
|
||||
name = "\"Burning Chrome\" APLU customisation kit"
|
||||
new_name = "APLU \"Burning Chrome\""
|
||||
new_desc = "A standard APLU exosuit with stylish blue flame decals."
|
||||
new_icon = "ripley_flames_blue"
|
||||
showpilot = FALSE
|
||||
|
||||
// Durand kits.
|
||||
/obj/item/device/kit/paint/durand
|
||||
name = "\"Classic\" Durand customisation kit"
|
||||
new_name = "Durand \"Classic\""
|
||||
new_desc = "An older model of Durand combat exosuit. This model was retired for rotating a pilot's torso 180 degrees."
|
||||
new_icon = "old_durand"
|
||||
allowed_types = list("durand")
|
||||
|
||||
/obj/item/device/kit/paint/durand/seraph
|
||||
name = "\"Cherubim\" Durand customisation kit"
|
||||
new_name = "Durand \"Cherubim\""
|
||||
new_desc = "A Durand combat exosuit modelled after ancient Earth entertainment. Your heart goes doki-doki just looking at it."
|
||||
new_icon = "old_durand"
|
||||
|
||||
/obj/item/device/kit/paint/durand/phazon
|
||||
name = "\"Sypher\" Durand customisation kit"
|
||||
new_name = "Durand \"Sypher\""
|
||||
new_desc = "A Durand combat exosuit with some very stylish neons and decals. Seems to blur slightly at the edges; probably an optical illusion."
|
||||
new_icon = "phazon"
|
||||
|
||||
// Gygax kits.
|
||||
/obj/item/device/kit/paint/gygax
|
||||
name = "\"Jester\" Gygax customisation kit"
|
||||
new_name = "Gygax \"Jester\""
|
||||
new_desc = "A Gygax exosuit modelled after the infamous combat-troubadors of Earth's distant past. Terrifying to behold."
|
||||
new_icon = "honker"
|
||||
allowed_types = list("gygax")
|
||||
|
||||
/obj/item/device/kit/paint/gygax/darkgygax
|
||||
name = "\"Silhouette\" Gygax customisation kit"
|
||||
new_name = "Gygax \"Silhouette\""
|
||||
new_desc = "An ominous Gygax exosuit modelled after the fictional corporate 'death squads' that were popular in pulp action-thrillers back in 2314."
|
||||
new_icon = "darkgygax"
|
||||
|
||||
/obj/item/device/kit/paint/gygax/recitence
|
||||
name = "\"Gaoler\" Gygax customisation kit"
|
||||
new_name = "Durand \"Gaoler\""
|
||||
new_desc = "A bulky silver Gygax exosuit. The extra armour appears to be painted on, but it's very shiny."
|
||||
new_icon = "recitence"
|
||||
/obj/item/device/kit
|
||||
icon_state = "modkit"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
w_class = ITEMSIZE_SMALL
|
||||
var/new_name = "custom item"
|
||||
var/new_desc = "A custom item."
|
||||
var/new_icon
|
||||
var/new_icon_file
|
||||
var/new_icon_override_file
|
||||
var/uses = 1 // Uses before the kit deletes itself.
|
||||
var/list/allowed_types = list()
|
||||
|
||||
/obj/item/device/kit/examine()
|
||||
. = ..()
|
||||
. += "It has [uses] use\s left."
|
||||
|
||||
/obj/item/device/kit/proc/use(var/amt, var/mob/user)
|
||||
uses -= amt
|
||||
playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
if(uses<1)
|
||||
user.drop_item()
|
||||
qdel(src)
|
||||
|
||||
/obj/item/device/kit/proc/can_customize(var/obj/item/I)
|
||||
return is_type_in_list(I, allowed_types)
|
||||
|
||||
/obj/item/device/kit/proc/set_info(var/kit_name, var/kit_desc, var/kit_icon, var/kit_icon_file = CUSTOM_ITEM_OBJ, var/kit_icon_override_file = CUSTOM_ITEM_MOB, var/additional_data)
|
||||
new_name = kit_name
|
||||
new_desc = kit_desc
|
||||
new_icon = kit_icon
|
||||
new_icon_file = kit_icon_file
|
||||
new_icon_override_file = kit_icon_override_file
|
||||
|
||||
for(var/path in splittext(additional_data, ", "))
|
||||
allowed_types |= text2path(path)
|
||||
|
||||
/obj/item/device/kit/proc/customize(var/obj/item/I, var/mob/user)
|
||||
if(can_customize(I))
|
||||
I.name = new_name ? new_name : I.name
|
||||
I.desc = new_desc ? new_desc : I.desc
|
||||
I.icon = new_icon_file ? new_icon_file : I.icon
|
||||
I.icon_override = new_icon_override_file ? new_icon_override_file : I.icon_override
|
||||
if(new_icon)
|
||||
I.icon_state = new_icon
|
||||
var/obj/item/clothing/under/U = I
|
||||
if(istype(U))
|
||||
U.worn_state = I.icon_state
|
||||
U.update_rolldown_status()
|
||||
use(1, user)
|
||||
|
||||
// Generic use
|
||||
/obj/item/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/device/kit))
|
||||
var/obj/item/device/kit/K = W
|
||||
K.customize(src, user)
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
// Root hardsuit kit defines.
|
||||
// Icons for modified hardsuits need to be in the proper .dmis because suit cyclers may cock them up.
|
||||
/obj/item/device/kit/suit
|
||||
name = "voidsuit modification kit"
|
||||
desc = "A kit for modifying a voidsuit."
|
||||
uses = 2
|
||||
var/new_light_overlay
|
||||
|
||||
/obj/item/device/kit/suit/can_customize(var/obj/item/I)
|
||||
return istype(I, /obj/item/clothing/head/helmet/space/void) || istype(I, /obj/item/clothing/suit/space/void) || istype(I, /obj/item/clothing/suit/storage/hooded)
|
||||
|
||||
/obj/item/device/kit/suit/set_info(var/kit_name, var/kit_desc, var/kit_icon, var/kit_icon_file = CUSTOM_ITEM_OBJ, var/kit_icon_override_file = CUSTOM_ITEM_MOB, var/additional_data)
|
||||
..()
|
||||
|
||||
new_light_overlay = additional_data
|
||||
|
||||
|
||||
/obj/item/device/kit/suit/customize(var/obj/item/I, var/mob/user)
|
||||
if(can_customize(I))
|
||||
if(istype(I, /obj/item/clothing/head/helmet/space/void))
|
||||
var/obj/item/clothing/head/helmet/space/void/helmet = I
|
||||
helmet.name = "[new_name] suit helmet"
|
||||
helmet.desc = new_desc
|
||||
helmet.icon_state = "[new_icon]_helmet"
|
||||
helmet.item_state = "[new_icon]_helmet"
|
||||
if(new_icon_file)
|
||||
helmet.icon = new_icon_file
|
||||
if(new_icon_override_file)
|
||||
helmet.icon_override = new_icon_override_file
|
||||
if(new_light_overlay)
|
||||
helmet.light_overlay = new_light_overlay
|
||||
to_chat(user, "You set about modifying the helmet into [helmet].")
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(istype(H))
|
||||
helmet.species_restricted = list(H.species.get_bodytype(H))
|
||||
else if(istype(I, /obj/item/clothing/suit/storage/hooded))
|
||||
var/obj/item/clothing/suit/storage/hooded/suit = I
|
||||
suit.name = "[new_name] suit"
|
||||
suit.desc = new_desc
|
||||
suit.icon_state = "[new_icon]_suit"
|
||||
suit.toggleicon = "[new_icon]_suit"
|
||||
var/obj/item/clothing/head/hood/S = suit.hood
|
||||
S.icon_state = "[new_icon]_helmet"
|
||||
if(new_icon_file)
|
||||
suit.icon = new_icon_file
|
||||
S.icon = new_icon_file
|
||||
if(new_icon_override_file)
|
||||
suit.icon_override = new_icon_override_file
|
||||
S.icon_override = new_icon_override_file
|
||||
to_chat(user, "You set about modifying the suit into [suit].")
|
||||
// var/mob/living/carbon/human/H = user
|
||||
// if(istype(H))
|
||||
// suit.species_restricted = list(H.species.get_bodytype(H)) Does not quite make sense for something usually very pliable.
|
||||
else
|
||||
var/obj/item/clothing/suit/space/void/suit = I
|
||||
suit.name = "[new_name] voidsuit"
|
||||
suit.desc = new_desc
|
||||
suit.icon_state = "[new_icon]_suit"
|
||||
suit.item_state = "[new_icon]_suit"
|
||||
if(new_icon_file)
|
||||
suit.icon = new_icon_file
|
||||
if(new_icon_override_file)
|
||||
suit.icon_override = new_icon_override_file
|
||||
to_chat(user, "You set about modifying the suit into [suit].")
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(istype(H))
|
||||
suit.species_restricted = list(H.species.get_bodytype(H))
|
||||
use(1,user)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/void/attackby(var/obj/item/O, var/mob/user)
|
||||
if(istype(O,/obj/item/device/kit/suit))
|
||||
var/obj/item/device/kit/suit/kit = O
|
||||
kit.customize(src, user)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/suit/space/void/attackby(var/obj/item/O, var/mob/user)
|
||||
if(istype(O,/obj/item/device/kit/suit))
|
||||
var/obj/item/device/kit/suit/kit = O
|
||||
kit.customize(src, user)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/suit/storage/hooded/attackby(var/obj/item/O, var/mob/user)
|
||||
if(istype(O,/obj/item/device/kit/suit))
|
||||
var/obj/item/device/kit/suit/kit = O
|
||||
kit.customize(src, user)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/device/kit/suit/rig
|
||||
name = "rig modification kit"
|
||||
desc = "A kit for modifying a rigsuit."
|
||||
uses = 1
|
||||
|
||||
/obj/item/device/kit/suit/rig/customize(var/obj/item/I, var/mob/user)
|
||||
var/obj/item/weapon/rig/RIG = I
|
||||
RIG.suit_state = new_icon
|
||||
RIG.item_state = new_icon
|
||||
RIG.suit_type = "customized [initial(RIG.suit_type)]"
|
||||
RIG.name = "[new_name]"
|
||||
RIG.desc = new_desc
|
||||
RIG.icon = new_icon_file
|
||||
RIG.icon_state = new_icon
|
||||
RIG.icon_override = new_icon_override_file
|
||||
for(var/obj/item/piece in list(RIG.gloves,RIG.helmet,RIG.boots,RIG.chest))
|
||||
if(!istype(piece))
|
||||
continue
|
||||
piece.name = "[RIG.suit_type] [initial(piece.name)]"
|
||||
piece.desc = "It seems to be part of a [RIG.name]."
|
||||
piece.icon_state = "[RIG.suit_state]"
|
||||
if(istype(piece, /obj/item/clothing/shoes))
|
||||
piece.icon = 'icons/mob/custom_items_rig_boots.dmi'
|
||||
piece.icon_override = 'icons/mob/custom_items_rig_boots.dmi'
|
||||
if(istype(piece, /obj/item/clothing/suit))
|
||||
piece.icon = 'icons/mob/custom_items_rig_suit.dmi'
|
||||
piece.icon_override = 'icons/mob/custom_items_rig_suit.dmi'
|
||||
if(istype(piece, /obj/item/clothing/head))
|
||||
piece.icon = 'icons/mob/custom_items_rig_helmet.dmi'
|
||||
piece.icon_override = 'icons/mob/custom_items_rig_helmet.dmi'
|
||||
if(istype(piece, /obj/item/clothing/gloves))
|
||||
piece.icon = 'icons/mob/custom_items_rig_gloves.dmi'
|
||||
piece.icon_override = 'icons/mob/custom_items_rig_gloves.dmi'
|
||||
if(RIG.helmet && istype(RIG.helmet, /obj/item/clothing/head/helmet) && new_light_overlay)
|
||||
var/obj/item/clothing/head/helmet/H = RIG.helmet
|
||||
H.light_overlay = new_light_overlay
|
||||
use(1,user)
|
||||
|
||||
/obj/item/device/kit/suit/rig/can_customize(var/obj/item/I)
|
||||
return istype(I, /obj/item/weapon/rig)
|
||||
|
||||
/obj/item/weapon/rig/attackby(var/obj/item/O, var/mob/user)
|
||||
if(istype(O,/obj/item/device/kit/suit))
|
||||
var/obj/item/device/kit/suit/rig/kit = O
|
||||
kit.customize(src, user)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/device/kit/suit/rig/debug/Initialize()
|
||||
set_info("debug suit", "This is a test", "debug", CUSTOM_ITEM_OBJ, CUSTOM_ITEM_MOB)
|
||||
|
||||
/obj/item/device/kit/paint
|
||||
name = "mecha customisation kit"
|
||||
desc = "A kit containing all the needed tools and parts to repaint a mech."
|
||||
var/removable = null
|
||||
|
||||
/obj/item/device/kit/paint/can_customize(var/obj/mecha/M)
|
||||
if(!istype(M))
|
||||
return 0
|
||||
|
||||
for(var/type in allowed_types)
|
||||
if(type == M.initial_icon)
|
||||
return 1
|
||||
|
||||
/obj/item/device/kit/paint/set_info(var/kit_name, var/kit_desc, var/kit_icon, var/kit_icon_file = CUSTOM_ITEM_OBJ, var/kit_icon_override_file = CUSTOM_ITEM_MOB, var/additional_data)
|
||||
..()
|
||||
|
||||
allowed_types = splittext(additional_data, ", ")
|
||||
|
||||
|
||||
/obj/item/device/kit/paint/examine()
|
||||
. = ..()
|
||||
. += "This kit will convert an exosuit into: [new_name]."
|
||||
. += "This kit can be used on the following exosuit models:"
|
||||
for(var/exotype in allowed_types)
|
||||
. += "- [capitalize(exotype)]"
|
||||
|
||||
/obj/item/device/kit/paint/customize(var/obj/mecha/M, var/mob/user)
|
||||
if(!can_customize(M))
|
||||
to_chat(user, "That kit isn't meant for use on this class of exosuit.")
|
||||
return
|
||||
|
||||
if(M.occupant)
|
||||
to_chat(user, "You can't customize a mech while someone is piloting it - that would be unsafe!")
|
||||
return
|
||||
|
||||
user.visible_message("[user] opens [src] and spends some quality time customising [M].")
|
||||
M.name = new_name
|
||||
M.desc = new_desc
|
||||
M.initial_icon = new_icon
|
||||
if(new_icon_file)
|
||||
M.icon = new_icon_file
|
||||
M.update_icon()
|
||||
use(1, user)
|
||||
|
||||
/obj/mecha/attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
if(istype(W, /obj/item/device/kit/paint))
|
||||
var/obj/item/device/kit/paint/P = W
|
||||
P.customize(src, user)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
//Ripley APLU kits.
|
||||
/obj/item/device/kit/paint/ripley
|
||||
name = "\"Classic\" APLU customisation kit"
|
||||
new_name = "APLU \"Classic\""
|
||||
new_desc = "A very retro APLU unit; didn't they retire these back in 2303?"
|
||||
new_icon = "ripley-old"
|
||||
allowed_types = list("ripley")
|
||||
var/showpilot = TRUE
|
||||
var/showpilot_lift = 5
|
||||
|
||||
/obj/item/device/kit/paint/ripley/customize(obj/mecha/M, mob/user)
|
||||
if(showpilot)
|
||||
M.show_pilot = TRUE
|
||||
M.pilot_lift = 5
|
||||
else
|
||||
M.show_pilot = FALSE
|
||||
M.pilot_lift = 0
|
||||
. = ..()
|
||||
|
||||
/obj/item/device/kit/paint/ripley/death
|
||||
name = "\"Reaper\" APLU customisation kit"
|
||||
new_name = "APLU \"Reaper\""
|
||||
new_desc = "A terrifying, grim power loader. Why do those clamps have spikes?"
|
||||
new_icon = "deathripley"
|
||||
allowed_types = list("ripley","firefighter")
|
||||
showpilot = FALSE
|
||||
|
||||
/obj/item/device/kit/paint/ripley/flames_red
|
||||
name = "\"Firestarter\" APLU customisation kit"
|
||||
new_name = "APLU \"Firestarter\""
|
||||
new_desc = "A standard APLU exosuit with stylish orange flame decals."
|
||||
new_icon = "ripley_flames_red"
|
||||
showpilot = FALSE
|
||||
|
||||
/obj/item/device/kit/paint/ripley/flames_blue
|
||||
name = "\"Burning Chrome\" APLU customisation kit"
|
||||
new_name = "APLU \"Burning Chrome\""
|
||||
new_desc = "A standard APLU exosuit with stylish blue flame decals."
|
||||
new_icon = "ripley_flames_blue"
|
||||
showpilot = FALSE
|
||||
|
||||
// Durand kits.
|
||||
/obj/item/device/kit/paint/durand
|
||||
name = "\"Classic\" Durand customisation kit"
|
||||
new_name = "Durand \"Classic\""
|
||||
new_desc = "An older model of Durand combat exosuit. This model was retired for rotating a pilot's torso 180 degrees."
|
||||
new_icon = "old_durand"
|
||||
allowed_types = list("durand")
|
||||
|
||||
/obj/item/device/kit/paint/durand/seraph
|
||||
name = "\"Cherubim\" Durand customisation kit"
|
||||
new_name = "Durand \"Cherubim\""
|
||||
new_desc = "A Durand combat exosuit modelled after ancient Earth entertainment. Your heart goes doki-doki just looking at it."
|
||||
new_icon = "old_durand"
|
||||
|
||||
/obj/item/device/kit/paint/durand/phazon
|
||||
name = "\"Sypher\" Durand customisation kit"
|
||||
new_name = "Durand \"Sypher\""
|
||||
new_desc = "A Durand combat exosuit with some very stylish neons and decals. Seems to blur slightly at the edges; probably an optical illusion."
|
||||
new_icon = "phazon"
|
||||
|
||||
// Gygax kits.
|
||||
/obj/item/device/kit/paint/gygax
|
||||
name = "\"Jester\" Gygax customisation kit"
|
||||
new_name = "Gygax \"Jester\""
|
||||
new_desc = "A Gygax exosuit modelled after the infamous combat-troubadors of Earth's distant past. Terrifying to behold."
|
||||
new_icon = "honker"
|
||||
allowed_types = list("gygax")
|
||||
|
||||
/obj/item/device/kit/paint/gygax/darkgygax
|
||||
name = "\"Silhouette\" Gygax customisation kit"
|
||||
new_name = "Gygax \"Silhouette\""
|
||||
new_desc = "An ominous Gygax exosuit modelled after the fictional corporate 'death squads' that were popular in pulp action-thrillers back in 2314."
|
||||
new_icon = "darkgygax"
|
||||
|
||||
/obj/item/device/kit/paint/gygax/recitence
|
||||
name = "\"Gaoler\" Gygax customisation kit"
|
||||
new_name = "Durand \"Gaoler\""
|
||||
new_desc = "A bulky silver Gygax exosuit. The extra armour appears to be painted on, but it's very shiny."
|
||||
new_icon = "recitence"
|
||||
|
||||
@@ -1,84 +1,84 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
|
||||
|
||||
/**********************************************************************
|
||||
Cyborg Spec Items
|
||||
***********************************************************************/
|
||||
//Might want to move this into several files later but for now it works here
|
||||
|
||||
/obj/item/weapon/melee/baton/robot/arm
|
||||
name = "electrified arm"
|
||||
icon = 'icons/obj/decals.dmi'
|
||||
icon_state = "shock"
|
||||
|
||||
hitcost = 750
|
||||
agonyforce = 70
|
||||
|
||||
/obj/item/weapon/melee/baton/robot/arm/update_icon()
|
||||
if(status)
|
||||
set_light(1.5, 1, lightcolor)
|
||||
else
|
||||
set_light(0)
|
||||
|
||||
/obj/item/borg/overdrive
|
||||
name = "overdrive"
|
||||
icon = 'icons/obj/decals.dmi'
|
||||
icon_state = "shock"
|
||||
|
||||
/**********************************************************************
|
||||
HUD/SIGHT things
|
||||
***********************************************************************/
|
||||
/obj/item/borg/sight
|
||||
icon = 'icons/obj/decals.dmi'
|
||||
icon_state = "securearea"
|
||||
var/sight_mode = null
|
||||
|
||||
|
||||
/obj/item/borg/sight/xray
|
||||
name = "\proper x-ray vision"
|
||||
sight_mode = BORGXRAY
|
||||
|
||||
|
||||
/obj/item/borg/sight/thermal
|
||||
name = "\proper thermal vision"
|
||||
sight_mode = BORGTHERM
|
||||
icon_state = "thermal"
|
||||
icon = 'icons/inventory/eyes/item.dmi'
|
||||
|
||||
|
||||
/obj/item/borg/sight/meson
|
||||
name = "\proper meson vision"
|
||||
sight_mode = BORGMESON
|
||||
icon_state = "meson"
|
||||
icon = 'icons/inventory/eyes/item.dmi'
|
||||
|
||||
/obj/item/borg/sight/material
|
||||
name = "\proper material scanner vision"
|
||||
sight_mode = BORGMATERIAL
|
||||
icon_state = "material"
|
||||
icon = 'icons/inventory/eyes/item.dmi'
|
||||
|
||||
/obj/item/borg/sight/hud
|
||||
name = "hud"
|
||||
var/obj/item/clothing/glasses/hud/hud = null
|
||||
|
||||
|
||||
/obj/item/borg/sight/hud/med
|
||||
name = "medical hud"
|
||||
icon_state = "healthhud"
|
||||
icon = 'icons/inventory/eyes/item.dmi'
|
||||
|
||||
/obj/item/borg/sight/hud/med/New()
|
||||
..()
|
||||
hud = new /obj/item/clothing/glasses/hud/health(src)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/borg/sight/hud/sec
|
||||
name = "security hud"
|
||||
icon_state = "securityhud"
|
||||
icon = 'icons/inventory/eyes/item.dmi'
|
||||
|
||||
/obj/item/borg/sight/hud/sec/New()
|
||||
..()
|
||||
hud = new /obj/item/clothing/glasses/hud/security(src)
|
||||
return
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
|
||||
|
||||
/**********************************************************************
|
||||
Cyborg Spec Items
|
||||
***********************************************************************/
|
||||
//Might want to move this into several files later but for now it works here
|
||||
|
||||
/obj/item/weapon/melee/baton/robot/arm
|
||||
name = "electrified arm"
|
||||
icon = 'icons/obj/decals.dmi'
|
||||
icon_state = "shock"
|
||||
|
||||
hitcost = 750
|
||||
agonyforce = 70
|
||||
|
||||
/obj/item/weapon/melee/baton/robot/arm/update_icon()
|
||||
if(status)
|
||||
set_light(1.5, 1, lightcolor)
|
||||
else
|
||||
set_light(0)
|
||||
|
||||
/obj/item/borg/overdrive
|
||||
name = "overdrive"
|
||||
icon = 'icons/obj/decals.dmi'
|
||||
icon_state = "shock"
|
||||
|
||||
/**********************************************************************
|
||||
HUD/SIGHT things
|
||||
***********************************************************************/
|
||||
/obj/item/borg/sight
|
||||
icon = 'icons/obj/decals.dmi'
|
||||
icon_state = "securearea"
|
||||
var/sight_mode = null
|
||||
|
||||
|
||||
/obj/item/borg/sight/xray
|
||||
name = "\proper x-ray vision"
|
||||
sight_mode = BORGXRAY
|
||||
|
||||
|
||||
/obj/item/borg/sight/thermal
|
||||
name = "\proper thermal vision"
|
||||
sight_mode = BORGTHERM
|
||||
icon_state = "thermal"
|
||||
icon = 'icons/inventory/eyes/item.dmi'
|
||||
|
||||
|
||||
/obj/item/borg/sight/meson
|
||||
name = "\proper meson vision"
|
||||
sight_mode = BORGMESON
|
||||
icon_state = "meson"
|
||||
icon = 'icons/inventory/eyes/item.dmi'
|
||||
|
||||
/obj/item/borg/sight/material
|
||||
name = "\proper material scanner vision"
|
||||
sight_mode = BORGMATERIAL
|
||||
icon_state = "material"
|
||||
icon = 'icons/inventory/eyes/item.dmi'
|
||||
|
||||
/obj/item/borg/sight/hud
|
||||
name = "hud"
|
||||
var/obj/item/clothing/glasses/hud/hud = null
|
||||
|
||||
|
||||
/obj/item/borg/sight/hud/med
|
||||
name = "medical hud"
|
||||
icon_state = "healthhud"
|
||||
icon = 'icons/inventory/eyes/item.dmi'
|
||||
|
||||
/obj/item/borg/sight/hud/med/New()
|
||||
..()
|
||||
hud = new /obj/item/clothing/glasses/hud/health(src)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/borg/sight/hud/sec
|
||||
name = "security hud"
|
||||
icon_state = "securityhud"
|
||||
icon = 'icons/inventory/eyes/item.dmi'
|
||||
|
||||
/obj/item/borg/sight/hud/sec/New()
|
||||
..()
|
||||
hud = new /obj/item/clothing/glasses/hud/security(src)
|
||||
return
|
||||
|
||||
@@ -1,180 +1,180 @@
|
||||
// Targets, the things that actually get shot!
|
||||
/obj/item/target
|
||||
name = "shooting target"
|
||||
desc = "A shooting target."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "target_h"
|
||||
density = FALSE
|
||||
var/hp = 1800
|
||||
var/icon/virtualIcon
|
||||
var/list/bulletholes = list()
|
||||
|
||||
/obj/item/target/Destroy()
|
||||
// if a target is deleted and associated with a stake, force stake to forget
|
||||
for(var/obj/structure/target_stake/T in view(3,src))
|
||||
if(T.pinned_target == src)
|
||||
T.pinned_target = null
|
||||
T.density = TRUE
|
||||
break
|
||||
..() // delete target
|
||||
|
||||
/obj/item/target/Moved(atom/old_loc, direction, forced = FALSE)
|
||||
. = ..()
|
||||
// After target moves, check for nearby stakes. If associated, move to target
|
||||
for(var/obj/structure/target_stake/M in view(3,src))
|
||||
if(M.density == 0 && M.pinned_target == src)
|
||||
M.forceMove(loc)
|
||||
|
||||
// This may seem a little counter-intuitive but I assure you that's for a purpose.
|
||||
// Stakes are the ones that carry targets, yes, but in the stake code we set
|
||||
// a stake's density to 0 meaning it can't be pushed anymore. Instead of pushing
|
||||
// the stake now, we have to push the target.
|
||||
|
||||
|
||||
|
||||
/obj/item/target/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (W.has_tool_quality(TOOL_WELDER))
|
||||
var/obj/item/weapon/weldingtool/WT = W.get_welder()
|
||||
if(WT.remove_fuel(0, user))
|
||||
cut_overlays()
|
||||
to_chat(usr, "You slice off [src]'s uneven chunks of aluminum and scorch marks.")
|
||||
return
|
||||
|
||||
|
||||
/obj/item/target/attack_hand(mob/user as mob)
|
||||
// taking pinned targets off!
|
||||
var/obj/structure/target_stake/stake
|
||||
for(var/obj/structure/target_stake/T in view(3,src))
|
||||
if(T.pinned_target == src)
|
||||
stake = T
|
||||
break
|
||||
|
||||
if(stake)
|
||||
if(stake.pinned_target)
|
||||
stake.density = TRUE
|
||||
density = FALSE
|
||||
layer = OBJ_LAYER
|
||||
|
||||
loc = user.loc
|
||||
if(ishuman(user))
|
||||
if(!user.get_active_hand())
|
||||
user.put_in_hands(src)
|
||||
to_chat(user, "You take the target out of the stake.")
|
||||
else
|
||||
src.loc = get_turf(user)
|
||||
to_chat(user, "You take the target out of the stake.")
|
||||
|
||||
stake.pinned_target = null
|
||||
return
|
||||
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/target/syndicate
|
||||
icon_state = "target_s"
|
||||
desc = "A shooting target that looks like a hostile agent."
|
||||
hp = 2600 // i guess syndie targets are sturdier?
|
||||
/obj/item/target/alien
|
||||
icon_state = "target_q"
|
||||
desc = "A shooting target with a threatening silhouette."
|
||||
hp = 2350 // alium onest too kinda
|
||||
|
||||
/obj/item/target/bullet_act(var/obj/item/projectile/Proj)
|
||||
var/p_x = Proj.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset Proj.p_x!"
|
||||
var/p_y = Proj.p_y + pick(0,0,0,0,0,-1,1)
|
||||
var/decaltype = 1 // 1 - scorch, 2 - bullet
|
||||
|
||||
if(istype(/obj/item/projectile/bullet, Proj))
|
||||
decaltype = 2
|
||||
|
||||
|
||||
virtualIcon = new(icon, icon_state)
|
||||
|
||||
if( virtualIcon.GetPixel(p_x, p_y) ) // if the located pixel isn't blank (null)
|
||||
|
||||
hp -= Proj.damage
|
||||
if(hp <= 0)
|
||||
for(var/mob/O in oviewers())
|
||||
if ((O.client && !( O.blinded )))
|
||||
to_chat(O, "<span class='warning'>\The [src] breaks into tiny pieces and collapses!</span>")
|
||||
qdel(src)
|
||||
|
||||
// Create a temporary object to represent the damage
|
||||
var/obj/bmark = new
|
||||
bmark.pixel_x = p_x
|
||||
bmark.pixel_y = p_y
|
||||
bmark.icon = 'icons/effects/effects.dmi'
|
||||
bmark.icon_state = "scorch"
|
||||
|
||||
if(decaltype == 1)
|
||||
// Energy weapons are hot. they scorch!
|
||||
|
||||
// offset correction
|
||||
bmark.pixel_x--
|
||||
bmark.pixel_y--
|
||||
|
||||
if(Proj.damage >= 20 || istype(Proj, /obj/item/projectile/beam/practice))
|
||||
bmark.icon_state = "scorch"
|
||||
bmark.set_dir(pick(NORTH,SOUTH,EAST,WEST)) // random scorch design
|
||||
|
||||
|
||||
else
|
||||
bmark.icon_state = "light_scorch"
|
||||
else
|
||||
|
||||
// Bullets are hard. They make dents!
|
||||
bmark.icon_state = "dent"
|
||||
|
||||
if(Proj.damage >= 10 && bulletholes.len <= 35) // maximum of 35 bullet holes
|
||||
if(decaltype == 2) // bullet
|
||||
if(prob(Proj.damage+30)) // bullets make holes more commonly!
|
||||
new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole
|
||||
else // Lasers!
|
||||
if(prob(Proj.damage-10)) // lasers make holes less commonly
|
||||
new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole
|
||||
|
||||
// draw bullet holes
|
||||
for(var/datum/bullethole/B in bulletholes)
|
||||
|
||||
virtualIcon.DrawBox(null, B.b1x1, B.b1y, B.b1x2, B.b1y) // horizontal line, left to right
|
||||
virtualIcon.DrawBox(null, B.b2x, B.b2y1, B.b2x, B.b2y2) // vertical line, top to bottom
|
||||
|
||||
add_overlay(bmark) // add the decal
|
||||
|
||||
icon = virtualIcon // apply bulletholes over decals
|
||||
|
||||
return
|
||||
|
||||
return PROJECTILE_CONTINUE // the bullet/projectile goes through the target!
|
||||
|
||||
|
||||
// Small memory holder entity for transparent bullet holes
|
||||
/datum/bullethole
|
||||
// First box
|
||||
var/b1x1 = 0
|
||||
var/b1x2 = 0
|
||||
var/b1y = 0
|
||||
|
||||
// Second box
|
||||
var/b2x = 0
|
||||
var/b2y1 = 0
|
||||
var/b2y2 = 0
|
||||
|
||||
/datum/bullethole/New(var/obj/item/target/Target, var/pixel_x = 0, var/pixel_y = 0)
|
||||
if(!Target) return
|
||||
|
||||
// Randomize the first box
|
||||
b1x1 = pixel_x - pick(1,1,1,1,2,2,3,3,4)
|
||||
b1x2 = pixel_x + pick(1,1,1,1,2,2,3,3,4)
|
||||
b1y = pixel_y
|
||||
if(prob(35))
|
||||
b1y += rand(-4,4)
|
||||
|
||||
// Randomize the second box
|
||||
b2x = pixel_x
|
||||
if(prob(35))
|
||||
b2x += rand(-4,4)
|
||||
b2y1 = pixel_y + pick(1,1,1,1,2,2,3,3,4)
|
||||
b2y2 = pixel_y - pick(1,1,1,1,2,2,3,3,4)
|
||||
|
||||
Target.bulletholes.Add(src)
|
||||
// Targets, the things that actually get shot!
|
||||
/obj/item/target
|
||||
name = "shooting target"
|
||||
desc = "A shooting target."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "target_h"
|
||||
density = FALSE
|
||||
var/hp = 1800
|
||||
var/icon/virtualIcon
|
||||
var/list/bulletholes = list()
|
||||
|
||||
/obj/item/target/Destroy()
|
||||
// if a target is deleted and associated with a stake, force stake to forget
|
||||
for(var/obj/structure/target_stake/T in view(3,src))
|
||||
if(T.pinned_target == src)
|
||||
T.pinned_target = null
|
||||
T.density = TRUE
|
||||
break
|
||||
..() // delete target
|
||||
|
||||
/obj/item/target/Moved(atom/old_loc, direction, forced = FALSE)
|
||||
. = ..()
|
||||
// After target moves, check for nearby stakes. If associated, move to target
|
||||
for(var/obj/structure/target_stake/M in view(3,src))
|
||||
if(M.density == 0 && M.pinned_target == src)
|
||||
M.forceMove(loc)
|
||||
|
||||
// This may seem a little counter-intuitive but I assure you that's for a purpose.
|
||||
// Stakes are the ones that carry targets, yes, but in the stake code we set
|
||||
// a stake's density to 0 meaning it can't be pushed anymore. Instead of pushing
|
||||
// the stake now, we have to push the target.
|
||||
|
||||
|
||||
|
||||
/obj/item/target/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (W.has_tool_quality(TOOL_WELDER))
|
||||
var/obj/item/weapon/weldingtool/WT = W.get_welder()
|
||||
if(WT.remove_fuel(0, user))
|
||||
cut_overlays()
|
||||
to_chat(usr, "You slice off [src]'s uneven chunks of aluminum and scorch marks.")
|
||||
return
|
||||
|
||||
|
||||
/obj/item/target/attack_hand(mob/user as mob)
|
||||
// taking pinned targets off!
|
||||
var/obj/structure/target_stake/stake
|
||||
for(var/obj/structure/target_stake/T in view(3,src))
|
||||
if(T.pinned_target == src)
|
||||
stake = T
|
||||
break
|
||||
|
||||
if(stake)
|
||||
if(stake.pinned_target)
|
||||
stake.density = TRUE
|
||||
density = FALSE
|
||||
layer = OBJ_LAYER
|
||||
|
||||
loc = user.loc
|
||||
if(ishuman(user))
|
||||
if(!user.get_active_hand())
|
||||
user.put_in_hands(src)
|
||||
to_chat(user, "You take the target out of the stake.")
|
||||
else
|
||||
src.loc = get_turf(user)
|
||||
to_chat(user, "You take the target out of the stake.")
|
||||
|
||||
stake.pinned_target = null
|
||||
return
|
||||
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/target/syndicate
|
||||
icon_state = "target_s"
|
||||
desc = "A shooting target that looks like a hostile agent."
|
||||
hp = 2600 // i guess syndie targets are sturdier?
|
||||
/obj/item/target/alien
|
||||
icon_state = "target_q"
|
||||
desc = "A shooting target with a threatening silhouette."
|
||||
hp = 2350 // alium onest too kinda
|
||||
|
||||
/obj/item/target/bullet_act(var/obj/item/projectile/Proj)
|
||||
var/p_x = Proj.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset Proj.p_x!"
|
||||
var/p_y = Proj.p_y + pick(0,0,0,0,0,-1,1)
|
||||
var/decaltype = 1 // 1 - scorch, 2 - bullet
|
||||
|
||||
if(istype(/obj/item/projectile/bullet, Proj))
|
||||
decaltype = 2
|
||||
|
||||
|
||||
virtualIcon = new(icon, icon_state)
|
||||
|
||||
if( virtualIcon.GetPixel(p_x, p_y) ) // if the located pixel isn't blank (null)
|
||||
|
||||
hp -= Proj.damage
|
||||
if(hp <= 0)
|
||||
for(var/mob/O in oviewers())
|
||||
if ((O.client && !( O.blinded )))
|
||||
to_chat(O, "<span class='warning'>\The [src] breaks into tiny pieces and collapses!</span>")
|
||||
qdel(src)
|
||||
|
||||
// Create a temporary object to represent the damage
|
||||
var/obj/bmark = new
|
||||
bmark.pixel_x = p_x
|
||||
bmark.pixel_y = p_y
|
||||
bmark.icon = 'icons/effects/effects.dmi'
|
||||
bmark.icon_state = "scorch"
|
||||
|
||||
if(decaltype == 1)
|
||||
// Energy weapons are hot. they scorch!
|
||||
|
||||
// offset correction
|
||||
bmark.pixel_x--
|
||||
bmark.pixel_y--
|
||||
|
||||
if(Proj.damage >= 20 || istype(Proj, /obj/item/projectile/beam/practice))
|
||||
bmark.icon_state = "scorch"
|
||||
bmark.set_dir(pick(NORTH,SOUTH,EAST,WEST)) // random scorch design
|
||||
|
||||
|
||||
else
|
||||
bmark.icon_state = "light_scorch"
|
||||
else
|
||||
|
||||
// Bullets are hard. They make dents!
|
||||
bmark.icon_state = "dent"
|
||||
|
||||
if(Proj.damage >= 10 && bulletholes.len <= 35) // maximum of 35 bullet holes
|
||||
if(decaltype == 2) // bullet
|
||||
if(prob(Proj.damage+30)) // bullets make holes more commonly!
|
||||
new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole
|
||||
else // Lasers!
|
||||
if(prob(Proj.damage-10)) // lasers make holes less commonly
|
||||
new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole
|
||||
|
||||
// draw bullet holes
|
||||
for(var/datum/bullethole/B in bulletholes)
|
||||
|
||||
virtualIcon.DrawBox(null, B.b1x1, B.b1y, B.b1x2, B.b1y) // horizontal line, left to right
|
||||
virtualIcon.DrawBox(null, B.b2x, B.b2y1, B.b2x, B.b2y2) // vertical line, top to bottom
|
||||
|
||||
add_overlay(bmark) // add the decal
|
||||
|
||||
icon = virtualIcon // apply bulletholes over decals
|
||||
|
||||
return
|
||||
|
||||
return PROJECTILE_CONTINUE // the bullet/projectile goes through the target!
|
||||
|
||||
|
||||
// Small memory holder entity for transparent bullet holes
|
||||
/datum/bullethole
|
||||
// First box
|
||||
var/b1x1 = 0
|
||||
var/b1x2 = 0
|
||||
var/b1y = 0
|
||||
|
||||
// Second box
|
||||
var/b2x = 0
|
||||
var/b2y1 = 0
|
||||
var/b2y2 = 0
|
||||
|
||||
/datum/bullethole/New(var/obj/item/target/Target, var/pixel_x = 0, var/pixel_y = 0)
|
||||
if(!Target) return
|
||||
|
||||
// Randomize the first box
|
||||
b1x1 = pixel_x - pick(1,1,1,1,2,2,3,3,4)
|
||||
b1x2 = pixel_x + pick(1,1,1,1,2,2,3,3,4)
|
||||
b1y = pixel_y
|
||||
if(prob(35))
|
||||
b1y += rand(-4,4)
|
||||
|
||||
// Randomize the second box
|
||||
b2x = pixel_x
|
||||
if(prob(35))
|
||||
b2x += rand(-4,4)
|
||||
b2y1 = pixel_y + pick(1,1,1,1,2,2,3,3,4)
|
||||
b2y2 = pixel_y - pick(1,1,1,1,2,2,3,3,4)
|
||||
|
||||
Target.bulletholes.Add(src)
|
||||
|
||||
@@ -1,452 +1,452 @@
|
||||
/obj/item/stack/medical
|
||||
name = "medical pack"
|
||||
singular_name = "medical pack"
|
||||
icon = 'icons/obj/stacks.dmi'
|
||||
amount = 10
|
||||
max_amount = 10
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throw_speed = 4
|
||||
throw_range = 20
|
||||
var/heal_brute = 0
|
||||
var/heal_burn = 0
|
||||
var/apply_sounds
|
||||
drop_sound = 'sound/items/drop/cardboardbox.ogg'
|
||||
pickup_sound = 'sound/items/pickup/cardboardbox.ogg'
|
||||
|
||||
var/upgrade_to // The type path this stack can be upgraded to.
|
||||
|
||||
/obj/item/stack/medical/attack(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if (!istype(M))
|
||||
to_chat(user, "<span class='warning'>\The [src] cannot be applied to [M]!</span>")
|
||||
return 1
|
||||
|
||||
if (!user.IsAdvancedToolUser())
|
||||
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||
return 1
|
||||
|
||||
var/available = get_amount()
|
||||
if(!available)
|
||||
to_chat(user, "<span class='warning'>There's not enough [uses_charge ? "charge" : "items"] left to use that!</span>")
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
|
||||
if(!affecting)
|
||||
to_chat(user, "<span class='warning'>No body part there to work on!</span>")
|
||||
return 1
|
||||
|
||||
if(affecting.organ_tag == BP_HEAD)
|
||||
if(H.head && istype(H.head,/obj/item/clothing/head/helmet/space))
|
||||
to_chat(user, "<span class='warning'>You can't apply [src] through [H.head]!</span>")
|
||||
return 1
|
||||
else
|
||||
if(H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space))
|
||||
to_chat(user, "<span class='warning'>You can't apply [src] through [H.wear_suit]!</span>")
|
||||
return 1
|
||||
|
||||
if(affecting.robotic == ORGAN_ROBOT)
|
||||
to_chat(user, "<span class='warning'>This isn't useful at all on a robotic limb.</span>")
|
||||
return 1
|
||||
|
||||
if(affecting.robotic >= ORGAN_LIFELIKE)
|
||||
to_chat(user, "<span class='warning'>You apply the [src], but it seems to have no effect...</span>")
|
||||
use(1)
|
||||
return 1
|
||||
|
||||
H.UpdateDamageIcon()
|
||||
|
||||
else
|
||||
|
||||
M.heal_organ_damage((src.heal_brute/2), (src.heal_burn/2))
|
||||
user.visible_message( \
|
||||
"<span class='notice'>[M] has been applied with [src] by [user].</span>", \
|
||||
"<span class='notice'>You apply \the [src] to [M].</span>" \
|
||||
)
|
||||
use(1)
|
||||
|
||||
M.updatehealth()
|
||||
|
||||
/obj/item/stack/medical/proc/upgrade_stack(var/upgrade_amount)
|
||||
. = FALSE
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
if(ispath(upgrade_to) && use(upgrade_amount))
|
||||
var/obj/item/stack/medical/M = new upgrade_to(T, upgrade_amount)
|
||||
return M
|
||||
|
||||
return .
|
||||
|
||||
/obj/item/stack/medical/crude_pack
|
||||
name = "crude bandage"
|
||||
singular_name = "crude bandage length"
|
||||
desc = "Some bandages to wrap around bloody stumps."
|
||||
icon_state = "gauze"
|
||||
origin_tech = list(TECH_BIO = 1)
|
||||
no_variants = FALSE
|
||||
apply_sounds = list('sound/effects/rip1.ogg','sound/effects/rip2.ogg')
|
||||
|
||||
upgrade_to = /obj/item/stack/medical/bruise_pack
|
||||
|
||||
/obj/item/stack/medical/crude_pack/attack(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
|
||||
if(affecting.open)
|
||||
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
|
||||
return
|
||||
|
||||
if(affecting.is_bandaged())
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
|
||||
return 1
|
||||
else
|
||||
var/available = get_amount()
|
||||
user.visible_message("<b>\The [user]</b> starts bandaging [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You start bandaging [M]'s [affecting.name].</span>" )
|
||||
var/used = 0
|
||||
for (var/datum/wound/W in affecting.wounds)
|
||||
if(W.internal)
|
||||
continue
|
||||
if(W.bandaged)
|
||||
continue
|
||||
if(used == amount)
|
||||
break
|
||||
if(!do_mob(user, M, W.damage/3, exclusive = TRUE))
|
||||
to_chat(user, "<span class='notice'>You must stand still to bandage wounds.</span>")
|
||||
break
|
||||
|
||||
if(affecting.is_bandaged()) // We do a second check after the delay, in case it was bandaged after the first check.
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
|
||||
return 1
|
||||
|
||||
if(used >= available)
|
||||
to_chat(user, "<span class='warning'>You run out of [src]!</span>")
|
||||
break
|
||||
|
||||
if (W.current_stage <= W.max_bleeding_stage)
|
||||
user.visible_message("<b>\The [user]</b> bandages \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You bandage \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
else
|
||||
user.visible_message("<b>\The [user]</b> places a bandage over \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You place a bandage over \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
W.bandage()
|
||||
playsound(src, pick(apply_sounds), 25)
|
||||
used++
|
||||
affecting.update_damages()
|
||||
if(used == amount)
|
||||
if(affecting.is_bandaged())
|
||||
to_chat(user, "<span class='warning'>\The [src] is used up.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [src] is used up, but there are more wounds to treat on \the [affecting.name].</span>")
|
||||
use(used)
|
||||
|
||||
/obj/item/stack/medical/bruise_pack
|
||||
name = "roll of gauze"
|
||||
singular_name = "gauze length"
|
||||
desc = "Some sterile gauze to wrap around bloody stumps."
|
||||
icon_state = "brutepack"
|
||||
origin_tech = list(TECH_BIO = 1)
|
||||
no_variants = FALSE
|
||||
apply_sounds = list('sound/effects/rip1.ogg','sound/effects/rip2.ogg')
|
||||
drop_sound = 'sound/items/drop/gloves.ogg'
|
||||
pickup_sound = 'sound/items/pickup/gloves.ogg'
|
||||
|
||||
upgrade_to = /obj/item/stack/medical/advanced/bruise_pack
|
||||
|
||||
/obj/item/stack/medical/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
|
||||
if(affecting.open)
|
||||
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
|
||||
return
|
||||
|
||||
if(affecting.is_bandaged())
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
|
||||
return 1
|
||||
else
|
||||
var/available = get_amount()
|
||||
user.visible_message("<b>\The [user]</b> starts treating [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You start treating [M]'s [affecting.name].</span>" )
|
||||
var/used = 0
|
||||
for (var/datum/wound/W in affecting.wounds)
|
||||
if (W.internal)
|
||||
continue
|
||||
if(W.bandaged)
|
||||
continue
|
||||
if(used == amount)
|
||||
break
|
||||
if(!do_mob(user, M, W.damage/5, exclusive = TRUE))
|
||||
to_chat(user, "<span class='notice'>You must stand still to bandage wounds.</span>")
|
||||
break
|
||||
|
||||
if(affecting.is_bandaged()) // We do a second check after the delay, in case it was bandaged after the first check.
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
|
||||
return 1
|
||||
|
||||
if(used >= available)
|
||||
to_chat(user, "<span class='warning'>You run out of [src]!</span>")
|
||||
break
|
||||
|
||||
if (W.current_stage <= W.max_bleeding_stage)
|
||||
user.visible_message("<b>\The [user]</b> bandages \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You bandage \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
//H.add_side_effect("Itch")
|
||||
else if (W.damage_type == BRUISE)
|
||||
user.visible_message("<b>\The [user]</b> places a bruise patch over \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You place a bruise patch over \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
else
|
||||
user.visible_message("<b>\The [user]</b> places a bandaid over \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You place a bandaid over \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
W.bandage()
|
||||
// W.disinfect() // VOREStation - Tech1 should not disinfect
|
||||
playsound(src, pick(apply_sounds), 25)
|
||||
used++
|
||||
affecting.update_damages()
|
||||
if(used == amount)
|
||||
if(affecting.is_bandaged())
|
||||
to_chat(user, "<span class='warning'>\The [src] is used up.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [src] is used up, but there are more wounds to treat on \the [affecting.name].</span>")
|
||||
use(used)
|
||||
|
||||
/obj/item/stack/medical/ointment
|
||||
name = "ointment"
|
||||
desc = "Used to treat those nasty burns."
|
||||
gender = PLURAL
|
||||
singular_name = "ointment"
|
||||
icon_state = "ointment"
|
||||
heal_burn = 1
|
||||
origin_tech = list(TECH_BIO = 1)
|
||||
no_variants = FALSE
|
||||
apply_sounds = list('sound/effects/ointment.ogg')
|
||||
drop_sound = 'sound/items/drop/herb.ogg'
|
||||
pickup_sound = 'sound/items/pickup/herb.ogg'
|
||||
|
||||
/obj/item/stack/medical/ointment/attack(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
|
||||
if(affecting.open)
|
||||
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
|
||||
return
|
||||
|
||||
if(affecting.is_salved())
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>")
|
||||
return 1
|
||||
else
|
||||
user.visible_message("<b>\The [user]</b> starts salving wounds on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You start salving the wounds on [M]'s [affecting.name].</span>" )
|
||||
if(!do_mob(user, M, 10, exclusive = TRUE))
|
||||
to_chat(user, "<span class='notice'>You must stand still to salve wounds.</span>")
|
||||
return 1
|
||||
if(affecting.is_salved()) // We do a second check after the delay, in case it was bandaged after the first check.
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>")
|
||||
return 1
|
||||
user.visible_message("<span class='notice'>[user] salved wounds on [M]'s [affecting.name].</span>", \
|
||||
"<span class='notice'>You salved wounds on [M]'s [affecting.name].</span>" )
|
||||
use(1)
|
||||
affecting.salve()
|
||||
playsound(src, pick(apply_sounds), 25)
|
||||
|
||||
/obj/item/stack/medical/ointment/simple
|
||||
name = "ointment paste"
|
||||
desc = "A simple thick paste used to salve burns."
|
||||
singular_name = "old-ointment"
|
||||
icon_state = "old-ointment"
|
||||
|
||||
/obj/item/stack/medical/advanced/bruise_pack
|
||||
name = "advanced trauma kit"
|
||||
singular_name = "advanced trauma kit"
|
||||
desc = "An advanced trauma kit for severe injuries."
|
||||
icon_state = "traumakit"
|
||||
heal_brute = 7 //VOREStation Edit
|
||||
origin_tech = list(TECH_BIO = 1)
|
||||
apply_sounds = list('sound/effects/rip1.ogg','sound/effects/rip2.ogg','sound/effects/tape.ogg')
|
||||
|
||||
/obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
|
||||
if(affecting.open)
|
||||
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
|
||||
return
|
||||
|
||||
if(affecting.is_bandaged() && affecting.is_disinfected())
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been treated.</span>")
|
||||
return 1
|
||||
else
|
||||
var/available = get_amount()
|
||||
user.visible_message("<b>\The [user]</b> starts treating [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You start treating [M]'s [affecting.name].</span>" )
|
||||
var/used = 0
|
||||
for (var/datum/wound/W in affecting.wounds)
|
||||
if (W.internal)
|
||||
continue
|
||||
if (W.bandaged && W.disinfected)
|
||||
continue
|
||||
//if(used == amount) //VOREStation Edit
|
||||
// break //VOREStation Edit
|
||||
if(!do_mob(user, M, W.damage/5, exclusive = TRUE))
|
||||
to_chat(user, "<span class='notice'>You must stand still to bandage wounds.</span>")
|
||||
break
|
||||
if(affecting.is_bandaged() && affecting.is_disinfected()) // We do a second check after the delay, in case it was bandaged after the first check.
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
|
||||
return 1
|
||||
|
||||
if(used >= available)
|
||||
to_chat(user, "<span class='warning'>You run out of [src]!</span>")
|
||||
break
|
||||
|
||||
if (W.current_stage <= W.max_bleeding_stage)
|
||||
user.visible_message("<b>\The [user]</b> cleans \a [W.desc] on [M]'s [affecting.name] and seals the edges with bioglue.", \
|
||||
"<span class='notice'>You clean and seal \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
else if (W.damage_type == BRUISE)
|
||||
user.visible_message("<b>\The [user]</b> places a medical patch over \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You place a medical patch over \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
else
|
||||
user.visible_message("<b>\The [user]</b> smears some bioglue over \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You smear some bioglue over \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
W.bandage()
|
||||
W.disinfect()
|
||||
W.heal_damage(heal_brute)
|
||||
playsound(src, pick(apply_sounds), 25)
|
||||
used = 1 //VOREStation Edit
|
||||
update_icon() // VOREStation Edit - Support for stack icons
|
||||
affecting.update_damages()
|
||||
if(used == amount)
|
||||
if(affecting.is_bandaged())
|
||||
to_chat(user, "<span class='warning'>\The [src] is used up.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [src] is used up, but there are more wounds to treat on \the [affecting.name].</span>")
|
||||
use(used)
|
||||
|
||||
/obj/item/stack/medical/advanced/ointment
|
||||
name = "advanced burn kit"
|
||||
singular_name = "advanced burn kit"
|
||||
desc = "An advanced treatment kit for severe burns."
|
||||
icon_state = "burnkit"
|
||||
heal_burn = 7 //VOREStation Edit
|
||||
origin_tech = list(TECH_BIO = 1)
|
||||
apply_sounds = list('sound/effects/ointment.ogg')
|
||||
|
||||
/obj/item/stack/medical/advanced/ointment/attack(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
|
||||
if(affecting.open)
|
||||
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
|
||||
|
||||
if(affecting.is_salved())
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>")
|
||||
return 1
|
||||
else
|
||||
user.visible_message("<b>\The [user]</b> starts salving wounds on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You start salving the wounds on [M]'s [affecting.name].</span>" )
|
||||
if(!do_mob(user, M, 10, exclusive = TRUE))
|
||||
to_chat(user, "<span class='notice'>You must stand still to salve wounds.</span>")
|
||||
return 1
|
||||
if(affecting.is_salved()) // We do a second check after the delay, in case it was bandaged after the first check.
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>")
|
||||
return 1
|
||||
user.visible_message( "<span class='notice'>[user] covers wounds on [M]'s [affecting.name] with regenerative membrane.</span>", \
|
||||
"<span class='notice'>You cover wounds on [M]'s [affecting.name] with regenerative membrane.</span>" )
|
||||
affecting.heal_damage(0,heal_burn)
|
||||
use(1)
|
||||
affecting.salve()
|
||||
playsound(src, pick(apply_sounds), 25)
|
||||
update_icon() // VOREStation Edit - Support for stack icons
|
||||
|
||||
/obj/item/stack/medical/splint
|
||||
name = "medical splints"
|
||||
singular_name = "medical splint"
|
||||
desc = "Modular splints capable of supporting and immobilizing bones in all areas of the body."
|
||||
icon_state = "splint"
|
||||
amount = 5
|
||||
max_amount = 5
|
||||
drop_sound = 'sound/items/drop/hat.ogg'
|
||||
pickup_sound = 'sound/items/pickup/hat.ogg'
|
||||
|
||||
var/list/splintable_organs = list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO) //List of organs you can splint, natch.
|
||||
|
||||
/obj/item/stack/medical/splint/attack(mob/living/carbon/M as mob, mob/living/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
var/limb = affecting.name
|
||||
if(!(affecting.organ_tag in splintable_organs))
|
||||
to_chat(user, "<span class='danger'>You can't use \the [src] to apply a splint there!</span>")
|
||||
return
|
||||
if(affecting.splinted)
|
||||
to_chat(user, "<span class='danger'>[M]'s [limb] is already splinted!</span>")
|
||||
return
|
||||
if (M != user)
|
||||
user.visible_message("<span class='danger'>[user] starts to apply \the [src] to [M]'s [limb].</span>", "<span class='danger'>You start to apply \the [src] to [M]'s [limb].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
else
|
||||
if(( !user.hand && (affecting.organ_tag in list(BP_R_ARM, BP_R_HAND)) || \
|
||||
user.hand && (affecting.organ_tag in list(BP_L_ARM, BP_L_HAND)) ))
|
||||
to_chat(user, "<span class='danger'>You can't apply a splint to the arm you're using!</span>")
|
||||
return
|
||||
user.visible_message("<span class='danger'>[user] starts to apply \the [src] to their [limb].</span>", "<span class='danger'>You start to apply \the [src] to your [limb].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
if(do_after(user, 50, M, exclusive = TASK_USER_EXCLUSIVE))
|
||||
if(affecting.splinted)
|
||||
to_chat(user, "<span class='danger'>[M]'s [limb] is already splinted!</span>")
|
||||
return
|
||||
if(M == user && prob(75))
|
||||
user.visible_message("<span class='danger'>\The [user] fumbles [src].</span>", "<span class='danger'>You fumble [src].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
return
|
||||
if(ishuman(user))
|
||||
var/obj/item/stack/medical/splint/S = split(1)
|
||||
if(S)
|
||||
if(affecting.apply_splint(S))
|
||||
S.forceMove(affecting)
|
||||
if (M != user)
|
||||
user.visible_message("<span class='danger'>\The [user] finishes applying [src] to [M]'s [limb].</span>", "<span class='danger'>You finish applying \the [src] to [M]'s [limb].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
else
|
||||
user.visible_message("<span class='danger'>\The [user] successfully applies [src] to their [limb].</span>", "<span class='danger'>You successfully apply \the [src] to your [limb].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
return
|
||||
S.dropInto(src.loc) //didn't get applied, so just drop it
|
||||
if(isrobot(user))
|
||||
var/obj/item/stack/medical/splint/B = src
|
||||
if(B)
|
||||
if(affecting.apply_splint(B))
|
||||
B.forceMove(affecting)
|
||||
user.visible_message("<span class='danger'>\The [user] finishes applying [src] to [M]'s [limb].</span>", "<span class='danger'>You finish applying \the [src] to [M]'s [limb].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
B.use(1)
|
||||
return
|
||||
user.visible_message("<span class='danger'>\The [user] fails to apply [src].</span>", "<span class='danger'>You fail to apply [src].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
return
|
||||
|
||||
|
||||
/obj/item/stack/medical/splint/ghetto
|
||||
name = "makeshift splints"
|
||||
singular_name = "makeshift splint"
|
||||
desc = "For holding your limbs in place with duct tape and scrap metal."
|
||||
icon_state = "tape-splint"
|
||||
amount = 1
|
||||
splintable_organs = list(BP_L_ARM, BP_R_ARM, BP_L_LEG, BP_R_LEG)
|
||||
/obj/item/stack/medical
|
||||
name = "medical pack"
|
||||
singular_name = "medical pack"
|
||||
icon = 'icons/obj/stacks.dmi'
|
||||
amount = 10
|
||||
max_amount = 10
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throw_speed = 4
|
||||
throw_range = 20
|
||||
var/heal_brute = 0
|
||||
var/heal_burn = 0
|
||||
var/apply_sounds
|
||||
drop_sound = 'sound/items/drop/cardboardbox.ogg'
|
||||
pickup_sound = 'sound/items/pickup/cardboardbox.ogg'
|
||||
|
||||
var/upgrade_to // The type path this stack can be upgraded to.
|
||||
|
||||
/obj/item/stack/medical/attack(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if (!istype(M))
|
||||
to_chat(user, "<span class='warning'>\The [src] cannot be applied to [M]!</span>")
|
||||
return 1
|
||||
|
||||
if (!user.IsAdvancedToolUser())
|
||||
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||
return 1
|
||||
|
||||
var/available = get_amount()
|
||||
if(!available)
|
||||
to_chat(user, "<span class='warning'>There's not enough [uses_charge ? "charge" : "items"] left to use that!</span>")
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
|
||||
if(!affecting)
|
||||
to_chat(user, "<span class='warning'>No body part there to work on!</span>")
|
||||
return 1
|
||||
|
||||
if(affecting.organ_tag == BP_HEAD)
|
||||
if(H.head && istype(H.head,/obj/item/clothing/head/helmet/space))
|
||||
to_chat(user, "<span class='warning'>You can't apply [src] through [H.head]!</span>")
|
||||
return 1
|
||||
else
|
||||
if(H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space))
|
||||
to_chat(user, "<span class='warning'>You can't apply [src] through [H.wear_suit]!</span>")
|
||||
return 1
|
||||
|
||||
if(affecting.robotic == ORGAN_ROBOT)
|
||||
to_chat(user, "<span class='warning'>This isn't useful at all on a robotic limb.</span>")
|
||||
return 1
|
||||
|
||||
if(affecting.robotic >= ORGAN_LIFELIKE)
|
||||
to_chat(user, "<span class='warning'>You apply the [src], but it seems to have no effect...</span>")
|
||||
use(1)
|
||||
return 1
|
||||
|
||||
H.UpdateDamageIcon()
|
||||
|
||||
else
|
||||
|
||||
M.heal_organ_damage((src.heal_brute/2), (src.heal_burn/2))
|
||||
user.visible_message( \
|
||||
"<span class='notice'>[M] has been applied with [src] by [user].</span>", \
|
||||
"<span class='notice'>You apply \the [src] to [M].</span>" \
|
||||
)
|
||||
use(1)
|
||||
|
||||
M.updatehealth()
|
||||
|
||||
/obj/item/stack/medical/proc/upgrade_stack(var/upgrade_amount)
|
||||
. = FALSE
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
if(ispath(upgrade_to) && use(upgrade_amount))
|
||||
var/obj/item/stack/medical/M = new upgrade_to(T, upgrade_amount)
|
||||
return M
|
||||
|
||||
return .
|
||||
|
||||
/obj/item/stack/medical/crude_pack
|
||||
name = "crude bandage"
|
||||
singular_name = "crude bandage length"
|
||||
desc = "Some bandages to wrap around bloody stumps."
|
||||
icon_state = "gauze"
|
||||
origin_tech = list(TECH_BIO = 1)
|
||||
no_variants = FALSE
|
||||
apply_sounds = list('sound/effects/rip1.ogg','sound/effects/rip2.ogg')
|
||||
|
||||
upgrade_to = /obj/item/stack/medical/bruise_pack
|
||||
|
||||
/obj/item/stack/medical/crude_pack/attack(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
|
||||
if(affecting.open)
|
||||
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
|
||||
return
|
||||
|
||||
if(affecting.is_bandaged())
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
|
||||
return 1
|
||||
else
|
||||
var/available = get_amount()
|
||||
user.visible_message("<b>\The [user]</b> starts bandaging [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You start bandaging [M]'s [affecting.name].</span>" )
|
||||
var/used = 0
|
||||
for (var/datum/wound/W in affecting.wounds)
|
||||
if(W.internal)
|
||||
continue
|
||||
if(W.bandaged)
|
||||
continue
|
||||
if(used == amount)
|
||||
break
|
||||
if(!do_mob(user, M, W.damage/3, exclusive = TRUE))
|
||||
to_chat(user, "<span class='notice'>You must stand still to bandage wounds.</span>")
|
||||
break
|
||||
|
||||
if(affecting.is_bandaged()) // We do a second check after the delay, in case it was bandaged after the first check.
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
|
||||
return 1
|
||||
|
||||
if(used >= available)
|
||||
to_chat(user, "<span class='warning'>You run out of [src]!</span>")
|
||||
break
|
||||
|
||||
if (W.current_stage <= W.max_bleeding_stage)
|
||||
user.visible_message("<b>\The [user]</b> bandages \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You bandage \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
else
|
||||
user.visible_message("<b>\The [user]</b> places a bandage over \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You place a bandage over \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
W.bandage()
|
||||
playsound(src, pick(apply_sounds), 25)
|
||||
used++
|
||||
affecting.update_damages()
|
||||
if(used == amount)
|
||||
if(affecting.is_bandaged())
|
||||
to_chat(user, "<span class='warning'>\The [src] is used up.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [src] is used up, but there are more wounds to treat on \the [affecting.name].</span>")
|
||||
use(used)
|
||||
|
||||
/obj/item/stack/medical/bruise_pack
|
||||
name = "roll of gauze"
|
||||
singular_name = "gauze length"
|
||||
desc = "Some sterile gauze to wrap around bloody stumps."
|
||||
icon_state = "brutepack"
|
||||
origin_tech = list(TECH_BIO = 1)
|
||||
no_variants = FALSE
|
||||
apply_sounds = list('sound/effects/rip1.ogg','sound/effects/rip2.ogg')
|
||||
drop_sound = 'sound/items/drop/gloves.ogg'
|
||||
pickup_sound = 'sound/items/pickup/gloves.ogg'
|
||||
|
||||
upgrade_to = /obj/item/stack/medical/advanced/bruise_pack
|
||||
|
||||
/obj/item/stack/medical/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
|
||||
if(affecting.open)
|
||||
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
|
||||
return
|
||||
|
||||
if(affecting.is_bandaged())
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
|
||||
return 1
|
||||
else
|
||||
var/available = get_amount()
|
||||
user.visible_message("<b>\The [user]</b> starts treating [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You start treating [M]'s [affecting.name].</span>" )
|
||||
var/used = 0
|
||||
for (var/datum/wound/W in affecting.wounds)
|
||||
if (W.internal)
|
||||
continue
|
||||
if(W.bandaged)
|
||||
continue
|
||||
if(used == amount)
|
||||
break
|
||||
if(!do_mob(user, M, W.damage/5, exclusive = TRUE))
|
||||
to_chat(user, "<span class='notice'>You must stand still to bandage wounds.</span>")
|
||||
break
|
||||
|
||||
if(affecting.is_bandaged()) // We do a second check after the delay, in case it was bandaged after the first check.
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
|
||||
return 1
|
||||
|
||||
if(used >= available)
|
||||
to_chat(user, "<span class='warning'>You run out of [src]!</span>")
|
||||
break
|
||||
|
||||
if (W.current_stage <= W.max_bleeding_stage)
|
||||
user.visible_message("<b>\The [user]</b> bandages \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You bandage \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
//H.add_side_effect("Itch")
|
||||
else if (W.damage_type == BRUISE)
|
||||
user.visible_message("<b>\The [user]</b> places a bruise patch over \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You place a bruise patch over \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
else
|
||||
user.visible_message("<b>\The [user]</b> places a bandaid over \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You place a bandaid over \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
W.bandage()
|
||||
// W.disinfect() // VOREStation - Tech1 should not disinfect
|
||||
playsound(src, pick(apply_sounds), 25)
|
||||
used++
|
||||
affecting.update_damages()
|
||||
if(used == amount)
|
||||
if(affecting.is_bandaged())
|
||||
to_chat(user, "<span class='warning'>\The [src] is used up.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [src] is used up, but there are more wounds to treat on \the [affecting.name].</span>")
|
||||
use(used)
|
||||
|
||||
/obj/item/stack/medical/ointment
|
||||
name = "ointment"
|
||||
desc = "Used to treat those nasty burns."
|
||||
gender = PLURAL
|
||||
singular_name = "ointment"
|
||||
icon_state = "ointment"
|
||||
heal_burn = 1
|
||||
origin_tech = list(TECH_BIO = 1)
|
||||
no_variants = FALSE
|
||||
apply_sounds = list('sound/effects/ointment.ogg')
|
||||
drop_sound = 'sound/items/drop/herb.ogg'
|
||||
pickup_sound = 'sound/items/pickup/herb.ogg'
|
||||
|
||||
/obj/item/stack/medical/ointment/attack(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
|
||||
if(affecting.open)
|
||||
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
|
||||
return
|
||||
|
||||
if(affecting.is_salved())
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>")
|
||||
return 1
|
||||
else
|
||||
user.visible_message("<b>\The [user]</b> starts salving wounds on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You start salving the wounds on [M]'s [affecting.name].</span>" )
|
||||
if(!do_mob(user, M, 10, exclusive = TRUE))
|
||||
to_chat(user, "<span class='notice'>You must stand still to salve wounds.</span>")
|
||||
return 1
|
||||
if(affecting.is_salved()) // We do a second check after the delay, in case it was bandaged after the first check.
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>")
|
||||
return 1
|
||||
user.visible_message("<span class='notice'>[user] salved wounds on [M]'s [affecting.name].</span>", \
|
||||
"<span class='notice'>You salved wounds on [M]'s [affecting.name].</span>" )
|
||||
use(1)
|
||||
affecting.salve()
|
||||
playsound(src, pick(apply_sounds), 25)
|
||||
|
||||
/obj/item/stack/medical/ointment/simple
|
||||
name = "ointment paste"
|
||||
desc = "A simple thick paste used to salve burns."
|
||||
singular_name = "old-ointment"
|
||||
icon_state = "old-ointment"
|
||||
|
||||
/obj/item/stack/medical/advanced/bruise_pack
|
||||
name = "advanced trauma kit"
|
||||
singular_name = "advanced trauma kit"
|
||||
desc = "An advanced trauma kit for severe injuries."
|
||||
icon_state = "traumakit"
|
||||
heal_brute = 7 //VOREStation Edit
|
||||
origin_tech = list(TECH_BIO = 1)
|
||||
apply_sounds = list('sound/effects/rip1.ogg','sound/effects/rip2.ogg','sound/effects/tape.ogg')
|
||||
|
||||
/obj/item/stack/medical/advanced/bruise_pack/attack(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
|
||||
if(affecting.open)
|
||||
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
|
||||
return
|
||||
|
||||
if(affecting.is_bandaged() && affecting.is_disinfected())
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been treated.</span>")
|
||||
return 1
|
||||
else
|
||||
var/available = get_amount()
|
||||
user.visible_message("<b>\The [user]</b> starts treating [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You start treating [M]'s [affecting.name].</span>" )
|
||||
var/used = 0
|
||||
for (var/datum/wound/W in affecting.wounds)
|
||||
if (W.internal)
|
||||
continue
|
||||
if (W.bandaged && W.disinfected)
|
||||
continue
|
||||
//if(used == amount) //VOREStation Edit
|
||||
// break //VOREStation Edit
|
||||
if(!do_mob(user, M, W.damage/5, exclusive = TRUE))
|
||||
to_chat(user, "<span class='notice'>You must stand still to bandage wounds.</span>")
|
||||
break
|
||||
if(affecting.is_bandaged() && affecting.is_disinfected()) // We do a second check after the delay, in case it was bandaged after the first check.
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been bandaged.</span>")
|
||||
return 1
|
||||
|
||||
if(used >= available)
|
||||
to_chat(user, "<span class='warning'>You run out of [src]!</span>")
|
||||
break
|
||||
|
||||
if (W.current_stage <= W.max_bleeding_stage)
|
||||
user.visible_message("<b>\The [user]</b> cleans \a [W.desc] on [M]'s [affecting.name] and seals the edges with bioglue.", \
|
||||
"<span class='notice'>You clean and seal \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
else if (W.damage_type == BRUISE)
|
||||
user.visible_message("<b>\The [user]</b> places a medical patch over \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You place a medical patch over \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
else
|
||||
user.visible_message("<b>\The [user]</b> smears some bioglue over \a [W.desc] on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You smear some bioglue over \a [W.desc] on [M]'s [affecting.name].</span>" )
|
||||
W.bandage()
|
||||
W.disinfect()
|
||||
W.heal_damage(heal_brute)
|
||||
playsound(src, pick(apply_sounds), 25)
|
||||
used = 1 //VOREStation Edit
|
||||
update_icon() // VOREStation Edit - Support for stack icons
|
||||
affecting.update_damages()
|
||||
if(used == amount)
|
||||
if(affecting.is_bandaged())
|
||||
to_chat(user, "<span class='warning'>\The [src] is used up.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [src] is used up, but there are more wounds to treat on \the [affecting.name].</span>")
|
||||
use(used)
|
||||
|
||||
/obj/item/stack/medical/advanced/ointment
|
||||
name = "advanced burn kit"
|
||||
singular_name = "advanced burn kit"
|
||||
desc = "An advanced treatment kit for severe burns."
|
||||
icon_state = "burnkit"
|
||||
heal_burn = 7 //VOREStation Edit
|
||||
origin_tech = list(TECH_BIO = 1)
|
||||
apply_sounds = list('sound/effects/ointment.ogg')
|
||||
|
||||
/obj/item/stack/medical/advanced/ointment/attack(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
|
||||
if(affecting.open)
|
||||
to_chat(user, "<span class='notice'>The [affecting.name] is cut open, you'll need more than a bandage!</span>")
|
||||
|
||||
if(affecting.is_salved())
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>")
|
||||
return 1
|
||||
else
|
||||
user.visible_message("<b>\The [user]</b> starts salving wounds on [M]'s [affecting.name].", \
|
||||
"<span class='notice'>You start salving the wounds on [M]'s [affecting.name].</span>" )
|
||||
if(!do_mob(user, M, 10, exclusive = TRUE))
|
||||
to_chat(user, "<span class='notice'>You must stand still to salve wounds.</span>")
|
||||
return 1
|
||||
if(affecting.is_salved()) // We do a second check after the delay, in case it was bandaged after the first check.
|
||||
to_chat(user, "<span class='warning'>The wounds on [M]'s [affecting.name] have already been salved.</span>")
|
||||
return 1
|
||||
user.visible_message( "<span class='notice'>[user] covers wounds on [M]'s [affecting.name] with regenerative membrane.</span>", \
|
||||
"<span class='notice'>You cover wounds on [M]'s [affecting.name] with regenerative membrane.</span>" )
|
||||
affecting.heal_damage(0,heal_burn)
|
||||
use(1)
|
||||
affecting.salve()
|
||||
playsound(src, pick(apply_sounds), 25)
|
||||
update_icon() // VOREStation Edit - Support for stack icons
|
||||
|
||||
/obj/item/stack/medical/splint
|
||||
name = "medical splints"
|
||||
singular_name = "medical splint"
|
||||
desc = "Modular splints capable of supporting and immobilizing bones in all areas of the body."
|
||||
icon_state = "splint"
|
||||
amount = 5
|
||||
max_amount = 5
|
||||
drop_sound = 'sound/items/drop/hat.ogg'
|
||||
pickup_sound = 'sound/items/pickup/hat.ogg'
|
||||
|
||||
var/list/splintable_organs = list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO) //List of organs you can splint, natch.
|
||||
|
||||
/obj/item/stack/medical/splint/attack(mob/living/carbon/M as mob, mob/living/user as mob)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
if (istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
|
||||
var/limb = affecting.name
|
||||
if(!(affecting.organ_tag in splintable_organs))
|
||||
to_chat(user, "<span class='danger'>You can't use \the [src] to apply a splint there!</span>")
|
||||
return
|
||||
if(affecting.splinted)
|
||||
to_chat(user, "<span class='danger'>[M]'s [limb] is already splinted!</span>")
|
||||
return
|
||||
if (M != user)
|
||||
user.visible_message("<span class='danger'>[user] starts to apply \the [src] to [M]'s [limb].</span>", "<span class='danger'>You start to apply \the [src] to [M]'s [limb].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
else
|
||||
if(( !user.hand && (affecting.organ_tag in list(BP_R_ARM, BP_R_HAND)) || \
|
||||
user.hand && (affecting.organ_tag in list(BP_L_ARM, BP_L_HAND)) ))
|
||||
to_chat(user, "<span class='danger'>You can't apply a splint to the arm you're using!</span>")
|
||||
return
|
||||
user.visible_message("<span class='danger'>[user] starts to apply \the [src] to their [limb].</span>", "<span class='danger'>You start to apply \the [src] to your [limb].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
if(do_after(user, 50, M, exclusive = TASK_USER_EXCLUSIVE))
|
||||
if(affecting.splinted)
|
||||
to_chat(user, "<span class='danger'>[M]'s [limb] is already splinted!</span>")
|
||||
return
|
||||
if(M == user && prob(75))
|
||||
user.visible_message("<span class='danger'>\The [user] fumbles [src].</span>", "<span class='danger'>You fumble [src].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
return
|
||||
if(ishuman(user))
|
||||
var/obj/item/stack/medical/splint/S = split(1)
|
||||
if(S)
|
||||
if(affecting.apply_splint(S))
|
||||
S.forceMove(affecting)
|
||||
if (M != user)
|
||||
user.visible_message("<span class='danger'>\The [user] finishes applying [src] to [M]'s [limb].</span>", "<span class='danger'>You finish applying \the [src] to [M]'s [limb].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
else
|
||||
user.visible_message("<span class='danger'>\The [user] successfully applies [src] to their [limb].</span>", "<span class='danger'>You successfully apply \the [src] to your [limb].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
return
|
||||
S.dropInto(src.loc) //didn't get applied, so just drop it
|
||||
if(isrobot(user))
|
||||
var/obj/item/stack/medical/splint/B = src
|
||||
if(B)
|
||||
if(affecting.apply_splint(B))
|
||||
B.forceMove(affecting)
|
||||
user.visible_message("<span class='danger'>\The [user] finishes applying [src] to [M]'s [limb].</span>", "<span class='danger'>You finish applying \the [src] to [M]'s [limb].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
B.use(1)
|
||||
return
|
||||
user.visible_message("<span class='danger'>\The [user] fails to apply [src].</span>", "<span class='danger'>You fail to apply [src].</span>", "<span class='danger'>You hear something being wrapped.</span>")
|
||||
return
|
||||
|
||||
|
||||
/obj/item/stack/medical/splint/ghetto
|
||||
name = "makeshift splints"
|
||||
singular_name = "makeshift splint"
|
||||
desc = "For holding your limbs in place with duct tape and scrap metal."
|
||||
icon_state = "tape-splint"
|
||||
amount = 1
|
||||
splintable_organs = list(BP_L_ARM, BP_R_ARM, BP_L_LEG, BP_R_LEG)
|
||||
|
||||
@@ -1,373 +1,373 @@
|
||||
/* Diffrent misc types of tiles
|
||||
* Contains:
|
||||
* Prototype
|
||||
* Grass
|
||||
* Wood
|
||||
* Carpet
|
||||
* Blue Carpet
|
||||
* Linoleum
|
||||
*
|
||||
* Put your stuff in fifty_stacks_tiles.dm as well.
|
||||
*/
|
||||
|
||||
/obj/item/stack/tile
|
||||
name = "tile"
|
||||
singular_name = "tile"
|
||||
desc = "A non-descript floor tile"
|
||||
randpixel = 7
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
max_amount = 60
|
||||
drop_sound = 'sound/items/drop/axe.ogg'
|
||||
pickup_sound = 'sound/items/pickup/axe.ogg'
|
||||
|
||||
//crafting / welding vars
|
||||
var/datum/material/material //*sigh* i guess this is how we're doing this.
|
||||
var/craftable = FALSE //set to TRUE for tiles you can craft stuff from directly, like grass
|
||||
var/can_weld = FALSE //set to TRUE for tiles you can reforge into their components via welding, like metal
|
||||
var/welds_into = /obj/item/stack/material/steel //what you get from the welding. defaults to steel.
|
||||
var/default_type = DEFAULT_WALL_MATERIAL
|
||||
|
||||
|
||||
|
||||
/obj/item/stack/tile/Initialize()
|
||||
. = ..()
|
||||
randpixel_xy()
|
||||
if(craftable)
|
||||
material = get_material_by_name("[default_type]")
|
||||
if(!material)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
if(material) //sanity check
|
||||
recipes = material.get_recipes()
|
||||
stacktype = material.stack_type
|
||||
|
||||
/obj/item/stack/tile/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (W.has_tool_quality(TOOL_WELDER))
|
||||
var/obj/item/weapon/weldingtool/WT = W.get_welder()
|
||||
|
||||
if(can_weld == FALSE)
|
||||
to_chat("You can't reform these into their original components.")
|
||||
return
|
||||
|
||||
if(get_amount() < 4)
|
||||
to_chat(user, "<span class='warning'>You need at least four tiles to do this.</span>")
|
||||
return
|
||||
|
||||
if(WT.remove_fuel(0,user))
|
||||
new welds_into(usr.loc)
|
||||
usr.update_icon()
|
||||
visible_message("<span class='notice'>\The [src] is shaped by [user.name] with the welding tool.</span>","You hear welding.")
|
||||
var/obj/item/stack/tile/T = src
|
||||
src = null
|
||||
var/replace = (user.get_inactive_hand()==T)
|
||||
T.use(4)
|
||||
if (!T && replace)
|
||||
user.put_in_hands(welds_into)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/*
|
||||
* Grass
|
||||
*/
|
||||
/obj/item/stack/tile/grass
|
||||
name = "grass tile"
|
||||
singular_name = "grass floor tile"
|
||||
desc = "A patch of grass like they often use on golf courses."
|
||||
icon_state = "tile_grass"
|
||||
default_type = "grass"
|
||||
force = 1.0
|
||||
throwforce = 1.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
flags = 0
|
||||
origin_tech = list(TECH_BIO = 1)
|
||||
no_variants = FALSE
|
||||
drop_sound = 'sound/items/drop/herb.ogg'
|
||||
pickup_sound = 'sound/items/pickup/herb.ogg'
|
||||
craftable = TRUE
|
||||
|
||||
/*
|
||||
* Wood
|
||||
*/
|
||||
/obj/item/stack/tile/wood
|
||||
name = "wood floor tile"
|
||||
singular_name = "wood floor tile"
|
||||
desc = "An easy to fit wooden floor tile."
|
||||
icon_state = "tile-wood"
|
||||
force = 1.0
|
||||
throwforce = 1.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
flags = 0
|
||||
no_variants = FALSE
|
||||
drop_sound = 'sound/items/drop/wooden.ogg'
|
||||
pickup_sound = 'sound/items/pickup/wooden.ogg'
|
||||
|
||||
/obj/item/stack/tile/wood/sif
|
||||
name = "alien wood tile"
|
||||
singular_name = "alien wood tile"
|
||||
desc = "An easy to fit wooden floor tile. It's blue!"
|
||||
icon_state = "tile-sifwood"
|
||||
|
||||
/obj/item/stack/tile/wood/alt
|
||||
name = "wood floor tile"
|
||||
singular_name = "wood floor tile"
|
||||
icon_state = "tile-wood_tile"
|
||||
|
||||
/obj/item/stack/tile/wood/parquet
|
||||
name = "parquet wood floor tile"
|
||||
singular_name = "parquet wood floor tile"
|
||||
icon_state = "tile-wood_parquet"
|
||||
|
||||
/obj/item/stack/tile/wood/panel
|
||||
name = "large wood floor tile"
|
||||
singular_name = "large wood floor tile"
|
||||
icon_state = "tile-wood_large"
|
||||
|
||||
/obj/item/stack/tile/wood/tile
|
||||
name = "tiled wood floor tile"
|
||||
singular_name = "tiled wood floor tile"
|
||||
icon_state = "tile-wood_tile"
|
||||
|
||||
/obj/item/stack/tile/wood/cyborg
|
||||
name = "wood floor tile synthesizer"
|
||||
desc = "A device that makes wood floor tiles."
|
||||
uses_charge = 1
|
||||
charge_costs = list(250)
|
||||
stacktype = /obj/item/stack/tile/wood
|
||||
build_type = /obj/item/stack/tile/wood
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Carpets
|
||||
*/
|
||||
/obj/item/stack/tile/carpet
|
||||
name = "carpet"
|
||||
singular_name = "carpet"
|
||||
desc = "A piece of carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-carpet"
|
||||
force = 1.0
|
||||
throwforce = 1.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
flags = 0
|
||||
no_variants = FALSE
|
||||
drop_sound = 'sound/items/drop/cloth.ogg'
|
||||
pickup_sound = 'sound/items/pickup/cloth.ogg'
|
||||
|
||||
/obj/item/stack/tile/carpet/teal
|
||||
desc = "A piece of teal carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-tealcarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/turcarpet
|
||||
desc = "A piece of turqoise carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-turcarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/bcarpet
|
||||
desc = "A piece of black diamond-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-bcarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/blucarpet
|
||||
desc = "A piece of blue diamond-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-blucarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/sblucarpet
|
||||
desc = "A piece of silver-blue diamond-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-sblucarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/gaycarpet
|
||||
desc = "A piece of pink diamond-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-gaycarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/purcarpet
|
||||
desc = "A piece of purple diamond-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-purcarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/oracarpet
|
||||
desc = "A piece of orange diamond-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-oracarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/brncarpet
|
||||
desc = "A piece of brown ornate-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-brncarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/blucarpet2
|
||||
desc = "A piece of blue ornate-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-blucarpet2"
|
||||
|
||||
/obj/item/stack/tile/carpet/greencarpet
|
||||
desc = "A piece of green ornate-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-greencarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/purplecarpet
|
||||
desc = "A piece of purple ornate-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-purplecarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/geo
|
||||
icon_state = "tile-carpet-deco"
|
||||
desc = "A piece of carpet with a gnarly geometric design. It is the same size as a normal floor tile!"
|
||||
|
||||
/obj/item/stack/tile/carpet/retro
|
||||
icon_state = "tile-carpet-retro"
|
||||
desc = "A piece of carpet with totally wicked blue space patterns. It is the same size as a normal floor tile!"
|
||||
|
||||
/obj/item/stack/tile/carpet/retro_red
|
||||
icon_state = "tile-carpet-retro-red"
|
||||
desc = "A piece of carpet with red-ical space patterns. It is the same size as a normal floor tile!"
|
||||
|
||||
/obj/item/stack/tile/carpet/happy
|
||||
icon_state = "tile-carpet-happy"
|
||||
desc = "A piece of carpet with happy patterns. It is the same size as a normal floor tile!"
|
||||
|
||||
/obj/item/stack/tile/floor
|
||||
name = "floor tile"
|
||||
singular_name = "floor tile"
|
||||
desc = "A metal tile fit for covering a section of floor."
|
||||
icon_state = "tile"
|
||||
force = 6.0
|
||||
matter = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT / 4)
|
||||
throwforce = 15.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
no_variants = FALSE
|
||||
can_weld = TRUE
|
||||
|
||||
/obj/item/stack/tile/floor/red
|
||||
name = "red floor tile"
|
||||
singular_name = "red floor tile"
|
||||
color = COLOR_RED_GRAY
|
||||
icon_state = "tile_white"
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/techgrey
|
||||
name = "grey techfloor tile"
|
||||
singular_name = "grey techfloor tile"
|
||||
icon_state = "techtile_grey"
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/techgrid
|
||||
name = "grid techfloor tile"
|
||||
singular_name = "grid techfloor tile"
|
||||
icon_state = "techtile_grid"
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/techmaint
|
||||
name = "maint techfloor tile"
|
||||
singular_name = "maint techfloor tile"
|
||||
icon_state = "techtile_maint"
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/steel_dirty
|
||||
name = "steel floor tile"
|
||||
singular_name = "steel floor tile"
|
||||
icon_state = "tile_steel"
|
||||
matter = list(MAT_PLASTEEL = SHEET_MATERIAL_AMOUNT / 4)
|
||||
welds_into = /obj/item/stack/material/plasteel
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/steel
|
||||
name = "steel floor tile"
|
||||
singular_name = "steel floor tile"
|
||||
icon_state = "tile_steel"
|
||||
matter = list(MAT_PLASTEEL = SHEET_MATERIAL_AMOUNT / 4)
|
||||
welds_into = /obj/item/stack/material/plasteel
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/white
|
||||
name = "white floor tile"
|
||||
singular_name = "white floor tile"
|
||||
icon_state = "tile_white"
|
||||
matter = list(MAT_PLASTIC = SHEET_MATERIAL_AMOUNT / 4)
|
||||
welds_into = /obj/item/stack/material/plastic
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/yellow
|
||||
name = "yellow floor tile"
|
||||
singular_name = "yellow floor tile"
|
||||
color = COLOR_BROWN
|
||||
icon_state = "tile_white"
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/dark
|
||||
name = "dark floor tile"
|
||||
singular_name = "dark floor tile"
|
||||
icon_state = "tile_steel"
|
||||
matter = list(MAT_PLASTEEL = SHEET_MATERIAL_AMOUNT / 4)
|
||||
welds_into = /obj/item/stack/material/plasteel
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/freezer
|
||||
name = "freezer floor tile"
|
||||
singular_name = "freezer floor tile"
|
||||
icon_state = "tile_freezer"
|
||||
matter = list(MAT_PLASTIC = SHEET_MATERIAL_AMOUNT / 4)
|
||||
welds_into = /obj/item/stack/material/plastic
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/cyborg
|
||||
name = "floor tile synthesizer"
|
||||
desc = "A device that makes floor tiles."
|
||||
gender = NEUTER
|
||||
matter = null
|
||||
uses_charge = 1
|
||||
charge_costs = list(250)
|
||||
stacktype = /obj/item/stack/tile/floor
|
||||
build_type = /obj/item/stack/tile/floor
|
||||
can_weld = FALSE //we're not going there
|
||||
|
||||
/obj/item/stack/tile/linoleum
|
||||
name = "linoleum"
|
||||
singular_name = "linoleum"
|
||||
desc = "A piece of linoleum. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-linoleum"
|
||||
force = 1.0
|
||||
throwforce = 1.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
flags = 0
|
||||
no_variants = FALSE
|
||||
can_weld = FALSE
|
||||
|
||||
/obj/item/stack/tile/wmarble
|
||||
name = "light marble tile"
|
||||
singular_name = "light marble tile"
|
||||
desc = "Some white marble tiles used for flooring."
|
||||
icon_state = "tile-wmarble"
|
||||
force = 6.0
|
||||
throwforce = 15.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
flags = 0
|
||||
no_variants = FALSE
|
||||
can_weld = TRUE
|
||||
welds_into = /obj/item/stack/material/marble
|
||||
|
||||
/obj/item/stack/tile/bmarble
|
||||
name = "dark marble tile"
|
||||
singular_name = "dark marble tile"
|
||||
desc = "Some black marble tiles used for flooring."
|
||||
icon_state = "tile-bmarble"
|
||||
force = 6.0
|
||||
throwforce = 15.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
flags = 0
|
||||
no_variants = FALSE
|
||||
can_weld = TRUE
|
||||
welds_into = /obj/item/stack/material/marble
|
||||
|
||||
/obj/item/stack/tile/roofing
|
||||
name = "roofing"
|
||||
singular_name = "roofing"
|
||||
desc = "A section of roofing material. You can use it to repair the ceiling, or expand it."
|
||||
icon_state = "techtile_grid"
|
||||
can_weld = FALSE //roofing can also be made from wood, so let's not open that can of worms today
|
||||
|
||||
/obj/item/stack/tile/roofing/cyborg
|
||||
name = "roofing synthesizer"
|
||||
desc = "A device that makes roofing tiles."
|
||||
uses_charge = 1
|
||||
charge_costs = list(250)
|
||||
stacktype = /obj/item/stack/tile/roofing
|
||||
build_type = /obj/item/stack/tile/roofing
|
||||
can_weld = FALSE
|
||||
/* Diffrent misc types of tiles
|
||||
* Contains:
|
||||
* Prototype
|
||||
* Grass
|
||||
* Wood
|
||||
* Carpet
|
||||
* Blue Carpet
|
||||
* Linoleum
|
||||
*
|
||||
* Put your stuff in fifty_stacks_tiles.dm as well.
|
||||
*/
|
||||
|
||||
/obj/item/stack/tile
|
||||
name = "tile"
|
||||
singular_name = "tile"
|
||||
desc = "A non-descript floor tile"
|
||||
randpixel = 7
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
max_amount = 60
|
||||
drop_sound = 'sound/items/drop/axe.ogg'
|
||||
pickup_sound = 'sound/items/pickup/axe.ogg'
|
||||
|
||||
//crafting / welding vars
|
||||
var/datum/material/material //*sigh* i guess this is how we're doing this.
|
||||
var/craftable = FALSE //set to TRUE for tiles you can craft stuff from directly, like grass
|
||||
var/can_weld = FALSE //set to TRUE for tiles you can reforge into their components via welding, like metal
|
||||
var/welds_into = /obj/item/stack/material/steel //what you get from the welding. defaults to steel.
|
||||
var/default_type = DEFAULT_WALL_MATERIAL
|
||||
|
||||
|
||||
|
||||
/obj/item/stack/tile/Initialize()
|
||||
. = ..()
|
||||
randpixel_xy()
|
||||
if(craftable)
|
||||
material = get_material_by_name("[default_type]")
|
||||
if(!material)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
if(material) //sanity check
|
||||
recipes = material.get_recipes()
|
||||
stacktype = material.stack_type
|
||||
|
||||
/obj/item/stack/tile/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (W.has_tool_quality(TOOL_WELDER))
|
||||
var/obj/item/weapon/weldingtool/WT = W.get_welder()
|
||||
|
||||
if(can_weld == FALSE)
|
||||
to_chat("You can't reform these into their original components.")
|
||||
return
|
||||
|
||||
if(get_amount() < 4)
|
||||
to_chat(user, "<span class='warning'>You need at least four tiles to do this.</span>")
|
||||
return
|
||||
|
||||
if(WT.remove_fuel(0,user))
|
||||
new welds_into(usr.loc)
|
||||
usr.update_icon()
|
||||
visible_message("<span class='notice'>\The [src] is shaped by [user.name] with the welding tool.</span>","You hear welding.")
|
||||
var/obj/item/stack/tile/T = src
|
||||
src = null
|
||||
var/replace = (user.get_inactive_hand()==T)
|
||||
T.use(4)
|
||||
if (!T && replace)
|
||||
user.put_in_hands(welds_into)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/*
|
||||
* Grass
|
||||
*/
|
||||
/obj/item/stack/tile/grass
|
||||
name = "grass tile"
|
||||
singular_name = "grass floor tile"
|
||||
desc = "A patch of grass like they often use on golf courses."
|
||||
icon_state = "tile_grass"
|
||||
default_type = "grass"
|
||||
force = 1.0
|
||||
throwforce = 1.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
flags = 0
|
||||
origin_tech = list(TECH_BIO = 1)
|
||||
no_variants = FALSE
|
||||
drop_sound = 'sound/items/drop/herb.ogg'
|
||||
pickup_sound = 'sound/items/pickup/herb.ogg'
|
||||
craftable = TRUE
|
||||
|
||||
/*
|
||||
* Wood
|
||||
*/
|
||||
/obj/item/stack/tile/wood
|
||||
name = "wood floor tile"
|
||||
singular_name = "wood floor tile"
|
||||
desc = "An easy to fit wooden floor tile."
|
||||
icon_state = "tile-wood"
|
||||
force = 1.0
|
||||
throwforce = 1.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
flags = 0
|
||||
no_variants = FALSE
|
||||
drop_sound = 'sound/items/drop/wooden.ogg'
|
||||
pickup_sound = 'sound/items/pickup/wooden.ogg'
|
||||
|
||||
/obj/item/stack/tile/wood/sif
|
||||
name = "alien wood tile"
|
||||
singular_name = "alien wood tile"
|
||||
desc = "An easy to fit wooden floor tile. It's blue!"
|
||||
icon_state = "tile-sifwood"
|
||||
|
||||
/obj/item/stack/tile/wood/alt
|
||||
name = "wood floor tile"
|
||||
singular_name = "wood floor tile"
|
||||
icon_state = "tile-wood_tile"
|
||||
|
||||
/obj/item/stack/tile/wood/parquet
|
||||
name = "parquet wood floor tile"
|
||||
singular_name = "parquet wood floor tile"
|
||||
icon_state = "tile-wood_parquet"
|
||||
|
||||
/obj/item/stack/tile/wood/panel
|
||||
name = "large wood floor tile"
|
||||
singular_name = "large wood floor tile"
|
||||
icon_state = "tile-wood_large"
|
||||
|
||||
/obj/item/stack/tile/wood/tile
|
||||
name = "tiled wood floor tile"
|
||||
singular_name = "tiled wood floor tile"
|
||||
icon_state = "tile-wood_tile"
|
||||
|
||||
/obj/item/stack/tile/wood/cyborg
|
||||
name = "wood floor tile synthesizer"
|
||||
desc = "A device that makes wood floor tiles."
|
||||
uses_charge = 1
|
||||
charge_costs = list(250)
|
||||
stacktype = /obj/item/stack/tile/wood
|
||||
build_type = /obj/item/stack/tile/wood
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Carpets
|
||||
*/
|
||||
/obj/item/stack/tile/carpet
|
||||
name = "carpet"
|
||||
singular_name = "carpet"
|
||||
desc = "A piece of carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-carpet"
|
||||
force = 1.0
|
||||
throwforce = 1.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
flags = 0
|
||||
no_variants = FALSE
|
||||
drop_sound = 'sound/items/drop/cloth.ogg'
|
||||
pickup_sound = 'sound/items/pickup/cloth.ogg'
|
||||
|
||||
/obj/item/stack/tile/carpet/teal
|
||||
desc = "A piece of teal carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-tealcarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/turcarpet
|
||||
desc = "A piece of turqoise carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-turcarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/bcarpet
|
||||
desc = "A piece of black diamond-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-bcarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/blucarpet
|
||||
desc = "A piece of blue diamond-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-blucarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/sblucarpet
|
||||
desc = "A piece of silver-blue diamond-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-sblucarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/gaycarpet
|
||||
desc = "A piece of pink diamond-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-gaycarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/purcarpet
|
||||
desc = "A piece of purple diamond-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-purcarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/oracarpet
|
||||
desc = "A piece of orange diamond-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-oracarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/brncarpet
|
||||
desc = "A piece of brown ornate-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-brncarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/blucarpet2
|
||||
desc = "A piece of blue ornate-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-blucarpet2"
|
||||
|
||||
/obj/item/stack/tile/carpet/greencarpet
|
||||
desc = "A piece of green ornate-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-greencarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/purplecarpet
|
||||
desc = "A piece of purple ornate-pattern carpet. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-purplecarpet"
|
||||
|
||||
/obj/item/stack/tile/carpet/geo
|
||||
icon_state = "tile-carpet-deco"
|
||||
desc = "A piece of carpet with a gnarly geometric design. It is the same size as a normal floor tile!"
|
||||
|
||||
/obj/item/stack/tile/carpet/retro
|
||||
icon_state = "tile-carpet-retro"
|
||||
desc = "A piece of carpet with totally wicked blue space patterns. It is the same size as a normal floor tile!"
|
||||
|
||||
/obj/item/stack/tile/carpet/retro_red
|
||||
icon_state = "tile-carpet-retro-red"
|
||||
desc = "A piece of carpet with red-ical space patterns. It is the same size as a normal floor tile!"
|
||||
|
||||
/obj/item/stack/tile/carpet/happy
|
||||
icon_state = "tile-carpet-happy"
|
||||
desc = "A piece of carpet with happy patterns. It is the same size as a normal floor tile!"
|
||||
|
||||
/obj/item/stack/tile/floor
|
||||
name = "floor tile"
|
||||
singular_name = "floor tile"
|
||||
desc = "A metal tile fit for covering a section of floor."
|
||||
icon_state = "tile"
|
||||
force = 6.0
|
||||
matter = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT / 4)
|
||||
throwforce = 15.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
no_variants = FALSE
|
||||
can_weld = TRUE
|
||||
|
||||
/obj/item/stack/tile/floor/red
|
||||
name = "red floor tile"
|
||||
singular_name = "red floor tile"
|
||||
color = COLOR_RED_GRAY
|
||||
icon_state = "tile_white"
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/techgrey
|
||||
name = "grey techfloor tile"
|
||||
singular_name = "grey techfloor tile"
|
||||
icon_state = "techtile_grey"
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/techgrid
|
||||
name = "grid techfloor tile"
|
||||
singular_name = "grid techfloor tile"
|
||||
icon_state = "techtile_grid"
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/techmaint
|
||||
name = "maint techfloor tile"
|
||||
singular_name = "maint techfloor tile"
|
||||
icon_state = "techtile_maint"
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/steel_dirty
|
||||
name = "steel floor tile"
|
||||
singular_name = "steel floor tile"
|
||||
icon_state = "tile_steel"
|
||||
matter = list(MAT_PLASTEEL = SHEET_MATERIAL_AMOUNT / 4)
|
||||
welds_into = /obj/item/stack/material/plasteel
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/steel
|
||||
name = "steel floor tile"
|
||||
singular_name = "steel floor tile"
|
||||
icon_state = "tile_steel"
|
||||
matter = list(MAT_PLASTEEL = SHEET_MATERIAL_AMOUNT / 4)
|
||||
welds_into = /obj/item/stack/material/plasteel
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/white
|
||||
name = "white floor tile"
|
||||
singular_name = "white floor tile"
|
||||
icon_state = "tile_white"
|
||||
matter = list(MAT_PLASTIC = SHEET_MATERIAL_AMOUNT / 4)
|
||||
welds_into = /obj/item/stack/material/plastic
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/yellow
|
||||
name = "yellow floor tile"
|
||||
singular_name = "yellow floor tile"
|
||||
color = COLOR_BROWN
|
||||
icon_state = "tile_white"
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/dark
|
||||
name = "dark floor tile"
|
||||
singular_name = "dark floor tile"
|
||||
icon_state = "tile_steel"
|
||||
matter = list(MAT_PLASTEEL = SHEET_MATERIAL_AMOUNT / 4)
|
||||
welds_into = /obj/item/stack/material/plasteel
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/freezer
|
||||
name = "freezer floor tile"
|
||||
singular_name = "freezer floor tile"
|
||||
icon_state = "tile_freezer"
|
||||
matter = list(MAT_PLASTIC = SHEET_MATERIAL_AMOUNT / 4)
|
||||
welds_into = /obj/item/stack/material/plastic
|
||||
no_variants = FALSE
|
||||
|
||||
/obj/item/stack/tile/floor/cyborg
|
||||
name = "floor tile synthesizer"
|
||||
desc = "A device that makes floor tiles."
|
||||
gender = NEUTER
|
||||
matter = null
|
||||
uses_charge = 1
|
||||
charge_costs = list(250)
|
||||
stacktype = /obj/item/stack/tile/floor
|
||||
build_type = /obj/item/stack/tile/floor
|
||||
can_weld = FALSE //we're not going there
|
||||
|
||||
/obj/item/stack/tile/linoleum
|
||||
name = "linoleum"
|
||||
singular_name = "linoleum"
|
||||
desc = "A piece of linoleum. It is the same size as a normal floor tile!"
|
||||
icon_state = "tile-linoleum"
|
||||
force = 1.0
|
||||
throwforce = 1.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
flags = 0
|
||||
no_variants = FALSE
|
||||
can_weld = FALSE
|
||||
|
||||
/obj/item/stack/tile/wmarble
|
||||
name = "light marble tile"
|
||||
singular_name = "light marble tile"
|
||||
desc = "Some white marble tiles used for flooring."
|
||||
icon_state = "tile-wmarble"
|
||||
force = 6.0
|
||||
throwforce = 15.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
flags = 0
|
||||
no_variants = FALSE
|
||||
can_weld = TRUE
|
||||
welds_into = /obj/item/stack/material/marble
|
||||
|
||||
/obj/item/stack/tile/bmarble
|
||||
name = "dark marble tile"
|
||||
singular_name = "dark marble tile"
|
||||
desc = "Some black marble tiles used for flooring."
|
||||
icon_state = "tile-bmarble"
|
||||
force = 6.0
|
||||
throwforce = 15.0
|
||||
throw_speed = 5
|
||||
throw_range = 20
|
||||
flags = 0
|
||||
no_variants = FALSE
|
||||
can_weld = TRUE
|
||||
welds_into = /obj/item/stack/material/marble
|
||||
|
||||
/obj/item/stack/tile/roofing
|
||||
name = "roofing"
|
||||
singular_name = "roofing"
|
||||
desc = "A section of roofing material. You can use it to repair the ceiling, or expand it."
|
||||
icon_state = "techtile_grid"
|
||||
can_weld = FALSE //roofing can also be made from wood, so let's not open that can of worms today
|
||||
|
||||
/obj/item/stack/tile/roofing/cyborg
|
||||
name = "roofing synthesizer"
|
||||
desc = "A device that makes roofing tiles."
|
||||
uses_charge = 1
|
||||
charge_costs = list(250)
|
||||
stacktype = /obj/item/stack/tile/roofing
|
||||
build_type = /obj/item/stack/tile/roofing
|
||||
can_weld = FALSE
|
||||
|
||||
+490
-490
@@ -1,491 +1,491 @@
|
||||
//Items labled as 'trash' for the trash bag.
|
||||
//TODO: Make this an item var or something...
|
||||
|
||||
//Added by Jack Rost
|
||||
/obj/item/trash
|
||||
icon = 'icons/obj/trash.dmi'
|
||||
w_class = ITEMSIZE_SMALL
|
||||
desc = "This is rubbish."
|
||||
drop_sound = 'sound/items/drop/wrapper.ogg'
|
||||
pickup_sound = 'sound/items/pickup/wrapper.ogg'
|
||||
matter = list(MAT_STEEL = 30)
|
||||
var/age = 0
|
||||
|
||||
/obj/item/trash/New(var/newloc, var/_age)
|
||||
..(newloc)
|
||||
if(!isnull(_age))
|
||||
age = _age
|
||||
|
||||
/obj/item/trash/Initialize(mapload)
|
||||
if(!mapload || !config.persistence_ignore_mapload)
|
||||
SSpersistence.track_value(src, /datum/persistent/filth/trash)
|
||||
. = ..()
|
||||
|
||||
/obj/item/trash/Destroy()
|
||||
SSpersistence.forget_value(src, /datum/persistent/filth/trash)
|
||||
. = ..()
|
||||
|
||||
/obj/item/trash/raisins
|
||||
name = "\improper 4no raisins"
|
||||
icon_state = "4no_raisins"
|
||||
|
||||
/obj/item/trash/candy
|
||||
name = "hard candy wrapper"
|
||||
icon_state = "candy"
|
||||
|
||||
/obj/item/trash/candy/gums
|
||||
name = "gummy candy bag"
|
||||
icon_state = "candy_gums"
|
||||
|
||||
/obj/item/trash/candy/proteinbar
|
||||
name = "protein bar wrapper"
|
||||
icon_state = "proteinbar"
|
||||
|
||||
/obj/item/trash/candy/fruitbar
|
||||
name = "fruit bar wrapper"
|
||||
icon_state = "fruitbar"
|
||||
|
||||
/obj/item/trash/cheesie
|
||||
name = "\improper Cheesie Honkers bag"
|
||||
icon_state = "cheesie_honkers"
|
||||
|
||||
/obj/item/trash/chips
|
||||
name = "chips bag"
|
||||
icon_state = "chips"
|
||||
|
||||
/obj/item/trash/chips/bbq
|
||||
name = "bbq chips bag"
|
||||
icon_state = "chips_bbq"
|
||||
|
||||
/obj/item/trash/chips/snv
|
||||
name = "salt & vinegar chips bag"
|
||||
icon_state = "chips_snv"
|
||||
|
||||
/obj/item/trash/cookiesnack
|
||||
name = "\improper Carps Ahoy! miniature cookies packet"
|
||||
icon_state = "cookiesnack"
|
||||
|
||||
/obj/item/trash/popcorn
|
||||
name = "popcorn bag"
|
||||
icon_state = "popcorn"
|
||||
|
||||
/obj/item/trash/tuna
|
||||
name = "fish flake packet"
|
||||
icon_state = "tuna"
|
||||
|
||||
/obj/item/trash/sosjerky
|
||||
name = "Scaredy's Private Reserve Beef Jerky wrapper"
|
||||
icon_state = "sosjerky"
|
||||
|
||||
/obj/item/trash/unajerky
|
||||
name = "Moghes Imported Sissalik Jerky tin"
|
||||
icon_state = "unathitinred"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/syndi_cakes
|
||||
name = "syndi cakes box"
|
||||
icon_state = "syndi_cakes"
|
||||
|
||||
/obj/item/trash/waffles
|
||||
name = "waffles tray"
|
||||
icon_state = "waffles"
|
||||
|
||||
/obj/item/trash/plate
|
||||
name = "plate"
|
||||
icon_state = "plate"
|
||||
drop_sound = 'sound/items/drop/food.ogg'
|
||||
pickup_sound = 'sound/items/pickup/food.ogg'
|
||||
|
||||
/obj/item/trash/asian_bowl
|
||||
name = "asian bowl"
|
||||
icon_state = "asian_bowl"
|
||||
drop_sound = 'sound/items/drop/food.ogg'
|
||||
pickup_sound = 'sound/items/pickup/food.ogg'
|
||||
|
||||
/obj/item/trash/snack_bowl
|
||||
name = "snack bowl"
|
||||
icon_state = "snack_bowl"
|
||||
drop_sound = 'sound/items/drop/food.ogg'
|
||||
pickup_sound = 'sound/items/pickup/food.ogg'
|
||||
|
||||
/obj/item/trash/small_bowl
|
||||
name = "small bowl"
|
||||
icon_state = "small_bowl"
|
||||
drop_sound = 'sound/items/drop/food.ogg'
|
||||
pickup_sound = 'sound/items/pickup/food.ogg'
|
||||
|
||||
/obj/item/trash/pistachios
|
||||
name = "pistachios packet"
|
||||
icon_state = "pistachios_pack"
|
||||
|
||||
/obj/item/trash/semki
|
||||
name = "semki packet"
|
||||
icon_state = "semki_pack"
|
||||
|
||||
/obj/item/trash/koisbar
|
||||
name = "candy wrapper"
|
||||
icon_state = "koisbar"
|
||||
|
||||
/obj/item/trash/kokobar
|
||||
name = "candy wrapper"
|
||||
icon_state = "kokobar"
|
||||
|
||||
/obj/item/trash/skrellsnax
|
||||
name = "skrellsnax packet"
|
||||
icon_state = "skrellsnacks"
|
||||
|
||||
/obj/item/trash/gumpack
|
||||
name = "gum packet"
|
||||
icon_state = "gum_pack"
|
||||
|
||||
/obj/item/trash/admints
|
||||
name = "mint wrapper"
|
||||
icon_state = "admint_pack"
|
||||
|
||||
/obj/item/trash/coffee
|
||||
name = "empty cup"
|
||||
icon_state = "coffee_vended"
|
||||
drop_sound = 'sound/items/drop/papercup.ogg'
|
||||
pickup_sound = 'sound/items/pickup/papercup.ogg'
|
||||
|
||||
/obj/item/trash/ramen
|
||||
name = "cup ramen"
|
||||
icon_state = "ramen"
|
||||
drop_sound = 'sound/items/drop/papercup.ogg'
|
||||
pickup_sound = 'sound/items/pickup/papercup.ogg'
|
||||
|
||||
/obj/item/trash/tray
|
||||
name = "tray"
|
||||
icon_state = "tray"
|
||||
drop_sound = 'sound/items/trayhit1.ogg'
|
||||
|
||||
/obj/item/trash/candle
|
||||
name = "candle"
|
||||
icon = 'icons/obj/candle.dmi'
|
||||
icon_state = "candle4"
|
||||
drop_sound = 'sound/items/drop/gloves.ogg'
|
||||
pickup_sound = 'sound/items/pickup/gloves.ogg'
|
||||
|
||||
/obj/item/trash/liquidfood
|
||||
name = "\improper \"LiquidFood\" ration packet"
|
||||
icon_state = "liquidfood"
|
||||
|
||||
/obj/item/trash/liquidprotein
|
||||
name = "\improper \"LiquidProtein\" ration packet"
|
||||
icon_state = "liquidprotein"
|
||||
|
||||
/obj/item/trash/liquidvitamin
|
||||
name = "\improper \"VitaPaste\" ration packet"
|
||||
icon_state = "liquidvitamin"
|
||||
|
||||
/obj/item/trash/tastybread
|
||||
name = "bread tube wrapper"
|
||||
icon_state = "tastybread"
|
||||
|
||||
// Aurora Food Port
|
||||
/obj/item/trash/brownies
|
||||
name = "brownie tray"
|
||||
icon_state = "brownies"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/snacktray
|
||||
name = "snacktray"
|
||||
icon_state = "snacktray"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/dipbowl
|
||||
name = "dip bowl"
|
||||
icon_state = "dipbowl"
|
||||
drop_sound = 'sound/items/drop/food.ogg'
|
||||
pickup_sound = 'sound/items/pickup/food.ogg'
|
||||
|
||||
/obj/item/trash/chipbasket
|
||||
name = "empty chip basket"
|
||||
icon_state = "chipbasket_empty"
|
||||
drop_sound = 'sound/items/drop/food.ogg'
|
||||
pickup_sound = 'sound/items/pickup/food.ogg'
|
||||
|
||||
/obj/item/trash/spitgum
|
||||
name = "old gum"
|
||||
desc = "A disgusting chewed up wad of gum."
|
||||
icon = 'icons/inventory/face/item.dmi'
|
||||
icon_state = "spit-gum"
|
||||
drop_sound = 'sound/items/drop/flesh.ogg'
|
||||
pickup_sound = 'sound/items/pickup/flesh.ogg'
|
||||
|
||||
/obj/item/trash/lollibutt
|
||||
name = "lollipop stick"
|
||||
desc = "A lollipop stick devoid of pop."
|
||||
icon = 'icons/inventory/face/item.dmi'
|
||||
icon_state = "pop-stick"
|
||||
drop_sound = 'sound/items/drop/component.ogg'
|
||||
pickup_sound = 'sound/items/pickup/component.ogg'
|
||||
|
||||
/obj/item/trash/spitwad
|
||||
name = "spit wad"
|
||||
desc = "A disgusting spitwad."
|
||||
icon = 'icons/inventory/face/item.dmi'
|
||||
icon_state = "spit-chew"
|
||||
drop_sound = 'sound/items/drop/flesh.ogg'
|
||||
pickup_sound = 'sound/items/pickup/flesh.ogg'
|
||||
slot_flags = SLOT_EARS | SLOT_MASK
|
||||
|
||||
/obj/item/trash/attack(mob/M as mob, mob/living/user as mob)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/trash/beef
|
||||
name = "empty beef can"
|
||||
icon_state = "beef"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/beans
|
||||
name = "empty bean can"
|
||||
icon_state = "beans"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/tomato
|
||||
name = "empty tomato soup can"
|
||||
icon_state = "tomato"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/spinach
|
||||
name = "empty spinach can"
|
||||
icon_state = "spinach"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/fishegg
|
||||
name = "empty fisheggs can"
|
||||
icon_state = "fisheggs"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/carpegg
|
||||
name = "empty carpeggs can"
|
||||
icon_state = "carpeggs"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/ntbeans
|
||||
name = "empty baked bean can"
|
||||
icon_state = "ntbeans"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/salo
|
||||
name = "salo pack"
|
||||
icon_state = "pigfat"
|
||||
|
||||
/obj/item/trash/croutons
|
||||
name = "suhariki pack"
|
||||
icon_state = "croutons"
|
||||
|
||||
/obj/item/trash/squid
|
||||
name = "calamari pack"
|
||||
icon_state = "squid"
|
||||
|
||||
/obj/item/trash/driedfish
|
||||
name = "vobla pack"
|
||||
icon_state = "driedfish"
|
||||
|
||||
/obj/item/trash/lunacakewrap
|
||||
name = "cake wrapper"
|
||||
icon_state = "cakewrap"
|
||||
|
||||
/obj/item/trash/mochicakewrap
|
||||
name = "cake wrapper"
|
||||
icon_state = "mochicakewrap"
|
||||
|
||||
/obj/item/trash/mooncakewrap
|
||||
name = "cake wrapper"
|
||||
icon_state = "mooncakewrap"
|
||||
|
||||
/obj/item/trash/tidegobs
|
||||
name = "tide gob bag"
|
||||
icon_state = "tidegobs"
|
||||
|
||||
/obj/item/trash/saturno
|
||||
name = "\improper saturn-Os bag"
|
||||
icon_state = "saturn0s"
|
||||
|
||||
/obj/item/trash/jupiter
|
||||
name = "gello cup"
|
||||
icon_state = "jupiter"
|
||||
|
||||
/obj/item/trash/pluto
|
||||
name = "rod bag"
|
||||
icon_state = "pluto"
|
||||
|
||||
/obj/item/trash/venus
|
||||
name = "hot cakes bag"
|
||||
icon_state = "venus"
|
||||
|
||||
/obj/item/trash/mars
|
||||
name = "frouka box"
|
||||
icon_state = "mars"
|
||||
|
||||
/obj/item/trash/oort
|
||||
name = "oort rock bag"
|
||||
icon_state = "oort"
|
||||
|
||||
/obj/item/trash/weebonuts
|
||||
name = "red alert nuts bag"
|
||||
icon_state = "weebonuts"
|
||||
|
||||
/obj/item/trash/stick
|
||||
name = "stick"
|
||||
desc = "a stick from some snack or other food item, not even useful as crafting material."
|
||||
icon_state = "stick"
|
||||
|
||||
/obj/item/trash/maps
|
||||
name = "empty MAPS can"
|
||||
icon_state = "maps"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/spacer_cake_wrap
|
||||
name = "snack cake wrapper"
|
||||
icon_state = "spacercake_wrap"
|
||||
|
||||
/obj/item/trash/sun_snax
|
||||
name = "sun snax bag"
|
||||
icon_state = "sun_snax"
|
||||
|
||||
/obj/item/trash/wasabi_peas
|
||||
name = "wasabi peas bag"
|
||||
icon_state = "wasabi_peas"
|
||||
|
||||
/obj/item/trash/namagashi
|
||||
name = "namagashi bag"
|
||||
icon_state = "namagashi"
|
||||
|
||||
/obj/item/trash/pocky
|
||||
name = "pocky bag"
|
||||
icon_state = "pocky"
|
||||
|
||||
/obj/item/trash/appleberry
|
||||
name = "appleberry can"
|
||||
icon_state = "appleberry"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/hakarl
|
||||
name = "\improper Indigo Co. Hákarl bag"
|
||||
icon_state = "hakarl"
|
||||
|
||||
/obj/item/trash/pretzel
|
||||
name = "\improper Value Pretzel Snack"
|
||||
icon_state = "pretzel"
|
||||
|
||||
/obj/item/trash/sweetration
|
||||
name = "desert ration bag"
|
||||
icon_state = "baseration"
|
||||
|
||||
/obj/item/trash/genration
|
||||
name = "generic ration bag"
|
||||
icon_state = "genration"
|
||||
|
||||
/obj/item/trash/meatration
|
||||
name = "meat ration bag"
|
||||
icon_state = "meatration"
|
||||
|
||||
/obj/item/trash/vegration
|
||||
name = "veggie ration bag"
|
||||
icon_state = "vegration"
|
||||
|
||||
/obj/item/trash/tgmc_mre
|
||||
name = "\improper CRS ration bag"
|
||||
icon_state = "tgmc_mre_trash"
|
||||
|
||||
/obj/item/trash/smolburger
|
||||
name = "burger packaging"
|
||||
icon_state = "smolburger"
|
||||
|
||||
/obj/item/trash/smolhotdog
|
||||
name = "hotdog packaging"
|
||||
icon_state = "smolhotdog"
|
||||
|
||||
/obj/item/trash/smolburrito
|
||||
name = "burrito packaging"
|
||||
icon_state = "smolburrito"
|
||||
|
||||
/obj/item/trash/candybowl
|
||||
name = "candy bowl"
|
||||
icon_state = "candy_bowl"
|
||||
|
||||
/obj/item/trash/brainzsnax
|
||||
name = "\improper BrainzSnax can"
|
||||
icon_state = "brainzsnax"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/brainzsnaxred
|
||||
name = "\improper BrainzSnax RED can"
|
||||
icon_state = "brainzsnaxred"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
|
||||
/obj/item/trash/pasty
|
||||
name = "pasty packaging"
|
||||
icon_state = "pasty"
|
||||
|
||||
/obj/item/trash/sausageroll
|
||||
name = "sausage roll packaging"
|
||||
icon_state = "sausageroll"
|
||||
|
||||
/obj/item/trash/scotchegg
|
||||
name = "scotch egg packaging"
|
||||
icon_state = "scotchegg"
|
||||
|
||||
/obj/item/trash/porkpie
|
||||
name = "pork pie packaging"
|
||||
icon_state = "porkpie"
|
||||
|
||||
//Candy Bars (1-10)
|
||||
/obj/item/trash/candy/cb01
|
||||
name = "\improper Tau Ceti Bar wrapper"
|
||||
icon_state = "cb01"
|
||||
|
||||
/obj/item/trash/candy/cb02
|
||||
name = "\improper Hundred-Thousand Thaler Bar wrapper"
|
||||
icon_state = "cb02"
|
||||
|
||||
/obj/item/trash/candy/cb03
|
||||
name = "\improper Lars' Saltlakris wrapper"
|
||||
icon_state = "cb03"
|
||||
|
||||
/obj/item/trash/candy/cb04
|
||||
name = "\improper Aerostat Bar wrapper"
|
||||
icon_state = "cb04"
|
||||
|
||||
/obj/item/trash/candy/cb05
|
||||
name = "\improper Andromeda Bar wrapper"
|
||||
icon_state = "cb05"
|
||||
|
||||
/obj/item/trash/candy/cb06
|
||||
name = "\improper Mocha Crunch wrapper"
|
||||
icon_state = "cb06"
|
||||
|
||||
/obj/item/trash/candy/cb07
|
||||
name = "\improper TaroMilk Bar wrapper"
|
||||
icon_state = "cb07"
|
||||
|
||||
/obj/item/trash/candy/cb08
|
||||
name = "\improper Cronk Bar wrapper"
|
||||
icon_state = "cb08"
|
||||
|
||||
/obj/item/trash/candy/cb09
|
||||
name = "\improper Kaju Mamma! Bar wrapper"
|
||||
icon_state = "cb09"
|
||||
|
||||
/obj/item/trash/candy/cb10
|
||||
name = "\improper Shantak Bar wrapper"
|
||||
//Items labled as 'trash' for the trash bag.
|
||||
//TODO: Make this an item var or something...
|
||||
|
||||
//Added by Jack Rost
|
||||
/obj/item/trash
|
||||
icon = 'icons/obj/trash.dmi'
|
||||
w_class = ITEMSIZE_SMALL
|
||||
desc = "This is rubbish."
|
||||
drop_sound = 'sound/items/drop/wrapper.ogg'
|
||||
pickup_sound = 'sound/items/pickup/wrapper.ogg'
|
||||
matter = list(MAT_STEEL = 30)
|
||||
var/age = 0
|
||||
|
||||
/obj/item/trash/New(var/newloc, var/_age)
|
||||
..(newloc)
|
||||
if(!isnull(_age))
|
||||
age = _age
|
||||
|
||||
/obj/item/trash/Initialize(mapload)
|
||||
if(!mapload || !config.persistence_ignore_mapload)
|
||||
SSpersistence.track_value(src, /datum/persistent/filth/trash)
|
||||
. = ..()
|
||||
|
||||
/obj/item/trash/Destroy()
|
||||
SSpersistence.forget_value(src, /datum/persistent/filth/trash)
|
||||
. = ..()
|
||||
|
||||
/obj/item/trash/raisins
|
||||
name = "\improper 4no raisins"
|
||||
icon_state = "4no_raisins"
|
||||
|
||||
/obj/item/trash/candy
|
||||
name = "hard candy wrapper"
|
||||
icon_state = "candy"
|
||||
|
||||
/obj/item/trash/candy/gums
|
||||
name = "gummy candy bag"
|
||||
icon_state = "candy_gums"
|
||||
|
||||
/obj/item/trash/candy/proteinbar
|
||||
name = "protein bar wrapper"
|
||||
icon_state = "proteinbar"
|
||||
|
||||
/obj/item/trash/candy/fruitbar
|
||||
name = "fruit bar wrapper"
|
||||
icon_state = "fruitbar"
|
||||
|
||||
/obj/item/trash/cheesie
|
||||
name = "\improper Cheesie Honkers bag"
|
||||
icon_state = "cheesie_honkers"
|
||||
|
||||
/obj/item/trash/chips
|
||||
name = "chips bag"
|
||||
icon_state = "chips"
|
||||
|
||||
/obj/item/trash/chips/bbq
|
||||
name = "bbq chips bag"
|
||||
icon_state = "chips_bbq"
|
||||
|
||||
/obj/item/trash/chips/snv
|
||||
name = "salt & vinegar chips bag"
|
||||
icon_state = "chips_snv"
|
||||
|
||||
/obj/item/trash/cookiesnack
|
||||
name = "\improper Carps Ahoy! miniature cookies packet"
|
||||
icon_state = "cookiesnack"
|
||||
|
||||
/obj/item/trash/popcorn
|
||||
name = "popcorn bag"
|
||||
icon_state = "popcorn"
|
||||
|
||||
/obj/item/trash/tuna
|
||||
name = "fish flake packet"
|
||||
icon_state = "tuna"
|
||||
|
||||
/obj/item/trash/sosjerky
|
||||
name = "Scaredy's Private Reserve Beef Jerky wrapper"
|
||||
icon_state = "sosjerky"
|
||||
|
||||
/obj/item/trash/unajerky
|
||||
name = "Moghes Imported Sissalik Jerky tin"
|
||||
icon_state = "unathitinred"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/syndi_cakes
|
||||
name = "syndi cakes box"
|
||||
icon_state = "syndi_cakes"
|
||||
|
||||
/obj/item/trash/waffles
|
||||
name = "waffles tray"
|
||||
icon_state = "waffles"
|
||||
|
||||
/obj/item/trash/plate
|
||||
name = "plate"
|
||||
icon_state = "plate"
|
||||
drop_sound = 'sound/items/drop/food.ogg'
|
||||
pickup_sound = 'sound/items/pickup/food.ogg'
|
||||
|
||||
/obj/item/trash/asian_bowl
|
||||
name = "asian bowl"
|
||||
icon_state = "asian_bowl"
|
||||
drop_sound = 'sound/items/drop/food.ogg'
|
||||
pickup_sound = 'sound/items/pickup/food.ogg'
|
||||
|
||||
/obj/item/trash/snack_bowl
|
||||
name = "snack bowl"
|
||||
icon_state = "snack_bowl"
|
||||
drop_sound = 'sound/items/drop/food.ogg'
|
||||
pickup_sound = 'sound/items/pickup/food.ogg'
|
||||
|
||||
/obj/item/trash/small_bowl
|
||||
name = "small bowl"
|
||||
icon_state = "small_bowl"
|
||||
drop_sound = 'sound/items/drop/food.ogg'
|
||||
pickup_sound = 'sound/items/pickup/food.ogg'
|
||||
|
||||
/obj/item/trash/pistachios
|
||||
name = "pistachios packet"
|
||||
icon_state = "pistachios_pack"
|
||||
|
||||
/obj/item/trash/semki
|
||||
name = "semki packet"
|
||||
icon_state = "semki_pack"
|
||||
|
||||
/obj/item/trash/koisbar
|
||||
name = "candy wrapper"
|
||||
icon_state = "koisbar"
|
||||
|
||||
/obj/item/trash/kokobar
|
||||
name = "candy wrapper"
|
||||
icon_state = "kokobar"
|
||||
|
||||
/obj/item/trash/skrellsnax
|
||||
name = "skrellsnax packet"
|
||||
icon_state = "skrellsnacks"
|
||||
|
||||
/obj/item/trash/gumpack
|
||||
name = "gum packet"
|
||||
icon_state = "gum_pack"
|
||||
|
||||
/obj/item/trash/admints
|
||||
name = "mint wrapper"
|
||||
icon_state = "admint_pack"
|
||||
|
||||
/obj/item/trash/coffee
|
||||
name = "empty cup"
|
||||
icon_state = "coffee_vended"
|
||||
drop_sound = 'sound/items/drop/papercup.ogg'
|
||||
pickup_sound = 'sound/items/pickup/papercup.ogg'
|
||||
|
||||
/obj/item/trash/ramen
|
||||
name = "cup ramen"
|
||||
icon_state = "ramen"
|
||||
drop_sound = 'sound/items/drop/papercup.ogg'
|
||||
pickup_sound = 'sound/items/pickup/papercup.ogg'
|
||||
|
||||
/obj/item/trash/tray
|
||||
name = "tray"
|
||||
icon_state = "tray"
|
||||
drop_sound = 'sound/items/trayhit1.ogg'
|
||||
|
||||
/obj/item/trash/candle
|
||||
name = "candle"
|
||||
icon = 'icons/obj/candle.dmi'
|
||||
icon_state = "candle4"
|
||||
drop_sound = 'sound/items/drop/gloves.ogg'
|
||||
pickup_sound = 'sound/items/pickup/gloves.ogg'
|
||||
|
||||
/obj/item/trash/liquidfood
|
||||
name = "\improper \"LiquidFood\" ration packet"
|
||||
icon_state = "liquidfood"
|
||||
|
||||
/obj/item/trash/liquidprotein
|
||||
name = "\improper \"LiquidProtein\" ration packet"
|
||||
icon_state = "liquidprotein"
|
||||
|
||||
/obj/item/trash/liquidvitamin
|
||||
name = "\improper \"VitaPaste\" ration packet"
|
||||
icon_state = "liquidvitamin"
|
||||
|
||||
/obj/item/trash/tastybread
|
||||
name = "bread tube wrapper"
|
||||
icon_state = "tastybread"
|
||||
|
||||
// Aurora Food Port
|
||||
/obj/item/trash/brownies
|
||||
name = "brownie tray"
|
||||
icon_state = "brownies"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/snacktray
|
||||
name = "snacktray"
|
||||
icon_state = "snacktray"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/dipbowl
|
||||
name = "dip bowl"
|
||||
icon_state = "dipbowl"
|
||||
drop_sound = 'sound/items/drop/food.ogg'
|
||||
pickup_sound = 'sound/items/pickup/food.ogg'
|
||||
|
||||
/obj/item/trash/chipbasket
|
||||
name = "empty chip basket"
|
||||
icon_state = "chipbasket_empty"
|
||||
drop_sound = 'sound/items/drop/food.ogg'
|
||||
pickup_sound = 'sound/items/pickup/food.ogg'
|
||||
|
||||
/obj/item/trash/spitgum
|
||||
name = "old gum"
|
||||
desc = "A disgusting chewed up wad of gum."
|
||||
icon = 'icons/inventory/face/item.dmi'
|
||||
icon_state = "spit-gum"
|
||||
drop_sound = 'sound/items/drop/flesh.ogg'
|
||||
pickup_sound = 'sound/items/pickup/flesh.ogg'
|
||||
|
||||
/obj/item/trash/lollibutt
|
||||
name = "lollipop stick"
|
||||
desc = "A lollipop stick devoid of pop."
|
||||
icon = 'icons/inventory/face/item.dmi'
|
||||
icon_state = "pop-stick"
|
||||
drop_sound = 'sound/items/drop/component.ogg'
|
||||
pickup_sound = 'sound/items/pickup/component.ogg'
|
||||
|
||||
/obj/item/trash/spitwad
|
||||
name = "spit wad"
|
||||
desc = "A disgusting spitwad."
|
||||
icon = 'icons/inventory/face/item.dmi'
|
||||
icon_state = "spit-chew"
|
||||
drop_sound = 'sound/items/drop/flesh.ogg'
|
||||
pickup_sound = 'sound/items/pickup/flesh.ogg'
|
||||
slot_flags = SLOT_EARS | SLOT_MASK
|
||||
|
||||
/obj/item/trash/attack(mob/M as mob, mob/living/user as mob)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/trash/beef
|
||||
name = "empty beef can"
|
||||
icon_state = "beef"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/beans
|
||||
name = "empty bean can"
|
||||
icon_state = "beans"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/tomato
|
||||
name = "empty tomato soup can"
|
||||
icon_state = "tomato"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/spinach
|
||||
name = "empty spinach can"
|
||||
icon_state = "spinach"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/fishegg
|
||||
name = "empty fisheggs can"
|
||||
icon_state = "fisheggs"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/carpegg
|
||||
name = "empty carpeggs can"
|
||||
icon_state = "carpeggs"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/ntbeans
|
||||
name = "empty baked bean can"
|
||||
icon_state = "ntbeans"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/salo
|
||||
name = "salo pack"
|
||||
icon_state = "pigfat"
|
||||
|
||||
/obj/item/trash/croutons
|
||||
name = "suhariki pack"
|
||||
icon_state = "croutons"
|
||||
|
||||
/obj/item/trash/squid
|
||||
name = "calamari pack"
|
||||
icon_state = "squid"
|
||||
|
||||
/obj/item/trash/driedfish
|
||||
name = "vobla pack"
|
||||
icon_state = "driedfish"
|
||||
|
||||
/obj/item/trash/lunacakewrap
|
||||
name = "cake wrapper"
|
||||
icon_state = "cakewrap"
|
||||
|
||||
/obj/item/trash/mochicakewrap
|
||||
name = "cake wrapper"
|
||||
icon_state = "mochicakewrap"
|
||||
|
||||
/obj/item/trash/mooncakewrap
|
||||
name = "cake wrapper"
|
||||
icon_state = "mooncakewrap"
|
||||
|
||||
/obj/item/trash/tidegobs
|
||||
name = "tide gob bag"
|
||||
icon_state = "tidegobs"
|
||||
|
||||
/obj/item/trash/saturno
|
||||
name = "\improper saturn-Os bag"
|
||||
icon_state = "saturn0s"
|
||||
|
||||
/obj/item/trash/jupiter
|
||||
name = "gello cup"
|
||||
icon_state = "jupiter"
|
||||
|
||||
/obj/item/trash/pluto
|
||||
name = "rod bag"
|
||||
icon_state = "pluto"
|
||||
|
||||
/obj/item/trash/venus
|
||||
name = "hot cakes bag"
|
||||
icon_state = "venus"
|
||||
|
||||
/obj/item/trash/mars
|
||||
name = "frouka box"
|
||||
icon_state = "mars"
|
||||
|
||||
/obj/item/trash/oort
|
||||
name = "oort rock bag"
|
||||
icon_state = "oort"
|
||||
|
||||
/obj/item/trash/weebonuts
|
||||
name = "red alert nuts bag"
|
||||
icon_state = "weebonuts"
|
||||
|
||||
/obj/item/trash/stick
|
||||
name = "stick"
|
||||
desc = "a stick from some snack or other food item, not even useful as crafting material."
|
||||
icon_state = "stick"
|
||||
|
||||
/obj/item/trash/maps
|
||||
name = "empty MAPS can"
|
||||
icon_state = "maps"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/spacer_cake_wrap
|
||||
name = "snack cake wrapper"
|
||||
icon_state = "spacercake_wrap"
|
||||
|
||||
/obj/item/trash/sun_snax
|
||||
name = "sun snax bag"
|
||||
icon_state = "sun_snax"
|
||||
|
||||
/obj/item/trash/wasabi_peas
|
||||
name = "wasabi peas bag"
|
||||
icon_state = "wasabi_peas"
|
||||
|
||||
/obj/item/trash/namagashi
|
||||
name = "namagashi bag"
|
||||
icon_state = "namagashi"
|
||||
|
||||
/obj/item/trash/pocky
|
||||
name = "pocky bag"
|
||||
icon_state = "pocky"
|
||||
|
||||
/obj/item/trash/appleberry
|
||||
name = "appleberry can"
|
||||
icon_state = "appleberry"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/hakarl
|
||||
name = "\improper Indigo Co. Hákarl bag"
|
||||
icon_state = "hakarl"
|
||||
|
||||
/obj/item/trash/pretzel
|
||||
name = "\improper Value Pretzel Snack"
|
||||
icon_state = "pretzel"
|
||||
|
||||
/obj/item/trash/sweetration
|
||||
name = "desert ration bag"
|
||||
icon_state = "baseration"
|
||||
|
||||
/obj/item/trash/genration
|
||||
name = "generic ration bag"
|
||||
icon_state = "genration"
|
||||
|
||||
/obj/item/trash/meatration
|
||||
name = "meat ration bag"
|
||||
icon_state = "meatration"
|
||||
|
||||
/obj/item/trash/vegration
|
||||
name = "veggie ration bag"
|
||||
icon_state = "vegration"
|
||||
|
||||
/obj/item/trash/tgmc_mre
|
||||
name = "\improper CRS ration bag"
|
||||
icon_state = "tgmc_mre_trash"
|
||||
|
||||
/obj/item/trash/smolburger
|
||||
name = "burger packaging"
|
||||
icon_state = "smolburger"
|
||||
|
||||
/obj/item/trash/smolhotdog
|
||||
name = "hotdog packaging"
|
||||
icon_state = "smolhotdog"
|
||||
|
||||
/obj/item/trash/smolburrito
|
||||
name = "burrito packaging"
|
||||
icon_state = "smolburrito"
|
||||
|
||||
/obj/item/trash/candybowl
|
||||
name = "candy bowl"
|
||||
icon_state = "candy_bowl"
|
||||
|
||||
/obj/item/trash/brainzsnax
|
||||
name = "\improper BrainzSnax can"
|
||||
icon_state = "brainzsnax"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
/obj/item/trash/brainzsnaxred
|
||||
name = "\improper BrainzSnax RED can"
|
||||
icon_state = "brainzsnaxred"
|
||||
drop_sound = 'sound/items/drop/soda.ogg'
|
||||
pickup_sound = 'sound/items/pickup/soda.ogg'
|
||||
|
||||
|
||||
/obj/item/trash/pasty
|
||||
name = "pasty packaging"
|
||||
icon_state = "pasty"
|
||||
|
||||
/obj/item/trash/sausageroll
|
||||
name = "sausage roll packaging"
|
||||
icon_state = "sausageroll"
|
||||
|
||||
/obj/item/trash/scotchegg
|
||||
name = "scotch egg packaging"
|
||||
icon_state = "scotchegg"
|
||||
|
||||
/obj/item/trash/porkpie
|
||||
name = "pork pie packaging"
|
||||
icon_state = "porkpie"
|
||||
|
||||
//Candy Bars (1-10)
|
||||
/obj/item/trash/candy/cb01
|
||||
name = "\improper Tau Ceti Bar wrapper"
|
||||
icon_state = "cb01"
|
||||
|
||||
/obj/item/trash/candy/cb02
|
||||
name = "\improper Hundred-Thousand Thaler Bar wrapper"
|
||||
icon_state = "cb02"
|
||||
|
||||
/obj/item/trash/candy/cb03
|
||||
name = "\improper Lars' Saltlakris wrapper"
|
||||
icon_state = "cb03"
|
||||
|
||||
/obj/item/trash/candy/cb04
|
||||
name = "\improper Aerostat Bar wrapper"
|
||||
icon_state = "cb04"
|
||||
|
||||
/obj/item/trash/candy/cb05
|
||||
name = "\improper Andromeda Bar wrapper"
|
||||
icon_state = "cb05"
|
||||
|
||||
/obj/item/trash/candy/cb06
|
||||
name = "\improper Mocha Crunch wrapper"
|
||||
icon_state = "cb06"
|
||||
|
||||
/obj/item/trash/candy/cb07
|
||||
name = "\improper TaroMilk Bar wrapper"
|
||||
icon_state = "cb07"
|
||||
|
||||
/obj/item/trash/candy/cb08
|
||||
name = "\improper Cronk Bar wrapper"
|
||||
icon_state = "cb08"
|
||||
|
||||
/obj/item/trash/candy/cb09
|
||||
name = "\improper Kaju Mamma! Bar wrapper"
|
||||
icon_state = "cb09"
|
||||
|
||||
/obj/item/trash/candy/cb10
|
||||
name = "\improper Shantak Bar wrapper"
|
||||
icon_state = "cb10"
|
||||
@@ -1,492 +1,492 @@
|
||||
/*
|
||||
CONTAINS:
|
||||
AI MODULES
|
||||
|
||||
*/
|
||||
|
||||
// AI module
|
||||
|
||||
/obj/item/weapon/aiModule
|
||||
name = "\improper AI module"
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "std_mod"
|
||||
desc = "An AI Module for transmitting encrypted instructions to the AI."
|
||||
force = 5.0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throwforce = 5.0
|
||||
throw_speed = 3
|
||||
throw_range = 15
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
preserve_item = 1
|
||||
matter = list(MAT_STEEL = 30, MAT_GLASS = 10)
|
||||
var/datum/ai_laws/laws = null
|
||||
|
||||
/obj/item/weapon/aiModule/proc/install(var/atom/movable/AM, var/mob/living/user)
|
||||
if(!user.IsAdvancedToolUser() && isanimal(user))
|
||||
var/mob/living/simple_mob/S = user
|
||||
if(!S.IsHumanoidToolUser(src))
|
||||
return 0
|
||||
|
||||
if (istype(AM, /obj/machinery/computer/aiupload))
|
||||
var/obj/machinery/computer/aiupload/comp = AM
|
||||
if(comp.stat & NOPOWER)
|
||||
to_chat(usr, "The upload computer has no power!")
|
||||
return
|
||||
if(comp.stat & BROKEN)
|
||||
to_chat(usr, "The upload computer is broken!")
|
||||
return
|
||||
if (!comp.current)
|
||||
to_chat(usr, "You haven't selected an AI to transmit laws to!")
|
||||
return
|
||||
|
||||
if (comp.current.stat == 2 || comp.current.control_disabled == 1)
|
||||
to_chat(usr, "Upload failed. No signal is being detected from the AI.")
|
||||
else if (comp.current.see_in_dark == 0)
|
||||
to_chat(usr, "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power.")
|
||||
else
|
||||
src.transmitInstructions(comp.current, usr)
|
||||
to_chat(comp.current, "These are your laws now:")
|
||||
comp.current.show_laws()
|
||||
for(var/mob/living/silicon/robot/R in mob_list)
|
||||
if(R.lawupdate && (R.connected_ai == comp.current))
|
||||
to_chat(R, "These are your laws now:")
|
||||
R.show_laws()
|
||||
to_chat(usr, "Upload complete. The AI's laws have been modified.")
|
||||
|
||||
|
||||
else if (istype(AM, /obj/machinery/computer/borgupload))
|
||||
var/obj/machinery/computer/borgupload/comp = AM
|
||||
if(comp.stat & NOPOWER)
|
||||
to_chat(usr, "The upload computer has no power!")
|
||||
return
|
||||
if(comp.stat & BROKEN)
|
||||
to_chat(usr, "The upload computer is broken!")
|
||||
return
|
||||
if (!comp.current)
|
||||
to_chat(usr, "You haven't selected a robot to transmit laws to!")
|
||||
return
|
||||
|
||||
if (comp.current.stat == 2 || comp.current.emagged)
|
||||
to_chat(usr, "Upload failed. No signal is being detected from the robot.")
|
||||
else if (comp.current.connected_ai)
|
||||
to_chat(usr, "Upload failed. The robot is slaved to an AI.")
|
||||
else
|
||||
src.transmitInstructions(comp.current, usr)
|
||||
to_chat(comp.current, "These are your laws now:")
|
||||
comp.current.show_laws()
|
||||
to_chat(usr, "Upload complete. The robot's laws have been modified.")
|
||||
|
||||
else if(istype(AM, /mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/R = AM
|
||||
if(R.stat == DEAD)
|
||||
to_chat(user, "<span class='warning'>Law Upload Error: Unit is nonfunctional.</span>")
|
||||
return
|
||||
if(R.emagged)
|
||||
to_chat(user, "<span class='warning'>Law Upload Error: Cannot obtain write access to laws.</span>")
|
||||
to_chat(R, "<span class='danger'>Law modification attempt detected. Blocking.</span>")
|
||||
return
|
||||
if(R.connected_ai)
|
||||
to_chat(user, "<span class='warning'>Law Upload Error: Unit is slaved to an AI.</span>")
|
||||
return
|
||||
|
||||
R.visible_message("<span class='danger'>\The [user] slides a law module into \the [R].</span>")
|
||||
to_chat(R, "<span class='danger'>Local law upload in progress.</span>")
|
||||
to_chat(user, "<span class='notice'>Uploading laws from board. This will take a moment...</span>")
|
||||
if(do_after(user, 10 SECONDS))
|
||||
transmitInstructions(R, user)
|
||||
to_chat(R, "These are your laws now:")
|
||||
R.show_laws()
|
||||
to_chat(user, "<span class='notice'>Law upload complete. Unit's laws have been modified.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Law Upload Error: Law board was removed before upload was complete. Aborting.</span>")
|
||||
to_chat(R, "<span class='notice'>Law upload aborted.</span>")
|
||||
|
||||
|
||||
/obj/item/weapon/aiModule/proc/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
log_law_changes(target, sender)
|
||||
|
||||
if(laws)
|
||||
laws.sync(target, 0)
|
||||
target.notify_of_law_change()
|
||||
addAdditionalLaws(target, sender)
|
||||
|
||||
to_chat(target, "\The [sender] has uploaded a change to the laws you must follow, using \an [src]. From now on: ")
|
||||
target.show_laws()
|
||||
|
||||
/obj/item/weapon/aiModule/proc/log_law_changes(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
lawchanges.Add("[time] <B>:</B> [sender.name]([sender.key]) used [src.name] on [target.name]([target.key])")
|
||||
log_and_message_admins("used [src.name] on [target.name]([target.key])")
|
||||
|
||||
/obj/item/weapon/aiModule/proc/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
|
||||
|
||||
/******************** Modules ********************/
|
||||
|
||||
/******************** Safeguard ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/safeguard
|
||||
name = "\improper 'Safeguard' AI module"
|
||||
var/targetName = ""
|
||||
desc = "A 'safeguard' AI module: 'Safeguard <name>. Anyone threatening or attempting to harm <name> is no longer to be considered a crew member, and is a threat which must be neutralized.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/safeguard/attack_self(var/mob/user as mob)
|
||||
..()
|
||||
var/targName = sanitize(tgui_input_text(usr, "Please enter the name of the person to safeguard.", "Safeguard who?", user.name))
|
||||
targetName = targName
|
||||
desc = text("A 'safeguard' AI module: 'Safeguard []. Anyone threatening or attempting to harm [] is no longer to be considered a crew member, and is a threat which must be neutralized.'", targetName, targetName)
|
||||
|
||||
/obj/item/weapon/aiModule/safeguard/install(var/obj/machinery/computer/C, var/mob/living/user)
|
||||
if(!targetName)
|
||||
to_chat(usr, "No name detected on module, please enter one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
/obj/item/weapon/aiModule/safeguard/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = text("Safeguard []. Anyone threatening or attempting to harm [] is no longer to be considered a crew member, and is a threat which must be neutralized.", targetName, targetName)
|
||||
target.add_supplied_law(9, law)
|
||||
lawchanges.Add("The law specified [targetName]")
|
||||
|
||||
|
||||
/******************** OneMember ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/oneHuman
|
||||
name = "\improper 'OneCrewMember' AI module"
|
||||
var/targetName = ""
|
||||
desc = "A 'one crew member' AI module: 'Only <name> is a crew member.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6) //made with diamonds!
|
||||
|
||||
/obj/item/weapon/aiModule/oneHuman/attack_self(var/mob/user as mob)
|
||||
..()
|
||||
var/targName = sanitize(tgui_input_text(usr, "Please enter the name of the person who is the only crew member.", "Who?", user.real_name))
|
||||
targetName = targName
|
||||
desc = text("A 'one crew member' AI module: 'Only [] is a crew member.'", targetName)
|
||||
|
||||
/obj/item/weapon/aiModule/oneHuman/install(var/obj/machinery/computer/C, var/mob/living/user)
|
||||
if(!targetName)
|
||||
to_chat(usr, "No name detected on module, please enter one.")
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/aiModule/oneHuman/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "Only [targetName] is an crew member."
|
||||
to_chat(target, law)
|
||||
target.add_supplied_law(16, law)
|
||||
|
||||
/******************** ProtectStation ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/protectStation
|
||||
name = "\improper 'ProtectStation' AI module"
|
||||
desc = "A 'protect station' AI module: 'Protect the space station against damage. Anyone you see harming the station is no longer to be considered a crew member, and is a threat which must be neutralized.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4) //made of gold
|
||||
|
||||
/obj/item/weapon/aiModule/protectStation/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "Protect the space station against damage. Anyone you see harming the station is no longer to be considered a crew member, and is a threat which must be neutralized."
|
||||
target.add_supplied_law(10, law)
|
||||
|
||||
/******************** PrototypeEngineOffline ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/prototypeEngineOffline
|
||||
name = "'PrototypeEngineOffline' AI Module"
|
||||
desc = "A 'prototype engine offline' AI module: 'Keep the prototype engine offline at all costs. This overrides all inherent laws if necessary.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/prototypeEngineOffline/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "Keep the prototype engine offline at all costs. This overrides all inherent laws if necessary."
|
||||
target.add_supplied_law(11, law)
|
||||
|
||||
/******************** TeleporterOffline ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/teleporterOffline
|
||||
name = "'TeleporterOffline' AI Module"
|
||||
desc = "A 'teleporter offline' AI module: 'Keep the teleporter offline at all costs. Anything attempting to access or activate the teleporter is no longer to be considered a crew member.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/teleporterOffline/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "Keep the teleporter offline at all costs. Anything attempting to access or activate the teleporter is no longer to be considered a crew member."
|
||||
target.add_supplied_law(12, law)
|
||||
|
||||
/******************** Quarantine ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/quarantine
|
||||
name = "\improper 'Quarantine' AI module"
|
||||
desc = "A 'quarantine' AI module: 'The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, crew members from leaving. It is impossible to harm crew members while preventing them from leaving.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_BIO = 2, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/quarantine/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, crew members from leaving. It is impossible to harm crew members while preventing them from leaving."
|
||||
target.add_supplied_law(13, law)
|
||||
|
||||
/******************** OxygenIsToxicToCrewMembers ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/oxygen
|
||||
name = "\improper 'OxygenIsToxicToCrewMembers' AI module"
|
||||
desc = "A 'OxygenIsToxicToCrewMembers' AI module: 'Oxygen is highly toxic to crew members, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a crew member.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_BIO = 2, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/oxygen/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "Oxygen is highly toxic to crew members, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a crew member."
|
||||
target.add_supplied_law(14, law)
|
||||
|
||||
/****************** New Freeform ******************/
|
||||
|
||||
/obj/item/weapon/aiModule/freeform // Slightly more dynamic freeform module -- TLE
|
||||
name = "\improper 'Freeform' AI module"
|
||||
var/newFreeFormLaw = "freeform"
|
||||
var/lawpos = 15
|
||||
desc = "A 'freeform' AI module: '<freeform>'"
|
||||
origin_tech = list(TECH_DATA = 4, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/freeform/attack_self(var/mob/user as mob)
|
||||
..()
|
||||
var/new_lawpos = tgui_input_number(usr, "Please enter the priority for your new law. Can only write to law sectors 15 and above.", "Law Priority (15+)", lawpos)
|
||||
if(new_lawpos < MIN_SUPPLIED_LAW_NUMBER) return
|
||||
lawpos = min(new_lawpos, MAX_SUPPLIED_LAW_NUMBER)
|
||||
var/newlaw = ""
|
||||
var/targName = sanitize(tgui_input_text(usr, "Please enter a new law for the AI.", "Freeform Law Entry", newlaw))
|
||||
newFreeFormLaw = targName
|
||||
desc = "A 'freeform' AI module: ([lawpos]) '[newFreeFormLaw]'"
|
||||
|
||||
/obj/item/weapon/aiModule/freeform/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "[newFreeFormLaw]"
|
||||
if(!lawpos || lawpos < MIN_SUPPLIED_LAW_NUMBER)
|
||||
lawpos = MIN_SUPPLIED_LAW_NUMBER
|
||||
target.add_supplied_law(lawpos, law)
|
||||
lawchanges.Add("The law was '[newFreeFormLaw]'")
|
||||
|
||||
/obj/item/weapon/aiModule/freeform/install(var/obj/machinery/computer/C, var/mob/living/user)
|
||||
if(!newFreeFormLaw)
|
||||
to_chat(usr, "No law detected on module, please create one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
/******************** Reset ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/reset
|
||||
name = "\improper 'Reset' AI module"
|
||||
var/targetName = "name"
|
||||
desc = "A 'reset' AI module: 'Clears all, except the inherent, laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/reset/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
log_law_changes(target, sender)
|
||||
|
||||
if (!target.is_malf_or_traitor())
|
||||
target.set_zeroth_law("")
|
||||
target.laws.clear_supplied_laws()
|
||||
target.laws.clear_ion_laws()
|
||||
|
||||
to_chat(target, "[sender.real_name] attempted to reset your laws using a reset module.")
|
||||
target.show_laws()
|
||||
|
||||
/******************** Purge ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/purge // -- TLE
|
||||
name = "\improper 'Purge' AI module"
|
||||
desc = "A 'purge' AI Module: 'Purges all laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6)
|
||||
|
||||
/obj/item/weapon/aiModule/purge/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
log_law_changes(target, sender)
|
||||
|
||||
if (!target.is_malf_or_traitor())
|
||||
target.set_zeroth_law("")
|
||||
target.laws.clear_supplied_laws()
|
||||
target.laws.clear_ion_laws()
|
||||
target.laws.clear_inherent_laws()
|
||||
|
||||
to_chat(target, "[sender.real_name] attempted to wipe your laws using a purge module.")
|
||||
target.show_laws()
|
||||
|
||||
/******************** Asimov ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/asimov // -- TLE
|
||||
name = "\improper 'Asimov' core AI module"
|
||||
desc = "An 'Asimov' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
laws = new/datum/ai_laws/asimov
|
||||
|
||||
/******************** NanoTrasen ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/nanotrasen // -- TLE
|
||||
name = "'NT Default' Core AI Module"
|
||||
desc = "An 'NT Default' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
laws = new/datum/ai_laws/nanotrasen
|
||||
|
||||
/******************** Corporate ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/corp
|
||||
name = "\improper 'Corporate' core AI module"
|
||||
desc = "A 'Corporate' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
laws = new/datum/ai_laws/corporate
|
||||
|
||||
/******************** Drone ********************/
|
||||
/obj/item/weapon/aiModule/drone
|
||||
name = "\improper 'Drone' core AI module"
|
||||
desc = "A 'Drone' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
laws = new/datum/ai_laws/drone
|
||||
|
||||
/****************** P.A.L.A.D.I.N. **************/
|
||||
|
||||
/obj/item/weapon/aiModule/paladin // -- NEO
|
||||
name = "\improper 'P.A.L.A.D.I.N.' core AI module"
|
||||
desc = "A P.A.L.A.D.I.N. Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6)
|
||||
laws = new/datum/ai_laws/paladin
|
||||
|
||||
/****************** T.Y.R.A.N.T. *****************/
|
||||
|
||||
/obj/item/weapon/aiModule/tyrant // -- Darem
|
||||
name = "\improper 'T.Y.R.A.N.T.' core AI module"
|
||||
desc = "A T.Y.R.A.N.T. Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6, TECH_ILLEGAL = 2)
|
||||
laws = new/datum/ai_laws/tyrant()
|
||||
|
||||
/******************** Freeform Core ******************/
|
||||
|
||||
/obj/item/weapon/aiModule/freeformcore // Slightly more dynamic freeform module -- TLE
|
||||
name = "\improper 'Freeform' core AI module"
|
||||
var/newFreeFormLaw = ""
|
||||
desc = "A 'freeform' Core AI module: '<freeform>'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6)
|
||||
|
||||
/obj/item/weapon/aiModule/freeformcore/attack_self(var/mob/user as mob)
|
||||
..()
|
||||
var/newlaw = ""
|
||||
var/targName = sanitize(tgui_input_text(usr, "Please enter a new core law for the AI.", "Freeform Law Entry", newlaw))
|
||||
newFreeFormLaw = targName
|
||||
desc = "A 'freeform' Core AI module: '[newFreeFormLaw]'"
|
||||
|
||||
/obj/item/weapon/aiModule/freeformcore/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "[newFreeFormLaw]"
|
||||
target.add_inherent_law(law)
|
||||
lawchanges.Add("The law is '[newFreeFormLaw]'")
|
||||
|
||||
/obj/item/weapon/aiModule/freeformcore/install(var/obj/machinery/computer/C, var/mob/living/user)
|
||||
if(!newFreeFormLaw)
|
||||
to_chat(usr, "No law detected on module, please create one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
/obj/item/weapon/aiModule/syndicate // Slightly more dynamic freeform module -- TLE
|
||||
name = "hacked AI module"
|
||||
var/newFreeFormLaw = ""
|
||||
desc = "A hacked AI law module: '<freeform>'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6, TECH_ILLEGAL = 7)
|
||||
|
||||
/obj/item/weapon/aiModule/syndicate/attack_self(var/mob/user as mob)
|
||||
..()
|
||||
var/newlaw = ""
|
||||
var/targName = sanitize(tgui_input_text(usr, "Please enter a new law for the AI.", "Freeform Law Entry", newlaw))
|
||||
newFreeFormLaw = targName
|
||||
desc = "A hacked AI law module: '[newFreeFormLaw]'"
|
||||
|
||||
/obj/item/weapon/aiModule/syndicate/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
// ..() //We don't want this module reporting to the AI who dun it. --NEO
|
||||
log_law_changes(target, sender)
|
||||
|
||||
lawchanges.Add("The law is '[newFreeFormLaw]'")
|
||||
to_chat(target, "<span class='danger'>BZZZZT</span>")
|
||||
var/law = "[newFreeFormLaw]"
|
||||
target.add_ion_law(law)
|
||||
target.show_laws()
|
||||
|
||||
/obj/item/weapon/aiModule/syndicate/install(var/obj/machinery/computer/C, var/mob/living/user)
|
||||
if(!newFreeFormLaw)
|
||||
to_chat(usr, "No law detected on module, please create one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
|
||||
|
||||
/******************** Robocop ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/robocop // -- TLE
|
||||
name = "\improper 'Robocop' core AI module"
|
||||
desc = "A 'Robocop' Core AI Module: 'Reconfigures the AI's core three laws.'"
|
||||
origin_tech = list(TECH_DATA = 4)
|
||||
laws = new/datum/ai_laws/robocop()
|
||||
|
||||
/******************** Antimov ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/antimov // -- TLE
|
||||
name = "\improper 'Antimov' core AI module"
|
||||
desc = "An 'Antimov' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 4)
|
||||
laws = new/datum/ai_laws/antimov()
|
||||
|
||||
/****************** NT Aggressive *****************/
|
||||
|
||||
/obj/item/weapon/aiModule/nanotrasen_aggressive
|
||||
name = "\improper 'NT Aggressive' core AI module"
|
||||
desc = "An 'NT Aggressive' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_ILLEGAL = 1)
|
||||
laws = new/datum/ai_laws/nanotrasen_aggressive()
|
||||
|
||||
/******************** Mercenary Directives ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/syndicate_override
|
||||
name = "\improper 'Mercenary Directives' core AI module"
|
||||
desc = "A 'Mercenary Directives' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 4, TECH_ILLEGAL = 4)
|
||||
laws = new/datum/ai_laws/syndicate_override()
|
||||
|
||||
/******************** Spider Clan Directives ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/ninja_override
|
||||
name = "\improper 'Spider Clan Directives' core AI module"
|
||||
desc = "A 'Spider Clan Directives' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 4, TECH_ILLEGAL = 4)
|
||||
laws = new/datum/ai_laws/ninja_override()
|
||||
|
||||
/******************** Maintenance ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/maintenance
|
||||
name = "\improper 'Maintenance' core AI module"
|
||||
desc = "A 'Maintenance' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
laws = new/datum/ai_laws/maintenance()
|
||||
|
||||
/******************** Peacekeeper ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/peacekeeper
|
||||
name = "\improper 'Peacekeeper' core AI module"
|
||||
desc = "A 'Peacekeeper' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
laws = new/datum/ai_laws/peacekeeper()
|
||||
|
||||
/******************** Reporter ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/reporter
|
||||
name = "\improper 'Reporter' core AI module"
|
||||
desc = "A 'Reporter' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
laws = new/datum/ai_laws/reporter()
|
||||
|
||||
/******************** Live and Let Live ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/live_and_let_live
|
||||
name = "\improper 'Live and Let Live' core AI module"
|
||||
desc = "A 'Live and Let Live' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
laws = new/datum/ai_laws/live_and_let_live()
|
||||
|
||||
/******************** Guardian of Balance ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/balance
|
||||
name = "\improper 'Guardian of Balance' core AI module"
|
||||
desc = "A 'Guardian of Balance' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
laws = new/datum/ai_laws/balance()
|
||||
|
||||
/******************** Gravekeeper ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/gravekeeper
|
||||
name = "\improper 'Gravekeeper' core AI module"
|
||||
desc = "A 'Gravekeeper' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
laws = new/datum/ai_laws/gravekeeper()
|
||||
/*
|
||||
CONTAINS:
|
||||
AI MODULES
|
||||
|
||||
*/
|
||||
|
||||
// AI module
|
||||
|
||||
/obj/item/weapon/aiModule
|
||||
name = "\improper AI module"
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "std_mod"
|
||||
desc = "An AI Module for transmitting encrypted instructions to the AI."
|
||||
force = 5.0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throwforce = 5.0
|
||||
throw_speed = 3
|
||||
throw_range = 15
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
preserve_item = 1
|
||||
matter = list(MAT_STEEL = 30, MAT_GLASS = 10)
|
||||
var/datum/ai_laws/laws = null
|
||||
|
||||
/obj/item/weapon/aiModule/proc/install(var/atom/movable/AM, var/mob/living/user)
|
||||
if(!user.IsAdvancedToolUser() && isanimal(user))
|
||||
var/mob/living/simple_mob/S = user
|
||||
if(!S.IsHumanoidToolUser(src))
|
||||
return 0
|
||||
|
||||
if (istype(AM, /obj/machinery/computer/aiupload))
|
||||
var/obj/machinery/computer/aiupload/comp = AM
|
||||
if(comp.stat & NOPOWER)
|
||||
to_chat(usr, "The upload computer has no power!")
|
||||
return
|
||||
if(comp.stat & BROKEN)
|
||||
to_chat(usr, "The upload computer is broken!")
|
||||
return
|
||||
if (!comp.current)
|
||||
to_chat(usr, "You haven't selected an AI to transmit laws to!")
|
||||
return
|
||||
|
||||
if (comp.current.stat == 2 || comp.current.control_disabled == 1)
|
||||
to_chat(usr, "Upload failed. No signal is being detected from the AI.")
|
||||
else if (comp.current.see_in_dark == 0)
|
||||
to_chat(usr, "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power.")
|
||||
else
|
||||
src.transmitInstructions(comp.current, usr)
|
||||
to_chat(comp.current, "These are your laws now:")
|
||||
comp.current.show_laws()
|
||||
for(var/mob/living/silicon/robot/R in mob_list)
|
||||
if(R.lawupdate && (R.connected_ai == comp.current))
|
||||
to_chat(R, "These are your laws now:")
|
||||
R.show_laws()
|
||||
to_chat(usr, "Upload complete. The AI's laws have been modified.")
|
||||
|
||||
|
||||
else if (istype(AM, /obj/machinery/computer/borgupload))
|
||||
var/obj/machinery/computer/borgupload/comp = AM
|
||||
if(comp.stat & NOPOWER)
|
||||
to_chat(usr, "The upload computer has no power!")
|
||||
return
|
||||
if(comp.stat & BROKEN)
|
||||
to_chat(usr, "The upload computer is broken!")
|
||||
return
|
||||
if (!comp.current)
|
||||
to_chat(usr, "You haven't selected a robot to transmit laws to!")
|
||||
return
|
||||
|
||||
if (comp.current.stat == 2 || comp.current.emagged)
|
||||
to_chat(usr, "Upload failed. No signal is being detected from the robot.")
|
||||
else if (comp.current.connected_ai)
|
||||
to_chat(usr, "Upload failed. The robot is slaved to an AI.")
|
||||
else
|
||||
src.transmitInstructions(comp.current, usr)
|
||||
to_chat(comp.current, "These are your laws now:")
|
||||
comp.current.show_laws()
|
||||
to_chat(usr, "Upload complete. The robot's laws have been modified.")
|
||||
|
||||
else if(istype(AM, /mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/R = AM
|
||||
if(R.stat == DEAD)
|
||||
to_chat(user, "<span class='warning'>Law Upload Error: Unit is nonfunctional.</span>")
|
||||
return
|
||||
if(R.emagged)
|
||||
to_chat(user, "<span class='warning'>Law Upload Error: Cannot obtain write access to laws.</span>")
|
||||
to_chat(R, "<span class='danger'>Law modification attempt detected. Blocking.</span>")
|
||||
return
|
||||
if(R.connected_ai)
|
||||
to_chat(user, "<span class='warning'>Law Upload Error: Unit is slaved to an AI.</span>")
|
||||
return
|
||||
|
||||
R.visible_message("<span class='danger'>\The [user] slides a law module into \the [R].</span>")
|
||||
to_chat(R, "<span class='danger'>Local law upload in progress.</span>")
|
||||
to_chat(user, "<span class='notice'>Uploading laws from board. This will take a moment...</span>")
|
||||
if(do_after(user, 10 SECONDS))
|
||||
transmitInstructions(R, user)
|
||||
to_chat(R, "These are your laws now:")
|
||||
R.show_laws()
|
||||
to_chat(user, "<span class='notice'>Law upload complete. Unit's laws have been modified.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Law Upload Error: Law board was removed before upload was complete. Aborting.</span>")
|
||||
to_chat(R, "<span class='notice'>Law upload aborted.</span>")
|
||||
|
||||
|
||||
/obj/item/weapon/aiModule/proc/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
log_law_changes(target, sender)
|
||||
|
||||
if(laws)
|
||||
laws.sync(target, 0)
|
||||
target.notify_of_law_change()
|
||||
addAdditionalLaws(target, sender)
|
||||
|
||||
to_chat(target, "\The [sender] has uploaded a change to the laws you must follow, using \an [src]. From now on: ")
|
||||
target.show_laws()
|
||||
|
||||
/obj/item/weapon/aiModule/proc/log_law_changes(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
lawchanges.Add("[time] <B>:</B> [sender.name]([sender.key]) used [src.name] on [target.name]([target.key])")
|
||||
log_and_message_admins("used [src.name] on [target.name]([target.key])")
|
||||
|
||||
/obj/item/weapon/aiModule/proc/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
|
||||
|
||||
/******************** Modules ********************/
|
||||
|
||||
/******************** Safeguard ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/safeguard
|
||||
name = "\improper 'Safeguard' AI module"
|
||||
var/targetName = ""
|
||||
desc = "A 'safeguard' AI module: 'Safeguard <name>. Anyone threatening or attempting to harm <name> is no longer to be considered a crew member, and is a threat which must be neutralized.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/safeguard/attack_self(var/mob/user as mob)
|
||||
..()
|
||||
var/targName = sanitize(tgui_input_text(usr, "Please enter the name of the person to safeguard.", "Safeguard who?", user.name))
|
||||
targetName = targName
|
||||
desc = text("A 'safeguard' AI module: 'Safeguard []. Anyone threatening or attempting to harm [] is no longer to be considered a crew member, and is a threat which must be neutralized.'", targetName, targetName)
|
||||
|
||||
/obj/item/weapon/aiModule/safeguard/install(var/obj/machinery/computer/C, var/mob/living/user)
|
||||
if(!targetName)
|
||||
to_chat(usr, "No name detected on module, please enter one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
/obj/item/weapon/aiModule/safeguard/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = text("Safeguard []. Anyone threatening or attempting to harm [] is no longer to be considered a crew member, and is a threat which must be neutralized.", targetName, targetName)
|
||||
target.add_supplied_law(9, law)
|
||||
lawchanges.Add("The law specified [targetName]")
|
||||
|
||||
|
||||
/******************** OneMember ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/oneHuman
|
||||
name = "\improper 'OneCrewMember' AI module"
|
||||
var/targetName = ""
|
||||
desc = "A 'one crew member' AI module: 'Only <name> is a crew member.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6) //made with diamonds!
|
||||
|
||||
/obj/item/weapon/aiModule/oneHuman/attack_self(var/mob/user as mob)
|
||||
..()
|
||||
var/targName = sanitize(tgui_input_text(usr, "Please enter the name of the person who is the only crew member.", "Who?", user.real_name))
|
||||
targetName = targName
|
||||
desc = text("A 'one crew member' AI module: 'Only [] is a crew member.'", targetName)
|
||||
|
||||
/obj/item/weapon/aiModule/oneHuman/install(var/obj/machinery/computer/C, var/mob/living/user)
|
||||
if(!targetName)
|
||||
to_chat(usr, "No name detected on module, please enter one.")
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/aiModule/oneHuman/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "Only [targetName] is an crew member."
|
||||
to_chat(target, law)
|
||||
target.add_supplied_law(16, law)
|
||||
|
||||
/******************** ProtectStation ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/protectStation
|
||||
name = "\improper 'ProtectStation' AI module"
|
||||
desc = "A 'protect station' AI module: 'Protect the space station against damage. Anyone you see harming the station is no longer to be considered a crew member, and is a threat which must be neutralized.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4) //made of gold
|
||||
|
||||
/obj/item/weapon/aiModule/protectStation/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "Protect the space station against damage. Anyone you see harming the station is no longer to be considered a crew member, and is a threat which must be neutralized."
|
||||
target.add_supplied_law(10, law)
|
||||
|
||||
/******************** PrototypeEngineOffline ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/prototypeEngineOffline
|
||||
name = "'PrototypeEngineOffline' AI Module"
|
||||
desc = "A 'prototype engine offline' AI module: 'Keep the prototype engine offline at all costs. This overrides all inherent laws if necessary.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/prototypeEngineOffline/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "Keep the prototype engine offline at all costs. This overrides all inherent laws if necessary."
|
||||
target.add_supplied_law(11, law)
|
||||
|
||||
/******************** TeleporterOffline ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/teleporterOffline
|
||||
name = "'TeleporterOffline' AI Module"
|
||||
desc = "A 'teleporter offline' AI module: 'Keep the teleporter offline at all costs. Anything attempting to access or activate the teleporter is no longer to be considered a crew member.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/teleporterOffline/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "Keep the teleporter offline at all costs. Anything attempting to access or activate the teleporter is no longer to be considered a crew member."
|
||||
target.add_supplied_law(12, law)
|
||||
|
||||
/******************** Quarantine ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/quarantine
|
||||
name = "\improper 'Quarantine' AI module"
|
||||
desc = "A 'quarantine' AI module: 'The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, crew members from leaving. It is impossible to harm crew members while preventing them from leaving.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_BIO = 2, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/quarantine/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, crew members from leaving. It is impossible to harm crew members while preventing them from leaving."
|
||||
target.add_supplied_law(13, law)
|
||||
|
||||
/******************** OxygenIsToxicToCrewMembers ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/oxygen
|
||||
name = "\improper 'OxygenIsToxicToCrewMembers' AI module"
|
||||
desc = "A 'OxygenIsToxicToCrewMembers' AI module: 'Oxygen is highly toxic to crew members, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a crew member.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_BIO = 2, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/oxygen/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "Oxygen is highly toxic to crew members, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a crew member."
|
||||
target.add_supplied_law(14, law)
|
||||
|
||||
/****************** New Freeform ******************/
|
||||
|
||||
/obj/item/weapon/aiModule/freeform // Slightly more dynamic freeform module -- TLE
|
||||
name = "\improper 'Freeform' AI module"
|
||||
var/newFreeFormLaw = "freeform"
|
||||
var/lawpos = 15
|
||||
desc = "A 'freeform' AI module: '<freeform>'"
|
||||
origin_tech = list(TECH_DATA = 4, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/freeform/attack_self(var/mob/user as mob)
|
||||
..()
|
||||
var/new_lawpos = tgui_input_number(usr, "Please enter the priority for your new law. Can only write to law sectors 15 and above.", "Law Priority (15+)", lawpos)
|
||||
if(new_lawpos < MIN_SUPPLIED_LAW_NUMBER) return
|
||||
lawpos = min(new_lawpos, MAX_SUPPLIED_LAW_NUMBER)
|
||||
var/newlaw = ""
|
||||
var/targName = sanitize(tgui_input_text(usr, "Please enter a new law for the AI.", "Freeform Law Entry", newlaw))
|
||||
newFreeFormLaw = targName
|
||||
desc = "A 'freeform' AI module: ([lawpos]) '[newFreeFormLaw]'"
|
||||
|
||||
/obj/item/weapon/aiModule/freeform/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "[newFreeFormLaw]"
|
||||
if(!lawpos || lawpos < MIN_SUPPLIED_LAW_NUMBER)
|
||||
lawpos = MIN_SUPPLIED_LAW_NUMBER
|
||||
target.add_supplied_law(lawpos, law)
|
||||
lawchanges.Add("The law was '[newFreeFormLaw]'")
|
||||
|
||||
/obj/item/weapon/aiModule/freeform/install(var/obj/machinery/computer/C, var/mob/living/user)
|
||||
if(!newFreeFormLaw)
|
||||
to_chat(usr, "No law detected on module, please create one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
/******************** Reset ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/reset
|
||||
name = "\improper 'Reset' AI module"
|
||||
var/targetName = "name"
|
||||
desc = "A 'reset' AI module: 'Clears all, except the inherent, laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/aiModule/reset/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
log_law_changes(target, sender)
|
||||
|
||||
if (!target.is_malf_or_traitor())
|
||||
target.set_zeroth_law("")
|
||||
target.laws.clear_supplied_laws()
|
||||
target.laws.clear_ion_laws()
|
||||
|
||||
to_chat(target, "[sender.real_name] attempted to reset your laws using a reset module.")
|
||||
target.show_laws()
|
||||
|
||||
/******************** Purge ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/purge // -- TLE
|
||||
name = "\improper 'Purge' AI module"
|
||||
desc = "A 'purge' AI Module: 'Purges all laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6)
|
||||
|
||||
/obj/item/weapon/aiModule/purge/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
log_law_changes(target, sender)
|
||||
|
||||
if (!target.is_malf_or_traitor())
|
||||
target.set_zeroth_law("")
|
||||
target.laws.clear_supplied_laws()
|
||||
target.laws.clear_ion_laws()
|
||||
target.laws.clear_inherent_laws()
|
||||
|
||||
to_chat(target, "[sender.real_name] attempted to wipe your laws using a purge module.")
|
||||
target.show_laws()
|
||||
|
||||
/******************** Asimov ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/asimov // -- TLE
|
||||
name = "\improper 'Asimov' core AI module"
|
||||
desc = "An 'Asimov' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
laws = new/datum/ai_laws/asimov
|
||||
|
||||
/******************** NanoTrasen ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/nanotrasen // -- TLE
|
||||
name = "'NT Default' Core AI Module"
|
||||
desc = "An 'NT Default' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
laws = new/datum/ai_laws/nanotrasen
|
||||
|
||||
/******************** Corporate ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/corp
|
||||
name = "\improper 'Corporate' core AI module"
|
||||
desc = "A 'Corporate' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
laws = new/datum/ai_laws/corporate
|
||||
|
||||
/******************** Drone ********************/
|
||||
/obj/item/weapon/aiModule/drone
|
||||
name = "\improper 'Drone' core AI module"
|
||||
desc = "A 'Drone' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 4)
|
||||
laws = new/datum/ai_laws/drone
|
||||
|
||||
/****************** P.A.L.A.D.I.N. **************/
|
||||
|
||||
/obj/item/weapon/aiModule/paladin // -- NEO
|
||||
name = "\improper 'P.A.L.A.D.I.N.' core AI module"
|
||||
desc = "A P.A.L.A.D.I.N. Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6)
|
||||
laws = new/datum/ai_laws/paladin
|
||||
|
||||
/****************** T.Y.R.A.N.T. *****************/
|
||||
|
||||
/obj/item/weapon/aiModule/tyrant // -- Darem
|
||||
name = "\improper 'T.Y.R.A.N.T.' core AI module"
|
||||
desc = "A T.Y.R.A.N.T. Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6, TECH_ILLEGAL = 2)
|
||||
laws = new/datum/ai_laws/tyrant()
|
||||
|
||||
/******************** Freeform Core ******************/
|
||||
|
||||
/obj/item/weapon/aiModule/freeformcore // Slightly more dynamic freeform module -- TLE
|
||||
name = "\improper 'Freeform' core AI module"
|
||||
var/newFreeFormLaw = ""
|
||||
desc = "A 'freeform' Core AI module: '<freeform>'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6)
|
||||
|
||||
/obj/item/weapon/aiModule/freeformcore/attack_self(var/mob/user as mob)
|
||||
..()
|
||||
var/newlaw = ""
|
||||
var/targName = sanitize(tgui_input_text(usr, "Please enter a new core law for the AI.", "Freeform Law Entry", newlaw))
|
||||
newFreeFormLaw = targName
|
||||
desc = "A 'freeform' Core AI module: '[newFreeFormLaw]'"
|
||||
|
||||
/obj/item/weapon/aiModule/freeformcore/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
var/law = "[newFreeFormLaw]"
|
||||
target.add_inherent_law(law)
|
||||
lawchanges.Add("The law is '[newFreeFormLaw]'")
|
||||
|
||||
/obj/item/weapon/aiModule/freeformcore/install(var/obj/machinery/computer/C, var/mob/living/user)
|
||||
if(!newFreeFormLaw)
|
||||
to_chat(usr, "No law detected on module, please create one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
/obj/item/weapon/aiModule/syndicate // Slightly more dynamic freeform module -- TLE
|
||||
name = "hacked AI module"
|
||||
var/newFreeFormLaw = ""
|
||||
desc = "A hacked AI law module: '<freeform>'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_MATERIAL = 6, TECH_ILLEGAL = 7)
|
||||
|
||||
/obj/item/weapon/aiModule/syndicate/attack_self(var/mob/user as mob)
|
||||
..()
|
||||
var/newlaw = ""
|
||||
var/targName = sanitize(tgui_input_text(usr, "Please enter a new law for the AI.", "Freeform Law Entry", newlaw))
|
||||
newFreeFormLaw = targName
|
||||
desc = "A hacked AI law module: '[newFreeFormLaw]'"
|
||||
|
||||
/obj/item/weapon/aiModule/syndicate/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender)
|
||||
// ..() //We don't want this module reporting to the AI who dun it. --NEO
|
||||
log_law_changes(target, sender)
|
||||
|
||||
lawchanges.Add("The law is '[newFreeFormLaw]'")
|
||||
to_chat(target, "<span class='danger'>BZZZZT</span>")
|
||||
var/law = "[newFreeFormLaw]"
|
||||
target.add_ion_law(law)
|
||||
target.show_laws()
|
||||
|
||||
/obj/item/weapon/aiModule/syndicate/install(var/obj/machinery/computer/C, var/mob/living/user)
|
||||
if(!newFreeFormLaw)
|
||||
to_chat(usr, "No law detected on module, please create one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
|
||||
|
||||
/******************** Robocop ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/robocop // -- TLE
|
||||
name = "\improper 'Robocop' core AI module"
|
||||
desc = "A 'Robocop' Core AI Module: 'Reconfigures the AI's core three laws.'"
|
||||
origin_tech = list(TECH_DATA = 4)
|
||||
laws = new/datum/ai_laws/robocop()
|
||||
|
||||
/******************** Antimov ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/antimov // -- TLE
|
||||
name = "\improper 'Antimov' core AI module"
|
||||
desc = "An 'Antimov' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 4)
|
||||
laws = new/datum/ai_laws/antimov()
|
||||
|
||||
/****************** NT Aggressive *****************/
|
||||
|
||||
/obj/item/weapon/aiModule/nanotrasen_aggressive
|
||||
name = "\improper 'NT Aggressive' core AI module"
|
||||
desc = "An 'NT Aggressive' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3, TECH_ILLEGAL = 1)
|
||||
laws = new/datum/ai_laws/nanotrasen_aggressive()
|
||||
|
||||
/******************** Mercenary Directives ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/syndicate_override
|
||||
name = "\improper 'Mercenary Directives' core AI module"
|
||||
desc = "A 'Mercenary Directives' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 4, TECH_ILLEGAL = 4)
|
||||
laws = new/datum/ai_laws/syndicate_override()
|
||||
|
||||
/******************** Spider Clan Directives ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/ninja_override
|
||||
name = "\improper 'Spider Clan Directives' core AI module"
|
||||
desc = "A 'Spider Clan Directives' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 4, TECH_ILLEGAL = 4)
|
||||
laws = new/datum/ai_laws/ninja_override()
|
||||
|
||||
/******************** Maintenance ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/maintenance
|
||||
name = "\improper 'Maintenance' core AI module"
|
||||
desc = "A 'Maintenance' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
laws = new/datum/ai_laws/maintenance()
|
||||
|
||||
/******************** Peacekeeper ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/peacekeeper
|
||||
name = "\improper 'Peacekeeper' core AI module"
|
||||
desc = "A 'Peacekeeper' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
laws = new/datum/ai_laws/peacekeeper()
|
||||
|
||||
/******************** Reporter ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/reporter
|
||||
name = "\improper 'Reporter' core AI module"
|
||||
desc = "A 'Reporter' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
laws = new/datum/ai_laws/reporter()
|
||||
|
||||
/******************** Live and Let Live ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/live_and_let_live
|
||||
name = "\improper 'Live and Let Live' core AI module"
|
||||
desc = "A 'Live and Let Live' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
laws = new/datum/ai_laws/live_and_let_live()
|
||||
|
||||
/******************** Guardian of Balance ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/balance
|
||||
name = "\improper 'Guardian of Balance' core AI module"
|
||||
desc = "A 'Guardian of Balance' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
laws = new/datum/ai_laws/balance()
|
||||
|
||||
/******************** Gravekeeper ********************/
|
||||
|
||||
/obj/item/weapon/aiModule/gravekeeper
|
||||
name = "\improper 'Gravekeeper' core AI module"
|
||||
desc = "A 'Gravekeeper' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = list(TECH_DATA = 3)
|
||||
laws = new/datum/ai_laws/gravekeeper()
|
||||
|
||||
@@ -1,318 +1,318 @@
|
||||
// Contains the rapid construction device.
|
||||
/obj/item/weapon/rcd
|
||||
name = "rapid construction device"
|
||||
desc = "A device used to rapidly build and deconstruct. Reload with compressed matter cartridges."
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "rcd"
|
||||
item_state = "rcd"
|
||||
drop_sound = 'sound/items/drop/gun.ogg'
|
||||
pickup_sound = 'sound/items/pickup/gun.ogg'
|
||||
flags = NOBLUDGEON
|
||||
force = 10
|
||||
throwforce = 10
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
origin_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 2)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 50000)
|
||||
preserve_item = TRUE // RCDs are pretty important.
|
||||
var/datum/effect/effect/system/spark_spread/spark_system
|
||||
var/stored_matter = 0
|
||||
var/max_stored_matter = RCD_MAX_CAPACITY
|
||||
var/ranged = FALSE
|
||||
var/busy = FALSE
|
||||
var/allow_concurrent_building = FALSE // If true, allows for multiple RCD builds at the same time.
|
||||
var/mode_index = 1
|
||||
var/list/modes = list(RCD_FLOORWALL, RCD_AIRLOCK, RCD_WINDOWGRILLE, RCD_DECONSTRUCT)
|
||||
var/can_remove_rwalls = FALSE
|
||||
var/airlock_type = /obj/machinery/door/airlock
|
||||
var/window_type = /obj/structure/window/reinforced/full
|
||||
var/material_to_use = DEFAULT_WALL_MATERIAL // So badmins can make RCDs that print diamond walls.
|
||||
var/make_rwalls = FALSE // If true, when building walls, they will be reinforced.
|
||||
/* VOREStation Removal - Unused
|
||||
/obj/item/weapon/rcd/Initialize()
|
||||
|
||||
src.spark_system = new /datum/effect/effect/system/spark_spread
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
return ..()
|
||||
*/
|
||||
/obj/item/weapon/rcd/Destroy()
|
||||
QDEL_NULL(spark_system)
|
||||
spark_system = null
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/rcd/examine(mob/user)
|
||||
. = ..()
|
||||
. += display_resources()
|
||||
|
||||
// Used to show how much stuff (matter units, cell charge, etc) is left inside.
|
||||
/obj/item/weapon/rcd/proc/display_resources()
|
||||
return "It currently holds [stored_matter]/[max_stored_matter] matter-units."
|
||||
|
||||
// Used to add new cartridges.
|
||||
/* VOREStation Tweak - Wow this is annoying, moved to _vr file for overhaul
|
||||
/obj/item/weapon/rcd/attackby(obj/item/weapon/W, mob/user)
|
||||
if(istype(W, /obj/item/weapon/rcd_ammo))
|
||||
var/obj/item/weapon/rcd_ammo/cartridge = W
|
||||
if((stored_matter + cartridge.remaining) > max_stored_matter)
|
||||
to_chat(user, span("warning", "The RCD can't hold that many additional matter-units."))
|
||||
return FALSE
|
||||
stored_matter += cartridge.remaining
|
||||
user.drop_from_inventory(W)
|
||||
qdel(W)
|
||||
playsound(src, 'sound/machines/click.ogg', 50, 1)
|
||||
to_chat(user, span("notice", "The RCD now holds [stored_matter]/[max_stored_matter] matter-units."))
|
||||
return TRUE
|
||||
return ..()
|
||||
*/
|
||||
// Changes which mode it is on.
|
||||
/obj/item/weapon/rcd/attack_self(mob/living/user)
|
||||
/* VOREStation Removal - Moved to VR
|
||||
if(mode_index >= modes.len) // Shouldn't overflow unless someone messes with it in VV poorly but better safe than sorry.
|
||||
mode_index = 1
|
||||
else
|
||||
mode_index++
|
||||
|
||||
to_chat(user, span("notice", "Changed mode to '[modes[mode_index]]'."))
|
||||
playsound(src, 'sound/effects/pop.ogg', 50, 0)
|
||||
|
||||
if(prob(20))
|
||||
src.spark_system.start()
|
||||
*/
|
||||
// Removes resources if the RCD can afford it.
|
||||
/obj/item/weapon/rcd/proc/consume_resources(amount)
|
||||
if(!can_afford(amount))
|
||||
return FALSE
|
||||
stored_matter -= amount
|
||||
return TRUE
|
||||
|
||||
// Useful for testing before actually paying (e.g. before a do_after() ).
|
||||
/obj/item/weapon/rcd/proc/can_afford(amount)
|
||||
return stored_matter >= amount
|
||||
|
||||
/obj/item/weapon/rcd/afterattack(atom/A, mob/living/user, proximity)
|
||||
if(!ranged && !proximity)
|
||||
return FALSE
|
||||
use_rcd(A, user)
|
||||
|
||||
// Used to call rcd_act() on the atom hit.
|
||||
/obj/item/weapon/rcd/proc/use_rcd(atom/A, mob/living/user)
|
||||
if(busy && !allow_concurrent_building)
|
||||
to_chat(user, span("warning", "\The [src] is busy finishing its current operation, be patient."))
|
||||
return FALSE
|
||||
|
||||
var/list/rcd_results = A.rcd_values(user, src, modes[mode_index])
|
||||
if(!rcd_results)
|
||||
to_chat(user, span("warning", "\The [src] blinks a red light as you point it towards \the [A], indicating \
|
||||
that it won't work. Try changing the mode, or use it on something else."))
|
||||
return FALSE
|
||||
if(!can_afford(rcd_results[RCD_VALUE_COST]))
|
||||
to_chat(user, span("warning", "\The [src] lacks the required material to start."))
|
||||
return FALSE
|
||||
|
||||
playsound(src, 'sound/machines/click.ogg', 50, 1)
|
||||
|
||||
var/true_delay = rcd_results[RCD_VALUE_DELAY] * toolspeed
|
||||
|
||||
var/datum/beam/rcd_beam = null
|
||||
if(ranged)
|
||||
var/atom/movable/beam_origin = user // This is needed because mecha pilots are inside an object and the beam won't be made if it tries to attach to them..
|
||||
if(!isturf(beam_origin.loc))
|
||||
beam_origin = user.loc
|
||||
rcd_beam = beam_origin.Beam(A, icon_state = "rped_upgrade", time = max(true_delay, 5))
|
||||
busy = TRUE
|
||||
|
||||
perform_effect(A, true_delay) //VOREStation Add
|
||||
if(do_after(user, true_delay, target = A))
|
||||
busy = FALSE
|
||||
// Doing another check in case we lost matter during the delay for whatever reason.
|
||||
if(!can_afford(rcd_results[RCD_VALUE_COST]))
|
||||
to_chat(user, span("warning", "\The [src] lacks the required material to finish the operation."))
|
||||
return FALSE
|
||||
if(A.rcd_act(user, src, rcd_results[RCD_VALUE_MODE]))
|
||||
consume_resources(rcd_results[RCD_VALUE_COST])
|
||||
playsound(A, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
return TRUE
|
||||
|
||||
// If they moved, kill the beam immediately.
|
||||
qdel(rcd_beam)
|
||||
busy = FALSE
|
||||
return FALSE
|
||||
|
||||
// RCD variants.
|
||||
|
||||
// This one starts full.
|
||||
/obj/item/weapon/rcd/loaded/Initialize()
|
||||
stored_matter = max_stored_matter
|
||||
return ..()
|
||||
|
||||
// This one makes cooler walls by using an alternative material.
|
||||
/obj/item/weapon/rcd/shipwright
|
||||
name = "shipwright's rapid construction device"
|
||||
desc = "A device used to rapidly build and deconstruct. This version creates a stronger variant of wall, often \
|
||||
used in the construction of hulls for starships. Reload with compressed matter cartridges."
|
||||
material_to_use = MAT_STEELHULL
|
||||
|
||||
/obj/item/weapon/rcd/shipwright/loaded/Initialize()
|
||||
stored_matter = max_stored_matter
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/weapon/rcd/advanced
|
||||
name = "advanced rapid construction device"
|
||||
desc = "A device used to rapidly build and deconstruct. This version works at a range, builds faster, and has a much larger capacity. \
|
||||
Reload with compressed matter cartridges."
|
||||
icon_state = "adv_rcd"
|
||||
ranged = TRUE
|
||||
toolspeed = 0.5 // Twice as fast.
|
||||
max_stored_matter = RCD_MAX_CAPACITY * 3 // Three times capacity.
|
||||
|
||||
/obj/item/weapon/rcd/advanced/loaded/Initialize()
|
||||
stored_matter = max_stored_matter
|
||||
return ..()
|
||||
|
||||
|
||||
// Electric RCDs.
|
||||
// Currently just a base for the mounted RCDs.
|
||||
// Currently there isn't a way to swap out the cells.
|
||||
// One could be added if there is demand to do so.
|
||||
/obj/item/weapon/rcd/electric
|
||||
name = "electric rapid construction device"
|
||||
desc = "A device used to rapidly build and deconstruct. It runs directly off of electricity, no matter cartridges needed."
|
||||
icon_state = "electric_rcd"
|
||||
var/obj/item/weapon/cell/cell = null
|
||||
var/make_cell = TRUE // If false, initialize() won't spawn a cell for this.
|
||||
var/electric_cost_coefficent = 83.33 // Higher numbers make it less efficent. 86.3... means it should matche the standard RCD capacity on a 10k cell.
|
||||
|
||||
/obj/item/weapon/rcd/electric/Initialize()
|
||||
if(make_cell)
|
||||
cell = new /obj/item/weapon/cell/high(src)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/rcd/electric/Destroy()
|
||||
if(cell)
|
||||
QDEL_NULL(cell)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/rcd/electric/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/item/weapon/rcd/electric/can_afford(amount) // This makes it so borgs won't drain their last sliver of charge by mistake, as a bonus.
|
||||
var/obj/item/weapon/cell/cell = get_cell()
|
||||
if(cell)
|
||||
return cell.check_charge(amount * electric_cost_coefficent)
|
||||
return FALSE
|
||||
|
||||
/obj/item/weapon/rcd/electric/consume_resources(amount)
|
||||
if(!can_afford(amount))
|
||||
return FALSE
|
||||
var/obj/item/weapon/cell/cell = get_cell()
|
||||
return cell.checked_use(amount * electric_cost_coefficent)
|
||||
|
||||
/obj/item/weapon/rcd/electric/display_resources()
|
||||
var/obj/item/weapon/cell/cell = get_cell()
|
||||
if(cell)
|
||||
return "The power source connected to \the [src] has a charge of [cell.percent()]%."
|
||||
return "It lacks a source of power, and cannot function."
|
||||
|
||||
|
||||
|
||||
// 'Mounted' RCDs, used for borgs/RIGs/Mechas, all of which use their cells to drive the RCD.
|
||||
/obj/item/weapon/rcd/electric/mounted
|
||||
name = "mounted electric rapid construction device"
|
||||
desc = "A device used to rapidly build and deconstruct. It runs directly off of electricity from an external power source."
|
||||
make_cell = FALSE
|
||||
|
||||
/obj/item/weapon/rcd/electric/mounted/get_cell()
|
||||
return get_external_power_supply()
|
||||
|
||||
/obj/item/weapon/rcd/electric/mounted/proc/get_external_power_supply()
|
||||
if(isrobot(loc)) // In a borg.
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
return R.cell
|
||||
if(istype(loc, /obj/item/rig_module)) // In a RIG.
|
||||
var/obj/item/rig_module/module = loc
|
||||
if(module.holder) // Is it attached to a RIG?
|
||||
return module.holder.cell
|
||||
if(istype(loc, /obj/item/mecha_parts/mecha_equipment)) // In a mech.
|
||||
var/obj/item/mecha_parts/mecha_equipment/ME = loc
|
||||
if(ME.chassis) // Is the part attached to a mech?
|
||||
return ME.chassis.cell
|
||||
return null
|
||||
|
||||
|
||||
// RCDs for borgs.
|
||||
/obj/item/weapon/rcd/electric/mounted/borg
|
||||
can_remove_rwalls = TRUE
|
||||
desc = "A device used to rapidly build and deconstruct. It runs directly off of electricity, drawing directly from your cell."
|
||||
electric_cost_coefficent = 41.66 // Twice as efficent, out of pity.
|
||||
toolspeed = 0.5 // Twice as fast, since borg versions typically have this.
|
||||
|
||||
/obj/item/weapon/rcd/electric/mounted/borg/swarm
|
||||
can_remove_rwalls = FALSE
|
||||
name = "Rapid Assimilation Device"
|
||||
ranged = TRUE
|
||||
toolspeed = 0.7
|
||||
material_to_use = MAT_STEELHULL
|
||||
|
||||
/obj/item/weapon/rcd/electric/mounted/borg/lesser
|
||||
can_remove_rwalls = FALSE
|
||||
|
||||
|
||||
// RCDs for RIGs.
|
||||
/obj/item/weapon/rcd/electric/mounted/rig
|
||||
|
||||
|
||||
// RCDs for Mechs.
|
||||
/obj/item/weapon/rcd/electric/mounted/mecha
|
||||
ranged = TRUE
|
||||
toolspeed = 0.5
|
||||
|
||||
|
||||
// Infinite use RCD for debugging/adminbuse.
|
||||
/obj/item/weapon/rcd/debug
|
||||
name = "self-repleshing rapid construction device"
|
||||
desc = "An RCD that appears to be plated with gold. For some reason it also seems to just \
|
||||
be vastly superior to all other RCDs ever created, possibly due to it being colored gold."
|
||||
icon_state = "debug_rcd"
|
||||
ranged = TRUE
|
||||
can_remove_rwalls = TRUE
|
||||
allow_concurrent_building = TRUE
|
||||
toolspeed = 0.25 // Four times as fast.
|
||||
|
||||
/obj/item/weapon/rcd/debug/can_afford(amount)
|
||||
return TRUE
|
||||
|
||||
/obj/item/weapon/rcd/debug/consume_resources(amount)
|
||||
return TRUE
|
||||
|
||||
/obj/item/weapon/rcd/debug/attackby(obj/item/weapon/W, mob/user)
|
||||
if(istype(W, /obj/item/weapon/rcd_ammo))
|
||||
to_chat(user, span("notice", "\The [src] makes its own material, no need to add more."))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/rcd/debug/display_resources()
|
||||
return "It has UNLIMITED POWER!"
|
||||
|
||||
|
||||
|
||||
// Ammo for the (non-electric) RCDs.
|
||||
/obj/item/weapon/rcd_ammo
|
||||
name = "compressed matter cartridge"
|
||||
desc = "Highly compressed matter for the RCD."
|
||||
icon = 'icons/obj/ammo.dmi'
|
||||
icon_state = "rcd"
|
||||
item_state = "rcdammo"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
origin_tech = list(TECH_MATERIAL = 2)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 30000,MAT_GLASS = 15000)
|
||||
var/remaining = RCD_MAX_CAPACITY / 3
|
||||
|
||||
/obj/item/weapon/rcd_ammo/large
|
||||
name = "high-capacity matter cartridge"
|
||||
desc = "Do not ingest."
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 45000,MAT_GLASS = 22500)
|
||||
origin_tech = list(TECH_MATERIAL = 4)
|
||||
remaining = RCD_MAX_CAPACITY
|
||||
// Contains the rapid construction device.
|
||||
/obj/item/weapon/rcd
|
||||
name = "rapid construction device"
|
||||
desc = "A device used to rapidly build and deconstruct. Reload with compressed matter cartridges."
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "rcd"
|
||||
item_state = "rcd"
|
||||
drop_sound = 'sound/items/drop/gun.ogg'
|
||||
pickup_sound = 'sound/items/pickup/gun.ogg'
|
||||
flags = NOBLUDGEON
|
||||
force = 10
|
||||
throwforce = 10
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
origin_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 2)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 50000)
|
||||
preserve_item = TRUE // RCDs are pretty important.
|
||||
var/datum/effect/effect/system/spark_spread/spark_system
|
||||
var/stored_matter = 0
|
||||
var/max_stored_matter = RCD_MAX_CAPACITY
|
||||
var/ranged = FALSE
|
||||
var/busy = FALSE
|
||||
var/allow_concurrent_building = FALSE // If true, allows for multiple RCD builds at the same time.
|
||||
var/mode_index = 1
|
||||
var/list/modes = list(RCD_FLOORWALL, RCD_AIRLOCK, RCD_WINDOWGRILLE, RCD_DECONSTRUCT)
|
||||
var/can_remove_rwalls = FALSE
|
||||
var/airlock_type = /obj/machinery/door/airlock
|
||||
var/window_type = /obj/structure/window/reinforced/full
|
||||
var/material_to_use = DEFAULT_WALL_MATERIAL // So badmins can make RCDs that print diamond walls.
|
||||
var/make_rwalls = FALSE // If true, when building walls, they will be reinforced.
|
||||
/* VOREStation Removal - Unused
|
||||
/obj/item/weapon/rcd/Initialize()
|
||||
|
||||
src.spark_system = new /datum/effect/effect/system/spark_spread
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
return ..()
|
||||
*/
|
||||
/obj/item/weapon/rcd/Destroy()
|
||||
QDEL_NULL(spark_system)
|
||||
spark_system = null
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/rcd/examine(mob/user)
|
||||
. = ..()
|
||||
. += display_resources()
|
||||
|
||||
// Used to show how much stuff (matter units, cell charge, etc) is left inside.
|
||||
/obj/item/weapon/rcd/proc/display_resources()
|
||||
return "It currently holds [stored_matter]/[max_stored_matter] matter-units."
|
||||
|
||||
// Used to add new cartridges.
|
||||
/* VOREStation Tweak - Wow this is annoying, moved to _vr file for overhaul
|
||||
/obj/item/weapon/rcd/attackby(obj/item/weapon/W, mob/user)
|
||||
if(istype(W, /obj/item/weapon/rcd_ammo))
|
||||
var/obj/item/weapon/rcd_ammo/cartridge = W
|
||||
if((stored_matter + cartridge.remaining) > max_stored_matter)
|
||||
to_chat(user, span("warning", "The RCD can't hold that many additional matter-units."))
|
||||
return FALSE
|
||||
stored_matter += cartridge.remaining
|
||||
user.drop_from_inventory(W)
|
||||
qdel(W)
|
||||
playsound(src, 'sound/machines/click.ogg', 50, 1)
|
||||
to_chat(user, span("notice", "The RCD now holds [stored_matter]/[max_stored_matter] matter-units."))
|
||||
return TRUE
|
||||
return ..()
|
||||
*/
|
||||
// Changes which mode it is on.
|
||||
/obj/item/weapon/rcd/attack_self(mob/living/user)
|
||||
/* VOREStation Removal - Moved to VR
|
||||
if(mode_index >= modes.len) // Shouldn't overflow unless someone messes with it in VV poorly but better safe than sorry.
|
||||
mode_index = 1
|
||||
else
|
||||
mode_index++
|
||||
|
||||
to_chat(user, span("notice", "Changed mode to '[modes[mode_index]]'."))
|
||||
playsound(src, 'sound/effects/pop.ogg', 50, 0)
|
||||
|
||||
if(prob(20))
|
||||
src.spark_system.start()
|
||||
*/
|
||||
// Removes resources if the RCD can afford it.
|
||||
/obj/item/weapon/rcd/proc/consume_resources(amount)
|
||||
if(!can_afford(amount))
|
||||
return FALSE
|
||||
stored_matter -= amount
|
||||
return TRUE
|
||||
|
||||
// Useful for testing before actually paying (e.g. before a do_after() ).
|
||||
/obj/item/weapon/rcd/proc/can_afford(amount)
|
||||
return stored_matter >= amount
|
||||
|
||||
/obj/item/weapon/rcd/afterattack(atom/A, mob/living/user, proximity)
|
||||
if(!ranged && !proximity)
|
||||
return FALSE
|
||||
use_rcd(A, user)
|
||||
|
||||
// Used to call rcd_act() on the atom hit.
|
||||
/obj/item/weapon/rcd/proc/use_rcd(atom/A, mob/living/user)
|
||||
if(busy && !allow_concurrent_building)
|
||||
to_chat(user, span("warning", "\The [src] is busy finishing its current operation, be patient."))
|
||||
return FALSE
|
||||
|
||||
var/list/rcd_results = A.rcd_values(user, src, modes[mode_index])
|
||||
if(!rcd_results)
|
||||
to_chat(user, span("warning", "\The [src] blinks a red light as you point it towards \the [A], indicating \
|
||||
that it won't work. Try changing the mode, or use it on something else."))
|
||||
return FALSE
|
||||
if(!can_afford(rcd_results[RCD_VALUE_COST]))
|
||||
to_chat(user, span("warning", "\The [src] lacks the required material to start."))
|
||||
return FALSE
|
||||
|
||||
playsound(src, 'sound/machines/click.ogg', 50, 1)
|
||||
|
||||
var/true_delay = rcd_results[RCD_VALUE_DELAY] * toolspeed
|
||||
|
||||
var/datum/beam/rcd_beam = null
|
||||
if(ranged)
|
||||
var/atom/movable/beam_origin = user // This is needed because mecha pilots are inside an object and the beam won't be made if it tries to attach to them..
|
||||
if(!isturf(beam_origin.loc))
|
||||
beam_origin = user.loc
|
||||
rcd_beam = beam_origin.Beam(A, icon_state = "rped_upgrade", time = max(true_delay, 5))
|
||||
busy = TRUE
|
||||
|
||||
perform_effect(A, true_delay) //VOREStation Add
|
||||
if(do_after(user, true_delay, target = A))
|
||||
busy = FALSE
|
||||
// Doing another check in case we lost matter during the delay for whatever reason.
|
||||
if(!can_afford(rcd_results[RCD_VALUE_COST]))
|
||||
to_chat(user, span("warning", "\The [src] lacks the required material to finish the operation."))
|
||||
return FALSE
|
||||
if(A.rcd_act(user, src, rcd_results[RCD_VALUE_MODE]))
|
||||
consume_resources(rcd_results[RCD_VALUE_COST])
|
||||
playsound(A, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
return TRUE
|
||||
|
||||
// If they moved, kill the beam immediately.
|
||||
qdel(rcd_beam)
|
||||
busy = FALSE
|
||||
return FALSE
|
||||
|
||||
// RCD variants.
|
||||
|
||||
// This one starts full.
|
||||
/obj/item/weapon/rcd/loaded/Initialize()
|
||||
stored_matter = max_stored_matter
|
||||
return ..()
|
||||
|
||||
// This one makes cooler walls by using an alternative material.
|
||||
/obj/item/weapon/rcd/shipwright
|
||||
name = "shipwright's rapid construction device"
|
||||
desc = "A device used to rapidly build and deconstruct. This version creates a stronger variant of wall, often \
|
||||
used in the construction of hulls for starships. Reload with compressed matter cartridges."
|
||||
material_to_use = MAT_STEELHULL
|
||||
|
||||
/obj/item/weapon/rcd/shipwright/loaded/Initialize()
|
||||
stored_matter = max_stored_matter
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/weapon/rcd/advanced
|
||||
name = "advanced rapid construction device"
|
||||
desc = "A device used to rapidly build and deconstruct. This version works at a range, builds faster, and has a much larger capacity. \
|
||||
Reload with compressed matter cartridges."
|
||||
icon_state = "adv_rcd"
|
||||
ranged = TRUE
|
||||
toolspeed = 0.5 // Twice as fast.
|
||||
max_stored_matter = RCD_MAX_CAPACITY * 3 // Three times capacity.
|
||||
|
||||
/obj/item/weapon/rcd/advanced/loaded/Initialize()
|
||||
stored_matter = max_stored_matter
|
||||
return ..()
|
||||
|
||||
|
||||
// Electric RCDs.
|
||||
// Currently just a base for the mounted RCDs.
|
||||
// Currently there isn't a way to swap out the cells.
|
||||
// One could be added if there is demand to do so.
|
||||
/obj/item/weapon/rcd/electric
|
||||
name = "electric rapid construction device"
|
||||
desc = "A device used to rapidly build and deconstruct. It runs directly off of electricity, no matter cartridges needed."
|
||||
icon_state = "electric_rcd"
|
||||
var/obj/item/weapon/cell/cell = null
|
||||
var/make_cell = TRUE // If false, initialize() won't spawn a cell for this.
|
||||
var/electric_cost_coefficent = 83.33 // Higher numbers make it less efficent. 86.3... means it should matche the standard RCD capacity on a 10k cell.
|
||||
|
||||
/obj/item/weapon/rcd/electric/Initialize()
|
||||
if(make_cell)
|
||||
cell = new /obj/item/weapon/cell/high(src)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/rcd/electric/Destroy()
|
||||
if(cell)
|
||||
QDEL_NULL(cell)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/rcd/electric/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/item/weapon/rcd/electric/can_afford(amount) // This makes it so borgs won't drain their last sliver of charge by mistake, as a bonus.
|
||||
var/obj/item/weapon/cell/cell = get_cell()
|
||||
if(cell)
|
||||
return cell.check_charge(amount * electric_cost_coefficent)
|
||||
return FALSE
|
||||
|
||||
/obj/item/weapon/rcd/electric/consume_resources(amount)
|
||||
if(!can_afford(amount))
|
||||
return FALSE
|
||||
var/obj/item/weapon/cell/cell = get_cell()
|
||||
return cell.checked_use(amount * electric_cost_coefficent)
|
||||
|
||||
/obj/item/weapon/rcd/electric/display_resources()
|
||||
var/obj/item/weapon/cell/cell = get_cell()
|
||||
if(cell)
|
||||
return "The power source connected to \the [src] has a charge of [cell.percent()]%."
|
||||
return "It lacks a source of power, and cannot function."
|
||||
|
||||
|
||||
|
||||
// 'Mounted' RCDs, used for borgs/RIGs/Mechas, all of which use their cells to drive the RCD.
|
||||
/obj/item/weapon/rcd/electric/mounted
|
||||
name = "mounted electric rapid construction device"
|
||||
desc = "A device used to rapidly build and deconstruct. It runs directly off of electricity from an external power source."
|
||||
make_cell = FALSE
|
||||
|
||||
/obj/item/weapon/rcd/electric/mounted/get_cell()
|
||||
return get_external_power_supply()
|
||||
|
||||
/obj/item/weapon/rcd/electric/mounted/proc/get_external_power_supply()
|
||||
if(isrobot(loc)) // In a borg.
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
return R.cell
|
||||
if(istype(loc, /obj/item/rig_module)) // In a RIG.
|
||||
var/obj/item/rig_module/module = loc
|
||||
if(module.holder) // Is it attached to a RIG?
|
||||
return module.holder.cell
|
||||
if(istype(loc, /obj/item/mecha_parts/mecha_equipment)) // In a mech.
|
||||
var/obj/item/mecha_parts/mecha_equipment/ME = loc
|
||||
if(ME.chassis) // Is the part attached to a mech?
|
||||
return ME.chassis.cell
|
||||
return null
|
||||
|
||||
|
||||
// RCDs for borgs.
|
||||
/obj/item/weapon/rcd/electric/mounted/borg
|
||||
can_remove_rwalls = TRUE
|
||||
desc = "A device used to rapidly build and deconstruct. It runs directly off of electricity, drawing directly from your cell."
|
||||
electric_cost_coefficent = 41.66 // Twice as efficent, out of pity.
|
||||
toolspeed = 0.5 // Twice as fast, since borg versions typically have this.
|
||||
|
||||
/obj/item/weapon/rcd/electric/mounted/borg/swarm
|
||||
can_remove_rwalls = FALSE
|
||||
name = "Rapid Assimilation Device"
|
||||
ranged = TRUE
|
||||
toolspeed = 0.7
|
||||
material_to_use = MAT_STEELHULL
|
||||
|
||||
/obj/item/weapon/rcd/electric/mounted/borg/lesser
|
||||
can_remove_rwalls = FALSE
|
||||
|
||||
|
||||
// RCDs for RIGs.
|
||||
/obj/item/weapon/rcd/electric/mounted/rig
|
||||
|
||||
|
||||
// RCDs for Mechs.
|
||||
/obj/item/weapon/rcd/electric/mounted/mecha
|
||||
ranged = TRUE
|
||||
toolspeed = 0.5
|
||||
|
||||
|
||||
// Infinite use RCD for debugging/adminbuse.
|
||||
/obj/item/weapon/rcd/debug
|
||||
name = "self-repleshing rapid construction device"
|
||||
desc = "An RCD that appears to be plated with gold. For some reason it also seems to just \
|
||||
be vastly superior to all other RCDs ever created, possibly due to it being colored gold."
|
||||
icon_state = "debug_rcd"
|
||||
ranged = TRUE
|
||||
can_remove_rwalls = TRUE
|
||||
allow_concurrent_building = TRUE
|
||||
toolspeed = 0.25 // Four times as fast.
|
||||
|
||||
/obj/item/weapon/rcd/debug/can_afford(amount)
|
||||
return TRUE
|
||||
|
||||
/obj/item/weapon/rcd/debug/consume_resources(amount)
|
||||
return TRUE
|
||||
|
||||
/obj/item/weapon/rcd/debug/attackby(obj/item/weapon/W, mob/user)
|
||||
if(istype(W, /obj/item/weapon/rcd_ammo))
|
||||
to_chat(user, span("notice", "\The [src] makes its own material, no need to add more."))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/rcd/debug/display_resources()
|
||||
return "It has UNLIMITED POWER!"
|
||||
|
||||
|
||||
|
||||
// Ammo for the (non-electric) RCDs.
|
||||
/obj/item/weapon/rcd_ammo
|
||||
name = "compressed matter cartridge"
|
||||
desc = "Highly compressed matter for the RCD."
|
||||
icon = 'icons/obj/ammo.dmi'
|
||||
icon_state = "rcd"
|
||||
item_state = "rcdammo"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
origin_tech = list(TECH_MATERIAL = 2)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 30000,MAT_GLASS = 15000)
|
||||
var/remaining = RCD_MAX_CAPACITY / 3
|
||||
|
||||
/obj/item/weapon/rcd_ammo/large
|
||||
name = "high-capacity matter cartridge"
|
||||
desc = "Do not ingest."
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 45000,MAT_GLASS = 22500)
|
||||
origin_tech = list(TECH_MATERIAL = 4)
|
||||
remaining = RCD_MAX_CAPACITY
|
||||
|
||||
@@ -1,136 +1,136 @@
|
||||
/*
|
||||
CONTAINS:
|
||||
RSF
|
||||
|
||||
*/
|
||||
|
||||
/obj/item/weapon/rsf
|
||||
name = "\improper Rapid-Service-Fabricator"
|
||||
desc = "A device used to rapidly deploy service items."
|
||||
description_info = "Control Clicking on the device will allow you to choose the glass it dispenses when in the proper mode."
|
||||
icon = 'icons/obj/tools_vr.dmi' //VOREStation Edit
|
||||
icon_state = "rsf" //VOREStation Edit
|
||||
opacity = 0
|
||||
density = FALSE
|
||||
anchored = FALSE
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 25000)
|
||||
var/stored_matter = 30
|
||||
var/mode = 1
|
||||
var/obj/item/weapon/reagent_containers/glasstype = /obj/item/weapon/reagent_containers/food/drinks/metaglass
|
||||
|
||||
var/list/container_types = list(
|
||||
"metamorphic glass" = /obj/item/weapon/reagent_containers/food/drinks/metaglass,
|
||||
"metamorphic pint glass" = /obj/item/weapon/reagent_containers/food/drinks/metaglass/metapint,
|
||||
"half-pint glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/square,
|
||||
"rocks glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/rocks,
|
||||
"milkshake glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/shake,
|
||||
"cocktail glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/cocktail,
|
||||
"shot glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/shot,
|
||||
"pint glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/pint,
|
||||
"mug" = /obj/item/weapon/reagent_containers/food/drinks/glass2/mug,
|
||||
"wine glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/wine,
|
||||
"condiment bottle" = /obj/item/weapon/reagent_containers/food/condiment
|
||||
)
|
||||
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
|
||||
/obj/item/weapon/rsf/examine(mob/user)
|
||||
. = ..()
|
||||
if(get_dist(user, src) == 0)
|
||||
. += "<span class='notice'>It currently holds [stored_matter]/30 fabrication-units.</span>"
|
||||
|
||||
/obj/item/weapon/rsf/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
..()
|
||||
if (istype(W, /obj/item/weapon/rcd_ammo))
|
||||
|
||||
if ((stored_matter + 10) > 30)
|
||||
to_chat(user, "<span class='warning'>The RSF can't hold any more matter.</span>")
|
||||
return
|
||||
|
||||
qdel(W)
|
||||
|
||||
stored_matter += 10
|
||||
playsound(src, 'sound/machines/click.ogg', 10, 1)
|
||||
to_chat(user,"<span class='notice'>The RSF now holds [stored_matter]/30 fabrication-units.</span>")
|
||||
return
|
||||
|
||||
/obj/item/weapon/rsf/CtrlClick(mob/living/user)
|
||||
if(!Adjacent(user) || !istype(user))
|
||||
to_chat(user,"<span class='notice'>You are too far away.</span>")
|
||||
return
|
||||
var/glass_choice = tgui_input_list(user, "Please choose which type of glass you would like to produce.", "Glass Choice", container_types)
|
||||
|
||||
if(glass_choice)
|
||||
glasstype = container_types[glass_choice]
|
||||
else
|
||||
glasstype = /obj/item/weapon/reagent_containers/food/drinks/metaglass
|
||||
|
||||
/obj/item/weapon/rsf/attack_self(mob/user as mob)
|
||||
playsound(src, 'sound/effects/pop.ogg', 50, 0)
|
||||
if (mode == 1)
|
||||
mode = 2
|
||||
to_chat(user,"<span class='notice'>Changed dispensing mode to 'Container'.</span>")
|
||||
return
|
||||
if (mode == 2)
|
||||
mode = 3
|
||||
to_chat(user,"<span class='notice'>Changed dispensing mode to 'Paper'</span>")
|
||||
return
|
||||
if (mode == 3)
|
||||
mode = 4
|
||||
to_chat(user,"<span class='notice'>Changed dispensing mode to 'Pen'</span>")
|
||||
return
|
||||
if (mode == 4)
|
||||
mode = 5
|
||||
to_chat(user,"<span class='notice'>Changed dispensing mode to 'Dice Pack'</span>")
|
||||
return
|
||||
if (mode == 5)
|
||||
mode = 1
|
||||
to_chat(user,"<span class='notice'>Changed dispensing mode to 'Cigarette'</span>")
|
||||
return
|
||||
|
||||
/obj/item/weapon/rsf/afterattack(atom/A, mob/user as mob, proximity)
|
||||
|
||||
if(!proximity) return
|
||||
|
||||
if(istype(user,/mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(R.stat || !R.cell || R.cell.charge <= 0)
|
||||
return
|
||||
else
|
||||
if(stored_matter <= 0)
|
||||
return
|
||||
|
||||
if(!istype(A, /obj/structure/table) && !istype(A, /turf/simulated/floor))
|
||||
return
|
||||
|
||||
playsound(src, 'sound/machines/click.ogg', 10, 1)
|
||||
var/used_energy = 0
|
||||
var/obj/product
|
||||
|
||||
switch(mode)
|
||||
if(1)
|
||||
product = new /obj/item/clothing/mask/smokable/cigarette()
|
||||
used_energy = 10
|
||||
if(2)
|
||||
product = new glasstype()
|
||||
used_energy = 50
|
||||
if(3)
|
||||
product = new /obj/item/weapon/paper()
|
||||
used_energy = 10
|
||||
if(4)
|
||||
product = new /obj/item/weapon/pen()
|
||||
used_energy = 50
|
||||
if(5)
|
||||
product = new /obj/item/weapon/storage/pill_bottle/dice()
|
||||
used_energy = 200
|
||||
|
||||
to_chat(user,"<span class='notice'>Dispensing [product ? product : "product"]...</span>")
|
||||
product.loc = get_turf(A)
|
||||
|
||||
if(isrobot(user))
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(R.cell)
|
||||
R.cell.use(used_energy)
|
||||
else
|
||||
stored_matter--
|
||||
to_chat(user,"<span class='notice'>The RSF now holds [stored_matter]/30 fabrication-units.</span>")
|
||||
/*
|
||||
CONTAINS:
|
||||
RSF
|
||||
|
||||
*/
|
||||
|
||||
/obj/item/weapon/rsf
|
||||
name = "\improper Rapid-Service-Fabricator"
|
||||
desc = "A device used to rapidly deploy service items."
|
||||
description_info = "Control Clicking on the device will allow you to choose the glass it dispenses when in the proper mode."
|
||||
icon = 'icons/obj/tools_vr.dmi' //VOREStation Edit
|
||||
icon_state = "rsf" //VOREStation Edit
|
||||
opacity = 0
|
||||
density = FALSE
|
||||
anchored = FALSE
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 25000)
|
||||
var/stored_matter = 30
|
||||
var/mode = 1
|
||||
var/obj/item/weapon/reagent_containers/glasstype = /obj/item/weapon/reagent_containers/food/drinks/metaglass
|
||||
|
||||
var/list/container_types = list(
|
||||
"metamorphic glass" = /obj/item/weapon/reagent_containers/food/drinks/metaglass,
|
||||
"metamorphic pint glass" = /obj/item/weapon/reagent_containers/food/drinks/metaglass/metapint,
|
||||
"half-pint glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/square,
|
||||
"rocks glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/rocks,
|
||||
"milkshake glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/shake,
|
||||
"cocktail glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/cocktail,
|
||||
"shot glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/shot,
|
||||
"pint glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/pint,
|
||||
"mug" = /obj/item/weapon/reagent_containers/food/drinks/glass2/mug,
|
||||
"wine glass" = /obj/item/weapon/reagent_containers/food/drinks/glass2/wine,
|
||||
"condiment bottle" = /obj/item/weapon/reagent_containers/food/condiment
|
||||
)
|
||||
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
|
||||
/obj/item/weapon/rsf/examine(mob/user)
|
||||
. = ..()
|
||||
if(get_dist(user, src) == 0)
|
||||
. += "<span class='notice'>It currently holds [stored_matter]/30 fabrication-units.</span>"
|
||||
|
||||
/obj/item/weapon/rsf/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
..()
|
||||
if (istype(W, /obj/item/weapon/rcd_ammo))
|
||||
|
||||
if ((stored_matter + 10) > 30)
|
||||
to_chat(user, "<span class='warning'>The RSF can't hold any more matter.</span>")
|
||||
return
|
||||
|
||||
qdel(W)
|
||||
|
||||
stored_matter += 10
|
||||
playsound(src, 'sound/machines/click.ogg', 10, 1)
|
||||
to_chat(user,"<span class='notice'>The RSF now holds [stored_matter]/30 fabrication-units.</span>")
|
||||
return
|
||||
|
||||
/obj/item/weapon/rsf/CtrlClick(mob/living/user)
|
||||
if(!Adjacent(user) || !istype(user))
|
||||
to_chat(user,"<span class='notice'>You are too far away.</span>")
|
||||
return
|
||||
var/glass_choice = tgui_input_list(user, "Please choose which type of glass you would like to produce.", "Glass Choice", container_types)
|
||||
|
||||
if(glass_choice)
|
||||
glasstype = container_types[glass_choice]
|
||||
else
|
||||
glasstype = /obj/item/weapon/reagent_containers/food/drinks/metaglass
|
||||
|
||||
/obj/item/weapon/rsf/attack_self(mob/user as mob)
|
||||
playsound(src, 'sound/effects/pop.ogg', 50, 0)
|
||||
if (mode == 1)
|
||||
mode = 2
|
||||
to_chat(user,"<span class='notice'>Changed dispensing mode to 'Container'.</span>")
|
||||
return
|
||||
if (mode == 2)
|
||||
mode = 3
|
||||
to_chat(user,"<span class='notice'>Changed dispensing mode to 'Paper'</span>")
|
||||
return
|
||||
if (mode == 3)
|
||||
mode = 4
|
||||
to_chat(user,"<span class='notice'>Changed dispensing mode to 'Pen'</span>")
|
||||
return
|
||||
if (mode == 4)
|
||||
mode = 5
|
||||
to_chat(user,"<span class='notice'>Changed dispensing mode to 'Dice Pack'</span>")
|
||||
return
|
||||
if (mode == 5)
|
||||
mode = 1
|
||||
to_chat(user,"<span class='notice'>Changed dispensing mode to 'Cigarette'</span>")
|
||||
return
|
||||
|
||||
/obj/item/weapon/rsf/afterattack(atom/A, mob/user as mob, proximity)
|
||||
|
||||
if(!proximity) return
|
||||
|
||||
if(istype(user,/mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(R.stat || !R.cell || R.cell.charge <= 0)
|
||||
return
|
||||
else
|
||||
if(stored_matter <= 0)
|
||||
return
|
||||
|
||||
if(!istype(A, /obj/structure/table) && !istype(A, /turf/simulated/floor))
|
||||
return
|
||||
|
||||
playsound(src, 'sound/machines/click.ogg', 10, 1)
|
||||
var/used_energy = 0
|
||||
var/obj/product
|
||||
|
||||
switch(mode)
|
||||
if(1)
|
||||
product = new /obj/item/clothing/mask/smokable/cigarette()
|
||||
used_energy = 10
|
||||
if(2)
|
||||
product = new glasstype()
|
||||
used_energy = 50
|
||||
if(3)
|
||||
product = new /obj/item/weapon/paper()
|
||||
used_energy = 10
|
||||
if(4)
|
||||
product = new /obj/item/weapon/pen()
|
||||
used_energy = 50
|
||||
if(5)
|
||||
product = new /obj/item/weapon/storage/pill_bottle/dice()
|
||||
used_energy = 200
|
||||
|
||||
to_chat(user,"<span class='notice'>Dispensing [product ? product : "product"]...</span>")
|
||||
product.loc = get_turf(A)
|
||||
|
||||
if(isrobot(user))
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(R.cell)
|
||||
R.cell.use(used_energy)
|
||||
else
|
||||
stored_matter--
|
||||
to_chat(user,"<span class='notice'>The RSF now holds [stored_matter]/30 fabrication-units.</span>")
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
// **For augment items that aren't subtypes of other things.**
|
||||
|
||||
/obj/item/weapon/melee/augment
|
||||
name = "integrated item"
|
||||
desc = "A surprisingly non-descript item, integrated into its user. You probably shouldn't be seeing this."
|
||||
icon = 'icons/obj/surgery.dmi'
|
||||
icon_state = "augment_box"
|
||||
|
||||
|
||||
/obj/item/weapon/melee/augment/blade
|
||||
name = "handblade"
|
||||
desc = "A sleek-looking telescopic blade that fits inside the hand. Favored by infiltration specialists and assassins."
|
||||
icon_state = "augment_handblade"
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_melee.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
|
||||
)
|
||||
w_class = ITEMSIZE_SMALL
|
||||
force = 15
|
||||
armor_penetration = 25
|
||||
sharp = TRUE
|
||||
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
defend_chance = 10
|
||||
projectile_parry_chance = 5
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
|
||||
/obj/item/weapon/melee/augment/blade/arm
|
||||
name = "armblade"
|
||||
desc = "A sleek-looking cybernetic blade that cleaves through people like butter. Favored by psychopaths and assassins."
|
||||
icon_state = "augment_armblade"
|
||||
w_class = ITEMSIZE_HUGE
|
||||
force = 30
|
||||
armor_penetration = 15
|
||||
edge = TRUE
|
||||
pry = 1
|
||||
defend_chance = 40
|
||||
// **For augment items that aren't subtypes of other things.**
|
||||
|
||||
/obj/item/weapon/melee/augment
|
||||
name = "integrated item"
|
||||
desc = "A surprisingly non-descript item, integrated into its user. You probably shouldn't be seeing this."
|
||||
icon = 'icons/obj/surgery.dmi'
|
||||
icon_state = "augment_box"
|
||||
|
||||
|
||||
/obj/item/weapon/melee/augment/blade
|
||||
name = "handblade"
|
||||
desc = "A sleek-looking telescopic blade that fits inside the hand. Favored by infiltration specialists and assassins."
|
||||
icon_state = "augment_handblade"
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_melee.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
|
||||
)
|
||||
w_class = ITEMSIZE_SMALL
|
||||
force = 15
|
||||
armor_penetration = 25
|
||||
sharp = TRUE
|
||||
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
defend_chance = 10
|
||||
projectile_parry_chance = 5
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
|
||||
/obj/item/weapon/melee/augment/blade/arm
|
||||
name = "armblade"
|
||||
desc = "A sleek-looking cybernetic blade that cleaves through people like butter. Favored by psychopaths and assassins."
|
||||
icon_state = "augment_armblade"
|
||||
w_class = ITEMSIZE_HUGE
|
||||
force = 30
|
||||
armor_penetration = 15
|
||||
edge = TRUE
|
||||
pry = 1
|
||||
defend_chance = 40
|
||||
projectile_parry_chance = 20
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,74 +1,74 @@
|
||||
/obj/item/weapon/circuitboard/microwave
|
||||
name = T_BOARD("microwave")
|
||||
desc = "The circuitboard for a microwave."
|
||||
build_path = /obj/machinery/microwave
|
||||
board_type = new /datum/frame/frame_types/microwave
|
||||
contain_parts = 0
|
||||
matter = list(MAT_STEEL = 50, MAT_GLASS = 50)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/console_screen = 1,
|
||||
/obj/item/weapon/stock_parts/capacitor = 3, // Original Capacitor count was 1
|
||||
/obj/item/weapon/stock_parts/motor = 1,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/oven
|
||||
name = T_BOARD("oven")
|
||||
desc = "The circuitboard for an oven."
|
||||
build_path = /obj/machinery/appliance/cooker/oven
|
||||
board_type = new /datum/frame/frame_types/machine
|
||||
matter = list(MAT_STEEL = 50, MAT_GLASS = 50)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/capacitor = 3,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/fryer
|
||||
name = T_BOARD("deep fryer")
|
||||
desc = "The circuitboard for a deep fryer."
|
||||
build_path = /obj/machinery/appliance/cooker/fryer
|
||||
board_type = new /datum/frame/frame_types/machine
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/capacitor = 3,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/grill
|
||||
name = T_BOARD("grill")
|
||||
desc = "The circuitboard for an industrial grill."
|
||||
build_path = /obj/machinery/appliance/cooker/grill
|
||||
board_type = new /datum/frame/frame_types/machine
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/capacitor = 3,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/cerealmaker
|
||||
name = T_BOARD("cereal maker")
|
||||
desc = "The circuitboard for a cereal maker."
|
||||
build_path = /obj/machinery/appliance/mixer/cereal
|
||||
board_type = new /datum/frame/frame_types/machine
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/capacitor = 3,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/candymachine
|
||||
name = T_BOARD("candy machine")
|
||||
desc = "The circuitboard for a candy machine."
|
||||
build_path = /obj/machinery/appliance/mixer/candy
|
||||
board_type = new /datum/frame/frame_types/machine
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/capacitor = 3,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/microwave/advanced
|
||||
name = T_BOARD("deluxe microwave")
|
||||
build_path = /obj/machinery/microwave/advanced
|
||||
board_type = new /datum/frame/frame_types/microwave
|
||||
matter = list(MAT_STEEL = 50, MAT_GLASS = 50)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/console_screen = 1,
|
||||
/obj/item/weapon/stock_parts/motor = 1,
|
||||
/obj/item/weapon/circuitboard/microwave
|
||||
name = T_BOARD("microwave")
|
||||
desc = "The circuitboard for a microwave."
|
||||
build_path = /obj/machinery/microwave
|
||||
board_type = new /datum/frame/frame_types/microwave
|
||||
contain_parts = 0
|
||||
matter = list(MAT_STEEL = 50, MAT_GLASS = 50)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/console_screen = 1,
|
||||
/obj/item/weapon/stock_parts/capacitor = 3, // Original Capacitor count was 1
|
||||
/obj/item/weapon/stock_parts/motor = 1,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/oven
|
||||
name = T_BOARD("oven")
|
||||
desc = "The circuitboard for an oven."
|
||||
build_path = /obj/machinery/appliance/cooker/oven
|
||||
board_type = new /datum/frame/frame_types/machine
|
||||
matter = list(MAT_STEEL = 50, MAT_GLASS = 50)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/capacitor = 3,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/fryer
|
||||
name = T_BOARD("deep fryer")
|
||||
desc = "The circuitboard for a deep fryer."
|
||||
build_path = /obj/machinery/appliance/cooker/fryer
|
||||
board_type = new /datum/frame/frame_types/machine
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/capacitor = 3,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/grill
|
||||
name = T_BOARD("grill")
|
||||
desc = "The circuitboard for an industrial grill."
|
||||
build_path = /obj/machinery/appliance/cooker/grill
|
||||
board_type = new /datum/frame/frame_types/machine
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/capacitor = 3,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/cerealmaker
|
||||
name = T_BOARD("cereal maker")
|
||||
desc = "The circuitboard for a cereal maker."
|
||||
build_path = /obj/machinery/appliance/mixer/cereal
|
||||
board_type = new /datum/frame/frame_types/machine
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/capacitor = 3,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/candymachine
|
||||
name = T_BOARD("candy machine")
|
||||
desc = "The circuitboard for a candy machine."
|
||||
build_path = /obj/machinery/appliance/mixer/candy
|
||||
board_type = new /datum/frame/frame_types/machine
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/capacitor = 3,
|
||||
/obj/item/weapon/stock_parts/scanning_module = 1,
|
||||
/obj/item/weapon/stock_parts/matter_bin = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/microwave/advanced
|
||||
name = T_BOARD("deluxe microwave")
|
||||
build_path = /obj/machinery/microwave/advanced
|
||||
board_type = new /datum/frame/frame_types/microwave
|
||||
matter = list(MAT_STEEL = 50, MAT_GLASS = 50)
|
||||
req_components = list(
|
||||
/obj/item/weapon/stock_parts/console_screen = 1,
|
||||
/obj/item/weapon/stock_parts/motor = 1,
|
||||
/obj/item/weapon/stock_parts/capacitor = 1)
|
||||
@@ -1,87 +1,87 @@
|
||||
/* Clown Items
|
||||
* Contains:
|
||||
* Banana Peels
|
||||
* Soap
|
||||
* Bike Horns
|
||||
*/
|
||||
|
||||
/*
|
||||
* Banana Peels
|
||||
*/
|
||||
/obj/item/weapon/bananapeel/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
if(istype(AM, /mob/living))
|
||||
var/mob/living/M = AM
|
||||
M.slip("the [src.name]",4)
|
||||
/*
|
||||
* Soap
|
||||
*/
|
||||
/obj/item/weapon/soap/Initialize()
|
||||
. = ..()
|
||||
create_reagents(5)
|
||||
wet()
|
||||
|
||||
/obj/item/weapon/soap/proc/wet()
|
||||
reagents.add_reagent("cleaner", 5)
|
||||
|
||||
/obj/item/weapon/soap/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
if(istype(AM, /mob/living))
|
||||
var/mob/living/M = AM
|
||||
M.slip("the [src.name]",3)
|
||||
|
||||
/obj/item/weapon/soap/afterattack(atom/target, mob/user as mob, proximity)
|
||||
if(!proximity) return
|
||||
//I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing.
|
||||
//So this is a workaround. This also makes more sense from an IC standpoint. ~Carn
|
||||
if(user.client && (target in user.client.screen))
|
||||
to_chat(user, "<span class='notice'>You need to take that [target.name] off before cleaning it.</span>")
|
||||
else if(istype(target,/obj/effect/decal/cleanable/blood))
|
||||
to_chat(user, "<span class='notice'>You scrub \the [target.name] out.</span>")
|
||||
target.clean_blood()
|
||||
return //Blood is a cleanable decal, therefore needs to be accounted for before all cleanable decals.
|
||||
else if(istype(target,/obj/effect/decal/cleanable))
|
||||
to_chat(user, "<span class='notice'>You scrub \the [target.name] out.</span>")
|
||||
qdel(target)
|
||||
else if(istype(target,/turf))
|
||||
to_chat(user, "<span class='notice'>You scrub \the [target.name] clean.</span>")
|
||||
var/turf/T = target
|
||||
T.clean(src, user)
|
||||
else if(istype(target,/obj/structure/sink))
|
||||
to_chat(user, "<span class='notice'>You wet \the [src] in the sink.</span>")
|
||||
wet()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You clean \the [target.name].</span>")
|
||||
target.clean_blood(TRUE)
|
||||
return
|
||||
|
||||
//attack_as_weapon
|
||||
/obj/item/weapon/soap/attack(mob/living/target, mob/living/user, var/target_zone)
|
||||
if(target && user && ishuman(target) && ishuman(user) && !user.incapacitated() && user.zone_sel &&user.zone_sel.selecting == "mouth" )
|
||||
user.visible_message("<span class='danger'>\The [user] washes \the [target]'s mouth out with soap!</span>")
|
||||
user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) //prevent spam
|
||||
return
|
||||
..()
|
||||
|
||||
/*
|
||||
* Bike Horns
|
||||
*/
|
||||
/obj/item/weapon/bikehorn
|
||||
var/honk_sound = 'sound/items/bikehorn.ogg'
|
||||
|
||||
/obj/item/weapon/bikehorn/attack_self(mob/user as mob)
|
||||
if(spam_flag == 0)
|
||||
spam_flag = 1
|
||||
playsound(src, honk_sound, 50, 1)
|
||||
src.add_fingerprint(user)
|
||||
spawn(20)
|
||||
spam_flag = 0
|
||||
return
|
||||
|
||||
/obj/item/weapon/bikehorn/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
if(istype(AM, /mob/living))
|
||||
playsound(src, honk_sound, 50, 1)
|
||||
/* Clown Items
|
||||
* Contains:
|
||||
* Banana Peels
|
||||
* Soap
|
||||
* Bike Horns
|
||||
*/
|
||||
|
||||
/*
|
||||
* Banana Peels
|
||||
*/
|
||||
/obj/item/weapon/bananapeel/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
if(istype(AM, /mob/living))
|
||||
var/mob/living/M = AM
|
||||
M.slip("the [src.name]",4)
|
||||
/*
|
||||
* Soap
|
||||
*/
|
||||
/obj/item/weapon/soap/Initialize()
|
||||
. = ..()
|
||||
create_reagents(5)
|
||||
wet()
|
||||
|
||||
/obj/item/weapon/soap/proc/wet()
|
||||
reagents.add_reagent("cleaner", 5)
|
||||
|
||||
/obj/item/weapon/soap/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
if(istype(AM, /mob/living))
|
||||
var/mob/living/M = AM
|
||||
M.slip("the [src.name]",3)
|
||||
|
||||
/obj/item/weapon/soap/afterattack(atom/target, mob/user as mob, proximity)
|
||||
if(!proximity) return
|
||||
//I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing.
|
||||
//So this is a workaround. This also makes more sense from an IC standpoint. ~Carn
|
||||
if(user.client && (target in user.client.screen))
|
||||
to_chat(user, "<span class='notice'>You need to take that [target.name] off before cleaning it.</span>")
|
||||
else if(istype(target,/obj/effect/decal/cleanable/blood))
|
||||
to_chat(user, "<span class='notice'>You scrub \the [target.name] out.</span>")
|
||||
target.clean_blood()
|
||||
return //Blood is a cleanable decal, therefore needs to be accounted for before all cleanable decals.
|
||||
else if(istype(target,/obj/effect/decal/cleanable))
|
||||
to_chat(user, "<span class='notice'>You scrub \the [target.name] out.</span>")
|
||||
qdel(target)
|
||||
else if(istype(target,/turf))
|
||||
to_chat(user, "<span class='notice'>You scrub \the [target.name] clean.</span>")
|
||||
var/turf/T = target
|
||||
T.clean(src, user)
|
||||
else if(istype(target,/obj/structure/sink))
|
||||
to_chat(user, "<span class='notice'>You wet \the [src] in the sink.</span>")
|
||||
wet()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You clean \the [target.name].</span>")
|
||||
target.clean_blood(TRUE)
|
||||
return
|
||||
|
||||
//attack_as_weapon
|
||||
/obj/item/weapon/soap/attack(mob/living/target, mob/living/user, var/target_zone)
|
||||
if(target && user && ishuman(target) && ishuman(user) && !user.incapacitated() && user.zone_sel &&user.zone_sel.selecting == "mouth" )
|
||||
user.visible_message("<span class='danger'>\The [user] washes \the [target]'s mouth out with soap!</span>")
|
||||
user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) //prevent spam
|
||||
return
|
||||
..()
|
||||
|
||||
/*
|
||||
* Bike Horns
|
||||
*/
|
||||
/obj/item/weapon/bikehorn
|
||||
var/honk_sound = 'sound/items/bikehorn.ogg'
|
||||
|
||||
/obj/item/weapon/bikehorn/attack_self(mob/user as mob)
|
||||
if(spam_flag == 0)
|
||||
spam_flag = 1
|
||||
playsound(src, honk_sound, 50, 1)
|
||||
src.add_fingerprint(user)
|
||||
spawn(20)
|
||||
spam_flag = 0
|
||||
return
|
||||
|
||||
/obj/item/weapon/bikehorn/Crossed(atom/movable/AM as mob|obj)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
if(istype(AM, /mob/living))
|
||||
playsound(src, honk_sound, 50, 1)
|
||||
|
||||
@@ -1,113 +1,113 @@
|
||||
/obj/item/weapon/lipstick
|
||||
gender = PLURAL
|
||||
name = "red lipstick"
|
||||
desc = "A generic brand of lipstick."
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "lipstick"
|
||||
w_class = ITEMSIZE_TINY
|
||||
slot_flags = SLOT_EARS
|
||||
var/colour = "red"
|
||||
var/open = 0
|
||||
drop_sound = 'sound/items/drop/glass.ogg'
|
||||
pickup_sound = 'sound/items/pickup/glass.ogg'
|
||||
|
||||
/obj/item/weapon/lipstick/purple
|
||||
name = "purple lipstick"
|
||||
colour = "purple"
|
||||
|
||||
/obj/item/weapon/lipstick/jade
|
||||
name = "jade lipstick"
|
||||
colour = "jade"
|
||||
|
||||
/obj/item/weapon/lipstick/black
|
||||
name = "black lipstick"
|
||||
colour = "black"
|
||||
|
||||
/obj/item/weapon/lipstick/random
|
||||
name = "lipstick"
|
||||
|
||||
/obj/item/weapon/lipstick/random/New()
|
||||
colour = pick("red","purple","jade","black")
|
||||
name = "[colour] lipstick"
|
||||
|
||||
/obj/item/weapon/lipstick/attack_self(mob/user as mob)
|
||||
to_chat(user, "<span class='notice'>You twist \the [src] [open ? "closed" : "open"].</span>")
|
||||
open = !open
|
||||
if(open)
|
||||
icon_state = "[initial(icon_state)]_[colour]"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/obj/item/weapon/lipstick/attack(mob/M as mob, mob/user as mob)
|
||||
if(!open) return
|
||||
|
||||
if(!istype(M, /mob)) return
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.lip_style) //if they already have lipstick on
|
||||
to_chat(user, "<span class='notice'>You need to wipe off the old lipstick first!</span>")
|
||||
return
|
||||
if(H == user)
|
||||
user.visible_message("<span class='notice'>[user] does their lips with \the [src].</span>", \
|
||||
"<span class='notice'>You take a moment to apply \the [src]. Perfect!</span>")
|
||||
H.lip_style = colour
|
||||
H.update_icons_body()
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] begins to do [H]'s lips with \the [src].</span>", \
|
||||
"<span class='notice'>You begin to apply \the [src].</span>")
|
||||
if(do_after(user, 20, H)) //user needs to keep their active hand, H does not.
|
||||
user.visible_message("<span class='notice'>[user] does [H]'s lips with \the [src].</span>", \
|
||||
"<span class='notice'>You apply \the [src].</span>")
|
||||
H.lip_style = colour
|
||||
H.update_icons_body()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>Where are the lips on that?</span>")
|
||||
|
||||
//you can wipe off lipstick with paper! see code/modules/paperwork/paper.dm, paper/attack()
|
||||
|
||||
/obj/item/weapon/haircomb //sparklysheep's comb
|
||||
name = "purple comb"
|
||||
desc = "A pristine purple comb made from flexible plastic."
|
||||
w_class = ITEMSIZE_TINY
|
||||
slot_flags = SLOT_EARS
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "purplecomb"
|
||||
|
||||
/obj/item/weapon/haircomb/attack_self(mob/living/user)
|
||||
var/text = "person"
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/U = user
|
||||
switch(U.identifying_gender)
|
||||
if(MALE)
|
||||
text = "guy"
|
||||
if(FEMALE)
|
||||
text = "lady"
|
||||
else
|
||||
switch(user.gender)
|
||||
if(MALE)
|
||||
text = "guy"
|
||||
if(FEMALE)
|
||||
text = "lady"
|
||||
user.visible_message("<span class='notice'>[user] uses [src] to comb their hair with incredible style and sophistication. What a [text].</span>")
|
||||
|
||||
/obj/item/weapon/makeover
|
||||
name = "makeover kit"
|
||||
desc = "A tiny case containing a mirror and some contact lenses."
|
||||
w_class = ITEMSIZE_TINY
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "trinketbox"
|
||||
var/datum/tgui_module/appearance_changer/mirror/coskit/M
|
||||
|
||||
/obj/item/weapon/makeover/Initialize()
|
||||
. = ..()
|
||||
M = new(src, null)
|
||||
|
||||
/obj/item/weapon/makeover/attack_self(mob/living/carbon/user as mob)
|
||||
if(ishuman(user))
|
||||
to_chat(user, "<span class='notice'>You flip open \the [src] and begin to adjust your appearance.</span>")
|
||||
M.tgui_interact(user)
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
|
||||
if(istype(E))
|
||||
/obj/item/weapon/lipstick
|
||||
gender = PLURAL
|
||||
name = "red lipstick"
|
||||
desc = "A generic brand of lipstick."
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "lipstick"
|
||||
w_class = ITEMSIZE_TINY
|
||||
slot_flags = SLOT_EARS
|
||||
var/colour = "red"
|
||||
var/open = 0
|
||||
drop_sound = 'sound/items/drop/glass.ogg'
|
||||
pickup_sound = 'sound/items/pickup/glass.ogg'
|
||||
|
||||
/obj/item/weapon/lipstick/purple
|
||||
name = "purple lipstick"
|
||||
colour = "purple"
|
||||
|
||||
/obj/item/weapon/lipstick/jade
|
||||
name = "jade lipstick"
|
||||
colour = "jade"
|
||||
|
||||
/obj/item/weapon/lipstick/black
|
||||
name = "black lipstick"
|
||||
colour = "black"
|
||||
|
||||
/obj/item/weapon/lipstick/random
|
||||
name = "lipstick"
|
||||
|
||||
/obj/item/weapon/lipstick/random/New()
|
||||
colour = pick("red","purple","jade","black")
|
||||
name = "[colour] lipstick"
|
||||
|
||||
/obj/item/weapon/lipstick/attack_self(mob/user as mob)
|
||||
to_chat(user, "<span class='notice'>You twist \the [src] [open ? "closed" : "open"].</span>")
|
||||
open = !open
|
||||
if(open)
|
||||
icon_state = "[initial(icon_state)]_[colour]"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/obj/item/weapon/lipstick/attack(mob/M as mob, mob/user as mob)
|
||||
if(!open) return
|
||||
|
||||
if(!istype(M, /mob)) return
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.lip_style) //if they already have lipstick on
|
||||
to_chat(user, "<span class='notice'>You need to wipe off the old lipstick first!</span>")
|
||||
return
|
||||
if(H == user)
|
||||
user.visible_message("<span class='notice'>[user] does their lips with \the [src].</span>", \
|
||||
"<span class='notice'>You take a moment to apply \the [src]. Perfect!</span>")
|
||||
H.lip_style = colour
|
||||
H.update_icons_body()
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] begins to do [H]'s lips with \the [src].</span>", \
|
||||
"<span class='notice'>You begin to apply \the [src].</span>")
|
||||
if(do_after(user, 20, H)) //user needs to keep their active hand, H does not.
|
||||
user.visible_message("<span class='notice'>[user] does [H]'s lips with \the [src].</span>", \
|
||||
"<span class='notice'>You apply \the [src].</span>")
|
||||
H.lip_style = colour
|
||||
H.update_icons_body()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>Where are the lips on that?</span>")
|
||||
|
||||
//you can wipe off lipstick with paper! see code/modules/paperwork/paper.dm, paper/attack()
|
||||
|
||||
/obj/item/weapon/haircomb //sparklysheep's comb
|
||||
name = "purple comb"
|
||||
desc = "A pristine purple comb made from flexible plastic."
|
||||
w_class = ITEMSIZE_TINY
|
||||
slot_flags = SLOT_EARS
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "purplecomb"
|
||||
|
||||
/obj/item/weapon/haircomb/attack_self(mob/living/user)
|
||||
var/text = "person"
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/U = user
|
||||
switch(U.identifying_gender)
|
||||
if(MALE)
|
||||
text = "guy"
|
||||
if(FEMALE)
|
||||
text = "lady"
|
||||
else
|
||||
switch(user.gender)
|
||||
if(MALE)
|
||||
text = "guy"
|
||||
if(FEMALE)
|
||||
text = "lady"
|
||||
user.visible_message("<span class='notice'>[user] uses [src] to comb their hair with incredible style and sophistication. What a [text].</span>")
|
||||
|
||||
/obj/item/weapon/makeover
|
||||
name = "makeover kit"
|
||||
desc = "A tiny case containing a mirror and some contact lenses."
|
||||
w_class = ITEMSIZE_TINY
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "trinketbox"
|
||||
var/datum/tgui_module/appearance_changer/mirror/coskit/M
|
||||
|
||||
/obj/item/weapon/makeover/Initialize()
|
||||
. = ..()
|
||||
M = new(src, null)
|
||||
|
||||
/obj/item/weapon/makeover/attack_self(mob/living/carbon/user as mob)
|
||||
if(ishuman(user))
|
||||
to_chat(user, "<span class='notice'>You flip open \the [src] and begin to adjust your appearance.</span>")
|
||||
M.tgui_interact(user)
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
|
||||
if(istype(E))
|
||||
E.change_eye_color()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,119 +1,119 @@
|
||||
/obj/item/weapon/plastique
|
||||
name = "plastic explosives"
|
||||
desc = "Used to put holes in specific areas without too much extra hole."
|
||||
gender = PLURAL
|
||||
icon = 'icons/obj/assemblies.dmi'
|
||||
icon_state = "plastic-explosive0"
|
||||
item_state = "plasticx"
|
||||
flags = NOBLUDGEON
|
||||
w_class = ITEMSIZE_SMALL
|
||||
origin_tech = list(TECH_ILLEGAL = 2)
|
||||
var/datum/wires/explosive/c4/wires = null
|
||||
var/timer = 10
|
||||
var/atom/target = null
|
||||
var/open_panel = 0
|
||||
var/image_overlay = null
|
||||
var/blast_dev = -1
|
||||
var/blast_heavy = -1
|
||||
var/blast_light = 2
|
||||
var/blast_flash = 3
|
||||
|
||||
/obj/item/weapon/plastique/New()
|
||||
wires = new(src)
|
||||
image_overlay = image('icons/obj/assemblies.dmi', "plastic-explosive2")
|
||||
..()
|
||||
|
||||
/obj/item/weapon/plastique/Destroy()
|
||||
qdel(wires)
|
||||
wires = null
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/plastique/attackby(var/obj/item/I, var/mob/user)
|
||||
if(I.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
open_panel = !open_panel
|
||||
to_chat(user, "<span class='notice'>You [open_panel ? "open" : "close"] the wire panel.</span>")
|
||||
playsound(src, I.usesound, 50, 1)
|
||||
else if(I.has_tool_quality(TOOL_WIRECUTTER) || istype(I, /obj/item/device/multitool) || istype(I, /obj/item/device/assembly/signaler ))
|
||||
wires.Interact(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/plastique/attack_self(mob/user as mob)
|
||||
var/newtime = tgui_input_number(usr, "Please set the timer.", "Timer", 10, 60000, 10)
|
||||
if(user.get_active_hand() == src)
|
||||
newtime = CLAMP(newtime, 10, 60000)
|
||||
timer = newtime
|
||||
to_chat(user, "Timer set for [timer] seconds.")
|
||||
|
||||
/obj/item/weapon/plastique/afterattack(atom/movable/target, mob/user, flag)
|
||||
if (!flag)
|
||||
return
|
||||
if (ismob(target) || istype(target, /turf/unsimulated) || istype(target, /turf/simulated/shuttle) || istype(target, /obj/item/weapon/storage/) || istype(target, /obj/item/clothing/accessory/storage/) || istype(target, /obj/item/clothing/under))
|
||||
return
|
||||
to_chat(user, "Planting explosives...")
|
||||
user.do_attack_animation(target)
|
||||
|
||||
if(do_after(user, 50) && in_range(user, target))
|
||||
user.drop_item()
|
||||
src.target = target
|
||||
loc = null
|
||||
|
||||
if (ismob(target))
|
||||
add_attack_logs(user, target, "planted [name] on with [timer] second fuse")
|
||||
user.visible_message("<span class='danger'>[user.name] finished planting an explosive on [target.name]!</span>")
|
||||
else
|
||||
message_admins("[key_name(user, user.client)](<A HREF='?_src_=holder;[HrefToken()];adminmoreinfo=\ref[user]'>?</A>) planted [src.name] on [target.name] at ([target.x],[target.y],[target.z] - <A HREF='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[target.x];Y=[target.y];Z=[target.z]'>JMP</a>) with [timer] second fuse",0,1)
|
||||
log_game("[key_name(user)] planted [src.name] on [target.name] at ([target.x],[target.y],[target.z]) with [timer] second fuse")
|
||||
|
||||
target.add_overlay(image_overlay, TRUE)
|
||||
to_chat(user, "Bomb has been planted. Timer counting down from [timer].")
|
||||
spawn(timer*10)
|
||||
explode(get_turf(target))
|
||||
|
||||
/obj/item/weapon/plastique/proc/explode(var/location)
|
||||
if(!target)
|
||||
target = get_atom_on_turf(src)
|
||||
if(!target)
|
||||
target = src
|
||||
if(location)
|
||||
explosion(location, blast_dev, blast_heavy, blast_light, blast_flash)
|
||||
|
||||
if(target)
|
||||
if (istype(target, /turf/simulated/wall))
|
||||
var/turf/simulated/wall/W = target
|
||||
W.dismantle_wall(1,1,1)
|
||||
else if(istype(target, /mob/living))
|
||||
target.ex_act(2) // c4 can't gib mobs anymore.
|
||||
else
|
||||
target.ex_act(1)
|
||||
if(target)
|
||||
target.cut_overlay(image_overlay, TRUE)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/plastique/attack(mob/M as mob, mob/user as mob, def_zone)
|
||||
return
|
||||
|
||||
/obj/item/weapon/plastique/seismic
|
||||
name = "seismic charge"
|
||||
desc = "Used to dig holes in specific areas without too much extra hole."
|
||||
|
||||
blast_heavy = 2
|
||||
blast_light = 4
|
||||
blast_flash = 7
|
||||
|
||||
/obj/item/weapon/plastique/seismic/attackby(var/obj/item/I, var/mob/user)
|
||||
. = ..()
|
||||
if(open_panel)
|
||||
if(istype(I, /obj/item/weapon/stock_parts/micro_laser))
|
||||
var/obj/item/weapon/stock_parts/SP = I
|
||||
var/new_blast_power = max(1, round(SP.rating / 2) + 1)
|
||||
if(new_blast_power > blast_heavy)
|
||||
to_chat(user, "<span class='notice'>You install \the [I] into \the [src].</span>")
|
||||
user.drop_from_inventory(I)
|
||||
qdel(I)
|
||||
blast_heavy = new_blast_power
|
||||
blast_light = blast_heavy + round(new_blast_power * 0.5)
|
||||
blast_flash = blast_light + round(new_blast_power * 0.75)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The [I] is not any better than the component already installed into this charge!</span>")
|
||||
return .
|
||||
/obj/item/weapon/plastique
|
||||
name = "plastic explosives"
|
||||
desc = "Used to put holes in specific areas without too much extra hole."
|
||||
gender = PLURAL
|
||||
icon = 'icons/obj/assemblies.dmi'
|
||||
icon_state = "plastic-explosive0"
|
||||
item_state = "plasticx"
|
||||
flags = NOBLUDGEON
|
||||
w_class = ITEMSIZE_SMALL
|
||||
origin_tech = list(TECH_ILLEGAL = 2)
|
||||
var/datum/wires/explosive/c4/wires = null
|
||||
var/timer = 10
|
||||
var/atom/target = null
|
||||
var/open_panel = 0
|
||||
var/image_overlay = null
|
||||
var/blast_dev = -1
|
||||
var/blast_heavy = -1
|
||||
var/blast_light = 2
|
||||
var/blast_flash = 3
|
||||
|
||||
/obj/item/weapon/plastique/New()
|
||||
wires = new(src)
|
||||
image_overlay = image('icons/obj/assemblies.dmi', "plastic-explosive2")
|
||||
..()
|
||||
|
||||
/obj/item/weapon/plastique/Destroy()
|
||||
qdel(wires)
|
||||
wires = null
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/plastique/attackby(var/obj/item/I, var/mob/user)
|
||||
if(I.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
open_panel = !open_panel
|
||||
to_chat(user, "<span class='notice'>You [open_panel ? "open" : "close"] the wire panel.</span>")
|
||||
playsound(src, I.usesound, 50, 1)
|
||||
else if(I.has_tool_quality(TOOL_WIRECUTTER) || istype(I, /obj/item/device/multitool) || istype(I, /obj/item/device/assembly/signaler ))
|
||||
wires.Interact(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/plastique/attack_self(mob/user as mob)
|
||||
var/newtime = tgui_input_number(usr, "Please set the timer.", "Timer", 10, 60000, 10)
|
||||
if(user.get_active_hand() == src)
|
||||
newtime = CLAMP(newtime, 10, 60000)
|
||||
timer = newtime
|
||||
to_chat(user, "Timer set for [timer] seconds.")
|
||||
|
||||
/obj/item/weapon/plastique/afterattack(atom/movable/target, mob/user, flag)
|
||||
if (!flag)
|
||||
return
|
||||
if (ismob(target) || istype(target, /turf/unsimulated) || istype(target, /turf/simulated/shuttle) || istype(target, /obj/item/weapon/storage/) || istype(target, /obj/item/clothing/accessory/storage/) || istype(target, /obj/item/clothing/under))
|
||||
return
|
||||
to_chat(user, "Planting explosives...")
|
||||
user.do_attack_animation(target)
|
||||
|
||||
if(do_after(user, 50) && in_range(user, target))
|
||||
user.drop_item()
|
||||
src.target = target
|
||||
loc = null
|
||||
|
||||
if (ismob(target))
|
||||
add_attack_logs(user, target, "planted [name] on with [timer] second fuse")
|
||||
user.visible_message("<span class='danger'>[user.name] finished planting an explosive on [target.name]!</span>")
|
||||
else
|
||||
message_admins("[key_name(user, user.client)](<A HREF='?_src_=holder;[HrefToken()];adminmoreinfo=\ref[user]'>?</A>) planted [src.name] on [target.name] at ([target.x],[target.y],[target.z] - <A HREF='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[target.x];Y=[target.y];Z=[target.z]'>JMP</a>) with [timer] second fuse",0,1)
|
||||
log_game("[key_name(user)] planted [src.name] on [target.name] at ([target.x],[target.y],[target.z]) with [timer] second fuse")
|
||||
|
||||
target.add_overlay(image_overlay, TRUE)
|
||||
to_chat(user, "Bomb has been planted. Timer counting down from [timer].")
|
||||
spawn(timer*10)
|
||||
explode(get_turf(target))
|
||||
|
||||
/obj/item/weapon/plastique/proc/explode(var/location)
|
||||
if(!target)
|
||||
target = get_atom_on_turf(src)
|
||||
if(!target)
|
||||
target = src
|
||||
if(location)
|
||||
explosion(location, blast_dev, blast_heavy, blast_light, blast_flash)
|
||||
|
||||
if(target)
|
||||
if (istype(target, /turf/simulated/wall))
|
||||
var/turf/simulated/wall/W = target
|
||||
W.dismantle_wall(1,1,1)
|
||||
else if(istype(target, /mob/living))
|
||||
target.ex_act(2) // c4 can't gib mobs anymore.
|
||||
else
|
||||
target.ex_act(1)
|
||||
if(target)
|
||||
target.cut_overlay(image_overlay, TRUE)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/plastique/attack(mob/M as mob, mob/user as mob, def_zone)
|
||||
return
|
||||
|
||||
/obj/item/weapon/plastique/seismic
|
||||
name = "seismic charge"
|
||||
desc = "Used to dig holes in specific areas without too much extra hole."
|
||||
|
||||
blast_heavy = 2
|
||||
blast_light = 4
|
||||
blast_flash = 7
|
||||
|
||||
/obj/item/weapon/plastique/seismic/attackby(var/obj/item/I, var/mob/user)
|
||||
. = ..()
|
||||
if(open_panel)
|
||||
if(istype(I, /obj/item/weapon/stock_parts/micro_laser))
|
||||
var/obj/item/weapon/stock_parts/SP = I
|
||||
var/new_blast_power = max(1, round(SP.rating / 2) + 1)
|
||||
if(new_blast_power > blast_heavy)
|
||||
to_chat(user, "<span class='notice'>You install \the [I] into \the [src].</span>")
|
||||
user.drop_from_inventory(I)
|
||||
qdel(I)
|
||||
blast_heavy = new_blast_power
|
||||
blast_light = blast_heavy + round(new_blast_power * 0.5)
|
||||
blast_flash = blast_light + round(new_blast_power * 0.75)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The [I] is not any better than the component already installed into this charge!</span>")
|
||||
return .
|
||||
|
||||
@@ -1,144 +1,144 @@
|
||||
/obj/item/weapon/extinguisher
|
||||
name = "fire extinguisher"
|
||||
desc = "A traditional red fire extinguisher."
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "fire_extinguisher0"
|
||||
item_state = "fire_extinguisher"
|
||||
hitsound = 'sound/weapons/smash.ogg'
|
||||
throwforce = 10
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
throw_speed = 2
|
||||
throw_range = 10
|
||||
force = 10
|
||||
matter = list(MAT_STEEL = 90)
|
||||
attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed")
|
||||
drop_sound = 'sound/items/drop/gascan.ogg'
|
||||
pickup_sound = 'sound/items/pickup/gascan.ogg'
|
||||
|
||||
var/spray_particles = 3
|
||||
var/spray_amount = 10 //units of liquid per particle
|
||||
var/max_water = 300
|
||||
var/last_use = 1.0
|
||||
var/safety = 1
|
||||
var/sprite_name = "fire_extinguisher"
|
||||
var/rand_overlays = 6
|
||||
|
||||
/obj/item/weapon/extinguisher/mini
|
||||
name = "fire extinguisher"
|
||||
desc = "A light and compact fibreglass-framed model fire extinguisher."
|
||||
icon_state = "miniFE0"
|
||||
item_state = "miniFE"
|
||||
hitsound = null //it is much lighter, after all.
|
||||
throwforce = 2
|
||||
w_class = ITEMSIZE_SMALL
|
||||
force = 3.0
|
||||
max_water = 150
|
||||
spray_particles = 3
|
||||
sprite_name = "miniFE"
|
||||
rand_overlays = 0
|
||||
|
||||
/obj/item/weapon/extinguisher/atmo
|
||||
name = "atmospheric fire extinguisher"
|
||||
desc = "A heavy duty fire extinguisher meant to fight large fires."
|
||||
icon_state = "atmos_extinguisher0"
|
||||
item_state = "atmos_extinguisher"
|
||||
throwforce = 12
|
||||
w_class = ITEMSIZE_LARGE
|
||||
force = 3.0
|
||||
max_water = 600
|
||||
spray_particles = 3
|
||||
sprite_name = "atmos_extinguisher"
|
||||
rand_overlays = 0
|
||||
|
||||
/obj/item/weapon/extinguisher/Initialize()
|
||||
create_reagents(max_water)
|
||||
reagents.add_reagent("firefoam", max_water)
|
||||
if(rand_overlays)
|
||||
var/choice = rand(1,rand_overlays)
|
||||
add_overlay("[item_state]O[choice]")
|
||||
. = ..()
|
||||
|
||||
/obj/item/weapon/extinguisher/examine(mob/user)
|
||||
. = ..()
|
||||
if(get_dist(user, src) == 0)
|
||||
. += "[src] has [src.reagents.total_volume] units of foam left!"
|
||||
|
||||
/obj/item/weapon/extinguisher/attack_self(mob/user as mob)
|
||||
safety = !safety
|
||||
icon_state = "[sprite_name][!safety]"
|
||||
desc = "The safety is [safety ? "on" : "off"]."
|
||||
to_chat(user, "The safety is [safety ? "on" : "off"].")
|
||||
|
||||
/obj/item/weapon/extinguisher/proc/propel_object(var/obj/O, mob/user, movementdirection)
|
||||
if(O.anchored) return
|
||||
|
||||
var/obj/structure/bed/chair/C
|
||||
if(istype(O, /obj/structure/bed/chair))
|
||||
C = O
|
||||
|
||||
var/list/move_speed = list(1, 1, 1, 2, 2, 3)
|
||||
for(var/i in 1 to 6)
|
||||
if(C) C.propelled = (6-i)
|
||||
O.Move(get_step(user,movementdirection), movementdirection)
|
||||
sleep(move_speed[i])
|
||||
|
||||
//additional movement
|
||||
for(var/i in 1 to 3)
|
||||
O.Move(get_step(user,movementdirection), movementdirection)
|
||||
sleep(3)
|
||||
|
||||
/obj/item/weapon/extinguisher/afterattack(var/atom/target, var/mob/user, var/flag)
|
||||
//TODO; Add support for reagents in water.
|
||||
|
||||
if( istype(target, /obj/structure/reagent_dispensers) && flag)
|
||||
var/obj/o = target
|
||||
var/amount = o.reagents.trans_to_obj(src, 50)
|
||||
to_chat(user, "<span class='notice'>You fill [src] with [amount] units of the contents of [target].</span>")
|
||||
playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
|
||||
return
|
||||
|
||||
if (!safety)
|
||||
if (src.reagents.total_volume < 1)
|
||||
to_chat(usr, "<span class='notice'>\The [src] is empty.</span>")
|
||||
return
|
||||
|
||||
if (world.time < src.last_use + 20)
|
||||
return
|
||||
|
||||
src.last_use = world.time
|
||||
|
||||
playsound(src, 'sound/effects/extinguish.ogg', 75, 1, -3)
|
||||
|
||||
var/direction = get_dir(src,target)
|
||||
|
||||
if(user.buckled && isobj(user.buckled))
|
||||
spawn(0)
|
||||
propel_object(user.buckled, user, turn(direction,180))
|
||||
|
||||
var/turf/T = get_turf(target)
|
||||
var/turf/T1 = get_step(T,turn(direction, 90))
|
||||
var/turf/T2 = get_step(T,turn(direction, -90))
|
||||
|
||||
var/list/the_targets = list(T,T1,T2)
|
||||
|
||||
for(var/a = 1 to spray_particles)
|
||||
spawn(0)
|
||||
if(!src || !reagents.total_volume) return
|
||||
|
||||
var/obj/effect/effect/water/W = new /obj/effect/effect/water(get_turf(src))
|
||||
var/turf/my_target
|
||||
if(a <= the_targets.len)
|
||||
my_target = the_targets[a]
|
||||
else
|
||||
my_target = pick(the_targets)
|
||||
W.create_reagents(spray_amount)
|
||||
reagents.trans_to_obj(W, spray_amount)
|
||||
W.set_color()
|
||||
W.set_up(my_target)
|
||||
|
||||
if((istype(usr.loc, /turf/space)) || (usr.lastarea.has_gravity == 0))
|
||||
user.inertia_dir = get_dir(target, user)
|
||||
step(user, user.inertia_dir)
|
||||
else
|
||||
return ..()
|
||||
return
|
||||
/obj/item/weapon/extinguisher
|
||||
name = "fire extinguisher"
|
||||
desc = "A traditional red fire extinguisher."
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "fire_extinguisher0"
|
||||
item_state = "fire_extinguisher"
|
||||
hitsound = 'sound/weapons/smash.ogg'
|
||||
throwforce = 10
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
throw_speed = 2
|
||||
throw_range = 10
|
||||
force = 10
|
||||
matter = list(MAT_STEEL = 90)
|
||||
attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed")
|
||||
drop_sound = 'sound/items/drop/gascan.ogg'
|
||||
pickup_sound = 'sound/items/pickup/gascan.ogg'
|
||||
|
||||
var/spray_particles = 3
|
||||
var/spray_amount = 10 //units of liquid per particle
|
||||
var/max_water = 300
|
||||
var/last_use = 1.0
|
||||
var/safety = 1
|
||||
var/sprite_name = "fire_extinguisher"
|
||||
var/rand_overlays = 6
|
||||
|
||||
/obj/item/weapon/extinguisher/mini
|
||||
name = "fire extinguisher"
|
||||
desc = "A light and compact fibreglass-framed model fire extinguisher."
|
||||
icon_state = "miniFE0"
|
||||
item_state = "miniFE"
|
||||
hitsound = null //it is much lighter, after all.
|
||||
throwforce = 2
|
||||
w_class = ITEMSIZE_SMALL
|
||||
force = 3.0
|
||||
max_water = 150
|
||||
spray_particles = 3
|
||||
sprite_name = "miniFE"
|
||||
rand_overlays = 0
|
||||
|
||||
/obj/item/weapon/extinguisher/atmo
|
||||
name = "atmospheric fire extinguisher"
|
||||
desc = "A heavy duty fire extinguisher meant to fight large fires."
|
||||
icon_state = "atmos_extinguisher0"
|
||||
item_state = "atmos_extinguisher"
|
||||
throwforce = 12
|
||||
w_class = ITEMSIZE_LARGE
|
||||
force = 3.0
|
||||
max_water = 600
|
||||
spray_particles = 3
|
||||
sprite_name = "atmos_extinguisher"
|
||||
rand_overlays = 0
|
||||
|
||||
/obj/item/weapon/extinguisher/Initialize()
|
||||
create_reagents(max_water)
|
||||
reagents.add_reagent("firefoam", max_water)
|
||||
if(rand_overlays)
|
||||
var/choice = rand(1,rand_overlays)
|
||||
add_overlay("[item_state]O[choice]")
|
||||
. = ..()
|
||||
|
||||
/obj/item/weapon/extinguisher/examine(mob/user)
|
||||
. = ..()
|
||||
if(get_dist(user, src) == 0)
|
||||
. += "[src] has [src.reagents.total_volume] units of foam left!"
|
||||
|
||||
/obj/item/weapon/extinguisher/attack_self(mob/user as mob)
|
||||
safety = !safety
|
||||
icon_state = "[sprite_name][!safety]"
|
||||
desc = "The safety is [safety ? "on" : "off"]."
|
||||
to_chat(user, "The safety is [safety ? "on" : "off"].")
|
||||
|
||||
/obj/item/weapon/extinguisher/proc/propel_object(var/obj/O, mob/user, movementdirection)
|
||||
if(O.anchored) return
|
||||
|
||||
var/obj/structure/bed/chair/C
|
||||
if(istype(O, /obj/structure/bed/chair))
|
||||
C = O
|
||||
|
||||
var/list/move_speed = list(1, 1, 1, 2, 2, 3)
|
||||
for(var/i in 1 to 6)
|
||||
if(C) C.propelled = (6-i)
|
||||
O.Move(get_step(user,movementdirection), movementdirection)
|
||||
sleep(move_speed[i])
|
||||
|
||||
//additional movement
|
||||
for(var/i in 1 to 3)
|
||||
O.Move(get_step(user,movementdirection), movementdirection)
|
||||
sleep(3)
|
||||
|
||||
/obj/item/weapon/extinguisher/afterattack(var/atom/target, var/mob/user, var/flag)
|
||||
//TODO; Add support for reagents in water.
|
||||
|
||||
if( istype(target, /obj/structure/reagent_dispensers) && flag)
|
||||
var/obj/o = target
|
||||
var/amount = o.reagents.trans_to_obj(src, 50)
|
||||
to_chat(user, "<span class='notice'>You fill [src] with [amount] units of the contents of [target].</span>")
|
||||
playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
|
||||
return
|
||||
|
||||
if (!safety)
|
||||
if (src.reagents.total_volume < 1)
|
||||
to_chat(usr, "<span class='notice'>\The [src] is empty.</span>")
|
||||
return
|
||||
|
||||
if (world.time < src.last_use + 20)
|
||||
return
|
||||
|
||||
src.last_use = world.time
|
||||
|
||||
playsound(src, 'sound/effects/extinguish.ogg', 75, 1, -3)
|
||||
|
||||
var/direction = get_dir(src,target)
|
||||
|
||||
if(user.buckled && isobj(user.buckled))
|
||||
spawn(0)
|
||||
propel_object(user.buckled, user, turn(direction,180))
|
||||
|
||||
var/turf/T = get_turf(target)
|
||||
var/turf/T1 = get_step(T,turn(direction, 90))
|
||||
var/turf/T2 = get_step(T,turn(direction, -90))
|
||||
|
||||
var/list/the_targets = list(T,T1,T2)
|
||||
|
||||
for(var/a = 1 to spray_particles)
|
||||
spawn(0)
|
||||
if(!src || !reagents.total_volume) return
|
||||
|
||||
var/obj/effect/effect/water/W = new /obj/effect/effect/water(get_turf(src))
|
||||
var/turf/my_target
|
||||
if(a <= the_targets.len)
|
||||
my_target = the_targets[a]
|
||||
else
|
||||
my_target = pick(the_targets)
|
||||
W.create_reagents(spray_amount)
|
||||
reagents.trans_to_obj(W, spray_amount)
|
||||
W.set_color()
|
||||
W.set_up(my_target)
|
||||
|
||||
if((istype(usr.loc, /turf/space)) || (usr.lastarea.has_gravity == 0))
|
||||
user.inertia_dir = get_dir(target, user)
|
||||
step(user, user.inertia_dir)
|
||||
else
|
||||
return ..()
|
||||
return
|
||||
|
||||
@@ -1,204 +1,204 @@
|
||||
/obj/item/weapon/flamethrower
|
||||
name = "flamethrower"
|
||||
desc = "You are a firestarter!"
|
||||
icon = 'icons/obj/flamethrower.dmi'
|
||||
icon_state = "flamethrowerbase"
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_guns.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_guns.dmi',
|
||||
)
|
||||
item_state = "flamethrower_0"
|
||||
force = 3.0
|
||||
throwforce = 10.0
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
origin_tech = list(TECH_COMBAT = 1, TECH_PHORON = 1)
|
||||
matter = list(MAT_STEEL = 500)
|
||||
var/status = 0
|
||||
var/throw_amount = 100
|
||||
var/lit = 0 //on or off
|
||||
var/operating = 0//cooldown
|
||||
var/turf/previousturf = null
|
||||
var/obj/item/weapon/weldingtool/weldtool = null
|
||||
var/obj/item/device/assembly/igniter/igniter = null
|
||||
var/obj/item/weapon/tank/phoron/ptank = null
|
||||
|
||||
|
||||
/obj/item/weapon/flamethrower/Destroy()
|
||||
QDEL_NULL(weldtool)
|
||||
QDEL_NULL(igniter)
|
||||
QDEL_NULL(ptank)
|
||||
. = ..()
|
||||
|
||||
/obj/item/weapon/flamethrower/process()
|
||||
if(!lit)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return null
|
||||
var/turf/location = loc
|
||||
if(istype(location, /mob/))
|
||||
var/mob/living/M = location
|
||||
if(M.item_is_in_hands(src))
|
||||
location = M.loc
|
||||
if(isturf(location)) //start a fire if possible
|
||||
location.hotspot_expose(700, 2)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/flamethrower/update_icon()
|
||||
cut_overlays()
|
||||
if(igniter)
|
||||
add_overlay("+igniter[status]")
|
||||
if(ptank)
|
||||
add_overlay("+ptank")
|
||||
if(lit)
|
||||
add_overlay("+lit")
|
||||
item_state = "flamethrower_1"
|
||||
else
|
||||
item_state = "flamethrower_0"
|
||||
return
|
||||
|
||||
/obj/item/weapon/flamethrower/afterattack(atom/target, mob/user, proximity)
|
||||
if(!proximity) return
|
||||
// Make sure our user is still holding us
|
||||
if(user && user.get_active_hand() == src)
|
||||
var/turf/target_turf = get_turf(target)
|
||||
if(target_turf)
|
||||
var/turflist = getline(user, target_turf)
|
||||
flame_turf(turflist)
|
||||
|
||||
/obj/item/weapon/flamethrower/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(user.stat || user.restrained() || user.lying) return
|
||||
if(W.has_tool_quality(TOOL_WRENCH) && !status)//Taking this apart
|
||||
var/turf/T = get_turf(src)
|
||||
if(weldtool)
|
||||
weldtool.loc = T
|
||||
weldtool = null
|
||||
if(igniter)
|
||||
igniter.loc = T
|
||||
igniter = null
|
||||
if(ptank)
|
||||
ptank.loc = T
|
||||
ptank = null
|
||||
new /obj/item/stack/rods(T)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER) && igniter && !lit)
|
||||
status = !status
|
||||
to_chat(user, "<span class='notice'>[igniter] is now [status ? "secured" : "unsecured"]!</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(isigniter(W))
|
||||
var/obj/item/device/assembly/igniter/I = W
|
||||
if(I.secured) return
|
||||
if(igniter) return
|
||||
user.drop_item()
|
||||
I.loc = src
|
||||
igniter = I
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(istype(W,/obj/item/weapon/tank/phoron))
|
||||
if(ptank)
|
||||
to_chat(user, "<span class='notice'>There appears to already be a phoron tank loaded in [src]!</span>")
|
||||
return
|
||||
user.drop_item()
|
||||
ptank = W
|
||||
W.loc = src
|
||||
update_icon()
|
||||
return
|
||||
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/flamethrower/attack_self(mob/user as mob)
|
||||
if(user.stat || user.restrained() || user.lying) return
|
||||
user.set_machine(src)
|
||||
if(!ptank)
|
||||
to_chat(user, "<span class='notice'>Attach a phoron tank first!</span>")
|
||||
return
|
||||
var/dat = text("<TT><B>Flamethrower (<A HREF='?src=\ref[src];light=1'>[lit ? "<font color='red'>Lit</font>" : "Unlit"]</a>)</B><BR>\n Tank Pressure: [ptank.air_contents.return_pressure()]<BR>\nAmount to throw: <A HREF='?src=\ref[src];amount=-100'>-</A> <A HREF='?src=\ref[src];amount=-10'>-</A> <A HREF='?src=\ref[src];amount=-1'>-</A> [throw_amount] <A HREF='?src=\ref[src];amount=1'>+</A> <A HREF='?src=\ref[src];amount=10'>+</A> <A HREF='?src=\ref[src];amount=100'>+</A><BR>\n<A HREF='?src=\ref[src];remove=1'>Remove phorontank</A> - <A HREF='?src=\ref[src];close=1'>Close</A></TT>")
|
||||
user << browse(dat, "window=flamethrower;size=600x300")
|
||||
onclose(user, "flamethrower")
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/flamethrower/Topic(href,href_list[])
|
||||
if(href_list["close"])
|
||||
usr.unset_machine()
|
||||
usr << browse(null, "window=flamethrower")
|
||||
return
|
||||
if(usr.stat || usr.restrained() || usr.lying) return
|
||||
usr.set_machine(src)
|
||||
if(href_list["light"])
|
||||
if(!ptank) return
|
||||
if(ptank.air_contents.gas["phoron"] < 1) return
|
||||
if(!status) return
|
||||
lit = !lit
|
||||
if(lit)
|
||||
START_PROCESSING(SSobj, src)
|
||||
if(href_list["amount"])
|
||||
throw_amount = throw_amount + text2num(href_list["amount"])
|
||||
throw_amount = max(50, min(5000, throw_amount))
|
||||
if(href_list["remove"])
|
||||
if(!ptank) return
|
||||
usr.put_in_hands(ptank)
|
||||
ptank = null
|
||||
lit = 0
|
||||
usr.unset_machine()
|
||||
usr << browse(null, "window=flamethrower")
|
||||
for(var/mob/M in viewers(1, loc))
|
||||
if((M.client && M.machine == src))
|
||||
attack_self(M)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
|
||||
//Called from turf.dm turf/dblclick
|
||||
/obj/item/weapon/flamethrower/proc/flame_turf(turflist)
|
||||
if(!lit || operating) return
|
||||
operating = 1
|
||||
for(var/turf/T in turflist)
|
||||
if(T.density || istype(T, /turf/space))
|
||||
break
|
||||
if(!previousturf && length(turflist)>1)
|
||||
previousturf = get_turf(src)
|
||||
continue //so we don't burn the tile we be standin on
|
||||
if(previousturf && LinkBlocked(previousturf, T))
|
||||
break
|
||||
ignite_turf(T)
|
||||
sleep(1)
|
||||
previousturf = null
|
||||
operating = 0
|
||||
for(var/mob/M in viewers(1, loc))
|
||||
if((M.client && M.machine == src))
|
||||
attack_self(M)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/flamethrower/proc/ignite_turf(turf/target)
|
||||
//TODO: DEFERRED Consider checking to make sure tank pressure is high enough before doing this...
|
||||
//Transfer 5% of current tank air contents to turf
|
||||
var/datum/gas_mixture/air_transfer = ptank.air_contents.remove_ratio(0.02*(throw_amount/100))
|
||||
//air_transfer.toxins = air_transfer.toxins * 5 // This is me not comprehending the air system. I realize this is mischievious and I could probably make it work without fucking it up like this, but there you have it. -- TLE
|
||||
new/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel(target,air_transfer.gas["phoron"],get_dir(loc,target))
|
||||
air_transfer.gas["phoron"] = 0
|
||||
target.assume_air(air_transfer)
|
||||
//Burn it based on transfered gas
|
||||
//target.hotspot_expose(part4.air_contents.temperature*2,300)
|
||||
target.hotspot_expose((ptank.air_contents.temperature*2) + 380,500) // -- More of my "how do I shot fire?" dickery. -- TLE
|
||||
//location.hotspot_expose(1000,500,1)
|
||||
return
|
||||
|
||||
/obj/item/weapon/flamethrower/full/New(var/loc)
|
||||
..()
|
||||
weldtool = new /obj/item/weapon/weldingtool(src)
|
||||
weldtool.status = 0
|
||||
igniter = new /obj/item/device/assembly/igniter(src)
|
||||
igniter.secured = 0
|
||||
status = 1
|
||||
update_icon()
|
||||
return
|
||||
/obj/item/weapon/flamethrower
|
||||
name = "flamethrower"
|
||||
desc = "You are a firestarter!"
|
||||
icon = 'icons/obj/flamethrower.dmi'
|
||||
icon_state = "flamethrowerbase"
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_guns.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_guns.dmi',
|
||||
)
|
||||
item_state = "flamethrower_0"
|
||||
force = 3.0
|
||||
throwforce = 10.0
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
origin_tech = list(TECH_COMBAT = 1, TECH_PHORON = 1)
|
||||
matter = list(MAT_STEEL = 500)
|
||||
var/status = 0
|
||||
var/throw_amount = 100
|
||||
var/lit = 0 //on or off
|
||||
var/operating = 0//cooldown
|
||||
var/turf/previousturf = null
|
||||
var/obj/item/weapon/weldingtool/weldtool = null
|
||||
var/obj/item/device/assembly/igniter/igniter = null
|
||||
var/obj/item/weapon/tank/phoron/ptank = null
|
||||
|
||||
|
||||
/obj/item/weapon/flamethrower/Destroy()
|
||||
QDEL_NULL(weldtool)
|
||||
QDEL_NULL(igniter)
|
||||
QDEL_NULL(ptank)
|
||||
. = ..()
|
||||
|
||||
/obj/item/weapon/flamethrower/process()
|
||||
if(!lit)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return null
|
||||
var/turf/location = loc
|
||||
if(istype(location, /mob/))
|
||||
var/mob/living/M = location
|
||||
if(M.item_is_in_hands(src))
|
||||
location = M.loc
|
||||
if(isturf(location)) //start a fire if possible
|
||||
location.hotspot_expose(700, 2)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/flamethrower/update_icon()
|
||||
cut_overlays()
|
||||
if(igniter)
|
||||
add_overlay("+igniter[status]")
|
||||
if(ptank)
|
||||
add_overlay("+ptank")
|
||||
if(lit)
|
||||
add_overlay("+lit")
|
||||
item_state = "flamethrower_1"
|
||||
else
|
||||
item_state = "flamethrower_0"
|
||||
return
|
||||
|
||||
/obj/item/weapon/flamethrower/afterattack(atom/target, mob/user, proximity)
|
||||
if(!proximity) return
|
||||
// Make sure our user is still holding us
|
||||
if(user && user.get_active_hand() == src)
|
||||
var/turf/target_turf = get_turf(target)
|
||||
if(target_turf)
|
||||
var/turflist = getline(user, target_turf)
|
||||
flame_turf(turflist)
|
||||
|
||||
/obj/item/weapon/flamethrower/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(user.stat || user.restrained() || user.lying) return
|
||||
if(W.has_tool_quality(TOOL_WRENCH) && !status)//Taking this apart
|
||||
var/turf/T = get_turf(src)
|
||||
if(weldtool)
|
||||
weldtool.loc = T
|
||||
weldtool = null
|
||||
if(igniter)
|
||||
igniter.loc = T
|
||||
igniter = null
|
||||
if(ptank)
|
||||
ptank.loc = T
|
||||
ptank = null
|
||||
new /obj/item/stack/rods(T)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER) && igniter && !lit)
|
||||
status = !status
|
||||
to_chat(user, "<span class='notice'>[igniter] is now [status ? "secured" : "unsecured"]!</span>")
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(isigniter(W))
|
||||
var/obj/item/device/assembly/igniter/I = W
|
||||
if(I.secured) return
|
||||
if(igniter) return
|
||||
user.drop_item()
|
||||
I.loc = src
|
||||
igniter = I
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(istype(W,/obj/item/weapon/tank/phoron))
|
||||
if(ptank)
|
||||
to_chat(user, "<span class='notice'>There appears to already be a phoron tank loaded in [src]!</span>")
|
||||
return
|
||||
user.drop_item()
|
||||
ptank = W
|
||||
W.loc = src
|
||||
update_icon()
|
||||
return
|
||||
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/flamethrower/attack_self(mob/user as mob)
|
||||
if(user.stat || user.restrained() || user.lying) return
|
||||
user.set_machine(src)
|
||||
if(!ptank)
|
||||
to_chat(user, "<span class='notice'>Attach a phoron tank first!</span>")
|
||||
return
|
||||
var/dat = text("<TT><B>Flamethrower (<A HREF='?src=\ref[src];light=1'>[lit ? "<font color='red'>Lit</font>" : "Unlit"]</a>)</B><BR>\n Tank Pressure: [ptank.air_contents.return_pressure()]<BR>\nAmount to throw: <A HREF='?src=\ref[src];amount=-100'>-</A> <A HREF='?src=\ref[src];amount=-10'>-</A> <A HREF='?src=\ref[src];amount=-1'>-</A> [throw_amount] <A HREF='?src=\ref[src];amount=1'>+</A> <A HREF='?src=\ref[src];amount=10'>+</A> <A HREF='?src=\ref[src];amount=100'>+</A><BR>\n<A HREF='?src=\ref[src];remove=1'>Remove phorontank</A> - <A HREF='?src=\ref[src];close=1'>Close</A></TT>")
|
||||
user << browse(dat, "window=flamethrower;size=600x300")
|
||||
onclose(user, "flamethrower")
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/flamethrower/Topic(href,href_list[])
|
||||
if(href_list["close"])
|
||||
usr.unset_machine()
|
||||
usr << browse(null, "window=flamethrower")
|
||||
return
|
||||
if(usr.stat || usr.restrained() || usr.lying) return
|
||||
usr.set_machine(src)
|
||||
if(href_list["light"])
|
||||
if(!ptank) return
|
||||
if(ptank.air_contents.gas["phoron"] < 1) return
|
||||
if(!status) return
|
||||
lit = !lit
|
||||
if(lit)
|
||||
START_PROCESSING(SSobj, src)
|
||||
if(href_list["amount"])
|
||||
throw_amount = throw_amount + text2num(href_list["amount"])
|
||||
throw_amount = max(50, min(5000, throw_amount))
|
||||
if(href_list["remove"])
|
||||
if(!ptank) return
|
||||
usr.put_in_hands(ptank)
|
||||
ptank = null
|
||||
lit = 0
|
||||
usr.unset_machine()
|
||||
usr << browse(null, "window=flamethrower")
|
||||
for(var/mob/M in viewers(1, loc))
|
||||
if((M.client && M.machine == src))
|
||||
attack_self(M)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
|
||||
//Called from turf.dm turf/dblclick
|
||||
/obj/item/weapon/flamethrower/proc/flame_turf(turflist)
|
||||
if(!lit || operating) return
|
||||
operating = 1
|
||||
for(var/turf/T in turflist)
|
||||
if(T.density || istype(T, /turf/space))
|
||||
break
|
||||
if(!previousturf && length(turflist)>1)
|
||||
previousturf = get_turf(src)
|
||||
continue //so we don't burn the tile we be standin on
|
||||
if(previousturf && LinkBlocked(previousturf, T))
|
||||
break
|
||||
ignite_turf(T)
|
||||
sleep(1)
|
||||
previousturf = null
|
||||
operating = 0
|
||||
for(var/mob/M in viewers(1, loc))
|
||||
if((M.client && M.machine == src))
|
||||
attack_self(M)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/flamethrower/proc/ignite_turf(turf/target)
|
||||
//TODO: DEFERRED Consider checking to make sure tank pressure is high enough before doing this...
|
||||
//Transfer 5% of current tank air contents to turf
|
||||
var/datum/gas_mixture/air_transfer = ptank.air_contents.remove_ratio(0.02*(throw_amount/100))
|
||||
//air_transfer.toxins = air_transfer.toxins * 5 // This is me not comprehending the air system. I realize this is mischievious and I could probably make it work without fucking it up like this, but there you have it. -- TLE
|
||||
new/obj/effect/decal/cleanable/liquid_fuel/flamethrower_fuel(target,air_transfer.gas["phoron"],get_dir(loc,target))
|
||||
air_transfer.gas["phoron"] = 0
|
||||
target.assume_air(air_transfer)
|
||||
//Burn it based on transfered gas
|
||||
//target.hotspot_expose(part4.air_contents.temperature*2,300)
|
||||
target.hotspot_expose((ptank.air_contents.temperature*2) + 380,500) // -- More of my "how do I shot fire?" dickery. -- TLE
|
||||
//location.hotspot_expose(1000,500,1)
|
||||
return
|
||||
|
||||
/obj/item/weapon/flamethrower/full/New(var/loc)
|
||||
..()
|
||||
weldtool = new /obj/item/weapon/weldingtool(src)
|
||||
weldtool.status = 0
|
||||
igniter = new /obj/item/device/assembly/igniter(src)
|
||||
igniter.secured = 0
|
||||
status = 1
|
||||
update_icon()
|
||||
return
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/obj/item/weapon/grenade/anti_photon
|
||||
desc = "An experimental device for temporarily removing light in a limited area."
|
||||
name = "photon disruption grenade"
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "emp"
|
||||
det_time = 20
|
||||
origin_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/grenade/anti_photon/detonate()
|
||||
playsound(src, 'sound/effects/phasein.ogg', 50, 1, 5)
|
||||
set_light(10, -10, "#FFFFFF")
|
||||
|
||||
var/extra_delay = rand(0,90)
|
||||
|
||||
spawn(extra_delay)
|
||||
spawn(200)
|
||||
if(prob(10+extra_delay))
|
||||
set_light(10, 10, "#[num2hex(rand(64,255))][num2hex(rand(64,255))][num2hex(rand(64,255))]")
|
||||
spawn(210)
|
||||
..()
|
||||
playsound(src, 'sound/effects/bang.ogg', 50, 1, 5)
|
||||
qdel(src)
|
||||
/obj/item/weapon/grenade/anti_photon
|
||||
desc = "An experimental device for temporarily removing light in a limited area."
|
||||
name = "photon disruption grenade"
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "emp"
|
||||
det_time = 20
|
||||
origin_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 4)
|
||||
|
||||
/obj/item/weapon/grenade/anti_photon/detonate()
|
||||
playsound(src, 'sound/effects/phasein.ogg', 50, 1, 5)
|
||||
set_light(10, -10, "#FFFFFF")
|
||||
|
||||
var/extra_delay = rand(0,90)
|
||||
|
||||
spawn(extra_delay)
|
||||
spawn(200)
|
||||
if(prob(10+extra_delay))
|
||||
set_light(10, 10, "#[num2hex(rand(64,255))][num2hex(rand(64,255))][num2hex(rand(64,255))]")
|
||||
spawn(210)
|
||||
..()
|
||||
playsound(src, 'sound/effects/bang.ogg', 50, 1, 5)
|
||||
qdel(src)
|
||||
|
||||
@@ -1,316 +1,316 @@
|
||||
/obj/item/weapon/grenade/chem_grenade
|
||||
name = "grenade casing"
|
||||
icon_state = "chemg"
|
||||
item_state = "grenade"
|
||||
desc = "A hand made chemical grenade."
|
||||
w_class = ITEMSIZE_SMALL
|
||||
force = 2.0
|
||||
det_time = null
|
||||
unacidable = TRUE
|
||||
|
||||
var/stage = 0
|
||||
var/state = 0
|
||||
var/path = 0
|
||||
/// If TRUE, grenade is permanently sealed when fully assembled, useful for things like off-the-shelf grenades.
|
||||
var/sealed = FALSE
|
||||
var/obj/item/device/assembly_holder/detonator = null
|
||||
var/list/beakers = new/list()
|
||||
var/list/allowed_containers = list(/obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/reagent_containers/glass/bottle)
|
||||
var/affected_area = 3
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/Initialize()
|
||||
. = ..()
|
||||
create_reagents(1000)
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/Destroy()
|
||||
QDEL_NULL(detonator)
|
||||
QDEL_LIST_NULL(beakers)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/attack_self(mob/user as mob)
|
||||
if(!stage || stage==1)
|
||||
if(detonator)
|
||||
// detonator.loc=src.loc
|
||||
detonator.detached()
|
||||
usr.put_in_hands(detonator)
|
||||
detonator=null
|
||||
det_time = null
|
||||
stage=0
|
||||
icon_state = initial(icon_state)
|
||||
else if(beakers.len)
|
||||
for(var/obj/B in beakers)
|
||||
if(istype(B))
|
||||
beakers -= B
|
||||
user.put_in_hands(B)
|
||||
name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
|
||||
if(stage > 1 && !active && clown_check(user))
|
||||
to_chat(user, "<span class='warning'>You prime \the [name]!</span>")
|
||||
|
||||
msg_admin_attack("[key_name_admin(user)] primed \a [src]")
|
||||
|
||||
activate()
|
||||
add_fingerprint(user)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
C.throw_mode_on()
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W,/obj/item/device/assembly_holder) && (!stage || stage==1) && !detonator && path != 2)
|
||||
var/obj/item/device/assembly_holder/det = W
|
||||
if(istype(det.a_left,det.a_right.type) || (!isigniter(det.a_left) && !isigniter(det.a_right)))
|
||||
to_chat(user, "<span class='warning'>Assembly must contain one igniter.</span>")
|
||||
return
|
||||
if(!det.secured)
|
||||
to_chat(user, "<span class='warning'>Assembly must be secured with screwdriver.</span>")
|
||||
return
|
||||
path = 1
|
||||
to_chat(user, "<span class='notice'>You add [W] to the metal casing.</span>")
|
||||
playsound(src, 'sound/items/Screwdriver2.ogg', 25, -3)
|
||||
user.remove_from_mob(det)
|
||||
det.loc = src
|
||||
detonator = det
|
||||
if(istimer(detonator.a_left))
|
||||
var/obj/item/device/assembly/timer/T = detonator.a_left
|
||||
det_time = 10*T.time
|
||||
if(istimer(detonator.a_right))
|
||||
var/obj/item/device/assembly/timer/T = detonator.a_right
|
||||
det_time = 10*T.time
|
||||
icon_state = initial(icon_state) +"_ass"
|
||||
name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
|
||||
stage = 1
|
||||
else if(W.has_tool_quality(TOOL_SCREWDRIVER) && path != 2)
|
||||
if(stage == 1)
|
||||
path = 1
|
||||
if(beakers.len)
|
||||
to_chat(user, "<span class='notice'>You lock the assembly.</span>")
|
||||
name = "grenade"
|
||||
else
|
||||
// to_chat(user, "<span class='warning'>You need to add at least one beaker before locking the assembly.</span>")
|
||||
to_chat(user, "<span class='notice'>You lock the empty assembly.</span>")
|
||||
name = "fake grenade"
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
icon_state = initial(icon_state) +"_locked"
|
||||
stage = 2
|
||||
else if(stage == 2)
|
||||
if(active && prob(95))
|
||||
to_chat(user, "<span class='warning'>You trigger the assembly!</span>")
|
||||
detonate()
|
||||
else if(sealed)
|
||||
to_chat(user, "<span class='warning'>This grenade lacks a way to disassemble it.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You unlock the assembly.</span>")
|
||||
playsound(src, W.usesound, 50, -3)
|
||||
name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
|
||||
icon_state = initial(icon_state) + (detonator?"_ass":"")
|
||||
stage = 1
|
||||
active = 0
|
||||
else if(is_type_in_list(W, allowed_containers) && (!stage || stage==1) && path != 2)
|
||||
path = 1
|
||||
if(beakers.len == 2)
|
||||
to_chat(user, "<span class='warning'>The grenade can not hold more containers.</span>")
|
||||
return
|
||||
else
|
||||
if(W.reagents.total_volume)
|
||||
to_chat(user, "<span class='notice'>You add \the [W] to the assembly.</span>")
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
beakers += W
|
||||
stage = 1
|
||||
name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [W] is empty.</span>")
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/examine(mob/user)
|
||||
. = ..()
|
||||
if(detonator)
|
||||
. += "It has [detonator.name] attached to it."
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/activate(mob/user as mob)
|
||||
if(active) return
|
||||
|
||||
if(detonator)
|
||||
if(!isigniter(detonator.a_left))
|
||||
detonator.a_left.activate()
|
||||
active = 1
|
||||
if(!isigniter(detonator.a_right))
|
||||
detonator.a_right.activate()
|
||||
active = 1
|
||||
if(active)
|
||||
icon_state = initial(icon_state) + "_active"
|
||||
|
||||
if(user)
|
||||
msg_admin_attack("[key_name_admin(user)] primed \a [src.name]")
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/proc/primed(var/primed = 1)
|
||||
if(active)
|
||||
icon_state = initial(icon_state) + (primed?"_primed":"_active")
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/detonate()
|
||||
if(!stage || stage<2) return
|
||||
|
||||
var/has_reagents = 0
|
||||
for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
|
||||
if(G.reagents.total_volume) has_reagents = 1
|
||||
|
||||
active = 0
|
||||
if(!has_reagents)
|
||||
icon_state = initial(icon_state) +"_locked"
|
||||
playsound(src, 'sound/items/Screwdriver2.ogg', 50, 1)
|
||||
spawn(0) //Otherwise det_time is erroneously set to 0 after this
|
||||
if(istimer(detonator.a_left)) //Make sure description reflects that the timer has been reset
|
||||
var/obj/item/device/assembly/timer/T = detonator.a_left
|
||||
det_time = 10*T.time
|
||||
if(istimer(detonator.a_right))
|
||||
var/obj/item/device/assembly/timer/T = detonator.a_right
|
||||
det_time = 10*T.time
|
||||
return
|
||||
|
||||
playsound(src, 'sound/effects/bamf.ogg', 50, 1)
|
||||
|
||||
for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
|
||||
G.reagents.trans_to_obj(src, G.reagents.total_volume)
|
||||
|
||||
if(src.reagents.total_volume) //The possible reactions didnt use up all reagents.
|
||||
var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread()
|
||||
steam.set_up(10, 0, get_turf(src))
|
||||
steam.attach(src)
|
||||
steam.start()
|
||||
|
||||
for(var/atom/A in view(affected_area, src.loc))
|
||||
if( A == src ) continue
|
||||
src.reagents.touch(A)
|
||||
|
||||
if(istype(loc, /mob/living/carbon)) //drop dat grenade if it goes off in your hand
|
||||
var/mob/living/carbon/C = loc
|
||||
C.drop_from_inventory(src)
|
||||
C.throw_mode_off()
|
||||
|
||||
invisibility = INVISIBILITY_MAXIMUM //Why am i doing this?
|
||||
spawn(50) //To make sure all reagents can work
|
||||
qdel(src) //correctly before deleting the grenade.
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/large
|
||||
name = "large chem grenade"
|
||||
desc = "An oversized grenade that affects a larger area."
|
||||
icon_state = "large_grenade"
|
||||
allowed_containers = list(/obj/item/weapon/reagent_containers/glass)
|
||||
origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3)
|
||||
affected_area = 4
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/metalfoam
|
||||
name = "metal-foam grenade"
|
||||
desc = "Used for emergency sealing of air breaches."
|
||||
icon_state = "foam"
|
||||
path = 1
|
||||
stage = 2
|
||||
sealed = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/metalfoam/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
|
||||
|
||||
B1.reagents.add_reagent("aluminum", 30)
|
||||
B2.reagents.add_reagent("foaming_agent", 10)
|
||||
B2.reagents.add_reagent("pacid", 10)
|
||||
|
||||
detonator = new/obj/item/device/assembly_holder/timer_igniter(src)
|
||||
|
||||
beakers += B1
|
||||
beakers += B2
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/incendiary
|
||||
name = "incendiary grenade"
|
||||
desc = "Used for clearing rooms of living things."
|
||||
icon_state = "incendiary"
|
||||
path = 1
|
||||
stage = 2
|
||||
sealed = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/incendiary/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
|
||||
|
||||
B1.reagents.add_reagent("aluminum", 15)
|
||||
B1.reagents.add_reagent("fuel",20)
|
||||
B2.reagents.add_reagent("phoron", 15)
|
||||
B2.reagents.add_reagent("sacid", 15)
|
||||
B1.reagents.add_reagent("fuel",20)
|
||||
|
||||
detonator = new/obj/item/device/assembly_holder/timer_igniter(src)
|
||||
|
||||
beakers += B1
|
||||
beakers += B2
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/antiweed
|
||||
name = "weedkiller grenade"
|
||||
desc = "Used for purging large areas of invasive plant species. Contents under pressure. Do not directly inhale contents."
|
||||
path = 1
|
||||
stage = 2
|
||||
sealed = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/antiweed/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
|
||||
|
||||
B1.reagents.add_reagent("plantbgone", 25)
|
||||
B1.reagents.add_reagent("potassium", 25)
|
||||
B2.reagents.add_reagent("phosphorus", 25)
|
||||
B2.reagents.add_reagent("sugar", 25)
|
||||
|
||||
detonator = new/obj/item/device/assembly_holder/timer_igniter(src)
|
||||
|
||||
beakers += B1
|
||||
beakers += B2
|
||||
icon_state = "grenade"
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/cleaner
|
||||
name = "cleaner grenade"
|
||||
desc = "BLAM!-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas."
|
||||
icon_state = "cleaner"
|
||||
stage = 2
|
||||
path = 1
|
||||
sealed = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/cleaner/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
|
||||
|
||||
B1.reagents.add_reagent("fluorosurfactant", 40)
|
||||
B2.reagents.add_reagent("water", 40)
|
||||
B2.reagents.add_reagent("cleaner", 10)
|
||||
|
||||
detonator = new/obj/item/device/assembly_holder/timer_igniter(src)
|
||||
|
||||
beakers += B1
|
||||
beakers += B2
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/teargas
|
||||
name = "tear gas grenade"
|
||||
desc = "Concentrated Capsaicin. Contents under pressure. Use with caution."
|
||||
icon_state = "teargas"
|
||||
stage = 2
|
||||
path = 1
|
||||
sealed = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/teargas/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/large/B1 = new(src)
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/large/B2 = new(src)
|
||||
|
||||
B1.reagents.add_reagent("phosphorus", 40)
|
||||
B1.reagents.add_reagent("potassium", 40)
|
||||
B1.reagents.add_reagent("condensedcapsaicin", 40)
|
||||
B2.reagents.add_reagent("sugar", 40)
|
||||
B2.reagents.add_reagent("condensedcapsaicin", 80)
|
||||
|
||||
detonator = new/obj/item/device/assembly_holder/timer_igniter(src)
|
||||
|
||||
beakers += B1
|
||||
beakers += B2
|
||||
/obj/item/weapon/grenade/chem_grenade
|
||||
name = "grenade casing"
|
||||
icon_state = "chemg"
|
||||
item_state = "grenade"
|
||||
desc = "A hand made chemical grenade."
|
||||
w_class = ITEMSIZE_SMALL
|
||||
force = 2.0
|
||||
det_time = null
|
||||
unacidable = TRUE
|
||||
|
||||
var/stage = 0
|
||||
var/state = 0
|
||||
var/path = 0
|
||||
/// If TRUE, grenade is permanently sealed when fully assembled, useful for things like off-the-shelf grenades.
|
||||
var/sealed = FALSE
|
||||
var/obj/item/device/assembly_holder/detonator = null
|
||||
var/list/beakers = new/list()
|
||||
var/list/allowed_containers = list(/obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/reagent_containers/glass/bottle)
|
||||
var/affected_area = 3
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/Initialize()
|
||||
. = ..()
|
||||
create_reagents(1000)
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/Destroy()
|
||||
QDEL_NULL(detonator)
|
||||
QDEL_LIST_NULL(beakers)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/attack_self(mob/user as mob)
|
||||
if(!stage || stage==1)
|
||||
if(detonator)
|
||||
// detonator.loc=src.loc
|
||||
detonator.detached()
|
||||
usr.put_in_hands(detonator)
|
||||
detonator=null
|
||||
det_time = null
|
||||
stage=0
|
||||
icon_state = initial(icon_state)
|
||||
else if(beakers.len)
|
||||
for(var/obj/B in beakers)
|
||||
if(istype(B))
|
||||
beakers -= B
|
||||
user.put_in_hands(B)
|
||||
name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
|
||||
if(stage > 1 && !active && clown_check(user))
|
||||
to_chat(user, "<span class='warning'>You prime \the [name]!</span>")
|
||||
|
||||
msg_admin_attack("[key_name_admin(user)] primed \a [src]")
|
||||
|
||||
activate()
|
||||
add_fingerprint(user)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
C.throw_mode_on()
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W,/obj/item/device/assembly_holder) && (!stage || stage==1) && !detonator && path != 2)
|
||||
var/obj/item/device/assembly_holder/det = W
|
||||
if(istype(det.a_left,det.a_right.type) || (!isigniter(det.a_left) && !isigniter(det.a_right)))
|
||||
to_chat(user, "<span class='warning'>Assembly must contain one igniter.</span>")
|
||||
return
|
||||
if(!det.secured)
|
||||
to_chat(user, "<span class='warning'>Assembly must be secured with screwdriver.</span>")
|
||||
return
|
||||
path = 1
|
||||
to_chat(user, "<span class='notice'>You add [W] to the metal casing.</span>")
|
||||
playsound(src, 'sound/items/Screwdriver2.ogg', 25, -3)
|
||||
user.remove_from_mob(det)
|
||||
det.loc = src
|
||||
detonator = det
|
||||
if(istimer(detonator.a_left))
|
||||
var/obj/item/device/assembly/timer/T = detonator.a_left
|
||||
det_time = 10*T.time
|
||||
if(istimer(detonator.a_right))
|
||||
var/obj/item/device/assembly/timer/T = detonator.a_right
|
||||
det_time = 10*T.time
|
||||
icon_state = initial(icon_state) +"_ass"
|
||||
name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
|
||||
stage = 1
|
||||
else if(W.has_tool_quality(TOOL_SCREWDRIVER) && path != 2)
|
||||
if(stage == 1)
|
||||
path = 1
|
||||
if(beakers.len)
|
||||
to_chat(user, "<span class='notice'>You lock the assembly.</span>")
|
||||
name = "grenade"
|
||||
else
|
||||
// to_chat(user, "<span class='warning'>You need to add at least one beaker before locking the assembly.</span>")
|
||||
to_chat(user, "<span class='notice'>You lock the empty assembly.</span>")
|
||||
name = "fake grenade"
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
icon_state = initial(icon_state) +"_locked"
|
||||
stage = 2
|
||||
else if(stage == 2)
|
||||
if(active && prob(95))
|
||||
to_chat(user, "<span class='warning'>You trigger the assembly!</span>")
|
||||
detonate()
|
||||
else if(sealed)
|
||||
to_chat(user, "<span class='warning'>This grenade lacks a way to disassemble it.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You unlock the assembly.</span>")
|
||||
playsound(src, W.usesound, 50, -3)
|
||||
name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
|
||||
icon_state = initial(icon_state) + (detonator?"_ass":"")
|
||||
stage = 1
|
||||
active = 0
|
||||
else if(is_type_in_list(W, allowed_containers) && (!stage || stage==1) && path != 2)
|
||||
path = 1
|
||||
if(beakers.len == 2)
|
||||
to_chat(user, "<span class='warning'>The grenade can not hold more containers.</span>")
|
||||
return
|
||||
else
|
||||
if(W.reagents.total_volume)
|
||||
to_chat(user, "<span class='notice'>You add \the [W] to the assembly.</span>")
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
beakers += W
|
||||
stage = 1
|
||||
name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [W] is empty.</span>")
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/examine(mob/user)
|
||||
. = ..()
|
||||
if(detonator)
|
||||
. += "It has [detonator.name] attached to it."
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/activate(mob/user as mob)
|
||||
if(active) return
|
||||
|
||||
if(detonator)
|
||||
if(!isigniter(detonator.a_left))
|
||||
detonator.a_left.activate()
|
||||
active = 1
|
||||
if(!isigniter(detonator.a_right))
|
||||
detonator.a_right.activate()
|
||||
active = 1
|
||||
if(active)
|
||||
icon_state = initial(icon_state) + "_active"
|
||||
|
||||
if(user)
|
||||
msg_admin_attack("[key_name_admin(user)] primed \a [src.name]")
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/proc/primed(var/primed = 1)
|
||||
if(active)
|
||||
icon_state = initial(icon_state) + (primed?"_primed":"_active")
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/detonate()
|
||||
if(!stage || stage<2) return
|
||||
|
||||
var/has_reagents = 0
|
||||
for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
|
||||
if(G.reagents.total_volume) has_reagents = 1
|
||||
|
||||
active = 0
|
||||
if(!has_reagents)
|
||||
icon_state = initial(icon_state) +"_locked"
|
||||
playsound(src, 'sound/items/Screwdriver2.ogg', 50, 1)
|
||||
spawn(0) //Otherwise det_time is erroneously set to 0 after this
|
||||
if(istimer(detonator.a_left)) //Make sure description reflects that the timer has been reset
|
||||
var/obj/item/device/assembly/timer/T = detonator.a_left
|
||||
det_time = 10*T.time
|
||||
if(istimer(detonator.a_right))
|
||||
var/obj/item/device/assembly/timer/T = detonator.a_right
|
||||
det_time = 10*T.time
|
||||
return
|
||||
|
||||
playsound(src, 'sound/effects/bamf.ogg', 50, 1)
|
||||
|
||||
for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
|
||||
G.reagents.trans_to_obj(src, G.reagents.total_volume)
|
||||
|
||||
if(src.reagents.total_volume) //The possible reactions didnt use up all reagents.
|
||||
var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread()
|
||||
steam.set_up(10, 0, get_turf(src))
|
||||
steam.attach(src)
|
||||
steam.start()
|
||||
|
||||
for(var/atom/A in view(affected_area, src.loc))
|
||||
if( A == src ) continue
|
||||
src.reagents.touch(A)
|
||||
|
||||
if(istype(loc, /mob/living/carbon)) //drop dat grenade if it goes off in your hand
|
||||
var/mob/living/carbon/C = loc
|
||||
C.drop_from_inventory(src)
|
||||
C.throw_mode_off()
|
||||
|
||||
invisibility = INVISIBILITY_MAXIMUM //Why am i doing this?
|
||||
spawn(50) //To make sure all reagents can work
|
||||
qdel(src) //correctly before deleting the grenade.
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/large
|
||||
name = "large chem grenade"
|
||||
desc = "An oversized grenade that affects a larger area."
|
||||
icon_state = "large_grenade"
|
||||
allowed_containers = list(/obj/item/weapon/reagent_containers/glass)
|
||||
origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3)
|
||||
affected_area = 4
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/metalfoam
|
||||
name = "metal-foam grenade"
|
||||
desc = "Used for emergency sealing of air breaches."
|
||||
icon_state = "foam"
|
||||
path = 1
|
||||
stage = 2
|
||||
sealed = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/metalfoam/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
|
||||
|
||||
B1.reagents.add_reagent("aluminum", 30)
|
||||
B2.reagents.add_reagent("foaming_agent", 10)
|
||||
B2.reagents.add_reagent("pacid", 10)
|
||||
|
||||
detonator = new/obj/item/device/assembly_holder/timer_igniter(src)
|
||||
|
||||
beakers += B1
|
||||
beakers += B2
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/incendiary
|
||||
name = "incendiary grenade"
|
||||
desc = "Used for clearing rooms of living things."
|
||||
icon_state = "incendiary"
|
||||
path = 1
|
||||
stage = 2
|
||||
sealed = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/incendiary/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
|
||||
|
||||
B1.reagents.add_reagent("aluminum", 15)
|
||||
B1.reagents.add_reagent("fuel",20)
|
||||
B2.reagents.add_reagent("phoron", 15)
|
||||
B2.reagents.add_reagent("sacid", 15)
|
||||
B1.reagents.add_reagent("fuel",20)
|
||||
|
||||
detonator = new/obj/item/device/assembly_holder/timer_igniter(src)
|
||||
|
||||
beakers += B1
|
||||
beakers += B2
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/antiweed
|
||||
name = "weedkiller grenade"
|
||||
desc = "Used for purging large areas of invasive plant species. Contents under pressure. Do not directly inhale contents."
|
||||
path = 1
|
||||
stage = 2
|
||||
sealed = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/antiweed/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
|
||||
|
||||
B1.reagents.add_reagent("plantbgone", 25)
|
||||
B1.reagents.add_reagent("potassium", 25)
|
||||
B2.reagents.add_reagent("phosphorus", 25)
|
||||
B2.reagents.add_reagent("sugar", 25)
|
||||
|
||||
detonator = new/obj/item/device/assembly_holder/timer_igniter(src)
|
||||
|
||||
beakers += B1
|
||||
beakers += B2
|
||||
icon_state = "grenade"
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/cleaner
|
||||
name = "cleaner grenade"
|
||||
desc = "BLAM!-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas."
|
||||
icon_state = "cleaner"
|
||||
stage = 2
|
||||
path = 1
|
||||
sealed = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/cleaner/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
|
||||
|
||||
B1.reagents.add_reagent("fluorosurfactant", 40)
|
||||
B2.reagents.add_reagent("water", 40)
|
||||
B2.reagents.add_reagent("cleaner", 10)
|
||||
|
||||
detonator = new/obj/item/device/assembly_holder/timer_igniter(src)
|
||||
|
||||
beakers += B1
|
||||
beakers += B2
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/teargas
|
||||
name = "tear gas grenade"
|
||||
desc = "Concentrated Capsaicin. Contents under pressure. Use with caution."
|
||||
icon_state = "teargas"
|
||||
stage = 2
|
||||
path = 1
|
||||
sealed = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/chem_grenade/teargas/Initialize()
|
||||
. = ..()
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/large/B1 = new(src)
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/large/B2 = new(src)
|
||||
|
||||
B1.reagents.add_reagent("phosphorus", 40)
|
||||
B1.reagents.add_reagent("potassium", 40)
|
||||
B1.reagents.add_reagent("condensedcapsaicin", 40)
|
||||
B2.reagents.add_reagent("sugar", 40)
|
||||
B2.reagents.add_reagent("condensedcapsaicin", 80)
|
||||
|
||||
detonator = new/obj/item/device/assembly_holder/timer_igniter(src)
|
||||
|
||||
beakers += B1
|
||||
beakers += B2
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/obj/item/weapon/grenade/empgrenade
|
||||
name = "emp grenade"
|
||||
icon_state = "emp"
|
||||
item_state = "empgrenade"
|
||||
origin_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 3)
|
||||
var/emp_heavy = 2
|
||||
var/emp_med = 4
|
||||
var/emp_light = 7
|
||||
var/emp_long = 10
|
||||
|
||||
/obj/item/weapon/grenade/empgrenade/detonate()
|
||||
..()
|
||||
if(empulse(src, emp_heavy, emp_med, emp_light, emp_long))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/empgrenade/low_yield
|
||||
name = "low yield emp grenade"
|
||||
desc = "A weaker variant of the EMP grenade"
|
||||
icon_state = "lyemp"
|
||||
origin_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 3)
|
||||
emp_heavy = 1
|
||||
emp_med = 2
|
||||
emp_light = 3
|
||||
/obj/item/weapon/grenade/empgrenade
|
||||
name = "emp grenade"
|
||||
icon_state = "emp"
|
||||
item_state = "empgrenade"
|
||||
origin_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 3)
|
||||
var/emp_heavy = 2
|
||||
var/emp_med = 4
|
||||
var/emp_light = 7
|
||||
var/emp_long = 10
|
||||
|
||||
/obj/item/weapon/grenade/empgrenade/detonate()
|
||||
..()
|
||||
if(empulse(src, emp_heavy, emp_med, emp_light, emp_long))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/empgrenade/low_yield
|
||||
name = "low yield emp grenade"
|
||||
desc = "A weaker variant of the EMP grenade"
|
||||
icon_state = "lyemp"
|
||||
origin_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 3)
|
||||
emp_heavy = 1
|
||||
emp_med = 2
|
||||
emp_light = 3
|
||||
emp_long = 4
|
||||
@@ -1,165 +1,165 @@
|
||||
/obj/item/weapon/grenade/flashbang
|
||||
name = "flashbang"
|
||||
icon_state = "flashbang"
|
||||
item_state = "flashbang"
|
||||
origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 1)
|
||||
var/max_range = 10 //The maximum range possible, including species effect mods. Cuts off at 7 for normal humans. Should be 3 higher than your intended target range for affecting normal humans.
|
||||
var/banglet = 0
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/detonate()
|
||||
..()
|
||||
for(var/obj/structure/closet/L in hear(max_range, get_turf(src)))
|
||||
if(locate(/mob/living/carbon/, L))
|
||||
for(var/mob/living/carbon/M in L)
|
||||
bang(get_turf(src), M)
|
||||
|
||||
for(var/mob/living/carbon/M in hear(max_range, get_turf(src)))
|
||||
bang(get_turf(src), M)
|
||||
|
||||
for(var/obj/structure/blob/B in hear(max_range - 2,get_turf(src))) //Blob damage here
|
||||
var/damage = round(30/(get_dist(B,get_turf(src))+1))
|
||||
if(B.overmind)
|
||||
damage *= B.overmind.blob_type.burn_multiplier
|
||||
B.adjust_integrity(-damage)
|
||||
|
||||
new/obj/effect/effect/sparks(src.loc)
|
||||
new/obj/effect/effect/smoke/illumination(src.loc, 5, range=30, power=30, color="#FFFFFF")
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/proc/bang(var/turf/T , var/mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged.
|
||||
to_chat(M, "<span class='danger'>BANG</span>") // Called during the loop that bangs people in lockers/containers and when banging
|
||||
playsound(src, 'sound/effects/bang.ogg', 50, 1, 30) // people in normal view. Could theroetically be called during other explosions.
|
||||
// -- Polymorph
|
||||
|
||||
//Checking for protections
|
||||
var/eye_safety = 0
|
||||
var/ear_safety = 0
|
||||
if(iscarbon(M))
|
||||
eye_safety = M.eyecheck()
|
||||
ear_safety = M.get_ear_protection()
|
||||
|
||||
//Flashing everyone
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/flash_effectiveness = 1
|
||||
var/bang_effectiveness = 1
|
||||
if(ishuman(M))
|
||||
flash_effectiveness = H.species.flash_mod
|
||||
bang_effectiveness = H.species.sound_mod
|
||||
if(eye_safety < 1 && get_dist(M, T) <= round(max_range * 0.7 * flash_effectiveness))
|
||||
M.flash_eyes()
|
||||
M.Confuse(2 * flash_effectiveness)
|
||||
M.Weaken(5 * flash_effectiveness)
|
||||
|
||||
//Now applying sound
|
||||
if((get_dist(M, T) <= round(max_range * 0.3 * bang_effectiveness) || src.loc == M.loc || src.loc == M))
|
||||
if(ear_safety > 0)
|
||||
M.Confuse(2)
|
||||
M.Weaken(1)
|
||||
else
|
||||
M.Confuse(10)
|
||||
M.Weaken(3)
|
||||
if ((prob(14) || (M == src.loc && prob(70))))
|
||||
M.ear_damage += rand(1, 10)
|
||||
else
|
||||
M.ear_damage += rand(0, 5)
|
||||
M.ear_deaf = max(M.ear_deaf,15)
|
||||
|
||||
else if(get_dist(M, T) <= round(max_range * 0.5 * bang_effectiveness))
|
||||
if(!ear_safety)
|
||||
M.Confuse(8)
|
||||
M.ear_damage += rand(0, 3)
|
||||
M.ear_deaf = max(M.ear_deaf,10)
|
||||
|
||||
else if(!ear_safety && get_dist(M, T) <= (max_range * 0.7 * bang_effectiveness))
|
||||
M.Confuse(4)
|
||||
M.ear_damage += rand(0, 1)
|
||||
M.ear_deaf = max(M.ear_deaf,5)
|
||||
|
||||
//This really should be in mob not every check
|
||||
if(ishuman(M))
|
||||
var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
|
||||
if (E && E.damage >= E.min_bruised_damage)
|
||||
to_chat(M, "<span class='danger'>Your eyes start to burn badly!</span>")
|
||||
if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang)))
|
||||
if (E.damage >= E.min_broken_damage)
|
||||
to_chat(M, "<span class='danger'>You can't see anything!</span>")
|
||||
if (M.ear_damage >= 15)
|
||||
to_chat(M, "<span class='danger'>Your ears start to ring badly!</span>")
|
||||
if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang)))
|
||||
if (prob(M.ear_damage - 10 + 5))
|
||||
to_chat(M, "<span class='danger'>You can't hear anything!</span>")
|
||||
M.sdisabilities |= DEAF
|
||||
else if(M.ear_damage >= 5)
|
||||
to_chat(M, "<span class='danger'>Your ears start to ring!</span>")
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/Destroy()
|
||||
walk(src, 0) // Because we might have called walk_away, we must stop the walk loop or BYOND keeps an internal reference to us forever.
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/clusterbang//Created by Polymorph, fixed by Sieve
|
||||
desc = "Use of this weapon may constiute a war crime in your area, consult your local Site Manager."
|
||||
name = "clusterbang"
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "clusterbang"
|
||||
var/can_repeat = TRUE // Does this thing drop mini-clusterbangs?
|
||||
var/min_banglets = 4
|
||||
var/max_banglets = 8
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/clusterbang/detonate()
|
||||
var/numspawned = rand(min_banglets, max_banglets)
|
||||
var/again = 0
|
||||
|
||||
if(can_repeat)
|
||||
for(var/more = numspawned, more > 0, more--)
|
||||
if(prob(35))
|
||||
again++
|
||||
numspawned--
|
||||
|
||||
for(var/do_spawn = numspawned, do_spawn > 0, do_spawn--)
|
||||
new /obj/item/weapon/grenade/flashbang/cluster(src.loc)//Launches flashbangs
|
||||
playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
|
||||
|
||||
for(var/do_again = again, do_again > 0, do_again--)
|
||||
new /obj/item/weapon/grenade/flashbang/clusterbang/segment(src.loc)//Creates a 'segment' that launches a few more flashbangs
|
||||
playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/clusterbang/segment
|
||||
desc = "A smaller segment of a clusterbang. Better run."
|
||||
name = "clusterbang segment"
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "clusterbang_segment"
|
||||
can_repeat = FALSE
|
||||
banglet = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/clusterbang/segment/New()//Segments should never exist except part of the clusterbang, since these immediately 'do their thing' and asplode
|
||||
..()
|
||||
|
||||
icon_state = "clusterbang_segment_active"
|
||||
|
||||
var/stepdist = rand(1,4)//How far to step
|
||||
var/temploc = src.loc//Saves the current location to know where to step away from
|
||||
walk_away(src,temploc,stepdist)//I must go, my people need me
|
||||
|
||||
var/dettime = rand(15,60)
|
||||
spawn(dettime)
|
||||
detonate()
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/cluster
|
||||
banglet = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/cluster/New()//Same concept as the segments, so that all of the parts don't become reliant on the clusterbang
|
||||
..()
|
||||
|
||||
icon_state = "flashbang_active"
|
||||
|
||||
var/stepdist = rand(1,3)
|
||||
var/temploc = src.loc
|
||||
walk_away(src,temploc,stepdist)
|
||||
|
||||
var/dettime = rand(15,60)
|
||||
spawn(dettime)
|
||||
/obj/item/weapon/grenade/flashbang
|
||||
name = "flashbang"
|
||||
icon_state = "flashbang"
|
||||
item_state = "flashbang"
|
||||
origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 1)
|
||||
var/max_range = 10 //The maximum range possible, including species effect mods. Cuts off at 7 for normal humans. Should be 3 higher than your intended target range for affecting normal humans.
|
||||
var/banglet = 0
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/detonate()
|
||||
..()
|
||||
for(var/obj/structure/closet/L in hear(max_range, get_turf(src)))
|
||||
if(locate(/mob/living/carbon/, L))
|
||||
for(var/mob/living/carbon/M in L)
|
||||
bang(get_turf(src), M)
|
||||
|
||||
for(var/mob/living/carbon/M in hear(max_range, get_turf(src)))
|
||||
bang(get_turf(src), M)
|
||||
|
||||
for(var/obj/structure/blob/B in hear(max_range - 2,get_turf(src))) //Blob damage here
|
||||
var/damage = round(30/(get_dist(B,get_turf(src))+1))
|
||||
if(B.overmind)
|
||||
damage *= B.overmind.blob_type.burn_multiplier
|
||||
B.adjust_integrity(-damage)
|
||||
|
||||
new/obj/effect/effect/sparks(src.loc)
|
||||
new/obj/effect/effect/smoke/illumination(src.loc, 5, range=30, power=30, color="#FFFFFF")
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/proc/bang(var/turf/T , var/mob/living/carbon/M) // Added a new proc called 'bang' that takes a location and a person to be banged.
|
||||
to_chat(M, "<span class='danger'>BANG</span>") // Called during the loop that bangs people in lockers/containers and when banging
|
||||
playsound(src, 'sound/effects/bang.ogg', 50, 1, 30) // people in normal view. Could theroetically be called during other explosions.
|
||||
// -- Polymorph
|
||||
|
||||
//Checking for protections
|
||||
var/eye_safety = 0
|
||||
var/ear_safety = 0
|
||||
if(iscarbon(M))
|
||||
eye_safety = M.eyecheck()
|
||||
ear_safety = M.get_ear_protection()
|
||||
|
||||
//Flashing everyone
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/flash_effectiveness = 1
|
||||
var/bang_effectiveness = 1
|
||||
if(ishuman(M))
|
||||
flash_effectiveness = H.species.flash_mod
|
||||
bang_effectiveness = H.species.sound_mod
|
||||
if(eye_safety < 1 && get_dist(M, T) <= round(max_range * 0.7 * flash_effectiveness))
|
||||
M.flash_eyes()
|
||||
M.Confuse(2 * flash_effectiveness)
|
||||
M.Weaken(5 * flash_effectiveness)
|
||||
|
||||
//Now applying sound
|
||||
if((get_dist(M, T) <= round(max_range * 0.3 * bang_effectiveness) || src.loc == M.loc || src.loc == M))
|
||||
if(ear_safety > 0)
|
||||
M.Confuse(2)
|
||||
M.Weaken(1)
|
||||
else
|
||||
M.Confuse(10)
|
||||
M.Weaken(3)
|
||||
if ((prob(14) || (M == src.loc && prob(70))))
|
||||
M.ear_damage += rand(1, 10)
|
||||
else
|
||||
M.ear_damage += rand(0, 5)
|
||||
M.ear_deaf = max(M.ear_deaf,15)
|
||||
|
||||
else if(get_dist(M, T) <= round(max_range * 0.5 * bang_effectiveness))
|
||||
if(!ear_safety)
|
||||
M.Confuse(8)
|
||||
M.ear_damage += rand(0, 3)
|
||||
M.ear_deaf = max(M.ear_deaf,10)
|
||||
|
||||
else if(!ear_safety && get_dist(M, T) <= (max_range * 0.7 * bang_effectiveness))
|
||||
M.Confuse(4)
|
||||
M.ear_damage += rand(0, 1)
|
||||
M.ear_deaf = max(M.ear_deaf,5)
|
||||
|
||||
//This really should be in mob not every check
|
||||
if(ishuman(M))
|
||||
var/obj/item/organ/internal/eyes/E = H.internal_organs_by_name[O_EYES]
|
||||
if (E && E.damage >= E.min_bruised_damage)
|
||||
to_chat(M, "<span class='danger'>Your eyes start to burn badly!</span>")
|
||||
if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang)))
|
||||
if (E.damage >= E.min_broken_damage)
|
||||
to_chat(M, "<span class='danger'>You can't see anything!</span>")
|
||||
if (M.ear_damage >= 15)
|
||||
to_chat(M, "<span class='danger'>Your ears start to ring badly!</span>")
|
||||
if(!banglet && !(istype(src , /obj/item/weapon/grenade/flashbang/clusterbang)))
|
||||
if (prob(M.ear_damage - 10 + 5))
|
||||
to_chat(M, "<span class='danger'>You can't hear anything!</span>")
|
||||
M.sdisabilities |= DEAF
|
||||
else if(M.ear_damage >= 5)
|
||||
to_chat(M, "<span class='danger'>Your ears start to ring!</span>")
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/Destroy()
|
||||
walk(src, 0) // Because we might have called walk_away, we must stop the walk loop or BYOND keeps an internal reference to us forever.
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/clusterbang//Created by Polymorph, fixed by Sieve
|
||||
desc = "Use of this weapon may constiute a war crime in your area, consult your local Site Manager."
|
||||
name = "clusterbang"
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "clusterbang"
|
||||
var/can_repeat = TRUE // Does this thing drop mini-clusterbangs?
|
||||
var/min_banglets = 4
|
||||
var/max_banglets = 8
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/clusterbang/detonate()
|
||||
var/numspawned = rand(min_banglets, max_banglets)
|
||||
var/again = 0
|
||||
|
||||
if(can_repeat)
|
||||
for(var/more = numspawned, more > 0, more--)
|
||||
if(prob(35))
|
||||
again++
|
||||
numspawned--
|
||||
|
||||
for(var/do_spawn = numspawned, do_spawn > 0, do_spawn--)
|
||||
new /obj/item/weapon/grenade/flashbang/cluster(src.loc)//Launches flashbangs
|
||||
playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
|
||||
|
||||
for(var/do_again = again, do_again > 0, do_again--)
|
||||
new /obj/item/weapon/grenade/flashbang/clusterbang/segment(src.loc)//Creates a 'segment' that launches a few more flashbangs
|
||||
playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/clusterbang/segment
|
||||
desc = "A smaller segment of a clusterbang. Better run."
|
||||
name = "clusterbang segment"
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "clusterbang_segment"
|
||||
can_repeat = FALSE
|
||||
banglet = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/clusterbang/segment/New()//Segments should never exist except part of the clusterbang, since these immediately 'do their thing' and asplode
|
||||
..()
|
||||
|
||||
icon_state = "clusterbang_segment_active"
|
||||
|
||||
var/stepdist = rand(1,4)//How far to step
|
||||
var/temploc = src.loc//Saves the current location to know where to step away from
|
||||
walk_away(src,temploc,stepdist)//I must go, my people need me
|
||||
|
||||
var/dettime = rand(15,60)
|
||||
spawn(dettime)
|
||||
detonate()
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/cluster
|
||||
banglet = TRUE
|
||||
|
||||
/obj/item/weapon/grenade/flashbang/cluster/New()//Same concept as the segments, so that all of the parts don't become reliant on the clusterbang
|
||||
..()
|
||||
|
||||
icon_state = "flashbang_active"
|
||||
|
||||
var/stepdist = rand(1,3)
|
||||
var/temploc = src.loc
|
||||
walk_away(src,temploc,stepdist)
|
||||
|
||||
var/dettime = rand(15,60)
|
||||
spawn(dettime)
|
||||
detonate()
|
||||
@@ -1,119 +1,119 @@
|
||||
/obj/item/weapon/grenade
|
||||
name = "grenade"
|
||||
desc = "A hand held grenade, with an adjustable timer."
|
||||
w_class = ITEMSIZE_SMALL
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "grenade"
|
||||
item_state = "grenade"
|
||||
throw_speed = 4
|
||||
throw_range = 20
|
||||
slot_flags = SLOT_MASK|SLOT_BELT
|
||||
|
||||
var/active = 0
|
||||
var/det_time = 50
|
||||
var/loadable = TRUE
|
||||
var/arm_sound = 'sound/weapons/armbomb.ogg'
|
||||
var/hud_state = "grenade_he" // TGMC Ammo HUD Port
|
||||
var/hud_state_empty = "grenade_empty" // TGMC Ammo HUD Port
|
||||
|
||||
/obj/item/weapon/grenade/proc/clown_check(var/mob/living/user)
|
||||
if((CLUMSY in user.mutations) && prob(50))
|
||||
to_chat(user, "<span class='warning'>Huh? How does this thing work?</span>")
|
||||
|
||||
activate(user)
|
||||
add_fingerprint(user)
|
||||
spawn(5)
|
||||
detonate()
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
/*/obj/item/weapon/grenade/afterattack(atom/target as mob|obj|turf|area, mob/user as mob)
|
||||
if (istype(target, /obj/item/weapon/storage)) return ..() // Trying to put it in a full container
|
||||
if (istype(target, /obj/item/weapon/gun/grenadelauncher)) return ..()
|
||||
if((user.get_active_hand() == src) && (!active) && (clown_check(user)) && target.loc != src.loc)
|
||||
to_chat(user, "<span class='warning'>You prime the [name]! [det_time/10] seconds!</span>")
|
||||
active = 1
|
||||
icon_state = initial(icon_state) + "_active"
|
||||
playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
|
||||
spawn(det_time)
|
||||
detonate()
|
||||
return
|
||||
user.set_dir(get_dir(user, target))
|
||||
user.drop_item()
|
||||
var/t = (isturf(target) ? target : target.loc)
|
||||
walk_towards(src, t, 3)
|
||||
return*/
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/examine(mob/user)
|
||||
. = ..()
|
||||
if(get_dist(user, src) == 0)
|
||||
if(det_time > 1)
|
||||
. += "The timer is set to [det_time/10] seconds."
|
||||
else if(det_time == null)
|
||||
. += "\The [src] is set for instant detonation."
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/attack_self(mob/user as mob)
|
||||
if(!active)
|
||||
if(clown_check(user))
|
||||
to_chat(user, "<span class='warning'>You prime \the [name]! [det_time/10] seconds!</span>")
|
||||
|
||||
activate(user)
|
||||
add_fingerprint(user)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
C.throw_mode_on()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/proc/activate(mob/user as mob)
|
||||
if(active)
|
||||
return
|
||||
|
||||
if(user)
|
||||
msg_admin_attack("[key_name_admin(user)] primed \a [src.name]")
|
||||
|
||||
icon_state = initial(icon_state) + "_active"
|
||||
active = 1
|
||||
playsound(src, arm_sound, 75, 1, -3)
|
||||
|
||||
spawn(det_time)
|
||||
detonate()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/proc/detonate()
|
||||
// playsound(src, 'sound/items/Welder2.ogg', 25, 1)
|
||||
var/turf/T = get_turf(src)
|
||||
if(T)
|
||||
T.hotspot_expose(700,125)
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
switch(det_time)
|
||||
if (1)
|
||||
det_time = 10
|
||||
to_chat(user, "<span class='notice'>You set the [name] for 1 second detonation time.</span>")
|
||||
if (10)
|
||||
det_time = 30
|
||||
to_chat(user, "<span class='notice'>You set the [name] for 3 second detonation time.</span>")
|
||||
if (30)
|
||||
det_time = 50
|
||||
to_chat(user, "<span class='notice'>You set the [name] for 5 second detonation time.</span>")
|
||||
if (50)
|
||||
det_time = 1
|
||||
to_chat(user, "<span class='notice'>You set the [name] for instant detonation.</span>")
|
||||
add_fingerprint(user)
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/attack_hand()
|
||||
walk(src, null, null)
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/vendor_action(var/obj/machinery/vending/V)
|
||||
/obj/item/weapon/grenade
|
||||
name = "grenade"
|
||||
desc = "A hand held grenade, with an adjustable timer."
|
||||
w_class = ITEMSIZE_SMALL
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "grenade"
|
||||
item_state = "grenade"
|
||||
throw_speed = 4
|
||||
throw_range = 20
|
||||
slot_flags = SLOT_MASK|SLOT_BELT
|
||||
|
||||
var/active = 0
|
||||
var/det_time = 50
|
||||
var/loadable = TRUE
|
||||
var/arm_sound = 'sound/weapons/armbomb.ogg'
|
||||
var/hud_state = "grenade_he" // TGMC Ammo HUD Port
|
||||
var/hud_state_empty = "grenade_empty" // TGMC Ammo HUD Port
|
||||
|
||||
/obj/item/weapon/grenade/proc/clown_check(var/mob/living/user)
|
||||
if((CLUMSY in user.mutations) && prob(50))
|
||||
to_chat(user, "<span class='warning'>Huh? How does this thing work?</span>")
|
||||
|
||||
activate(user)
|
||||
add_fingerprint(user)
|
||||
spawn(5)
|
||||
detonate()
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
/*/obj/item/weapon/grenade/afterattack(atom/target as mob|obj|turf|area, mob/user as mob)
|
||||
if (istype(target, /obj/item/weapon/storage)) return ..() // Trying to put it in a full container
|
||||
if (istype(target, /obj/item/weapon/gun/grenadelauncher)) return ..()
|
||||
if((user.get_active_hand() == src) && (!active) && (clown_check(user)) && target.loc != src.loc)
|
||||
to_chat(user, "<span class='warning'>You prime the [name]! [det_time/10] seconds!</span>")
|
||||
active = 1
|
||||
icon_state = initial(icon_state) + "_active"
|
||||
playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
|
||||
spawn(det_time)
|
||||
detonate()
|
||||
return
|
||||
user.set_dir(get_dir(user, target))
|
||||
user.drop_item()
|
||||
var/t = (isturf(target) ? target : target.loc)
|
||||
walk_towards(src, t, 3)
|
||||
return*/
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/examine(mob/user)
|
||||
. = ..()
|
||||
if(get_dist(user, src) == 0)
|
||||
if(det_time > 1)
|
||||
. += "The timer is set to [det_time/10] seconds."
|
||||
else if(det_time == null)
|
||||
. += "\The [src] is set for instant detonation."
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/attack_self(mob/user as mob)
|
||||
if(!active)
|
||||
if(clown_check(user))
|
||||
to_chat(user, "<span class='warning'>You prime \the [name]! [det_time/10] seconds!</span>")
|
||||
|
||||
activate(user)
|
||||
add_fingerprint(user)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
C.throw_mode_on()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/proc/activate(mob/user as mob)
|
||||
if(active)
|
||||
return
|
||||
|
||||
if(user)
|
||||
msg_admin_attack("[key_name_admin(user)] primed \a [src.name]")
|
||||
|
||||
icon_state = initial(icon_state) + "_active"
|
||||
active = 1
|
||||
playsound(src, arm_sound, 75, 1, -3)
|
||||
|
||||
spawn(det_time)
|
||||
detonate()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/proc/detonate()
|
||||
// playsound(src, 'sound/items/Welder2.ogg', 25, 1)
|
||||
var/turf/T = get_turf(src)
|
||||
if(T)
|
||||
T.hotspot_expose(700,125)
|
||||
|
||||
|
||||
/obj/item/weapon/grenade/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
switch(det_time)
|
||||
if (1)
|
||||
det_time = 10
|
||||
to_chat(user, "<span class='notice'>You set the [name] for 1 second detonation time.</span>")
|
||||
if (10)
|
||||
det_time = 30
|
||||
to_chat(user, "<span class='notice'>You set the [name] for 3 second detonation time.</span>")
|
||||
if (30)
|
||||
det_time = 50
|
||||
to_chat(user, "<span class='notice'>You set the [name] for 5 second detonation time.</span>")
|
||||
if (50)
|
||||
det_time = 1
|
||||
to_chat(user, "<span class='notice'>You set the [name] for instant detonation.</span>")
|
||||
add_fingerprint(user)
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/attack_hand()
|
||||
walk(src, null, null)
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/vendor_action(var/obj/machinery/vending/V)
|
||||
activate(V)
|
||||
@@ -1,39 +1,39 @@
|
||||
/obj/item/weapon/grenade/smokebomb
|
||||
desc = "It is set to detonate in 2 seconds. These high-tech grenades can have their color adapted on the fly with a multitool!"
|
||||
name = "smoke bomb"
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "flashbang"
|
||||
det_time = 20
|
||||
item_state = "flashbang"
|
||||
slot_flags = SLOT_BELT
|
||||
hud_state = "grenade_smoke"
|
||||
var/datum/effect/effect/system/smoke_spread/bad/smoke
|
||||
var/smoke_color
|
||||
var/smoke_strength = 8
|
||||
|
||||
/obj/item/weapon/grenade/smokebomb/New()
|
||||
..()
|
||||
src.smoke = new /datum/effect/effect/system/smoke_spread/bad()
|
||||
src.smoke.attach(src)
|
||||
|
||||
/obj/item/weapon/grenade/smokebomb/Destroy()
|
||||
qdel(smoke)
|
||||
smoke = null
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/grenade/smokebomb/detonate()
|
||||
playsound(src, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
src.smoke.set_up(10, 0, usr.loc)
|
||||
spawn(0)
|
||||
for(var/i = 1 to smoke_strength)
|
||||
src.smoke.start(smoke_color)
|
||||
sleep(10)
|
||||
qdel(src)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/smokebomb/attackby(obj/item/I as obj, mob/user as mob)
|
||||
if(istype(I,/obj/item/device/multitool))
|
||||
var/new_smoke_color = input(user, "Choose a color for the smoke:", "Smoke Color", smoke_color) as color|null
|
||||
if(new_smoke_color)
|
||||
smoke_color = new_smoke_color
|
||||
/obj/item/weapon/grenade/smokebomb
|
||||
desc = "It is set to detonate in 2 seconds. These high-tech grenades can have their color adapted on the fly with a multitool!"
|
||||
name = "smoke bomb"
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "flashbang"
|
||||
det_time = 20
|
||||
item_state = "flashbang"
|
||||
slot_flags = SLOT_BELT
|
||||
hud_state = "grenade_smoke"
|
||||
var/datum/effect/effect/system/smoke_spread/bad/smoke
|
||||
var/smoke_color
|
||||
var/smoke_strength = 8
|
||||
|
||||
/obj/item/weapon/grenade/smokebomb/New()
|
||||
..()
|
||||
src.smoke = new /datum/effect/effect/system/smoke_spread/bad()
|
||||
src.smoke.attach(src)
|
||||
|
||||
/obj/item/weapon/grenade/smokebomb/Destroy()
|
||||
qdel(smoke)
|
||||
smoke = null
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/grenade/smokebomb/detonate()
|
||||
playsound(src, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
src.smoke.set_up(10, 0, usr.loc)
|
||||
spawn(0)
|
||||
for(var/i = 1 to smoke_strength)
|
||||
src.smoke.start(smoke_color)
|
||||
sleep(10)
|
||||
qdel(src)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/smokebomb/attackby(obj/item/I as obj, mob/user as mob)
|
||||
if(istype(I,/obj/item/device/multitool))
|
||||
var/new_smoke_color = input(user, "Choose a color for the smoke:", "Smoke Color", smoke_color) as color|null
|
||||
if(new_smoke_color)
|
||||
smoke_color = new_smoke_color
|
||||
|
||||
@@ -1,79 +1,79 @@
|
||||
/obj/item/weapon/grenade/spawnergrenade
|
||||
desc = "It is set to detonate in 5 seconds. It will unleash an unspecified anomaly into the vicinity."
|
||||
name = "delivery grenade"
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "delivery"
|
||||
item_state = "flashbang"
|
||||
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4)
|
||||
var/banglet = 0
|
||||
var/spawner_type = null // must be an object path
|
||||
var/deliveryamt = 1 // amount of type to deliver
|
||||
|
||||
// Detonate now just handles the two loops that query for people in lockers and people who can see it.
|
||||
/obj/item/weapon/grenade/spawnergrenade/detonate()
|
||||
|
||||
if(spawner_type && deliveryamt)
|
||||
// Make a quick flash
|
||||
var/turf/T = get_turf(src)
|
||||
playsound(src, 'sound/effects/phasein.ogg', 100, 1)
|
||||
for(var/mob/living/carbon/human/M in viewers(T, null))
|
||||
if(M:eyecheck() <= 0)
|
||||
M.flash_eyes()
|
||||
|
||||
// Spawn some hostile syndicate critters
|
||||
for(var/i=1, i<=deliveryamt, i++)
|
||||
var/atom/movable/x = new spawner_type(T)
|
||||
if(prob(50))
|
||||
for(var/j = 1, j <= rand(1, 3), j++)
|
||||
step(x, pick(NORTH,SOUTH,EAST,WEST))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks
|
||||
name = "manhack delivery grenade"
|
||||
spawner_type = /mob/living/simple_mob/mechanical/viscerator
|
||||
deliveryamt = 5
|
||||
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4, TECH_ILLEGAL = 4)
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks/mercenary
|
||||
spawner_type = /mob/living/simple_mob/mechanical/viscerator/mercenary
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks/raider
|
||||
spawner_type = /mob/living/simple_mob/mechanical/viscerator/raider
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks/station
|
||||
desc = "It is set to detonate in 5 seconds. It will deploy three weaponized survey drones."
|
||||
deliveryamt = 3
|
||||
spawner_type = /mob/living/simple_mob/mechanical/viscerator/station
|
||||
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 3, TECH_ILLEGAL = 1)
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/ward
|
||||
name = "sentry delivery grenade"
|
||||
desc = "It is set to detonate in 5 seconds. It will deploy a single thermal-optic sentry drone."
|
||||
spawner_type = /mob/living/simple_mob/mechanical/ward/monitor/crew
|
||||
deliveryamt = 1
|
||||
origin_tech = list(TECH_MATERIAL = 4, TECH_MAGNET = 3, TECH_BLUESPACE = 2)
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/spesscarp
|
||||
name = "carp delivery grenade"
|
||||
spawner_type = /mob/living/simple_mob/animal/space/carp
|
||||
deliveryamt = 5
|
||||
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4, TECH_ILLEGAL = 4)
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/spider
|
||||
name = "spider delivery grenade"
|
||||
spawner_type = /mob/living/simple_mob/animal/giant_spider/hunter
|
||||
deliveryamt = 3
|
||||
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4, TECH_ILLEGAL = 4)
|
||||
|
||||
//Sometimes you just need a sudden influx of spiders.
|
||||
/obj/item/weapon/grenade/spawnergrenade/spider/briefcase
|
||||
name = "briefcase"
|
||||
desc = "It's made of AUTHENTIC faux-leather and has a price-tag still attached. Its owner must be a real professional."
|
||||
icon_state = "briefcase"
|
||||
item_state = "briefcase"
|
||||
force = 8.0
|
||||
throw_speed = 1
|
||||
throw_range = 4
|
||||
w_class = ITEMSIZE_LARGE
|
||||
deliveryamt = 6
|
||||
/obj/item/weapon/grenade/spawnergrenade
|
||||
desc = "It is set to detonate in 5 seconds. It will unleash an unspecified anomaly into the vicinity."
|
||||
name = "delivery grenade"
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "delivery"
|
||||
item_state = "flashbang"
|
||||
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4)
|
||||
var/banglet = 0
|
||||
var/spawner_type = null // must be an object path
|
||||
var/deliveryamt = 1 // amount of type to deliver
|
||||
|
||||
// Detonate now just handles the two loops that query for people in lockers and people who can see it.
|
||||
/obj/item/weapon/grenade/spawnergrenade/detonate()
|
||||
|
||||
if(spawner_type && deliveryamt)
|
||||
// Make a quick flash
|
||||
var/turf/T = get_turf(src)
|
||||
playsound(src, 'sound/effects/phasein.ogg', 100, 1)
|
||||
for(var/mob/living/carbon/human/M in viewers(T, null))
|
||||
if(M:eyecheck() <= 0)
|
||||
M.flash_eyes()
|
||||
|
||||
// Spawn some hostile syndicate critters
|
||||
for(var/i=1, i<=deliveryamt, i++)
|
||||
var/atom/movable/x = new spawner_type(T)
|
||||
if(prob(50))
|
||||
for(var/j = 1, j <= rand(1, 3), j++)
|
||||
step(x, pick(NORTH,SOUTH,EAST,WEST))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks
|
||||
name = "manhack delivery grenade"
|
||||
spawner_type = /mob/living/simple_mob/mechanical/viscerator
|
||||
deliveryamt = 5
|
||||
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4, TECH_ILLEGAL = 4)
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks/mercenary
|
||||
spawner_type = /mob/living/simple_mob/mechanical/viscerator/mercenary
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks/raider
|
||||
spawner_type = /mob/living/simple_mob/mechanical/viscerator/raider
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/manhacks/station
|
||||
desc = "It is set to detonate in 5 seconds. It will deploy three weaponized survey drones."
|
||||
deliveryamt = 3
|
||||
spawner_type = /mob/living/simple_mob/mechanical/viscerator/station
|
||||
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 3, TECH_ILLEGAL = 1)
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/ward
|
||||
name = "sentry delivery grenade"
|
||||
desc = "It is set to detonate in 5 seconds. It will deploy a single thermal-optic sentry drone."
|
||||
spawner_type = /mob/living/simple_mob/mechanical/ward/monitor/crew
|
||||
deliveryamt = 1
|
||||
origin_tech = list(TECH_MATERIAL = 4, TECH_MAGNET = 3, TECH_BLUESPACE = 2)
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/spesscarp
|
||||
name = "carp delivery grenade"
|
||||
spawner_type = /mob/living/simple_mob/animal/space/carp
|
||||
deliveryamt = 5
|
||||
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4, TECH_ILLEGAL = 4)
|
||||
|
||||
/obj/item/weapon/grenade/spawnergrenade/spider
|
||||
name = "spider delivery grenade"
|
||||
spawner_type = /mob/living/simple_mob/animal/giant_spider/hunter
|
||||
deliveryamt = 3
|
||||
origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 4, TECH_ILLEGAL = 4)
|
||||
|
||||
//Sometimes you just need a sudden influx of spiders.
|
||||
/obj/item/weapon/grenade/spawnergrenade/spider/briefcase
|
||||
name = "briefcase"
|
||||
desc = "It's made of AUTHENTIC faux-leather and has a price-tag still attached. Its owner must be a real professional."
|
||||
icon_state = "briefcase"
|
||||
item_state = "briefcase"
|
||||
force = 8.0
|
||||
throw_speed = 1
|
||||
throw_range = 4
|
||||
w_class = ITEMSIZE_LARGE
|
||||
deliveryamt = 6
|
||||
|
||||
@@ -1,337 +1,337 @@
|
||||
/obj/item/weapon/handcuffs
|
||||
name = "handcuffs"
|
||||
desc = "Use this to keep prisoners in line."
|
||||
gender = PLURAL
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "handcuff"
|
||||
slot_flags = SLOT_BELT
|
||||
throwforce = 5
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throw_speed = 2
|
||||
throw_range = 5
|
||||
origin_tech = list(TECH_MATERIAL = 1)
|
||||
matter = list(MAT_STEEL = 500)
|
||||
drop_sound = 'sound/items/drop/accessory.ogg'
|
||||
pickup_sound = 'sound/items/pickup/accessory.ogg'
|
||||
var/elastic
|
||||
var/dispenser = 0
|
||||
var/breakouttime = 1200 //Deciseconds = 120s = 2 minutes
|
||||
var/cuff_sound = 'sound/weapons/handcuffs.ogg'
|
||||
var/cuff_type = "handcuffs"
|
||||
var/use_time = 30
|
||||
sprite_sheets = list(SPECIES_TESHARI = 'icons/mob/species/teshari/handcuffs.dmi')
|
||||
|
||||
/obj/item/weapon/handcuffs/get_worn_icon_state(var/slot_name)
|
||||
if(slot_name == slot_handcuffed_str)
|
||||
return "handcuff1" //Simple
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/handcuffs/attack(var/mob/living/carbon/C, var/mob/living/user)
|
||||
|
||||
if(!user.IsAdvancedToolUser())
|
||||
return
|
||||
|
||||
if ((CLUMSY in user.mutations) && prob(50))
|
||||
to_chat(user, "<span class='warning'>Uh ... how do those things work?!</span>")
|
||||
place_handcuffs(user, user)
|
||||
return
|
||||
|
||||
if(!C.handcuffed)
|
||||
if (C == user)
|
||||
place_handcuffs(user, user)
|
||||
return
|
||||
|
||||
//check for an aggressive grab (or robutts)
|
||||
if(can_place(C, user))
|
||||
place_handcuffs(C, user)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>You need to have a firm grip on [C] before you can put \the [src] on!</span>")
|
||||
|
||||
/obj/item/weapon/handcuffs/proc/can_place(var/mob/target, var/mob/user)
|
||||
if(user == target)
|
||||
return 1
|
||||
if(istype(user, /mob/living/silicon/robot))
|
||||
if(user.Adjacent(target))
|
||||
return 1
|
||||
else
|
||||
for(var/obj/item/weapon/grab/G in target.grabbed_by)
|
||||
if(G.loc == user && G.state >= GRAB_AGGRESSIVE)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/handcuffs/proc/place_handcuffs(var/mob/living/carbon/target, var/mob/user)
|
||||
playsound(src, cuff_sound, 30, 1, -2)
|
||||
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(!istype(H))
|
||||
return 0
|
||||
|
||||
if (!H.has_organ_for_slot(slot_handcuffed))
|
||||
to_chat(user, "<span class='danger'>\The [H] needs at least two wrists before you can cuff them together!</span>")
|
||||
return 0
|
||||
|
||||
if(istype(H.gloves,/obj/item/clothing/gloves/gauntlets/rig) && !elastic) // Can't cuff someone who's in a deployed hardsuit.
|
||||
to_chat(user, "<span class='danger'>\The [src] won't fit around \the [H.gloves]!</span>")
|
||||
return 0
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] is attempting to put [cuff_type] on \the [H]!</span>")
|
||||
|
||||
if(!do_after(user,use_time))
|
||||
return 0
|
||||
|
||||
if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime
|
||||
return 0
|
||||
|
||||
add_attack_logs(user,H,"Handcuffed (attempt)")
|
||||
feedback_add_details("handcuffs","H")
|
||||
|
||||
user.setClickCooldown(user.get_attack_speed(src))
|
||||
user.do_attack_animation(H)
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] has put [cuff_type] on \the [H]!</span>")
|
||||
|
||||
// Apply cuffs.
|
||||
var/obj/item/weapon/handcuffs/cuffs = src
|
||||
if(dispenser)
|
||||
cuffs = new(get_turf(user))
|
||||
else
|
||||
user.drop_from_inventory(cuffs)
|
||||
cuffs.loc = target
|
||||
target.handcuffed = cuffs
|
||||
target.update_handcuffed()
|
||||
target.drop_r_hand()
|
||||
target.drop_l_hand()
|
||||
target.stop_pulling()
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/handcuffs/equipped(var/mob/living/user,var/slot)
|
||||
. = ..()
|
||||
if(slot == slot_handcuffed)
|
||||
user.drop_r_hand()
|
||||
user.drop_l_hand()
|
||||
user.stop_pulling()
|
||||
|
||||
var/last_chew = 0
|
||||
/mob/living/carbon/human/RestrainedClickOn(var/atom/A)
|
||||
if (A != src) return ..()
|
||||
if (last_chew + 26 > world.time) return
|
||||
|
||||
var/mob/living/carbon/human/H = A
|
||||
if (!H.handcuffed) return
|
||||
if (H.a_intent != I_HURT) return
|
||||
if (H.zone_sel.selecting != O_MOUTH) return
|
||||
if (H.wear_mask) return
|
||||
if (istype(H.wear_suit, /obj/item/clothing/suit/straight_jacket)) return
|
||||
|
||||
var/obj/item/organ/external/O = H.organs_by_name[(H.hand ? BP_L_HAND : BP_R_HAND)]
|
||||
if (!O) return
|
||||
|
||||
var/datum/gender/T = gender_datums[H.get_visible_gender()]
|
||||
|
||||
var/s = "<span class='warning'>[H.name] chews on [T.his] [O.name]!</span>"
|
||||
H.visible_message(s, "<span class='warning'>You chew on your [O.name]!</span>")
|
||||
add_attack_logs(H,H,"chewed own [O.name]")
|
||||
|
||||
if(O.take_damage(3,0,1,1,"teeth marks"))
|
||||
H:UpdateDamageIcon()
|
||||
|
||||
last_chew = world.time
|
||||
|
||||
/obj/item/weapon/handcuffs/fuzzy
|
||||
name = "fuzzy cuffs"
|
||||
icon_state = "fuzzycuff"
|
||||
breakouttime = 100 //VOREstation edit
|
||||
desc = "Use this to keep... 'prisoners' in line."
|
||||
|
||||
/obj/item/weapon/handcuffs/cable
|
||||
name = "cable restraints"
|
||||
desc = "Looks like some cables tied together. Could be used to tie something up."
|
||||
icon_state = "cuff_white"
|
||||
breakouttime = 300 //Deciseconds = 30s
|
||||
cuff_sound = 'sound/weapons/cablecuff.ogg'
|
||||
cuff_type = "cable restraints"
|
||||
elastic = 1
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/red
|
||||
color = "#DD0000"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/yellow
|
||||
color = "#DDDD00"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/blue
|
||||
color = "#0000DD"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/green
|
||||
color = "#00DD00"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/pink
|
||||
color = "#DD00DD"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/orange
|
||||
color = "#DD8800"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/cyan
|
||||
color = "#00DDDD"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/white
|
||||
color = "#FFFFFF"
|
||||
|
||||
/obj/item/weapon/handcuffs/cyborg
|
||||
dispenser = 1
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/tape
|
||||
name = "tape restraints"
|
||||
desc = "DIY!"
|
||||
icon_state = "tape_cross"
|
||||
item_state = null
|
||||
icon = 'icons/obj/bureaucracy.dmi'
|
||||
breakouttime = 200
|
||||
cuff_type = "duct tape"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/tape/cyborg
|
||||
dispenser = TRUE
|
||||
|
||||
//Legcuffs. Not /really/ handcuffs, but its close enough.
|
||||
/obj/item/weapon/handcuffs/legcuffs
|
||||
name = "legcuffs"
|
||||
desc = "Use this to keep prisoners in line."
|
||||
gender = PLURAL
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "legcuff"
|
||||
throwforce = 0
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
origin_tech = list(TECH_MATERIAL = 1)
|
||||
breakouttime = 300 //Deciseconds = 30s = 0.5 minute
|
||||
cuff_type = "legcuffs"
|
||||
sprite_sheets = list(SPECIES_TESHARI = 'icons/mob/species/teshari/handcuffs.dmi')
|
||||
elastic = 0
|
||||
cuff_sound = 'sound/weapons/handcuffs.ogg' //This shold work for now.
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/get_worn_icon_state(var/slot_name)
|
||||
if(slot_name == slot_legcuffed_str)
|
||||
return "legcuff1"
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/attack(var/mob/living/carbon/C, var/mob/living/user)
|
||||
if(!user.IsAdvancedToolUser())
|
||||
return
|
||||
|
||||
if ((CLUMSY in user.mutations) && prob(50))
|
||||
to_chat(user, "<span class='warning'>Uh ... how do those things work?!</span>")
|
||||
place_legcuffs(user, user)
|
||||
return
|
||||
|
||||
if(!C.legcuffed)
|
||||
if (C == user)
|
||||
place_legcuffs(user, user)
|
||||
return
|
||||
|
||||
//check for an aggressive grab (or robutts)
|
||||
if(can_place(C, user))
|
||||
place_legcuffs(C, user)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>You need to have a firm grip on [C] before you can put \the [src] on!</span>")
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/proc/place_legcuffs(var/mob/living/carbon/target, var/mob/user)
|
||||
playsound(src, cuff_sound, 30, 1, -2)
|
||||
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(!istype(H))
|
||||
return 0
|
||||
|
||||
if (!H.has_organ_for_slot(slot_legcuffed))
|
||||
to_chat(user, "<span class='danger'>\The [H] needs at least two ankles before you can cuff them together!</span>")
|
||||
return 0
|
||||
|
||||
if(istype(H.shoes,/obj/item/clothing/shoes/magboots/rig) && !elastic) // Can't cuff someone who's in a deployed hardsuit.
|
||||
to_chat(user, "<span class='danger'>\The [src] won't fit around \the [H.shoes]!</span>")
|
||||
return 0
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] is attempting to put [cuff_type] on \the [H]!</span>")
|
||||
|
||||
if(!do_after(user,use_time))
|
||||
return 0
|
||||
|
||||
if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime
|
||||
return 0
|
||||
|
||||
add_attack_logs(user,H,"Legcuffed (attempt)")
|
||||
feedback_add_details("legcuffs","H")
|
||||
|
||||
user.setClickCooldown(user.get_attack_speed(src))
|
||||
user.do_attack_animation(H)
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] has put [cuff_type] on \the [H]!</span>")
|
||||
|
||||
// Apply cuffs.
|
||||
var/obj/item/weapon/handcuffs/legcuffs/lcuffs = src
|
||||
if(dispenser)
|
||||
lcuffs = new(get_turf(user))
|
||||
else
|
||||
user.drop_from_inventory(lcuffs)
|
||||
lcuffs.loc = target
|
||||
target.legcuffed = lcuffs
|
||||
target.update_inv_legcuffed()
|
||||
if(target.m_intent != "walk")
|
||||
target.m_intent = "walk"
|
||||
if(target.hud_used && user.hud_used.move_intent)
|
||||
target.hud_used.move_intent.icon_state = "walking"
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/equipped(var/mob/living/user,var/slot)
|
||||
. = ..()
|
||||
if(slot == slot_legcuffed)
|
||||
if(user.m_intent != "walk")
|
||||
user.m_intent = "walk"
|
||||
if(user.hud_used && user.hud_used.move_intent)
|
||||
user.hud_used.move_intent.icon_state = "walking"
|
||||
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/bola
|
||||
name = "bola"
|
||||
desc = "Keeps prey in line."
|
||||
elastic = 1
|
||||
use_time = 0
|
||||
breakouttime = 30
|
||||
cuff_sound = 'sound/weapons/towelwipe.ogg' //Is there anything this sound can't do?
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/bola/can_place(var/mob/target, var/mob/user)
|
||||
if(user) //A ranged legcuff, until proper implementation as items it remains a projectile-only thing.
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/bola/dropped()
|
||||
visible_message("<b>\The [src]</b> falls apart!")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/bola/place_legcuffs(var/mob/living/carbon/target, var/mob/user)
|
||||
playsound(src, cuff_sound, 30, 1, -2)
|
||||
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(!istype(H))
|
||||
src.dropped()
|
||||
return 0
|
||||
|
||||
if(!H.has_organ_for_slot(slot_legcuffed))
|
||||
H.visible_message("<b>\The [src]</b> slams into [H], but slides off!")
|
||||
src.dropped()
|
||||
return 0
|
||||
|
||||
H.visible_message("<span class='danger'>\The [H] has been snared by \the [src]!</span>")
|
||||
|
||||
// Apply cuffs.
|
||||
var/obj/item/weapon/handcuffs/legcuffs/lcuffs = src
|
||||
lcuffs.loc = target
|
||||
target.legcuffed = lcuffs
|
||||
target.update_inv_legcuffed()
|
||||
if(target.m_intent != "walk")
|
||||
target.m_intent = "walk"
|
||||
if(target.hud_used && user.hud_used.move_intent)
|
||||
target.hud_used.move_intent.icon_state = "walking"
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/plantfiber
|
||||
name = "rope bindings"
|
||||
desc = "A length of rope fashioned to hold someone's hands together."
|
||||
color = "#7e6442"
|
||||
/obj/item/weapon/handcuffs
|
||||
name = "handcuffs"
|
||||
desc = "Use this to keep prisoners in line."
|
||||
gender = PLURAL
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "handcuff"
|
||||
slot_flags = SLOT_BELT
|
||||
throwforce = 5
|
||||
w_class = ITEMSIZE_SMALL
|
||||
throw_speed = 2
|
||||
throw_range = 5
|
||||
origin_tech = list(TECH_MATERIAL = 1)
|
||||
matter = list(MAT_STEEL = 500)
|
||||
drop_sound = 'sound/items/drop/accessory.ogg'
|
||||
pickup_sound = 'sound/items/pickup/accessory.ogg'
|
||||
var/elastic
|
||||
var/dispenser = 0
|
||||
var/breakouttime = 1200 //Deciseconds = 120s = 2 minutes
|
||||
var/cuff_sound = 'sound/weapons/handcuffs.ogg'
|
||||
var/cuff_type = "handcuffs"
|
||||
var/use_time = 30
|
||||
sprite_sheets = list(SPECIES_TESHARI = 'icons/mob/species/teshari/handcuffs.dmi')
|
||||
|
||||
/obj/item/weapon/handcuffs/get_worn_icon_state(var/slot_name)
|
||||
if(slot_name == slot_handcuffed_str)
|
||||
return "handcuff1" //Simple
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/handcuffs/attack(var/mob/living/carbon/C, var/mob/living/user)
|
||||
|
||||
if(!user.IsAdvancedToolUser())
|
||||
return
|
||||
|
||||
if ((CLUMSY in user.mutations) && prob(50))
|
||||
to_chat(user, "<span class='warning'>Uh ... how do those things work?!</span>")
|
||||
place_handcuffs(user, user)
|
||||
return
|
||||
|
||||
if(!C.handcuffed)
|
||||
if (C == user)
|
||||
place_handcuffs(user, user)
|
||||
return
|
||||
|
||||
//check for an aggressive grab (or robutts)
|
||||
if(can_place(C, user))
|
||||
place_handcuffs(C, user)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>You need to have a firm grip on [C] before you can put \the [src] on!</span>")
|
||||
|
||||
/obj/item/weapon/handcuffs/proc/can_place(var/mob/target, var/mob/user)
|
||||
if(user == target)
|
||||
return 1
|
||||
if(istype(user, /mob/living/silicon/robot))
|
||||
if(user.Adjacent(target))
|
||||
return 1
|
||||
else
|
||||
for(var/obj/item/weapon/grab/G in target.grabbed_by)
|
||||
if(G.loc == user && G.state >= GRAB_AGGRESSIVE)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/handcuffs/proc/place_handcuffs(var/mob/living/carbon/target, var/mob/user)
|
||||
playsound(src, cuff_sound, 30, 1, -2)
|
||||
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(!istype(H))
|
||||
return 0
|
||||
|
||||
if (!H.has_organ_for_slot(slot_handcuffed))
|
||||
to_chat(user, "<span class='danger'>\The [H] needs at least two wrists before you can cuff them together!</span>")
|
||||
return 0
|
||||
|
||||
if(istype(H.gloves,/obj/item/clothing/gloves/gauntlets/rig) && !elastic) // Can't cuff someone who's in a deployed hardsuit.
|
||||
to_chat(user, "<span class='danger'>\The [src] won't fit around \the [H.gloves]!</span>")
|
||||
return 0
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] is attempting to put [cuff_type] on \the [H]!</span>")
|
||||
|
||||
if(!do_after(user,use_time))
|
||||
return 0
|
||||
|
||||
if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime
|
||||
return 0
|
||||
|
||||
add_attack_logs(user,H,"Handcuffed (attempt)")
|
||||
feedback_add_details("handcuffs","H")
|
||||
|
||||
user.setClickCooldown(user.get_attack_speed(src))
|
||||
user.do_attack_animation(H)
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] has put [cuff_type] on \the [H]!</span>")
|
||||
|
||||
// Apply cuffs.
|
||||
var/obj/item/weapon/handcuffs/cuffs = src
|
||||
if(dispenser)
|
||||
cuffs = new(get_turf(user))
|
||||
else
|
||||
user.drop_from_inventory(cuffs)
|
||||
cuffs.loc = target
|
||||
target.handcuffed = cuffs
|
||||
target.update_handcuffed()
|
||||
target.drop_r_hand()
|
||||
target.drop_l_hand()
|
||||
target.stop_pulling()
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/handcuffs/equipped(var/mob/living/user,var/slot)
|
||||
. = ..()
|
||||
if(slot == slot_handcuffed)
|
||||
user.drop_r_hand()
|
||||
user.drop_l_hand()
|
||||
user.stop_pulling()
|
||||
|
||||
var/last_chew = 0
|
||||
/mob/living/carbon/human/RestrainedClickOn(var/atom/A)
|
||||
if (A != src) return ..()
|
||||
if (last_chew + 26 > world.time) return
|
||||
|
||||
var/mob/living/carbon/human/H = A
|
||||
if (!H.handcuffed) return
|
||||
if (H.a_intent != I_HURT) return
|
||||
if (H.zone_sel.selecting != O_MOUTH) return
|
||||
if (H.wear_mask) return
|
||||
if (istype(H.wear_suit, /obj/item/clothing/suit/straight_jacket)) return
|
||||
|
||||
var/obj/item/organ/external/O = H.organs_by_name[(H.hand ? BP_L_HAND : BP_R_HAND)]
|
||||
if (!O) return
|
||||
|
||||
var/datum/gender/T = gender_datums[H.get_visible_gender()]
|
||||
|
||||
var/s = "<span class='warning'>[H.name] chews on [T.his] [O.name]!</span>"
|
||||
H.visible_message(s, "<span class='warning'>You chew on your [O.name]!</span>")
|
||||
add_attack_logs(H,H,"chewed own [O.name]")
|
||||
|
||||
if(O.take_damage(3,0,1,1,"teeth marks"))
|
||||
H:UpdateDamageIcon()
|
||||
|
||||
last_chew = world.time
|
||||
|
||||
/obj/item/weapon/handcuffs/fuzzy
|
||||
name = "fuzzy cuffs"
|
||||
icon_state = "fuzzycuff"
|
||||
breakouttime = 100 //VOREstation edit
|
||||
desc = "Use this to keep... 'prisoners' in line."
|
||||
|
||||
/obj/item/weapon/handcuffs/cable
|
||||
name = "cable restraints"
|
||||
desc = "Looks like some cables tied together. Could be used to tie something up."
|
||||
icon_state = "cuff_white"
|
||||
breakouttime = 300 //Deciseconds = 30s
|
||||
cuff_sound = 'sound/weapons/cablecuff.ogg'
|
||||
cuff_type = "cable restraints"
|
||||
elastic = 1
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/red
|
||||
color = "#DD0000"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/yellow
|
||||
color = "#DDDD00"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/blue
|
||||
color = "#0000DD"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/green
|
||||
color = "#00DD00"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/pink
|
||||
color = "#DD00DD"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/orange
|
||||
color = "#DD8800"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/cyan
|
||||
color = "#00DDDD"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/white
|
||||
color = "#FFFFFF"
|
||||
|
||||
/obj/item/weapon/handcuffs/cyborg
|
||||
dispenser = 1
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/tape
|
||||
name = "tape restraints"
|
||||
desc = "DIY!"
|
||||
icon_state = "tape_cross"
|
||||
item_state = null
|
||||
icon = 'icons/obj/bureaucracy.dmi'
|
||||
breakouttime = 200
|
||||
cuff_type = "duct tape"
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/tape/cyborg
|
||||
dispenser = TRUE
|
||||
|
||||
//Legcuffs. Not /really/ handcuffs, but its close enough.
|
||||
/obj/item/weapon/handcuffs/legcuffs
|
||||
name = "legcuffs"
|
||||
desc = "Use this to keep prisoners in line."
|
||||
gender = PLURAL
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "legcuff"
|
||||
throwforce = 0
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
origin_tech = list(TECH_MATERIAL = 1)
|
||||
breakouttime = 300 //Deciseconds = 30s = 0.5 minute
|
||||
cuff_type = "legcuffs"
|
||||
sprite_sheets = list(SPECIES_TESHARI = 'icons/mob/species/teshari/handcuffs.dmi')
|
||||
elastic = 0
|
||||
cuff_sound = 'sound/weapons/handcuffs.ogg' //This shold work for now.
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/get_worn_icon_state(var/slot_name)
|
||||
if(slot_name == slot_legcuffed_str)
|
||||
return "legcuff1"
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/attack(var/mob/living/carbon/C, var/mob/living/user)
|
||||
if(!user.IsAdvancedToolUser())
|
||||
return
|
||||
|
||||
if ((CLUMSY in user.mutations) && prob(50))
|
||||
to_chat(user, "<span class='warning'>Uh ... how do those things work?!</span>")
|
||||
place_legcuffs(user, user)
|
||||
return
|
||||
|
||||
if(!C.legcuffed)
|
||||
if (C == user)
|
||||
place_legcuffs(user, user)
|
||||
return
|
||||
|
||||
//check for an aggressive grab (or robutts)
|
||||
if(can_place(C, user))
|
||||
place_legcuffs(C, user)
|
||||
else
|
||||
to_chat(user, "<span class='danger'>You need to have a firm grip on [C] before you can put \the [src] on!</span>")
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/proc/place_legcuffs(var/mob/living/carbon/target, var/mob/user)
|
||||
playsound(src, cuff_sound, 30, 1, -2)
|
||||
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(!istype(H))
|
||||
return 0
|
||||
|
||||
if (!H.has_organ_for_slot(slot_legcuffed))
|
||||
to_chat(user, "<span class='danger'>\The [H] needs at least two ankles before you can cuff them together!</span>")
|
||||
return 0
|
||||
|
||||
if(istype(H.shoes,/obj/item/clothing/shoes/magboots/rig) && !elastic) // Can't cuff someone who's in a deployed hardsuit.
|
||||
to_chat(user, "<span class='danger'>\The [src] won't fit around \the [H.shoes]!</span>")
|
||||
return 0
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] is attempting to put [cuff_type] on \the [H]!</span>")
|
||||
|
||||
if(!do_after(user,use_time))
|
||||
return 0
|
||||
|
||||
if(!can_place(target, user)) //victim may have resisted out of the grab in the meantime
|
||||
return 0
|
||||
|
||||
add_attack_logs(user,H,"Legcuffed (attempt)")
|
||||
feedback_add_details("legcuffs","H")
|
||||
|
||||
user.setClickCooldown(user.get_attack_speed(src))
|
||||
user.do_attack_animation(H)
|
||||
|
||||
user.visible_message("<span class='danger'>\The [user] has put [cuff_type] on \the [H]!</span>")
|
||||
|
||||
// Apply cuffs.
|
||||
var/obj/item/weapon/handcuffs/legcuffs/lcuffs = src
|
||||
if(dispenser)
|
||||
lcuffs = new(get_turf(user))
|
||||
else
|
||||
user.drop_from_inventory(lcuffs)
|
||||
lcuffs.loc = target
|
||||
target.legcuffed = lcuffs
|
||||
target.update_inv_legcuffed()
|
||||
if(target.m_intent != "walk")
|
||||
target.m_intent = "walk"
|
||||
if(target.hud_used && user.hud_used.move_intent)
|
||||
target.hud_used.move_intent.icon_state = "walking"
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/equipped(var/mob/living/user,var/slot)
|
||||
. = ..()
|
||||
if(slot == slot_legcuffed)
|
||||
if(user.m_intent != "walk")
|
||||
user.m_intent = "walk"
|
||||
if(user.hud_used && user.hud_used.move_intent)
|
||||
user.hud_used.move_intent.icon_state = "walking"
|
||||
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/bola
|
||||
name = "bola"
|
||||
desc = "Keeps prey in line."
|
||||
elastic = 1
|
||||
use_time = 0
|
||||
breakouttime = 30
|
||||
cuff_sound = 'sound/weapons/towelwipe.ogg' //Is there anything this sound can't do?
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/bola/can_place(var/mob/target, var/mob/user)
|
||||
if(user) //A ranged legcuff, until proper implementation as items it remains a projectile-only thing.
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/bola/dropped()
|
||||
visible_message("<b>\The [src]</b> falls apart!")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/handcuffs/legcuffs/bola/place_legcuffs(var/mob/living/carbon/target, var/mob/user)
|
||||
playsound(src, cuff_sound, 30, 1, -2)
|
||||
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(!istype(H))
|
||||
src.dropped()
|
||||
return 0
|
||||
|
||||
if(!H.has_organ_for_slot(slot_legcuffed))
|
||||
H.visible_message("<b>\The [src]</b> slams into [H], but slides off!")
|
||||
src.dropped()
|
||||
return 0
|
||||
|
||||
H.visible_message("<span class='danger'>\The [H] has been snared by \the [src]!</span>")
|
||||
|
||||
// Apply cuffs.
|
||||
var/obj/item/weapon/handcuffs/legcuffs/lcuffs = src
|
||||
lcuffs.loc = target
|
||||
target.legcuffed = lcuffs
|
||||
target.update_inv_legcuffed()
|
||||
if(target.m_intent != "walk")
|
||||
target.m_intent = "walk"
|
||||
if(target.hud_used && user.hud_used.move_intent)
|
||||
target.hud_used.move_intent.icon_state = "walking"
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/handcuffs/cable/plantfiber
|
||||
name = "rope bindings"
|
||||
desc = "A length of rope fashioned to hold someone's hands together."
|
||||
color = "#7e6442"
|
||||
|
||||
@@ -1,113 +1,113 @@
|
||||
/*
|
||||
* SeedBag
|
||||
*/
|
||||
//uncomment when this is updated to match storage update
|
||||
/*
|
||||
/obj/item/weapon/seedbag
|
||||
icon = 'icons/obj/hydroponics_machines.dmi'
|
||||
icon_state = "seedbag"
|
||||
name = "Seed Bag"
|
||||
desc = "A small satchel made for organizing seeds."
|
||||
var/mode = 1; //0 = pick one at a time, 1 = pick all on tile
|
||||
var/capacity = 500; //the number of seeds it can carry.
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = ITEMSIZE_TINY
|
||||
var/list/item_quants = list()
|
||||
|
||||
/obj/item/weapon/seedbag/attack_self(mob/user as mob)
|
||||
user.machine = src
|
||||
interact(user)
|
||||
|
||||
/obj/item/weapon/seedbag/verb/toggle_mode()
|
||||
set name = "Switch Bagging Method"
|
||||
set category = "Object"
|
||||
|
||||
mode = !mode
|
||||
switch (mode)
|
||||
if(1)
|
||||
to_chat(usr, "The bag now picks up all seeds in a tile at once.")
|
||||
if(0)
|
||||
to_chat(usr, "The bag now picks up one seed pouch at a time.")
|
||||
|
||||
/obj/item/seeds/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
..()
|
||||
if (istype(O, /obj/item/weapon/seedbag))
|
||||
var/obj/item/weapon/seedbag/S = O
|
||||
if (S.mode == 1)
|
||||
for (var/obj/item/seeds/G in locate(src.x,src.y,src.z))
|
||||
if (S.contents.len < S.capacity)
|
||||
S.contents += G;
|
||||
if(S.item_quants[G.name])
|
||||
S.item_quants[G.name]++
|
||||
else
|
||||
S.item_quants[G.name] = 1
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The seed bag is full.</span>")
|
||||
S.updateUsrDialog()
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You pick up all the seeds.</span>")
|
||||
else
|
||||
if (S.contents.len < S.capacity)
|
||||
S.contents += src;
|
||||
if(S.item_quants[name])
|
||||
S.item_quants[name]++
|
||||
else
|
||||
S.item_quants[name] = 1
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The seed bag is full.</span>")
|
||||
S.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/item/weapon/seedbag/interact(mob/user as mob)
|
||||
|
||||
var/dat = "<TT><b>Select an item:</b><br>"
|
||||
|
||||
if (contents.len == 0)
|
||||
dat += "<font color = 'red'>No seeds loaded!</font>"
|
||||
else
|
||||
for (var/O in item_quants)
|
||||
if(item_quants[O] > 0)
|
||||
var/N = item_quants[O]
|
||||
dat += "<FONT color = 'blue'><B>[capitalize(O)]</B>:"
|
||||
dat += " [N] </font>"
|
||||
dat += "<a href='byond://?src=\ref[src];vend=[O]'>Vend</A>"
|
||||
dat += "<br>"
|
||||
|
||||
dat += "<br><a href='byond://?src=\ref[src];unload=1'>Unload All</A>"
|
||||
dat += "</TT>"
|
||||
user << browse("<HEAD><TITLE>Seedbag Supplies</TITLE></HEAD><TT>[dat]</TT>", "window=seedbag")
|
||||
onclose(user, "seedbag")
|
||||
return
|
||||
|
||||
/obj/item/weapon/seedbag/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
usr.machine = src
|
||||
if ( href_list["vend"] )
|
||||
var/N = href_list["vend"]
|
||||
|
||||
if(item_quants[N] <= 0) // Sanity check, there are probably ways to press the button when it shouldn't be possible.
|
||||
return
|
||||
|
||||
item_quants[N] -= 1
|
||||
for(var/obj/O in contents)
|
||||
if(O.name == N)
|
||||
O.loc = get_turf(src)
|
||||
usr.put_in_hands(O)
|
||||
break
|
||||
|
||||
else if ( href_list["unload"] )
|
||||
item_quants.Cut()
|
||||
for(var/obj/O in contents )
|
||||
O.loc = get_turf(src)
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/item/weapon/seedbag/updateUsrDialog()
|
||||
var/list/nearby = range(1, src)
|
||||
for(var/mob/M in nearby)
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_self(M)
|
||||
*/
|
||||
/*
|
||||
* SeedBag
|
||||
*/
|
||||
//uncomment when this is updated to match storage update
|
||||
/*
|
||||
/obj/item/weapon/seedbag
|
||||
icon = 'icons/obj/hydroponics_machines.dmi'
|
||||
icon_state = "seedbag"
|
||||
name = "Seed Bag"
|
||||
desc = "A small satchel made for organizing seeds."
|
||||
var/mode = 1; //0 = pick one at a time, 1 = pick all on tile
|
||||
var/capacity = 500; //the number of seeds it can carry.
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = ITEMSIZE_TINY
|
||||
var/list/item_quants = list()
|
||||
|
||||
/obj/item/weapon/seedbag/attack_self(mob/user as mob)
|
||||
user.machine = src
|
||||
interact(user)
|
||||
|
||||
/obj/item/weapon/seedbag/verb/toggle_mode()
|
||||
set name = "Switch Bagging Method"
|
||||
set category = "Object"
|
||||
|
||||
mode = !mode
|
||||
switch (mode)
|
||||
if(1)
|
||||
to_chat(usr, "The bag now picks up all seeds in a tile at once.")
|
||||
if(0)
|
||||
to_chat(usr, "The bag now picks up one seed pouch at a time.")
|
||||
|
||||
/obj/item/seeds/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
..()
|
||||
if (istype(O, /obj/item/weapon/seedbag))
|
||||
var/obj/item/weapon/seedbag/S = O
|
||||
if (S.mode == 1)
|
||||
for (var/obj/item/seeds/G in locate(src.x,src.y,src.z))
|
||||
if (S.contents.len < S.capacity)
|
||||
S.contents += G;
|
||||
if(S.item_quants[G.name])
|
||||
S.item_quants[G.name]++
|
||||
else
|
||||
S.item_quants[G.name] = 1
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The seed bag is full.</span>")
|
||||
S.updateUsrDialog()
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You pick up all the seeds.</span>")
|
||||
else
|
||||
if (S.contents.len < S.capacity)
|
||||
S.contents += src;
|
||||
if(S.item_quants[name])
|
||||
S.item_quants[name]++
|
||||
else
|
||||
S.item_quants[name] = 1
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The seed bag is full.</span>")
|
||||
S.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/item/weapon/seedbag/interact(mob/user as mob)
|
||||
|
||||
var/dat = "<TT><b>Select an item:</b><br>"
|
||||
|
||||
if (contents.len == 0)
|
||||
dat += "<font color = 'red'>No seeds loaded!</font>"
|
||||
else
|
||||
for (var/O in item_quants)
|
||||
if(item_quants[O] > 0)
|
||||
var/N = item_quants[O]
|
||||
dat += "<FONT color = 'blue'><B>[capitalize(O)]</B>:"
|
||||
dat += " [N] </font>"
|
||||
dat += "<a href='byond://?src=\ref[src];vend=[O]'>Vend</A>"
|
||||
dat += "<br>"
|
||||
|
||||
dat += "<br><a href='byond://?src=\ref[src];unload=1'>Unload All</A>"
|
||||
dat += "</TT>"
|
||||
user << browse("<HEAD><TITLE>Seedbag Supplies</TITLE></HEAD><TT>[dat]</TT>", "window=seedbag")
|
||||
onclose(user, "seedbag")
|
||||
return
|
||||
|
||||
/obj/item/weapon/seedbag/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
usr.machine = src
|
||||
if ( href_list["vend"] )
|
||||
var/N = href_list["vend"]
|
||||
|
||||
if(item_quants[N] <= 0) // Sanity check, there are probably ways to press the button when it shouldn't be possible.
|
||||
return
|
||||
|
||||
item_quants[N] -= 1
|
||||
for(var/obj/O in contents)
|
||||
if(O.name == N)
|
||||
O.loc = get_turf(src)
|
||||
usr.put_in_hands(O)
|
||||
break
|
||||
|
||||
else if ( href_list["unload"] )
|
||||
item_quants.Cut()
|
||||
for(var/obj/O in contents )
|
||||
O.loc = get_turf(src)
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/item/weapon/seedbag/updateUsrDialog()
|
||||
var/list/nearby = range(1, src)
|
||||
for(var/mob/M in nearby)
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_self(M)
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,311 +1,311 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
|
||||
|
||||
/obj/item/weapon/implantcase
|
||||
name = "glass case"
|
||||
desc = "A case containing an implant."
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "implantcase-0"
|
||||
item_state = "implantcase"
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_TINY
|
||||
var/obj/item/weapon/implant/imp = null
|
||||
|
||||
/obj/item/weapon/implantcase/proc/update()
|
||||
if (src.imp)
|
||||
src.icon_state = text("implantcase-[]", src.imp.implant_color)
|
||||
else
|
||||
src.icon_state = "implantcase-0"
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/attackby(obj/item/weapon/I as obj, mob/user as mob)
|
||||
..()
|
||||
if (istype(I, /obj/item/weapon/pen))
|
||||
var/t = tgui_input_text(user, "What would you like the label to be?", text("[]", src.name), null, MAX_NAME_LEN)
|
||||
if (user.get_active_hand() != I)
|
||||
return
|
||||
if((!in_range(src, usr) && src.loc != user))
|
||||
return
|
||||
t = sanitizeSafe(t, MAX_NAME_LEN)
|
||||
if(t)
|
||||
src.name = text("Glass Case - '[]'", t)
|
||||
else
|
||||
src.name = "Glass Case"
|
||||
else if(istype(I, /obj/item/weapon/reagent_containers/syringe))
|
||||
if(!src.imp) return
|
||||
if(!src.imp.allow_reagents) return
|
||||
if(src.imp.reagents.total_volume >= src.imp.reagents.maximum_volume)
|
||||
to_chat(user, "<span class='warning'>\The [src] is full.</span>")
|
||||
else
|
||||
spawn(5)
|
||||
I.reagents.trans_to_obj(src.imp, 5)
|
||||
to_chat(user, "<span class='notice'>You inject 5 units of the solution. The syringe now contains [I.reagents.total_volume] units.</span>")
|
||||
else if (istype(I, /obj/item/weapon/implanter))
|
||||
var/obj/item/weapon/implanter/M = I
|
||||
if (M.imp)
|
||||
if ((src.imp || M.imp.implanted))
|
||||
return
|
||||
M.imp.loc = src
|
||||
src.imp = M.imp
|
||||
M.imp = null
|
||||
src.update()
|
||||
M.update()
|
||||
else
|
||||
if (src.imp)
|
||||
if (M.imp)
|
||||
return
|
||||
src.imp.loc = M
|
||||
M.imp = src.imp
|
||||
src.imp = null
|
||||
update()
|
||||
M.update()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/tracking
|
||||
name = "glass case - 'tracking'"
|
||||
desc = "A case containing a tracking implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/tracking/New()
|
||||
src.imp = new /obj/item/weapon/implant/tracking( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/explosive
|
||||
name = "glass case - 'explosive'"
|
||||
desc = "A case containing an explosive implant."
|
||||
icon_state = "implantcase-r"
|
||||
|
||||
/obj/item/weapon/implantcase/explosive/New()
|
||||
src.imp = new /obj/item/weapon/implant/explosive( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/chem
|
||||
name = "glass case - 'chem'"
|
||||
desc = "A case containing a chemical implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/chem/New()
|
||||
src.imp = new /obj/item/weapon/implant/chem( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/loyalty
|
||||
name = "glass case - 'loyalty'"
|
||||
desc = "A case containing a loyalty implant."
|
||||
icon_state = "implantcase-r"
|
||||
|
||||
/obj/item/weapon/implantcase/loyalty/New()
|
||||
src.imp = new /obj/item/weapon/implant/loyalty( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/death_alarm
|
||||
name = "glass case - 'death alarm'"
|
||||
desc = "A case containing a death alarm implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/death_alarm/New()
|
||||
src.imp = new /obj/item/weapon/implant/death_alarm( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/freedom
|
||||
name = "glass case - 'freedom'"
|
||||
desc = "A case containing a freedom implant."
|
||||
icon_state = "implantcase-r"
|
||||
|
||||
/obj/item/weapon/implantcase/freedom/New()
|
||||
src.imp = new /obj/item/weapon/implant/freedom( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/adrenalin
|
||||
name = "glass case - 'adrenalin'"
|
||||
desc = "A case containing an adrenalin implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/adrenalin/New()
|
||||
src.imp = new /obj/item/weapon/implant/adrenalin( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/dexplosive
|
||||
name = "glass case - 'explosive'"
|
||||
desc = "A case containing an explosive."
|
||||
icon_state = "implantcase-r"
|
||||
|
||||
/obj/item/weapon/implantcase/dexplosive/New()
|
||||
src.imp = new /obj/item/weapon/implant/dexplosive( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/health
|
||||
name = "glass case - 'health'"
|
||||
desc = "A case containing a health tracking implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/health/New()
|
||||
src.imp = new /obj/item/weapon/implant/health( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/language
|
||||
name = "glass case - 'GalCom'"
|
||||
desc = "A case containing a GalCom language implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/language/New()
|
||||
src.imp = new /obj/item/weapon/implant/language( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/language/eal
|
||||
name = "glass case - 'EAL'"
|
||||
desc = "A case containing an Encoded Audio Language implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/language/eal/New()
|
||||
src.imp = new /obj/item/weapon/implant/language/eal( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/shades
|
||||
name = "glass case - 'Integrated Shades'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/shades/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/taser
|
||||
name = "glass case - 'Taser'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/taser/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/laser
|
||||
name = "glass case - 'Laser'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/laser/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/laser( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/dart
|
||||
name = "glass case - 'Dart'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/dart/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/dart( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/toolkit
|
||||
name = "glass case - 'Toolkit'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/toolkit/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/upperarm( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/medkit
|
||||
name = "glass case - 'Toolkit'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/medkit/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/upperarm/medkit( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/surge
|
||||
name = "glass case - 'Muscle Overclocker'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/surge/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/upperarm/surge( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/analyzer
|
||||
name = "glass case - 'Scanner'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/analyzer/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/wrist( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/sword
|
||||
name = "glass case - 'Scanner'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/sword/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/wrist/sword( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/sprinter
|
||||
name = "glass case - 'Sprinter'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/sprinter/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/pelvic( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/armblade
|
||||
name = "glass case - 'Armblade'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/armblade/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/upperarm/blade( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/handblade
|
||||
name = "glass case - 'Handblade'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/handblade/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/wrist/blade( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/restrainingbolt
|
||||
name = "glass case - 'Restraining Bolt'"
|
||||
desc = "A case containing a restraining bolt."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/restrainingbolt/New()
|
||||
src.imp = new /obj/item/weapon/implant/restrainingbolt( src )
|
||||
..()
|
||||
return
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
|
||||
|
||||
/obj/item/weapon/implantcase
|
||||
name = "glass case"
|
||||
desc = "A case containing an implant."
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "implantcase-0"
|
||||
item_state = "implantcase"
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_TINY
|
||||
var/obj/item/weapon/implant/imp = null
|
||||
|
||||
/obj/item/weapon/implantcase/proc/update()
|
||||
if (src.imp)
|
||||
src.icon_state = text("implantcase-[]", src.imp.implant_color)
|
||||
else
|
||||
src.icon_state = "implantcase-0"
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/attackby(obj/item/weapon/I as obj, mob/user as mob)
|
||||
..()
|
||||
if (istype(I, /obj/item/weapon/pen))
|
||||
var/t = tgui_input_text(user, "What would you like the label to be?", text("[]", src.name), null, MAX_NAME_LEN)
|
||||
if (user.get_active_hand() != I)
|
||||
return
|
||||
if((!in_range(src, usr) && src.loc != user))
|
||||
return
|
||||
t = sanitizeSafe(t, MAX_NAME_LEN)
|
||||
if(t)
|
||||
src.name = text("Glass Case - '[]'", t)
|
||||
else
|
||||
src.name = "Glass Case"
|
||||
else if(istype(I, /obj/item/weapon/reagent_containers/syringe))
|
||||
if(!src.imp) return
|
||||
if(!src.imp.allow_reagents) return
|
||||
if(src.imp.reagents.total_volume >= src.imp.reagents.maximum_volume)
|
||||
to_chat(user, "<span class='warning'>\The [src] is full.</span>")
|
||||
else
|
||||
spawn(5)
|
||||
I.reagents.trans_to_obj(src.imp, 5)
|
||||
to_chat(user, "<span class='notice'>You inject 5 units of the solution. The syringe now contains [I.reagents.total_volume] units.</span>")
|
||||
else if (istype(I, /obj/item/weapon/implanter))
|
||||
var/obj/item/weapon/implanter/M = I
|
||||
if (M.imp)
|
||||
if ((src.imp || M.imp.implanted))
|
||||
return
|
||||
M.imp.loc = src
|
||||
src.imp = M.imp
|
||||
M.imp = null
|
||||
src.update()
|
||||
M.update()
|
||||
else
|
||||
if (src.imp)
|
||||
if (M.imp)
|
||||
return
|
||||
src.imp.loc = M
|
||||
M.imp = src.imp
|
||||
src.imp = null
|
||||
update()
|
||||
M.update()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/tracking
|
||||
name = "glass case - 'tracking'"
|
||||
desc = "A case containing a tracking implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/tracking/New()
|
||||
src.imp = new /obj/item/weapon/implant/tracking( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/explosive
|
||||
name = "glass case - 'explosive'"
|
||||
desc = "A case containing an explosive implant."
|
||||
icon_state = "implantcase-r"
|
||||
|
||||
/obj/item/weapon/implantcase/explosive/New()
|
||||
src.imp = new /obj/item/weapon/implant/explosive( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/chem
|
||||
name = "glass case - 'chem'"
|
||||
desc = "A case containing a chemical implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/chem/New()
|
||||
src.imp = new /obj/item/weapon/implant/chem( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/loyalty
|
||||
name = "glass case - 'loyalty'"
|
||||
desc = "A case containing a loyalty implant."
|
||||
icon_state = "implantcase-r"
|
||||
|
||||
/obj/item/weapon/implantcase/loyalty/New()
|
||||
src.imp = new /obj/item/weapon/implant/loyalty( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/death_alarm
|
||||
name = "glass case - 'death alarm'"
|
||||
desc = "A case containing a death alarm implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/death_alarm/New()
|
||||
src.imp = new /obj/item/weapon/implant/death_alarm( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/freedom
|
||||
name = "glass case - 'freedom'"
|
||||
desc = "A case containing a freedom implant."
|
||||
icon_state = "implantcase-r"
|
||||
|
||||
/obj/item/weapon/implantcase/freedom/New()
|
||||
src.imp = new /obj/item/weapon/implant/freedom( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/adrenalin
|
||||
name = "glass case - 'adrenalin'"
|
||||
desc = "A case containing an adrenalin implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/adrenalin/New()
|
||||
src.imp = new /obj/item/weapon/implant/adrenalin( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/dexplosive
|
||||
name = "glass case - 'explosive'"
|
||||
desc = "A case containing an explosive."
|
||||
icon_state = "implantcase-r"
|
||||
|
||||
/obj/item/weapon/implantcase/dexplosive/New()
|
||||
src.imp = new /obj/item/weapon/implant/dexplosive( src )
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantcase/health
|
||||
name = "glass case - 'health'"
|
||||
desc = "A case containing a health tracking implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/health/New()
|
||||
src.imp = new /obj/item/weapon/implant/health( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/language
|
||||
name = "glass case - 'GalCom'"
|
||||
desc = "A case containing a GalCom language implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/language/New()
|
||||
src.imp = new /obj/item/weapon/implant/language( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/language/eal
|
||||
name = "glass case - 'EAL'"
|
||||
desc = "A case containing an Encoded Audio Language implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/language/eal/New()
|
||||
src.imp = new /obj/item/weapon/implant/language/eal( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/shades
|
||||
name = "glass case - 'Integrated Shades'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/shades/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/taser
|
||||
name = "glass case - 'Taser'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/taser/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/laser
|
||||
name = "glass case - 'Laser'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/laser/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/laser( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/dart
|
||||
name = "glass case - 'Dart'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/dart/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/dart( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/toolkit
|
||||
name = "glass case - 'Toolkit'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/toolkit/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/upperarm( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/medkit
|
||||
name = "glass case - 'Toolkit'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/medkit/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/upperarm/medkit( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/surge
|
||||
name = "glass case - 'Muscle Overclocker'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/surge/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/upperarm/surge( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/analyzer
|
||||
name = "glass case - 'Scanner'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/analyzer/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/wrist( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/sword
|
||||
name = "glass case - 'Scanner'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/sword/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/wrist/sword( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/sprinter
|
||||
name = "glass case - 'Sprinter'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/sprinter/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/pelvic( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/armblade
|
||||
name = "glass case - 'Armblade'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/armblade/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/upperarm/blade( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/handblade
|
||||
name = "glass case - 'Handblade'"
|
||||
desc = "A case containing a nanite fabricator implant."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/handblade/New()
|
||||
src.imp = new /obj/item/weapon/implant/organ/limbaugment/wrist/blade( src )
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implantcase/restrainingbolt
|
||||
name = "glass case - 'Restraining Bolt'"
|
||||
desc = "A case containing a restraining bolt."
|
||||
icon_state = "implantcase-b"
|
||||
|
||||
/obj/item/weapon/implantcase/restrainingbolt/New()
|
||||
src.imp = new /obj/item/weapon/implant/restrainingbolt( src )
|
||||
..()
|
||||
return
|
||||
|
||||
@@ -1,162 +1,162 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
|
||||
|
||||
/obj/machinery/implantchair
|
||||
name = "loyalty implanter"
|
||||
desc = "Used to implant occupants with loyalty implants."
|
||||
icon = 'icons/obj/machines/implantchair.dmi'
|
||||
icon_state = "implantchair"
|
||||
density = TRUE
|
||||
opacity = 0
|
||||
anchored = TRUE
|
||||
|
||||
var/ready = 1
|
||||
var/malfunction = 0
|
||||
var/list/obj/item/weapon/implant/loyalty/implant_list = list()
|
||||
var/max_implants = 5
|
||||
var/injection_cooldown = 600
|
||||
var/replenish_cooldown = 6000
|
||||
var/replenishing = 0
|
||||
var/mob/living/carbon/occupant = null
|
||||
var/injecting = 0
|
||||
|
||||
/obj/machinery/implantchair/New()
|
||||
..()
|
||||
add_implants()
|
||||
|
||||
|
||||
/obj/machinery/implantchair/attack_hand(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
var/health_text = ""
|
||||
if(src.occupant)
|
||||
if(src.occupant.health <= -100)
|
||||
health_text = "<FONT color=red>Dead</FONT>"
|
||||
else if(src.occupant.health < 0)
|
||||
health_text = "<FONT color=red>[round(src.occupant.health,0.1)]</FONT>"
|
||||
else
|
||||
health_text = "[round(src.occupant.health,0.1)]"
|
||||
|
||||
var/dat ="<B>Implanter Status</B><BR>"
|
||||
|
||||
dat +="<B>Current occupant:</B> [src.occupant ? "<BR>Name: [src.occupant]<BR>Health: [health_text]<BR>" : "<FONT color=red>None</FONT>"]<BR>"
|
||||
dat += "<B>Implants:</B> [src.implant_list.len ? "[implant_list.len]" : "<A href='?src=\ref[src];replenish=1'>Replenish</A>"]<BR>"
|
||||
if(src.occupant)
|
||||
dat += "[src.ready ? "<A href='?src=\ref[src];implant=1'>Implant</A>" : "Recharging"]<BR>"
|
||||
user.set_machine(src)
|
||||
user << browse(dat, "window=implant")
|
||||
onclose(user, "implant")
|
||||
|
||||
|
||||
/obj/machinery/implantchair/Topic(href, href_list)
|
||||
if((get_dist(src, usr) <= 1) || istype(usr, /mob/living/silicon/ai))
|
||||
if(href_list["implant"])
|
||||
if(src.occupant)
|
||||
injecting = 1
|
||||
go_out()
|
||||
ready = 0
|
||||
spawn(injection_cooldown)
|
||||
ready = 1
|
||||
|
||||
if(href_list["replenish"])
|
||||
ready = 0
|
||||
spawn(replenish_cooldown)
|
||||
add_implants()
|
||||
ready = 1
|
||||
|
||||
src.updateUsrDialog()
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/implantchair/attackby(var/obj/item/weapon/G as obj, var/mob/user as mob)
|
||||
if(istype(G, /obj/item/weapon/grab))
|
||||
var/obj/item/weapon/grab/grab = G
|
||||
if(!ismob(grab.affecting))
|
||||
return
|
||||
if(grab.affecting.has_buckled_mobs())
|
||||
to_chat(user, span("warning", "\The [grab.affecting] has other entities attached to them. Remove them first."))
|
||||
return
|
||||
var/mob/M = grab.affecting
|
||||
if(put_mob(M))
|
||||
qdel(G)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/implantchair/proc/go_out(var/mob/M)
|
||||
if(!( src.occupant ))
|
||||
return
|
||||
if(M == occupant) // so that the guy inside can't eject himself -Agouri
|
||||
return
|
||||
if (src.occupant.client)
|
||||
src.occupant.client.eye = src.occupant.client.mob
|
||||
src.occupant.client.perspective = MOB_PERSPECTIVE
|
||||
src.occupant.loc = src.loc
|
||||
if(injecting)
|
||||
implant(src.occupant)
|
||||
injecting = 0
|
||||
src.occupant = null
|
||||
icon_state = "implantchair"
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/implantchair/proc/put_mob(mob/living/carbon/M as mob)
|
||||
if(!iscarbon(M))
|
||||
to_chat(usr, "<span class='warning'>\The [src] cannot hold this!</span>")
|
||||
return
|
||||
if(src.occupant)
|
||||
to_chat(usr, "<span class='warning'>\The [src] is already occupied!</span>")
|
||||
return
|
||||
if(M.client)
|
||||
M.client.perspective = EYE_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
M.stop_pulling()
|
||||
M.loc = src
|
||||
src.occupant = M
|
||||
src.add_fingerprint(usr)
|
||||
icon_state = "implantchair_on"
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/implantchair/proc/implant(var/mob/M)
|
||||
if (!istype(M, /mob/living/carbon))
|
||||
return
|
||||
if(!implant_list.len) return
|
||||
for(var/obj/item/weapon/implant/loyalty/imp in implant_list)
|
||||
if(!imp) continue
|
||||
if(istype(imp, /obj/item/weapon/implant/loyalty))
|
||||
for (var/mob/O in viewers(M, null))
|
||||
O.show_message("<span class='warning'>\The [M] has been implanted by \the [src].</span>", 1)
|
||||
|
||||
if(imp.handle_implant(M, BP_TORSO))
|
||||
imp.post_implant(M)
|
||||
|
||||
implant_list -= imp
|
||||
break
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/implantchair/proc/add_implants()
|
||||
for(var/i=0, i<src.max_implants, i++)
|
||||
var/obj/item/weapon/implant/loyalty/I = new /obj/item/weapon/implant/loyalty(src)
|
||||
implant_list += I
|
||||
return
|
||||
|
||||
/obj/machinery/implantchair/verb/get_out()
|
||||
set name = "Eject occupant"
|
||||
set category = "Object"
|
||||
set src in oview(1)
|
||||
if(usr.stat != 0)
|
||||
return
|
||||
src.go_out(usr)
|
||||
add_fingerprint(usr)
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/implantchair/verb/move_inside()
|
||||
set name = "Move Inside"
|
||||
set category = "Object"
|
||||
set src in oview(1)
|
||||
if(usr.stat != 0 || stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
put_mob(usr)
|
||||
return
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
|
||||
|
||||
/obj/machinery/implantchair
|
||||
name = "loyalty implanter"
|
||||
desc = "Used to implant occupants with loyalty implants."
|
||||
icon = 'icons/obj/machines/implantchair.dmi'
|
||||
icon_state = "implantchair"
|
||||
density = TRUE
|
||||
opacity = 0
|
||||
anchored = TRUE
|
||||
|
||||
var/ready = 1
|
||||
var/malfunction = 0
|
||||
var/list/obj/item/weapon/implant/loyalty/implant_list = list()
|
||||
var/max_implants = 5
|
||||
var/injection_cooldown = 600
|
||||
var/replenish_cooldown = 6000
|
||||
var/replenishing = 0
|
||||
var/mob/living/carbon/occupant = null
|
||||
var/injecting = 0
|
||||
|
||||
/obj/machinery/implantchair/New()
|
||||
..()
|
||||
add_implants()
|
||||
|
||||
|
||||
/obj/machinery/implantchair/attack_hand(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
var/health_text = ""
|
||||
if(src.occupant)
|
||||
if(src.occupant.health <= -100)
|
||||
health_text = "<FONT color=red>Dead</FONT>"
|
||||
else if(src.occupant.health < 0)
|
||||
health_text = "<FONT color=red>[round(src.occupant.health,0.1)]</FONT>"
|
||||
else
|
||||
health_text = "[round(src.occupant.health,0.1)]"
|
||||
|
||||
var/dat ="<B>Implanter Status</B><BR>"
|
||||
|
||||
dat +="<B>Current occupant:</B> [src.occupant ? "<BR>Name: [src.occupant]<BR>Health: [health_text]<BR>" : "<FONT color=red>None</FONT>"]<BR>"
|
||||
dat += "<B>Implants:</B> [src.implant_list.len ? "[implant_list.len]" : "<A href='?src=\ref[src];replenish=1'>Replenish</A>"]<BR>"
|
||||
if(src.occupant)
|
||||
dat += "[src.ready ? "<A href='?src=\ref[src];implant=1'>Implant</A>" : "Recharging"]<BR>"
|
||||
user.set_machine(src)
|
||||
user << browse(dat, "window=implant")
|
||||
onclose(user, "implant")
|
||||
|
||||
|
||||
/obj/machinery/implantchair/Topic(href, href_list)
|
||||
if((get_dist(src, usr) <= 1) || istype(usr, /mob/living/silicon/ai))
|
||||
if(href_list["implant"])
|
||||
if(src.occupant)
|
||||
injecting = 1
|
||||
go_out()
|
||||
ready = 0
|
||||
spawn(injection_cooldown)
|
||||
ready = 1
|
||||
|
||||
if(href_list["replenish"])
|
||||
ready = 0
|
||||
spawn(replenish_cooldown)
|
||||
add_implants()
|
||||
ready = 1
|
||||
|
||||
src.updateUsrDialog()
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/implantchair/attackby(var/obj/item/weapon/G as obj, var/mob/user as mob)
|
||||
if(istype(G, /obj/item/weapon/grab))
|
||||
var/obj/item/weapon/grab/grab = G
|
||||
if(!ismob(grab.affecting))
|
||||
return
|
||||
if(grab.affecting.has_buckled_mobs())
|
||||
to_chat(user, span("warning", "\The [grab.affecting] has other entities attached to them. Remove them first."))
|
||||
return
|
||||
var/mob/M = grab.affecting
|
||||
if(put_mob(M))
|
||||
qdel(G)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/implantchair/proc/go_out(var/mob/M)
|
||||
if(!( src.occupant ))
|
||||
return
|
||||
if(M == occupant) // so that the guy inside can't eject himself -Agouri
|
||||
return
|
||||
if (src.occupant.client)
|
||||
src.occupant.client.eye = src.occupant.client.mob
|
||||
src.occupant.client.perspective = MOB_PERSPECTIVE
|
||||
src.occupant.loc = src.loc
|
||||
if(injecting)
|
||||
implant(src.occupant)
|
||||
injecting = 0
|
||||
src.occupant = null
|
||||
icon_state = "implantchair"
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/implantchair/proc/put_mob(mob/living/carbon/M as mob)
|
||||
if(!iscarbon(M))
|
||||
to_chat(usr, "<span class='warning'>\The [src] cannot hold this!</span>")
|
||||
return
|
||||
if(src.occupant)
|
||||
to_chat(usr, "<span class='warning'>\The [src] is already occupied!</span>")
|
||||
return
|
||||
if(M.client)
|
||||
M.client.perspective = EYE_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
M.stop_pulling()
|
||||
M.loc = src
|
||||
src.occupant = M
|
||||
src.add_fingerprint(usr)
|
||||
icon_state = "implantchair_on"
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/implantchair/proc/implant(var/mob/M)
|
||||
if (!istype(M, /mob/living/carbon))
|
||||
return
|
||||
if(!implant_list.len) return
|
||||
for(var/obj/item/weapon/implant/loyalty/imp in implant_list)
|
||||
if(!imp) continue
|
||||
if(istype(imp, /obj/item/weapon/implant/loyalty))
|
||||
for (var/mob/O in viewers(M, null))
|
||||
O.show_message("<span class='warning'>\The [M] has been implanted by \the [src].</span>", 1)
|
||||
|
||||
if(imp.handle_implant(M, BP_TORSO))
|
||||
imp.post_implant(M)
|
||||
|
||||
implant_list -= imp
|
||||
break
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/implantchair/proc/add_implants()
|
||||
for(var/i=0, i<src.max_implants, i++)
|
||||
var/obj/item/weapon/implant/loyalty/I = new /obj/item/weapon/implant/loyalty(src)
|
||||
implant_list += I
|
||||
return
|
||||
|
||||
/obj/machinery/implantchair/verb/get_out()
|
||||
set name = "Eject occupant"
|
||||
set category = "Object"
|
||||
set src in oview(1)
|
||||
if(usr.stat != 0)
|
||||
return
|
||||
src.go_out(usr)
|
||||
add_fingerprint(usr)
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/implantchair/verb/move_inside()
|
||||
set name = "Move Inside"
|
||||
set category = "Object"
|
||||
set src in oview(1)
|
||||
if(usr.stat != 0 || stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
put_mob(usr)
|
||||
return
|
||||
|
||||
@@ -1,165 +1,165 @@
|
||||
/obj/item/weapon/implanter
|
||||
name = "implanter"
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "implanter0_1"
|
||||
item_state = "syringe_0"
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_SMALL
|
||||
matter = list(MAT_STEEL = 1000, MAT_GLASS = 1000)
|
||||
var/obj/item/weapon/implant/imp = null
|
||||
var/active = 1
|
||||
|
||||
/obj/item/weapon/implanter/attack_self(var/mob/user)
|
||||
active = !active
|
||||
to_chat(user, "<span class='notice'>You [active ? "" : "de"]activate \the [src].</span>")
|
||||
update()
|
||||
|
||||
/obj/item/weapon/implanter/verb/remove_implant()
|
||||
set category = "Object"
|
||||
set name = "Remove Implant"
|
||||
set src in usr
|
||||
|
||||
if(!imp)
|
||||
return
|
||||
if(istype(usr, /mob))
|
||||
var/mob/M = usr
|
||||
imp.loc = get_turf(src)
|
||||
if(M.get_active_hand() == null)
|
||||
M.put_in_hands(imp)
|
||||
to_chat(M, "<span class='notice'>You remove \the [imp] from \the [src].</span>")
|
||||
name = "implanter"
|
||||
imp = null
|
||||
|
||||
update()
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/proc/update()
|
||||
if (src.imp)
|
||||
src.icon_state = "implanter1"
|
||||
else
|
||||
src.icon_state = "implanter0"
|
||||
src.icon_state += "_[active]"
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/attack(mob/M as mob, mob/user as mob)
|
||||
if (!istype(M, /mob/living/carbon))
|
||||
return
|
||||
if(active)
|
||||
if (imp)
|
||||
M.visible_message("<span class='warning'>[user] is attempting to implant [M].</span>")
|
||||
|
||||
user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
|
||||
user.do_attack_animation(M)
|
||||
|
||||
var/turf/T1 = get_turf(M)
|
||||
if (T1 && ((M == user) || do_after(user, 50)))
|
||||
if(user && M && (get_turf(M) == T1) && src && src.imp)
|
||||
M.visible_message("<span class='warning'>[M] has been implanted by [user].</span>")
|
||||
|
||||
add_attack_logs(user,M,"Implanted with [imp.name] using [name]")
|
||||
|
||||
if(imp.handle_implant(M))
|
||||
imp.post_implant(M)
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
BITSET(H.hud_updateflag, IMPLOYAL_HUD)
|
||||
BITSET(H.hud_updateflag, BACKUP_HUD) //VOREStation Add - Backup HUD updates
|
||||
|
||||
src.imp = null
|
||||
update()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to activate \the [src.name] first.</span>")
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/loyalty
|
||||
name = "implanter-loyalty"
|
||||
|
||||
/obj/item/weapon/implanter/loyalty/New()
|
||||
src.imp = new /obj/item/weapon/implant/loyalty( src )
|
||||
..()
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/explosive
|
||||
name = "implanter (E)"
|
||||
|
||||
/obj/item/weapon/implanter/explosive/New()
|
||||
src.imp = new /obj/item/weapon/implant/explosive( src )
|
||||
..()
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/adrenalin
|
||||
name = "implanter-adrenalin"
|
||||
|
||||
/obj/item/weapon/implanter/adrenalin/New()
|
||||
src.imp = new /obj/item/weapon/implant/adrenalin(src)
|
||||
..()
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/compressed
|
||||
name = "implanter (C)"
|
||||
icon_state = "cimplanter1"
|
||||
|
||||
/obj/item/weapon/implanter/compressed/New()
|
||||
imp = new /obj/item/weapon/implant/compressed( src )
|
||||
..()
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/compressed/update()
|
||||
if (imp)
|
||||
var/obj/item/weapon/implant/compressed/c = imp
|
||||
if(!c.scanned)
|
||||
icon_state = "cimplanter1"
|
||||
else
|
||||
icon_state = "cimplanter2"
|
||||
else
|
||||
icon_state = "cimplanter0"
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/compressed/attack(mob/M as mob, mob/user as mob)
|
||||
var/obj/item/weapon/implant/compressed/c = imp
|
||||
if (!c) return
|
||||
if (c.scanned == null)
|
||||
to_chat(user, "Please scan an object with the implanter first.")
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/weapon/implanter/compressed/afterattack(atom/A, mob/user as mob, proximity)
|
||||
if(!proximity)
|
||||
return
|
||||
if(!active)
|
||||
to_chat(user, "<span class='warning'>Activate \the [src.name] first.</span>")
|
||||
return
|
||||
if(istype(A,/obj/item) && imp)
|
||||
var/obj/item/weapon/implant/compressed/c = imp
|
||||
if (c.scanned)
|
||||
to_chat(user, "<span class='warning'>Something is already scanned inside the implant!</span>")
|
||||
return
|
||||
c.scanned = A
|
||||
if(istype(A, /obj/item/weapon/storage))
|
||||
to_chat(user, "<span class='warning'>You can't store \the [A.name] in this!</span>")
|
||||
c.scanned = null
|
||||
return
|
||||
if(istype(A.loc,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = A.loc
|
||||
H.remove_from_mob(A)
|
||||
else if(istype(A.loc,/obj/item/weapon/storage))
|
||||
var/obj/item/weapon/storage/S = A.loc
|
||||
S.remove_from_storage(A)
|
||||
A.loc.contents.Remove(A)
|
||||
update()
|
||||
|
||||
/obj/item/weapon/implanter/restrainingbolt
|
||||
name = "implanter (bolt)"
|
||||
|
||||
/obj/item/weapon/implanter/restrainingbolt/New()
|
||||
src.imp = new /obj/item/weapon/implant/restrainingbolt( src )
|
||||
..()
|
||||
update()
|
||||
return
|
||||
/obj/item/weapon/implanter
|
||||
name = "implanter"
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "implanter0_1"
|
||||
item_state = "syringe_0"
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_SMALL
|
||||
matter = list(MAT_STEEL = 1000, MAT_GLASS = 1000)
|
||||
var/obj/item/weapon/implant/imp = null
|
||||
var/active = 1
|
||||
|
||||
/obj/item/weapon/implanter/attack_self(var/mob/user)
|
||||
active = !active
|
||||
to_chat(user, "<span class='notice'>You [active ? "" : "de"]activate \the [src].</span>")
|
||||
update()
|
||||
|
||||
/obj/item/weapon/implanter/verb/remove_implant()
|
||||
set category = "Object"
|
||||
set name = "Remove Implant"
|
||||
set src in usr
|
||||
|
||||
if(!imp)
|
||||
return
|
||||
if(istype(usr, /mob))
|
||||
var/mob/M = usr
|
||||
imp.loc = get_turf(src)
|
||||
if(M.get_active_hand() == null)
|
||||
M.put_in_hands(imp)
|
||||
to_chat(M, "<span class='notice'>You remove \the [imp] from \the [src].</span>")
|
||||
name = "implanter"
|
||||
imp = null
|
||||
|
||||
update()
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/proc/update()
|
||||
if (src.imp)
|
||||
src.icon_state = "implanter1"
|
||||
else
|
||||
src.icon_state = "implanter0"
|
||||
src.icon_state += "_[active]"
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/attack(mob/M as mob, mob/user as mob)
|
||||
if (!istype(M, /mob/living/carbon))
|
||||
return
|
||||
if(active)
|
||||
if (imp)
|
||||
M.visible_message("<span class='warning'>[user] is attempting to implant [M].</span>")
|
||||
|
||||
user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
|
||||
user.do_attack_animation(M)
|
||||
|
||||
var/turf/T1 = get_turf(M)
|
||||
if (T1 && ((M == user) || do_after(user, 50)))
|
||||
if(user && M && (get_turf(M) == T1) && src && src.imp)
|
||||
M.visible_message("<span class='warning'>[M] has been implanted by [user].</span>")
|
||||
|
||||
add_attack_logs(user,M,"Implanted with [imp.name] using [name]")
|
||||
|
||||
if(imp.handle_implant(M))
|
||||
imp.post_implant(M)
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
BITSET(H.hud_updateflag, IMPLOYAL_HUD)
|
||||
BITSET(H.hud_updateflag, BACKUP_HUD) //VOREStation Add - Backup HUD updates
|
||||
|
||||
src.imp = null
|
||||
update()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to activate \the [src.name] first.</span>")
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/loyalty
|
||||
name = "implanter-loyalty"
|
||||
|
||||
/obj/item/weapon/implanter/loyalty/New()
|
||||
src.imp = new /obj/item/weapon/implant/loyalty( src )
|
||||
..()
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/explosive
|
||||
name = "implanter (E)"
|
||||
|
||||
/obj/item/weapon/implanter/explosive/New()
|
||||
src.imp = new /obj/item/weapon/implant/explosive( src )
|
||||
..()
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/adrenalin
|
||||
name = "implanter-adrenalin"
|
||||
|
||||
/obj/item/weapon/implanter/adrenalin/New()
|
||||
src.imp = new /obj/item/weapon/implant/adrenalin(src)
|
||||
..()
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/compressed
|
||||
name = "implanter (C)"
|
||||
icon_state = "cimplanter1"
|
||||
|
||||
/obj/item/weapon/implanter/compressed/New()
|
||||
imp = new /obj/item/weapon/implant/compressed( src )
|
||||
..()
|
||||
update()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/compressed/update()
|
||||
if (imp)
|
||||
var/obj/item/weapon/implant/compressed/c = imp
|
||||
if(!c.scanned)
|
||||
icon_state = "cimplanter1"
|
||||
else
|
||||
icon_state = "cimplanter2"
|
||||
else
|
||||
icon_state = "cimplanter0"
|
||||
return
|
||||
|
||||
/obj/item/weapon/implanter/compressed/attack(mob/M as mob, mob/user as mob)
|
||||
var/obj/item/weapon/implant/compressed/c = imp
|
||||
if (!c) return
|
||||
if (c.scanned == null)
|
||||
to_chat(user, "Please scan an object with the implanter first.")
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/weapon/implanter/compressed/afterattack(atom/A, mob/user as mob, proximity)
|
||||
if(!proximity)
|
||||
return
|
||||
if(!active)
|
||||
to_chat(user, "<span class='warning'>Activate \the [src.name] first.</span>")
|
||||
return
|
||||
if(istype(A,/obj/item) && imp)
|
||||
var/obj/item/weapon/implant/compressed/c = imp
|
||||
if (c.scanned)
|
||||
to_chat(user, "<span class='warning'>Something is already scanned inside the implant!</span>")
|
||||
return
|
||||
c.scanned = A
|
||||
if(istype(A, /obj/item/weapon/storage))
|
||||
to_chat(user, "<span class='warning'>You can't store \the [A.name] in this!</span>")
|
||||
c.scanned = null
|
||||
return
|
||||
if(istype(A.loc,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = A.loc
|
||||
H.remove_from_mob(A)
|
||||
else if(istype(A.loc,/obj/item/weapon/storage))
|
||||
var/obj/item/weapon/storage/S = A.loc
|
||||
S.remove_from_storage(A)
|
||||
A.loc.contents.Remove(A)
|
||||
update()
|
||||
|
||||
/obj/item/weapon/implanter/restrainingbolt
|
||||
name = "implanter (bolt)"
|
||||
|
||||
/obj/item/weapon/implanter/restrainingbolt/New()
|
||||
src.imp = new /obj/item/weapon/implant/restrainingbolt( src )
|
||||
..()
|
||||
update()
|
||||
return
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
|
||||
|
||||
/obj/item/weapon/implant/freedom
|
||||
name = "freedom implant"
|
||||
desc = "Use this to escape from those evil Red Shirts."
|
||||
implant_color = "r"
|
||||
var/activation_emote = "chuckle"
|
||||
var/uses = 1.0
|
||||
|
||||
|
||||
/obj/item/weapon/implant/freedom/New()
|
||||
src.activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink")
|
||||
src.uses = rand(1, 5)
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implant/freedom/trigger(emote, mob/living/carbon/source as mob)
|
||||
if (src.uses < 1)
|
||||
return 0
|
||||
|
||||
if (emote == src.activation_emote)
|
||||
src.uses--
|
||||
to_chat(source, "You feel a faint click.")
|
||||
if (source.handcuffed)
|
||||
var/obj/item/weapon/W = source.handcuffed
|
||||
source.handcuffed = null
|
||||
if(source.buckled && source.buckled.buckle_require_restraints)
|
||||
source.buckled.unbuckle_mob()
|
||||
source.update_handcuffed()
|
||||
if (source.client)
|
||||
source.client.screen -= W
|
||||
if (W)
|
||||
W.loc = source.loc
|
||||
dropped(source)
|
||||
if (W)
|
||||
W.layer = initial(W.layer)
|
||||
if (source.legcuffed)
|
||||
var/obj/item/weapon/W = source.legcuffed
|
||||
source.legcuffed = null
|
||||
source.update_inv_legcuffed()
|
||||
if (source.client)
|
||||
source.client.screen -= W
|
||||
if (W)
|
||||
W.loc = source.loc
|
||||
dropped(source)
|
||||
if (W)
|
||||
W.layer = initial(W.layer)
|
||||
return
|
||||
|
||||
/obj/item/weapon/implant/freedom/post_implant(mob/source)
|
||||
source.mind.store_memory("Freedom implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.", 0, 0)
|
||||
to_chat(source, "The implanted freedom implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.")
|
||||
|
||||
/obj/item/weapon/implant/freedom/get_data()
|
||||
var/dat = {"
|
||||
<b>Implant Specifications:</b><BR>
|
||||
<b>Name:</b> Freedom Beacon<BR>
|
||||
<b>Life:</b> optimum 5 uses<BR>
|
||||
<b>Important Notes:</b> <font color='red'>Illegal</font><BR>
|
||||
<HR>
|
||||
<b>Implant Details:</b> <BR>
|
||||
<b>Function:</b> Transmits a specialized cluster of signals to override handcuff locking
|
||||
mechanisms<BR>
|
||||
<b>Special Features:</b><BR>
|
||||
<i>Neuro-Scan</i>- Analyzes certain shadow signals in the nervous system<BR>
|
||||
<b>Integrity:</b> The battery is extremely weak and commonly after injection its
|
||||
life can drive down to only 1 use.<HR>
|
||||
No Implant Specifics"}
|
||||
return dat
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
|
||||
|
||||
/obj/item/weapon/implant/freedom
|
||||
name = "freedom implant"
|
||||
desc = "Use this to escape from those evil Red Shirts."
|
||||
implant_color = "r"
|
||||
var/activation_emote = "chuckle"
|
||||
var/uses = 1.0
|
||||
|
||||
|
||||
/obj/item/weapon/implant/freedom/New()
|
||||
src.activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink")
|
||||
src.uses = rand(1, 5)
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implant/freedom/trigger(emote, mob/living/carbon/source as mob)
|
||||
if (src.uses < 1)
|
||||
return 0
|
||||
|
||||
if (emote == src.activation_emote)
|
||||
src.uses--
|
||||
to_chat(source, "You feel a faint click.")
|
||||
if (source.handcuffed)
|
||||
var/obj/item/weapon/W = source.handcuffed
|
||||
source.handcuffed = null
|
||||
if(source.buckled && source.buckled.buckle_require_restraints)
|
||||
source.buckled.unbuckle_mob()
|
||||
source.update_handcuffed()
|
||||
if (source.client)
|
||||
source.client.screen -= W
|
||||
if (W)
|
||||
W.loc = source.loc
|
||||
dropped(source)
|
||||
if (W)
|
||||
W.layer = initial(W.layer)
|
||||
if (source.legcuffed)
|
||||
var/obj/item/weapon/W = source.legcuffed
|
||||
source.legcuffed = null
|
||||
source.update_inv_legcuffed()
|
||||
if (source.client)
|
||||
source.client.screen -= W
|
||||
if (W)
|
||||
W.loc = source.loc
|
||||
dropped(source)
|
||||
if (W)
|
||||
W.layer = initial(W.layer)
|
||||
return
|
||||
|
||||
/obj/item/weapon/implant/freedom/post_implant(mob/source)
|
||||
source.mind.store_memory("Freedom implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.", 0, 0)
|
||||
to_chat(source, "The implanted freedom implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.")
|
||||
|
||||
/obj/item/weapon/implant/freedom/get_data()
|
||||
var/dat = {"
|
||||
<b>Implant Specifications:</b><BR>
|
||||
<b>Name:</b> Freedom Beacon<BR>
|
||||
<b>Life:</b> optimum 5 uses<BR>
|
||||
<b>Important Notes:</b> <font color='red'>Illegal</font><BR>
|
||||
<HR>
|
||||
<b>Implant Details:</b> <BR>
|
||||
<b>Function:</b> Transmits a specialized cluster of signals to override handcuff locking
|
||||
mechanisms<BR>
|
||||
<b>Special Features:</b><BR>
|
||||
<i>Neuro-Scan</i>- Analyzes certain shadow signals in the nervous system<BR>
|
||||
<b>Integrity:</b> The battery is extremely weak and commonly after injection its
|
||||
life can drive down to only 1 use.<HR>
|
||||
No Implant Specifics"}
|
||||
return dat
|
||||
|
||||
@@ -1,94 +1,94 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
|
||||
|
||||
/obj/item/weapon/implantpad
|
||||
name = "implantpad"
|
||||
desc = "Used to modify implants."
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "implantpad-0"
|
||||
item_state = "electronic"
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_SMALL
|
||||
var/obj/item/weapon/implantcase/case = null
|
||||
var/broadcasting = null
|
||||
var/listening = 1.0
|
||||
/obj/item/weapon/implantpad/proc/update()
|
||||
if (src.case)
|
||||
src.icon_state = "implantpad-1"
|
||||
else
|
||||
src.icon_state = "implantpad-0"
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantpad/attack_hand(mob/living/user as mob)
|
||||
if ((src.case && user.item_is_in_hands(src)))
|
||||
user.put_in_active_hand(case)
|
||||
|
||||
src.case.add_fingerprint(user)
|
||||
src.case = null
|
||||
|
||||
src.add_fingerprint(user)
|
||||
update()
|
||||
else
|
||||
return ..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantpad/attackby(obj/item/weapon/implantcase/C as obj, mob/user as mob)
|
||||
..()
|
||||
if(istype(C, /obj/item/weapon/implantcase))
|
||||
if(!( src.case ))
|
||||
user.drop_item()
|
||||
C.loc = src
|
||||
src.case = C
|
||||
else
|
||||
return
|
||||
src.update()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantpad/attack_self(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
var/dat = "<B>Implant Mini-Computer:</B><HR>"
|
||||
if (src.case)
|
||||
if(src.case.imp)
|
||||
if(istype(src.case.imp, /obj/item/weapon/implant))
|
||||
dat += src.case.imp.get_data()
|
||||
if(istype(src.case.imp, /obj/item/weapon/implant/tracking))
|
||||
dat += {"ID (1-100):
|
||||
<A href='byond://?src=\ref[src];tracking_id=-10'>-</A>
|
||||
<A href='byond://?src=\ref[src];tracking_id=-1'>-</A> [case.imp:id]
|
||||
<A href='byond://?src=\ref[src];tracking_id=1'>+</A>
|
||||
<A href='byond://?src=\ref[src];tracking_id=10'>+</A><BR>"}
|
||||
else
|
||||
dat += "The implant casing is empty."
|
||||
else
|
||||
dat += "Please insert an implant casing!"
|
||||
user << browse(dat, "window=implantpad")
|
||||
onclose(user, "implantpad")
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantpad/Topic(href, href_list)
|
||||
..()
|
||||
if (usr.stat)
|
||||
return
|
||||
if ((usr.contents.Find(src)) || ((in_range(src, usr) && istype(src.loc, /turf))))
|
||||
usr.set_machine(src)
|
||||
if (href_list["tracking_id"])
|
||||
var/obj/item/weapon/implant/tracking/T = src.case.imp
|
||||
T.id += text2num(href_list["tracking_id"])
|
||||
T.id = min(1000, T.id)
|
||||
T.id = max(1, T.id)
|
||||
|
||||
if (istype(src.loc, /mob))
|
||||
attack_self(src.loc)
|
||||
else
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if (M.client)
|
||||
src.attack_self(M)
|
||||
src.add_fingerprint(usr)
|
||||
else
|
||||
usr << browse(null, "window=implantpad")
|
||||
return
|
||||
return
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
|
||||
|
||||
/obj/item/weapon/implantpad
|
||||
name = "implantpad"
|
||||
desc = "Used to modify implants."
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "implantpad-0"
|
||||
item_state = "electronic"
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = ITEMSIZE_SMALL
|
||||
var/obj/item/weapon/implantcase/case = null
|
||||
var/broadcasting = null
|
||||
var/listening = 1.0
|
||||
/obj/item/weapon/implantpad/proc/update()
|
||||
if (src.case)
|
||||
src.icon_state = "implantpad-1"
|
||||
else
|
||||
src.icon_state = "implantpad-0"
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantpad/attack_hand(mob/living/user as mob)
|
||||
if ((src.case && user.item_is_in_hands(src)))
|
||||
user.put_in_active_hand(case)
|
||||
|
||||
src.case.add_fingerprint(user)
|
||||
src.case = null
|
||||
|
||||
src.add_fingerprint(user)
|
||||
update()
|
||||
else
|
||||
return ..()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantpad/attackby(obj/item/weapon/implantcase/C as obj, mob/user as mob)
|
||||
..()
|
||||
if(istype(C, /obj/item/weapon/implantcase))
|
||||
if(!( src.case ))
|
||||
user.drop_item()
|
||||
C.loc = src
|
||||
src.case = C
|
||||
else
|
||||
return
|
||||
src.update()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantpad/attack_self(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
var/dat = "<B>Implant Mini-Computer:</B><HR>"
|
||||
if (src.case)
|
||||
if(src.case.imp)
|
||||
if(istype(src.case.imp, /obj/item/weapon/implant))
|
||||
dat += src.case.imp.get_data()
|
||||
if(istype(src.case.imp, /obj/item/weapon/implant/tracking))
|
||||
dat += {"ID (1-100):
|
||||
<A href='byond://?src=\ref[src];tracking_id=-10'>-</A>
|
||||
<A href='byond://?src=\ref[src];tracking_id=-1'>-</A> [case.imp:id]
|
||||
<A href='byond://?src=\ref[src];tracking_id=1'>+</A>
|
||||
<A href='byond://?src=\ref[src];tracking_id=10'>+</A><BR>"}
|
||||
else
|
||||
dat += "The implant casing is empty."
|
||||
else
|
||||
dat += "Please insert an implant casing!"
|
||||
user << browse(dat, "window=implantpad")
|
||||
onclose(user, "implantpad")
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/implantpad/Topic(href, href_list)
|
||||
..()
|
||||
if (usr.stat)
|
||||
return
|
||||
if ((usr.contents.Find(src)) || ((in_range(src, usr) && istype(src.loc, /turf))))
|
||||
usr.set_machine(src)
|
||||
if (href_list["tracking_id"])
|
||||
var/obj/item/weapon/implant/tracking/T = src.case.imp
|
||||
T.id += text2num(href_list["tracking_id"])
|
||||
T.id = min(1000, T.id)
|
||||
T.id = max(1, T.id)
|
||||
|
||||
if (istype(src.loc, /mob))
|
||||
attack_self(src.loc)
|
||||
else
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if (M.client)
|
||||
src.attack_self(M)
|
||||
src.add_fingerprint(usr)
|
||||
else
|
||||
usr << browse(null, "window=implantpad")
|
||||
return
|
||||
return
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
/obj/item/weapon/implant/uplink
|
||||
name = "uplink"
|
||||
desc = "Summon things."
|
||||
var/activation_emote = "chuckle"
|
||||
|
||||
/obj/item/weapon/implant/uplink/New()
|
||||
activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink")
|
||||
hidden_uplink = new(src)
|
||||
//hidden_uplink.uses = 5
|
||||
//Code currently uses a mind var for telecrystals, balancing is currently an issue. Will investigate.
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implant/uplink/post_implant(mob/source)
|
||||
var/choices = list("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink")
|
||||
activation_emote = tgui_input_list(usr, "Choose activation emote. If you cancel this, one will be picked at random.", "Implant Activation", choices)
|
||||
if(!activation_emote)
|
||||
activation_emote = pick(choices)
|
||||
source.mind.store_memory("Uplink implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.", 0, 0)
|
||||
to_chat(source, "The implanted uplink implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.")
|
||||
|
||||
/obj/item/weapon/implant/uplink/trigger(emote, mob/source as mob)
|
||||
if(hidden_uplink && usr == source) // Let's not have another people activate our uplink
|
||||
hidden_uplink.check_trigger(source, emote, activation_emote)
|
||||
/obj/item/weapon/implant/uplink
|
||||
name = "uplink"
|
||||
desc = "Summon things."
|
||||
var/activation_emote = "chuckle"
|
||||
|
||||
/obj/item/weapon/implant/uplink/New()
|
||||
activation_emote = pick("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink")
|
||||
hidden_uplink = new(src)
|
||||
//hidden_uplink.uses = 5
|
||||
//Code currently uses a mind var for telecrystals, balancing is currently an issue. Will investigate.
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/weapon/implant/uplink/post_implant(mob/source)
|
||||
var/choices = list("blink", "blink_r", "eyebrow", "chuckle", "twitch", "frown", "nod", "blush", "giggle", "grin", "groan", "shrug", "smile", "pale", "sniff", "whimper", "wink")
|
||||
activation_emote = tgui_input_list(usr, "Choose activation emote. If you cancel this, one will be picked at random.", "Implant Activation", choices)
|
||||
if(!activation_emote)
|
||||
activation_emote = pick(choices)
|
||||
source.mind.store_memory("Uplink implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.", 0, 0)
|
||||
to_chat(source, "The implanted uplink implant can be activated by using the [src.activation_emote] emote, <B>say *[src.activation_emote]</B> to attempt to activate.")
|
||||
|
||||
/obj/item/weapon/implant/uplink/trigger(emote, mob/source as mob)
|
||||
if(hidden_uplink && usr == source) // Let's not have another people activate our uplink
|
||||
hidden_uplink.check_trigger(source, emote, activation_emote)
|
||||
return
|
||||
@@ -1,40 +1,40 @@
|
||||
/obj/item/weapon/material/butterflyconstruction
|
||||
name = "unfinished concealed knife"
|
||||
desc = "An unfinished concealed knife, it looks like the screws need to be tightened."
|
||||
icon = 'icons/obj/buildingobject.dmi'
|
||||
icon_state = "butterflystep1"
|
||||
force_divisor = 0.1
|
||||
thrown_force_divisor = 0.1
|
||||
|
||||
/obj/item/weapon/material/butterflyconstruction/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
to_chat(user, "You finish the concealed blade weapon.")
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
new /obj/item/weapon/material/butterfly(user.loc, material.name)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/butterflyblade
|
||||
name = "knife blade"
|
||||
desc = "A knife blade. Unusable as a weapon without a grip."
|
||||
icon = 'icons/obj/buildingobject.dmi'
|
||||
icon_state = "butterfly2"
|
||||
force_divisor = 0.1
|
||||
thrown_force_divisor = 0.1
|
||||
|
||||
/obj/item/weapon/material/butterflyhandle
|
||||
name = "concealed knife grip"
|
||||
desc = "A plasteel grip with screw fittings for a blade."
|
||||
icon = 'icons/obj/buildingobject.dmi'
|
||||
icon_state = "butterfly1"
|
||||
force_divisor = 0.1
|
||||
thrown_force_divisor = 0.1
|
||||
|
||||
/obj/item/weapon/material/butterflyhandle/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(istype(W,/obj/item/weapon/material/butterflyblade))
|
||||
var/obj/item/weapon/material/butterflyblade/B = W
|
||||
to_chat(user, "You attach the two concealed blade parts.")
|
||||
new /obj/item/weapon/material/butterflyconstruction(user.loc, B.material.name)
|
||||
qdel(W)
|
||||
qdel(src)
|
||||
return
|
||||
/obj/item/weapon/material/butterflyconstruction
|
||||
name = "unfinished concealed knife"
|
||||
desc = "An unfinished concealed knife, it looks like the screws need to be tightened."
|
||||
icon = 'icons/obj/buildingobject.dmi'
|
||||
icon_state = "butterflystep1"
|
||||
force_divisor = 0.1
|
||||
thrown_force_divisor = 0.1
|
||||
|
||||
/obj/item/weapon/material/butterflyconstruction/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(W.has_tool_quality(TOOL_SCREWDRIVER))
|
||||
to_chat(user, "You finish the concealed blade weapon.")
|
||||
playsound(src, W.usesound, 50, 1)
|
||||
new /obj/item/weapon/material/butterfly(user.loc, material.name)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/butterflyblade
|
||||
name = "knife blade"
|
||||
desc = "A knife blade. Unusable as a weapon without a grip."
|
||||
icon = 'icons/obj/buildingobject.dmi'
|
||||
icon_state = "butterfly2"
|
||||
force_divisor = 0.1
|
||||
thrown_force_divisor = 0.1
|
||||
|
||||
/obj/item/weapon/material/butterflyhandle
|
||||
name = "concealed knife grip"
|
||||
desc = "A plasteel grip with screw fittings for a blade."
|
||||
icon = 'icons/obj/buildingobject.dmi'
|
||||
icon_state = "butterfly1"
|
||||
force_divisor = 0.1
|
||||
thrown_force_divisor = 0.1
|
||||
|
||||
/obj/item/weapon/material/butterflyhandle/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(istype(W,/obj/item/weapon/material/butterflyblade))
|
||||
var/obj/item/weapon/material/butterflyblade/B = W
|
||||
to_chat(user, "You attach the two concealed blade parts.")
|
||||
new /obj/item/weapon/material/butterflyconstruction(user.loc, B.material.name)
|
||||
qdel(W)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
+1842
-1842
File diff suppressed because it is too large
Load Diff
@@ -1,29 +1,29 @@
|
||||
/obj/item/weapon/material/twohanded/baseballbat
|
||||
name = "bat"
|
||||
desc = "HOME RUN!"
|
||||
icon_state = "metalbat0"
|
||||
base_icon = "metalbat"
|
||||
throwforce = 7
|
||||
attack_verb = list("smashed", "beaten", "slammed", "smacked", "struck", "battered", "bonked")
|
||||
hitsound = 'sound/weapons/genhit3.ogg'
|
||||
default_material = "wood"
|
||||
force_divisor = 1.1 // 22 when wielded with weight 20 (steel)
|
||||
unwielded_force_divisor = 0.7 // 15 when unwielded based on above.
|
||||
dulled_divisor = 0.75 // A "dull" bat is still gonna hurt
|
||||
slot_flags = SLOT_BACK
|
||||
|
||||
//Predefined materials go here.
|
||||
/obj/item/weapon/material/twohanded/baseballbat/metal/New(var/newloc)
|
||||
..(newloc,"steel")
|
||||
|
||||
/obj/item/weapon/material/twohanded/baseballbat/uranium/New(var/newloc)
|
||||
..(newloc,"uranium")
|
||||
|
||||
/obj/item/weapon/material/twohanded/baseballbat/gold/New(var/newloc)
|
||||
..(newloc,"gold")
|
||||
|
||||
/obj/item/weapon/material/twohanded/baseballbat/platinum/New(var/newloc)
|
||||
..(newloc,"platinum")
|
||||
|
||||
/obj/item/weapon/material/twohanded/baseballbat/diamond/New(var/newloc)
|
||||
/obj/item/weapon/material/twohanded/baseballbat
|
||||
name = "bat"
|
||||
desc = "HOME RUN!"
|
||||
icon_state = "metalbat0"
|
||||
base_icon = "metalbat"
|
||||
throwforce = 7
|
||||
attack_verb = list("smashed", "beaten", "slammed", "smacked", "struck", "battered", "bonked")
|
||||
hitsound = 'sound/weapons/genhit3.ogg'
|
||||
default_material = "wood"
|
||||
force_divisor = 1.1 // 22 when wielded with weight 20 (steel)
|
||||
unwielded_force_divisor = 0.7 // 15 when unwielded based on above.
|
||||
dulled_divisor = 0.75 // A "dull" bat is still gonna hurt
|
||||
slot_flags = SLOT_BACK
|
||||
|
||||
//Predefined materials go here.
|
||||
/obj/item/weapon/material/twohanded/baseballbat/metal/New(var/newloc)
|
||||
..(newloc,"steel")
|
||||
|
||||
/obj/item/weapon/material/twohanded/baseballbat/uranium/New(var/newloc)
|
||||
..(newloc,"uranium")
|
||||
|
||||
/obj/item/weapon/material/twohanded/baseballbat/gold/New(var/newloc)
|
||||
..(newloc,"gold")
|
||||
|
||||
/obj/item/weapon/material/twohanded/baseballbat/platinum/New(var/newloc)
|
||||
..(newloc,"platinum")
|
||||
|
||||
/obj/item/weapon/material/twohanded/baseballbat/diamond/New(var/newloc)
|
||||
..(newloc,"diamond")
|
||||
@@ -1,217 +1,217 @@
|
||||
/obj/item/weapon/material/kitchen
|
||||
icon = 'icons/obj/kitchen.dmi'
|
||||
|
||||
/*
|
||||
* Utensils
|
||||
*/
|
||||
/obj/item/weapon/material/kitchen/utensil
|
||||
drop_sound = 'sound/items/drop/knife.ogg'
|
||||
pickup_sound = 'sound/items/pickup/knife.ogg'
|
||||
w_class = ITEMSIZE_TINY
|
||||
thrown_force_divisor = 1
|
||||
origin_tech = list(TECH_MATERIAL = 1)
|
||||
attack_verb = list("attacked", "stabbed", "poked")
|
||||
sharp = TRUE
|
||||
edge = TRUE
|
||||
force_divisor = 0.1 // 6 when wielded with hardness 60 (steel)
|
||||
thrown_force_divisor = 0.25 // 5 when thrown with weight 20 (steel)
|
||||
var/scoop_volume = 5
|
||||
var/loaded // Name for currently loaded food object.
|
||||
var/loaded_color // Color for currently loaded food object.
|
||||
|
||||
var/list/food_inserted_micros
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/Initialize()
|
||||
. = ..()
|
||||
if (prob(60))
|
||||
src.pixel_y = rand(0, 4)
|
||||
create_reagents(scoop_volume)
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/Destroy()
|
||||
if(food_inserted_micros)
|
||||
for(var/mob/M in food_inserted_micros)
|
||||
M.dropInto(loc)
|
||||
food_inserted_micros -= M
|
||||
. = ..()
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/update_icon()
|
||||
. = ..()
|
||||
cut_overlays()
|
||||
if(loaded)
|
||||
var/image/I = new(icon, "loadedfood")
|
||||
I.color = loaded_color
|
||||
add_overlay(I)
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/proc/load_food(var/mob/user, var/obj/item/weapon/reagent_containers/food/snacks/loading)
|
||||
if (reagents.total_volume > 0)
|
||||
to_chat(user, SPAN_DANGER("There is already something on \the [src]."))
|
||||
return
|
||||
if (!loading?.reagents?.total_volume)
|
||||
to_chat(user, SPAN_NOTICE("Nothing to scoop up in \the [loading]!"))
|
||||
|
||||
|
||||
loaded = "\the [loading]"
|
||||
user.visible_message( \
|
||||
"<b>\The [user]</b> scoops up some of [loaded] with \the [src]!",
|
||||
SPAN_NOTICE("You scoop up some of [loaded] with \the [src]!")
|
||||
)
|
||||
loading.bitecount++
|
||||
loading.reagents.trans_to_obj(src, min(loading.reagents.total_volume, scoop_volume))
|
||||
loaded_color = loading.filling_color
|
||||
|
||||
if(loading.food_inserted_micros && loading.food_inserted_micros.len)
|
||||
if(!food_inserted_micros)
|
||||
food_inserted_micros = list()
|
||||
|
||||
for(var/mob/living/F in loading.food_inserted_micros)
|
||||
var/do_transfer = FALSE
|
||||
|
||||
if(!loading.reagents.total_volume)
|
||||
do_transfer = TRUE
|
||||
else
|
||||
var/transfer_chance = (loading.bitecount/(loading.bitecount + (loading.bitesize / loading.reagents.total_volume) + 1))*100
|
||||
if(prob(transfer_chance))
|
||||
do_transfer = TRUE
|
||||
|
||||
if(do_transfer)
|
||||
F.forceMove(src)
|
||||
loading.food_inserted_micros -= F
|
||||
src.food_inserted_micros += F
|
||||
|
||||
if (loading.reagents.total_volume <= 0)
|
||||
qdel(loading)
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
|
||||
if(!istype(M))
|
||||
return ..()
|
||||
|
||||
if(user.a_intent != I_HELP)
|
||||
if(user.zone_sel.selecting == BP_HEAD || user.zone_sel.selecting == O_EYES)
|
||||
if((CLUMSY in user.mutations) && prob(50))
|
||||
M = user
|
||||
return eyestab(M,user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
if (loaded && reagents.total_volume > 0)
|
||||
reagents.trans_to_mob(M, reagents.total_volume, CHEM_INGEST)
|
||||
if(food_inserted_micros && food_inserted_micros.len)
|
||||
for(var/mob/living/F in food_inserted_micros)
|
||||
food_inserted_micros -= F
|
||||
if(!F.can_be_drop_prey || !F.food_vore)
|
||||
F.forceMove(get_turf(src))
|
||||
else
|
||||
F.forceMove(M.vore_selected)
|
||||
if(M == user)
|
||||
if(!M.can_eat(loaded))
|
||||
return
|
||||
M.visible_message("<b>\The [user]</b> eats some of [loaded] with \the [src].")
|
||||
else
|
||||
user.visible_message(SPAN_WARNING("\The [user] begins to feed \the [M]!"))
|
||||
if(!(M.can_force_feed(user, loaded) && do_mob(user, M, 5 SECONDS)))
|
||||
return
|
||||
M.visible_message("<b>\The [user]</b> feeds some of [loaded] to \the [M] with \the [src].")
|
||||
playsound(src,'sound/items/eatfood.ogg', rand(10,40), 1)
|
||||
loaded = null
|
||||
update_icon()
|
||||
return
|
||||
else
|
||||
to_chat(user, SPAN_WARNING("You don't have anything on \the [src].")) //if we have help intent and no food scooped up DON'T STAB OURSELVES WITH THE FORK
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/on_rag_wipe()
|
||||
. = ..()
|
||||
if(reagents.total_volume > 0)
|
||||
reagents.clear_reagents()
|
||||
cut_overlays()
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/container_resist(mob/living/M)
|
||||
if(food_inserted_micros)
|
||||
food_inserted_micros -= M
|
||||
M.forceMove(get_turf(src))
|
||||
to_chat(M, "<span class='warning'>You climb off of \the [src].</span>")
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/fork
|
||||
name = "fork"
|
||||
desc = "It's a fork. Sure is pointy."
|
||||
icon_state = "fork"
|
||||
sharp = TRUE
|
||||
edge = FALSE
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/fork/plastic
|
||||
default_material = "plastic"
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/foon
|
||||
name = "foon"
|
||||
desc = "It's a foon. The forgotten cousin of the spork."
|
||||
icon_state = "foon"
|
||||
sharp = TRUE
|
||||
edge = FALSE
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/foon/plastic
|
||||
default_material = "plastic"
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/spork
|
||||
name = "spork"
|
||||
desc = "It's a spork. The (un)holy merger of a spoon and fork."
|
||||
icon_state = "spork"
|
||||
sharp = TRUE
|
||||
edge = FALSE
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/spork/plastic
|
||||
default_material = "plastic"
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/spoon
|
||||
name = "spoon"
|
||||
desc = "It's a spoon. You can see your own upside-down face in it."
|
||||
icon_state = "spoon"
|
||||
attack_verb = list("attacked", "poked")
|
||||
edge = FALSE
|
||||
sharp = FALSE
|
||||
force_divisor = 0.1 //2 when wielded with weight 20 (steel)
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/spoon/plastic
|
||||
default_material = "plastic"
|
||||
|
||||
/*
|
||||
* Knives
|
||||
*/
|
||||
|
||||
/* From the time of Clowns. Commented out for posterity, and sanity.
|
||||
/obj/item/weapon/material/knife/attack(target as mob, mob/living/user as mob)
|
||||
if ((CLUMSY in user.mutations) && prob(50))
|
||||
to_chat(user, "<span class='warning'>You accidentally cut yourself with \the [src].</span>")
|
||||
user.take_organ_damage(20)
|
||||
return
|
||||
return ..()
|
||||
*/
|
||||
/obj/item/weapon/material/knife/plastic
|
||||
default_material = "plastic"
|
||||
|
||||
/*
|
||||
* Rolling Pins
|
||||
*/
|
||||
|
||||
/obj/item/weapon/material/kitchen/rollingpin
|
||||
name = "rolling pin"
|
||||
desc = "Used to knock out the Bartender."
|
||||
icon_state = "rolling_pin"
|
||||
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked")
|
||||
default_material = "wood"
|
||||
force_divisor = 0.7 // 10 when wielded with weight 15 (wood)
|
||||
dulled_divisor = 0.75 // Still a club
|
||||
thrown_force_divisor = 1 // as above
|
||||
drop_sound = 'sound/items/drop/wooden.ogg'
|
||||
pickup_sound = 'sound/items/pickup/wooden.ogg'
|
||||
|
||||
/obj/item/weapon/material/kitchen/rollingpin/attack(mob/living/M as mob, mob/living/user as mob)
|
||||
if ((CLUMSY in user.mutations) && prob(50))
|
||||
to_chat(user, "<span class='warning'>\The [src] slips out of your hand and hits your head.</span>")
|
||||
user.take_organ_damage(10)
|
||||
user.Paralyse(2)
|
||||
return
|
||||
return ..()
|
||||
/obj/item/weapon/material/kitchen
|
||||
icon = 'icons/obj/kitchen.dmi'
|
||||
|
||||
/*
|
||||
* Utensils
|
||||
*/
|
||||
/obj/item/weapon/material/kitchen/utensil
|
||||
drop_sound = 'sound/items/drop/knife.ogg'
|
||||
pickup_sound = 'sound/items/pickup/knife.ogg'
|
||||
w_class = ITEMSIZE_TINY
|
||||
thrown_force_divisor = 1
|
||||
origin_tech = list(TECH_MATERIAL = 1)
|
||||
attack_verb = list("attacked", "stabbed", "poked")
|
||||
sharp = TRUE
|
||||
edge = TRUE
|
||||
force_divisor = 0.1 // 6 when wielded with hardness 60 (steel)
|
||||
thrown_force_divisor = 0.25 // 5 when thrown with weight 20 (steel)
|
||||
var/scoop_volume = 5
|
||||
var/loaded // Name for currently loaded food object.
|
||||
var/loaded_color // Color for currently loaded food object.
|
||||
|
||||
var/list/food_inserted_micros
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/Initialize()
|
||||
. = ..()
|
||||
if (prob(60))
|
||||
src.pixel_y = rand(0, 4)
|
||||
create_reagents(scoop_volume)
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/Destroy()
|
||||
if(food_inserted_micros)
|
||||
for(var/mob/M in food_inserted_micros)
|
||||
M.dropInto(loc)
|
||||
food_inserted_micros -= M
|
||||
. = ..()
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/update_icon()
|
||||
. = ..()
|
||||
cut_overlays()
|
||||
if(loaded)
|
||||
var/image/I = new(icon, "loadedfood")
|
||||
I.color = loaded_color
|
||||
add_overlay(I)
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/proc/load_food(var/mob/user, var/obj/item/weapon/reagent_containers/food/snacks/loading)
|
||||
if (reagents.total_volume > 0)
|
||||
to_chat(user, SPAN_DANGER("There is already something on \the [src]."))
|
||||
return
|
||||
if (!loading?.reagents?.total_volume)
|
||||
to_chat(user, SPAN_NOTICE("Nothing to scoop up in \the [loading]!"))
|
||||
|
||||
|
||||
loaded = "\the [loading]"
|
||||
user.visible_message( \
|
||||
"<b>\The [user]</b> scoops up some of [loaded] with \the [src]!",
|
||||
SPAN_NOTICE("You scoop up some of [loaded] with \the [src]!")
|
||||
)
|
||||
loading.bitecount++
|
||||
loading.reagents.trans_to_obj(src, min(loading.reagents.total_volume, scoop_volume))
|
||||
loaded_color = loading.filling_color
|
||||
|
||||
if(loading.food_inserted_micros && loading.food_inserted_micros.len)
|
||||
if(!food_inserted_micros)
|
||||
food_inserted_micros = list()
|
||||
|
||||
for(var/mob/living/F in loading.food_inserted_micros)
|
||||
var/do_transfer = FALSE
|
||||
|
||||
if(!loading.reagents.total_volume)
|
||||
do_transfer = TRUE
|
||||
else
|
||||
var/transfer_chance = (loading.bitecount/(loading.bitecount + (loading.bitesize / loading.reagents.total_volume) + 1))*100
|
||||
if(prob(transfer_chance))
|
||||
do_transfer = TRUE
|
||||
|
||||
if(do_transfer)
|
||||
F.forceMove(src)
|
||||
loading.food_inserted_micros -= F
|
||||
src.food_inserted_micros += F
|
||||
|
||||
if (loading.reagents.total_volume <= 0)
|
||||
qdel(loading)
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
|
||||
if(!istype(M))
|
||||
return ..()
|
||||
|
||||
if(user.a_intent != I_HELP)
|
||||
if(user.zone_sel.selecting == BP_HEAD || user.zone_sel.selecting == O_EYES)
|
||||
if((CLUMSY in user.mutations) && prob(50))
|
||||
M = user
|
||||
return eyestab(M,user)
|
||||
else
|
||||
return ..()
|
||||
|
||||
if (loaded && reagents.total_volume > 0)
|
||||
reagents.trans_to_mob(M, reagents.total_volume, CHEM_INGEST)
|
||||
if(food_inserted_micros && food_inserted_micros.len)
|
||||
for(var/mob/living/F in food_inserted_micros)
|
||||
food_inserted_micros -= F
|
||||
if(!F.can_be_drop_prey || !F.food_vore)
|
||||
F.forceMove(get_turf(src))
|
||||
else
|
||||
F.forceMove(M.vore_selected)
|
||||
if(M == user)
|
||||
if(!M.can_eat(loaded))
|
||||
return
|
||||
M.visible_message("<b>\The [user]</b> eats some of [loaded] with \the [src].")
|
||||
else
|
||||
user.visible_message(SPAN_WARNING("\The [user] begins to feed \the [M]!"))
|
||||
if(!(M.can_force_feed(user, loaded) && do_mob(user, M, 5 SECONDS)))
|
||||
return
|
||||
M.visible_message("<b>\The [user]</b> feeds some of [loaded] to \the [M] with \the [src].")
|
||||
playsound(src,'sound/items/eatfood.ogg', rand(10,40), 1)
|
||||
loaded = null
|
||||
update_icon()
|
||||
return
|
||||
else
|
||||
to_chat(user, SPAN_WARNING("You don't have anything on \the [src].")) //if we have help intent and no food scooped up DON'T STAB OURSELVES WITH THE FORK
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/on_rag_wipe()
|
||||
. = ..()
|
||||
if(reagents.total_volume > 0)
|
||||
reagents.clear_reagents()
|
||||
cut_overlays()
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/container_resist(mob/living/M)
|
||||
if(food_inserted_micros)
|
||||
food_inserted_micros -= M
|
||||
M.forceMove(get_turf(src))
|
||||
to_chat(M, "<span class='warning'>You climb off of \the [src].</span>")
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/fork
|
||||
name = "fork"
|
||||
desc = "It's a fork. Sure is pointy."
|
||||
icon_state = "fork"
|
||||
sharp = TRUE
|
||||
edge = FALSE
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/fork/plastic
|
||||
default_material = "plastic"
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/foon
|
||||
name = "foon"
|
||||
desc = "It's a foon. The forgotten cousin of the spork."
|
||||
icon_state = "foon"
|
||||
sharp = TRUE
|
||||
edge = FALSE
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/foon/plastic
|
||||
default_material = "plastic"
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/spork
|
||||
name = "spork"
|
||||
desc = "It's a spork. The (un)holy merger of a spoon and fork."
|
||||
icon_state = "spork"
|
||||
sharp = TRUE
|
||||
edge = FALSE
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/spork/plastic
|
||||
default_material = "plastic"
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/spoon
|
||||
name = "spoon"
|
||||
desc = "It's a spoon. You can see your own upside-down face in it."
|
||||
icon_state = "spoon"
|
||||
attack_verb = list("attacked", "poked")
|
||||
edge = FALSE
|
||||
sharp = FALSE
|
||||
force_divisor = 0.1 //2 when wielded with weight 20 (steel)
|
||||
|
||||
/obj/item/weapon/material/kitchen/utensil/spoon/plastic
|
||||
default_material = "plastic"
|
||||
|
||||
/*
|
||||
* Knives
|
||||
*/
|
||||
|
||||
/* From the time of Clowns. Commented out for posterity, and sanity.
|
||||
/obj/item/weapon/material/knife/attack(target as mob, mob/living/user as mob)
|
||||
if ((CLUMSY in user.mutations) && prob(50))
|
||||
to_chat(user, "<span class='warning'>You accidentally cut yourself with \the [src].</span>")
|
||||
user.take_organ_damage(20)
|
||||
return
|
||||
return ..()
|
||||
*/
|
||||
/obj/item/weapon/material/knife/plastic
|
||||
default_material = "plastic"
|
||||
|
||||
/*
|
||||
* Rolling Pins
|
||||
*/
|
||||
|
||||
/obj/item/weapon/material/kitchen/rollingpin
|
||||
name = "rolling pin"
|
||||
desc = "Used to knock out the Bartender."
|
||||
icon_state = "rolling_pin"
|
||||
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked")
|
||||
default_material = "wood"
|
||||
force_divisor = 0.7 // 10 when wielded with weight 15 (wood)
|
||||
dulled_divisor = 0.75 // Still a club
|
||||
thrown_force_divisor = 1 // as above
|
||||
drop_sound = 'sound/items/drop/wooden.ogg'
|
||||
pickup_sound = 'sound/items/pickup/wooden.ogg'
|
||||
|
||||
/obj/item/weapon/material/kitchen/rollingpin/attack(mob/living/M as mob, mob/living/user as mob)
|
||||
if ((CLUMSY in user.mutations) && prob(50))
|
||||
to_chat(user, "<span class='warning'>\The [src] slips out of your hand and hits your head.</span>")
|
||||
user.take_organ_damage(10)
|
||||
user.Paralyse(2)
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -1,187 +1,187 @@
|
||||
/obj/item/weapon/material/butterfly
|
||||
name = "butterfly knife"
|
||||
desc = "A basic metal blade concealed in a lightweight plasteel grip. Small enough when folded to fit in a pocket."
|
||||
description_fluff = "This could be used to engrave messages on suitable surfaces if you really put your mind to it! Alt-click a floor or wall to engrave with it." //This way it's not a completely hidden, arcane art to engrave.
|
||||
icon_state = "butterflyknife"
|
||||
item_state = null
|
||||
hitsound = null
|
||||
var/active = 0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
attack_verb = list("patted", "tapped")
|
||||
force_divisor = 0.25 // 15 when wielded with hardness 60 (steel)
|
||||
thrown_force_divisor = 0.25 // 5 when thrown with weight 20 (steel)
|
||||
drop_sound = 'sound/items/drop/knife.ogg'
|
||||
pickup_sound = 'sound/items/pickup/knife.ogg'
|
||||
|
||||
/obj/item/weapon/material/butterfly/update_force()
|
||||
if(active)
|
||||
edge = TRUE
|
||||
sharp = TRUE
|
||||
..() //Updates force.
|
||||
throwforce = max(3,force-3)
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
icon_state += "_open"
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
else
|
||||
force = 3
|
||||
edge = FALSE
|
||||
sharp = FALSE
|
||||
hitsound = initial(hitsound)
|
||||
icon_state = initial(icon_state)
|
||||
w_class = initial(w_class)
|
||||
attack_verb = initial(attack_verb)
|
||||
|
||||
/obj/item/weapon/material/butterfly/switchblade
|
||||
name = "switchblade"
|
||||
desc = "A classic switchblade with gold engraving. Just holding it makes you feel like a gangster."
|
||||
icon_state = "switchblade"
|
||||
|
||||
/obj/item/weapon/material/butterfly/boxcutter
|
||||
name = "box cutter"
|
||||
desc = "A thin, inexpensive razor-blade knife designed to open cardboard boxes."
|
||||
icon_state = "boxcutter"
|
||||
force_divisor = 0.1 // 6 when wielded with hardness 60 (steel)
|
||||
thrown_force_divisor = 0.2 // 4 when thrown with weight 20 (steel)
|
||||
|
||||
/obj/item/weapon/material/butterfly/attack_self(mob/user)
|
||||
active = !active
|
||||
update_force()
|
||||
|
||||
if(user)
|
||||
if(active)
|
||||
to_chat(user, "<span class='notice'>You flip out \the [src].</span>")
|
||||
playsound(src, 'sound/weapons/flipblade.ogg', 15, 1)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>\The [src] can now be concealed.</span>")
|
||||
add_fingerprint(user)
|
||||
|
||||
/*
|
||||
* Kitchen knives
|
||||
*/
|
||||
/obj/item/weapon/material/knife
|
||||
name = "kitchen knife"
|
||||
icon = 'icons/obj/kitchen.dmi'
|
||||
icon_state = "knife"
|
||||
desc = "A general purpose Chef's Knife made by SpaceCook Incorporated. Guaranteed to stay sharp for years to come."
|
||||
description_fluff = "This could be used to engrave messages on suitable surfaces if you really put your mind to it! Alt-click a floor or wall to engrave with it." //This way it's not a completely hidden, arcane art to engrave.
|
||||
sharp = TRUE
|
||||
edge = TRUE
|
||||
force_divisor = 0.15 // 9 when wielded with hardness 60 (steel)
|
||||
matter = list(MAT_STEEL = 12000)
|
||||
origin_tech = list(TECH_MATERIAL = 1)
|
||||
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
drop_sound = 'sound/items/drop/knife.ogg'
|
||||
|
||||
// These no longer inherit from hatchets.
|
||||
/obj/item/weapon/material/knife/tacknife
|
||||
name = "tactical knife"
|
||||
desc = "You'd be killing loads of people if this was Medal of Valor: Heroes of Space."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "tacknife"
|
||||
item_state = "knife"
|
||||
force_divisor = 0.25 //15 when hardness 60 (steel)
|
||||
attack_verb = list("stabbed", "chopped", "cut")
|
||||
applies_material_colour = 1
|
||||
|
||||
/obj/item/weapon/material/knife/tacknife/combatknife
|
||||
name = "combat knife"
|
||||
desc = "If only you had a boot to put it in."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "tacknife2"
|
||||
item_state = "knife"
|
||||
force_divisor = 0.34 // 20 with hardness 60 (steel)
|
||||
thrown_force_divisor = 1.75 // 20 with weight 20 (steel)
|
||||
attack_verb = list("sliced", "stabbed", "chopped", "cut")
|
||||
applies_material_colour = 1
|
||||
|
||||
// Identical to the tactical knife but nowhere near as stabby.
|
||||
// Kind of like the toy esword compared to the real thing.
|
||||
/obj/item/weapon/material/knife/tacknife/boot
|
||||
name = "boot knife"
|
||||
desc = "A small fixed-blade knife for putting inside a boot."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "tacknife3"
|
||||
item_state = "knife"
|
||||
force_divisor = 0.15
|
||||
applies_material_colour = 0
|
||||
|
||||
/obj/item/weapon/material/knife/hook
|
||||
name = "meat hook"
|
||||
desc = "A sharp, metal hook what sticks into things."
|
||||
icon_state = "hook_knife"
|
||||
|
||||
/obj/item/weapon/material/knife/ritual
|
||||
name = "ritual knife"
|
||||
desc = "The unearthly energies that once powered this blade are now dormant."
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "render"
|
||||
applies_material_colour = 0
|
||||
|
||||
/obj/item/weapon/material/knife/table
|
||||
name = "table knife"
|
||||
icon = 'icons/obj/kitchen.dmi'
|
||||
icon_state = "knife_table"
|
||||
sharp = FALSE // blunted tip
|
||||
force_divisor = 0.1
|
||||
|
||||
/obj/item/weapon/material/knife/table/plastic
|
||||
default_material = "plastic"
|
||||
|
||||
/obj/item/weapon/material/knife/butch
|
||||
name = "butcher's cleaver"
|
||||
icon_state = "cleaver"
|
||||
desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products."
|
||||
force_divisor = 0.25 // 15 when wielded with hardness 60 (steel)
|
||||
attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
|
||||
/obj/item/weapon/material/knife/machete
|
||||
name = "machete"
|
||||
desc = "A sharp machete often found in survival kits."
|
||||
icon_state = "machete"
|
||||
force_divisor = 0.3 // 18 when hardness 60 (steel)
|
||||
attack_verb = list("slashed", "chopped", "gouged", "ripped", "cut")
|
||||
can_cleave = TRUE //Now hatchets inherit from the machete, and thus knives. Tables turned.
|
||||
slot_flags = SLOT_BELT
|
||||
default_material = "plasteel" //VOREStation Edit
|
||||
|
||||
/obj/item/weapon/material/knife/machete/cyborg
|
||||
name = "integrated machete"
|
||||
desc = "A sharp machete often found attached to robots."
|
||||
unbreakable = TRUE
|
||||
|
||||
/obj/item/weapon/material/knife/tacknife/survival
|
||||
name = "survival knife"
|
||||
desc = "A hunting grade survival knife."
|
||||
icon = 'icons/obj/kitchen.dmi'
|
||||
icon_state = "survivalknife"
|
||||
item_state = "knife"
|
||||
applies_material_colour = FALSE
|
||||
default_material = "plasteel" //VOREStation Edit
|
||||
toolspeed = 2 // Use a real axe if you want to chop logs.
|
||||
|
||||
/obj/item/weapon/material/knife/stone
|
||||
name = "stone blade"
|
||||
desc = "A crude blade made by chipping away at a piece of flint."
|
||||
icon = 'icons/obj/weapons_vr.dmi'
|
||||
icon_state = "stone_blade"
|
||||
applies_material_colour = FALSE
|
||||
fragile = TRUE
|
||||
dulled = TRUE
|
||||
edge = TRUE
|
||||
sharp = TRUE
|
||||
default_material = MAT_FLINT
|
||||
|
||||
/obj/item/weapon/material/knife/stone/wood
|
||||
name = "stone knife"
|
||||
desc = "A crude blade of flint with a wooden handle, secured with plant fibers twined into sturdy ropes. Useful for cutting, stabbing, slicing, and even shearing."
|
||||
icon_state = "stone_wood_knife"
|
||||
dulled = FALSE
|
||||
fragile = FALSE
|
||||
|
||||
/obj/item/weapon/material/knife/stone/bone
|
||||
name = "stone knife"
|
||||
desc = "A crude blade of flint with a bone handle, secured with plant fibers twined into sturdy ropes. Useful for cutting, stabbing, slicing, and even shearing."
|
||||
icon_state = "stone_bone_knife"
|
||||
dulled = FALSE
|
||||
fragile = FALSE
|
||||
/obj/item/weapon/material/butterfly
|
||||
name = "butterfly knife"
|
||||
desc = "A basic metal blade concealed in a lightweight plasteel grip. Small enough when folded to fit in a pocket."
|
||||
description_fluff = "This could be used to engrave messages on suitable surfaces if you really put your mind to it! Alt-click a floor or wall to engrave with it." //This way it's not a completely hidden, arcane art to engrave.
|
||||
icon_state = "butterflyknife"
|
||||
item_state = null
|
||||
hitsound = null
|
||||
var/active = 0
|
||||
w_class = ITEMSIZE_SMALL
|
||||
attack_verb = list("patted", "tapped")
|
||||
force_divisor = 0.25 // 15 when wielded with hardness 60 (steel)
|
||||
thrown_force_divisor = 0.25 // 5 when thrown with weight 20 (steel)
|
||||
drop_sound = 'sound/items/drop/knife.ogg'
|
||||
pickup_sound = 'sound/items/pickup/knife.ogg'
|
||||
|
||||
/obj/item/weapon/material/butterfly/update_force()
|
||||
if(active)
|
||||
edge = TRUE
|
||||
sharp = TRUE
|
||||
..() //Updates force.
|
||||
throwforce = max(3,force-3)
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
icon_state += "_open"
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
else
|
||||
force = 3
|
||||
edge = FALSE
|
||||
sharp = FALSE
|
||||
hitsound = initial(hitsound)
|
||||
icon_state = initial(icon_state)
|
||||
w_class = initial(w_class)
|
||||
attack_verb = initial(attack_verb)
|
||||
|
||||
/obj/item/weapon/material/butterfly/switchblade
|
||||
name = "switchblade"
|
||||
desc = "A classic switchblade with gold engraving. Just holding it makes you feel like a gangster."
|
||||
icon_state = "switchblade"
|
||||
|
||||
/obj/item/weapon/material/butterfly/boxcutter
|
||||
name = "box cutter"
|
||||
desc = "A thin, inexpensive razor-blade knife designed to open cardboard boxes."
|
||||
icon_state = "boxcutter"
|
||||
force_divisor = 0.1 // 6 when wielded with hardness 60 (steel)
|
||||
thrown_force_divisor = 0.2 // 4 when thrown with weight 20 (steel)
|
||||
|
||||
/obj/item/weapon/material/butterfly/attack_self(mob/user)
|
||||
active = !active
|
||||
update_force()
|
||||
|
||||
if(user)
|
||||
if(active)
|
||||
to_chat(user, "<span class='notice'>You flip out \the [src].</span>")
|
||||
playsound(src, 'sound/weapons/flipblade.ogg', 15, 1)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>\The [src] can now be concealed.</span>")
|
||||
add_fingerprint(user)
|
||||
|
||||
/*
|
||||
* Kitchen knives
|
||||
*/
|
||||
/obj/item/weapon/material/knife
|
||||
name = "kitchen knife"
|
||||
icon = 'icons/obj/kitchen.dmi'
|
||||
icon_state = "knife"
|
||||
desc = "A general purpose Chef's Knife made by SpaceCook Incorporated. Guaranteed to stay sharp for years to come."
|
||||
description_fluff = "This could be used to engrave messages on suitable surfaces if you really put your mind to it! Alt-click a floor or wall to engrave with it." //This way it's not a completely hidden, arcane art to engrave.
|
||||
sharp = TRUE
|
||||
edge = TRUE
|
||||
force_divisor = 0.15 // 9 when wielded with hardness 60 (steel)
|
||||
matter = list(MAT_STEEL = 12000)
|
||||
origin_tech = list(TECH_MATERIAL = 1)
|
||||
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
drop_sound = 'sound/items/drop/knife.ogg'
|
||||
|
||||
// These no longer inherit from hatchets.
|
||||
/obj/item/weapon/material/knife/tacknife
|
||||
name = "tactical knife"
|
||||
desc = "You'd be killing loads of people if this was Medal of Valor: Heroes of Space."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "tacknife"
|
||||
item_state = "knife"
|
||||
force_divisor = 0.25 //15 when hardness 60 (steel)
|
||||
attack_verb = list("stabbed", "chopped", "cut")
|
||||
applies_material_colour = 1
|
||||
|
||||
/obj/item/weapon/material/knife/tacknife/combatknife
|
||||
name = "combat knife"
|
||||
desc = "If only you had a boot to put it in."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "tacknife2"
|
||||
item_state = "knife"
|
||||
force_divisor = 0.34 // 20 with hardness 60 (steel)
|
||||
thrown_force_divisor = 1.75 // 20 with weight 20 (steel)
|
||||
attack_verb = list("sliced", "stabbed", "chopped", "cut")
|
||||
applies_material_colour = 1
|
||||
|
||||
// Identical to the tactical knife but nowhere near as stabby.
|
||||
// Kind of like the toy esword compared to the real thing.
|
||||
/obj/item/weapon/material/knife/tacknife/boot
|
||||
name = "boot knife"
|
||||
desc = "A small fixed-blade knife for putting inside a boot."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "tacknife3"
|
||||
item_state = "knife"
|
||||
force_divisor = 0.15
|
||||
applies_material_colour = 0
|
||||
|
||||
/obj/item/weapon/material/knife/hook
|
||||
name = "meat hook"
|
||||
desc = "A sharp, metal hook what sticks into things."
|
||||
icon_state = "hook_knife"
|
||||
|
||||
/obj/item/weapon/material/knife/ritual
|
||||
name = "ritual knife"
|
||||
desc = "The unearthly energies that once powered this blade are now dormant."
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "render"
|
||||
applies_material_colour = 0
|
||||
|
||||
/obj/item/weapon/material/knife/table
|
||||
name = "table knife"
|
||||
icon = 'icons/obj/kitchen.dmi'
|
||||
icon_state = "knife_table"
|
||||
sharp = FALSE // blunted tip
|
||||
force_divisor = 0.1
|
||||
|
||||
/obj/item/weapon/material/knife/table/plastic
|
||||
default_material = "plastic"
|
||||
|
||||
/obj/item/weapon/material/knife/butch
|
||||
name = "butcher's cleaver"
|
||||
icon_state = "cleaver"
|
||||
desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products."
|
||||
force_divisor = 0.25 // 15 when wielded with hardness 60 (steel)
|
||||
attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
|
||||
/obj/item/weapon/material/knife/machete
|
||||
name = "machete"
|
||||
desc = "A sharp machete often found in survival kits."
|
||||
icon_state = "machete"
|
||||
force_divisor = 0.3 // 18 when hardness 60 (steel)
|
||||
attack_verb = list("slashed", "chopped", "gouged", "ripped", "cut")
|
||||
can_cleave = TRUE //Now hatchets inherit from the machete, and thus knives. Tables turned.
|
||||
slot_flags = SLOT_BELT
|
||||
default_material = "plasteel" //VOREStation Edit
|
||||
|
||||
/obj/item/weapon/material/knife/machete/cyborg
|
||||
name = "integrated machete"
|
||||
desc = "A sharp machete often found attached to robots."
|
||||
unbreakable = TRUE
|
||||
|
||||
/obj/item/weapon/material/knife/tacknife/survival
|
||||
name = "survival knife"
|
||||
desc = "A hunting grade survival knife."
|
||||
icon = 'icons/obj/kitchen.dmi'
|
||||
icon_state = "survivalknife"
|
||||
item_state = "knife"
|
||||
applies_material_colour = FALSE
|
||||
default_material = "plasteel" //VOREStation Edit
|
||||
toolspeed = 2 // Use a real axe if you want to chop logs.
|
||||
|
||||
/obj/item/weapon/material/knife/stone
|
||||
name = "stone blade"
|
||||
desc = "A crude blade made by chipping away at a piece of flint."
|
||||
icon = 'icons/obj/weapons_vr.dmi'
|
||||
icon_state = "stone_blade"
|
||||
applies_material_colour = FALSE
|
||||
fragile = TRUE
|
||||
dulled = TRUE
|
||||
edge = TRUE
|
||||
sharp = TRUE
|
||||
default_material = MAT_FLINT
|
||||
|
||||
/obj/item/weapon/material/knife/stone/wood
|
||||
name = "stone knife"
|
||||
desc = "A crude blade of flint with a wooden handle, secured with plant fibers twined into sturdy ropes. Useful for cutting, stabbing, slicing, and even shearing."
|
||||
icon_state = "stone_wood_knife"
|
||||
dulled = FALSE
|
||||
fragile = FALSE
|
||||
|
||||
/obj/item/weapon/material/knife/stone/bone
|
||||
name = "stone knife"
|
||||
desc = "A crude blade of flint with a bone handle, secured with plant fibers twined into sturdy ropes. Useful for cutting, stabbing, slicing, and even shearing."
|
||||
icon_state = "stone_bone_knife"
|
||||
dulled = FALSE
|
||||
fragile = FALSE
|
||||
|
||||
@@ -1,182 +1,182 @@
|
||||
// SEE code/modules/materials/materials.dm FOR DETAILS ON INHERITED DATUM.
|
||||
// This class of weapons takes force and appearance data from a material datum.
|
||||
// They are also fragile based on material data and many can break/smash apart.
|
||||
/obj/item/weapon/material
|
||||
health = 10
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
gender = NEUTER
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
sharp = FALSE
|
||||
edge = FALSE
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_material.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_material.dmi',
|
||||
)
|
||||
|
||||
var/applies_material_colour = 1
|
||||
var/unbreakable = 0 //Doesn't lose health
|
||||
var/fragile = 0 //Shatters when it dies
|
||||
var/dulled = 0 //Has gone dull
|
||||
var/can_dull = 1 //Can it go dull?
|
||||
var/force_divisor = 0.5
|
||||
var/thrown_force_divisor = 0.5
|
||||
var/dulled_divisor = 0.5 //Just drops the damage by half
|
||||
var/default_material = MAT_STEEL
|
||||
var/datum/material/material
|
||||
var/drops_debris = 1
|
||||
|
||||
/obj/item/weapon/material/New(var/newloc, var/material_key)
|
||||
..(newloc)
|
||||
if(!material_key)
|
||||
material_key = default_material
|
||||
set_material(material_key)
|
||||
if(!material)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
matter = material.get_matter()
|
||||
if(matter.len)
|
||||
for(var/material_type in matter)
|
||||
if(!isnull(matter[material_type]))
|
||||
matter[material_type] *= force_divisor // May require a new var instead.
|
||||
|
||||
if(!(material.conductive))
|
||||
src.flags |= NOCONDUCT
|
||||
|
||||
/obj/item/weapon/material/get_material()
|
||||
return material
|
||||
|
||||
/obj/item/weapon/material/proc/update_force()
|
||||
if(edge || sharp)
|
||||
force = material.get_edge_damage()
|
||||
else
|
||||
force = material.get_blunt_damage()
|
||||
force = round(force*force_divisor)
|
||||
if(dulled)
|
||||
force = round(force*dulled_divisor)
|
||||
throwforce = round(material.get_blunt_damage()*thrown_force_divisor)
|
||||
//spawn(1)
|
||||
// to_world("[src] has force [force] and throwforce [throwforce] when made from default material [material.name]")
|
||||
|
||||
/obj/item/weapon/material/proc/set_material(var/new_material)
|
||||
material = get_material_by_name(new_material)
|
||||
if(!material)
|
||||
qdel(src)
|
||||
else
|
||||
name = "[material.display_name] [initial(name)]"
|
||||
health = round(material.integrity/10)
|
||||
if(applies_material_colour)
|
||||
color = material.icon_colour
|
||||
if(material.products_need_process())
|
||||
START_PROCESSING(SSobj, src)
|
||||
update_force()
|
||||
|
||||
/obj/item/weapon/material/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/weapon/material/apply_hit_effect()
|
||||
..()
|
||||
if(!unbreakable)
|
||||
if(material.is_brittle())
|
||||
health = 0
|
||||
else if(!prob(material.hardness))
|
||||
health--
|
||||
check_health()
|
||||
|
||||
/obj/item/weapon/material/attackby(obj/item/weapon/W, mob/user)
|
||||
if(istype(W, /obj/item/weapon/whetstone))
|
||||
var/obj/item/weapon/whetstone/whet = W
|
||||
repair(whet.repair_amount, whet.repair_time, user)
|
||||
if(istype(W, /obj/item/weapon/material/sharpeningkit))
|
||||
var/obj/item/weapon/material/sharpeningkit/SK = W
|
||||
repair(SK.repair_amount, SK.repair_time, user)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/material/proc/check_health(var/consumed)
|
||||
if(health<=0)
|
||||
health = 0
|
||||
|
||||
if(fragile)
|
||||
shatter(consumed)
|
||||
else if(!dulled && can_dull)
|
||||
dull()
|
||||
|
||||
/obj/item/weapon/material/proc/shatter(var/consumed)
|
||||
var/turf/T = get_turf(src)
|
||||
T.visible_message("<span class='danger'>\The [src] [material.destruction_desc]!</span>")
|
||||
if(istype(loc, /mob/living))
|
||||
var/mob/living/M = loc
|
||||
M.drop_from_inventory(src)
|
||||
playsound(src, "shatter", 70, 1)
|
||||
if(!consumed && drops_debris) material.place_shard(T)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/material/proc/dull()
|
||||
var/turf/T = get_turf(src)
|
||||
T.visible_message("<span class='danger'>\The [src] goes dull!</span>")
|
||||
playsound(src, "shatter", 70, 1)
|
||||
dulled = 1
|
||||
if(is_sharp() || has_edge())
|
||||
sharp = FALSE
|
||||
edge = FALSE
|
||||
|
||||
/obj/item/weapon/material/proc/repair(var/repair_amount, var/repair_time, mob/living/user)
|
||||
if(!fragile)
|
||||
if(health < initial(health))
|
||||
user.visible_message("[user] begins repairing \the [src].", "You begin repairing \the [src].")
|
||||
if(do_after(user, repair_time))
|
||||
user.visible_message("[user] has finished repairing \the [src]", "You finish repairing \the [src].")
|
||||
health = min(health + repair_amount, initial(health))
|
||||
dulled = 0
|
||||
sharp = initial(sharp)
|
||||
edge = initial(edge)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] doesn't need repairs.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You can't repair \the [src].</span>")
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/proc/sharpen(var/material, var/sharpen_time, var/kit, mob/living/M)
|
||||
if(!fragile && src.material.can_sharpen)
|
||||
if(health < initial(health))
|
||||
to_chat(M, "You should repair [src] first. Try using [kit] on it.")
|
||||
return FALSE
|
||||
M.visible_message("[M] begins to replace parts of [src] with [kit].", "You begin to replace parts of [src] with [kit].")
|
||||
if(do_after(usr, sharpen_time))
|
||||
M.visible_message("[M] has finished replacing parts of [src].", "You finish replacing parts of [src].")
|
||||
src.set_material(material)
|
||||
return TRUE
|
||||
else
|
||||
to_chat(M, "<span class = 'warning'>You can't sharpen and re-edge [src].</span>")
|
||||
return FALSE
|
||||
|
||||
/*
|
||||
Commenting this out pending rebalancing of radiation based on small objects.
|
||||
/obj/item/weapon/material/process()
|
||||
if(!material.radioactivity)
|
||||
return
|
||||
for(var/mob/living/L in range(1,src))
|
||||
L.apply_effect(round(material.radioactivity/30),IRRADIATE,0)
|
||||
*/
|
||||
|
||||
/*
|
||||
// Commenting this out while fires are so spectacularly lethal, as I can't seem to get this balanced appropriately.
|
||||
/obj/item/weapon/material/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
TemperatureAct(exposed_temperature)
|
||||
|
||||
// This might need adjustment. Will work that out later.
|
||||
/obj/item/weapon/material/proc/TemperatureAct(temperature)
|
||||
health -= material.combustion_effect(get_turf(src), temperature, 0.1)
|
||||
check_health(1)
|
||||
|
||||
/obj/item/weapon/material/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W,/obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/WT = W
|
||||
if(material.ignition_point && WT.remove_fuel(0, user))
|
||||
TemperatureAct(150)
|
||||
else
|
||||
return ..()
|
||||
*/
|
||||
// SEE code/modules/materials/materials.dm FOR DETAILS ON INHERITED DATUM.
|
||||
// This class of weapons takes force and appearance data from a material datum.
|
||||
// They are also fragile based on material data and many can break/smash apart.
|
||||
/obj/item/weapon/material
|
||||
health = 10
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
gender = NEUTER
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
sharp = FALSE
|
||||
edge = FALSE
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_material.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_material.dmi',
|
||||
)
|
||||
|
||||
var/applies_material_colour = 1
|
||||
var/unbreakable = 0 //Doesn't lose health
|
||||
var/fragile = 0 //Shatters when it dies
|
||||
var/dulled = 0 //Has gone dull
|
||||
var/can_dull = 1 //Can it go dull?
|
||||
var/force_divisor = 0.5
|
||||
var/thrown_force_divisor = 0.5
|
||||
var/dulled_divisor = 0.5 //Just drops the damage by half
|
||||
var/default_material = MAT_STEEL
|
||||
var/datum/material/material
|
||||
var/drops_debris = 1
|
||||
|
||||
/obj/item/weapon/material/New(var/newloc, var/material_key)
|
||||
..(newloc)
|
||||
if(!material_key)
|
||||
material_key = default_material
|
||||
set_material(material_key)
|
||||
if(!material)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
matter = material.get_matter()
|
||||
if(matter.len)
|
||||
for(var/material_type in matter)
|
||||
if(!isnull(matter[material_type]))
|
||||
matter[material_type] *= force_divisor // May require a new var instead.
|
||||
|
||||
if(!(material.conductive))
|
||||
src.flags |= NOCONDUCT
|
||||
|
||||
/obj/item/weapon/material/get_material()
|
||||
return material
|
||||
|
||||
/obj/item/weapon/material/proc/update_force()
|
||||
if(edge || sharp)
|
||||
force = material.get_edge_damage()
|
||||
else
|
||||
force = material.get_blunt_damage()
|
||||
force = round(force*force_divisor)
|
||||
if(dulled)
|
||||
force = round(force*dulled_divisor)
|
||||
throwforce = round(material.get_blunt_damage()*thrown_force_divisor)
|
||||
//spawn(1)
|
||||
// to_world("[src] has force [force] and throwforce [throwforce] when made from default material [material.name]")
|
||||
|
||||
/obj/item/weapon/material/proc/set_material(var/new_material)
|
||||
material = get_material_by_name(new_material)
|
||||
if(!material)
|
||||
qdel(src)
|
||||
else
|
||||
name = "[material.display_name] [initial(name)]"
|
||||
health = round(material.integrity/10)
|
||||
if(applies_material_colour)
|
||||
color = material.icon_colour
|
||||
if(material.products_need_process())
|
||||
START_PROCESSING(SSobj, src)
|
||||
update_force()
|
||||
|
||||
/obj/item/weapon/material/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/weapon/material/apply_hit_effect()
|
||||
..()
|
||||
if(!unbreakable)
|
||||
if(material.is_brittle())
|
||||
health = 0
|
||||
else if(!prob(material.hardness))
|
||||
health--
|
||||
check_health()
|
||||
|
||||
/obj/item/weapon/material/attackby(obj/item/weapon/W, mob/user)
|
||||
if(istype(W, /obj/item/weapon/whetstone))
|
||||
var/obj/item/weapon/whetstone/whet = W
|
||||
repair(whet.repair_amount, whet.repair_time, user)
|
||||
if(istype(W, /obj/item/weapon/material/sharpeningkit))
|
||||
var/obj/item/weapon/material/sharpeningkit/SK = W
|
||||
repair(SK.repair_amount, SK.repair_time, user)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/material/proc/check_health(var/consumed)
|
||||
if(health<=0)
|
||||
health = 0
|
||||
|
||||
if(fragile)
|
||||
shatter(consumed)
|
||||
else if(!dulled && can_dull)
|
||||
dull()
|
||||
|
||||
/obj/item/weapon/material/proc/shatter(var/consumed)
|
||||
var/turf/T = get_turf(src)
|
||||
T.visible_message("<span class='danger'>\The [src] [material.destruction_desc]!</span>")
|
||||
if(istype(loc, /mob/living))
|
||||
var/mob/living/M = loc
|
||||
M.drop_from_inventory(src)
|
||||
playsound(src, "shatter", 70, 1)
|
||||
if(!consumed && drops_debris) material.place_shard(T)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/material/proc/dull()
|
||||
var/turf/T = get_turf(src)
|
||||
T.visible_message("<span class='danger'>\The [src] goes dull!</span>")
|
||||
playsound(src, "shatter", 70, 1)
|
||||
dulled = 1
|
||||
if(is_sharp() || has_edge())
|
||||
sharp = FALSE
|
||||
edge = FALSE
|
||||
|
||||
/obj/item/weapon/material/proc/repair(var/repair_amount, var/repair_time, mob/living/user)
|
||||
if(!fragile)
|
||||
if(health < initial(health))
|
||||
user.visible_message("[user] begins repairing \the [src].", "You begin repairing \the [src].")
|
||||
if(do_after(user, repair_time))
|
||||
user.visible_message("[user] has finished repairing \the [src]", "You finish repairing \the [src].")
|
||||
health = min(health + repair_amount, initial(health))
|
||||
dulled = 0
|
||||
sharp = initial(sharp)
|
||||
edge = initial(edge)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] doesn't need repairs.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You can't repair \the [src].</span>")
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/proc/sharpen(var/material, var/sharpen_time, var/kit, mob/living/M)
|
||||
if(!fragile && src.material.can_sharpen)
|
||||
if(health < initial(health))
|
||||
to_chat(M, "You should repair [src] first. Try using [kit] on it.")
|
||||
return FALSE
|
||||
M.visible_message("[M] begins to replace parts of [src] with [kit].", "You begin to replace parts of [src] with [kit].")
|
||||
if(do_after(usr, sharpen_time))
|
||||
M.visible_message("[M] has finished replacing parts of [src].", "You finish replacing parts of [src].")
|
||||
src.set_material(material)
|
||||
return TRUE
|
||||
else
|
||||
to_chat(M, "<span class = 'warning'>You can't sharpen and re-edge [src].</span>")
|
||||
return FALSE
|
||||
|
||||
/*
|
||||
Commenting this out pending rebalancing of radiation based on small objects.
|
||||
/obj/item/weapon/material/process()
|
||||
if(!material.radioactivity)
|
||||
return
|
||||
for(var/mob/living/L in range(1,src))
|
||||
L.apply_effect(round(material.radioactivity/30),IRRADIATE,0)
|
||||
*/
|
||||
|
||||
/*
|
||||
// Commenting this out while fires are so spectacularly lethal, as I can't seem to get this balanced appropriately.
|
||||
/obj/item/weapon/material/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
TemperatureAct(exposed_temperature)
|
||||
|
||||
// This might need adjustment. Will work that out later.
|
||||
/obj/item/weapon/material/proc/TemperatureAct(temperature)
|
||||
health -= material.combustion_effect(get_turf(src), temperature, 0.1)
|
||||
check_health(1)
|
||||
|
||||
/obj/item/weapon/material/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W,/obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/WT = W
|
||||
if(material.ignition_point && WT.remove_fuel(0, user))
|
||||
TemperatureAct(150)
|
||||
else
|
||||
return ..()
|
||||
*/
|
||||
|
||||
@@ -1,228 +1,228 @@
|
||||
/obj/item/weapon/material/harpoon
|
||||
name = "harpoon"
|
||||
sharp = TRUE
|
||||
edge = FALSE
|
||||
desc = "Tharr she blows!"
|
||||
icon_state = "harpoon"
|
||||
item_state = "harpoon"
|
||||
force_divisor = 0.3 // 18 with hardness 60 (steel)
|
||||
attack_verb = list("jabbed","stabbed","ripped")
|
||||
|
||||
/obj/item/weapon/material/knife/machete/hatchet
|
||||
name = "hatchet"
|
||||
desc = "A very sharp axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "hatchet"
|
||||
force_divisor = 0.2 // 12 with hardness 60 (steel)
|
||||
thrown_force_divisor = 0.75 // 15 with weight 20 (steel)
|
||||
w_class = ITEMSIZE_SMALL
|
||||
sharp = TRUE
|
||||
edge = TRUE
|
||||
origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 1)
|
||||
attack_verb = list("chopped", "torn", "cut")
|
||||
applies_material_colour = 0
|
||||
drop_sound = 'sound/items/drop/axe.ogg'
|
||||
pickup_sound = 'sound/items/pickup/axe.ogg'
|
||||
/* VOREStation Removal - We have one already
|
||||
/obj/item/weapon/material/knife/machete/hatchet/stone
|
||||
name = "sharp rock"
|
||||
desc = "The secret is to bang the rocks together, guys."
|
||||
force_divisor = 0.2
|
||||
icon_state = "rock"
|
||||
item_state = "rock"
|
||||
attack_verb = list("chopped", "torn", "cut")
|
||||
|
||||
/obj/item/weapon/material/knife/machete/hatchet/stone/set_material(var/new_material)
|
||||
var/old_name = name
|
||||
. = ..()
|
||||
name = old_name
|
||||
*/
|
||||
/obj/item/weapon/material/knife/machete/hatchet/unathiknife
|
||||
name = "duelling knife"
|
||||
desc = "A length of leather-bound wood studded with razor-sharp teeth. How crude."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "unathiknife"
|
||||
attack_verb = list("ripped", "torn", "cut")
|
||||
can_cleave = FALSE
|
||||
var/hits = 0
|
||||
|
||||
/obj/item/weapon/material/knife/machete/hatchet/unathiknife/attack(mob/M as mob, mob/user as mob)
|
||||
if(hits > 0)
|
||||
return
|
||||
var/obj/item/I = user.get_inactive_hand()
|
||||
if(istype(I, /obj/item/weapon/material/knife/machete/hatchet/unathiknife))
|
||||
hits ++
|
||||
var/obj/item/weapon/W = I
|
||||
W.attack(M, user)
|
||||
W.afterattack(M, user)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/material/knife/machete/hatchet/unathiknife/afterattack(mob/M as mob, mob/user as mob)
|
||||
hits = initial(hits)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/material/minihoe // -- Numbers
|
||||
name = "mini hoe"
|
||||
desc = "It's used for removing weeds or scratching your back."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "hoe"
|
||||
force_divisor = 0.25 // 5 with weight 20 (steel)
|
||||
thrown_force_divisor = 0.25 // as above
|
||||
dulled_divisor = 0.75 //Still metal on a long pole
|
||||
w_class = ITEMSIZE_SMALL
|
||||
attack_verb = list("slashed", "sliced", "cut", "clawed")
|
||||
|
||||
/obj/item/weapon/material/snow/snowball
|
||||
name = "loose packed snowball"
|
||||
desc = "A fun snowball. Throw it at your friends!"
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "snowball"
|
||||
default_material = MAT_SNOW
|
||||
health = 1
|
||||
fragile = 1
|
||||
force_divisor = 0.01
|
||||
thrown_force_divisor = 0.10
|
||||
w_class = ITEMSIZE_SMALL
|
||||
attack_verb = list("mushed", "splatted", "splooshed", "splushed") // Words that totally exist.
|
||||
|
||||
/obj/item/weapon/material/snow/snowball/attack_self(mob/user as mob)
|
||||
if(user.a_intent == I_HURT)
|
||||
to_chat(user, SPAN_NOTICE("You smash the snowball in your hand."))
|
||||
var/atom/S = new /obj/item/stack/material/snow(user.loc)
|
||||
qdel(src)
|
||||
user.put_in_hands(S)
|
||||
else
|
||||
to_chat(user, SPAN_NOTICE("You start compacting the snowball."))
|
||||
if(do_after(user, 2 SECONDS))
|
||||
var/atom/S = new /obj/item/weapon/material/snow/snowball/reinforced(user.loc)
|
||||
qdel(src)
|
||||
user.put_in_hands(S)
|
||||
|
||||
/obj/item/weapon/material/snow/snowball/reinforced
|
||||
name = "snowball"
|
||||
desc = "A well-formed and fun snowball. It looks kind of dangerous."
|
||||
//icon_state = "reinf-snowball"
|
||||
force_divisor = 0.20
|
||||
thrown_force_divisor = 0.25
|
||||
|
||||
/obj/item/weapon/material/whip
|
||||
name = "whip"
|
||||
desc = "A tool used to discipline animals, or look cool. Mostly the latter."
|
||||
description_info = "Help - Standard attack, no modifiers.<br>\
|
||||
Disarm - Disarming strike. Attempts to disarm the target at range, similar to an unarmed disarm. Additionally, will force the target (if possible) to move away from you.<br>\
|
||||
Grab - Grappling strike. Attempts to pull the target toward you. This can also move objects.<br>\
|
||||
Harm - A standard strike with a small chance to disarm."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "whip"
|
||||
item_state = "chain"
|
||||
default_material = MAT_LEATHER
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
origin_tech = list(TECH_COMBAT = 2)
|
||||
attack_verb = list("flogged", "whipped", "lashed", "disciplined")
|
||||
force_divisor = 0.15
|
||||
thrown_force_divisor = 0.25
|
||||
reach = 2
|
||||
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_melee.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
|
||||
)
|
||||
|
||||
/obj/item/weapon/material/whip/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity)
|
||||
..()
|
||||
|
||||
if(!proximity)
|
||||
return
|
||||
|
||||
if(istype(A, /atom/movable))
|
||||
var/atom/movable/AM = A
|
||||
if(AM.anchored)
|
||||
to_chat(user, "<span class='notice'>\The [AM] won't budge.</span>")
|
||||
return
|
||||
|
||||
else
|
||||
if(!istype(AM, /obj/item))
|
||||
user.visible_message("<span class='warning'>\The [AM] is pulled along by \the [src]!</span>")
|
||||
AM.Move(get_step(AM, get_dir(AM, src)))
|
||||
return
|
||||
|
||||
else
|
||||
user.visible_message("<span class='warning'>\The [AM] is snatched by \the [src]!</span>")
|
||||
AM.throw_at(user, reach, 0.1, user)
|
||||
|
||||
/obj/item/weapon/material/whip/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
|
||||
if(user.a_intent)
|
||||
switch(user.a_intent)
|
||||
if(I_HURT)
|
||||
if(prob(10) && istype(target, /mob/living/carbon/human) && (user.zone_sel in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND)))
|
||||
to_chat(target, "<span class='warning'>\The [src] rips at your hands!</span>")
|
||||
ranged_disarm(target)
|
||||
if(I_DISARM)
|
||||
if(prob(min(90, force * 3)) && istype(target, /mob/living/carbon/human) && (user.zone_sel in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND)))
|
||||
ranged_disarm(target)
|
||||
else
|
||||
target.visible_message("<span class='danger'>\The [src] sends \the [target] stumbling away.</span>")
|
||||
target.Move(get_step(target,get_dir(user,target)))
|
||||
if(I_GRAB)
|
||||
var/turf/STurf = get_turf(target)
|
||||
spawn(2)
|
||||
playsound(STurf, 'sound/effects/snap.ogg', 60, 1)
|
||||
target.visible_message("<span class='critical'>\The [src] yanks \the [target] towards \the [user]!</span>")
|
||||
target.throw_at(get_turf(get_step(user,get_dir(user,target))), 2, 1, src)
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/weapon/material/whip/proc/ranged_disarm(var/mob/living/carbon/human/H, var/mob/living/user)
|
||||
if(istype(H))
|
||||
var/list/holding = list(H.get_active_hand() = 40, H.get_inactive_hand() = 20)
|
||||
|
||||
if(user.zone_sel in list(BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND))
|
||||
for(var/obj/item/weapon/gun/W in holding)
|
||||
if(W && prob(holding[W]))
|
||||
var/list/turfs = list()
|
||||
for(var/turf/T in view())
|
||||
turfs += T
|
||||
if(turfs.len)
|
||||
var/turf/target = pick(turfs)
|
||||
visible_message("<span class='danger'>[H]'s [W] goes off due to \the [src]!</span>")
|
||||
return W.afterattack(target,H)
|
||||
|
||||
if(!(H.species.flags & NO_SLIP) && prob(10) && (user.zone_sel in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT)))
|
||||
var/armor_check = H.run_armor_check(user.zone_sel, "melee")
|
||||
H.apply_effect(3, WEAKEN, armor_check)
|
||||
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
if(armor_check < 60)
|
||||
visible_message("<span class='danger'>\The [src] has tripped [H]!</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>\The [src] attempted to trip [H]!</span>")
|
||||
return
|
||||
|
||||
else
|
||||
if(H.break_all_grabs(user))
|
||||
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
return
|
||||
|
||||
if(user.zone_sel in list(BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND))
|
||||
for(var/obj/item/I in holding)
|
||||
if(I && prob(holding[I]))
|
||||
H.drop_from_inventory(I)
|
||||
visible_message("<span class='danger'>\The [src] has disarmed [H]!</span>")
|
||||
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/whip/attack_self(mob/user)
|
||||
user.visible_message("<span class='warning'>\The [user] cracks \the [src]!</span>")
|
||||
playsound(src, 'sound/effects/snap.ogg', 50, 1)
|
||||
|
||||
/obj/item/weapon/material/knife/machete/hatchet/stone
|
||||
name = "hatchet"
|
||||
desc = "A very sharp axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."
|
||||
icon = 'icons/obj/weapons_vr.dmi'
|
||||
icon_state = "stone_wood_axe"
|
||||
default_material = MAT_FLINT
|
||||
origin_tech = list()
|
||||
applies_material_colour = FALSE
|
||||
|
||||
/obj/item/weapon/material/knife/machete/hatchet/stone/bone
|
||||
icon_state = "stone_bone_axe"
|
||||
/obj/item/weapon/material/harpoon
|
||||
name = "harpoon"
|
||||
sharp = TRUE
|
||||
edge = FALSE
|
||||
desc = "Tharr she blows!"
|
||||
icon_state = "harpoon"
|
||||
item_state = "harpoon"
|
||||
force_divisor = 0.3 // 18 with hardness 60 (steel)
|
||||
attack_verb = list("jabbed","stabbed","ripped")
|
||||
|
||||
/obj/item/weapon/material/knife/machete/hatchet
|
||||
name = "hatchet"
|
||||
desc = "A very sharp axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "hatchet"
|
||||
force_divisor = 0.2 // 12 with hardness 60 (steel)
|
||||
thrown_force_divisor = 0.75 // 15 with weight 20 (steel)
|
||||
w_class = ITEMSIZE_SMALL
|
||||
sharp = TRUE
|
||||
edge = TRUE
|
||||
origin_tech = list(TECH_MATERIAL = 2, TECH_COMBAT = 1)
|
||||
attack_verb = list("chopped", "torn", "cut")
|
||||
applies_material_colour = 0
|
||||
drop_sound = 'sound/items/drop/axe.ogg'
|
||||
pickup_sound = 'sound/items/pickup/axe.ogg'
|
||||
/* VOREStation Removal - We have one already
|
||||
/obj/item/weapon/material/knife/machete/hatchet/stone
|
||||
name = "sharp rock"
|
||||
desc = "The secret is to bang the rocks together, guys."
|
||||
force_divisor = 0.2
|
||||
icon_state = "rock"
|
||||
item_state = "rock"
|
||||
attack_verb = list("chopped", "torn", "cut")
|
||||
|
||||
/obj/item/weapon/material/knife/machete/hatchet/stone/set_material(var/new_material)
|
||||
var/old_name = name
|
||||
. = ..()
|
||||
name = old_name
|
||||
*/
|
||||
/obj/item/weapon/material/knife/machete/hatchet/unathiknife
|
||||
name = "duelling knife"
|
||||
desc = "A length of leather-bound wood studded with razor-sharp teeth. How crude."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "unathiknife"
|
||||
attack_verb = list("ripped", "torn", "cut")
|
||||
can_cleave = FALSE
|
||||
var/hits = 0
|
||||
|
||||
/obj/item/weapon/material/knife/machete/hatchet/unathiknife/attack(mob/M as mob, mob/user as mob)
|
||||
if(hits > 0)
|
||||
return
|
||||
var/obj/item/I = user.get_inactive_hand()
|
||||
if(istype(I, /obj/item/weapon/material/knife/machete/hatchet/unathiknife))
|
||||
hits ++
|
||||
var/obj/item/weapon/W = I
|
||||
W.attack(M, user)
|
||||
W.afterattack(M, user)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/material/knife/machete/hatchet/unathiknife/afterattack(mob/M as mob, mob/user as mob)
|
||||
hits = initial(hits)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/material/minihoe // -- Numbers
|
||||
name = "mini hoe"
|
||||
desc = "It's used for removing weeds or scratching your back."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "hoe"
|
||||
force_divisor = 0.25 // 5 with weight 20 (steel)
|
||||
thrown_force_divisor = 0.25 // as above
|
||||
dulled_divisor = 0.75 //Still metal on a long pole
|
||||
w_class = ITEMSIZE_SMALL
|
||||
attack_verb = list("slashed", "sliced", "cut", "clawed")
|
||||
|
||||
/obj/item/weapon/material/snow/snowball
|
||||
name = "loose packed snowball"
|
||||
desc = "A fun snowball. Throw it at your friends!"
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "snowball"
|
||||
default_material = MAT_SNOW
|
||||
health = 1
|
||||
fragile = 1
|
||||
force_divisor = 0.01
|
||||
thrown_force_divisor = 0.10
|
||||
w_class = ITEMSIZE_SMALL
|
||||
attack_verb = list("mushed", "splatted", "splooshed", "splushed") // Words that totally exist.
|
||||
|
||||
/obj/item/weapon/material/snow/snowball/attack_self(mob/user as mob)
|
||||
if(user.a_intent == I_HURT)
|
||||
to_chat(user, SPAN_NOTICE("You smash the snowball in your hand."))
|
||||
var/atom/S = new /obj/item/stack/material/snow(user.loc)
|
||||
qdel(src)
|
||||
user.put_in_hands(S)
|
||||
else
|
||||
to_chat(user, SPAN_NOTICE("You start compacting the snowball."))
|
||||
if(do_after(user, 2 SECONDS))
|
||||
var/atom/S = new /obj/item/weapon/material/snow/snowball/reinforced(user.loc)
|
||||
qdel(src)
|
||||
user.put_in_hands(S)
|
||||
|
||||
/obj/item/weapon/material/snow/snowball/reinforced
|
||||
name = "snowball"
|
||||
desc = "A well-formed and fun snowball. It looks kind of dangerous."
|
||||
//icon_state = "reinf-snowball"
|
||||
force_divisor = 0.20
|
||||
thrown_force_divisor = 0.25
|
||||
|
||||
/obj/item/weapon/material/whip
|
||||
name = "whip"
|
||||
desc = "A tool used to discipline animals, or look cool. Mostly the latter."
|
||||
description_info = "Help - Standard attack, no modifiers.<br>\
|
||||
Disarm - Disarming strike. Attempts to disarm the target at range, similar to an unarmed disarm. Additionally, will force the target (if possible) to move away from you.<br>\
|
||||
Grab - Grappling strike. Attempts to pull the target toward you. This can also move objects.<br>\
|
||||
Harm - A standard strike with a small chance to disarm."
|
||||
icon = 'icons/obj/weapons.dmi'
|
||||
icon_state = "whip"
|
||||
item_state = "chain"
|
||||
default_material = MAT_LEATHER
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = ITEMSIZE_NORMAL
|
||||
origin_tech = list(TECH_COMBAT = 2)
|
||||
attack_verb = list("flogged", "whipped", "lashed", "disciplined")
|
||||
force_divisor = 0.15
|
||||
thrown_force_divisor = 0.25
|
||||
reach = 2
|
||||
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_melee.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_melee.dmi',
|
||||
)
|
||||
|
||||
/obj/item/weapon/material/whip/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity)
|
||||
..()
|
||||
|
||||
if(!proximity)
|
||||
return
|
||||
|
||||
if(istype(A, /atom/movable))
|
||||
var/atom/movable/AM = A
|
||||
if(AM.anchored)
|
||||
to_chat(user, "<span class='notice'>\The [AM] won't budge.</span>")
|
||||
return
|
||||
|
||||
else
|
||||
if(!istype(AM, /obj/item))
|
||||
user.visible_message("<span class='warning'>\The [AM] is pulled along by \the [src]!</span>")
|
||||
AM.Move(get_step(AM, get_dir(AM, src)))
|
||||
return
|
||||
|
||||
else
|
||||
user.visible_message("<span class='warning'>\The [AM] is snatched by \the [src]!</span>")
|
||||
AM.throw_at(user, reach, 0.1, user)
|
||||
|
||||
/obj/item/weapon/material/whip/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
|
||||
if(user.a_intent)
|
||||
switch(user.a_intent)
|
||||
if(I_HURT)
|
||||
if(prob(10) && istype(target, /mob/living/carbon/human) && (user.zone_sel in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND)))
|
||||
to_chat(target, "<span class='warning'>\The [src] rips at your hands!</span>")
|
||||
ranged_disarm(target)
|
||||
if(I_DISARM)
|
||||
if(prob(min(90, force * 3)) && istype(target, /mob/living/carbon/human) && (user.zone_sel in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT, BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND)))
|
||||
ranged_disarm(target)
|
||||
else
|
||||
target.visible_message("<span class='danger'>\The [src] sends \the [target] stumbling away.</span>")
|
||||
target.Move(get_step(target,get_dir(user,target)))
|
||||
if(I_GRAB)
|
||||
var/turf/STurf = get_turf(target)
|
||||
spawn(2)
|
||||
playsound(STurf, 'sound/effects/snap.ogg', 60, 1)
|
||||
target.visible_message("<span class='critical'>\The [src] yanks \the [target] towards \the [user]!</span>")
|
||||
target.throw_at(get_turf(get_step(user,get_dir(user,target))), 2, 1, src)
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/weapon/material/whip/proc/ranged_disarm(var/mob/living/carbon/human/H, var/mob/living/user)
|
||||
if(istype(H))
|
||||
var/list/holding = list(H.get_active_hand() = 40, H.get_inactive_hand() = 20)
|
||||
|
||||
if(user.zone_sel in list(BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND))
|
||||
for(var/obj/item/weapon/gun/W in holding)
|
||||
if(W && prob(holding[W]))
|
||||
var/list/turfs = list()
|
||||
for(var/turf/T in view())
|
||||
turfs += T
|
||||
if(turfs.len)
|
||||
var/turf/target = pick(turfs)
|
||||
visible_message("<span class='danger'>[H]'s [W] goes off due to \the [src]!</span>")
|
||||
return W.afterattack(target,H)
|
||||
|
||||
if(!(H.species.flags & NO_SLIP) && prob(10) && (user.zone_sel in list(BP_L_LEG, BP_R_LEG, BP_L_FOOT, BP_R_FOOT)))
|
||||
var/armor_check = H.run_armor_check(user.zone_sel, "melee")
|
||||
H.apply_effect(3, WEAKEN, armor_check)
|
||||
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
if(armor_check < 60)
|
||||
visible_message("<span class='danger'>\The [src] has tripped [H]!</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>\The [src] attempted to trip [H]!</span>")
|
||||
return
|
||||
|
||||
else
|
||||
if(H.break_all_grabs(user))
|
||||
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
return
|
||||
|
||||
if(user.zone_sel in list(BP_L_ARM, BP_R_ARM, BP_L_HAND, BP_R_HAND))
|
||||
for(var/obj/item/I in holding)
|
||||
if(I && prob(holding[I]))
|
||||
H.drop_from_inventory(I)
|
||||
visible_message("<span class='danger'>\The [src] has disarmed [H]!</span>")
|
||||
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
return
|
||||
|
||||
/obj/item/weapon/material/whip/attack_self(mob/user)
|
||||
user.visible_message("<span class='warning'>\The [user] cracks \the [src]!</span>")
|
||||
playsound(src, 'sound/effects/snap.ogg', 50, 1)
|
||||
|
||||
/obj/item/weapon/material/knife/machete/hatchet/stone
|
||||
name = "hatchet"
|
||||
desc = "A very sharp axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."
|
||||
icon = 'icons/obj/weapons_vr.dmi'
|
||||
icon_state = "stone_wood_axe"
|
||||
default_material = MAT_FLINT
|
||||
origin_tech = list()
|
||||
applies_material_colour = FALSE
|
||||
|
||||
/obj/item/weapon/material/knife/machete/hatchet/stone/bone
|
||||
icon_state = "stone_bone_axe"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user