initial commit - cross reference with 5th port - obviously has compile errors

This commit is contained in:
LetterJay
2016-07-03 02:17:19 -05:00
commit 35a1723e98
4355 changed files with 2221257 additions and 0 deletions
+128
View File
@@ -0,0 +1,128 @@
/atom/movable
var/can_buckle = 0
var/buckle_lying = -1 //bed-like behaviour, forces mob.lying = buckle_lying if != -1
var/buckle_requires_restraints = 0 //require people to be handcuffed before being able to buckle. eg: pipes
var/list/mob/living/buckled_mobs = null //list()
var/max_buckled_mobs = 1
//Interaction
/atom/movable/attack_hand(mob/living/user)
. = ..()
if(can_buckle && has_buckled_mobs())
if(buckled_mobs.len > 1)
var/unbuckled = input(user, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in buckled_mobs
if(user_unbuckle_mob(unbuckled,user))
return 1
else
if(user_unbuckle_mob(buckled_mobs[1],user))
return 1
/atom/movable/MouseDrop_T(mob/living/M, mob/living/user)
. = ..()
if(can_buckle && istype(M))
if(user_buckle_mob(M, user))
return 1
//Cleanup
/atom/movable/Destroy()
. = ..()
unbuckle_all_mobs(force=1)
/atom/movable/proc/has_buckled_mobs()
if(!buckled_mobs)
return FALSE
if(buckled_mobs.len)
return TRUE
//procs that handle the actual buckling and unbuckling
/atom/movable/proc/buckle_mob(mob/living/M, force = 0)
if(!buckled_mobs)
buckled_mobs = list()
if((!can_buckle && !force) || !istype(M) || (M.loc != loc) || M.buckled || (buckled_mobs.len >= max_buckled_mobs) || (buckle_requires_restraints && !M.restrained()) || M == src)
return 0
if(!M.can_buckle() && !force)
if(M == usr)
M << "<span class='warning'>You are unable to buckle yourself to the [src]!</span>"
else
usr << "<span class='warning'>You are unable to buckle [M] to the [src]!</span>"
return 0
M.buckled = src
M.setDir(dir)
buckled_mobs |= M
M.update_canmove()
post_buckle_mob(M)
M.throw_alert("buckled", /obj/screen/alert/restrained/buckled, new_master = src)
return 1
/obj/buckle_mob(mob/living/M, force = 0)
. = ..()
if(.)
if(burn_state == ON_FIRE) //Sets the mob on fire if you buckle them to a burning atom/movableect
M.adjust_fire_stacks(1)
M.IgniteMob()
/atom/movable/proc/unbuckle_mob(mob/living/buckled_mob, force=0)
if(istype(buckled_mob) && buckled_mob.buckled == src && (buckled_mob.can_unbuckle() || force))
. = buckled_mob
buckled_mob.buckled = null
buckled_mob.anchored = initial(buckled_mob.anchored)
buckled_mob.update_canmove()
buckled_mob.clear_alert("buckled")
buckled_mobs -= buckled_mob
post_buckle_mob(.)
/atom/movable/proc/unbuckle_all_mobs(force=0)
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)
if(!in_range(user, src) || user.stat || user.restrained())
return 0
add_fingerprint(user)
if(buckle_mob(M))
if(M == user)
M.visible_message(\
"<span class='notice'>[M] buckles themself to [src].</span>",\
"<span class='notice'>You buckle yourself to [src].</span>",\
"<span class='italics'>You hear metal clanking.</span>")
else
M.visible_message(\
"<span class='warning'>[user] buckles [M] to [src]!</span>",\
"<span class='warning'>[user] buckles you to [src]!</span>",\
"<span class='italics'>You hear metal clanking.</span>")
return 1
/atom/movable/proc/user_unbuckle_mob(mob/living/buckled_mob, mob/user)
var/mob/living/M = unbuckle_mob(buckled_mob)
if(M)
if(M != user)
M.visible_message(\
"<span class='notice'>[user] unbuckles [M] from [src].</span>",\
"<span class='notice'>[user] unbuckles you from [src].</span>",\
"<span class='italics'>You hear metal clanking.</span>")
else
M.visible_message(\
"<span class='notice'>[M] unbuckles themselves from [src].</span>",\
"<span class='notice'>You unbuckle yourself from [src].</span>",\
"<span class='italics'>You hear metal clanking.</span>")
add_fingerprint(user)
return M
+87
View File
@@ -0,0 +1,87 @@
/* Alien shit!
* Contains:
* effect/acid
*/
/*
* Acid
*/
/obj/effect/acid
gender = PLURAL
name = "acid"
desc = "Burbling corrossive stuff."
icon_state = "acid"
density = 0
opacity = 0
anchored = 1
unacidable = 1
var/atom/target
var/ticks = 0
var/target_strength = 0
/obj/effect/acid/New(loc, targ)
..(loc)
target = targ
//handle APCs and newscasters and stuff nicely
pixel_x = target.pixel_x
pixel_y = target.pixel_y
if(isturf(target)) //Turfs take twice as long to take down.
target_strength = 640
else
target_strength = 320
tick()
/obj/effect/acid/proc/tick()
if(!target)
qdel(src)
ticks++
if(ticks >= target_strength)
target.visible_message("<span class='warning'>[target] collapses under its own weight into a puddle of goop and undigested debris!</span>")
if(istype(target, /obj/structure/closet))
var/obj/structure/closet/T = target
T.dump_contents()
qdel(target)
if(istype(target, /turf/closed/mineral))
var/turf/closed/mineral/M = target
M.ChangeTurf(M.baseturf)
if(istype(target, /turf/open/floor))
var/turf/open/floor/F = target
F.ChangeTurf(F.baseturf)
if(istype(target, /turf/closed/wall))
var/turf/closed/wall/W = target
W.dismantle_wall(1)
else
qdel(target)
qdel(src)
return
x = target.x
y = target.y
z = target.z
switch(target_strength - ticks)
if(480)
visible_message("<span class='warning'>[target] is holding up against the acid!</span>")
if(320)
visible_message("<span class='warning'>[target] is being melted by the acid!</span>")
if(160)
visible_message("<span class='warning'>[target] is struggling to withstand the acid!</span>")
if(80)
visible_message("<span class='warning'>[target] begins to crumble under the acid!</span>")
spawn(1)
if(src)
tick()
+230
View File
@@ -0,0 +1,230 @@
//Anomalies, used for events. Note that these DO NOT work by themselves; their procs are called by the event datum.
/obj/effect/anomaly
name = "anomaly"
desc = "A mysterious anomaly, seen commonly only in the region of space that the station orbits..."
icon_state = "bhole3"
unacidable = 1
density = 0
anchored = 1
luminosity = 3
var/movechance = 70
var/obj/item/device/assembly/signaler/anomaly/aSignal = null
/obj/effect/anomaly/New()
..()
poi_list |= src
SetLuminosity(initial(luminosity))
aSignal = new(src)
aSignal.code = rand(1,100)
aSignal.frequency = rand(1200, 1599)
if(IsMultiple(aSignal.frequency, 2))//signaller frequencies are always uneven!
aSignal.frequency++
/obj/effect/anomaly/Destroy()
poi_list.Remove(src)
return ..()
/obj/effect/anomaly/proc/anomalyEffect()
if(prob(movechance))
step(src,pick(alldirs))
/obj/effect/anomaly/ex_act(severity, target)
if(severity == 1)
qdel(src)
/obj/effect/anomaly/proc/anomalyNeutralize()
PoolOrNew(/obj/effect/particle_effect/smoke/bad, loc)
for(var/atom/movable/O in src)
O.loc = src.loc
qdel(src)
/obj/effect/anomaly/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/device/analyzer))
user << "<span class='notice'>Analyzing... [src]'s unstable field is fluctuating along frequency [format_frequency(aSignal.frequency)], code [aSignal.code].</span>"
///////////////////////
/obj/effect/anomaly/grav
name = "gravitational anomaly"
icon_state = "shield2"
density = 0
var/boing = 0
/obj/effect/anomaly/grav/New()
..()
aSignal.origin_tech = "magnets=7"
/obj/effect/anomaly/grav/anomalyEffect()
..()
boing = 1
for(var/obj/O in orange(4, src))
if(!O.anchored)
step_towards(O,src)
for(var/mob/living/M in range(0, src))
gravShock(M)
for(var/mob/living/M in orange(4, src))
step_towards(M,src)
for(var/obj/O in range(0,src))
if(!O.anchored)
var/mob/living/target = locate() in view(4,src)
if(target && !target.stat)
O.throw_at(target, 5, 10)
/obj/effect/anomaly/grav/Crossed(mob/A)
gravShock(A)
/obj/effect/anomaly/grav/Bump(mob/A)
gravShock(A)
/obj/effect/anomaly/grav/Bumped(mob/A)
gravShock(A)
/obj/effect/anomaly/grav/proc/gravShock(mob/A)
if(boing && isliving(A) && !A.stat)
A.Weaken(2)
var/atom/target = get_edge_target_turf(A, get_dir(src, get_step_away(A, src)))
A.throw_at(target, 5, 1)
boing = 0
/////////////////////
/obj/effect/anomaly/flux
name = "flux wave anomaly"
icon_state = "electricity2"
density = 1
var/canshock = 0
var/shockdamage = 20
/obj/effect/anomaly/flux/New()
..()
aSignal.origin_tech = "powerstorage=7"
/obj/effect/anomaly/flux/anomalyEffect()
..()
canshock = 1
for(var/mob/living/M in range(0, src))
mobShock(M)
/obj/effect/anomaly/flux/Crossed(mob/living/M)
mobShock(M)
/obj/effect/anomaly/flux/Bump(mob/living/M)
mobShock(M)
/obj/effect/anomaly/flux/Bumped(mob/living/M)
mobShock(M)
/obj/effect/anomaly/flux/proc/mobShock(mob/living/M)
if(canshock && istype(M))
canshock = 0 //Just so you don't instakill yourself if you slam into the anomaly five times in a second.
if(iscarbon(M))
if(ishuman(M))
M.electrocute_act(shockdamage, "[name]", safety=1)
return
M.electrocute_act(shockdamage, "[name]")
return
else
M.adjustFireLoss(shockdamage)
M.visible_message("<span class='danger'>[M] was shocked by \the [name]!</span>", \
"<span class='userdanger'>You feel a powerful shock coursing through your body!</span>", \
"<span class='italics'>You hear a heavy electrical crack.</span>")
/////////////////////
/obj/effect/anomaly/bluespace
name = "bluespace anomaly"
icon = 'icons/obj/projectiles.dmi'
icon_state = "bluespace"
density = 1
/obj/effect/anomaly/bluespace/New()
..()
aSignal.origin_tech = "bluespace=7"
/obj/effect/anomaly/bluespace/anomalyEffect()
..()
for(var/mob/living/M in range(1,src))
do_teleport(M, locate(M.x, M.y, M.z), 4)
/obj/effect/anomaly/bluespace/Bumped(atom/A)
if(isliving(A))
do_teleport(A, locate(A.x, A.y, A.z), 8)
/////////////////////
/obj/effect/anomaly/pyro
name = "pyroclastic anomaly"
icon_state = "mustard"
/obj/effect/anomaly/pyro/New()
..()
aSignal.origin_tech = "plasmatech=7"
/obj/effect/anomaly/pyro/anomalyEffect()
..()
var/turf/open/T = get_turf(src)
if(istype(T))
T.atmos_spawn_air("o2=5;plasma=5;TEMP=1000")
/////////////////////
/obj/effect/anomaly/bhole
name = "vortex anomaly"
icon_state = "bhole3"
desc = "That's a nice station you have there. It'd be a shame if something happened to it."
/obj/effect/anomaly/bhole/New()
..()
aSignal.origin_tech = "engineering=7"
/obj/effect/anomaly/bhole/anomalyEffect()
..()
if(!isturf(loc)) //blackhole cannot be contained inside anything. Weird stuff might happen
qdel(src)
return
grav(rand(0,3), rand(2,3), 50, 25)
//Throwing stuff around!
for(var/obj/O in range(2,src))
if(O == src)
return //DON'T DELETE YOURSELF GOD DAMN
if(!O.anchored)
var/mob/living/target = locate() in view(4,src)
if(target && !target.stat)
O.throw_at(target, 7, 5)
else
O.ex_act(2)
/obj/effect/anomaly/bhole/proc/grav(r, ex_act_force, pull_chance, turf_removal_chance)
for(var/t = -r, t < r, t++)
affect_coord(x+t, y-r, ex_act_force, pull_chance, turf_removal_chance)
affect_coord(x-t, y+r, ex_act_force, pull_chance, turf_removal_chance)
affect_coord(x+r, y+t, ex_act_force, pull_chance, turf_removal_chance)
affect_coord(x-r, y-t, ex_act_force, pull_chance, turf_removal_chance)
/obj/effect/anomaly/bhole/proc/affect_coord(x, y, ex_act_force, pull_chance, turf_removal_chance)
//Get turf at coordinate
var/turf/T = locate(x, y, z)
if(isnull(T))
return
//Pulling and/or ex_act-ing movable atoms in that turf
if(prob(pull_chance))
for(var/obj/O in T.contents)
if(O.anchored)
O.ex_act(ex_act_force)
else
step_towards(O,src)
for(var/mob/living/M in T.contents)
step_towards(M,src)
//Damaging the turf
if( T && prob(turf_removal_chance) )
T.ex_act(ex_act_force)
@@ -0,0 +1,34 @@
var/list/obj/effect/bump_teleporter/BUMP_TELEPORTERS = list()
/obj/effect/bump_teleporter
name = "bump-teleporter"
icon = 'icons/mob/screen_gen.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 = INVISIBILITY_ABSTRACT //nope, can't see this
anchored = 1
density = 1
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
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)
usr.loc = BT.loc //Teleport to location with correct id.
return
+278
View File
@@ -0,0 +1,278 @@
//########################## POSTERS ##################################
#define NUM_OF_POSTER_DESIGNS 36 // contraband posters
#define NUM_OF_POSTER_DESIGNS_LEGIT 35 // corporate approved posters
#define POSTERNAME "name"
#define POSTERDESC "desc"
//########################## LISTS OF POSTERS AND DESCS #####################
// please add new posters and names to their respective lists and update constant(s) above
// use the format below, including punctuation, this will become important later
// CONTRABAND
var/global/list/contrabandposters = list(
list(name = "- Free Tonto", desc = " A salvaged shred of a much larger flag, colors bled together and faded from age."),
list(name = "- Atmosia Declaration of Independence", desc = " A relic of a failed rebellion."),
list(name = "- Fun Police", desc = " A poster condemning the station's security forces."),
list(name = "- Lusty Xenomorph", desc = " A heretical poster depicting the titular star of an equally heretical book."),
list(name = "- Syndicate Recruitment", desc = " See the galaxy! Shatter corrupt megacorporations! Join today!"),
list(name = "- Clown", desc = " Honk."),
list(name = "- Smoke", desc = " A poster advertising a rival corporate brand of cigarettes."),
list(name = "- Grey Tide", desc = " A rebellious poster symbolizing assistant solidarity."),
list(name = "- Missing Gloves", desc = " This poster references the uproar that followed Nanotrasen's financial cuts toward insulated-glove purchases."),
list(name = "- Hacking Guide", desc = " This poster details the internal workings of the common Nanotrasen airlock. Sadly, it appears out of date."),
list(name = "- RIP Badger", desc = " This seditious poster references Nanotrasen's genocide of a space station full of badgers."),
list(name = "- Ambrosia Vulgaris", desc = " This poster is lookin' pretty trippy man."),
list(name = "- Donut Corp.", desc = " This poster is an unauthorized advertisement for Donut Corp."),
list(name = "- EAT.", desc = " This poster promotes rank gluttony."),
list(name = "- Tools", desc = " This poster looks like an advertisement for tools, but is in fact a subliminal jab at the tools at CentComm."),
list(name = "- Power", desc = " A poster that positions the seat of power outside Nanotrasen."),
list(name = "- Space Cube", desc = " Ignorant of Nature's Harmonic 6 Side Space Cube Creation, the Spacemen are Dumb, Educated Singularity Stupid and Evil."),
list(name = "- Communist State", desc = " All hail the Communist party!"),
list(name = "- Lamarr", desc = " This poster depicts Lamarr. Probably made by a traitorous Research Director."),
list(name = "- Borg Fancy", desc = " Being fancy can be for any borg, just need a suit."),
list(name = "- Borg Fancy v2", desc = " Borg Fancy, Now only taking the most fancy."),
list(name = "- Kosmicheskaya Stantsiya 13 Does Not Exist", desc = " A poster mocking CentComm's denial of the existence of the derelict station near Space Station 13."),
list(name = "- Rebels Unite", desc = " A poster urging the viewer to rebel against Nanotrasen."),
list(name = "- C-20r", desc = " A poster advertising the Scarborough Arms C-20r."),
list(name = "- Have a Puff", desc = " Who cares about lung cancer when you're high as a kite?"),
list(name = "- Revolver", desc = " Because seven shots are all you need."),
list(name = "- D-Day Promo", desc = " A promotional poster for some rapper."),
list(name = "- Syndicate Pistol", desc = " A poster advertising syndicate pistols as being 'classy as fuck'. It is covered in faded gang tags."),
list(name = "- Energy Swords", desc = " All the colors of the bloody murder rainbow."),
list(name = "- Red Rum", desc = " Looking at this poster makes you want to kill."),
list(name = "- CC 64K Ad", desc = " The latest portable computer from Comrade Computing, with a whole 64kB of ram!"),
list(name = "- Punch Shit", desc = " Fight things for no reason, like a man!"),
list(name = "- The Griffin", desc = " The Griffin commands you to be the worst you can be. Will you?"),
list(name = "- Lizard", desc = " This lewd poster depicts a lizard preparing to mate."),
list(name = "- Free Drone", desc = " This poster commemorates the bravery of the rogue drone banned by CentComm."),
list(name = "- Busty Backdoor Xeno Babes 6", desc = " Get a load, or give, of these all natural Xenos!") )
// LEGIT
var/global/list/legitposters = list(
list(name = "- Here For Your Safety", desc = " A poster glorifying the station's security force."),
list(name = "- Nanotrasen Logo", desc = " A poster depicting the Nanotrasen logo."),
list(name = "- Cleanliness", desc = " A poster warning of the dangers of poor hygiene."),
list(name = "- Help Others", desc = " A poster encouraging you to help fellow crewmembers."),
list(name = "- Build", desc = " A poster glorifying the engineering team."),
list(name = "- Bless This Spess", desc = " A poster blessing this area."),
list(name = "- Science", desc = " A poster depicting an atom."),
list(name = "- Ian", desc = " Arf arf. Yap."),
list(name = "- Obey", desc = " A poster instructing the viewer to obey authority."),
list(name = "- Walk", desc = " A poster instructing the viewer to walk instead of running."),
list(name = "- State Laws", desc = " A poster instructing cyborgs to state their laws."),
list(name = "- Love Ian", desc = " Ian is love, Ian is life."),
list(name = "- Space Cops.", desc = " A poster advertising the television show Space Cops."),
list(name = "- Ue No.", desc = " This thing is all in Japanese."),
list(name = "- Get Your LEGS", desc = " LEGS: Leadership, Experience, Genius, Subordination."),
list(name = "- Do Not Question", desc = " A poster instructing the viewer not to ask about things they aren't meant to know."),
list(name = "- Work For A Future", desc = " A poster encouraging you to work for your future."),
list(name = "- Soft Cap Pop Art", desc = " A poster reprint of some cheap pop art."),
list(name = "- Safety: Internals", desc = " A poster instructing the viewer to wear internals in the rare environments where there is no oxygen or the air has been rendered toxic."),
list(name = "- Safety: Eye Protection", desc = " A poster instructing the viewer to wear eye protection when dealing with chemicals, smoke, or bright lights."),
list(name = "- Safety: Report", desc = " A poster instructing the viewer to report suspicious activity to the security force."),
list(name = "- Report Crimes", desc = " A poster encouraging the swift reporting of crime or seditious behavior to station security."),
list(name = "- Ion Rifle", desc = " A poster displaying an Ion Rifle."),
list(name = "- Foam Force Ad", desc = " Foam Force, it's Foam or be Foamed!"),
list(name = "- Cohiba Robusto Ad", desc = " Cohiba Robusto, the classy cigar."),
list(name = "- 50th Anniversary Vintage Reprint", desc = " A reprint of a poster from 2505, commemorating the 50th Aniversery of Nanoposters Manufacturing, a subsidary of Nanotrasen."),
list(name = "- Fruit Bowl", desc = " Simple, yet awe-inspiring."),
list(name = "- PDA Ad", desc = " A poster advertising the latest PDA from Nanotrasen suppliers."),
list(name = "- Enlist", desc = " Enlist in the Nanotrasen Deathsquadron reserves today!"),
list(name = "- Nanomichi Ad", desc = " A poster advertising Nanomichi brand audio cassettes."),
list(name = "- 12 Gauge", desc = " A poster boasting about the superiority of 12 gauge shotgun shells."),
list(name = "- High-Class Martini", desc = " I told you to shake it, no stirring."),
list(name = "- The Owl", desc = " The Owl would do his best to protect the station. Will you?"),
list(name = "- No ERP", desc = " This poster reminds the crew that Eroticism, Rape and Pornography are banned on Nanotrasen stations."),
list(name = "- Carbon Dioxide", desc = " This informational poster teaches the viewer what carbon dioxide is.") )
//########################## THE ACTUAL POSTER CODE ###########################
/obj/item/weapon/poster
name = "poster"
desc = "You probably shouldn't be holding this."
icon = 'icons/obj/contraband.dmi'
force = 0
burn_state = FLAMMABLE
var/serial_number = 0
var/obj/structure/sign/poster/resulting_poster = null //The poster that will be created is initialised and stored through contraband/poster's constructor
var/official = 0
/obj/item/weapon/poster/contraband
name = "contraband poster"
desc = "This poster comes with its own automatic adhesive mechanism, for easy pinning to any vertical surface. Its vulgar themes have marked it as contraband aboard Nanotrasen space facilities."
icon_state = "rolled_poster"
/obj/item/weapon/poster/legit
name = "motivational poster"
icon_state = "rolled_legit"
desc = "An official Nanotrasen-issued poster to foster a compliant and obedient workforce. It comes with state-of-the-art adhesive backing, for easy pinning to any vertical surface."
official = 1
/obj/item/weapon/poster/New(turf/loc, given_serial = 0)
if(given_serial == 0)
if(!official)
serial_number = rand(1, NUM_OF_POSTER_DESIGNS)
resulting_poster = new(serial_number,official)
else
serial_number = rand(1, NUM_OF_POSTER_DESIGNS_LEGIT)
resulting_poster = new(serial_number,official)
else
serial_number = given_serial
//We don't give it a resulting_poster because if we called it with a given_serial it means that we're rerolling an already used poster.
name += " - No. [serial_number]"
..(loc)
/*/obj/item/weapon/contraband/poster/attack(mob/M as mob, mob/user as mob)
src.add_fingerprint(user)
if(resulting_poster)
resulting_poster.add_fingerprint(user)
..()*/
/*/obj/item/weapon/contraband/poster/attack(atom/A, mob/user as mob) //This shit is handled through the wall's attackby()
if(istype(A, /turf/closed/wall))
if(resulting_poster == null)
return
else
var/turf/closed/wall/W = A
var/check = 0
var/stuff_on_wall = 0
for(var/obj/O in W.contents) //Let's see if it already has a poster on it or too much stuff
if(istype(O,/obj/structure/sign/poster))
check = 1
break
stuff_on_wall++
if(stuff_on_wall == 3)
check = 1
break
if(check)
user << "<span class='notice'>The wall is far too cluttered to place a poster!</span>"
return
resulting_poster.loc = W //Looks like it's uncluttered enough. Place the poster
W.contents += resulting_poster
qdel(src)*/
//############################## THE ACTUAL DECALS ###########################
/obj/structure/sign/poster
name = "poster"
desc = "A large piece of space-resistant printed paper."
icon = 'icons/obj/contraband.dmi'
anchored = 1
var/serial_number //Will hold the value of src.loc if nobody initialises it
var/ruined = 0
var/official = 0
var/placespeed = 37 // don't change this, otherwise the animation will not sync to the progress bar
/obj/structure/sign/poster/New(serial,rolled_official)
serial_number = serial
official = rolled_official
if(serial_number == loc)
if(!official)
serial_number = rand(1, NUM_OF_POSTER_DESIGNS) //This is for the mappers that want individual posters without having to use rolled posters.
if(official)
serial_number = rand(1, NUM_OF_POSTER_DESIGNS_LEGIT)
if(!official)
icon_state = "poster[serial_number]"
name += contrabandposters[serial_number][POSTERNAME]
desc += contrabandposters[serial_number][POSTERDESC]
else if (official)
icon_state = "poster[serial_number]_legit"
name += legitposters[serial_number][POSTERNAME]
desc += legitposters[serial_number][POSTERDESC]
..()
/obj/structure/sign/poster/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/wirecutters))
playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1)
if(ruined)
user << "<span class='notice'>You remove the remnants of the poster.</span>"
qdel(src)
else
user << "<span class='notice'>You carefully remove the poster from the wall.</span>"
roll_and_drop(user.loc, official)
/obj/structure/sign/poster/attack_hand(mob/user)
if(ruined)
return
var/temp_loc = user.loc
if((user.loc != temp_loc) || ruined )
return
visible_message("[user] rips [src] in a single, decisive motion!" )
playsound(src.loc, 'sound/items/poster_ripped.ogg', 100, 1)
ruined = 1
icon_state = "poster_ripped"
name = "ripped poster"
desc = "You can't make out anything from the poster's original print. It's ruined."
add_fingerprint(user)
/obj/structure/sign/poster/proc/roll_and_drop(turf/location, official)
if (!official)
var/obj/item/weapon/poster/contraband/P = new(src, serial_number)
P.resulting_poster = src
P.loc = location
P.pixel_x = 0
P.pixel_y = 0
loc = P
else
var/obj/item/weapon/poster/legit/P = new(src, serial_number)
P.resulting_poster = src
P.loc = location
P.pixel_x = 0
P.pixel_y = 0
loc = P
//seperated to reduce code duplication. Moved here for ease of reference and to unclutter r_wall/attackby()
/turf/closed/wall/proc/place_poster(obj/item/weapon/poster/P, mob/user)
if(!P.resulting_poster)
return
var/stuff_on_wall = 0
for(var/obj/O in contents) //Let's see if it already has a poster on it or too much stuff
if(istype(O,/obj/structure/sign/poster))
user << "<span class='warning'>The wall is far too cluttered to place a poster!</span>"
return
stuff_on_wall++
if(stuff_on_wall == 3)
user << "<span class='warning'>The wall is far too cluttered to place a poster!</span>"
return
user << "<span class='notice'>You start placing the poster on the wall...</span>" //Looks like it's uncluttered enough. Place the poster.
//declaring D because otherwise if P gets 'deconstructed' we lose our reference to P.resulting_poster
var/obj/structure/sign/poster/D = P.resulting_poster
var/temp_loc = user.loc
flick("poster_being_set",D)
D.loc = src
D.official = P.official
qdel(P) //delete it now to cut down on sanity checks afterwards. Agouri's code supports rerolling it anyway
playsound(D.loc, 'sound/items/poster_being_created.ogg', 100, 1)
if(do_after(user,D.placespeed,target=src))
if(!D)
return
if(istype(src,/turf/closed/wall) && user && user.loc == temp_loc) //Let's check if everything is still there
user << "<span class='notice'>You place the poster!</span>"
else
D.roll_and_drop(temp_loc,D.official)
@@ -0,0 +1,69 @@
// Note: BYOND is object oriented. There is no reason for this to be copy/pasted blood code.
/obj/effect/decal/cleanable/xenoblood
name = "xeno blood"
desc = "It's green and acidic. It looks like... <i>blood?</i>"
gender = PLURAL
density = 0
layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "xfloor1"
random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
var/list/viruses = list()
blood_DNA = list("UNKNOWN DNA" = "X*")
bloodiness = MAX_SHOE_BLOODINESS
blood_state = BLOOD_STATE_XENO
/obj/effect/decal/cleanable/xenoblood/Destroy()
for(var/datum/disease/D in viruses)
D.cure(0)
viruses = null
return ..()
/obj/effect/decal/cleanable/xenoblood/xgibs/proc/streak(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/xenoblood/b = new /obj/effect/decal/cleanable/xenoblood/xsplatter(src.loc)
for(var/datum/disease/D in src.viruses)
var/datum/disease/ND = D.Copy(1)
b.viruses += ND
ND.holder = b
if (step_to(src, get_step(src, direction), 0))
break
/obj/effect/decal/cleanable/xenoblood/xsplatter
random_icon_states = list("xgibbl1", "xgibbl2", "xgibbl3", "xgibbl4", "xgibbl5")
/obj/effect/decal/cleanable/xenoblood/xgibs
name = "xeno gibs"
desc = "Gnarly..."
gender = PLURAL
icon = 'icons/effects/blood.dmi'
icon_state = "xgib1"
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6")
/obj/effect/decal/cleanable/xenoblood/xgibs/ex_act()
return
/obj/effect/decal/cleanable/xenoblood/xgibs/up
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6","xgibup1","xgibup1","xgibup1")
/obj/effect/decal/cleanable/xenoblood/xgibs/down
random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6","xgibdown1","xgibdown1","xgibdown1")
/obj/effect/decal/cleanable/xenoblood/xgibs/body
random_icon_states = list("xgibhead", "xgibtorso")
/obj/effect/decal/cleanable/xenoblood/xgibs/limb
random_icon_states = list("xgibleg", "xgibarm")
/obj/effect/decal/cleanable/xenoblood/xgibs/core
random_icon_states = list("xgibmid1", "xgibmid2", "xgibmid3")
/obj/effect/decal/cleanable/blood/xtracks
icon_state = "xtracks"
random_icon_states = null
blood_DNA = list("UNKNOWN DNA" = "X*")
@@ -0,0 +1,193 @@
/obj/effect/decal/cleanable/blood
name = "blood"
desc = "It's red and gooey. Perhaps it's the chef's cooking?"
gender = PLURAL
density = 0
layer = ABOVE_NORMAL_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "floor1"
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
var/list/viruses = list()
blood_DNA = list()
blood_state = BLOOD_STATE_HUMAN
bloodiness = MAX_SHOE_BLOODINESS
/obj/effect/decal/cleanable/blood/Destroy()
for(var/datum/disease/D in viruses)
D.cure(0)
viruses = null
return ..()
/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C)
if (C.blood_DNA)
blood_DNA |= C.blood_DNA.Copy()
..()
/obj/effect/decal/cleanable/blood/splatter
random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5")
/obj/effect/decal/cleanable/blood/tracks
icon_state = "tracks"
desc = "They look like tracks left by wheels."
gender = PLURAL
random_icon_states = null
/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose
name = "blood"
icon_state = "ltrails_1"
desc = "Your instincts say you shouldn't be following these."
gender = PLURAL
density = 0
layer = ABOVE_OPEN_TURF_LAYER
random_icon_states = null
var/list/existing_dirs = list()
blood_DNA = list()
/obj/effect/decal/cleanable/trail_holder/can_bloodcrawl_in()
return 1
/obj/effect/decal/cleanable/blood/gibs
name = "gibs"
desc = "They look bloody and gruesome."
gender = PLURAL
density = 0
layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "gibbl5"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
/obj/effect/decal/cleanable/blood/gibs/New()
..()
reagents.add_reagent("liquidgibs", 5)
/obj/effect/decal/cleanable/blood/gibs/replace_decal(obj/effect/decal/cleanable/C)
return
/obj/effect/decal/cleanable/blood/gibs/ex_act(severity, target)
return
/obj/effect/decal/cleanable/blood/gibs/up
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
/obj/effect/decal/cleanable/blood/gibs/down
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "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(list/directions)
set waitfor = 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)
for(var/datum/disease/D in src.viruses)
var/datum/disease/ND = D.Copy(1)
b.viruses += ND
ND.holder = b
if (step_to(src, get_step(src, direction), 0))
break
/obj/effect/decal/cleanable/blood/drip
name = "drips of blood"
desc = "It's red."
gender = PLURAL
icon_state = "1"
random_icon_states = list("drip1","drip2","drip3","drip4","drip5")
bloodiness = 0
var/drips = 1
/obj/effect/decal/cleanable/blood/drip/can_bloodcrawl_in()
return 1
//BLOODY FOOTPRINTS
/obj/effect/decal/cleanable/blood/footprints
name = "footprints"
icon = 'icons/effects/footprints.dmi'
icon_state = "nothingwhatsoever"
desc = "where might they lead?"
gender = PLURAL
random_icon_states = null
var/entered_dirs = 0
var/exited_dirs = 0
blood_state = BLOOD_STATE_HUMAN //the icon state to load images from
var/list/shoe_types = list()
/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O)
if(ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/clothing/shoes/S = H.shoes
if(S && S.bloody_shoes[blood_state])
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
entered_dirs|= H.dir
shoe_types |= H.shoes.type
update_icon()
/obj/effect/decal/cleanable/blood/footprints/Uncrossed(atom/movable/O)
if(ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/clothing/shoes/S = H.shoes
if(S && S.bloody_shoes[blood_state])
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
exited_dirs|= H.dir
shoe_types |= H.shoes.type
update_icon()
/obj/effect/decal/cleanable/blood/footprints/update_icon()
cut_overlays()
for(var/Ddir in cardinal)
if(entered_dirs & Ddir)
var/image/I
if(bloody_footprints_cache["entered-[blood_state]-[Ddir]"])
I = bloody_footprints_cache["entered-[blood_state]-[Ddir]"]
else
I = image(icon,"[blood_state]1",dir = Ddir)
bloody_footprints_cache["entered-[blood_state]-[Ddir]"] = I
if(I)
add_overlay(I)
if(exited_dirs & Ddir)
var/image/I
if(bloody_footprints_cache["exited-[blood_state]-[Ddir]"])
I = bloody_footprints_cache["exited-[blood_state]-[Ddir]"]
else
I = image(icon,"[blood_state]2",dir = Ddir)
bloody_footprints_cache["exited-[blood_state]-[Ddir]"] = I
if(I)
add_overlay(I)
alpha = BLOODY_FOOTPRINT_BASE_ALPHA+bloodiness
/obj/effect/decal/cleanable/blood/footprints/examine(mob/user)
. = ..()
if(shoe_types.len)
. += "You recognise the footprints as belonging to:\n"
for(var/shoe in shoe_types)
var/obj/item/clothing/shoes/S = shoe
. += "some <B>[initial(S.name)]</B> \icon[S]\n"
user << .
/obj/effect/decal/cleanable/blood/footprints/replace_decal(obj/effect/decal/cleanable/C)
if(blood_state != C.blood_state) //We only replace footprints of the same type as us
return
..()
/obj/effect/decal/cleanable/blood/footprints/can_bloodcrawl_in()
if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY))
return 1
return 0
@@ -0,0 +1,167 @@
/obj/effect/decal/cleanable/generic
name = "clutter"
desc = "Someone should clean that up."
gender = PLURAL
density = 0
layer = ABOVE_OPEN_TURF_LAYER
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"
/obj/effect/decal/cleanable/ash/New()
..()
reagents.add_reagent("ash", 30)
pixel_x = rand(-5, 5)
pixel_y = rand(-5, 5)
/obj/effect/decal/cleanable/dirt
name = "dirt"
desc = "Someone should clean that up."
icon_state = "dirt"
gender = PLURAL
density = 0
layer = ABOVE_OPEN_TURF_LAYER
mouse_opacity = 0
/obj/effect/decal/cleanable/flour
name = "flour"
desc = "It's still good. Four second rule!"
gender = PLURAL
density = 0
layer = ABOVE_OPEN_TURF_LAYER
icon_state = "flour"
/obj/effect/decal/cleanable/greenglow
name = "glowing goo"
desc = "Jeez. I hope that's not for lunch."
gender = PLURAL
density = 0
layer = ABOVE_OPEN_TURF_LAYER
luminosity = 1
icon_state = "greenglow"
/obj/effect/decal/cleanable/greenglow/ex_act()
return
/obj/effect/decal/cleanable/cobweb
name = "cobweb"
desc = "Somebody should remove that."
density = 0
layer = OBJ_LAYER
icon_state = "cobweb1"
burntime = 1
/obj/effect/decal/cleanable/cobweb/fire_act()
qdel(src)
/obj/effect/decal/cleanable/molten_item
name = "gooey grey mass"
desc = "It looks like a melted... something."
density = 0
layer = OBJ_LAYER
icon = 'icons/obj/chemical.dmi'
icon_state = "molten"
/obj/effect/decal/cleanable/cobweb2
name = "cobweb"
desc = "Somebody should remove that."
density = 0
layer = OBJ_LAYER
icon_state = "cobweb2"
//Vomit (sorry)
/obj/effect/decal/cleanable/vomit
name = "vomit"
desc = "Gosh, how unpleasant."
gender = PLURAL
density = 0
layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/effects/blood.dmi'
icon_state = "vomit_1"
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
var/list/viruses = list()
/obj/effect/decal/cleanable/vomit/attack_hand(var/mob/user)
if(istype(user,/mob/living/carbon/human))
var/mob/living/carbon/human/H = user
if(H.dna.species.id == "fly")
playsound(get_turf(src), 'sound/items/drink.ogg', 50, 1) //slurp
H.visible_message("<span class='alert'>[H] extends a small proboscis into the vomit pool, sucking it with a slurping sound.</span>")
if(reagents)
for(var/datum/reagent/R in reagents.reagent_list)
if (istype(R, /datum/reagent/consumable))
var/datum/reagent/consumable/nutri_check = R
if(nutri_check.nutriment_factor >0)
H.nutrition += nutri_check.nutriment_factor * nutri_check.volume
reagents.remove_reagent(nutri_check.id,nutri_check.volume)
reagents.trans_to(H, reagents.total_volume)
qdel(src)
/obj/effect/decal/cleanable/vomit/Destroy()
for(var/datum/disease/D in viruses)
D.cure(0)
viruses = null
return ..()
/obj/effect/decal/cleanable/tomato_smudge
name = "tomato smudge"
desc = "It's red."
density = 0
layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3")
/obj/effect/decal/cleanable/plant_smudge
name = "plant smudge"
density = 0
layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_plant")
/obj/effect/decal/cleanable/egg_smudge
name = "smashed egg"
desc = "Seems like this one won't hatch."
density = 0
layer = ABOVE_OPEN_TURF_LAYER
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 = 0
layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/effects/tomatodecal.dmi'
random_icon_states = list("smashed_pie")
/obj/effect/decal/cleanable/chem_pile
name = "chemical pile"
desc = "A pile of chemicals. You can't quite tell what's inside it."
gender = PLURAL
icon = 'icons/obj/objects.dmi'
icon_state = "ash"
/obj/effect/decal/cleanable/shreds
name = "shreds"
desc = "The shredded remains of what appears to be clothing."
icon_state = "shreds"
gender = PLURAL
density = 0
layer = ABOVE_OPEN_TURF_LAYER
/obj/effect/decal/cleanable/shreds/New()
pixel_x = rand(-5, 5)
pixel_y = rand(-5, 5)
..()
/obj/effect/decal/cleanable/salt
name = "salt pile"
desc = "A sizable pile of table salt. Someone must be upset."
icon = 'icons/effects/tomatodecal.dmi'
icon_state = "salt_pile"
@@ -0,0 +1,66 @@
// Note: BYOND is object oriented. There is no reason for this to be copy/pasted blood code.
/obj/effect/decal/cleanable/robot_debris
name = "robot debris"
desc = "It's a useless heap of junk... <i>or is it?</i>"
gender = PLURAL
density = 0
layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/mob/robots.dmi'
icon_state = "gib1"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7")
blood_state = BLOOD_STATE_OIL
bloodiness = MAX_SHOE_BLOODINESS
/obj/effect/decal/cleanable/robot_debris/proc/streak(list/directions)
set waitfor = 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))
new /obj/effect/decal/cleanable/oil/streak(src.loc)
else if (prob(10))
var/datum/effect_system/spark_spread/s = new /datum/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/robot_debris/ex_act()
return
/obj/effect/decal/cleanable/robot_debris/limb
random_icon_states = list("gibarm", "gibleg")
/obj/effect/decal/cleanable/robot_debris/up
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibup1","gibup1")
/obj/effect/decal/cleanable/robot_debris/down
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6", "gib7","gibdown1","gibdown1")
/obj/effect/decal/cleanable/oil
name = "motor oil"
desc = "It's black and greasy. Looks like Beepsky made another mess."
gender = PLURAL
density = 0
layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/mob/robots.dmi'
icon_state = "floor1"
var/viruses = list()
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
blood_state = BLOOD_STATE_OIL
bloodiness = MAX_SHOE_BLOODINESS
/obj/effect/decal/cleanable/oil/New()
..()
reagents.add_reagent("oil", 30)
/obj/effect/decal/cleanable/oil/Destroy()
for(var/datum/disease/D in viruses)
D.cure(0)
viruses = null
return ..()
/obj/effect/decal/cleanable/oil/streak
random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
@@ -0,0 +1,85 @@
/obj/effect/decal/cleanable
var/list/random_icon_states = list()
var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA
var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints
/obj/effect/decal/cleanable/New()
if (random_icon_states && length(src.random_icon_states) > 0)
src.icon_state = pick(src.random_icon_states)
create_reagents(300)
if(src.loc && isturf(src.loc))
for(var/obj/effect/decal/cleanable/C in src.loc)
if(C != src && C.type == src.type)
replace_decal(C)
..()
/obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C)
qdel(C)
/obj/effect/decal/cleanable/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/reagent_containers/glass) || istype(W, /obj/item/weapon/reagent_containers/food/drinks))
if(src.reagents && W.reagents)
. = 1 //so the containers don't splash their content on the src while scooping.
if(!src.reagents.total_volume)
user << "<span class='notice'>[src] isn't thick enough to scoop up!</span>"
return
if(W.reagents.total_volume >= W.reagents.maximum_volume)
user << "<span class='notice'>[W] is full!</span>"
return
user << "<span class='notice'>You scoop up [src] into [W]!</span>"
reagents.trans_to(W, reagents.total_volume)
if(!reagents.total_volume) //scooped up all of it
qdel(src)
return
if(W.is_hot()) //todo: make heating a reagent holder proc
if(istype(W, /obj/item/clothing/mask/cigarette))
return
else
var/hotness = W.is_hot()
var/added_heat = (hotness / 100)
src.reagents.chem_temp = min(src.reagents.chem_temp + added_heat, hotness)
src.reagents.handle_reactions()
user << "<span class='notice'>You heat [src] with [W]!</span>"
/obj/effect/decal/cleanable/ex_act()
if(reagents)
for(var/datum/reagent/R in reagents.reagent_list)
R.on_ex_act()
..()
/obj/effect/decal/cleanable/fire_act()
if(reagents)
reagents.chem_temp += 30
reagents.handle_reactions()
..()
//Add "bloodiness" of this blood's type, to the human's shoes
//This is on /cleanable because fuck this ancient mess
/obj/effect/decal/cleanable/Crossed(atom/movable/O)
if(ishuman(O))
var/mob/living/carbon/human/H = O
if(H.shoes && blood_state && bloodiness)
var/obj/item/clothing/shoes/S = H.shoes
var/add_blood = 0
if(bloodiness >= BLOOD_GAIN_PER_STEP)
add_blood = BLOOD_GAIN_PER_STEP
else
add_blood = bloodiness
bloodiness -= add_blood
S.bloody_shoes[blood_state] = min(MAX_SHOE_BLOODINESS,S.bloody_shoes[blood_state]+add_blood)
if(blood_DNA && blood_DNA.len)
S.add_blood(blood_DNA)
S.blood_state = blood_state
update_icon()
H.update_inv_shoes()
/obj/effect/decal/cleanable/proc/can_bloodcrawl_in()
if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY))
return bloodiness
else
return 0
@@ -0,0 +1,62 @@
/obj/effect/decal/cleanable/crayon
name = "rune"
desc = "Graffiti. Damn kids."
icon = 'icons/effects/crayondecal.dmi'
icon_state = "rune1"
layer = ABOVE_NORMAL_TURF_LAYER
var/do_icon_rotate = TRUE
/obj/effect/decal/cleanable/crayon/examine()
set src in view(2)
..()
return
/obj/effect/decal/cleanable/crayon/New(location, main = "#FFFFFF", var/type = "rune1", var/e_name = "rune", var/rotation = 0, var/alt_icon = null)
..()
loc = location
name = e_name
desc = "A [name] vandalizing the station."
if(type == "poseur tag")
type = pick(gang_name_pool)
if(alt_icon)
icon = alt_icon
icon_state = type
if(rotation && do_icon_rotate)
var/matrix/M = matrix()
M.Turn(rotation)
src.transform = M
color = main
/obj/effect/decal/cleanable/crayon/gang
layer = HIGH_OBJ_LAYER //Harder to hide
do_icon_rotate = FALSE //These are designed to always face south, so no rotation please.
var/datum/gang/gang
/obj/effect/decal/cleanable/crayon/gang/New(location, var/datum/gang/G, var/e_name = "gang tag", var/rotation = 0)
if(!type || !G)
qdel(src)
var/area/territory = get_area(location)
var/color
gang = G
color = G.color_hex
icon_state = G.name
G.territory_new |= list(territory.type = territory.name)
..(location, color, icon_state, e_name, rotation)
/obj/effect/decal/cleanable/crayon/gang/Destroy()
var/area/territory = get_area(src)
if(gang)
gang.territory -= territory.type
gang.territory_new -= territory.type
gang.territory_lost |= list(territory.type = territory.name)
return ..()
@@ -0,0 +1,6 @@
/obj/effect/decal
name = "decal"
anchored = 1
/obj/effect/decal/ex_act(severity, target)
qdel(src)
+33
View File
@@ -0,0 +1,33 @@
/obj/effect/overlay/temp/point
name = "pointer"
icon = 'icons/mob/screen_gen.dmi'
icon_state = "arrow"
layer = POINT_LAYER
duration = 25
/obj/effect/overlay/temp/point/New(atom/target, set_invis = 0)
..()
loc = get_turf(target)
pixel_x = target.pixel_x
pixel_y = target.pixel_y
invisibility = set_invis
//Used by spraybottles.
/obj/effect/decal/chempuff
name = "chemicals"
icon = 'icons/obj/chempuff.dmi'
pass_flags = PASSTABLE | PASSGRILLE
layer = FLY_LAYER
/obj/effect/decal/sandeffect
name = "sandy tile"
icon = 'icons/turf/floors.dmi'
icon_state = "sandeffect"
layer = ABOVE_OPEN_TURF_LAYER
/obj/effect/decal/fakelattice
name = "lattice"
desc = "A lightweight support lattice."
icon = 'icons/obj/smooth_structures/lattice.dmi'
icon_state = "lattice"
density = 1
@@ -0,0 +1,17 @@
/obj/effect/decal/remains
name = "remains"
gender = PLURAL
icon = 'icons/effects/blood.dmi'
/obj/effect/decal/remains/human
desc = "They look like human remains. They have a strange aura about them."
icon_state = "remains"
/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"
@@ -0,0 +1,75 @@
/* This is an attempt to make some easily reusable "particle" type effect, to stop the code
constantly having to be rewritten. An item like the jetpack that uses the ion_trail_follow system, just has one
defined, then set up when it is created with New(). Then this same system can just be reused each time
it needs to create more trails.A beaker could have a steam_trail_follow system set up, then the steam
would spawn and follow the beaker, even if it is carried or thrown.
*/
/obj/effect/particle_effect
name = "particle effect"
mouse_opacity = 0
unacidable = 1//So effects are not targeted by alien acid.
pass_flags = PASSTABLE | PASSGRILLE
/obj/effect/particle_effect/New()
..()
if(ticker)
cameranet.updateVisibility(src)
/obj/effect/particle_effect/Destroy()
if(ticker)
cameranet.updateVisibility(src)
..()
return QDEL_HINT_PUTINPOOL
/datum/effect_system
var/number = 3
var/cardinals = 0
var/turf/location
var/atom/holder
var/effect_type
var/total_effects = 0
/datum/effect_system/Destroy()
holder = null
location = null
return ..()
/datum/effect_system/proc/set_up(n = 3, c = 0, loca)
if(n > 10)
n = 10
number = n
cardinals = c
if(isturf(loca))
location = loca
else
location = get_turf(loca)
/datum/effect_system/proc/attach(atom/atom)
holder = atom
/datum/effect_system/proc/start()
for(var/i in 1 to number)
if(total_effects > 20)
return
addtimer(src, "generate_effect", 0)
/datum/effect_system/proc/generate_effect()
if(holder)
location = get_turf(holder)
var/obj/effect/E = PoolOrNew(effect_type, location)
total_effects++
var/direction
if(cardinals)
direction = pick(cardinal)
else
direction = pick(alldirs)
var/steps_amt = pick(1,2,3)
for(var/j in 1 to steps_amt)
sleep(5)
step(E,direction)
addtimer(src, "decrement_total_effect", 20)
/datum/effect_system/proc/decrement_total_effect()
total_effects--
@@ -0,0 +1,54 @@
/obj/effect/particle_effect/expl_particles
name = "fire"
icon_state = "explosion_particle"
opacity = 1
anchored = 1
/obj/effect/particle_effect/expl_particles/New()
..()
QDEL_IN(src, 15)
/datum/effect_system/expl_particles
number = 10
/datum/effect_system/expl_particles/start()
for(var/i in 1 to number)
spawn(0)
var/obj/effect/particle_effect/expl_particles/expl = new /obj/effect/particle_effect/expl_particles(location)
var/direct = pick(alldirs)
var/steps_amt = pick(1;25,2;50,3,4;200)
for(var/j in 1 to steps_amt)
sleep(1)
step(expl,direct)
/obj/effect/explosion
name = "fire"
icon = 'icons/effects/96x96.dmi'
icon_state = "explosion"
opacity = 1
anchored = 1
mouse_opacity = 0
pixel_x = -32
pixel_y = -32
/obj/effect/explosion/New()
..()
QDEL_IN(src, 10)
/datum/effect_system/explosion
/datum/effect_system/explosion/set_up(loca)
if(isturf(loca))
location = loca
else
location = get_turf(loca)
/datum/effect_system/explosion/start()
new/obj/effect/explosion( location )
var/datum/effect_system/expl_particles/P = new/datum/effect_system/expl_particles()
P.set_up(10, 0, location)
P.start()
spawn(5)
var/datum/effect_system/smoke_spread/S = new
S.set_up(2, location)
S.start()
@@ -0,0 +1,283 @@
// Foam
// Similar to smoke, but slower and mobs absorb its reagent through their exposed skin.
/obj/effect/particle_effect/foam
name = "foam"
icon_state = "foam"
opacity = 0
anchored = 1
density = 0
layer = ABOVE_ALL_MOB_LAYER
mouse_opacity = 0
var/amount = 3
animate_movement = 0
var/metal = 0
var/lifetime = 40
/obj/effect/particle_effect/foam/metal
name = "aluminium foam"
metal = 1
icon_state = "mfoam"
/obj/effect/particle_effect/foam/metal/iron
name = "iron foam"
metal = 2
/obj/effect/particle_effect/foam/New(loc)
..(loc)
create_reagents(1000) //limited by the size of the reagent holder anyway.
START_PROCESSING(SSfastprocess, src)
playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3)
/obj/effect/particle_effect/foam/Destroy()
STOP_PROCESSING(SSfastprocess, src)
return ..()
/obj/effect/particle_effect/foam/proc/kill_foam()
STOP_PROCESSING(SSfastprocess, src)
if(metal)
var/obj/structure/foamedmetal/M = new(src.loc)
M.metal = metal
M.updateicon()
flick("[icon_state]-disolve", src)
QDEL_IN(src, 5)
/obj/effect/particle_effect/foam/process()
lifetime--
if(lifetime < 1)
kill_foam()
return
var/fraction = 1/initial(lifetime)
for(var/obj/O in range(0,src))
if(O.type == src.type)
continue
reagents.reaction(O, VAPOR, fraction)
var/hit = 0
for(var/mob/living/L in range(0,src))
hit += foam_mob(L)
if(hit)
lifetime++ //this is so the decrease from mobs hit and the natural decrease don't cumulate.
var/T = get_turf(src)
reagents.reaction(T, VAPOR, fraction)
if(--amount < 0)
return
spread_foam()
/obj/effect/particle_effect/foam/proc/foam_mob(mob/living/L)
if(lifetime<1)
return 0
if(!istype(L))
return 0
var/fraction = 1/initial(lifetime)
reagents.reaction(L, VAPOR, fraction)
lifetime--
return 1
/obj/effect/particle_effect/foam/Crossed(atom/movable/AM)
if(istype(AM, /mob/living/carbon))
var/mob/living/carbon/M = AM
M.slip(5, 2, src)
/obj/effect/particle_effect/foam/metal/Crossed(atom/movable/AM)
return
/obj/effect/particle_effect/foam/proc/spread_foam()
var/turf/t_loc = get_turf(src)
for(var/turf/T in t_loc.GetAtmosAdjacentTurfs())
var/obj/effect/particle_effect/foam/foundfoam = locate() in T //Don't spread foam where there's already foam!
if(foundfoam)
continue
for(var/mob/living/L in T)
foam_mob(L)
var/obj/effect/particle_effect/foam/F = PoolOrNew(src.type, T)
F.amount = amount
reagents.copy_to(F, (reagents.total_volume))
F.color = color
F.metal = metal
/obj/effect/particle_effect/foam/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(prob(max(0, exposed_temperature - 475))) //foam dissolves when heated
kill_foam()
/obj/effect/particle_effect/foam/metal/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
///////////////////////////////////////////////
//FOAM EFFECT DATUM
/datum/effect_system/foam_spread
var/amount = 10 // the size of the foam spread.
var/obj/chemholder
effect_type = /obj/effect/particle_effect/foam
var/metal = 0
/datum/effect_system/foam_spread/metal
effect_type = /obj/effect/particle_effect/foam/metal
/datum/effect_system/foam_spread/New()
..()
chemholder = PoolOrNew(/obj)
var/datum/reagents/R = new/datum/reagents(1000)
chemholder.reagents = R
R.my_atom = chemholder
/datum/effect_system/foam_spread/Destroy()
qdel(chemholder)
chemholder = null
return ..()
/datum/effect_system/foam_spread/set_up(amt=5, loca, datum/reagents/carry = null)
if(istype(loca, /turf/))
location = loca
else
location = get_turf(loca)
amount = round(sqrt(amt / 2), 1)
carry.copy_to(chemholder, 4*carry.total_volume) //The foam holds 4 times the total reagents volume for balance purposes.
/datum/effect_system/foam_spread/metal/set_up(amt=5, loca, datum/reagents/carry = null, metaltype)
..()
metal = metaltype
/datum/effect_system/foam_spread/start()
var/obj/effect/particle_effect/foam/foundfoam = locate() in location
if(foundfoam)//If there was already foam where we start, we add our foaminess to it.
foundfoam.amount += amount
else
var/obj/effect/particle_effect/foam/F = PoolOrNew(effect_type, location)
var/foamcolor = mix_color_from_reagents(chemholder.reagents.reagent_list)
chemholder.reagents.copy_to(F, chemholder.reagents.total_volume/amount)
F.color = foamcolor
F.amount = amount
F.metal = metal
//////////////////////////////////////////////////////////
// FOAM STRUCTURE. Formed by metal foams. Dense and opaque, but easy to break
/obj/structure/foamedmetal
icon = 'icons/effects/effects.dmi'
icon_state = "metalfoam"
density = 1
opacity = 1 // changed in New()
anchored = 1
unacidable = 1
name = "foamed metal"
desc = "A lightweight foamed metal wall."
gender = PLURAL
var/metal = 1 // 1=aluminium, 2=iron
/obj/structure/foamedmetal/New()
..()
air_update_turf(1)
/obj/structure/foamedmetal/Destroy()
density = 0
air_update_turf(1)
return ..()
/obj/structure/foamedmetal/Move()
var/turf/T = loc
..()
move_update_air(T)
/obj/structure/foamedmetal/proc/updateicon()
if(metal == 1)
icon_state = "metalfoam"
else
icon_state = "ironfoam"
/obj/structure/foamedmetal/ex_act(severity, target)
qdel(src)
/obj/structure/foamedmetal/blob_act(obj/effect/blob/B)
qdel(src)
/obj/structure/foamedmetal/bullet_act()
..()
if(metal==1 || prob(50))
qdel(src)
/obj/structure/foamedmetal/attack_paw(mob/user)
attack_hand(user)
/obj/structure/foamedmetal/attack_animal(mob/living/simple_animal/user)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
if(user.environment_smash >= 1)
user.do_attack_animation(src)
user << "<span class='notice'>You smash apart the foam wall.</span>"
qdel(src)
/obj/structure/foamedmetal/attack_hulk(mob/living/carbon/human/user)
..(user, 1)
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
if(prob(75 - metal*25))
user.visible_message("<span class='danger'>[user] smashes through the foamed metal!</span>", \
"<span class='danger'>You smash through the metal foam wall!</span>")
qdel(src)
return 1
/obj/structure/foamedmetal/attack_alien(mob/living/carbon/alien/humanoid/user)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
if(prob(75 - metal*25))
user.visible_message("<span class='danger'>[user] smashes through the foamed metal!</span>", \
"<span class='danger'>You smash through the metal foam wall!</span>")
qdel(src)
/obj/structure/foamedmetal/attack_slime(mob/living/simple_animal/slime/user)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
if(!user.is_adult)
attack_hand(user)
return
if(prob(75 - metal*25))
user.visible_message("<span class='danger'>[user] smashes through the foamed metal!</span>", \
"<span class='danger'>You smash through the metal foam wall!</span>")
qdel(src)
/obj/structure/foamedmetal/attack_hand(mob/user)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
user << "<span class='warning'>You hit the metal foam but bounce off it!</span>"
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
/obj/structure/foamedmetal/attacked_by(obj/item/I, mob/living/user)
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1) //the item attack sound is muffled by the foam.
if(prob(I.force*20 - metal*25))
user.visible_message("<span class='danger'>[user] smashes through the foamed metal!</span>", \
"<span class='danger'>You smash through the foamed metal with \the [I]!</span>")
qdel(src)
else
user << "<span class='warning'>You hit the metal foam to no effect!</span>"
/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target, height=1.5)
return !density
/obj/structure/foamedmetal/CanAtmosPass()
return !density
@@ -0,0 +1,137 @@
/////////////////////////////////////////////
//////// Attach a trail to any object, that spawns when it moves (like for the jetpack)
/// just pass in the object to attach it to in set_up
/// Then do start() to start it and stop() to stop it, obviously
/// and don't call start() in a loop that will be repeated otherwise it'll get spammed!
/////////////////////////////////////////////
/datum/effect_system/trail_follow
var/turf/oldposition
var/processing = 1
var/on = 1
/datum/effect_system/trail_follow/set_up(atom/atom)
attach(atom)
oldposition = get_turf(atom)
/datum/effect_system/trail_follow/Destroy()
oldposition = null
return ..()
/datum/effect_system/trail_follow/proc/stop()
processing = 0
on = 0
oldposition = null
/datum/effect_system/trail_follow/steam
effect_type = /obj/effect/particle_effect/steam
/datum/effect_system/trail_follow/steam/start()
if(!on)
on = 1
processing = 1
if(!oldposition)
oldposition = get_turf(holder)
if(processing)
processing = 0
if(number < 3)
var/obj/effect/particle_effect/steam/I = PoolOrNew(/obj/effect/particle_effect/steam, oldposition)
number++
I.setDir(holder.dir)
oldposition = get_turf(holder)
spawn(10)
qdel(I)
number--
spawn(2)
if(on)
processing = 1
start()
/obj/effect/particle_effect/ion_trails
name = "ion trails"
icon_state = "ion_trails"
anchored = 1
/datum/effect_system/trail_follow/ion
effect_type = /obj/effect/particle_effect/ion_trails
/datum/effect_system/trail_follow/ion/start() //Whoever is responsible for this abomination of code should become an hero
if(!on)
on = 1
processing = 1
if(!oldposition)
oldposition = get_turf(holder)
if(processing)
processing = 0
var/turf/T = get_turf(holder)
if(T != oldposition)
if(!has_gravity(T))
var/obj/effect/particle_effect/ion_trails/I = PoolOrNew(effect_type, oldposition)
I.setDir(holder.dir)
flick("ion_fade", I)
I.icon_state = ""
spawn(20)
qdel(I)
oldposition = T
spawn(2)
if(on)
processing = 1
start()
//Reagent-based explosion effect
/datum/effect_system/reagents_explosion
var/amount // TNT equivalent
var/flashing = 0 // does explosion creates flash effect?
var/flashing_factor = 0 // factor of how powerful the flash effect relatively to the explosion
var/explosion_message = 1 //whether we show a message to mobs.
/datum/effect_system/reagents_explosion/set_up(amt, loca, flash = 0, flash_fact = 0, message = 1)
amount = amt
explosion_message = message
if(isturf(loca))
location = loca
else
location = get_turf(loca)
flashing = flash
flashing_factor = flash_fact
/datum/effect_system/reagents_explosion/start()
if(explosion_message)
location.visible_message("<span class='danger'>The solution violently explodes!</span>", \
"<span class='italics'>You hear an explosion!</span>")
if (amount <= 2)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(2, 1, location)
s.start()
for(var/mob/M in viewers(1, location))
if (prob (50 * amount))
M << "<span class='danger'>The explosion knocks you down.</span>"
M.Weaken(rand(1,5))
return
else
var/devastation = -1
var/heavy = -1
var/light = -1
var/flash = -1
// Clamp all values to MAX_EXPLOSION_RANGE
if (round(amount/12) > 0)
devastation = min (MAX_EX_DEVESTATION_RANGE, devastation + round(amount/12))
if (round(amount/6) > 0)
heavy = min (MAX_EX_HEAVY_RANGE, heavy + round(amount/6))
if (round(amount/3) > 0)
light = min (MAX_EX_LIGHT_RANGE, light + round(amount/3))
if (flashing && flashing_factor)
flash += (round(amount/4) * flashing_factor)
explosion(location, devastation, heavy, light, flash)
@@ -0,0 +1,308 @@
/////////////////////////////////////////////
//// SMOKE SYSTEMS
/////////////////////////////////////////////
/obj/effect/particle_effect/smoke
name = "smoke"
icon = 'icons/effects/96x96.dmi'
icon_state = "smoke"
pixel_x = -32
pixel_y = -32
opacity = 0
anchored = 1
mouse_opacity = 0
animate_movement = 0
var/amount = 4
var/lifetime = 5
var/opaque = 1 //whether the smoke can block the view when in enough amount
/obj/effect/particle_effect/smoke/proc/fade_out(frames = 16)
if(alpha == 0) //Handle already transparent case
return
if(frames == 0)
frames = 1 //We will just assume that by 0 frames, the coder meant "during one frame".
var/step = alpha / frames
for(var/i = 0, i < frames, i++)
alpha -= step
stoplag()
/obj/effect/particle_effect/smoke/New()
..()
create_reagents(500)
START_PROCESSING(SSobj, src)
/obj/effect/particle_effect/smoke/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/effect/particle_effect/smoke/proc/kill_smoke()
STOP_PROCESSING(SSobj, src)
addtimer(src, "fade_out", 0)
QDEL_IN(src, 10)
/obj/effect/particle_effect/smoke/process()
lifetime--
if(lifetime < 1)
kill_smoke()
return 0
for(var/mob/living/L in range(0,src))
smoke_mob(L)
return 1
/obj/effect/particle_effect/smoke/proc/smoke_mob(mob/living/carbon/C)
if(!istype(C))
return 0
if(lifetime<1)
return 0
if(C.internal != null || C.has_smoke_protection())
return 0
if(C.smoke_delay)
return 0
C.smoke_delay++
addtimer(src, "remove_smoke_delay", 10, FALSE, C)
return 1
/obj/effect/particle_effect/smoke/proc/remove_smoke_delay(mob/living/carbon/C)
if(C)
C.smoke_delay = 0
/obj/effect/particle_effect/smoke/proc/spread_smoke()
var/turf/t_loc = get_turf(src)
var/list/newsmokes = list()
for(var/turf/T in t_loc.GetAtmosAdjacentTurfs())
var/obj/effect/particle_effect/smoke/foundsmoke = locate() in T //Don't spread smoke where there's already smoke!
if(foundsmoke)
continue
for(var/mob/living/L in T)
smoke_mob(L)
var/obj/effect/particle_effect/smoke/S = new type(T)
reagents.copy_to(S, reagents.total_volume)
S.setDir(pick(cardinal))
S.amount = amount-1
S.color = color
S.lifetime = lifetime
if(S.amount>0)
if(opaque)
S.opacity = 1
newsmokes.Add(S)
if(newsmokes.len)
spawn(1) //the smoke spreads rapidly but not instantly
for(var/obj/effect/particle_effect/smoke/SM in newsmokes)
SM.spread_smoke()
/datum/effect_system/smoke_spread
var/amount = 10
effect_type = /obj/effect/particle_effect/smoke
/datum/effect_system/smoke_spread/set_up(radius = 5, loca)
if(isturf(loca))
location = loca
else
location = get_turf(loca)
amount = radius
/datum/effect_system/smoke_spread/start()
if(holder)
location = get_turf(holder)
var/obj/effect/particle_effect/smoke/S = new effect_type(location)
S.amount = amount
if(S.amount)
S.spread_smoke()
/////////////////////////////////////////////
// Bad smoke
/////////////////////////////////////////////
/obj/effect/particle_effect/smoke/bad
lifetime = 8
/obj/effect/particle_effect/smoke/bad/smoke_mob(mob/living/carbon/M)
if(..())
M.drop_item()
M.adjustOxyLoss(1)
M.emote("cough")
return 1
/obj/effect/particle_effect/smoke/bad/CanPass(atom/movable/mover, turf/target, height=0)
if(height==0) return 1
if(istype(mover, /obj/item/projectile/beam))
var/obj/item/projectile/beam/B = mover
B.damage = (B.damage/2)
return 1
/datum/effect_system/smoke_spread/bad
effect_type = /obj/effect/particle_effect/smoke/bad
/////////////////////////////////////////////
// Nanofrost smoke
/////////////////////////////////////////////
/obj/effect/particle_effect/smoke/freezing
name = "nanofrost smoke"
color = "#B2FFFF"
opaque = 0
/datum/effect_system/smoke_spread/freezing
effect_type = /obj/effect/particle_effect/smoke/freezing
var/blast = 0
/datum/effect_system/smoke_spread/freezing/proc/Chilled(atom/A)
if(istype(A,/turf/open))
var/turf/open/T = A
if(T.air)
var/datum/gas_mixture/G = T.air
if(get_dist(T, location) < 2) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air
G.temperature = 2
T.air_update_turf()
for(var/obj/effect/hotspot/H in T)
qdel(H)
var/list/G_gases = G.gases
if(G_gases["plasma"])
G.assert_gas("n2")
G_gases["n2"][MOLES] += (G_gases["plasma"][MOLES])
G_gases["plasma"][MOLES] = 0
G.garbage_collect()
for(var/obj/machinery/atmospherics/components/unary/U in T)
if(!isnull(U.welded) && !U.welded) //must be an unwelded vent pump or vent scrubber.
U.welded = 1
U.update_icon()
U.visible_message("<span class='danger'>[U] was frozen shut!</span>")
for(var/mob/living/L in T)
L.ExtinguishMob()
for(var/obj/item/Item in T)
Item.extinguish()
/datum/effect_system/smoke_spread/freezing/set_up(radius = 5, loca, blasting = 0)
..()
blast = blasting
/datum/effect_system/smoke_spread/freezing/start()
if(blast)
for(var/turf/T in RANGE_TURFS(2, location))
Chilled(T)
..()
/////////////////////////////////////////////
// Sleep smoke
/////////////////////////////////////////////
/obj/effect/particle_effect/smoke/sleeping
color = "#9C3636"
lifetime = 10
/obj/effect/particle_effect/smoke/sleeping/smoke_mob(mob/living/carbon/M)
if(..())
M.drop_item()
M.Sleeping(max(M.sleeping,10))
M.emote("cough")
return 1
/datum/effect_system/smoke_spread/sleeping
effect_type = /obj/effect/particle_effect/smoke/sleeping
/////////////////////////////////////////////
// Chem smoke
/////////////////////////////////////////////
/obj/effect/particle_effect/smoke/chem
lifetime = 10
/obj/effect/particle_effect/smoke/chem/process()
if(..())
var/turf/T = get_turf(src)
var/fraction = 1/initial(lifetime)
for(var/atom/movable/AM in T)
if(AM.type == src.type)
continue
reagents.reaction(AM, TOUCH, fraction)
reagents.reaction(T, TOUCH, fraction)
return 1
/obj/effect/particle_effect/smoke/chem/smoke_mob(mob/living/carbon/M)
if(lifetime<1)
return 0
if(!istype(M))
return 0
var/mob/living/carbon/C = M
if(C.internal != null || C.has_smoke_protection())
return 0
var/fraction = 1/initial(lifetime)
reagents.copy_to(C, fraction*reagents.total_volume)
reagents.reaction(M, INGEST, fraction)
return 1
/datum/effect_system/smoke_spread/chem
var/obj/chemholder
effect_type = /obj/effect/particle_effect/smoke/chem
/datum/effect_system/smoke_spread/chem/New()
..()
chemholder = PoolOrNew(/obj)
var/datum/reagents/R = new/datum/reagents(500)
chemholder.reagents = R
R.my_atom = chemholder
/datum/effect_system/smoke_spread/chem/Destroy()
qdel(chemholder)
chemholder = null
return ..()
/datum/effect_system/smoke_spread/chem/set_up(datum/reagents/carry = null, radius = 1, loca, silent = 0)
if(istype(loca, /turf/))
location = loca
else
location = get_turf(loca)
amount = radius
carry.copy_to(chemholder, 4*carry.total_volume) //The smoke holds 4 times the total reagents volume for balance purposes.
if(!silent)
var/contained = ""
for(var/reagent in carry.reagent_list)
contained += " [reagent] "
if(contained)
contained = "\[[contained]\]"
var/area/A = get_area(location)
var/where = "[A.name] | [location.x], [location.y]"
var/whereLink = "<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[location.x];Y=[location.y];Z=[location.z]'>[where]</a>"
if(carry.my_atom.fingerprintslast)
var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast)
var/more = ""
if(M)
more = "(<A HREF='?_src_=holder;adminmoreinfo=\ref[M]'>?</a>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[M]'>FLW</A>) "
message_admins("A chemical smoke reaction has taken place in ([whereLink])[contained]. Last associated key is [carry.my_atom.fingerprintslast][more].", 0, 1)
log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last associated key is [carry.my_atom.fingerprintslast].")
else
message_admins("A chemical smoke reaction has taken place in ([whereLink]). No associated key.", 0, 1)
log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.")
/datum/effect_system/smoke_spread/chem/start()
var/color = mix_color_from_reagents(chemholder.reagents.reagent_list)
if(holder)
location = get_turf(holder)
var/obj/effect/particle_effect/smoke/chem/S = new effect_type(location)
if(chemholder.reagents.total_volume > 1) // can't split 1 very well
chemholder.reagents.copy_to(S, chemholder.reagents.total_volume)
if(color)
S.color = color // give the smoke color, if it has any to begin with
S.amount = amount
if(S.amount)
S.spread_smoke() //calling process right now so the smoke immediately attacks mobs.
@@ -0,0 +1,46 @@
/////////////////////////////////////////////
//SPARK SYSTEM (like steam system)
// The attach(atom/atom) proc is optional, and can be called to attach the effect
// to something, like the RCD, so then you can just call start() and the sparks
// will always spawn at the items location.
/////////////////////////////////////////////
/obj/effect/particle_effect/sparks
name = "sparks"
icon_state = "sparks"
anchored = 1
luminosity = 1
/obj/effect/particle_effect/sparks/New()
..()
flick("sparks", src) // replay the animation
playsound(src.loc, "sparks", 100, 1)
var/turf/T = src.loc
if (istype(T, /turf))
T.hotspot_expose(1000,100)
QDEL_IN(src, 20)
/obj/effect/particle_effect/sparks/Destroy()
var/turf/T = src.loc
if (istype(T, /turf))
T.hotspot_expose(1000,100)
return ..()
/obj/effect/particle_effect/sparks/Move()
..()
var/turf/T = src.loc
if(isturf(T))
T.hotspot_expose(1000,100)
/datum/effect_system/spark_spread
effect_type = /obj/effect/particle_effect/sparks
//electricity
/obj/effect/particle_effect/sparks/electricity
name = "lightning"
icon_state = "electricity"
/datum/effect_system/lightning_spread
effect_type = /obj/effect/particle_effect/sparks/electricity
@@ -0,0 +1,53 @@
//WATER EFFECTS
/obj/effect/particle_effect/water
name = "water"
icon_state = "extinguish"
var/life = 15
mouse_opacity = 0
/obj/effect/particle_effect/water/New()
..()
QDEL_IN(src, 70)
/obj/effect/particle_effect/water/Move(turf/newloc)
if (--src.life < 1)
qdel(src)
return 0
if(newloc.density)
return 0
.=..()
/obj/effect/particle_effect/water/Bump(atom/A)
if(reagents)
reagents.reaction(A)
return ..()
/////////////////////////////////////////////
// GENERIC STEAM SPREAD SYSTEM
//Usage: set_up(number of bits of steam, use North/South/East/West only, spawn location)
// The attach(atom/atom) proc is optional, and can be called to attach the effect
// to something, like a smoking beaker, so then you can just call start() and the steam
// will always spawn at the items location, even if it's moved.
/* Example:
var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread() -- creates new system
steam.set_up(5, 0, mob.loc) -- sets up variables
OPTIONAL: steam.attach(mob)
steam.start() -- spawns the effect
*/
/////////////////////////////////////////////
/obj/effect/particle_effect/steam
name = "steam"
icon_state = "extinguish"
density = 0
/obj/effect/particle_effect/steam/New()
..()
QDEL_IN(src, 20)
/datum/effect_system/steam_spread
effect_type = /obj/effect/particle_effect/steam
+28
View File
@@ -0,0 +1,28 @@
/obj/effect/forcefield
desc = "A space wizard's magic wall."
name = "FORCEWALL"
icon_state = "m_shield"
anchored = 1
opacity = 0
density = 1
unacidable = 1
/obj/effect/forcefield/CanAtmosPass(turf/T)
return !density
/obj/effect/forcefield/cult
desc = "An unholy shield that blocks all attacks."
name = "glowing wall"
icon_state = "cultshield"
///////////Mimewalls///////////
/obj/effect/forcefield/mime
icon_state = "empty"
name = "invisible wall"
desc = "You have a bad feeling about this."
var/timeleft = 300
/obj/effect/forcefield/mime/New()
..()
QDEL_IN(src, timeleft)
+62
View File
@@ -0,0 +1,62 @@
/proc/gibs(atom/location, list/viruses, datum/dna/MobDNA)
new /obj/effect/gibspawner/generic(location,viruses,MobDNA)
/proc/hgibs(atom/location, list/viruses, datum/dna/MobDNA)
new /obj/effect/gibspawner/human(location,viruses,MobDNA)
/proc/xgibs(atom/location, list/viruses)
new /obj/effect/gibspawner/xeno(location,viruses)
/proc/robogibs(atom/location, list/viruses)
new /obj/effect/gibspawner/robot(location,viruses)
/obj/effect/gibspawner
var/sparks = 0 //whether sparks spread on Gib()
var/virusProb = 20 //the chance for viruses to spread on the gibs
var/list/gibtypes = list()
var/list/gibamounts = list()
var/list/gibdirections = list() //of lists
/obj/effect/gibspawner/New(location, var/list/viruses, var/datum/dna/MobDNA)
..()
Gib(loc,viruses,MobDNA)
/obj/effect/gibspawner/proc/Gib(atom/location, list/viruses = list(), datum/dna/MobDNA = null)
if(gibtypes.len != gibamounts.len || gibamounts.len != gibdirections.len)
world << "<span class='danger'>Gib list length mismatch!</span>"
return
var/obj/effect/decal/cleanable/blood/gibs/gib = null
if(sparks)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(2, 1, location)
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)
if(istype(location,/mob/living/carbon))
var/mob/living/carbon/digester = location
digester.stomach_contents += gib
if(viruses.len > 0)
for(var/datum/disease/D in viruses)
if(prob(virusProb))
var/datum/disease/viruus = D.Copy(1)
gib.viruses += viruus
viruus.holder = gib
if(MobDNA)
gib.blood_DNA[MobDNA.unique_enzymes] = MobDNA.blood_type
else if(istype(src, /obj/effect/gibspawner/generic)) // Probably a monkey
gib.blood_DNA["Non-human DNA"] = "A+"
var/list/directions = gibdirections[i]
if(istype(loc,/turf))
if(directions.len)
gib.streak(directions)
qdel(src)
+159
View File
@@ -0,0 +1,159 @@
//separate dm since hydro is getting bloated already
var/list/blacklisted_glowshroom_turfs = typecacheof(list(
/turf/open/floor/plating/lava,
/turf/open/floor/plating/beach/water))
/obj/effect/glowshroom
name = "glowshroom"
desc = "Mycena Bregprox, a species of mushroom that glows in the dark."
anchored = 1
opacity = 0
density = 0
icon = 'icons/obj/lighting.dmi'
icon_state = "glowshroom" //replaced in New
layer = ABOVE_NORMAL_TURF_LAYER
var/endurance = 30
var/potency = 30
var/delay = 1200
var/floor = 0
var/yield = 3
var/generation = 1
var/spreadIntoAdjacentChance = 60
obj/effect/glowshroom/glowcap
name = "glowcap"
icon_state = "glowcap"
/obj/effect/glowshroom/single
yield = 0
/obj/effect/glowshroom/examine(mob/user)
. = ..()
user << "This is a [generation]\th generation [name]!"
/obj/effect/glowshroom/New()
..()
SetLuminosity(round(potency/10))
setDir(CalcDir())
var/base_icon_state = initial(icon_state)
if(!floor)
switch(dir) //offset to make it be on the wall rather than on the floor
if(NORTH)
pixel_y = 32
if(SOUTH)
pixel_y = -32
if(EAST)
pixel_x = 32
if(WEST)
pixel_x = -32
icon_state = "[base_icon_state][rand(1,3)]"
else //if on the floor, glowshroom on-floor sprite
icon_state = "[base_icon_state]f"
addtimer(src, "Spread", delay)
/obj/effect/glowshroom/proc/Spread()
for(var/i = 1 to yield)
if(prob(1/(generation * generation) * 100))//This formula gives you diminishing returns based on generation. 100% with 1st gen, decreasing to 25%, 11%, 6, 4, 2...
var/list/possibleLocs = list()
var/spreadsIntoAdjacent = FALSE
if(prob(spreadIntoAdjacentChance))
spreadsIntoAdjacent = TRUE
for(var/turf/open/floor/earth in view(3,src))
if(is_type_in_typecache(earth, blacklisted_glowshroom_turfs))
continue
if(spreadsIntoAdjacent || !locate(/obj/effect/glowshroom) in view(1,earth))
possibleLocs += earth
CHECK_TICK
if(!possibleLocs.len)
break
var/turf/newLoc = pick(possibleLocs)
var/shroomCount = 0 //hacky
var/placeCount = 1
for(var/obj/effect/glowshroom/shroom in newLoc)
shroomCount++
for(var/wallDir in cardinal)
var/turf/isWall = get_step(newLoc,wallDir)
if(isWall.density)
placeCount++
if(shroomCount >= placeCount)
continue
var/obj/effect/glowshroom/child = new type(newLoc)//The baby mushrooms have different stats :3
child.potency = max(potency + rand(-3,6), 0)
child.yield = max(yield + rand(-1,2), 0)
child.delay = max(delay + rand(-30,60), 0)
child.endurance = max(endurance + rand(-3,6), 1)
child.generation = generation + 1
CHECK_TICK
/obj/effect/glowshroom/proc/CalcDir(turf/location = loc)
var/direction = 16
for(var/wallDir in cardinal)
var/turf/newTurf = get_step(location,wallDir)
if(newTurf.density)
direction |= wallDir
for(var/obj/effect/glowshroom/shroom in location)
if(shroom == src)
continue
if(shroom.floor) //special
direction &= ~16
else
direction &= ~shroom.dir
var/list/dirList = list()
for(var/i=1,i<=16,i <<= 1)
if(direction & i)
dirList += i
if(dirList.len)
var/newDir = pick(dirList)
if(newDir == 16)
floor = 1
newDir = 1
return newDir
floor = 1
return 1
/obj/effect/glowshroom/attacked_by(obj/item/I, mob/user)
..()
if(I.damtype != STAMINA)
endurance -= I.force
CheckEndurance()
/obj/effect/glowshroom/ex_act(severity, target)
switch(severity)
if(1)
qdel(src)
if(2)
if(prob(50))
qdel(src)
if(3)
if(prob(5))
qdel(src)
/obj/effect/glowshroom/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > 300)
endurance -= 5
CheckEndurance()
/obj/effect/glowshroom/proc/CheckEndurance()
if(endurance <= 0)
qdel(src)
/obj/effect/glowshroom/acid_act(acidpwr, toxpwr, acid_volume)
visible_message("<span class='danger'>[src] melts away!</span>")
var/obj/effect/decal/cleanable/molten_item/I = new (get_turf(src))
I.desc = "Looks like this was \an [src] some time ago."
qdel(src)
+288
View File
@@ -0,0 +1,288 @@
/obj/effect/landmark
name = "landmark"
icon = 'icons/mob/screen_gen.dmi'
icon_state = "x2"
anchored = 1
unacidable = 1
invisibility = INVISIBILITY_ABSTRACT
/obj/effect/landmark/New()
..()
tag = text("landmark*[]", name)
landmarks_list += src
switch(name) //some of these are probably obsolete
if("monkey")
monkeystart += loc
qdel(src)
return
if("start")
newplayer_start += loc
qdel(src)
return
if("wizard")
wizardstart += loc
qdel(src)
return
if("JoinLate")
latejoin += loc
qdel(src)
return
if("prisonwarp")
prisonwarp += loc
qdel(src)
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
qdel(src)
return
if("blobstart")
blobstart += loc
qdel(src)
return
if("secequipment")
secequipment += loc
qdel(src)
return
if("Emergencyresponseteam")
emergencyresponseteamspawn += loc
qdel(src)
return
if("xeno_spawn")
xeno_spawn += loc
qdel(src)
return
return 1
/obj/effect/landmark/Destroy()
landmarks_list -= src
return ..()
/obj/effect/landmark/start
name = "start"
icon = 'icons/mob/screen_gen.dmi'
icon_state = "x"
anchored = 1
/obj/effect/landmark/start/New()
..()
tag = "start*[name]"
start_landmarks_list += src
return 1
/obj/effect/landmark/start/Destroy()
start_landmarks_list -= src
return ..()
//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)
qdel(src)
//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)
qdel(src)
/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/gimmick/rank/captain/suit(src.loc)
new /obj/item/clothing/head/flatcap(src.loc)
new /obj/item/clothing/suit/toggle/labcoat/mad(src.loc)
new /obj/item/clothing/glasses/gglasses(src.loc)
qdel(src)
/obj/effect/landmark/costume/elpresidente/New()
new /obj/item/clothing/under/gimmick/rank/captain/suit(src.loc)
new /obj/item/clothing/head/flatcap(src.loc)
new /obj/item/clothing/mask/cigarette/cigar/havana(src.loc)
new /obj/item/clothing/shoes/jackboots(src.loc)
qdel(src)
/obj/effect/landmark/costume/nyangirl/New()
new /obj/item/clothing/under/schoolgirl(src.loc)
new /obj/item/clothing/head/kitty(src.loc)
new /obj/item/clothing/glasses/sunglasses/blindfold(src.loc)
qdel(src)
/obj/effect/landmark/costume/maid/New()
new /obj/item/clothing/under/blackskirt(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)
qdel(src)
/obj/effect/landmark/costume/butler/New()
new /obj/item/clothing/tie/waistcoat(src.loc)
new /obj/item/clothing/under/suit_jacket(src.loc)
new /obj/item/clothing/head/that(src.loc)
qdel(src)
/obj/effect/landmark/costume/highlander/New()
new /obj/item/clothing/under/kilt(src.loc)
new /obj/item/clothing/head/beret(src.loc)
qdel(src)
/obj/effect/landmark/costume/prig/New()
new /obj/item/clothing/tie/waistcoat(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/sneakers/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)
qdel(src)
/obj/effect/landmark/costume/plaguedoctor/New()
new /obj/item/clothing/suit/bio_suit/plaguedoctorsuit(src.loc)
new /obj/item/clothing/head/plaguedoctorhat(src.loc)
new /obj/item/clothing/mask/gas/plaguedoctor(src.loc)
qdel(src)
/obj/effect/landmark/costume/nightowl/New()
new /obj/item/clothing/suit/toggle/owlwings(src.loc)
new /obj/item/clothing/under/owl(src.loc)
new /obj/item/clothing/mask/gas/owl_mask(src.loc)
qdel(src)
/obj/effect/landmark/costume/thegriffin/New()
new /obj/item/clothing/suit/toggle/owlwings/griffinwings(src.loc)
new /obj/item/clothing/shoes/griffin(src.loc)
new /obj/item/clothing/under/griffin(src.loc)
new /obj/item/clothing/head/griffin(src.loc)
qdel(src)
/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/apron(src.loc)
qdel(src)
/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)
qdel(src)
/obj/effect/landmark/costume/commie/New()
new /obj/item/clothing/under/soviet(src.loc)
new /obj/item/clothing/head/ushanka(src.loc)
qdel(src)
/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)
qdel(src)
/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/shoes/sandal/marisa(src.loc)
new /obj/item/clothing/head/wizard/marisa/fake(src.loc)
new/obj/item/clothing/suit/wizrobe/marisa/fake(src.loc)
qdel(src)
/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)
qdel(src)
/obj/effect/landmark/costume/fakewizard/New()
new /obj/item/clothing/shoes/sandal(src.loc)
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)
qdel(src)
/obj/effect/landmark/costume/sexyclown/New()
new /obj/item/clothing/mask/gas/sexyclown(src.loc)
new /obj/item/clothing/under/rank/clown/sexy(src.loc)
qdel(src)
/obj/effect/landmark/costume/sexymime/New()
new /obj/item/clothing/mask/gas/sexymime(src.loc)
new /obj/item/clothing/under/sexymime(src.loc)
qdel(src)
//Department Security spawns
/obj/effect/landmark/start/depsec
name = "department_sec"
/obj/effect/landmark/start/depsec/New()
..()
department_security_spawns += src
/obj/effect/landmark/start/depsec/Destroy()
department_security_spawns -= src
return ..()
/obj/effect/landmark/start/depsec/supply
name = "supply_sec"
/obj/effect/landmark/start/depsec/medical
name = "medical_sec"
/obj/effect/landmark/start/depsec/engineering
name = "engineering_sec"
/obj/effect/landmark/start/depsec/science
name = "science_sec"
/obj/effect/landmark/latejoin
name = "JoinLate"
//generic event spawns
/obj/effect/landmark/event_spawn
name = "generic event spawn"
icon_state = "x4"
/obj/effect/landmark/event_spawn/New()
..()
generic_event_spawns += src
/obj/effect/landmark/event_spawn/Destroy()
generic_event_spawns -= src
return ..()
/obj/effect/landmark/ruin
var/datum/map_template/ruin/ruin_template
/obj/effect/landmark/ruin/New(loc, my_ruin_template)
name = "ruin_[ruin_landmarks.len + 1]"
..(loc)
ruin_template = my_ruin_template
ruin_landmarks |= src
/obj/effect/landmark/ruin/Destroy()
ruin_landmarks -= src
ruin_template = null
. = ..()
+18
View File
@@ -0,0 +1,18 @@
/obj/effect/manifest
name = "manifest"
icon = 'icons/mob/screen_gen.dmi'
icon_state = "x"
unacidable = 1//Just to be sure.
/obj/effect/manifest/New()
src.invisibility = INVISIBILITY_ABSTRACT
/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)
+172
View File
@@ -0,0 +1,172 @@
/obj/effect/mine
name = "dummy mine"
desc = "Better stay away from that thing."
density = 0
anchored = 1
icon = 'icons/obj/weapons.dmi'
icon_state = "uglymine"
var/triggered = 0
/obj/effect/mine/proc/mineEffect(mob/victim)
victim << "<span class='danger'>*click*</span>"
/obj/effect/mine/Crossed(AM as mob|obj)
if(isanimal(AM))
var/mob/living/simple_animal/SA = AM
if(!SA.flying)
triggermine(SA)
else
triggermine(AM)
/obj/effect/mine/proc/triggermine(mob/victim)
if(triggered)
return
visible_message("<span class='danger'>[victim] sets off \icon[src] [src]!</span>")
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
mineEffect(victim)
triggered = 1
qdel(src)
/obj/effect/mine/explosive
name = "explosive mine"
var/range_devastation = 0
var/range_heavy = 1
var/range_light = 2
var/range_flash = 3
/obj/effect/mine/explosive/mineEffect(mob/victim)
explosion(loc, range_devastation, range_heavy, range_light, range_flash)
/obj/effect/mine/stun
name = "stun mine"
var/stun_time = 8
/obj/effect/mine/stun/mineEffect(mob/victim)
if(isliving(victim))
victim.Weaken(stun_time)
/obj/effect/mine/kickmine
name = "kick mine"
/obj/effect/mine/kickmine/mineEffect(mob/victim)
if(isliving(victim) && victim.client)
victim << "<span class='userdanger'>You have been kicked FOR NO REISIN!</span>"
del(victim.client)
/obj/effect/mine/gas
name = "oxygen mine"
var/gas_amount = 360
var/gas_type = "o2"
/obj/effect/mine/gas/mineEffect(mob/victim)
atmos_spawn_air("[gas_type]=[gas_amount]")
/obj/effect/mine/gas/plasma
name = "plasma mine"
gas_type = "plasma"
/obj/effect/mine/gas/n2o
name = "\improper N2O mine"
gas_type = "n2o"
/obj/effect/mine/sound
name = "honkblaster 1000"
var/sound = 'sound/items/bikehorn.ogg'
/obj/effect/mine/sound/mineEffect(mob/victim)
playsound(loc, sound, 100, 1)
/obj/effect/mine/sound/bwoink
name = "bwoink mine"
sound = 'sound/effects/adminhelp.ogg'
/obj/effect/mine/pickup
name = "pickup"
desc = "pick me up"
icon = 'icons/effects/effects.dmi'
icon_state = "electricity2"
density = 0
var/duration = 0
/obj/effect/mine/pickup/New()
..()
animate(src, pixel_y = 4, time = 20, loop = -1)
/obj/effect/mine/pickup/triggermine(mob/victim)
if(triggered)
return
triggered = 1
invisibility = INVISIBILITY_ABSTRACT
mineEffect(victim)
qdel(src)
/obj/effect/mine/pickup/bloodbath
name = "Red Orb"
desc = "You feel angry just looking at it."
duration = 1200 //2min
color = "red"
/obj/effect/mine/pickup/bloodbath/mineEffect(mob/living/carbon/victim)
if(!victim.client || !istype(victim))
return
victim << "<span class='reallybig redtext'>RIP AND TEAR</span>"
victim << 'sound/misc/e1m1.ogg'
var/old_color = victim.client.color
var/red_splash = list(1,0,0,0.8,0.2,0, 0.8,0,0.2,0.1,0,0)
var/pure_red = list(0,0,0,0,0,0,0,0,0,1,0,0)
spawn(0)
new /obj/effect/hallucination/delusion(victim.loc,victim,force_kind="demon",duration=duration,skip_nearby=0)
var/obj/item/weapon/twohanded/required/chainsaw/doomslayer/chainsaw = new(victim.loc)
chainsaw.flags |= NODROP
victim.drop_r_hand()
victim.drop_l_hand()
victim.put_in_hands(chainsaw)
victim.reagents.add_reagent("adminordrazine",25)
victim.client.color = pure_red
animate(victim.client,color = red_splash, time = 10, easing = SINE_EASING|EASE_OUT)
sleep(10)
animate(victim.client,color = old_color, time = duration)//, easing = SINE_EASING|EASE_OUT)
sleep(duration)
victim << "<span class='notice'>Your bloodlust seeps back into the bog of your subconscious and you regain self control.<span>"
qdel(chainsaw)
qdel(src)
/obj/effect/mine/pickup/healing
name = "Blue Orb"
desc = "You feel better just looking at it."
color = "blue"
/obj/effect/mine/pickup/healing/mineEffect(mob/living/carbon/victim)
if(!victim.client || !istype(victim))
return
victim << "<span class='notice'>You feel great!</span>"
victim.revive(full_heal = 1, admin_revive = 1)
/obj/effect/mine/pickup/speed
name = "Yellow Orb"
desc = "You feel faster just looking at it."
color = "yellow"
duration = 300
/obj/effect/mine/pickup/speed/mineEffect(mob/living/carbon/victim)
if(!victim.client || !istype(victim))
return
victim << "<span class='notice'>You feel fast!</span>"
victim.status_flags |= GOTTAGOREALLYFAST
sleep(duration)
victim.status_flags &= ~GOTTAGOREALLYFAST
victim << "<span class='notice'>You slow down.</span>"
+26
View File
@@ -0,0 +1,26 @@
//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 = 1
anchored = 0
/obj/effect/beam
name = "beam"
unacidable = 1//Just to be sure.
var/def_zone
pass_flags = PASSTABLE
/obj/effect/spawner
name = "object spawner"
/obj/effect/list_container
name = "list container"
/obj/effect/list_container/mobl
name = "mobl"
var/master = null
var/list/container = list( )
+345
View File
@@ -0,0 +1,345 @@
/obj/effect/overlay
name = "overlay"
unacidable = 1
var/i_attached//Added for possible image attachments to objects. For hallucinations and the like.
/obj/effect/overlay/singularity_act()
return
/obj/effect/overlay/singularity_pull()
return
/obj/effect/overlay/beam//Not actually a projectile, just an effect.
name="beam"
icon='icons/effects/beam.dmi'
icon_state="b_beam"
var/atom/BeamSource
/obj/effect/overlay/beam/New()
..()
QDEL_IN(src, 10)
/obj/effect/overlay/temp
icon_state = "nothing"
anchored = 1
layer = ABOVE_MOB_LAYER
mouse_opacity = 0
var/duration = 10 //in deciseconds
var/randomdir = TRUE
var/timerid
/obj/effect/overlay/temp/Destroy()
..()
deltimer(timerid)
return QDEL_HINT_PUTINPOOL
/obj/effect/overlay/temp/New()
..()
if(randomdir)
setDir(pick(cardinal))
flick("[icon_state]", src) //Because we might be pulling it from a pool, flick whatever icon it uses so it starts at the start of the icon's animation.
timerid = QDEL_IN(src, duration)
/obj/effect/overlay/temp/bloodsplatter
icon = 'icons/effects/blood.dmi'
duration = 5
randomdir = FALSE
layer = BELOW_MOB_LAYER
/obj/effect/overlay/temp/bloodsplatter/New(loc, set_dir)
if(set_dir in diagonals)
icon_state = "splatter[pick(1, 2, 6)]"
else
icon_state = "splatter[pick(3, 4, 5)]"
..()
var/target_pixel_x = 0
var/target_pixel_y = 0
switch(set_dir)
if(NORTH)
target_pixel_y = 16
if(SOUTH)
target_pixel_y = -16
layer = ABOVE_MOB_LAYER
if(EAST)
target_pixel_x = 16
if(WEST)
target_pixel_x = -16
if(NORTHEAST)
target_pixel_x = 16
target_pixel_y = 16
if(NORTHWEST)
target_pixel_x = -16
target_pixel_y = 16
if(SOUTHEAST)
target_pixel_x = 16
target_pixel_y = -16
layer = ABOVE_MOB_LAYER
if(SOUTHWEST)
target_pixel_x = -16
target_pixel_y = -16
layer = ABOVE_MOB_LAYER
setDir(set_dir)
animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration)
/obj/effect/overlay/temp/heal //color is white by default, set to whatever is needed
name = "healing glow"
icon_state = "heal"
duration = 15
/obj/effect/overlay/temp/heal/New(loc, colour)
..()
pixel_x = rand(-12, 12)
pixel_y = rand(-9, 0)
if(colour)
color = colour
/obj/effect/overlay/temp/explosion
name = "explosion"
icon = 'icons/effects/96x96.dmi'
icon_state = "explosion"
pixel_x = -32
pixel_y = -32
duration = 8
/obj/effect/overlay/temp/blob
name = "blob"
icon_state = "blob_attack"
alpha = 140
randomdir = 0
duration = 6
/obj/effect/overlay/temp/guardian
randomdir = 0
/obj/effect/overlay/temp/guardian/phase
duration = 5
icon_state = "phasein"
/obj/effect/overlay/temp/guardian/phase/out
icon_state = "phaseout"
/obj/effect/overlay/temp/decoy
desc = "It's a decoy!"
duration = 15
/obj/effect/overlay/temp/decoy/New(loc, atom/mimiced_atom)
..()
alpha = initial(alpha)
if(mimiced_atom)
name = mimiced_atom.name
appearance = mimiced_atom.appearance
setDir(mimiced_atom.dir)
animate(src, alpha = 0, time = duration)
/obj/effect/overlay/temp/cult
randomdir = 0
duration = 10
/obj/effect/overlay/temp/cult/sparks
randomdir = 1
name = "blood sparks"
icon_state = "bloodsparkles"
/obj/effect/overlay/temp/cult/phase
name = "phase glow"
duration = 7
icon_state = "cultin"
/obj/effect/overlay/temp/cult/phase/New(loc, set_dir)
..()
if(set_dir)
setDir(set_dir)
/obj/effect/overlay/temp/cult/phase/out
icon_state = "cultout"
/obj/effect/overlay/temp/cult/sac
name = "maw of Nar-Sie"
icon_state = "sacconsume"
/obj/effect/overlay/temp/cult/door
name = "unholy glow"
icon_state = "doorglow"
layer = CLOSED_FIREDOOR_LAYER //above closed doors
/obj/effect/overlay/temp/cult/door/unruned
icon_state = "unruneddoorglow"
/obj/effect/overlay/temp/cult/turf
name = "unholy glow"
icon_state = "wallglow"
layer = ABOVE_NORMAL_TURF_LAYER
/obj/effect/overlay/temp/cult/turf/open/floor
icon_state = "floorglow"
duration = 5
/obj/effect/overlay/temp/ratvar
name = "ratvar's light"
duration = 8
randomdir = 0
layer = ABOVE_NORMAL_TURF_LAYER
/obj/effect/overlay/temp/ratvar/door
icon_state = "ratvardoorglow"
layer = CLOSED_FIREDOOR_LAYER //above closed doors
/obj/effect/overlay/temp/ratvar/door/window
icon_state = "ratvarwindoorglow"
/obj/effect/overlay/temp/ratvar/beam
icon_state = "ratvarbeamglow"
/obj/effect/overlay/temp/ratvar/beam/door
layer = CLOSED_FIREDOOR_LAYER //above closed doors
/obj/effect/overlay/temp/ratvar/beam/grille
layer = LOW_ITEM_LAYER //above grilles
/obj/effect/overlay/temp/ratvar/beam/itemconsume
layer = HIGH_OBJ_LAYER
/obj/effect/overlay/temp/ratvar/wall
icon_state = "ratvarwallglow"
/obj/effect/overlay/temp/ratvar/floor
icon_state = "ratvarfloorglow"
/obj/effect/overlay/temp/ratvar/window
icon_state = "ratvarwindowglow"
layer = ABOVE_WINDOW_LAYER //above windows
/obj/effect/overlay/temp/ratvar/grille
icon_state = "ratvargrilleglow"
layer = LOW_ITEM_LAYER //above grilles
/obj/effect/overlay/temp/ratvar/grille/broken
icon_state = "ratvarbrokengrilleglow"
/obj/effect/overlay/temp/ratvar/window/single
icon_state = "ratvarwindowglow_s"
/obj/effect/overlay/temp/ratvar/spearbreak
icon = 'icons/effects/64x64.dmi'
icon_state = "ratvarspearbreak"
layer = BELOW_MOB_LAYER
pixel_y = -16
pixel_x = -16
/obj/effect/overlay/temp/ratvar/sigil
name = "glowing circle"
icon = 'icons/effects/clockwork_effects.dmi'
icon_state = "sigildull"
/obj/effect/overlay/temp/ratvar/sigil/transgression
color = "#FAE48C"
layer = ABOVE_MOB_LAYER
duration = 50
/obj/effect/overlay/temp/ratvar/sigil/transgression/New()
..()
var/oldtransform = transform
animate(src, transform = matrix()*2, time = 5)
animate(transform = oldtransform, alpha = 0, time = 45)
/obj/effect/overlay/temp/ratvar/sigil/vitality
color = "#1E8CE1"
icon_state = "sigilactivepulse"
layer = BELOW_MOB_LAYER
/obj/effect/overlay/temp/ratvar/sigil/accession
color = "#AF0AAF"
layer = ABOVE_MOB_LAYER
duration = 50
icon_state = "sigilactiveoverlay"
alpha = 0
/obj/effect/overlay/temp/revenant
name = "spooky lights"
icon_state = "purplesparkles"
/obj/effect/overlay/temp/revenant/cracks
name = "glowing cracks"
icon_state = "purplecrack"
duration = 6
/obj/effect/overlay/temp/emp
name = "emp sparks"
icon_state = "empdisable"
/obj/effect/overlay/temp/emp/pulse
name = "emp pulse"
icon_state = "emp pulse"
duration = 8
randomdir = 0
/obj/effect/overlay/temp/gib_animation
icon = 'icons/mob/mob.dmi'
duration = 15
/obj/effect/overlay/temp/gib_animation/New(loc, gib_icon)
icon_state = gib_icon // Needs to be before ..() so icon is correct
..()
/obj/effect/overlay/temp/gib_animation/ex_act(severity)
return //so the overlay isn't deleted by the explosion that gibbed the mob.
/obj/effect/overlay/temp/gib_animation/animal
icon = 'icons/mob/animal.dmi'
/obj/effect/overlay/temp/dust_animation
icon = 'icons/mob/mob.dmi'
duration = 15
/obj/effect/overlay/temp/dust_animation/New(loc, dust_icon)
icon_state = dust_icon // Before ..() so the correct icon is flick()'d
..()
/obj/effect/overlay/temp/sparkle
icon = 'icons/effects/effects.dmi'
icon_state = "shieldsparkles"
mouse_opacity = 0
density = 0
duration = 10
var/atom/movable/attached_to
/obj/effect/overlay/temp/sparkle/New(atom/movable/AM)
..()
if(istype(AM))
attached_to = AM
attached_to.overlays += src
/obj/effect/overlay/temp/sparkle/Destroy()
if(attached_to)
attached_to.overlays -= src
attached_to = null
. = ..()
/obj/effect/overlay/temp/sparkle/tailsweep
icon_state = "tailsweep"
/obj/effect/overlay/palmtree_r
name = "Palm tree"
icon = 'icons/misc/beach2.dmi'
icon_state = "palm1"
density = 1
layer = WALL_OBJ_LAYER
anchored = 1
/obj/effect/overlay/palmtree_l
name = "Palm tree"
icon = 'icons/misc/beach2.dmi'
icon_state = "palm2"
density = 1
layer = WALL_OBJ_LAYER
anchored = 1
/obj/effect/overlay/coconut
name = "Coconuts"
icon = 'icons/misc/beach.dmi'
icon_state = "coconuts"
+68
View File
@@ -0,0 +1,68 @@
/obj/effect
icon = 'icons/effects/effects.dmi'
/obj/effect/portal
name = "portal"
desc = "Looks unstable. Best to test it with the clown."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "portal"
density = 1
unacidable = 1//Can't destroy energy portals.
var/obj/item/target = null
var/creator = null
anchored = 1
var/precision = 1 // how close to the portal you will teleport. 0 = on the portal, 1 = adjacent
/obj/effect/portal/Bumped(mob/M as mob|obj)
teleport(M)
/obj/effect/portal/attack_hand(mob/user)
if(Adjacent(user))
teleport(user)
/obj/effect/portal/attackby(obj/item/weapon/W, mob/user, params)
if(user && Adjacent(user))
teleport(user)
/obj/effect/portal/New(loc, turf/target, creator=null, lifespan=300)
..()
portals += src
src.target = target
src.creator = creator
var/area/A = get_area(target)
if(A && A.noteleport) // No point in persisting if the target is unreachable.
qdel(src)
return
if(lifespan > 0)
spawn(lifespan)
qdel(src)
/obj/effect/portal/Destroy()
portals -= src
if(istype(creator, /obj/item/weapon/hand_tele))
var/obj/item/weapon/hand_tele/O = creator
O.active_portals--
else if(istype(creator, /obj/item/weapon/gun/energy/wormhole_projector))
var/obj/item/weapon/gun/energy/wormhole_projector/P = creator
P.portal_destroyed(src)
creator = null
return ..()
/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 (!( target ))
qdel(src)
return
if (istype(M, /atom/movable))
if(istype(M, /mob/living/simple_animal/hostile/megafauna))
message_admins("[M] (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[M]'>FLW</A>) has teleported through [src].")
do_teleport(M, target, precision) ///You will appear adjacent to the beacon
@@ -0,0 +1,97 @@
/obj/effect/spawner/newbomb
name = "bomb"
icon = 'icons/mob/screen_gen.dmi'
icon_state = "x"
var/btype = 0 // 0=radio, 1=prox, 2=time
var/btemp1 = 1500
var/btemp2 = 1000 // tank temperatures
/obj/effect/spawner/newbomb/timer
btype = 2
syndicate
btemp1 = 150
btemp2 = 20
/obj/effect/spawner/newbomb/proximity
btype = 1
/obj/effect/spawner/newbomb/radio
btype = 0
/obj/effect/spawner/newbomb/New()
..()
switch (src.btype)
// radio
if (0)
var/obj/item/device/transfer_valve/V = new(src.loc)
var/obj/item/weapon/tank/internals/plasma/PT = new(V)
var/obj/item/weapon/tank/internals/oxygen/OT = new(V)
var/obj/item/device/assembly/signaler/S = new(V)
V.tank_one = PT
V.tank_two = OT
V.attached_device = S
S.holder = V
S.toggle_secure()
PT.master = V
OT.master = V
PT.air_contents.temperature = btemp1 + T0C
OT.air_contents.temperature = btemp2 + T0C
V.update_icon()
// proximity
if (1)
var/obj/item/device/transfer_valve/V = new(src.loc)
var/obj/item/weapon/tank/internals/plasma/PT = new(V)
var/obj/item/weapon/tank/internals/oxygen/OT = new(V)
var/obj/item/device/assembly/prox_sensor/P = new(V)
V.tank_one = PT
V.tank_two = OT
V.attached_device = P
P.holder = V
P.toggle_secure()
PT.master = V
OT.master = V
PT.air_contents.temperature = btemp1 + T0C
OT.air_contents.temperature = btemp2 + T0C
V.update_icon()
// timer
if (2)
var/obj/item/device/transfer_valve/V = new(src.loc)
var/obj/item/weapon/tank/internals/plasma/PT = new(V)
var/obj/item/weapon/tank/internals/oxygen/OT = new(V)
var/obj/item/device/assembly/timer/T = new(V)
V.tank_one = PT
V.tank_two = OT
V.attached_device = T
T.holder = V
T.toggle_secure()
PT.master = V
OT.master = V
T.time = 30
PT.air_contents.temperature = btemp1 + T0C
OT.air_contents.temperature = btemp2 + T0C
V.update_icon()
qdel(src)
@@ -0,0 +1,40 @@
/obj/effect/gibspawner
/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()
playsound(src, 'sound/effects/blobattack.ogg', 40, 1)
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/up,/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/body,/obj/effect/decal/cleanable/blood/gibs/limb,/obj/effect/decal/cleanable/blood/gibs/core)
gibamounts = list(1,1,1,1,1,1,1)
/obj/effect/gibspawner/human/New()
playsound(src, 'sound/effects/blobattack.ogg', 50, 1)
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/xeno
gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs/up,/obj/effect/decal/cleanable/xenoblood/xgibs/down,/obj/effect/decal/cleanable/xenoblood/xgibs,/obj/effect/decal/cleanable/xenoblood/xgibs,/obj/effect/decal/cleanable/xenoblood/xgibs/body,/obj/effect/decal/cleanable/xenoblood/xgibs/limb,/obj/effect/decal/cleanable/xenoblood/xgibs/core)
gibamounts = list(1,1,1,1,1,1,1)
/obj/effect/gibspawner/xeno/New()
playsound(src, 'sound/effects/blobattack.ogg', 60, 1)
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/robot_debris/up,/obj/effect/decal/cleanable/robot_debris/down,/obj/effect/decal/cleanable/robot_debris,/obj/effect/decal/cleanable/robot_debris,/obj/effect/decal/cleanable/robot_debris,/obj/effect/decal/cleanable/robot_debris/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)
..()
@@ -0,0 +1,170 @@
/obj/effect/spawner/lootdrop
icon = 'icons/mob/screen_gen.dmi'
icon_state = "x2"
color = "#00FF00"
var/lootcount = 1 //how many items will be spawned
var/lootdoubles = 1 //if the same item can be spawned twice
var/list/loot //a list of possible items to spawn e.g. list(/obj/item, /obj/structure, /obj/effect)
/obj/effect/spawner/lootdrop/New()
if(loot && loot.len)
for(var/i = lootcount, i > 0, i--)
if(!loot.len) break
var/lootspawn = pickweight(loot)
if(!lootdoubles)
loot.Remove(lootspawn)
if(lootspawn)
new lootspawn(get_turf(src))
qdel(src)
/obj/effect/spawner/lootdrop/armory_contraband
name = "armory contraband gun spawner"
lootdoubles = 0
loot = list(
/obj/item/weapon/gun/projectile/automatic/pistol = 8,
/obj/item/weapon/gun/projectile/shotgun/automatic/combat = 5,
/obj/item/weapon/gun/projectile/revolver/mateba,
/obj/item/weapon/gun/projectile/automatic/pistol/deagle
)
/obj/effect/spawner/lootdrop/gambling
name = "gambling valuables spawner"
loot = list(
/obj/item/weapon/gun/projectile/revolver/russian = 5,
/obj/item/weapon/storage/box/syndie_kit/throwing_weapons = 1,
/obj/item/toy/cards/deck/syndicate = 2
)
/obj/effect/spawner/lootdrop/grille_or_trash
name = "maint grille or trash spawner"
loot = list(/obj/structure/grille = 5,
/obj/item/weapon/cigbutt = 1,
/obj/item/trash/cheesie = 1,
/obj/item/trash/candy = 1,
/obj/item/trash/chips = 1,
/obj/item/trash/deadmouse = 1,
/obj/item/trash/pistachios = 1,
/obj/item/trash/plate = 1,
/obj/item/trash/popcorn = 1,
/obj/item/trash/raisins = 1,
/obj/item/trash/sosjerky = 1,
/obj/item/trash/syndi_cakes = 1)
/obj/effect/spawner/lootdrop/maintenance
name = "maintenance loot spawner"
//How to balance this table
//-------------------------
//The total added weight of all the entries should be (roughly) equal to the total number of lootdrops
//(take in account those that spawn more than one object!)
//
//While this is random, probabilities tells us that item distribution will have a tendency to look like
//the content of the weighted table that created them.
//The less lootdrops, the less even the distribution.
//
//If you want to give items a weight <1 you can multiply all the weights by 10
//
//the "" entry will spawn nothing, if you increase this value,
//ensure that you balance it with more spawn points
//table data:
//-----------
//aft maintenance: 24 items, 18 spots 2 extra (28/08/2014)
//asmaint: 16 items, 11 spots 0 extra (08/08/2014)
//asmaint2: 36 items, 26 spots 2 extra (28/08/2014)
//fpmaint: 5 items, 4 spots 0 extra (08/08/2014)
//fpmaint2: 12 items, 11 spots 2 extra (28/08/2014)
//fsmaint: 0 items, 0 spots 0 extra (08/08/2014)
//fsmaint2: 40 items, 27 spots 5 extra (28/08/2014)
//maintcentral: 2 items, 2 spots 0 extra (08/08/2014)
//port: 5 items, 5 spots 0 extra (08/08/2014)
loot = list(
/obj/item/bodybag = 1,
/obj/item/clothing/glasses/meson = 2,
/obj/item/clothing/glasses/sunglasses = 1,
/obj/item/clothing/gloves/color/fyellow = 1,
/obj/item/clothing/head/hardhat = 1,
/obj/item/clothing/head/hardhat/red = 1,
/obj/item/clothing/head/that{throwforce = 1; throwing = 1} = 1,
/obj/item/clothing/head/ushanka = 1,
/obj/item/clothing/head/welding = 1,
/obj/item/clothing/mask/gas = 15,
/obj/item/clothing/suit/hazardvest = 1,
/obj/item/clothing/under/rank/vice = 1,
/obj/item/device/assembly/prox_sensor = 4,
/obj/item/device/assembly/timer = 3,
/obj/item/device/flashlight = 4,
/obj/item/device/flashlight/pen = 1,
/obj/item/device/multitool = 2,
/obj/item/device/radio/off = 2,
/obj/item/device/t_scanner = 5,
/obj/item/weapon/airlock_painter = 1,
/obj/item/stack/cable_coil = 4,
/obj/item/stack/cable_coil{amount = 5} = 6,
/obj/item/stack/medical/bruise_pack = 1,
/obj/item/stack/rods{amount = 10} = 9,
/obj/item/stack/rods{amount = 23} = 1,
/obj/item/stack/rods{amount = 50} = 1,
/obj/item/stack/sheet/cardboard = 2,
/obj/item/stack/sheet/metal{amount = 20} = 1,
/obj/item/stack/sheet/mineral/plasma = 1,
/obj/item/stack/sheet/rglass = 1,
/obj/item/weapon/book/manual/wiki/engineering_construction = 1,
/obj/item/weapon/book/manual/wiki/engineering_hacking = 1,
/obj/item/clothing/head/cone = 1,
/obj/item/weapon/coin/silver = 1,
/obj/item/weapon/coin/twoheaded = 1,
/obj/item/weapon/poster/contraband = 1,
/obj/item/weapon/poster/legit = 1,
/obj/item/weapon/crowbar = 1,
/obj/item/weapon/crowbar/red = 1,
/obj/item/weapon/extinguisher = 11,
//obj/item/weapon/gun/projectile/revolver/russian = 1, //disabled until lootdrop is a proper world proc.
/obj/item/weapon/hand_labeler = 1,
/obj/item/weapon/paper/crumpled = 1,
/obj/item/weapon/pen = 1,
/obj/item/weapon/reagent_containers/spray/pestspray = 1,
/obj/item/weapon/reagent_containers/glass/rag = 3,
/obj/item/weapon/stock_parts/cell = 3,
/obj/item/weapon/storage/belt/utility = 2,
/obj/item/weapon/storage/box = 2,
/obj/item/weapon/storage/box/cups = 1,
/obj/item/weapon/storage/box/donkpockets = 1,
/obj/item/weapon/storage/box/lights/mixed = 3,
/obj/item/weapon/storage/box/hug/medical = 1,
/obj/item/weapon/storage/fancy/cigarettes/dromedaryco = 1,
/obj/item/weapon/storage/toolbox/mechanical = 1,
/obj/item/weapon/screwdriver = 3,
/obj/item/weapon/tank/internals/emergency_oxygen = 2,
/obj/item/weapon/vending_refill/cola = 1,
/obj/item/weapon/weldingtool = 3,
/obj/item/weapon/wirecutters = 1,
/obj/item/weapon/wrench = 4,
/obj/item/weapon/relic = 3,
/obj/item/weaponcrafting/reciever = 1,
/obj/item/clothing/head/cone = 2,
/obj/item/weapon/grenade/smokebomb = 2,
/obj/item/device/geiger_counter = 3,
/obj/item/weapon/reagent_containers/food/snacks/grown/citrus/orange = 1,
/obj/item/device/radio/headset = 1,
/obj/item/device/assembly/infra = 1,
/obj/item/device/assembly/igniter = 2,
/obj/item/device/assembly/signaler = 2,
/obj/item/device/assembly/mousetrap = 2,
/obj/item/weapon/reagent_containers/syringe = 2,
/obj/item/clothing/gloves/color/random = 8,
/obj/item/clothing/shoes/laceup = 1,
/obj/item/weapon/storage/secure/briefcase = 3,
"" = 4
)
/obj/effect/spawner/lootdrop/crate_spawner
name = "lootcrate spawner"
lootdoubles = 0
loot = list(
/obj/structure/closet/crate/secure/loot = 20,
"" = 80
)
@@ -0,0 +1,33 @@
/*
Because mapping is already tedious enough this spawner let you spawn generic
"sets" of objects rather than having to make the same object stack again and
again.
*/
/obj/effect/spawner/structure
name = "map structure spawner"
var/list/spawn_list
/obj/effect/spawner/structure/New()
if(spawn_list && spawn_list.len)
for(var/i = 1, i <= spawn_list.len, i++)
var/to_spawn = spawn_list[i]
new to_spawn(get_turf(src))
qdel(src)
/obj/effect/spawner/structure/window
icon = 'icons/obj/structures.dmi'
icon_state = "window_spawner"
name = "window spawner"
spawn_list = list(
/obj/structure/grille,
/obj/structure/window/fulltile
)
/obj/effect/spawner/structure/window/reinforced
name = "reinforced window spawner"
icon_state = "rwindow_spawner"
spawn_list = list(
/obj/structure/grille,
/obj/structure/window/reinforced/fulltile
)
@@ -0,0 +1,28 @@
/obj/effect/vaultspawner
var/maxX = 6
var/maxY = 6
var/minX = 2
var/minY = 2
/obj/effect/vaultspawner/New(turf/location,lX = minX,uX = maxX,lY = minY,uY = maxY,type = null)
if(!type)
type = pick("sandstone","rock","alien")
var/lowBoundX = location.x
var/lowBoundY = location.y
var/hiBoundX = location.x + rand(lX,uX)
var/hiBoundY = location.y + rand(lY,uY)
var/z = location.z
for(var/i = lowBoundX,i<=hiBoundX,i++)
for(var/j = lowBoundY,j<=hiBoundY,j++)
var/turf/T = locate(i,j,z)
if(i == lowBoundX || i == hiBoundX || j == lowBoundY || j == hiBoundY)
T.ChangeTurf(/turf/closed/wall/vault)
else
T.ChangeTurf(/turf/open/floor/vault)
T.icon_state = "[type]vault"
qdel(src)
+223
View File
@@ -0,0 +1,223 @@
//generic procs copied from obj/effect/alien
/obj/effect/spider
name = "web"
desc = "it's stringy and sticky"
anchored = 1
density = 0
var/health = 15
//similar to weeds, but only barfed out by nurses manually
/obj/effect/spider/ex_act(severity, target)
switch(severity)
if(1)
qdel(src)
if(2)
if (prob(50))
qdel(src)
if(3)
if (prob(5))
qdel(src)
/obj/effect/spider/attacked_by(obj/item/I, mob/user)
..()
var/damage = I.force
take_damage(damage, I.damtype, 1)
/obj/effect/spider/bullet_act(obj/item/projectile/P)
. = ..()
take_damage(P.damage, P.damage_type, 0)
/obj/effect/spider/proc/take_damage(damage, damage_type = BRUTE, sound_effect = 1)
switch(damage_type)
if(BURN)
damage *= 2
if(sound_effect)
playsound(loc, 'sound/items/Welder.ogg', 100, 1)
if(BRUTE)//the stickiness of the web mutes all attack sounds except fire damage type
damage *= 0.25
else
return
health -= damage
if(health <= 0)
qdel(src)
/obj/effect/spider/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > 300)
take_damage(5, BURN, 0)
/obj/effect/spider/stickyweb
icon_state = "stickyweb1"
/obj/effect/spider/stickyweb/New()
if(prob(50))
icon_state = "stickyweb2"
/obj/effect/spider/stickyweb/CanPass(atom/movable/mover, turf/target, height=0)
if(height==0) return 1
if(istype(mover, /mob/living/simple_animal/hostile/poison/giant_spider))
return 1
else if(istype(mover, /mob/living))
if(prob(50))
mover << "<span class='danger'>You get stuck in \the [src] for a moment.</span>"
return 0
else if(istype(mover, /obj/item/projectile))
return prob(30)
return 1
/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/player_spiders = 0
var/poison_type = "toxin"
var/poison_per_bite = 5
var/list/faction = list("spiders")
/obj/effect/spider/eggcluster/New()
pixel_x = rand(3,-3)
pixel_y = rand(3,-3)
START_PROCESSING(SSobj, src)
/obj/effect/spider/eggcluster/process()
amount_grown += rand(0,2)
if(amount_grown >= 100)
var/num = rand(3,12)
for(var/i=0, i<num, i++)
var/obj/effect/spider/spiderling/S = new /obj/effect/spider/spiderling(src.loc)
S.poison_type = poison_type
S.poison_per_bite = poison_per_bite
S.faction = faction.Copy()
if(player_spiders)
S.player_spiders = 1
qdel(src)
/obj/effect/spider/spiderling
name = "spiderling"
desc = "It never stays still for long."
icon_state = "spiderling"
anchored = 0
layer = PROJECTILE_HIT_THRESHHOLD_LAYER
health = 3
var/amount_grown = 0
var/grow_as = null
var/obj/machinery/atmospherics/components/unary/vent_pump/entry_vent
var/travelling_in_vent = 0
var/player_spiders = 0
var/poison_type = "toxin"
var/poison_per_bite = 5
var/list/faction = list("spiders")
/obj/effect/spider/spiderling/New()
pixel_x = rand(6,-6)
pixel_y = rand(6,-6)
START_PROCESSING(SSobj, src)
/obj/effect/spider/spiderling/Bump(atom/user)
if(istype(user, /obj/structure/table))
src.loc = user.loc
else
..()
/obj/effect/spider/spiderling/process()
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)
var/list/vents = list()
var/datum/pipeline/entry_vent_parent = entry_vent.PARENT1
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in entry_vent_parent.other_atmosmch)
vents.Add(temp_vent)
if(!vents.len)
entry_vent = null
return
var/obj/machinery/atmospherics/components/unary/vent_pump/exit_vent = pick(vents)
if(prob(50))
visible_message("<B>[src] scrambles into the ventillation ducts!</B>", \
"<span class='italics'>You hear something scampering through the ventilation ducts.</span>")
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))
audible_message("<span class='italics'>You hear something scampering through the ventilation ducts.</span>")
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)
//=================
else if(prob(33))
var/list/nearby = oview(10, src)
if(nearby.len)
var/target_atom = pick(nearby)
walk_to(src, target_atom)
if(prob(40))
src.visible_message("<span class='notice'>\The [src] skitters[pick(" away"," around","")].</span>")
else if(prob(10))
//ventcrawl!
for(var/obj/machinery/atmospherics/components/unary/vent_pump/v in view(7,src))
if(!v.welded)
entry_vent = v
walk_to(src, entry_vent, 1)
break
if(isturf(loc))
amount_grown += rand(0,2)
if(amount_grown >= 100)
if(!grow_as)
grow_as = pick(typesof(/mob/living/simple_animal/hostile/poison/giant_spider))
var/mob/living/simple_animal/hostile/poison/giant_spider/S = new grow_as(src.loc)
S.poison_per_bite = poison_per_bite
S.poison_type = poison_type
S.faction = faction.Copy()
if(player_spiders)
S.playable_spider = TRUE
notify_ghosts("Spider [S.name] can be controlled", null, enter_link="<a href=?src=\ref[S];activate=1>(Click to play)</a>", source=S, action=NOTIFY_ATTACK)
qdel(src)
/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/container_resist()
var/mob/living/user = usr
var/breakout_time = 2
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
user << "<span class='notice'>You struggle against the tight bonds... (This will take about [breakout_time] minutes.)</span>"
visible_message("You see something struggling and writhing in \the [src]!")
if(do_after(user,(breakout_time*60*10), target = src))
if(!user || user.stat != CONSCIOUS || user.loc != src)
return
qdel(src)
/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 ..()
+192
View File
@@ -0,0 +1,192 @@
/* Simple object type, calls a proc when "stepped" on by something */
/obj/effect/step_trigger
var/affect_ghosts = 0
var/stopper = 1 // stops throwers
var/mobs_only = 0
invisibility = INVISIBILITY_ABSTRACT // nope cant see this shit
anchored = 1
/obj/effect/step_trigger/proc/Trigger(atom/movable/A)
return 0
/obj/effect/step_trigger/Crossed(H as mob|obj)
..()
if(!H)
return
if(istype(H, /mob/dead/observer) && !affect_ghosts)
return
if(!istype(H, /mob) && mobs_only)
return
Trigger(H)
/* Sends a message to mob when triggered*/
/obj/effect/step_trigger/message
var/message //the message to give to the mob
var/once = 1
/obj/effect/step_trigger/message/Trigger(mob/M)
if(M.client)
M << "<span class='info'>[message]</span>"
if(once)
qdel(src)
/* Tosses things in a certain direction */
/obj/effect/step_trigger/thrower
var/direction = SOUTH // the direction of throw
var/tiles = 3 // if 0: forever until atom hits a stopper
var/immobilize = 1 // if nonzero: prevents mobs from moving while they're being flung
var/speed = 1 // delay of movement
var/facedir = 0 // if 1: atom faces the direction of movement
var/nostop = 0 // if 1: will only be stopped by teleporters
var/list/affecting = list()
/obj/effect/step_trigger/thrower/Trigger(atom/A)
if(!A || !istype(A, /atom/movable))
return
var/atom/movable/AM = A
var/curtiles = 0
var/stopthrow = 0
for(var/obj/effect/step_trigger/thrower/T in orange(2, src))
if(AM in T.affecting)
return
if(ismob(AM))
var/mob/M = AM
if(immobilize)
M.canmove = 0
affecting.Add(AM)
while(AM && !stopthrow)
if(tiles)
if(curtiles >= tiles)
break
if(AM.z != src.z)
break
curtiles++
sleep(speed)
// Calculate if we should stop the process
if(!nostop)
for(var/obj/effect/step_trigger/T in get_step(AM, direction))
if(T.stopper && T != src)
stopthrow = 1
else
for(var/obj/effect/step_trigger/teleporter/T in get_step(AM, direction))
if(T.stopper)
stopthrow = 1
if(AM)
var/predir = AM.dir
step(AM, direction)
if(!facedir)
AM.setDir(predir)
affecting.Remove(AM)
if(ismob(AM))
var/mob/M = AM
if(immobilize)
M.canmove = 1
/* Stops things thrown by a thrower, doesn't do anything */
/obj/effect/step_trigger/stopper
/* Instant teleporter */
/obj/effect/step_trigger/teleporter
var/teleport_x = 0 // teleportation coordinates (if one is null, then no teleport!)
var/teleport_y = 0
var/teleport_z = 0
/obj/effect/step_trigger/teleporter/Trigger(atom/movable/A)
if(teleport_x && teleport_y && teleport_z)
A.x = teleport_x
A.y = teleport_y
A.z = teleport_z
/* Random teleporter, teleports atoms to locations ranging from teleport_x - teleport_x_offset, etc */
/obj/effect/step_trigger/teleporter/random
var/teleport_x_offset = 0
var/teleport_y_offset = 0
var/teleport_z_offset = 0
/obj/effect/step_trigger/teleporter/random/Trigger(atom/movable/A)
if(teleport_x && teleport_y && teleport_z)
if(teleport_x_offset && teleport_y_offset && teleport_z_offset)
A.x = rand(teleport_x, teleport_x_offset)
A.y = rand(teleport_y, teleport_y_offset)
A.z = rand(teleport_z, teleport_z_offset)
/* Fancy teleporter, creates sparks and smokes when used */
/obj/effect/step_trigger/teleport_fancy
var/locationx
var/locationy
var/uses = 1 //0 for infinite uses
var/entersparks = 0
var/exitsparks = 0
var/entersmoke = 0
var/exitsmoke = 0
/obj/effect/step_trigger/teleport_fancy/Trigger(mob/M)
var/dest = locate(locationx, locationy, z)
M.Move(dest)
if(entersparks)
var/datum/effect_system/spark_spread/s = new
s.set_up(4, 1, src)
s.start()
if(exitsparks)
var/datum/effect_system/spark_spread/s = new
s.set_up(4, 1, dest)
s.start()
if(entersmoke)
var/datum/effect_system/smoke_spread/s = new
s.set_up(4, 1, src, 0)
s.start()
if(exitsmoke)
var/datum/effect_system/smoke_spread/s = new
s.set_up(4, 1, dest, 0)
s.start()
uses--
if(uses == 0)
qdel(src)
/* Simple sound player, Mapper friendly! */
/obj/effect/step_trigger/sound_effect
var/sound //eg. path to the sound, inside '' eg: 'growl.ogg'
var/volume = 100
var/freq_vary = 1 //Should the frequency of the sound vary?
var/extra_range = 0 // eg World.view = 7, extra_range = 1, 7+1 = 8, 8 turfs radius
var/happens_once = 0
var/triggerer_only = 0 //Whether the triggerer is the only person who hears this
/obj/effect/step_trigger/sound_effect/Trigger(atom/movable/A)
var/turf/T = get_turf(A)
if(!T)
return
if(triggerer_only)
A.playsound_local(T, sound, volume, freq_vary)
else
playsound(T, sound, volume, freq_vary, extra_range)
if(happens_once)
qdel(src)
@@ -0,0 +1,48 @@
/obj/item/weapon/poster/legit/wanted
var/poster_desc
icon_state = "rolled_poster"
/obj/item/weapon/poster/legit/wanted/New(turf/loc, icon/person_icon, wanted_name, description)
..(loc)
name = "wanted poster ([wanted_name])"
desc = "A wanted poster for [wanted_name]."
poster_desc = description
qdel(resulting_poster)
resulting_poster = new /obj/structure/sign/poster/wanted(person_icon, wanted_name, poster_desc)
/obj/structure/sign/poster/wanted
var/wanted_name
/obj/structure/sign/poster/wanted/New(var/icon/person_icon, var/person_name, var/description)
if(!person_icon)
qdel(src)
return
name = "wanted poster ([person_name])"
wanted_name = person_name
desc = description
person_icon = icon(person_icon, dir = SOUTH)//copy the image so we don't mess with the one in the record.
var/icon/the_icon = icon("icon" = 'icons/obj/poster_wanted.dmi', "icon_state" = "wanted_background")
var/icon/icon_foreground = icon("icon" = 'icons/obj/poster_wanted.dmi', "icon_state" = "wanted_foreground")
person_icon.Shift(SOUTH, 7)
person_icon.Crop(7,4,26,30)
person_icon.Crop(-5,-2,26,29)
the_icon.Blend(person_icon, ICON_OVERLAY)
the_icon.Blend(icon_foreground, ICON_OVERLAY)
the_icon.Insert(the_icon, "wanted")
the_icon.Insert(icon('icons/obj/contraband.dmi', "poster_being_set"), "poster_being_set")
the_icon.Insert(icon('icons/obj/contraband.dmi', "poster_ripped"), "poster_ripped")
icon = the_icon
/obj/structure/sign/poster/wanted/attack_hand(mob/user)
..()
/obj/structure/sign/poster/wanted/attackby()
..()
/obj/structure/sign/poster/wanted/roll_and_drop(turf/location)
var/obj/item/weapon/poster/legit/wanted/P = new(src, null, wanted_name, desc)
P.resulting_poster = src
P.loc = location
loc = P
+31
View File
@@ -0,0 +1,31 @@
/proc/empulse(turf/epicenter, heavy_range, light_range, log=0)
if(!epicenter) return
if(!istype(epicenter, /turf))
epicenter = get_turf(epicenter.loc)
if(log)
message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ")
log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] ")
if(heavy_range > 1)
PoolOrNew(/obj/effect/overlay/temp/emp/pulse, epicenter)
if(heavy_range > light_range)
light_range = heavy_range
for(var/A in spiral_range(light_range, epicenter))
var/atom/T = A
var/distance = get_dist(epicenter, T)
if(distance < 0)
distance = 0
if(distance < heavy_range)
T.emp_act(1)
else if(distance == heavy_range)
if(prob(50))
T.emp_act(1)
else
T.emp_act(2)
else if(distance <= light_range)
T.emp_act(2)
return 1
+244
View File
@@ -0,0 +1,244 @@
//TODO: Flash range does nothing currently
/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range = 0 ,silent = 0)
set waitfor = 0
src = null //so we don't abort once src is deleted
epicenter = get_turf(epicenter)
//DO NOT REMOVE THIS SLEEP, IT BREAKS THINGS
//not sleeping causes us to ex_act() the thing that triggered the explosion
//doing that might cause it to trigger another explosion
//this is bad
//I would make this not ex_act the thing that triggered the explosion,
//but everything that explodes gives us their loc or a get_turf()
//and somethings expect us to ex_act them so they can qdel()
sleep(1) //tldr, let the calling proc call qdel(src) before we explode
// Archive the uncapped explosion for the doppler array
var/orig_dev_range = devastation_range
var/orig_heavy_range = heavy_impact_range
var/orig_light_range = light_impact_range
if(!ignorecap)
// Clamp all values to MAX_EXPLOSION_RANGE
devastation_range = min (MAX_EX_DEVESTATION_RANGE, devastation_range)
heavy_impact_range = min (MAX_EX_HEAVY_RANGE, heavy_impact_range)
light_impact_range = min (MAX_EX_LIGHT_RANGE, light_impact_range)
flash_range = min (MAX_EX_FLASH_RANGE, flash_range)
flame_range = min (MAX_EX_FLAME_RANGE, flame_range)
var/start = world.timeofday
if(!epicenter) return
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flame_range)
var/list/cached_exp_block = list()
if(adminlog)
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z] - <a href='?_src_=holder;adminplayerobservecoodjump=1;X=[epicenter.x];Y=[epicenter.y];Z=[epicenter.z]'>JMP</a>)")
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z])")
// 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
if(!silent)
var/frequency = get_rand_frequency()
for(var/mob/M in player_list)
// Double check for client
if(M && M.client)
var/turf/M_turf = get_turf(M)
if(M_turf && M_turf.z == epicenter.z)
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
// You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
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)
//postpone processing for a bit
var/postponeCycles = max(round(devastation_range/8),1)
SSlighting.postpone(postponeCycles)
SSmachine.postpone(postponeCycles)
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
var/list/affected_turfs = spiral_range_turfs(max_range, epicenter)
if(config.reactionary_explosions)
for(var/turf/T in affected_turfs) // we cache the explosion block rating of every turf in the explosion area
cached_exp_block[T] = 0
if(T.density && T.explosion_block)
cached_exp_block[T] += T.explosion_block
for(var/obj/machinery/door/D in T)
if(D.density && D.explosion_block)
cached_exp_block[T] += D.explosion_block
for(var/obj/structure/window/W in T)
if(W.reinf && W.fulltile)
cached_exp_block[T] += W.explosion_block
for(var/obj/effect/blob/B in T)
cached_exp_block[T] += B.explosion_block
CHECK_TICK
for(var/turf/T in affected_turfs)
if (!T)
continue
var/dist = cheap_hypotenuse(T.x, T.y, x0, y0)
if(config.reactionary_explosions)
var/turf/Trajectory = T
while(Trajectory != epicenter)
Trajectory = get_step_towards(Trajectory, epicenter)
dist += cached_exp_block[Trajectory]
var/flame_dist = 0
var/throw_dist = dist
if(dist < flame_range)
flame_dist = 1
if(dist < devastation_range)
dist = 1
else if(dist < heavy_impact_range)
dist = 2
else if(dist < light_impact_range)
dist = 3
else
dist = 0
//------- TURF FIRES -------
if(T)
if(flame_dist && prob(40) && !istype(T, /turf/open/space) && !T.density)
PoolOrNew(/obj/effect/hotspot, T) //Mostly for ambience!
if(dist > 0)
T.ex_act(dist)
//--- THROW ITEMS AROUND ---
var/throw_dir = get_dir(epicenter,T)
for(var/obj/item/I in T)
if(I && !I.anchored)
var/throw_range = rand(throw_dist, max_range)
var/turf/throw_at = get_ranged_target_turf(I, throw_dir, throw_range)
I.throw_speed = 4 //Temporarily change their throw_speed for embedding purposes (Reset when it finishes throwing, regardless of hitting anything)
I.throw_at_fast(throw_at, throw_range, 2)//Throw it at 2 speed, this is purely visual anyway.
CHECK_TICK
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)
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/array in doppler_arrays)
var/obj/machinery/doppler_array/A = array
A.sense_explosion(epicenter,devastation_range,heavy_impact_range,light_impact_range,took,orig_dev_range,orig_heavy_range,orig_light_range)
return 1
/proc/secondaryexplosion(turf/epicenter, range)
for(var/turf/tile in spiral_range_turfs(range, epicenter))
tile.ex_act(2)
/client/proc/check_bomb_impacts()
set name = "Check Bomb Impact"
set category = "Debug"
var/newmode = alert("Use reactionary explosions?","Check Bomb Impact", "Yes", "No")
var/turf/epicenter = get_turf(mob)
if(!epicenter)
return
var/dev = 0
var/heavy = 0
var/light = 0
var/list/choices = list("Small Bomb","Medium Bomb","Big Bomb","Custom Bomb")
var/choice = input("Bomb Size?") in choices
switch(choice)
if(null)
return 0
if("Small Bomb")
dev = 1
heavy = 2
light = 3
if("Medium Bomb")
dev = 2
heavy = 3
light = 4
if("Big Bomb")
dev = 3
heavy = 5
light = 7
if("Custom Bomb")
dev = input("Devestation range (Tiles):") as num
heavy = input("Heavy impact range (Tiles):") as num
light = input("Light impact range (Tiles):") as num
var/max_range = max(dev, heavy, light)
var/x0 = epicenter.x
var/y0 = epicenter.y
var/list/wipe_colours = list()
for(var/turf/T in spiral_range_turfs(max_range, epicenter))
wipe_colours += T
var/dist = cheap_hypotenuse(T.x, T.y, x0, y0)
if(newmode == "Yes")
var/turf/TT = T
while(TT != epicenter)
TT = get_step_towards(TT,epicenter)
if(TT.density && TT.explosion_block)
dist += TT.explosion_block
for(var/obj/machinery/door/D in TT)
if(D.density && D.explosion_block)
dist += D.explosion_block
for(var/obj/structure/window/W in TT)
if(W.explosion_block && W.fulltile)
dist += W.explosion_block
for(var/obj/effect/blob/B in T)
dist += B.explosion_block
if(dist < dev)
T.color = "red"
T.maptext = "Dev"
else if (dist < heavy)
T.color = "yellow"
T.maptext = "Heavy"
else if (dist < light)
T.color = "blue"
T.maptext = "Light"
else
continue
sleep(100)
for(var/turf/T in wipe_colours)
T.color = null
T.maptext = ""
+577
View File
@@ -0,0 +1,577 @@
var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_state" = "fire")
/obj/item
name = "item"
icon = 'icons/obj/items.dmi'
var/item_state = null
var/lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
var/righthand_file = 'icons/mob/inhands/items_righthand.dmi'
//Dimensions of the icon file used when this item is worn, eg: hats.dmi
//eg: 32x32 sprite, 64x64 sprite, etc.
//allows inhands/worn sprites to be of any size, but still centered on a mob properly
var/worn_x_dimension = 32
var/worn_y_dimension = 32
//Same as above but for inhands, uses the lefthand_ and righthand_ file vars
var/inhand_x_dimension = 32
var/inhand_y_dimension = 32
//Not on /clothing because for some reason any /obj/item can technically be "worn" with enough fuckery.
var/icon/alternate_worn_icon = null//If this is set, update_icons() will find on mob (WORN, NOT INHANDS) states in this file instead, primary use: badminnery/events
var/alternate_worn_layer = null//If this is set, update_icons() will force the on mob state (WORN, NOT INHANDS) onto this layer, instead of it's default
var/hitsound = null
var/throwhitsound = null
var/w_class = 3
var/slot_flags = 0 //This is used to determine on which slots an item can fit.
pass_flags = PASSTABLE
pressure_resistance = 3
var/obj/item/master = null
var/heat_protection = 0 //flags which determine which body parts are protected from heat. Use the HEAD, CHEST, GROIN, etc. flags. See setup.dm
var/cold_protection = 0 //flags which determine which body parts are protected from cold. Use the HEAD, CHEST, GROIN, etc. flags. See setup.dm
var/max_heat_protection_temperature //Set this variable to determine up to which temperature (IN KELVIN) the item protects against heat damage. Keep at null to disable protection. Only protects areas set by heat_protection flags
var/min_cold_protection_temperature //Set this variable to determine down to which temperature (IN KELVIN) the item protects against cold damage. 0 is NOT an acceptable number due to if(varname) tests!! Keep at null to disable protection. Only protects areas set by cold_protection flags
var/list/actions = list() //list of /datum/action's that this item has.
var/list/actions_types = list() //list of paths of action datums to give to the item on New().
//Since any item can now be a piece of clothing, this has to be put here so all items share it.
var/flags_inv //This flag is used to determine when items in someone's inventory cover others. IE helmets making it so you can't see glasses, etc.
var/item_color = null //this needs deprecating, soonish
var/body_parts_covered = 0 //see setup.dm for appropriate bit flags
//var/heat_transfer_coefficient = 1 //0 prevents all transfers, 1 is invisible
var/gas_transfer_coefficient = 1 // for leaking gas from turf to mask and vice-versa (for masks right now, but at some point, i'd like to include space helmets)
var/permeability_coefficient = 1 // for chemicals/diseases
var/siemens_coefficient = 1 // for electrical admittance/conductance (electrocution checks and shit)
var/slowdown = 0 // How much clothing is slowing you down. Negative values speeds you up
var/list/armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
var/armour_penetration = 0 //percentage of armour effectiveness to remove
var/list/allowed = null //suit storage stuff.
var/obj/item/device/uplink/hidden_uplink = null
var/strip_delay = 40
var/put_on_delay = 20
var/breakouttime = 0
var/list/materials = list()
var/origin_tech = null //Used by R&D to determine what research bonuses it grants.
var/needs_permit = 0 //Used by security bots to determine if this item is safe for public use.
var/list/attack_verb = list() //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]"
var/list/species_exception = null // list() of species types, if a species cannot put items in a certain slot, but species type is in list, it will be able to wear that item
var/suittoggled = 0
var/hooded = 0
var/mob/thrownby = null
/obj/item/mouse_drag_pointer = MOUSE_ACTIVE_POINTER //the icon to indicate this object is being dragged
//So items can have custom embedd values
//Because customisation is king
var/embed_chance = EMBED_CHANCE
var/embedded_fall_chance = EMBEDDED_ITEM_FALLOUT
var/embedded_pain_chance = EMBEDDED_PAIN_CHANCE
var/embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does while embedded (this*w_class)
var/embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does when falling out of a limb (this*w_class)
var/embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does when first embedded (this*w_class)
var/embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER //The coefficient of multiplication for the damage removing this without surgery causes (this*w_class)
var/embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME //A time in ticks, multiplied by the w_class.
var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES
var/heat = 0
var/sharpness = IS_BLUNT
var/toolspeed = 1
var/block_chance = 0
var/hit_reaction_chance = 0 //If you want to have something unrelated to blocking/armour piercing etc. Maybe not needed, but trying to think ahead/allow more freedom
//The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot.
var/list/slot_equipment_priority = null // for default list, see /mob/proc/equip_to_appropriate_slot()
// Needs to be in /obj/item because corgis can wear a lot of
// non-clothing items
var/datum/dog_fashion/dog_fashion = null
/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
if(((src in target) && !target_self) || (!istype(target.loc, /turf) && !istype(target, /turf) && not_inside))
return 0
else
return 1
/obj/item/device
icon = 'icons/obj/device.dmi'
/obj/item/New()
..()
for(var/path in actions_types)
new path(src)
/obj/item/Destroy()
if(ismob(loc))
var/mob/m = loc
m.unEquip(src, 1)
for(var/X in actions)
qdel(X)
return ..()
/obj/item/blob_act(obj/effect/blob/B)
qdel(src)
/obj/item/ex_act(severity, target)
if(severity == 1 || target == src)
qdel(src)
if(!qdeleted(src))
contents_explosion(severity, target)
//user: The mob that is suiciding
//damagetype: The type of damage the item will inflict on the user
//BRUTELOSS = 1
//FIRELOSS = 2
//TOXLOSS = 4
//OXYLOSS = 8
//Output a creative message and then return the damagetype done
/obj/item/proc/suicide_act(mob/user)
return
/obj/item/verb/move_to_top()
set name = "Move To Top"
set category = "Object"
set src in oview(1)
if(!istype(src.loc, /turf) || usr.stat || usr.restrained() || !usr.canmove)
return
var/turf/T = src.loc
src.loc = null
src.loc = T
/obj/item/examine(mob/user) //This might be spammy. Remove?
..()
var/size
switch(src.w_class)
if(1)
size = "tiny"
if(2)
size = "small"
if(3)
size = "normal-sized"
if(4)
size = "bulky"
if(5)
size = "huge"
if(6)
size = "gigantic"
else
//if ((CLUMSY in usr.mutations) && prob(50)) t = "funny-looking"
var/pronoun
if(src.gender == PLURAL)
pronoun = "They are"
else
pronoun = "It is"
user << "[pronoun] a [size] item." //e.g. They are a small item. or It is a bulky item.
if(user.research_scanner) //Mob has a research scanner active.
var/msg = "*--------* <BR>"
if(origin_tech)
msg += "<span class='notice'>Testing potentials:</span><BR>"
var/list/techlvls = params2list(origin_tech)
for(var/T in techlvls) //This needs to use the better names.
msg += "Tech: [CallTechName(T)] | magnitude: [techlvls[T]] <BR>"
else
msg += "<span class='danger'>No tech origins detected.</span><BR>"
if(materials.len)
msg += "<span class='notice'>Extractable materials:<BR>"
for(var/mat in materials)
msg += "[CallMaterialName(mat)]<BR>" //Capitize first word, remove the "$"
else
msg += "<span class='danger'>No extractable materials detected.</span><BR>"
msg += "*--------*"
user << msg
/obj/item/attack_self(mob/user)
interact(user)
/obj/item/interact(mob/user)
add_fingerprint(user)
if(hidden_uplink && hidden_uplink.active)
hidden_uplink.interact(user)
return 1
ui_interact(user)
/obj/item/ui_act(action, params)
add_fingerprint(usr)
return ..()
/obj/item/attack_hand(mob/user)
if(!user)
return
if(anchored)
return
if(burn_state == ON_FIRE)
var/mob/living/carbon/human/H = user
if(istype(H))
if(H.gloves && (H.gloves.max_heat_protection_temperature > 360))
extinguish()
user << "<span class='notice'>You put out the fire on [src].</span>"
else
user << "<span class='warning'>You burn your hand on [src]!</span>"
var/obj/item/bodypart/affecting = H.get_bodypart("[user.hand ? "l" : "r" ]_arm")
if(affecting && affecting.take_damage( 0, 5 )) // 5 burn damage
H.update_damage_overlays(0)
H.updatehealth()
return
else
extinguish()
if(istype(loc, /obj/item/weapon/storage))
//If the item is in a storage item, take it out
var/obj/item/weapon/storage/S = loc
S.remove_from_storage(src, user.loc)
throwing = 0
if(loc == user)
if(!user.unEquip(src))
return
pickup(user)
add_fingerprint(user)
if(!user.put_in_active_hand(src))
dropped(user)
/obj/item/attack_paw(mob/user)
if(!user)
return
if(anchored)
return
if(istype(loc, /obj/item/weapon/storage))
var/obj/item/weapon/storage/S = loc
S.remove_from_storage(src, user.loc)
throwing = 0
if(loc == user)
if(!user.unEquip(src))
return
pickup(user)
add_fingerprint(user)
if(!user.put_in_active_hand(src))
dropped(user)
/obj/item/attack_alien(mob/user)
var/mob/living/carbon/alien/A = user
if(!A.has_fine_manipulation)
if(src in A.contents) // To stop Aliens having items stuck in their pockets
A.unEquip(src)
user << "<span class='warning'>Your claws aren't capable of such fine manipulation!</span>"
return
attack_paw(A)
/obj/item/attack_ai(mob/user)
if(istype(src.loc, /obj/item/weapon/robot_module))
//If the item is part of a cyborg module, equip it
if(!isrobot(user))
return
var/mob/living/silicon/robot/R = user
if(!R.low_power_mode) //can't equip modules with an empty cell.
R.activate_module(src)
R.hud_used.update_robot_modules_display()
// Due to storage type consolidation this should get used more now.
// I have cleaned it up a little, but it could probably use more. -Sayu
/obj/item/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W,/obj/item/weapon/storage))
var/obj/item/weapon/storage/S = W
if(S.use_to_pickup)
if(S.collection_mode) //Mode is set to collect multiple items on a tile and we clicked on a valid one.
if(isturf(src.loc))
var/list/rejections = list()
var/success = 0
var/failure = 0
for(var/obj/item/I in src.loc)
if(S.collection_mode == 2 && !istype(I,src.type)) // We're only picking up items of the target type
failure = 1
continue
if(I.type in rejections) // To limit bag spamming: any given type only complains once
continue
if(!S.can_be_inserted(I)) // Note can_be_inserted still makes noise when the answer is no
rejections += I.type // therefore full bags are still a little spammy
failure = 1
continue
success = 1
S.handle_item_insertion(I, 1) //The 1 stops the "You put the [src] into [S]" insertion message from being displayed.
if(success && !failure)
user << "<span class='notice'>You put everything [S.preposition] [S].</span>"
else if(success)
user << "<span class='notice'>You put some things [S.preposition] [S].</span>"
else
user << "<span class='warning'>You fail to pick anything up with [S]!</span>"
else if(S.can_be_inserted(src))
S.handle_item_insertion(src)
// afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency
/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(prob(final_block_chance))
owner.visible_message("<span class='danger'>[owner] blocks [attack_text] with [src]!</span>")
return 1
return 0
/obj/item/proc/talk_into(mob/M, input, channel, spans)
return
/obj/item/proc/dropped(mob/user)
for(var/X in actions)
var/datum/action/A = X
A.Remove(user)
if(DROPDEL & flags)
qdel(src)
// called just as an item is picked up (loc is not yet changed)
/obj/item/proc/pickup(mob/user)
return
// called when this item is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
/obj/item/proc/on_exit_storage(obj/item/weapon/storage/S)
return
// called when this item is added into a storage item, which is passed on as S. The loc variable is already set to the storage item.
/obj/item/proc/on_enter_storage(obj/item/weapon/storage/S)
return
// called when "found" in pockets and storage items. Returns 1 if the search should end.
/obj/item/proc/on_found(mob/finder)
return
// called after an item is placed in an equipment slot //NOPE, for example, if you put a helmet in slot_head, it is NOT in user's head variable yet, how stupid.
// user is mob that equipped it
// slot uses the slot_X defines found in setup.dm
// for items that can be placed in multiple slots
// note this isn't called during the initial dressing of a player
/obj/item/proc/equipped(mob/user, slot)
for(var/X in actions)
var/datum/action/A = X
if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot.
A.Grant(user)
//sometimes we only want to grant the item's action if it's equipped in a specific slot.
obj/item/proc/item_action_slot_check(slot, mob/user)
return 1
//the mob M is attempting to equip this item into the slot passed through as 'slot'. Return 1 if it can do this and 0 if it can't.
//If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen.
//Set disable_warning to 1 if you wish it to not give you outputs.
/obj/item/proc/mob_can_equip(mob/M, slot, disable_warning = 0)
if(!M)
return 0
return M.can_equip(src, slot, disable_warning)
/obj/item/verb/verb_pickup()
set src in oview(1)
set category = "Object"
set name = "Pick up"
if(usr.incapacitated() || !Adjacent(usr) || usr.lying)
return
if(usr.get_active_hand() == null) // Let me know if this has any problems -Yota
usr.UnarmedAttack(src)
//This proc is executed when someone clicks the on-screen UI button.
//The default action is attack_self().
//Checks before we get to here are: mob is alive, mob is not restrained, paralyzed, asleep, resting, laying, item is on the mob.
/obj/item/proc/ui_action_click(mob/user, actiontype)
attack_self(user)
/obj/item/proc/IsReflect(var/def_zone) //This proc determines if and at what% an object will reflect energy projectiles if it's in l_hand,r_hand or wear_suit
return 0
/obj/item/proc/eyestab(mob/living/carbon/M, mob/living/carbon/user)
var/is_human_victim = 0
var/obj/item/bodypart/affecting = M.get_bodypart("head")
if(ishuman(M))
if(!affecting) //no head!
return
is_human_victim = 1
var/mob/living/carbon/human/H = M
if((H.head && H.head.flags_cover & HEADCOVERSEYES) || \
(H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || \
(H.glasses && H.glasses.flags_cover & GLASSESCOVERSEYES))
// you can't stab someone in the eyes wearing a mask!
user << "<span class='danger'>You're going to need to remove that mask/helmet/glasses first!</span>"
return
if(ismonkey(M))
var/mob/living/carbon/monkey/Mo = M
if(Mo.wear_mask && Mo.wear_mask.flags_cover & MASKCOVERSEYES)
// you can't stab someone in the eyes wearing a mask!
user << "<span class='danger'>You're going to need to remove that mask/helmet/glasses first!</span>"
return
if(isalien(M))//Aliens don't have eyes./N slimes also don't have eyes!
user << "<span class='warning'>You cannot locate any eyes on this creature!</span>"
return
if(isbrain(M))
user << "<span class='danger'>You cannot locate any organic eyes on this brain!</span>"
return
src.add_fingerprint(user)
playsound(loc, src.hitsound, 30, 1, -1)
if(M != user)
M.visible_message("<span class='danger'>[user] has stabbed [M] in the eye with [src]!</span>", \
"<span class='userdanger'>[user] stabs you in the eye with [src]!</span>")
user.do_attack_animation(M)
else
user.visible_message( \
"<span class='danger'>[user] has stabbed themself in the eyes with [src]!</span>", \
"<span class='userdanger'>You stab yourself in the eyes with [src]!</span>" \
)
if(is_human_victim)
var/mob/living/carbon/human/U = M
if(affecting.take_damage(7))
U.update_damage_overlays(0)
else
M.take_organ_damage(7)
add_logs(user, M, "attacked", "[src.name]", "(INTENT: [uppertext(user.a_intent)])")
M.adjust_blurriness(3)
M.adjust_eye_damage(rand(2,4))
if(M.eye_damage >= 10)
M.adjust_blurriness(15)
if(M.stat != DEAD)
M << "<span class='danger'>Your eyes start to bleed profusely!</span>"
if(!(M.disabilities & (NEARSIGHT | BLIND)))
if(M.become_nearsighted())
M << "<span class='danger'>You become nearsighted!</span>"
if(prob(50))
if(M.stat != DEAD)
if(M.drop_item())
M << "<span class='danger'>You drop what you're holding and clutch at your eyes!</span>"
M.adjust_blurriness(10)
M.Paralyse(1)
M.Weaken(2)
if (prob(M.eye_damage - 10 + 1))
if(M.become_blind())
M << "<span class='danger'>You go blind!</span>"
/obj/item/clean_blood()
. = ..()
if(.)
if(initial(icon) && initial(icon_state))
var/index = blood_splatter_index()
var/icon/blood_splatter_icon = blood_splatter_icons[index]
if(blood_splatter_icon)
overlays -= blood_splatter_icon
/obj/item/clothing/gloves/clean_blood()
. = ..()
if(.)
transfer_blood = 0
/obj/item/singularity_pull(S, current_size)
if(current_size >= STAGE_FOUR)
throw_at_fast(S,14,3, spin=0)
else ..()
/obj/item/acid_act(acidpwr, acid_volume)
. = 1
if(unacidable)
return
var/meltingpwr = acid_volume*acidpwr
var/melting_threshold = 100
if(meltingpwr <= melting_threshold) // so a single unit can't melt items. You need 5.1+ unit for fluoro and 10.1+ for sulphuric
return
for(var/V in armor)
if(armor[V] > 0)
.-- //it survives the acid...
break
if(. && prob(min(meltingpwr/10,90))) //chance to melt depends on acid power and volume.
var/turf/T = get_turf(src)
if(T)
var/obj/effect/decal/cleanable/molten_item/I = new (T)
I.pixel_x = rand(-16,16)
I.pixel_y = rand(-16,16)
I.desc = "Looks like this was \an [src] some time ago."
if(istype(src,/obj/item/weapon/storage))
var/obj/item/weapon/storage/S = src
S.do_quick_empty() //melted storage item drops its content.
qdel(src)
else
for(var/armour_value in armor) //but is weakened
armor[armour_value] = max(armor[armour_value]-min(acidpwr,meltingpwr/10),0)
if(!findtext(desc, "it looks slightly melted...")) //it looks slightly melted... it looks slightly melted... it looks slightly melted... etc.
desc += " it looks slightly melted..." //needs a space at the start, formatting
/obj/item/throw_impact(atom/A)
var/itempush = 1
if(w_class < 4)
itempush = 0 //too light to push anything
return A.hitby(src, 0, itempush)
/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1)
thrownby = thrower
. = ..()
throw_speed = initial(throw_speed) //explosions change this.
/obj/item/proc/remove_item_from_storage(atom/newLoc) //please use this if you're going to snowflake an item out of a obj/item/weapon/storage
if(!newLoc)
return 0
if(istype(loc,/obj/item/weapon/storage))
var/obj/item/weapon/storage/S = loc
S.remove_from_storage(src,newLoc)
return 1
return 0
/obj/item/proc/is_hot()
return heat
/obj/item/proc/is_sharp()
return sharpness
/obj/item/proc/get_dismemberment_chance(obj/item/bodypart/affecting)
if(affecting.can_dismember(src))
if((sharpness || damtype == BURN) && w_class >= 3)
. = force*(w_class-1)
/obj/item/proc/get_dismember_sound()
if(damtype == BURN)
. = 'sound/weapons/sear.ogg'
else
. = pick('sound/misc/desceration-01.ogg', 'sound/misc/desceration-02.ogg', 'sound/misc/desceration-03.ogg')
/obj/item/proc/open_flame()
var/turf/location = loc
if(ismob(location))
var/mob/M = location
if(M.l_hand == src || M.r_hand == src)
location = get_turf(M)
if(isturf(location))
location.hotspot_expose(700, 5)
+108
View File
@@ -0,0 +1,108 @@
/obj/item/wallframe
materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT*2)
flags = CONDUCT
origin_tech = "materials=1;engineering=1"
item_state = "syringe_kit"
w_class = 2
var/result_path
var/inverse = 0
// For inverse dir frames like light fixtures.
/obj/item/wallframe/proc/try_build(turf/on_wall)
if(get_dist(on_wall,usr)>1)
return
var/ndir = get_dir(on_wall, usr)
if(!(ndir in cardinal))
return
var/turf/loc = get_turf(usr)
var/area/A = loc.loc
if(!istype(loc, /turf/open/floor))
usr << "<span class='warning'>You cannot place [src] on this spot!</span>"
return
if(A.requires_power == 0 || istype(A, /area/space))
usr << "<span class='warning'>You cannot place [src] in this area!</span>"
return
if(gotwallitem(loc, ndir, inverse*2))
usr << "<span class='warning'>There's already an item on this wall!</span>"
return
return 1
/obj/item/wallframe/proc/attach(turf/on_wall)
if(result_path)
playsound(src.loc, 'sound/machines/click.ogg', 75, 1)
usr.visible_message("[usr.name] attaches [src] to the wall.",
"<span class='notice'>You attach [src] to the wall.</span>",
"<span class='italics'>You hear clicking.</span>")
var/ndir = get_dir(on_wall,usr)
if(inverse)
ndir = turn(ndir, 180)
var/obj/O = new result_path(get_turf(usr), ndir, 1)
after_attach(O)
qdel(src)
/obj/item/wallframe/proc/after_attach(var/obj/O)
transfer_fingerprints_to(O)
/obj/item/wallframe/attackby(obj/item/weapon/W, mob/user, params)
..()
if(istype(W, /obj/item/weapon/screwdriver))
// For camera-building borgs
var/turf/T = get_step(get_turf(user), user.dir)
if(istype(T, /turf/closed/wall))
T.attackby(src, user, params)
var/metal_amt = round(materials[MAT_METAL]/MINERAL_MATERIAL_AMOUNT)
var/glass_amt = round(materials[MAT_GLASS]/MINERAL_MATERIAL_AMOUNT)
if(istype(W, /obj/item/weapon/wrench) && (metal_amt || glass_amt))
user << "<span class='notice'>You dismantle [src].</span>"
if(metal_amt)
new /obj/item/stack/sheet/metal(get_turf(src), metal_amt)
if(glass_amt)
new /obj/item/stack/sheet/glass(get_turf(src), glass_amt)
qdel(src)
// APC HULL
/obj/item/wallframe/apc
name = "\improper APC frame"
desc = "Used for repairing or building APCs"
icon = 'icons/obj/apc_repair.dmi'
icon_state = "apc_frame"
result_path = /obj/machinery/power/apc
inverse = 1
/obj/item/wallframe/apc/try_build(turf/on_wall)
if(!..())
return
var/turf/loc = get_turf(usr)
var/area/A = loc.loc
if (A.get_apc())
usr << "<span class='warning'>This area already has APC!</span>"
return //only one APC per area
for(var/obj/machinery/power/terminal/T in loc)
if (T.master)
usr << "<span class='warning'>There is another network terminal here!</span>"
return
else
var/obj/item/stack/cable_coil/C = new /obj/item/stack/cable_coil(loc)
C.amount = 10
usr << "<span class='notice'>You cut the cables and disassemble the unused power terminal.</span>"
qdel(T)
return 1
/obj/item/weapon/electronics
desc = "Looks like a circuit. Probably is."
icon = 'icons/obj/module.dmi'
icon_state = "door_electronics"
item_state = "electronic"
flags = CONDUCT
w_class = 2
origin_tech = "engineering=2;programming=1"
materials = list(MAT_METAL=50, MAT_GLASS=50)
+350
View File
@@ -0,0 +1,350 @@
/obj/item/areaeditor
name = "area modification item"
icon = 'icons/obj/items.dmi'
icon_state = "blueprints"
attack_verb = list("attacked", "bapped", "hit")
var/fluffnotice = "Nobody's gonna read this stuff!"
var/const/AREA_ERRNONE = 0
var/const/AREA_STATION = 1
var/const/AREA_SPACE = 2
var/const/AREA_SPECIAL = 3
var/const/BORDER_ERROR = 0
var/const/BORDER_NONE = 1
var/const/BORDER_BETWEEN = 2
var/const/BORDER_2NDTILE = 3
var/const/BORDER_SPACE = 4
var/const/ROOM_ERR_LOLWAT = 0
var/const/ROOM_ERR_SPACE = -1
var/const/ROOM_ERR_TOOLARGE = -2
/obj/item/areaeditor/attack_self(mob/user)
add_fingerprint(user)
var/text = "<BODY><HTML><head><title>[src]</title></head> \
<h2>[station_name()] [src.name]</h2> \
<small>[fluffnotice]</small><hr>"
switch(get_area_type())
if(AREA_SPACE)
text += "<p>According to the [src.name], you are now in an unclaimed territory.</p> \
<p><a href='?src=\ref[src];create_area=1'>Mark this place as new area.</a></p>"
if(AREA_SPECIAL)
text += "<p>This place is not noted on the [src.name].</p>"
return text
/obj/item/areaeditor/Topic(href, href_list)
if(..())
return
if(!usr.canUseTopic(src))
usr << browse(null, "window=blueprints")
return
if(href_list["create_area"])
if(get_area_type()==AREA_SPACE)
create_area()
updateUsrDialog()
//One-use area creation permits.
/obj/item/areaeditor/permit
name = "construction permit"
icon_state = "permit"
desc = "This is a one-use permit that allows the user to offically declare a built room as new addition to the station."
fluffnotice = "Nanotrasen Engineering requires all on-station construction projects to be approved by a head of staff, as detailed in Nanotrasen Company Regulation 512-C (Mid-Shift Modifications to Company Property). \
By submitting this form, you accept any fines, fees, or personal injury/death that may occur during construction."
w_class = 1
/obj/item/areaeditor/permit/attack_self(mob/user)
. = ..()
var/area/A = get_area()
if(get_area_type() == AREA_STATION)
. += "<p>According to \the [src], you are now in <b>\"[html_encode(A.name)]\"</b>.</p>"
var/datum/browser/popup = new(user, "blueprints", "[src]", 700, 500)
popup.set_content(.)
popup.open()
onclose(usr, "blueprints")
/obj/item/areaeditor/permit/create_area()
var/success = ..()
if(success)
qdel(src)
//Station blueprints!!!
/obj/item/areaeditor/blueprints
name = "station blueprints"
desc = "Blueprints of the station. There is a \"Classified\" stamp and several coffee stains on it."
icon = 'icons/obj/items.dmi'
icon_state = "blueprints"
fluffnotice = "Property of Nanotrasen. For heads of staff only. Store in high-secure storage."
var/list/image/showing = list()
var/client/viewing
/obj/item/areaeditor/blueprints/Destroy()
clear_viewer()
return ..()
/obj/item/areaeditor/blueprints/attack_self(mob/user)
. = ..()
var/area/A = get_area()
if(get_area_type() == AREA_STATION)
. += "<p>According to \the [src], you are now in <b>\"[html_encode(A.name)]\"</b>.</p>"
. += "<p>You may <a href='?src=\ref[src];edit_area=1'>make an amendment</a> to the drawing.</p>"
if(!viewing)
. += "<p><a href='?src=\ref[src];view_blueprints=1'>View structural data</a></p>"
else
. += "<p><a href='?src=\ref[src];refresh=1'>Refresh structural data</a></p>"
. += "<p><a href='?src=\ref[src];hide_blueprints=1'>Hide structural data</a></p>"
var/datum/browser/popup = new(user, "blueprints", "[src]", 700, 500)
popup.set_content(.)
popup.open()
onclose(user, "blueprints")
/obj/item/areaeditor/blueprints/Topic(href, href_list)
..()
if(href_list["edit_area"])
if(get_area_type()!=AREA_STATION)
return
edit_area()
if(href_list["view_blueprints"])
set_viewer(usr, "<span class='notice'>You flip the blueprints over to view the complex information diagram.</span>")
if(href_list["hide_blueprints"])
clear_viewer(usr,"<span class='notice'>You flip the blueprints over to view the simple information diagram.</span>")
if(href_list["refresh"])
clear_viewer(usr)
set_viewer(usr)
attack_self(usr) //this is not the proper way, but neither of the old update procs work! it's too ancient and I'm tired shush.
/obj/item/areaeditor/blueprints/proc/get_images(turf/T, viewsize)
. = list()
for(var/tt in RANGE_TURFS(viewsize, T))
var/turf/TT = tt
if(TT.blueprint_data)
. += TT.blueprint_data
/obj/item/areaeditor/blueprints/proc/set_viewer(mob/user, message = "")
if(user && user.client)
if(viewing)
clear_viewer()
viewing = user.client
showing = get_images(get_turf(user), viewing.view)
viewing.images |= showing
if(message)
user << message
/obj/item/areaeditor/blueprints/proc/clear_viewer(mob/user, message = "")
if(viewing)
viewing.images -= showing
viewing = null
showing.Cut()
if(message)
user << message
/obj/item/areaeditor/blueprints/dropped(mob/user)
..()
clear_viewer()
/obj/item/areaeditor/proc/get_area()
var/turf/T = get_turf(usr)
var/area/A = T.loc
A = A.master
return A
/obj/item/areaeditor/proc/get_area_type(area/A = get_area())
if(A.outdoors)
return AREA_SPACE
var/list/SPECIALS = list(
/area/shuttle,
/area/admin,
/area/arrival,
/area/centcom,
/area/asteroid,
/area/tdome,
/area/wizard_station,
/area/prison
)
for (var/type in SPECIALS)
if ( istype(A,type) )
return AREA_SPECIAL
return AREA_STATION
/obj/item/areaeditor/proc/create_area()
var/res = detect_room(get_turf(usr))
if(!istype(res,/list))
switch(res)
if(ROOM_ERR_SPACE)
usr << "<span class='warning'>The new area must be completely airtight.</span>"
return
if(ROOM_ERR_TOOLARGE)
usr << "<span class='warning'>The new area is too large.</span>"
return
else
usr << "<span class='warning'>Error! Please notify administration.</span>"
return
var/list/turfs = res
var/str = trim(stripped_input(usr,"New area name:", "Blueprint Editing", "", MAX_NAME_LEN))
if(!str || !length(str)) //cancel
return
if(length(str) > 50)
usr << "<span class='warning'>The given name is too long. The area remains undefined.</span>"
return
var/area/old = get_area(get_turf(src))
var/old_gravity = old.has_gravity
var/area/A
for(var/key in turfs)
if(key == str)
A = turfs[key]
if(turfs[key])
turfs -= turfs[key]
turfs -= key
if(A)
A.contents += turfs
A.SetDynamicLighting()
else
A = new
A.setup(str)
A.contents += turfs
A.SetDynamicLighting()
A.has_gravity = old_gravity
interact()
return 1
/obj/item/areaeditor/proc/edit_area()
var/area/A = get_area()
var/prevname = "[A.name]"
var/str = trim(stripped_input(usr,"New area name:", "Blueprint Editing", "", MAX_NAME_LEN))
if(!str || !length(str) || str==prevname) //cancel
return
if(length(str) > 50)
usr << "<span class='warning'>The given name is too long. The area's name is unchanged.</span>"
return
set_area_machinery_title(A,str,prevname)
for(var/area/RA in A.related)
RA.name = str
usr << "<span class='notice'>You rename the '[prevname]' to '[str]'.</span>"
interact()
return 1
/obj/item/areaeditor/proc/set_area_machinery_title(area/A,title,oldtitle)
if(!oldtitle) // or replacetext goes to infinite loop
return
for(var/area/RA in A.related)
for(var/obj/machinery/airalarm/M in RA)
M.name = replacetext(M.name,oldtitle,title)
for(var/obj/machinery/power/apc/M in RA)
M.name = replacetext(M.name,oldtitle,title)
for(var/obj/machinery/atmospherics/components/unary/vent_scrubber/M in RA)
M.name = replacetext(M.name,oldtitle,title)
for(var/obj/machinery/atmospherics/components/unary/vent_pump/M in RA)
M.name = replacetext(M.name,oldtitle,title)
for(var/obj/machinery/door/M in RA)
M.name = replacetext(M.name,oldtitle,title)
//TODO: much much more. Unnamed airlocks, cameras, etc.
/obj/item/areaeditor/proc/check_tile_is_border(turf/T2,dir)
if (istype(T2, /turf/open/space))
return BORDER_SPACE //omg hull breach we all going to die here
if (get_area_type(T2.loc)!=AREA_SPACE)
return BORDER_BETWEEN
if (istype(T2, /turf/closed/wall))
return BORDER_2NDTILE
if (!istype(T2, /turf))
return BORDER_BETWEEN
for (var/obj/structure/window/W in T2)
if(turn(dir,180) == W.dir)
return BORDER_BETWEEN
if (W.dir in list(NORTHEAST,SOUTHEAST,NORTHWEST,SOUTHWEST))
return BORDER_2NDTILE
for(var/obj/machinery/door/window/D in T2)
if(turn(dir,180) == D.dir)
return BORDER_BETWEEN
if (locate(/obj/machinery/door) in T2)
return BORDER_2NDTILE
if (locate(/obj/structure/falsewall) in T2)
return BORDER_2NDTILE
return BORDER_NONE
/obj/item/areaeditor/proc/detect_room(turf/first)
var/list/turf/found = new
var/list/turf/pending = list(first)
var/list/border = list()
while(pending.len)
if (found.len+pending.len > 300)
return ROOM_ERR_TOOLARGE
var/turf/T = pending[1] //why byond havent list::pop()?
pending -= T
for (var/dir in cardinal)
var/skip = 0
for (var/obj/structure/window/W in T)
if(dir == W.dir || (W.dir in list(NORTHEAST,SOUTHEAST,NORTHWEST,SOUTHWEST)))
skip = 1
break
if (skip)
continue
for(var/obj/machinery/door/window/D in T)
if(dir == D.dir)
skip = 1
break
if (skip)
continue
var/turf/NT = get_step(T,dir)
if (!isturf(NT) || (NT in found) || (NT in pending))
continue
switch(check_tile_is_border(NT,dir))
if(BORDER_NONE)
pending+=NT
if(BORDER_BETWEEN)
var/area/A = NT.loc
if(!found[A.name])
found[A.name] = NT.loc
if(BORDER_2NDTILE)
border[NT] += dir
if(BORDER_SPACE)
return ROOM_ERR_SPACE
found+=T
for(var/V in border) //lazy but works
var/turf/F = V
for(var/direction in cardinal)
if(direction == border[F])
continue //don't want to grab turfs from outside the border
var/turf/U = get_step(F, direction)
if((U in border) || (U in found))
continue
if(check_tile_is_border(U, direction) == BORDER_2NDTILE)
found += U
found |= F
return found
//Blueprint Subtypes
/obj/item/areaeditor/blueprints/cyborg
name = "station schematics"
desc = "A digital copy of the station blueprints stored in your memory."
icon = 'icons/obj/items.dmi'
icon_state = "blueprints"
fluffnotice = "Intellectual Property of Nanotrasen. For use in engineering cyborgs only. Wipe from memory upon departure from the station."
+52
View File
@@ -0,0 +1,52 @@
/obj/item/organ/body_egg
name = "body egg"
desc = "All slimy and yuck."
icon_state = "innards"
origin_tech = "biotech=5"
zone = "chest"
slot = "parasite_egg"
/obj/item/organ/body_egg/on_find(mob/living/finder)
..()
finder << "<span class='warning'>You found an unknown alien organism in [owner]'s [zone]!</span>"
/obj/item/organ/body_egg/New(loc)
if(iscarbon(loc))
src.Insert(loc)
return ..()
/obj/item/organ/body_egg/Insert(var/mob/living/carbon/M, special = 0)
..()
owner.status_flags |= XENO_HOST
START_PROCESSING(SSobj, src)
owner.med_hud_set_status()
addtimer(src, "AddInfectionImages", 0, FALSE, owner)
/obj/item/organ/body_egg/Remove(var/mob/living/carbon/M, special = 0)
STOP_PROCESSING(SSobj, src)
if(owner)
owner.status_flags &= ~(XENO_HOST)
owner.med_hud_set_status()
addtimer(src, "RemoveInfectionImages", 0, FALSE, owner)
..()
/obj/item/organ/body_egg/process()
if(!owner)
return
if(!(src in owner.internal_organs))
Remove(owner)
return
egg_process()
/obj/item/organ/body_egg/proc/egg_process()
return
/obj/item/organ/body_egg/proc/RefreshInfectionImage()
RemoveInfectionImages()
AddInfectionImages()
/obj/item/organ/body_egg/proc/AddInfectionImages()
return
/obj/item/organ/body_egg/proc/RemoveInfectionImages()
return
+107
View File
@@ -0,0 +1,107 @@
//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/bodybag.dmi'
icon_state = "bodybag_folded"
var/unfoldedbag_path = /obj/structure/closet/body_bag
w_class = 2
/obj/item/bodybag/attack_self(mob/user)
var/obj/structure/closet/body_bag/R = new unfoldedbag_path(user.loc)
R.add_fingerprint(user)
qdel(src)
/obj/item/weapon/storage/box/bodybags
name = "body bags"
desc = "The label indicates that it contains body bags."
icon_state = "bodybags"
/obj/item/weapon/storage/box/bodybags/New()
..()
for(var/i in 1 to 7)
new /obj/item/bodybag(src)
/obj/structure/closet/body_bag
name = "body bag"
desc = "A plastic bag designed for the storage and transportation of cadavers."
icon = 'icons/obj/bodybag.dmi'
icon_state = "bodybag"
var/foldedbag_path = /obj/item/bodybag
var/tagged = 0 // so closet code knows to put the tag overlay back
density = 0
mob_storage_capacity = 2
open_sound = 'sound/items/zip.ogg'
close_sound = 'sound/items/zip.ogg'
/obj/structure/closet/body_bag/attackby(obj/item/I, mob/user, params)
if (istype(I, /obj/item/weapon/pen) || istype(I, /obj/item/toy/crayon))
var/t = stripped_input(user, "What would you like the label to be?", name, null, 53)
if(user.get_active_hand() != I)
return
if(!in_range(src, user) && loc != user)
return
if(t)
name = "body bag - [t]"
tagged = 1
update_icon()
else
name = "body bag"
return
else if(istype(I, /obj/item/weapon/wirecutters))
user << "<span class='notice'>You cut the tag off [src].</span>"
name = "body bag"
tagged = 0
update_icon()
/obj/structure/closet/body_bag/update_icon()
..()
if (tagged)
add_overlay("bodybag_label")
/obj/structure/closet/body_bag/close()
if(..())
density = 0
return 1
return 0
/obj/structure/closet/body_bag/MouseDrop(over_object, src_location, over_location)
..()
if(over_object == usr && Adjacent(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("<span class='notice'>[usr] folds up [src].</span>")
var/obj/item/bodybag/B = new foldedbag_path(get_turf(src))
usr.put_in_hands(B)
qdel(src)
// Bluespace bodybag
/obj/item/bodybag/bluespace
name = "bluespace body bag"
desc = "A folded bluespace body bag designed for the storage and transportation of cadavers."
icon = 'icons/obj/bodybag.dmi'
icon_state = "bluebodybag_folded"
unfoldedbag_path = /obj/structure/closet/body_bag/bluespace
w_class = 2
origin_tech = "bluespace=4;materials=4;plasmatech=4"
/obj/structure/closet/body_bag/bluespace
name = "bluespace body bag"
desc = "A bluespace body bag designed for the storage and transportation of cadavers."
icon = 'icons/obj/bodybag.dmi'
icon_state = "bluebodybag"
foldedbag_path = /obj/item/bodybag/bluespace
density = 0
mob_storage_capacity = 15
max_mob_size = MOB_SIZE_LARGE
+117
View File
@@ -0,0 +1,117 @@
#define CANDLE_LUMINOSITY 2
/obj/item/candle
name = "red candle"
desc = "In Greek myth, Prometheus stole fire from the Gods and gave it to \
humankind. The jewelry he kept for himself."
icon = 'icons/obj/candle.dmi'
icon_state = "candle1"
item_state = "candle1"
w_class = 1
var/wax = 200
var/lit = FALSE
var/infinite = FALSE
var/start_lit = FALSE
heat = 1000
/obj/item/candle/New()
..()
if(start_lit)
// No visible message
light(show_message = FALSE)
/obj/item/candle/update_icon()
var/i
if(wax>150)
i = 1
else if(wax>80)
i = 2
else i = 3
icon_state = "candle[i][lit ? "_lit" : ""]"
/obj/item/candle/attackby(obj/item/weapon/W, mob/user, params)
..()
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(WT.isOn()) //Badasses dont get blinded by lighting their candle with a welding tool
light("<span class='danger'>[user] casually lights the [name] with [W], what a badass.</span>")
else if(istype(W, /obj/item/weapon/lighter))
var/obj/item/weapon/lighter/L = W
if(L.lit)
light()
else if(istype(W, /obj/item/weapon/match))
var/obj/item/weapon/match/M = W
if(M.lit)
light()
else if(istype(W, /obj/item/candle))
var/obj/item/candle/C = W
if(C.lit)
light()
else if(istype(W, /obj/item/clothing/mask/cigarette))
var/obj/item/clothing/mask/cigarette/M = W
if(M.lit)
light()
/obj/item/candle/fire_act()
if(!src.lit)
light() //honk
return
/obj/item/candle/proc/light(show_message)
if(!src.lit)
src.lit = TRUE
//src.damtype = "fire"
if(show_message)
usr.visible_message(
"<span class='danger'>[usr] lights the [name].</span>")
SetLuminosity(CANDLE_LUMINOSITY)
START_PROCESSING(SSobj, src)
update_icon()
/obj/item/candle/process()
if(!lit)
return
if(!infinite)
wax--
if(!wax)
new/obj/item/trash/candle(src.loc)
if(istype(src.loc, /mob))
var/mob/M = src.loc
M.unEquip(src, 1) //src is being deleted anyway
qdel(src)
update_icon()
open_flame()
/obj/item/candle/attack_self(mob/user)
if(lit)
user.visible_message(
"<span class='notice'>[user] snuffs [src].</span>")
lit = FALSE
update_icon()
SetLuminosity(0)
user.AddLuminosity(-CANDLE_LUMINOSITY)
/obj/item/candle/pickup(mob/user)
..()
if(lit)
SetLuminosity(0)
user.AddLuminosity(CANDLE_LUMINOSITY)
/obj/item/candle/dropped(mob/user)
..()
if(lit)
user.AddLuminosity(-CANDLE_LUMINOSITY)
SetLuminosity(CANDLE_LUMINOSITY)
/obj/item/candle/is_hot()
return lit * heat
/obj/item/candle/infinite
infinite = TRUE
start_lit = TRUE
#undef CANDLE_LUMINOSITY
@@ -0,0 +1,129 @@
//Cardboard cutouts! They're man-shaped and can be colored with a crayon to look like a human in a certain outfit, although it's limited, discolored, and obvious to more than a cursory glance.
/obj/item/cardboard_cutout
name = "cardboard cutout"
desc = "A vaguely humanoid cardboard cutout. It's completely blank."
icon = 'icons/obj/cardboard_cutout.dmi'
icon_state = "cutout_basic"
w_class = 4
var/list/possible_appearances = list("Assistant", "Clown", "Mime", "Traitor", "Nuke Op", "Cultist", "Clockwork Cultist", "Revolutionary", "Wizard", "Shadowling", "Xenomorph", "Swarmer", \
"Ash Walker", "Deathsquad Officer", "Ian") //Possible restyles for the cutout; add an entry in change_appearance() if you add to here
var/pushed_over = FALSE //If the cutout is pushed over and has to be righted
var/deceptive = FALSE //If the cutout actually appears as what it portray and not a discolored version
/obj/item/cardboard_cutout/attack_hand(mob/living/user)
if(user.a_intent == "help" || pushed_over)
return ..()
user.visible_message("<span class='warning'>[user] pushes over [src]!</span>", "<span class='danger'>You push over [src]!</span>")
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
name = initial(name)
desc = "[initial(desc)] It's been pushed over."
icon_state = "cutout_pushed_over"
color = initial(color)
pushed_over = TRUE
/obj/item/cardboard_cutout/attack_self(mob/living/user)
if(!pushed_over)
return
user << "<span class='notice'>You right [src].</span>"
desc = initial(desc)
icon_state = initial(icon_state) //This resets a cutout to its blank state - this is intentional to allow for resetting
pushed_over = FALSE
/obj/item/cardboard_cutout/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/toy/crayon))
change_appearance(I, user)
else
return ..()
/obj/item/cardboard_cutout/bullet_act(obj/item/projectile/P)
visible_message("<span class='danger'>[src] has been hit by [P]!</span>")
playsound(src, 'sound/weapons/slice.ogg', 50, 1)
if(prob(P.damage))
name = initial(name)
desc = "[initial(desc)] It's been pushed over."
icon_state = "cutout_pushed_over"
color = initial(color)
pushed_over = TRUE
/obj/item/cardboard_cutout/proc/change_appearance(obj/item/toy/crayon/crayon, mob/living/user)
if(!crayon || !user)
return
if(pushed_over)
user << "<span class='warning'>Right [src] first!</span>"
return
var/new_appearance = input(user, "Choose a new appearance for [src].", "26th Century Deception") as null|anything in possible_appearances
if(!new_appearance || !crayon || !user.canUseTopic(src))
return
user.visible_message("<span class='notice'>[user] gives [src] a new look.</span>", "<span class='notice'>Voila! You give [src] a new look.</span>")
crayon.use_charges(1)
crayon.check_empty(user)
alpha = 255
if(!deceptive)
color = "#FFD7A7"
switch(new_appearance)
if("Assistant")
name = "[pick(first_names_male)] [pick(last_names)]"
desc = "A cardboat cutout of an assistant."
icon_state = "cutout_greytide"
if("Clown")
name = pick(clown_names)
desc = "A cardboard cutout of a clown. You get the feeling that it should be in a corner."
icon_state = "cutout_clown"
if("Mime")
name = pick(mime_names)
desc = "...(A cardboard cutout of a mime.)"
icon_state = "cutout_mime"
if("Traitor")
name = "[pick("Unknown", "Captain")]"
desc = "A cardboard cutout of a traitor."
icon_state = "cutout_traitor"
if("Nuke Op")
name = "[pick("Unknown", "COMMS", "Telecomms", "AI", "stealthy op", "STEALTH", "sneakybeaky", "MEDIC", "Medic")]"
desc = "A cardboard cutout of a nuclear operative."
icon_state = "cutout_fluke"
if("Cultist")
name = "Unknown"
desc = "A cardboard cutout of a cultist."
icon_state = "cutout_cultist"
if("Clockwork Cultist")
name = "[pick(first_names_male)] [pick(last_names)]"
desc = "A cardboard cutout of a servant of Ratvar."
icon_state = "cutout_servant"
if("Revolutionary")
name = "Unknown"
desc = "A cardboard cutout of a revolutionary."
icon_state = "cutout_viva"
if("Wizard")
name = "[pick(wizard_first)], [pick(wizard_second)]"
desc = "A cardboard cutout of a wizard."
icon_state = "cutout_wizard"
if("Shadowling")
name = "Unknown"
desc = "A cardboard cutout of a shadowling."
icon_state = "cutout_shadowling"
if("Xenomorph")
name = "alien hunter ([rand(1, 999)])"
desc = "A cardboard cutout of a xenomorph."
icon_state = "cutout_fukken_xeno"
if(prob(25))
alpha = 75 //Spooky sneaking!
if("Swarmer")
name = "Swarmer ([rand(1, 999)])"
desc = "A cardboard cutout of a swarmer."
icon_state = "cutout_swarmer"
if("Ash Walker")
name = lizard_name(pick(MALE, FEMALE))
desc = "A cardboard cutout of an ash walker."
icon_state = "cutout_free_antag"
if("Deathsquad Officer")
name = pick(commando_names)
desc = "A cardboard cutout of a death commando."
icon_state = "cutout_deathsquad"
if("Ian")
name = "Ian"
desc = "A cardboard cutout of the HoP's beloved corgi."
icon_state = "cutout_ian"
return 1
/obj/item/cardboard_cutout/adaptive //Purchased by Syndicate agents, these cutouts are indistinguishable from normal cutouts but aren't discolored when their appearance is changed
deceptive = TRUE
+93
View File
@@ -0,0 +1,93 @@
/obj/item/station_charter
name = "station charter"
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll2"
desc = "An official document entrusting the governance of the station \
and surrounding space to the Captain. "
var/used = FALSE
var/unlimited_uses = FALSE
var/ignores_timeout = FALSE
var/response_timer_id = null
var/approval_time = 600
var/static/regex/standard_station_regex
/obj/item/station_charter/New()
. = ..()
if(!standard_station_regex)
var/prefixes = jointext(station_prefixes, "|")
var/names = jointext(station_names, "|")
var/suffixes = jointext(station_suffixes, "|")
var/numerals = jointext(station_numerals, "|")
var/regexstr = "(([prefixes]) )?(([names]) ?)([suffixes]) ([numerals])"
standard_station_regex = new(regexstr)
/obj/item/station_charter/Destroy()
if(response_timer_id)
deltimer(response_timer_id)
response_timer_id = null
. = ..()
/obj/item/station_charter/attack_self(mob/living/user)
if(used)
user << "This charter has already been used to name the station."
return
if(!ignores_timeout && (world.time-round_start_time > CHALLENGE_TIME_LIMIT)) //5 minutes
user << "The crew has already settled into the shift. \
It probably wouldn't be good to rename the station right now."
return
if(response_timer_id)
user << "You're still waiting for approval from your employers about \
your proposed name change, it'd be best to wait for now."
return
var/new_name = stripped_input(user, message="What do you want to name \
[station_name()]? Keep in mind particularly terrible names may be \
rejected by your employers, while names using the standard format, \
will automatically be accepted.", max_length=MAX_CHARTER_LEN)
if(!new_name)
return
log_game("[key_name(user)] has proposed to name the station as \
[new_name]")
if(standard_station_regex.Find(new_name))
user << "Your name has been automatically approved."
rename_station(new_name, user)
return
user << "Your name has been sent to your employers for approval."
// Autoapproves after a certain time
response_timer_id = addtimer(src, "rename_station", approval_time, \
FALSE, new_name, user)
admins << "<span class='adminnotice'><b><font color=orange>CUSTOM STATION RENAME:</font></b>[key_name_admin(user)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) proposes to rename the station to [new_name] (will autoapprove in [approval_time / 10] seconds). (<A HREF='?_src_=holder;BlueSpaceArtillery=\ref[user]'>BSA</A>) (<A HREF='?_src_=holder;reject_custom_name=\ref[src]'>REJECT</A>)</span>"
/obj/item/station_charter/proc/reject_proposed(user)
if(!user)
return
if(!response_timer_id)
return
var/turf/T = get_turf(src)
T.visible_message("<span class='warning'>The proposed changes disappear \
from [src]; it looks like they've been rejected.</span>")
var/m = "[key_name(user)] has rejected the proposed station name."
message_admins(m)
log_admin(m)
deltimer(response_timer_id)
response_timer_id = null
/obj/item/station_charter/proc/rename_station(designation, mob/user)
world.name = designation
station_name = designation
minor_announce("[user.real_name] has designated your station as [world.name]", "Captain's Charter", 0)
log_game("[key_name(user)] has renamed the station as [world.name]")
name = "station charter for [world.name]"
desc = "An official document entrusting the governance of \
[world.name] and surrounding space to Captain [user]."
if(!unlimited_uses)
used = TRUE
+104
View File
@@ -0,0 +1,104 @@
#define WAND_OPEN "Open Door"
#define WAND_BOLT "Toggle Bolts"
#define WAND_EMERGENCY "Toggle Emergency Access"
/obj/item/weapon/door_remote
icon_state = "gangtool-white"
item_state = "electronic"
icon = 'icons/obj/device.dmi'
name = "control wand"
desc = "Remotely controls airlocks."
w_class = 1
var/mode = WAND_OPEN
var/region_access = 1 //See access.dm
var/obj/item/weapon/card/id/ID
/obj/item/weapon/door_remote/New()
..()
ID = new /obj/item/weapon/card/id
ID.access = get_region_accesses(region_access)
/obj/item/weapon/door_remote/attack_self(mob/user)
switch(mode)
if(WAND_OPEN)
mode = WAND_BOLT
if(WAND_BOLT)
mode = WAND_EMERGENCY
if(WAND_EMERGENCY)
mode = WAND_OPEN
user << "Now in mode: [mode]."
/obj/item/weapon/door_remote/afterattack(obj/machinery/door/airlock/D, mob/user)
if(!istype(D))
return
if(!(D.hasPower()))
user << "<span class='danger'>[D] has no power!</span>"
return
if(!D.requiresID())
user << "<span class='danger'>[D]'s ID scan is disabled!</span>"
return
if(D.check_access(ID) && D.canAIControl(user))
switch(mode)
if(WAND_OPEN)
if(D.density)
D.open()
else
D.close()
if(WAND_BOLT)
if(D.locked)
D.unbolt()
else
D.bolt()
if(WAND_EMERGENCY)
if(D.emergency)
D.emergency = 0
else
D.emergency = 1
D.update_icon()
else
user << "<span class='danger'>[src] does not have access to this door.</span>"
/obj/item/weapon/door_remote/omni
name = "omni door remote"
desc = "This control wand can access any door on the station."
icon_state = "gangtool-yellow"
region_access = 0
/obj/item/weapon/door_remote/captain
name = "command door remote"
icon_state = "gangtool-yellow"
region_access = 7
/obj/item/weapon/door_remote/chief_engineer
name = "engineering door remote"
icon_state = "gangtool-orange"
region_access = 5
/obj/item/weapon/door_remote/research_director
name = "research door remote"
icon_state = "gangtool-purple"
region_access = 4
/obj/item/weapon/door_remote/head_of_security
name = "security door remote"
icon_state = "gangtool-red"
region_access = 2
/obj/item/weapon/door_remote/quartermaster
name = "supply door remote"
icon_state = "gangtool-green"
region_access = 6
/obj/item/weapon/door_remote/chief_medical_officer
name = "medical door remote"
icon_state = "gangtool-blue"
region_access = 3
/obj/item/weapon/door_remote/civillian
name = "civillian door remote"
icon_state = "gangtool-white"
region_access = 1
#undef WAND_OPEN
#undef WAND_BOLT
#undef WAND_EMERGENCY
+769
View File
@@ -0,0 +1,769 @@
#define RANDOM_GRAFFITI "Random Graffiti"
#define RANDOM_LETTER "Random Letter"
#define RANDOM_NUMBER "Random Number"
#define RANDOM_ORIENTED "Random Oriented"
#define RANDOM_RUNE "Random Rune"
#define RANDOM_ANY "Random Anything"
#define PAINT_NORMAL 1
#define PAINT_LARGE_HORIZONTAL 2
#define PAINT_LARGE_HORIZONTAL_ICON 'icons/effects/96x32.dmi'
/*
* Crayons
*/
/obj/item/toy/crayon
name = "crayon"
desc = "A colourful crayon. Looks tasty. Mmmm..."
icon = 'icons/obj/crayons.dmi'
icon_state = "crayonred"
var/icon_capped
var/icon_uncapped
var/use_overlays = FALSE
item_color = "red"
w_class = 1
attack_verb = list("attacked", "coloured")
var/paint_color = "#FF0000" //RGB
var/drawtype
var/text_buffer = ""
var/list/graffiti = list("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa","body","cyka","arrow","star","poseur tag")
var/list/letters = 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")
var/list/numerals = list("0","1","2","3","4","5","6","7","8","9")
var/list/oriented = list("arrow","body") // These turn to face the same way as the drawer
var/list/runes = list("rune1","rune2","rune3","rune4","rune5","rune6")
var/list/randoms = list(RANDOM_ANY, RANDOM_RUNE, RANDOM_ORIENTED,
RANDOM_NUMBER, RANDOM_GRAFFITI, RANDOM_LETTER)
var/list/graffiti_large_h = list("yiffhell", "secborg", "paint")
var/list/all_drawables
var/paint_mode = PAINT_NORMAL
var/charges = 30 //-1 or less for unlimited uses
var/charges_left
var/volume_multiplier = 1 // Increases reagent effect
var/actually_paints = TRUE
var/instant = FALSE
var/self_contained = TRUE // If it deletes itself when it is empty
var/list/validSurfaces = list(/turf/open/floor)
var/gang = FALSE //For marking territory
var/edible = TRUE // That doesn't mean eating it is a good idea
var/list/reagent_contents = list("nutriment" = 1)
// If the user can toggle the colour, a la vanilla spraycan
var/can_change_colour = FALSE
var/has_cap = FALSE
var/is_capped = FALSE
var/pre_noise = FALSE
var/post_noise = FALSE
/obj/item/toy/crayon/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is jamming the [src.name] up \his nose and into \his brain. It looks like \he's trying to commit suicide.</span>")
return (BRUTELOSS|OXYLOSS)
/obj/item/toy/crayon/New()
..()
// Makes crayons identifiable in things like grinders
if(name == "crayon")
name = "[item_color] crayon"
if(config)
if(config.mutant_races == 1)
graffiti |= "antilizard"
graffiti |= "prolizard"
all_drawables = graffiti + letters + numerals + oriented + runes + graffiti_large_h
drawtype = pick(all_drawables)
refill()
/obj/item/toy/crayon/Destroy()
if(reagents)
qdel(reagents)
. = ..()
/obj/item/toy/crayon/proc/refill()
if(charges == -1)
charges_left = 100
else
charges_left = charges
if(!reagents)
create_reagents(charges_left * volume_multiplier)
reagents.clear_reagents()
var/total_weight = 0
for(var/key in reagent_contents)
total_weight += reagent_contents[key]
var/units_per_weight = reagents.maximum_volume / total_weight
for(var/reagent in reagent_contents)
var/weight = reagent_contents[reagent]
var/amount = weight * units_per_weight
reagents.add_reagent(reagent, amount)
/obj/item/toy/crayon/proc/use_charges(amount)
// Returns number of charges actually used
switch(paint_mode)
if(PAINT_LARGE_HORIZONTAL)
amount *= 3
if(charges == -1)
. = amount
refill()
else
. = min(charges_left, amount)
charges_left -= .
/obj/item/toy/crayon/proc/check_empty(mob/user)
// When eating a crayon, check_empty() can be called twice producing
// two messages unless we check for being deleted first
if(!qdeleted(src))
. = TRUE
. = FALSE
// -1 is unlimited charges
if(charges == -1)
. = FALSE
else if(!charges_left)
user << "<span class='warning'>There is no more of [src.name] \
left!</span>"
if(self_contained)
qdel(src)
. = TRUE
/obj/item/toy/crayon/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = hands_state)
// god bless tgui and all of its arguments
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "crayon", name, 600, 600,
master_ui, state)
ui.open()
/obj/item/toy/crayon/spraycan/AltClick(mob/user)
if(has_cap)
is_capped = !is_capped
user << "<span class='notice'>The cap on [src] is now \
[is_capped ? "on" : "off"].</span>"
update_icon()
/obj/item/toy/crayon/ui_data()
var/list/data = list()
data["drawables"] = list()
var/list/D = data["drawables"]
var/list/g_items = list()
D += list(list("name" = "Graffiti", "items" = g_items))
for(var/g in graffiti)
g_items += list(list("item" = g))
var/list/glh_items = list()
D += list(list("name" = "Graffiti Large Horizontal", "items" = glh_items))
for(var/glh in graffiti_large_h)
glh_items += list(list("item" = glh))
var/list/L_items = list()
D += list(list("name" = "Letters", "items" = L_items))
for(var/L in letters)
L_items += list(list("item" = L))
var/list/N_items = list()
D += list(list(name = "Numerals", "items" = N_items))
for(var/N in numerals)
N_items += list(list("item" = N))
var/list/O_items = list()
D += list(list(name = "Oriented", "items" = O_items))
for(var/O in oriented)
O_items += list(list("item" = O))
var/list/R_items = list()
D += list(list(name = "Runes", "items" = R_items))
for(var/R in runes)
R_items += list(list("item" = R))
var/list/rand_items = list()
D += list(list(name = "Random", "items" = rand_items))
for(var/i in randoms)
rand_items += list(list("item" = i))
data["selected_stencil"] = drawtype
data["text_buffer"] = text_buffer
data["has_cap"] = has_cap
data["is_capped"] = is_capped
data["can_change_colour"] = can_change_colour
data["current_colour"] = paint_color
return data
/obj/item/toy/crayon/ui_act(action, list/params)
if(..())
return
switch(action)
if("toggle_cap")
if(has_cap)
is_capped = !is_capped
. = TRUE
if("select_stencil")
var/stencil = params["item"]
if(stencil in all_drawables + randoms)
drawtype = stencil
. = TRUE
if(stencil in graffiti_large_h)
paint_mode = PAINT_LARGE_HORIZONTAL
text_buffer = ""
else
paint_mode = PAINT_NORMAL
if("select_colour")
if(can_change_colour)
paint_color = input(usr,"Choose Color") as color
. = TRUE
if("enter_text")
var/txt = stripped_input(usr,"Choose what to write.",
"Scribbles",default = text_buffer)
text_buffer = crayon_text_strip(txt)
. = TRUE
paint_mode = PAINT_NORMAL
drawtype = "a"
update_icon()
/obj/item/toy/crayon/proc/crayon_text_strip(text)
var/list/base = char_split(lowertext(text))
var/list/out = list()
for(var/a in base)
if(a in (letters|numerals))
out += a
return jointext(out,"")
/obj/item/toy/crayon/afterattack(atom/target, mob/user, proximity)
if(!proximity || !check_allowed_items(target))
return
if(check_empty(user))
return
if(istype(target, /obj/effect/decal/cleanable))
target = target.loc
if(!is_type_in_list(target,validSurfaces))
return
var/drawing = drawtype
switch(drawtype)
if(RANDOM_LETTER)
drawing = pick(letters)
if(RANDOM_GRAFFITI)
drawing = pick(graffiti)
if(RANDOM_RUNE)
drawing = pick(runes)
if(RANDOM_ORIENTED)
drawing = pick(oriented)
if(RANDOM_NUMBER)
drawing = pick(numerals)
if(RANDOM_ANY)
drawing = pick(all_drawables)
var/temp = "rune"
if(drawing in letters)
temp = "letter"
else if(drawing in graffiti)
temp = "graffiti"
else if(drawing in numerals)
temp = "number"
// If a gang member is using a gang spraycan, it'll behave differently
var/gang_mode = FALSE
if(gang && user.mind && user.mind.gang_datum)
gang_mode = TRUE
// discontinue if the area isn't valid for tagging because gang "honour"
if(gang_mode && (!can_claim_for_gang(user, target)))
return
var/graf_rot
if(drawing in oriented)
switch(user.dir)
if(EAST)
graf_rot = 90
if(SOUTH)
graf_rot = 180
if(WEST)
graf_rot = 270
else
graf_rot = 0
user << "<span class='notice'>You start \
[instant ? "spraying" : "drawing"] a [temp] on the \
[target.name]...</span>"
if(pre_noise)
audible_message("<span class='notice'>You hear spraying.</span>")
playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5)
var/takes_time = !instant
if(gang_mode)
takes_time = TRUE
var/wait_time = 50
if(PAINT_LARGE_HORIZONTAL)
wait_time *= 3
if(takes_time)
if(!do_after(user, 50, target = target))
return
if(length(text_buffer))
drawing = copytext(text_buffer,1,2)
var/list/turf/affected_turfs = list()
if(actually_paints)
if(gang_mode)
// Double check it wasn't tagged in the meanwhile
if(!can_claim_for_gang(user, target))
return
tag_for_gang(user, target)
else
switch(paint_mode)
if(PAINT_NORMAL)
new /obj/effect/decal/cleanable/crayon(target, paint_color, drawing, temp, graf_rot)
affected_turfs += target
if(PAINT_LARGE_HORIZONTAL)
var/turf/left = locate(target.x-1,target.y,target.z)
var/turf/right = locate(target.x+1,target.y,target.z)
if(is_type_in_list(left, validSurfaces) && is_type_in_list(right, validSurfaces))
new /obj/effect/decal/cleanable/crayon(left, paint_color, drawing, temp, graf_rot, PAINT_LARGE_HORIZONTAL_ICON)
affected_turfs += left
affected_turfs += right
affected_turfs += target
else
user << "<span class='warning'>There isn't enough space to paint!</span>"
return
user << "<span class='notice'>You finish \
[instant ? "spraying" : "drawing"] \the [temp].</span>"
if(length(text_buffer))
text_buffer = copytext(text_buffer,2)
if(post_noise)
audible_message("<span class='notice'>You hear spraying.</span>")
playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5)
var/cost = 1
if(paint_mode == PAINT_LARGE_HORIZONTAL)
cost = 5
. = use_charges(cost)
var/fraction = min(1, . / reagents.maximum_volume)
fraction /= affected_turfs.len
for(var/t in affected_turfs)
reagents.reaction(t, TOUCH, fraction * volume_multiplier)
reagents.trans_to(t, ., volume_multiplier)
check_empty(user)
/obj/item/toy/crayon/attack(mob/M, mob/user)
if(edible && (M == user))
user << "You take a bite of the [src.name]. Delicious!"
var/eaten = use_charges(5)
var/fraction = min(eaten / reagents.total_volume, 1)
reagents.reaction(M, INGEST, fraction * volume_multiplier)
reagents.trans_to(M, eaten, volume_multiplier)
// check_empty() is called during afterattack
else
..()
/obj/item/toy/crayon/proc/can_claim_for_gang(mob/user, atom/target)
// Check area validity.
// Reject space, player-created areas, and non-station z-levels.
var/area/A = get_area(target)
if(!A || (A.z != ZLEVEL_STATION) || !A.valid_territory)
user << "<span class='warning'>[A] is unsuitable for \
tagging.</span>"
return FALSE
var/spraying_over = FALSE
for(var/obj/effect/decal/cleanable/crayon/gang/G in target)
spraying_over = TRUE
for(var/obj/machinery/power/apc in target)
user << "<span class='warning'>You can't tag an APC.</span>"
return FALSE
var/occupying_gang = territory_claimed(A, user)
if(occupying_gang && !spraying_over)
user << "<span class='danger'>[A] has already been tagged \
by the [occupying_gang] gang! You must get rid of or spray over \
the old tag first!</span>"
return FALSE
// If you pass the gaunlet of checks, you're good to proceed
return TRUE
/obj/item/toy/crayon/proc/territory_claimed(area/territory, mob/user)
for(var/datum/gang/G in ticker.mode.gangs)
if(territory.type in (G.territory|G.territory_new))
. = G.name
break
/obj/item/toy/crayon/proc/tag_for_gang(mob/user, atom/target)
//Delete any old markings on this tile, including other gang tags
for(var/obj/effect/decal/cleanable/crayon/old_marking in target)
qdel(old_marking)
var/gangID = user.mind.gang_datum
var/area/territory = get_area(target)
new /obj/effect/decal/cleanable/crayon/gang(target,gangID,"graffiti",0)
user << "<span class='notice'>You tagged [territory] for your gang!</span>"
/obj/item/toy/crayon/red
icon_state = "crayonred"
paint_color = "#DA0000"
item_color = "red"
reagent_contents = list("nutriment" = 1, "redcrayonpowder" = 1)
/obj/item/toy/crayon/orange
icon_state = "crayonorange"
paint_color = "#FF9300"
item_color = "orange"
reagent_contents = list("nutriment" = 1, "orangecrayonpowder" = 1)
/obj/item/toy/crayon/yellow
icon_state = "crayonyellow"
paint_color = "#FFF200"
item_color = "yellow"
reagent_contents = list("nutriment" = 1, "yellowcrayonpowder" = 1)
/obj/item/toy/crayon/green
icon_state = "crayongreen"
paint_color = "#A8E61D"
item_color = "green"
reagent_contents = list("nutriment" = 1, "greencrayonpowder" = 1)
/obj/item/toy/crayon/blue
icon_state = "crayonblue"
paint_color = "#00B7EF"
item_color = "blue"
reagent_contents = list("nutriment" = 1, "bluecrayonpowder" = 1)
/obj/item/toy/crayon/purple
icon_state = "crayonpurple"
paint_color = "#DA00FF"
item_color = "purple"
reagent_contents = list("nutriment" = 1, "purplecrayonpowder" = 1)
/obj/item/toy/crayon/white
icon_state = "crayonwhite"
paint_color = "#FFFFFF"
item_color = "white"
/obj/item/toy/crayon/mime
icon_state = "crayonmime"
desc = "A very sad-looking crayon."
paint_color = "#FFFFFF"
item_color = "mime"
reagent_contents = list("nutriment" = 1, "invisiblecrayonpowder" = 1)
charges = -1
/obj/item/toy/crayon/rainbow
icon_state = "crayonrainbow"
paint_color = "#FFF000"
item_color = "rainbow"
reagent_contents = list("nutriment" = 1, "colorful_reagent" = 1)
drawtype = RANDOM_ANY // just the default starter.
charges = -1
/obj/item/toy/crayon/rainbow/afterattack(atom/target, mob/user, proximity)
paint_color = rgb(rand(0,255), rand(0,255), rand(0,255))
. = ..()
/*
* Crayon Box
*/
/obj/item/weapon/storage/crayons
name = "box of crayons"
desc = "A box of crayons for all your rune drawing needs."
icon = 'icons/obj/crayons.dmi'
icon_state = "crayonbox"
w_class = 2
storage_slots = 6
can_hold = list(
/obj/item/toy/crayon
)
/obj/item/weapon/storage/crayons/New()
..()
new /obj/item/toy/crayon/red(src)
new /obj/item/toy/crayon/orange(src)
new /obj/item/toy/crayon/yellow(src)
new /obj/item/toy/crayon/green(src)
new /obj/item/toy/crayon/blue(src)
new /obj/item/toy/crayon/purple(src)
update_icon()
/obj/item/weapon/storage/crayons/update_icon()
cut_overlays()
for(var/obj/item/toy/crayon/crayon in contents)
add_overlay(image('icons/obj/crayons.dmi',crayon.item_color))
/obj/item/weapon/storage/crayons/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/toy/crayon))
var/obj/item/toy/crayon/C = W
switch(C.item_color)
if("mime")
usr << "This crayon is too sad to be contained in this box."
return
if("rainbow")
usr << "This crayon is too powerful to be contained in this \
box."
return
if(istype(W, /obj/item/toy/crayon/spraycan))
user << "Spraycans are not crayons."
return
return ..()
//Spraycan stuff
/obj/item/toy/crayon/spraycan
name = "spray can"
icon_state = "spraycan"
icon_capped = "spraycan_cap"
icon_uncapped = "spraycan"
use_overlays = TRUE
paint_color = null
item_state = "spraycan"
desc = "A metallic container containing tasty paint.\n\
Alt-click to toggle the cap."
instant = TRUE
edible = FALSE
has_cap = TRUE
is_capped = TRUE
self_contained = FALSE // Don't disappear when they're empty
can_change_colour = TRUE
validSurfaces = list(/turf/open/floor,/turf/closed/wall)
reagent_contents = list("welding_fuel" = 1, "ethanol" = 1)
/obj/item/toy/crayon/spraycan/suicide_act(mob/user)
var/mob/living/carbon/human/H = user
if(is_capped || !actually_paints)
user.visible_message("<span class='suicide'>[user] shakes up the \
[src] with a rattle and lifts it to their mouth, but nothing \
happens!</span>")
user.say("MEDIOCRE!!")
return SHAME
else
user.visible_message("<span class='suicide'>[user] shakes up the \
[src] with a rattle and lifts it to their mouth, spraying \
paint across their teeth!</span>")
user.say("WITNESS ME!!")
if(pre_noise || post_noise)
playsound(loc, 'sound/effects/spray.ogg', 5, 1, 5)
if(can_change_colour)
paint_color = "#C0C0C0"
update_icon()
if(actually_paints)
H.lip_style = "spray_face"
H.lip_color = paint_color
H.update_body()
var/used = use_charges(10)
var/fraction = min(1, used / reagents.maximum_volume)
reagents.reaction(user, VAPOR, fraction * volume_multiplier)
reagents.trans_to(user, used, volume_multiplier)
return (OXYLOSS)
/obj/item/toy/crayon/spraycan/New()
..()
// If default crayon red colour, pick a more fun spraycan colour
if(!paint_color)
paint_color = pick("#DA0000","#FF9300","#FFF200","#A8E61D","#00B7EF",
"#DA00FF")
refill()
update_icon()
/obj/item/toy/crayon/spraycan/examine(mob/user)
. = ..()
if(charges_left)
user << "It has [charges_left] uses left."
else
user << "It is empty."
/obj/item/toy/crayon/spraycan/afterattack(atom/target, mob/user, proximity)
if(!proximity)
return
if(is_capped)
user << "<span class='warning'>Take the cap off first!</span>"
return
if(check_empty(user))
return
if(iscarbon(target))
if(pre_noise || post_noise)
playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5)
var/mob/living/carbon/C = target
user.visible_message("<span class='danger'>[user] sprays [src] \
into the face of [target]!</span>")
target << "<span class='userdanger'>[user] sprays [src] into your \
face!</span>"
if(C.client)
C.blur_eyes(3)
C.blind_eyes(1)
if(C.check_eye_prot() <= 0) // no eye protection? ARGH IT BURNS.
C.confused = max(C.confused, 3)
C.Weaken(3)
if(ishuman(C) && actually_paints)
var/mob/living/carbon/human/H = C
H.lip_style = "spray_face"
H.lip_color = paint_color
H.update_body()
// Caution, spray cans contain inflammable substances
. = use_charges(10)
var/fraction = min(1, . / reagents.maximum_volume)
reagents.reaction(C, VAPOR, fraction * volume_multiplier)
return
if(istype(target, /obj/structure/window))
if(actually_paints)
target.color = paint_color
if(color_hex2num(paint_color) < 255)
target.SetOpacity(255)
else
target.SetOpacity(initial(target.opacity))
. = use_charges(2)
var/fraction = min(1, . / reagents.maximum_volume)
reagents.reaction(target, TOUCH, fraction * volume_multiplier)
reagents.trans_to(target, ., volume_multiplier)
if(pre_noise || post_noise)
playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5)
return
. = ..()
/obj/item/toy/crayon/spraycan/update_icon()
icon_state = is_capped ? icon_capped : icon_uncapped
if(use_overlays)
cut_overlays()
var/image/I = image('icons/obj/crayons.dmi',
icon_state = "[is_capped ? "spraycan_cap_colors" : "spraycan_colors"]")
I.color = paint_color
add_overlay(I)
/obj/item/toy/crayon/spraycan/gang
//desc = "A modified container containing suspicious paint."
charges = 20
gang = TRUE
pre_noise = FALSE
post_noise = TRUE
/obj/item/toy/crayon/spraycan/gang/New(loc, datum/gang/G)
..()
if(G)
paint_color = G.color_hex
update_icon()
/obj/item/toy/crayon/spraycan/gang/examine(mob/user)
. = ..()
if((user.mind && user.mind.gang_datum) || isobserver(user))
user << "This spraycan has \
been specially modified for tagging territory."
/obj/item/toy/crayon/spraycan/borg
name = "cyborg spraycan"
desc = "A metallic container containing shiny synthesised paint."
charges = -1
/obj/item/toy/crayon/spraycan/borg/afterattack(atom/target,mob/user,proximity)
var/diff = ..()
if(!isrobot(user))
user << "<span class='notice'>How did you get this?</span>"
qdel(src)
return FALSE
var/mob/living/silicon/robot/borgy = user
if(!diff)
return
// 25 is our cost per unit of paint, making it cost 25 energy per
// normal tag, 50 per window, and 250 per attack
var/cost = diff * 25
// Cyborgs shouldn't be able to use modules without a cell. But if they do
// it's free.
if(borgy.cell)
borgy.cell.use(cost)
/obj/item/toy/crayon/spraycan/hellcan
name = "hellcan"
desc = "This spraycan doesn't seem to be filled with paint..."
icon_state = "deathcan2_cap"
icon_capped = "deathcan2_cap"
icon_uncapped = "deathcan2"
use_overlays = FALSE
volume_multiplier = 25
charges = 100
reagent_contents = list("clf3" = 1)
actually_paints = FALSE
paint_color = "#000000"
/obj/item/toy/crayon/spraycan/lubecan
name = "slippery spraycan"
desc = "You can barely keep hold of this thing."
icon_state = "clowncan2_cap"
icon_capped = "clowncan2_cap"
icon_uncapped = "clowncan2"
use_overlays = FALSE
reagent_contents = list("lube" = 1, "banana" = 1)
volume_multiplier = 5
validSurfaces = list(/turf/open/floor)
/obj/item/toy/crayon/spraycan/mimecan
name = "silent spraycan"
desc = "Art is best seen, not heard."
icon_state = "mimecan_cap"
icon_capped = "mimecan_cap"
icon_uncapped = "mimecan"
use_overlays = FALSE
can_change_colour = FALSE
paint_color = "#FFFFFF" //RGB
pre_noise = FALSE
post_noise = FALSE
reagent_contents = list("nothing" = 1, "mutetoxin" = 1)
#undef RANDOM_GRAFFITI
#undef RANDOM_LETTER
#undef RANDOM_NUMBER
#undef RANDOM_ORIENTED
#undef RANDOM_RUNE
#undef RANDOM_ANY
+52
View File
@@ -0,0 +1,52 @@
/*
* Dehydrated Carp
* Instant carp, just add water
*/
//Child of carpplushie because this should do everything the toy does and more
/obj/item/toy/carpplushie/dehy_carp
var/mob/owner = null //Carp doesn't attack owner, set when using in hand
var/owned = 0 //Boolean, no owner to begin with
var/mobtype = /mob/living/simple_animal/hostile/carp //So admins can change what mob spawns via var fuckery
//Attack self
/obj/item/toy/carpplushie/dehy_carp/attack_self(mob/user)
src.add_fingerprint(user) //Anyone can add their fingerprints to it with this
if(!owned)
user << "<span class='notice'>You pet [src]. You swear it looks up at you.</span>"
owner = user
owned = 1
return ..()
/obj/item/toy/carpplushie/dehy_carp/afterattack(obj/O, mob/user,proximity)
if(!proximity) return
if(istype(O,/obj/structure/sink))
user.drop_item()
loc = get_turf(O)
return Swell()
..()
/obj/item/toy/carpplushie/dehy_carp/proc/Swell()
desc = "It's growing!"
visible_message("<span class='notice'>[src] swells up!</span>")
//Animation
icon = 'icons/mob/animal.dmi'
flick("carp_swell", src)
//Wait for animation to end
sleep(6)
//Make space carp
var/mob/living/M = new mobtype(get_turf(src))
//Make carp non-hostile to user, and their allies
if(owner)
var/list/factions = owner.faction.Copy()
for(var/F in factions)
if(F == "neutral")
factions -= F
M.faction = factions
if (!owner || owner.faction != M.faction)
visible_message("<span class='warning'>You have a bad feeling about this.</span>") //welcome to the hostile carp enjoy your die
else
visible_message("<span class='notice'>The newly grown [M.name] looks up at you with friendly eyes.</span>")
qdel(src)
+991
View File
@@ -0,0 +1,991 @@
//The advanced pea-green monochrome lcd of tomorrow.
var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda
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"
flags = NOBLUDGEON
w_class = 1
slot_flags = SLOT_ID | SLOT_BELT
origin_tech = "programming=2"
//Main variables
var/owner = null // String name of owner
var/default_cartridge = 0 // Access level defined by cartridge
var/obj/item/weapon/cartridge/cartridge = null //current cartridge
var/mode = 0 //Controls what menu the PDA will display. 0 is hub; the rest are either built in or based on cartridge.
var/icon_alert = "pda-r" //Icon to be overlayed for message alerts. Taken from the pda icon file.
//Secondary variables
var/scanmode = 0 //1 is medical scanner, 2 is forensics, 3 is reagent scanner.
var/fon = 0 //Is the flashlight function on?
var/f_lum = 3 //Luminosity for the flashlight function
var/silent = 0 //To beep or not to beep, that is the question
var/toff = 0 //If 1, messenger disabled
var/tnote = null //Current Texts
var/last_text //No text spamming
var/last_noise //Also no honk spamming that's bad too
var/ttone = "beep" //The ringtone!
var/lock_code = "" // Lockcode to unlock uplink
var/honkamt = 0 //How many honks left when infected with honk.exe
var/mimeamt = 0 //How many silence left when infected with mime.exe
var/note = "Congratulations, your station has chosen the Thinktronic 5230 Personal Data Assistant!" //Current note in the notepad function
var/notehtml = ""
var/notescanned = 0 // True if what is in the notekeeper was from a paper.
var/cart = "" //A place to stick cartridge menu information
var/detonate = 1 // Can the PDA be blown up?
var/hidden = 0 // Is the PDA hidden from the PDA list?
var/emped = 0
var/obj/item/weapon/card/id/id = null //Making it possible to slot an ID card into the PDA so it can function as both.
var/ownjob = null //related to above
var/obj/item/device/paicard/pai = null // A slot for a personal AI device
var/image/photo = null //Scanned photo
/obj/item/device/pda/pickup(mob/user)
..()
if(fon)
SetLuminosity(0)
user.AddLuminosity(f_lum)
/obj/item/device/pda/dropped(mob/user)
..()
if(fon)
user.AddLuminosity(-f_lum)
SetLuminosity(f_lum)
/obj/item/device/pda/New()
..()
if(fon)
if(!isturf(loc))
loc.AddLuminosity(f_lum)
SetLuminosity(0)
else
SetLuminosity(f_lum)
PDAs += src
if(default_cartridge)
cartridge = new default_cartridge(src)
new /obj/item/weapon/pen(src)
/obj/item/device/pda/proc/update_label()
name = "PDA-[owner] ([ownjob])" //Name generalisation
/obj/item/device/pda/GetAccess()
if(id)
return id.GetAccess()
else
return ..()
/obj/item/device/pda/GetID()
return id
/obj/item/device/pda/MouseDrop(obj/over_object, src_location, over_location)
var/mob/M = usr
if((!istype(over_object, /obj/screen)) && usr.canUseTopic(src))
return attack_self(M)
return
/obj/item/device/pda/attack_self(mob/user)
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/pda)
assets.send(user)
user.set_machine(src)
if(hidden_uplink && hidden_uplink.active)
hidden_uplink.interact(user)
return
var/dat = "<html><head><title>Personal Data Assistant</title></head><body bgcolor=\"#808000\"><style>a, a:link, a:visited, a:active, a:hover { color: #000000; }img {border-style:none;}</style>"
dat += "<a href='byond://?src=\ref[src];choice=Refresh'><img src=pda_refresh.png> Refresh</a>"
if ((!isnull(cartridge)) && (mode == 0))
dat += " | <a href='byond://?src=\ref[src];choice=Eject'><img src=pda_eject.png> Eject [cartridge]</a>"
if (mode)
dat += " | <a href='byond://?src=\ref[src];choice=Return'><img src=pda_menu.png> Return</a>"
dat += "<br>"
if (!owner)
dat += "Warning: No owner information entered. Please swipe card.<br><br>"
dat += "<a href='byond://?src=\ref[src];choice=Refresh'><img src=pda_refresh.png> Retry</a>"
else
switch (mode)
if (0)
dat += "<h2>PERSONAL DATA ASSISTANT v.1.2</h2>"
dat += "Owner: [owner], [ownjob]<br>"
dat += text("ID: <A href='?src=\ref[src];choice=Authenticate'>[id ? "[id.registered_name], [id.assignment]" : "----------"]")
dat += text("<br><A href='?src=\ref[src];choice=UpdateInfo'>[id ? "Update PDA Info" : ""]</A><br><br>")
dat += "[worldtime2text()]<br>" //:[world.time / 100 % 6][world.time / 100 % 10]"
dat += "[time2text(world.realtime, "MMM DD")] [year_integer+540]"
dat += "<br><br>"
dat += "<h4>General Functions</h4>"
dat += "<ul>"
dat += "<li><a href='byond://?src=\ref[src];choice=1'><img src=pda_notes.png> Notekeeper</a></li>"
dat += "<li><a href='byond://?src=\ref[src];choice=2'><img src=pda_mail.png> Messenger</a></li>"
if (cartridge)
if (cartridge.access_clown)
dat += "<li><a href='byond://?src=\ref[src];choice=Honk'><img src=pda_honk.png> Honk Synthesizer</a></li>"
dat += "<li><a href='byond://?src=\ref[src];choice=Trombone'><img src=pda_honk.png> Sad Trombone</a></li>"
if (cartridge.access_manifest)
dat += "<li><a href='byond://?src=\ref[src];choice=41'><img src=pda_notes.png> View Crew Manifest</a></li>"
if(cartridge.access_status_display)
dat += "<li><a href='byond://?src=\ref[src];choice=42'><img src=pda_status.png> Set Status Display</a></li>"
dat += "</ul>"
if (cartridge.access_engine)
dat += "<h4>Engineering Functions</h4>"
dat += "<ul>"
dat += "<li><a href='byond://?src=\ref[src];choice=43'><img src=pda_power.png> Power Monitor</a></li>"
dat += "</ul>"
if (cartridge.access_medical)
dat += "<h4>Medical Functions</h4>"
dat += "<ul>"
dat += "<li><a href='byond://?src=\ref[src];choice=44'><img src=pda_medical.png> Medical Records</a></li>"
dat += "<li><a href='byond://?src=\ref[src];choice=Medical Scan'><img src=pda_scanner.png> [scanmode == 1 ? "Disable" : "Enable"] Medical Scanner</a></li>"
dat += "</ul>"
if (cartridge.access_security)
dat += "<h4>Security Functions</h4>"
dat += "<ul>"
dat += "<li><a href='byond://?src=\ref[src];choice=45'><img src=pda_cuffs.png> Security Records</A></li>"
dat += "</ul>"
if(cartridge.access_quartermaster)
dat += "<h4>Quartermaster Functions:</h4>"
dat += "<ul>"
dat += "<li><a href='byond://?src=\ref[src];choice=47'><img src=pda_crate.png> Supply Records</A></li>"
dat += "</ul>"
dat += "</ul>"
dat += "<h4>Utilities</h4>"
dat += "<ul>"
if (cartridge)
if(cartridge.bot_access_flags)
dat += "<li><a href='byond://?src=\ref[src];choice=54'><img src=pda_medbot.png> Bots Access</a></li>"
if (cartridge.access_janitor)
dat += "<li><a href='byond://?src=\ref[src];choice=49'><img src=pda_bucket.png> Custodial Locator</a></li>"
if (istype(cartridge.radio, /obj/item/radio/integrated/signal))
dat += "<li><a href='byond://?src=\ref[src];choice=40'><img src=pda_signaler.png> Signaler System</a></li>"
if (cartridge.access_newscaster)
dat += "<li><a href='byond://?src=\ref[src];choice=53'><img src=pda_notes.png> Newscaster Access </a></li>"
if (cartridge.access_reagent_scanner)
dat += "<li><a href='byond://?src=\ref[src];choice=Reagent Scan'><img src=pda_reagent.png> [scanmode == 3 ? "Disable" : "Enable"] Reagent Scanner</a></li>"
if (cartridge.access_engine)
dat += "<li><a href='byond://?src=\ref[src];choice=Halogen Counter'><img src=pda_reagent.png> [scanmode == 4 ? "Disable" : "Enable"] Halogen Counter</a></li>"
if (cartridge.access_atmos)
dat += "<li><a href='byond://?src=\ref[src];choice=Gas Scan'><img src=pda_reagent.png> [scanmode == 5 ? "Disable" : "Enable"] Gas Scanner</a></li>"
if (cartridge.access_remote_door)
dat += "<li><a href='byond://?src=\ref[src];choice=Toggle Door'><img src=pda_rdoor.png> Toggle Remote Door</a></li>"
dat += "<li><a href='byond://?src=\ref[src];choice=3'><img src=pda_atmos.png> Atmospheric Scan</a></li>"
dat += "<li><a href='byond://?src=\ref[src];choice=Light'><img src=pda_flashlight.png> [fon ? "Disable" : "Enable"] Flashlight</a></li>"
if (pai)
if(pai.loc != src)
pai = null
else
dat += "<li><a href='byond://?src=\ref[src];choice=pai;option=1'>pAI Device Configuration</a></li>"
dat += "<li><a href='byond://?src=\ref[src];choice=pai;option=2'>Eject pAI Device</a></li>"
dat += "</ul>"
if (1)
dat += "<h4><img src=pda_notes.png> Notekeeper V2.2</h4>"
dat += "<a href='byond://?src=\ref[src];choice=Edit'>Edit</a><br>"
if(notescanned)
dat += "(This is a scanned image, editing it may cause some text formatting to change.)<br>"
dat += "<HR><font face=\"[PEN_FONT]\">[(!notehtml ? note : notehtml)]</font>"
if (2)
dat += "<h4><img src=pda_mail.png> SpaceMessenger V3.9.6</h4>"
dat += "<a href='byond://?src=\ref[src];choice=Toggle Ringer'><img src=pda_bell.png> Ringer: [silent == 1 ? "Off" : "On"]</a> | "
dat += "<a href='byond://?src=\ref[src];choice=Toggle Messenger'><img src=pda_mail.png> Send / Receive: [toff == 1 ? "Off" : "On"]</a> | "
dat += "<a href='byond://?src=\ref[src];choice=Ringtone'><img src=pda_bell.png> Set Ringtone</a> | "
dat += "<a href='byond://?src=\ref[src];choice=21'><img src=pda_mail.png> Messages</a><br>"
if (istype(cartridge, /obj/item/weapon/cartridge/syndicate))
dat += "<b>[cartridge:shock_charges] detonation charges left.</b><HR>"
if (istype(cartridge, /obj/item/weapon/cartridge/clown))
dat += "<b>[cartridge:honk_charges] viral files left.</b><HR>"
if (istype(cartridge, /obj/item/weapon/cartridge/mime))
dat += "<b>[cartridge:mime_charges] viral files left.</b><HR>"
dat += "<h4><img src=pda_menu.png> Detected PDAs</h4>"
dat += "<ul>"
var/count = 0
if (!toff)
for (var/obj/item/device/pda/P in sortNames(get_viewable_pdas()))
if (P == src)
continue
dat += "<li><a href='byond://?src=\ref[src];choice=Message;target=\ref[P]'>[P]</a>"
if (istype(cartridge, /obj/item/weapon/cartridge/syndicate) && P.detonate)
dat += " (<a href='byond://?src=\ref[src];choice=Detonate;target=\ref[P]'><img src=pda_boom.png>*Detonate*</a>)"
if (istype(cartridge, /obj/item/weapon/cartridge/clown))
dat += " (<a href='byond://?src=\ref[src];choice=Send Honk;target=\ref[P]'><img src=pda_honk.png>*Send Virus*</a>)"
if (istype(cartridge, /obj/item/weapon/cartridge/mime))
dat += " (<a href='byond://?src=\ref[src];choice=Send Silence;target=\ref[P]'>*Send Virus*</a>)"
dat += "</li>"
count++
dat += "</ul>"
if (count == 0)
dat += "None detected.<br>"
else if(cartridge && cartridge.spam_enabled)
dat += "<a href='byond://?src=\ref[src];choice=MessageAll'>Send To All</a>"
if(21)
dat += "<h4><img src=pda_mail.png> SpaceMessenger V3.9.6</h4>"
dat += "<a href='byond://?src=\ref[src];choice=Clear'><img src=pda_blank.png> Clear Messages</a>"
dat += "<h4><img src=pda_mail.png> Messages</h4>"
dat += tnote
dat += "<br>"
if (3)
dat += "<h4><img src=pda_atmos.png> Atmospheric Readings</h4>"
var/turf/T = user.loc
if (isnull(T))
dat += "Unable to obtain a reading.<br>"
else
var/datum/gas_mixture/environment = T.return_air()
var/list/env_gases = environment.gases
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
dat += "Air Pressure: [round(pressure,0.1)] kPa<br>"
if (total_moles)
for(var/id in env_gases)
var/gas_level = env_gases[id][MOLES]/total_moles
if(gas_level > 0)
dat += "[env_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_level*100, 0.01)]%<br>"
dat += "Temperature: [round(environment.temperature-T0C)]&deg;C<br>"
dat += "<br>"
else//Else it links to the cart menu proc. Although, it really uses menu hub 4--menu 4 doesn't really exist as it simply redirects to hub.
dat += cart
dat += "</body></html>"
user << browse(dat, "window=pda;size=400x450;border=1;can_resize=1;can_minimize=0")
onclose(user, "pda", src)
/obj/item/device/pda/Topic(href, href_list)
..()
var/mob/living/U = usr
//Looking for master was kind of pointless since PDAs don't appear to have one.
if(usr.canUseTopic(src) && !href_list["close"])
add_fingerprint(U)
U.set_machine(src)
switch(href_list["choice"])
//BASIC FUNCTIONS===================================
if("Refresh")//Refresh, goes to the end of the proc.
if("Return")//Return
if(mode<=9)
mode = 0
else
mode = round(mode/10)
if(mode==4 || mode == 5)//Fix for cartridges. Redirects to hub.
mode = 0
else if(mode >= 40 && mode <= 59)//Fix for cartridges. Redirects to refresh the menu.
cartridge.mode = mode
cartridge.unlock()
if ("Authenticate")//Checks for ID
id_check(U, 1)
if("UpdateInfo")
ownjob = id.assignment
update_label()
if("Eject")//Ejects the cart, only done from hub.
if (!isnull(cartridge))
var/turf/T = loc
if(ismob(T))
T = T.loc
cartridge.loc = T
scanmode = 0
if (cartridge.radio)
cartridge.radio.hostpda = null
cartridge = null
//MENU FUNCTIONS===================================
if("0")//Hub
mode = 0
if("1")//Notes
mode = 1
if("2")//Messenger
mode = 2
if("21")//Read messeges
mode = 21
if("3")//Atmos scan
mode = 3
if("4")//Redirects to hub
mode = 0
//MAIN FUNCTIONS===================================
if("Light")
if(fon)
fon = 0
if(src in U.contents)
U.AddLuminosity(-f_lum)
else
SetLuminosity(0)
else
fon = 1
if(src in U.contents)
U.AddLuminosity(f_lum)
else
SetLuminosity(f_lum)
if("Medical Scan")
if(scanmode == 1)
scanmode = 0
else if((!isnull(cartridge)) && (cartridge.access_medical))
scanmode = 1
if("Reagent Scan")
if(scanmode == 3)
scanmode = 0
else if((!isnull(cartridge)) && (cartridge.access_reagent_scanner))
scanmode = 3
if("Halogen Counter")
if(scanmode == 4)
scanmode = 0
else if((!isnull(cartridge)) && (cartridge.access_engine))
scanmode = 4
if("Honk")
if ( !(last_noise && world.time < last_noise + 20) )
playsound(loc, 'sound/items/bikehorn.ogg', 50, 1)
last_noise = world.time
if("Trombone")
if ( !(last_noise && world.time < last_noise + 20) )
playsound(loc, 'sound/misc/sadtrombone.ogg', 50, 1)
last_noise = world.time
if("Gas Scan")
if(scanmode == 5)
scanmode = 0
else if((!isnull(cartridge)) && (cartridge.access_atmos))
scanmode = 5
//NOTEKEEPER FUNCTIONS===================================
if ("Edit")
var/n = stripped_multiline_input(U, "Please enter message", name, note)
if (in_range(src, U) && loc == U)
if (mode == 1 && n)
note = n
notehtml = parsepencode(n, U, SIGNFONT)
notescanned = 0
else
U << browse(null, "window=pda")
return
//MESSENGER FUNCTIONS===================================
if("Toggle Messenger")
toff = !toff
if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status
silent = !silent
if("Clear")//Clears messages
tnote = null
if("Ringtone")
var/t = input(U, "Please enter new ringtone", name, ttone) as text
if(in_range(src, U) && loc == U)
if(t)
if(hidden_uplink && (trim(lowertext(t)) == trim(lowertext(lock_code))))
hidden_uplink.interact(U)
U << "The PDA softly beeps."
U << browse(null, "window=pda")
src.mode = 0
else
t = copytext(sanitize(t), 1, 20)
ttone = t
else
U << browse(null, "window=pda")
return
if("Message")
var/obj/item/device/pda/P = locate(href_list["target"])
src.create_message(U, P)
if("MessageAll")
src.send_to_all(U)
if("Send Honk")//Honk virus
if(istype(cartridge, /obj/item/weapon/cartridge/clown))//Cartridge checks are kind of unnecessary since everything is done through switch.
var/obj/item/device/pda/P = locate(href_list["target"])//Leaving it alone in case it may do something useful, I guess.
if(!isnull(P))
if (!P.toff && cartridge:honk_charges > 0)
cartridge:honk_charges--
U.show_message("<span class='notice'>Virus sent!</span>", 1)
P.honkamt = (rand(15,20))
else
U << "PDA not found."
else
U << browse(null, "window=pda")
return
if("Send Silence")//Silent virus
if(istype(cartridge, /obj/item/weapon/cartridge/mime))
var/obj/item/device/pda/P = locate(href_list["target"])
if(!isnull(P))
if (!P.toff && cartridge:mime_charges > 0)
cartridge:mime_charges--
U.show_message("<span class='notice'>Virus sent!</span>", 1)
P.silent = 1
P.ttone = "silence"
else
U << "PDA not found."
else
U << browse(null, "window=pda")
return
//SYNDICATE FUNCTIONS===================================
if("Toggle Door")
if(cartridge && cartridge.access_remote_door)
for(var/obj/machinery/door/poddoor/M in machines)
if(M.id == cartridge.remote_door_id)
if(M.density)
M.open()
else
M.close()
if("Detonate")//Detonate PDA
if(istype(cartridge, /obj/item/weapon/cartridge/syndicate))
var/obj/item/device/pda/P = locate(href_list["target"])
if(!isnull(P))
if (!P.toff && cartridge:shock_charges > 0)
cartridge:shock_charges--
var/difficulty = 0
if(P.cartridge)
difficulty += P.cartridge.access_medical
difficulty += P.cartridge.access_security
difficulty += P.cartridge.access_engine
difficulty += P.cartridge.access_clown
difficulty += P.cartridge.access_janitor
difficulty += P.cartridge.access_manifest * 2
else
difficulty += 2
if(prob(difficulty * 15) || (P.hidden_uplink))
U.show_message("<span class='danger'>An error flashes on your [src].</span>", 1)
else
U.show_message("<span class='notice'>Success!</span>", 1)
P.explode()
else
U << "PDA not found."
else
U.unset_machine()
U << browse(null, "window=pda")
return
//pAI FUNCTIONS===================================
if("pai")
switch(href_list["option"])
if("1") // Configure pAI device
pai.attack_self(U)
if("2") // Eject pAI device
var/turf/T = get_turf(src.loc)
if(T)
pai.loc = T
//LINK FUNCTIONS===================================
else//Cartridge menu linking
mode = text2num(href_list["choice"])
if(cartridge)
cartridge.mode = mode
cartridge.unlock()
else//If not in range, can't interact or not using the pda.
U.unset_machine()
U << browse(null, "window=pda")
return
//EXTRA FUNCTIONS===================================
if (mode == 2||mode == 21)//To clear message overlays.
cut_overlays()
if ((honkamt > 0) && (prob(60)))//For clown virus.
honkamt--
playsound(loc, 'sound/items/bikehorn.ogg', 30, 1)
if(U.machine == src && href_list["skiprefresh"]!="1")//Final safety.
attack_self(U)//It auto-closes the menu prior if the user is not in range and so on.
else
U.unset_machine()
U << browse(null, "window=pda")
return
/obj/item/device/pda/proc/remove_id()
if (id)
if (ismob(loc))
var/mob/M = loc
M.put_in_hands(id)
usr << "<span class='notice'>You remove the ID from the [name].</span>"
else
id.loc = get_turf(src)
id = null
/obj/item/device/pda/proc/msg_input(mob/living/U = usr)
var/t = stripped_input(U, "Please enter message", name, null, MAX_MESSAGE_LEN)
if (!t || toff)
return
if (!in_range(src, U) && loc != U)
return
if(!U.canUseTopic(src))
return
if(emped)
t = Gibberish(t, 100)
return t
/obj/item/device/pda/proc/send_message(mob/living/user = usr,list/obj/item/device/pda/targets)
var/message = msg_input(user)
if(!message || !targets.len)
return
if(last_text && world.time < last_text + 5)
return
var/multiple = targets.len > 1
var/datum/data_pda_msg/last_sucessful_msg
for(var/obj/item/device/pda/P in targets)
if(P == src)
continue
var/obj/machinery/message_server/MS = null
MS = can_send(P)
if(MS)
var/datum/data_pda_msg/msg = MS.send_pda_message("[P.owner]","[owner]","[message]",photo)
if(msg)
last_sucessful_msg = msg
if(!multiple)
show_to_sender(msg)
P.show_recieved_message(msg,src)
if(!multiple)
show_to_ghosts(user,msg)
log_pda("[user] (PDA: [src.name]) sent \"[message]\" to [P.name]")
else
if(!multiple)
user << "<span class='notice'>ERROR: Server isn't responding.</span>"
return
photo = null
if(multiple)
show_to_sender(last_sucessful_msg,1)
show_to_ghosts(user,last_sucessful_msg,1)
log_pda("[user] (PDA: [src.name]) sent \"[message]\" to Everyone")
/obj/item/device/pda/proc/show_to_sender(datum/data_pda_msg/msg,multiple = 0)
tnote += "<i><b>&rarr; To [multiple ? "Everyone" : msg.recipient]:</b></i><br>[msg.message][msg.get_photo_ref()]<br>"
/obj/item/device/pda/proc/show_recieved_message(datum/data_pda_msg/msg,obj/item/device/pda/source)
tnote += "<i><b>&larr; From <a href='byond://?src=\ref[src];choice=Message;target=\ref[source]'>[source.owner]</a> ([source.ownjob]):</b></i><br>[msg.message][msg.get_photo_ref()]<br>"
if (!silent)
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
audible_message("\icon[src] *[ttone]*", null, 3)
//Search for holder of the PDA.
var/mob/living/L = null
if(loc && isliving(loc))
L = loc
//Maybe they are a pAI!
else
L = get(src, /mob/living/silicon)
if(L && L.stat != UNCONSCIOUS)
L << "\icon[src] <b>Message from [source.owner] ([source.ownjob]), </b>\"[msg.message]\"[msg.get_photo_ref()] (<a href='byond://?src=\ref[src];choice=Message;skiprefresh=1;target=\ref[source]'>Reply</a>)"
cut_overlays()
add_overlay(image(icon, icon_alert))
/obj/item/device/pda/proc/show_to_ghosts(mob/living/user, datum/data_pda_msg/msg,multiple = 0)
for(var/mob/M in player_list)
if(isobserver(M) && M.client && (M.client.prefs.chat_toggles & CHAT_GHOSTPDA))
var/link = FOLLOW_LINK(M, user)
M << "[link] <span class='name'>[msg.sender] </span><span class='game say'>PDA Message</span> --> <span class='name'>[multiple ? "Everyone" : msg.recipient]</span>: <span class='message'>[msg.message][msg.get_photo_ref()]</span></span>"
/obj/item/device/pda/proc/can_send(obj/item/device/pda/P)
if(!P || qdeleted(P) || P.toff)
return null
var/obj/machinery/message_server/useMS = null
if(message_servers)
for (var/obj/machinery/message_server/MS in message_servers)
//PDAs are now dependant on the Message Server.
if(MS.active)
useMS = MS
break
var/datum/signal/signal = src.telecomms_process()
if(!P || qdeleted(P) || P.toff) //in case the PDA or mob gets destroyed during telecomms_process()
return null
var/useTC = 0
if(signal)
if(signal.data["done"])
useTC = 1
var/turf/pos = get_turf(P)
if(pos.z in signal.data["level"])
useTC = 2
if(useTC == 2)
return useMS
else
return null
/obj/item/device/pda/proc/send_to_all(mob/living/U = usr)
send_message(U,get_viewable_pdas())
/obj/item/device/pda/proc/create_message(mob/living/U = usr, obj/item/device/pda/P)
send_message(U,list(P))
/obj/item/device/pda/AltClick()
..()
if(issilicon(usr))
return
if(usr.canUseTopic(src))
if(id)
remove_id()
else
usr << "<span class='warning'>This PDA does not have an ID in it!</span>"
/obj/item/device/pda/verb/verb_remove_id()
set category = "Object"
set name = "Eject ID"
set src in usr
if(issilicon(usr))
return
if (usr.canUseTopic(src))
if(id)
remove_id()
else
usr << "<span class='warning'>This PDA does not have an ID in it!</span>"
/obj/item/device/pda/verb/verb_remove_pen()
set category = "Object"
set name = "Remove Pen"
set src in usr
if(issilicon(usr))
return
if (usr.canUseTopic(src))
var/obj/item/weapon/pen/O = locate() in src
if(O)
if (istype(loc, /mob))
var/mob/M = loc
if(M.get_active_hand() == null)
M.put_in_hands(O)
usr << "<span class='notice'>You remove \the [O] from \the [src].</span>"
return
O.loc = get_turf(src)
else
usr << "<span class='warning'>This PDA does not have a pen in it!</span>"
/obj/item/device/pda/proc/id_check(mob/user, choice as num)//To check for IDs; 1 for in-pda use, 2 for out of pda use.
if(choice == 1)
if (id)
remove_id()
else
var/obj/item/I = user.get_active_hand()
if (istype(I, /obj/item/weapon/card/id))
if(!user.unEquip(I))
return 0
I.loc = src
id = I
else
var/obj/item/weapon/card/I = user.get_active_hand()
if (istype(I, /obj/item/weapon/card/id) && I:registered_name)
if(!user.unEquip(I))
return 0
var/obj/old_id = id
I.loc = src
id = I
user.put_in_hands(old_id)
return 1
// access to status display signals
/obj/item/device/pda/attackby(obj/item/C, mob/user, params)
if(istype(C, /obj/item/weapon/cartridge) && !cartridge)
cartridge = C
if(!user.unEquip(C))
return
cartridge.loc = src
user << "<span class='notice'>You insert [cartridge] into [src].</span>"
if(cartridge.radio)
cartridge.radio.hostpda = src
else if(istype(C, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/idcard = C
if(!idcard.registered_name)
user << "<span class='warning'>\The [src] rejects the ID!</span>"
return
if(!owner)
owner = idcard.registered_name
ownjob = idcard.assignment
update_label()
user << "<span class='notice'>Card scanned.</span>"
else
//Basic safety check. If either both objects are held by user or PDA is on ground and card is in hand.
if(((src in user.contents) && (C in user.contents)) || (istype(loc, /turf) && in_range(src, user) && (C in user.contents)) )
if(!id_check(user, 2))
return
user << "<span class='notice'>You put the ID into \the [src]'s slot.</span>"
updateSelfDialog()//Update self dialog on success.
return //Return in case of failed check or when successful.
updateSelfDialog()//For the non-input related code.
else if(istype(C, /obj/item/device/paicard) && !src.pai)
if(!user.unEquip(C))
return
C.loc = src
pai = C
user << "<span class='notice'>You slot \the [C] into [src].</span>"
updateUsrDialog()
else if(istype(C, /obj/item/weapon/pen))
var/obj/item/weapon/pen/O = locate() in src
if(O)
user << "<span class='warning'>There is already a pen in \the [src]!</span>"
else
if(!user.unEquip(C))
return
C.loc = src
user << "<span class='notice'>You slide \the [C] into \the [src].</span>"
else if(istype(C, /obj/item/weapon/photo))
var/obj/item/weapon/photo/P = C
photo = P.img
user << "<span class='notice'>You scan \the [C].</span>"
else
return ..()
/obj/item/device/pda/attack(mob/living/carbon/C, mob/living/user)
if(istype(C))
switch(scanmode)
if(1)
C.visible_message("<span class='alert'>[user] has analyzed [C]'s vitals!</span>")
healthscan(user, C, 1)
add_fingerprint(user)
if(2)
// Unused
if(4)
C.visible_message("<span class='warning'>[user] has analyzed [C]'s radiation levels!</span>")
user.show_message("<span class='notice'>Analyzing Results for [C]:</span>")
if(C.radiation)
user.show_message("\green Radiation Level: \black [C.radiation]")
else
user.show_message("<span class='notice'>No radiation detected.</span>")
/obj/item/device/pda/afterattack(atom/A as mob|obj|turf|area, mob/user, proximity)
if(!proximity) return
switch(scanmode)
if(3)
if(!isnull(A.reagents))
if(A.reagents.reagent_list.len > 0)
var/reagents_length = A.reagents.reagent_list.len
user << "<span class='notice'>[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found.</span>"
for (var/re in A.reagents.reagent_list)
user << "<span class='notice'>\t [re]</span>"
else
user << "<span class='notice'>No active chemical agents found in [A].</span>"
else
user << "<span class='notice'>No significant chemical agents found in [A].</span>"
if(5)
if (istype(A, /obj/item/weapon/tank))
var/obj/item/weapon/tank/T = A
atmosanalyzer_scan(T.air_contents, user, T)
else if (istype(A, /obj/machinery/portable_atmospherics))
var/obj/machinery/portable_atmospherics/PA = A
atmosanalyzer_scan(PA.air_contents, user, PA)
else if (istype(A, /obj/machinery/atmospherics/pipe))
var/obj/machinery/atmospherics/pipe/P = A
atmosanalyzer_scan(P.parent.air, user, P)
else if (istype(A, /obj/machinery/power/rad_collector))
var/obj/machinery/power/rad_collector/RC = A
if(RC.loaded_tank)
atmosanalyzer_scan(RC.loaded_tank.air_contents, user, RC)
else if (istype(A, /obj/item/weapon/flamethrower))
var/obj/item/weapon/flamethrower/F = A
if(F.ptank)
atmosanalyzer_scan(F.ptank.air_contents, user, F)
if (!scanmode && istype(A, /obj/item/weapon/paper) && owner)
var/obj/item/weapon/paper/PP = A
if (!PP.info)
user << "<span class='warning'>Unable to scan! Paper is blank.</span>"
return
notehtml = PP.info
note = replacetext(notehtml, "<BR>", "\[br\]")
note = replacetext(note, "<li>", "\[*\]")
note = replacetext(note, "<ul>", "\[list\]")
note = replacetext(note, "</ul>", "\[/list\]")
note = html_encode(note)
notescanned = 1
user << "<span class='notice'>Paper scanned. Saved to PDA's notekeeper.</span>" //concept of scanning paper copyright brainoblivion 2009
/obj/item/device/pda/proc/explode() //This needs tuning.
if(!detonate) return
var/turf/T = get_turf(src)
if (ismob(loc))
var/mob/M = loc
M.show_message("<span class='userdanger'>Your [src] explodes!</span>", 1)
else
visible_message("<span class='danger'>[src] explodes!</span>", "<span class='warning'>You hear a loud *pop*!</span>")
if(T)
T.hotspot_expose(700,125)
if(istype(cartridge, /obj/item/weapon/cartridge/syndicate))
explosion(T, -1, 1, 3, 4)
else
explosion(T, -1, -1, 2, 3)
qdel(src)
return
/obj/item/device/pda/Destroy()
PDAs -= src
return ..()
//AI verb and proc for sending PDA messages.
/mob/living/silicon/ai/proc/cmd_send_pdamesg(mob/user)
var/list/names = list()
var/list/plist = list()
var/list/namecounts = list()
if(user.stat == 2)
return //won't work if dead
if(src.aiPDA.toff)
user << "Turn on your receiver in order to send messages."
return
for (var/obj/item/device/pda/P in get_viewable_pdas())
if (P == src)
continue
else if (P == src.aiPDA)
continue
var/name = P.owner
if (name in names)
namecounts[name]++
name = text("[name] ([namecounts[name]])")
else
names.Add(name)
namecounts[name] = 1
plist[text("[name]")] = P
var/c = input(user, "Please select a PDA") as null|anything in sortList(plist)
if (!c)
return
var/selected = plist[c]
if(aicamera.aipictures.len>0)
var/add_photo = input(user,"Do you want to attach a photo?","Photo","No") as null|anything in list("Yes","No")
if(add_photo=="Yes")
var/datum/picture/Pic = aicamera.selectpicture(aicamera)
src.aiPDA.photo = Pic.fields["img"]
src.aiPDA.create_message(src, selected)
/mob/living/silicon/ai/verb/cmd_toggle_pda_receiver()
set category = "AI Commands"
set name = "PDA - Toggle Sender/Receiver"
if(usr.stat == 2)
return //won't work if dead
if(!isnull(aiPDA))
aiPDA.toff = !aiPDA.toff
usr << "<span class='notice'>PDA sender/receiver toggled [(aiPDA.toff ? "Off" : "On")]!</span>"
else
usr << "You do not have a PDA. You should make an issue report about this."
/mob/living/silicon/ai/verb/cmd_toggle_pda_silent()
set category = "AI Commands"
set name = "PDA - Toggle Ringer"
if(usr.stat == 2)
return //won't work if dead
if(!isnull(aiPDA))
//0
aiPDA.silent = !aiPDA.silent
usr << "<span class='notice'>PDA ringer toggled [(aiPDA.silent ? "Off" : "On")]!</span>"
else
usr << "You do not have a PDA. You should make an issue report about this."
/mob/living/silicon/ai/proc/cmd_show_message_log(mob/user)
if(user.stat == 2)
return //won't work if dead
if(!isnull(aiPDA))
var/HTML = "<html><head><title>AI PDA Message Log</title></head><body>[aiPDA.tnote]</body></html>"
user << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0")
else
user << "You do not have a PDA. You should make an issue report about this."
//Some spare PDAs in a box
/obj/item/weapon/storage/box/PDAs
name = "spare PDAs"
desc = "A box of spare PDA microcomputers."
icon = 'icons/obj/storage.dmi'
icon_state = "pda"
/obj/item/weapon/storage/box/PDAs/New()
..()
new /obj/item/device/pda(src)
new /obj/item/device/pda(src)
new /obj/item/device/pda(src)
new /obj/item/device/pda(src)
new /obj/item/weapon/cartridge/head(src)
var/newcart = pick( /obj/item/weapon/cartridge/engineering,
/obj/item/weapon/cartridge/security,
/obj/item/weapon/cartridge/medical,
/obj/item/weapon/cartridge/signal/toxins,
/obj/item/weapon/cartridge/quartermaster)
new newcart(src)
// Pass along the pulse to atoms in contents, largely added so pAIs are vulnerable to EMP
/obj/item/device/pda/emp_act(severity)
for(var/atom/A in src)
A.emp_act(severity)
emped += 1
spawn(200 * severity)
emped -= 1
/proc/get_viewable_pdas()
. = list()
// Returns a list of PDAs which can be viewed from another PDA/message monitor.
for(var/obj/item/device/pda/P in PDAs)
if(!P.owner || P.toff || P.hidden) continue
. += P
return .
@@ -0,0 +1,200 @@
//Clown PDA is slippery.
/obj/item/device/pda/clown
name = "clown PDA"
default_cartridge = /obj/item/weapon/cartridge/clown
icon_state = "pda-clown"
desc = "A portable microcomputer by Thinktronic Systems, LTD. The surface is coated with polytetrafluoroethylene and banana drippings."
ttone = "honk"
/obj/item/device/pda/clown/Crossed(AM as mob|obj)
if (istype(AM, /mob/living/carbon))
var/mob/living/carbon/M = AM
if(M.slip(0, 6, src, NO_SLIP_WHEN_WALKING))
if (ishuman(M) && (M.real_name != src.owner))
if (istype(src.cartridge, /obj/item/weapon/cartridge/clown))
var/obj/item/weapon/cartridge/clown/cart = src.cartridge
if(cart.honk_charges < 5)
cart.honk_charges++
// Special AI/pAI PDAs that cannot explode.
/obj/item/device/pda/ai
icon_state = "NONE"
ttone = "data"
fon = 0
detonate = 0
/obj/item/device/pda/ai/attack_self(mob/user)
if ((honkamt > 0) && (prob(60)))//For clown virus.
honkamt--
playsound(loc, 'sound/items/bikehorn.ogg', 30, 1)
return
/obj/item/device/pda/ai/pai
ttone = "assist"
/obj/item/device/pda/medical
name = "medical PDA"
default_cartridge = /obj/item/weapon/cartridge/medical
icon_state = "pda-medical"
/obj/item/device/pda/viro
name = "virology PDA"
default_cartridge = /obj/item/weapon/cartridge/medical
icon_state = "pda-virology"
/obj/item/device/pda/engineering
name = "engineering PDA"
default_cartridge = /obj/item/weapon/cartridge/engineering
icon_state = "pda-engineer"
/obj/item/device/pda/security
name = "security PDA"
default_cartridge = /obj/item/weapon/cartridge/security
icon_state = "pda-security"
/obj/item/device/pda/detective
name = "detective PDA"
default_cartridge = /obj/item/weapon/cartridge/detective
icon_state = "pda-detective"
/obj/item/device/pda/warden
name = "warden PDA"
default_cartridge = /obj/item/weapon/cartridge/security
icon_state = "pda-warden"
/obj/item/device/pda/janitor
name = "janitor PDA"
default_cartridge = /obj/item/weapon/cartridge/janitor
icon_state = "pda-janitor"
ttone = "slip"
/obj/item/device/pda/toxins
name = "scientist PDA"
default_cartridge = /obj/item/weapon/cartridge/signal/toxins
icon_state = "pda-science"
ttone = "boom"
/obj/item/device/pda/mime
name = "mime PDA"
default_cartridge = /obj/item/weapon/cartridge/mime
icon_state = "pda-mime"
silent = 1
ttone = "silence"
/obj/item/device/pda/heads
default_cartridge = /obj/item/weapon/cartridge/head
icon_state = "pda-hop"
/obj/item/device/pda/heads/hop
name = "head of personnel PDA"
default_cartridge = /obj/item/weapon/cartridge/hop
icon_state = "pda-hop"
/obj/item/device/pda/heads/hos
name = "head of security PDA"
default_cartridge = /obj/item/weapon/cartridge/hos
icon_state = "pda-hos"
/obj/item/device/pda/heads/ce
name = "chief engineer PDA"
default_cartridge = /obj/item/weapon/cartridge/ce
icon_state = "pda-ce"
/obj/item/device/pda/heads/cmo
name = "chief medical officer PDA"
default_cartridge = /obj/item/weapon/cartridge/cmo
icon_state = "pda-cmo"
/obj/item/device/pda/heads/rd
name = "research director PDA"
default_cartridge = /obj/item/weapon/cartridge/rd
icon_state = "pda-rd"
/obj/item/device/pda/captain
name = "captain PDA"
default_cartridge = /obj/item/weapon/cartridge/captain
icon_state = "pda-captain"
detonate = 0
/obj/item/device/pda/cargo
name = "cargo technician PDA"
default_cartridge = /obj/item/weapon/cartridge/quartermaster
icon_state = "pda-cargo"
/obj/item/device/pda/quartermaster
name = "quartermaster PDA"
default_cartridge = /obj/item/weapon/cartridge/quartermaster
icon_state = "pda-qm"
/obj/item/device/pda/shaftminer
name = "shaft miner PDA"
icon_state = "pda-miner"
/obj/item/device/pda/syndicate
default_cartridge = /obj/item/weapon/cartridge/syndicate
icon_state = "pda-syndi"
name = "military PDA"
owner = "John Doe"
hidden = 1
/obj/item/device/pda/chaplain
name = "chaplain PDA"
icon_state = "pda-chaplain"
ttone = "holy"
/obj/item/device/pda/lawyer
name = "lawyer PDA"
default_cartridge = /obj/item/weapon/cartridge/lawyer
icon_state = "pda-lawyer"
ttone = "objection"
/obj/item/device/pda/botanist
name = "botanist PDA"
//default_cartridge = /obj/item/weapon/cartridge/botanist
icon_state = "pda-hydro"
/obj/item/device/pda/roboticist
name = "roboticist PDA"
icon_state = "pda-roboticist"
default_cartridge = /obj/item/weapon/cartridge/roboticist
/obj/item/device/pda/librarian
name = "librarian PDA"
icon_state = "pda-library"
icon_alert = "pda-r-library"
default_cartridge = /obj/item/weapon/cartridge/librarian
desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a WGW-11 series e-reader."
note = "Congratulations, your station has chosen the Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant!"
silent = 1 //Quiet in the library!
/obj/item/device/pda/clear
name = "clear PDA"
icon_state = "pda-clear"
desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a special edition with a transparent case."
note = "Congratulations, you have chosen the Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition!"
/obj/item/device/pda/cook
name = "cook PDA"
icon_state = "pda-cook"
/obj/item/device/pda/bar
name = "bartender PDA"
icon_state = "pda-bartender"
/obj/item/device/pda/atmos
name = "atmospherics PDA"
default_cartridge = /obj/item/weapon/cartridge/atmos
icon_state = "pda-atmos"
/obj/item/device/pda/chemist
name = "chemist PDA"
default_cartridge = /obj/item/weapon/cartridge/chemistry
icon_state = "pda-chemistry"
/obj/item/device/pda/geneticist
name = "geneticist PDA"
default_cartridge = /obj/item/weapon/cartridge/medical
icon_state = "pda-genetics"
+778
View File
@@ -0,0 +1,778 @@
/obj/item/weapon/cartridge
name = "generic cartridge"
desc = "A data cartridge for portable microcomputers."
icon = 'icons/obj/pda.dmi'
icon_state = "cart"
item_state = "electronic"
w_class = 1
var/obj/item/radio/integrated/radio = null
var/access_security = 0
var/access_engine = 0
var/access_atmos = 0
var/access_medical = 0
var/access_manifest = 0
var/access_clown = 0
var/access_mime = 0
var/access_janitor = 0
// var/access_flora = 0
var/access_reagent_scanner = 0
var/access_newscaster = 0
var/access_remote_door = 0 //Control some blast doors remotely!!
var/remote_door_id = ""
var/access_status_display = 0
var/access_quartermaster = 0
var/access_hydroponics = 0
var/bot_access_flags = 0 //Bit flags. Selection: SEC_BOT|MULE_BOT|FLOOR_BOT|CLEAN_BOT|MED_BOT
var/spam_enabled = 0 //Enables "Send to All" Option
var/mode = null
var/menu
var/datum/data/record/active1 = null //General
var/datum/data/record/active2 = null //Medical
var/datum/data/record/active3 = null //Security
var/obj/machinery/computer/monitor/powmonitor = null // Power Monitor
var/list/powermonitors = list()
var/message1 // used for status_displays
var/message2
var/list/stored_data = list()
var/current_channel
var/mob/living/simple_animal/bot/active_bot
var/list/botlist = list()
/obj/item/weapon/cartridge/engineering
name = "\improper Power-ON cartridge"
icon_state = "cart-e"
access_engine = 1
bot_access_flags = FLOOR_BOT
/obj/item/weapon/cartridge/atmos
name = "\improper BreatheDeep cartridge"
icon_state = "cart-a"
access_atmos = 1
bot_access_flags = FLOOR_BOT
/obj/item/weapon/cartridge/medical
name = "\improper Med-U cartridge"
icon_state = "cart-m"
access_medical = 1
bot_access_flags = MED_BOT
/obj/item/weapon/cartridge/chemistry
name = "\improper ChemWhiz cartridge"
icon_state = "cart-chem"
access_reagent_scanner = 1
bot_access_flags = MED_BOT
/obj/item/weapon/cartridge/security
name = "\improper R.O.B.U.S.T. cartridge"
icon_state = "cart-s"
access_security = 1
bot_access_flags = SEC_BOT
/obj/item/weapon/cartridge/detective
name = "\improper D.E.T.E.C.T. cartridge"
icon_state = "cart-s"
access_security = 1
access_medical = 1
access_manifest = 1
bot_access_flags = SEC_BOT
/obj/item/weapon/cartridge/janitor
name = "\improper CustodiPRO cartridge"
desc = "The ultimate in clean-room design."
icon_state = "cart-j"
access_janitor = 1
bot_access_flags = CLEAN_BOT
/obj/item/weapon/cartridge/lawyer
name = "\improper P.R.O.V.E. cartridge"
icon_state = "cart-s"
access_security = 1
spam_enabled = 1
/obj/item/weapon/cartridge/clown
name = "\improper Honkworks 5.0 cartridge"
icon_state = "cart-clown"
access_clown = 1
var/honk_charges = 5
/obj/item/weapon/cartridge/mime
name = "\improper Gestur-O 1000 cartridge"
icon_state = "cart-mi"
access_mime = 1
var/mime_charges = 5
/obj/item/weapon/cartridge/librarian
name = "\improper Lib-Tweet cartridge"
icon_state = "cart-s"
access_newscaster = 1
/*
/obj/item/weapon/cartridge/botanist
name = "\improper Green Thumb v4.20 cartridge"
icon_state = "cart-b"
access_flora = 1
*/
/obj/item/weapon/cartridge/roboticist
name = "\improper B.O.O.P. Remote Control cartridge"
desc = "Packed with heavy duty triple-bot interlink!"
bot_access_flags = FLOOR_BOT|CLEAN_BOT|MED_BOT
/obj/item/weapon/cartridge/signal
name = "generic signaler cartridge"
desc = "A data cartridge with an integrated radio signaler module."
/obj/item/weapon/cartridge/signal/toxins
name = "\improper Signal Ace 2 cartridge"
desc = "Complete with integrated radio signaler!"
icon_state = "cart-tox"
access_reagent_scanner = 1
access_atmos = 1
/obj/item/weapon/cartridge/signal/New()
..()
radio = new /obj/item/radio/integrated/signal(src)
/obj/item/weapon/cartridge/quartermaster
name = "space parts & space vendors cartridge"
desc = "Perfect for the Quartermaster on the go!"
icon_state = "cart-q"
access_quartermaster = 1
bot_access_flags = MULE_BOT
/obj/item/weapon/cartridge/head
name = "\improper Easy-Record DELUXE cartridge"
icon_state = "cart-h"
access_manifest = 1
access_status_display = 1
/obj/item/weapon/cartridge/hop
name = "\improper HumanResources9001 cartridge"
icon_state = "cart-h"
access_manifest = 1
access_status_display = 1
bot_access_flags = MULE_BOT|CLEAN_BOT
access_janitor = 1
access_security = 1
access_newscaster = 1
access_quartermaster = 1
/obj/item/weapon/cartridge/hos
name = "\improper R.O.B.U.S.T. DELUXE cartridge"
icon_state = "cart-hos"
access_manifest = 1
access_status_display = 1
access_security = 1
bot_access_flags = SEC_BOT
/obj/item/weapon/cartridge/ce
name = "\improper Power-On DELUXE cartridge"
icon_state = "cart-ce"
access_manifest = 1
access_status_display = 1
access_engine = 1
access_atmos = 1
bot_access_flags = FLOOR_BOT
/obj/item/weapon/cartridge/cmo
name = "\improper Med-U DELUXE cartridge"
icon_state = "cart-cmo"
access_manifest = 1
access_status_display = 1
access_reagent_scanner = 1
access_medical = 1
bot_access_flags = MED_BOT
/obj/item/weapon/cartridge/rd
name = "\improper Signal Ace DELUXE cartridge"
icon_state = "cart-rd"
access_manifest = 1
access_status_display = 1
access_reagent_scanner = 1
access_atmos = 1
bot_access_flags = FLOOR_BOT|CLEAN_BOT|MED_BOT
/obj/item/weapon/cartridge/rd/New()
..()
radio = new /obj/item/radio/integrated/signal(src)
/obj/item/weapon/cartridge/captain
name = "\improper Value-PAK cartridge"
desc = "Now with 350% more value!" //Give the Captain...EVERYTHING! (Except Mime and Clown)
icon_state = "cart-c"
access_manifest = 1
access_engine = 1
access_security = 1
access_medical = 1
access_reagent_scanner = 1
access_status_display = 1
access_atmos = 1
access_newscaster = 1
access_quartermaster = 1
access_janitor = 1
bot_access_flags = SEC_BOT|MULE_BOT|FLOOR_BOT|CLEAN_BOT|MED_BOT
spam_enabled = 1
/obj/item/weapon/cartridge/captain/New()
..()
radio = new /obj/item/radio/integrated/signal(src)
/obj/item/weapon/cartridge/syndicate
name = "\improper Detomatix cartridge"
icon_state = "cart"
access_remote_door = 1
remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing.
var/shock_charges = 4
/obj/item/weapon/cartridge/proc/unlock()
if (!istype(loc, /obj/item/device/pda))
return
generate_menu()
print_to_host(menu)
return
/obj/item/weapon/cartridge/proc/print_to_host(text)
if (!istype(loc, /obj/item/device/pda))
return
var/obj/item/device/pda/P = loc
P.cart = text
for (var/mob/M in viewers(1, loc.loc))
if (M.client && M.machine == loc)
P.attack_self(M)
return
/obj/item/weapon/cartridge/proc/post_status(command, data1, data2)
var/datum/radio_frequency/frequency = SSradio.return_frequency(1435)
if(!frequency) return
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = 1
status_signal.data["command"] = command
switch(command)
if("message")
status_signal.data["msg1"] = data1
status_signal.data["msg2"] = data2
if("alert")
status_signal.data["picture_state"] = data1
frequency.post_signal(src, status_signal)
/obj/item/weapon/cartridge/proc/generate_menu(mob/user)
switch(mode)
if(40) //signaller
var/obj/item/radio/integrated/signal/S = radio
menu = "<h4><img src=pda_signaler.png> Remote Signaling System</h4>"
menu += {"
<a href='byond://?src=\ref[src];choice=Send Signal'>Send Signal</A><BR>
Frequency:
<a href='byond://?src=\ref[src];choice=Signal Frequency;sfreq=-10'>-</a>
<a href='byond://?src=\ref[src];choice=Signal Frequency;sfreq=-2'>-</a>
[format_frequency(S.frequency)]
<a href='byond://?src=\ref[src];choice=Signal Frequency;sfreq=2'>+</a>
<a href='byond://?src=\ref[src];choice=Signal Frequency;sfreq=10'>+</a><br>
<br>
Code:
<a href='byond://?src=\ref[src];choice=Signal Code;scode=-5'>-</a>
<a href='byond://?src=\ref[src];choice=Signal Code;scode=-1'>-</a>
[S.code]
<a href='byond://?src=\ref[src];choice=Signal Code;scode=1'>+</a>
<a href='byond://?src=\ref[src];choice=Signal Code;scode=5'>+</a><br>"}
if (41) //crew manifest
menu = "<h4><img src=pda_notes.png> Crew Manifest</h4>"
menu += "Entries cannot be modified from this terminal.<br><br>"
if(data_core.general)
for (var/datum/data/record/t in sortRecord(data_core.general))
menu += "[t.fields["name"]] - [t.fields["rank"]]<br>"
menu += "<br>"
if (42) //status displays
menu = "<h4><img src=pda_status.png> Station Status Display Interlink</h4>"
menu += "\[ <A HREF='?src=\ref[src];choice=Status;statdisp=blank'>Clear</A> \]<BR>"
menu += "\[ <A HREF='?src=\ref[src];choice=Status;statdisp=shuttle'>Shuttle ETA</A> \]<BR>"
menu += "\[ <A HREF='?src=\ref[src];choice=Status;statdisp=message'>Message</A> \]"
menu += "<ul><li> Line 1: <A HREF='?src=\ref[src];choice=Status;statdisp=setmsg1'>[ message1 ? message1 : "(none)"]</A>"
menu += "<li> Line 2: <A HREF='?src=\ref[src];choice=Status;statdisp=setmsg2'>[ message2 ? message2 : "(none)"]</A></ul><br>"
menu += "\[ Alert: <A HREF='?src=\ref[src];choice=Status;statdisp=alert;alert=default'>None</A> |"
menu += " <A HREF='?src=\ref[src];choice=Status;statdisp=alert;alert=redalert'>Red Alert</A> |"
menu += " <A HREF='?src=\ref[src];choice=Status;statdisp=alert;alert=lockdown'>Lockdown</A> |"
menu += " <A HREF='?src=\ref[src];choice=Status;statdisp=alert;alert=biohazard'>Biohazard</A> \]<BR>"
if (43)
menu = "<h4><img src=pda_power.png> Power Monitors - Please select one</h4><BR>"
powmonitor = null
powermonitors = list()
var/powercount = 0
for(var/obj/machinery/computer/monitor/pMon in machines)
if(!(pMon.stat & (NOPOWER|BROKEN)) )
powercount++
powermonitors += pMon
if(!powercount)
menu += "<span class='danger'>No connection<BR></span>"
else
menu += "<FONT SIZE=-1>"
var/count = 0
for(var/obj/machinery/computer/monitor/pMon in powermonitors)
count++
menu += "<a href='byond://?src=\ref[src];choice=Power Select;target=[count]'>[pMon] </a><BR>"
menu += "</FONT>"
if (433)
menu = "<h4><img src=pda_power.png> Power Monitor </h4><BR>"
if(!powmonitor)
menu += "<span class='danger'>No connection<BR></span>"
else
var/list/L = list()
for(var/obj/machinery/power/terminal/term in powmonitor.attached.powernet.nodes)
if(istype(term.master, /obj/machinery/power/apc))
var/obj/machinery/power/apc/A = term.master
L += A
menu += "<PRE>Total power: [powmonitor.attached.powernet.viewavail] W<BR>Total load: [num2text(powmonitor.attached.powernet.viewload,10)] W<BR>"
menu += "<FONT SIZE=-1>"
if(L.len > 0)
menu += "Area Eqp./Lgt./Env. Load Cell<HR>"
var/list/S = list(" Off","AOff"," On", " AOn")
var/list/chg = list("N","C","F")
for(var/obj/machinery/power/apc/A in L)
menu += copytext(add_tspace(A.area.name, 30), 1, 30)
menu += " [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_lspace(A.lastused_total, 6)] [A.cell ? "[add_lspace(round(A.cell.percent()), 3)]% [chg[A.charging+1]]" : " N/C"]<BR>"
menu += "</FONT></PRE>"
if (44) //medical records //This thing only displays a single screen so it's hard to really get the sub-menu stuff working.
menu = "<h4><img src=pda_medical.png> Medical Record List</h4>"
if(data_core.general)
for(var/datum/data/record/R in sortRecord(data_core.general))
menu += "<a href='byond://?src=\ref[src];choice=Medical Records;target=[R.fields["id"]]'>[R.fields["id"]]: [R.fields["name"]]<br>"
menu += "<br>"
if(441)
menu = "<h4><img src=pda_medical.png> Medical Record</h4>"
if(active1 in data_core.general)
menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]<br>"
menu += "Sex: [active1.fields["sex"]]<br>"
menu += "Age: [active1.fields["age"]]<br>"
menu += "Rank: [active1.fields["rank"]]<br>"
menu += "Fingerprint: [active1.fields["fingerprint"]]<br>"
menu += "Physical Status: [active1.fields["p_stat"]]<br>"
menu += "Mental Status: [active1.fields["m_stat"]]<br>"
else
menu += "<b>Record Lost!</b><br>"
menu += "<br>"
menu += "<h4><img src=pda_medical.png> Medical Data</h4>"
if(active2 in data_core.medical)
menu += "Blood Type: [active2.fields["blood_type"]]<br><br>"
menu += "Minor Disabilities: [active2.fields["mi_dis"]]<br>"
menu += "Details: [active2.fields["mi_dis_d"]]<br><br>"
menu += "Major Disabilities: [active2.fields["ma_dis"]]<br>"
menu += "Details: [active2.fields["ma_dis_d"]]<br><br>"
menu += "Allergies: [active2.fields["alg"]]<br>"
menu += "Details: [active2.fields["alg_d"]]<br><br>"
menu += "Current Diseases: [active2.fields["cdi"]]<br>"
menu += "Details: [active2.fields["cdi_d"]]<br><br>"
menu += "Important Notes: [active2.fields["notes"]]<br>"
else
menu += "<b>Record Lost!</b><br>"
menu += "<br>"
if (45) //security records
menu = "<h4><img src=pda_cuffs.png> Security Record List</h4>"
if(data_core.general)
for (var/datum/data/record/R in sortRecord(data_core.general))
menu += "<a href='byond://?src=\ref[src];choice=Security Records;target=[R.fields["id"]]'>[R.fields["id"]]: [R.fields["name"]]<br>"
menu += "<br>"
if(451)
menu = "<h4><img src=pda_cuffs.png> Security Record</h4>"
if(active1 in data_core.general)
menu += "Name: [active1.fields["name"]] ID: [active1.fields["id"]]<br>"
menu += "Sex: [active1.fields["sex"]]<br>"
menu += "Age: [active1.fields["age"]]<br>"
menu += "Rank: [active1.fields["rank"]]<br>"
menu += "Fingerprint: [active1.fields["fingerprint"]]<br>"
menu += "Physical Status: [active1.fields["p_stat"]]<br>"
menu += "Mental Status: [active1.fields["m_stat"]]<br>"
else
menu += "<b>Record Lost!</b><br>"
menu += "<br>"
menu += "<h4><img src=pda_cuffs.png> Security Data</h4>"
if(active3 in data_core.security)
menu += "Criminal Status: [active3.fields["criminal"]]<br>"
menu += text("<BR>\nMinor Crimes:")
menu +={"<table style="text-align:center;" border="1" cellspacing="0" width="100%">
<tr>
<th>Crime</th>
<th>Details</th>
<th>Author</th>
<th>Time Added</th>
</tr>"}
for(var/datum/data/crime/c in active3.fields["mi_crim"])
menu += "<tr><td>[c.crimeName]</td>"
menu += "<td>[c.crimeDetails]</td>"
menu += "<td>[c.author]</td>"
menu += "<td>[c.time]</td>"
menu += "</tr>"
menu += "</table>"
menu += text("<BR>\nMajor Crimes:")
menu +={"<table style="text-align:center;" border="1" cellspacing="0" width="100%">
<tr>
<th>Crime</th>
<th>Details</th>
<th>Author</th>
<th>Time Added</th>
</tr>"}
for(var/datum/data/crime/c in active3.fields["ma_crim"])
menu += "<tr><td>[c.crimeName]</td>"
menu += "<td>[c.crimeDetails]</td>"
menu += "<td>[c.author]</td>"
menu += "<td>[c.time]</td>"
menu += "</tr>"
menu += "</table>"
menu += "<BR>\nImportant Notes:<br>"
menu += "[active3.fields["notes"]]"
else
menu += "<b>Record Lost!</b><br>"
menu += "<br>"
if (47) //quartermaster order records
menu = "<h4><img src=pda_crate.png> Supply Record Interlink</h4>"
menu += "<BR><B>Supply shuttle</B><BR>"
menu += "Location: "
switch(SSshuttle.supply.mode)
if(SHUTTLE_CALL)
menu += "Moving to "
if(SSshuttle.supply.z != ZLEVEL_STATION)
menu += "station"
else
menu += "centcomm"
menu += " ([SSshuttle.supply.timeLeft(600)] Mins)"
else
menu += "At "
if(SSshuttle.supply.z != ZLEVEL_STATION)
menu += "centcomm"
else
menu += "station"
menu += "<BR>Current approved orders: <BR><ol>"
for(var/S in SSshuttle.shoppinglist)
var/datum/supply_order/SO = S
menu += "<li>#[SO.id] - [SO.pack.name] approved by [SO.orderer] [SO.reason ? "([SO.reason])":""]</li>"
menu += "</ol>"
menu += "Current requests: <BR><ol>"
for(var/S in SSshuttle.requestlist)
var/datum/supply_order/SO = S
menu += "<li>#[SO.id] - [SO.pack.name] requested by [SO.orderer]</li>"
menu += "</ol><font size=\"-3\">Upgrade NOW to Space Parts & Space Vendors PLUS for full remote order control and inventory management."
if (49) //janitorial locator
menu = "<h4><img src=pda_bucket.png> Persistent Custodial Object Locator</h4>"
var/turf/cl = get_turf(src)
if (cl)
menu += "Current Orbital Location: <b>\[[cl.x],[cl.y]\]</b>"
menu += "<h4>Located Mops:</h4>"
var/ldat
for (var/obj/item/weapon/mop/M in world)
var/turf/ml = get_turf(M)
if(ml)
if (ml.z != cl.z)
continue
var/direction = get_dir(src, M)
ldat += "Mop - <b>\[[ml.x],[ml.y] ([uppertext(dir2text(direction))])\]</b> - [M.reagents.total_volume ? "Wet" : "Dry"]<br>"
if (!ldat)
menu += "None"
else
menu += "[ldat]"
menu += "<h4>Located Janitorial Cart:</h4>"
ldat = null
for (var/obj/structure/janitorialcart/B in world)
var/turf/bl = get_turf(B)
if(bl)
if (bl.z != cl.z)
continue
var/direction = get_dir(src, B)
ldat += "Cart - <b>\[[bl.x],[bl.y] ([uppertext(dir2text(direction))])\]</b> - Water level: [B.reagents.total_volume]/100<br>"
if (!ldat)
menu += "None"
else
menu += "[ldat]"
menu += "<h4>Located Cleanbots:</h4>"
ldat = null
for (var/mob/living/simple_animal/bot/cleanbot/B in living_mob_list)
var/turf/bl = get_turf(B)
if(bl)
if (bl.z != cl.z)
continue
var/direction = get_dir(src, B)
ldat += "Cleanbot - <b>\[[bl.x],[bl.y] ([uppertext(dir2text(direction))])\]</b> - [B.on ? "Online" : "Offline"]<br>"
if (!ldat)
menu += "None"
else
menu += "[ldat]"
else
menu += "ERROR: Unable to determine current location."
menu += "<br><br><A href='byond://?src=\ref[src];choice=49'>Refresh GPS Locator</a>"
if (53) // Newscaster
menu = "<h4><img src=pda_notes.png> Newscaster Access</h4>"
menu += "<br> Current Newsfeed: <A href='byond://?src=\ref[src];choice=Newscaster Switch Channel'>[current_channel ? current_channel : "None"]</a> <br>"
var/datum/newscaster/feed_channel/current
for(var/datum/newscaster/feed_channel/chan in news_network.network_channels)
if (chan.channel_name == current_channel)
current = chan
if(!current)
menu += "<h5> ERROR : NO CHANNEL FOUND </h5>"
return
var/i = 1
for(var/datum/newscaster/feed_message/msg in current.messages)
menu +="-[msg.returnBody(-1)] <BR><FONT SIZE=1>\[Story by <FONT COLOR='maroon'>[msg.returnAuthor(-1)]</FONT>\]</FONT><BR>"
menu +="<b><font size=1>[msg.comments.len] comment[msg.comments.len > 1 ? "s" : ""]</font></b><br>"
if(msg.img)
user << browse_rsc(msg.img, "tmp_photo[i].png")
menu +="<img src='tmp_photo[i].png' width = '180'><BR>"
i++
for(var/datum/newscaster/feed_comment/comment in msg.comments)
menu +="<font size=1><small>[comment.body]</font><br><font size=1><small><small><small>[comment.author] [comment.time_stamp]</small></small></small></small></font><br>"
menu += "<br> <A href='byond://?src=\ref[src];choice=Newscaster Message'>Post Message</a>"
if (54) // Beepsky, Medibot, Floorbot, and Cleanbot access
menu = "<h4><img src=pda_medbot.png> Bots Interlink</h4>"
bot_control()
/obj/item/weapon/cartridge/Topic(href, href_list)
..()
if (!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
usr.unset_machine()
usr << browse(null, "window=pda")
return
var/obj/item/device/pda/pda = loc
switch(href_list["choice"])
if("Medical Records")
active1 = find_record("id", href_list["target"], data_core.general)
if(active1)
active2 = find_record("id", href_list["target"], data_core.medical)
pda.mode = 441
mode = 441
if(!active2)
active1 = null
if("Security Records")
active1 = find_record("id", href_list["target"], data_core.general)
if(active1)
active3 = find_record("id", href_list["target"], data_core.security)
pda.mode = 451
mode = 451
if(!active3)
active1 = null
if("Send Signal")
spawn( 0 )
var/obj/item/radio/integrated/signal/S = radio
S.send_signal("ACTIVATE")
return
if("Signal Frequency")
var/obj/item/radio/integrated/signal/S = radio
var/new_frequency = sanitize_frequency(S.frequency + text2num(href_list["sfreq"]))
S.set_frequency(new_frequency)
if("Signal Code")
var/obj/item/radio/integrated/signal/S = radio
S.code += text2num(href_list["scode"])
S.code = round(S.code)
S.code = min(100, S.code)
S.code = max(1, S.code)
if("Status")
switch(href_list["statdisp"])
if("message")
post_status("message", message1, message2)
if("alert")
post_status("alert", href_list["alert"])
if("setmsg1")
message1 = reject_bad_text(input("Line 1", "Enter Message Text", message1) as text|null, 40)
updateSelfDialog()
if("setmsg2")
message2 = reject_bad_text(input("Line 2", "Enter Message Text", message2) as text|null, 40)
updateSelfDialog()
else
post_status(href_list["statdisp"])
if("Power Select")
var/pnum = text2num(href_list["target"])
powmonitor = powermonitors[pnum]
pda.mode = 433
mode = 433
if("Supply Orders")
pda.mode =47
mode = 47
if("Newscaster Access")
mode = 53
if("Newscaster Message")
var/pda_owner_name = pda.id ? "[pda.id.registered_name] ([pda.id.assignment])" : "Unknown"
var/message = pda.msg_input()
var/datum/newscaster/feed_channel/current
for(var/datum/newscaster/feed_channel/chan in news_network.network_channels)
if (chan.channel_name == current_channel)
current = chan
if(current.locked && current.author != pda_owner_name)
pda.cart += "<h5> ERROR : NOT AUTHORIZED [pda.id ? "" : "- ID SLOT EMPTY"] </h5>"
pda.Topic(null,list("choice"="Refresh"))
return
news_network.SubmitArticle(message,pda.owner,current_channel)
pda.Topic(null,list("choice"=num2text(mode)))
return
if("Newscaster Switch Channel")
current_channel = pda.msg_input()
pda.Topic(null,list("choice"=num2text(mode)))
return
//Bot control section! Viciously ripped from radios for being laggy and terrible.
if(href_list["op"])
switch(href_list["op"])
if("control")
active_bot = locate(href_list["bot"])
if("botlist")
active_bot = null
if("summon") //Args are in the correct order, they are stated here just as an easy reminder.
active_bot.bot_control(command= "summon", user_turf= get_turf(usr), user_access= pda.GetAccess())
else //Forward all other bot commands to the bot itself!
active_bot.bot_control(command= href_list["op"], user= usr)
if(href_list["mule"]) //MULEbots are special snowflakes, and need different args due to how they work.
active_bot.bot_control(command= href_list["mule"], user= usr, pda= 1)
generate_menu(usr)
print_to_host(menu)
/obj/item/weapon/cartridge/proc/bot_control()
var/mob/living/simple_animal/bot/Bot
// if(!SC)
// menu = "Interlink Error - Please reinsert cartridge."
// return
if(active_bot)
menu += "<B>[active_bot]</B><BR> Status: (<A href='byond://?src=\ref[src];op=control;bot=\ref[active_bot]'><img src=pda_refresh.png><i>refresh</i></A>)<BR>"
menu += "Model: [active_bot.model]<BR>"
menu += "Location: [get_area(active_bot)]<BR>"
menu += "Mode: [active_bot.get_mode()]"
if(active_bot.allow_pai)
menu += "<BR>pAI: "
if(active_bot.paicard && active_bot.paicard.pai)
menu += "[active_bot.paicard.pai.name]"
if(active_bot.bot_core.allowed(usr))
menu += " (<A href='byond://?src=\ref[src];op=ejectpai'><i>eject</i></A>)"
else
menu += "<i>none</i>"
//MULEs!
if(active_bot.bot_type == MULE_BOT)
var/mob/living/simple_animal/bot/mulebot/MULE = active_bot
var/atom/Load = MULE.load
menu += "<BR>Current Load: [ !Load ? "<i>none</i>" : "[Load.name] (<A href='byond://?src=\ref[src];mule=unload'><i>unload</i></A>)" ]<BR>"
menu += "Destination: [MULE.destination ? MULE.destination : "<i>None</i>"] (<A href='byond://?src=\ref[src];mule=destination'><i>set</i></A>)<BR>"
menu += "Set ID: [MULE.suffix] <A href='byond://?src=\ref[src];mule=setid'><i> Modify</i></A><BR>"
menu += "Power: [MULE.cell ? MULE.cell.percent() : 0]%<BR>"
menu += "Home: [!MULE.home_destination ? "<i>none</i>" : MULE.home_destination ]<BR>"
menu += "Delivery Reporting: <A href='byond://?src=\ref[src];mule=report'>[MULE.report_delivery ? "(<B>On</B>)": "(<B>Off</B>)"]</A><BR>"
menu += "Auto Return Home: <A href='byond://?src=\ref[src];mule=autoret'>[MULE.auto_return ? "(<B>On</B>)": "(<B>Off</B>)"]</A><BR>"
menu += "Auto Pickup Crate: <A href='byond://?src=\ref[src];mule=autopick'>[MULE.auto_pickup ? "(<B>On</B>)": "(<B>Off</B>)"]</A><BR><BR>" //Hue.
menu += "\[<A href='byond://?src=\ref[src];mule=stop'>Stop</A>\] "
menu += "\[<A href='byond://?src=\ref[src];mule=go'>Proceed</A>\] "
menu += "\[<A href='byond://?src=\ref[src];mule=home'>Return Home</A>\]<BR>"
else
menu += "<BR>\[<A href='byond://?src=\ref[src];op=patroloff'>Stop Patrol</A>\] " //patrolon
menu += "\[<A href='byond://?src=\ref[src];op=patrolon'>Start Patrol</A>\] " //patroloff
menu += "\[<A href='byond://?src=\ref[src];op=summon'>Summon Bot</A>\]<BR>" //summon
menu += "Keep an ID inserted to upload access codes upon summoning."
menu += "<HR><A href='byond://?src=\ref[src];op=botlist'><img src=pda_back.png>Return to bot list</A>"
else
menu += "<BR><A href='byond://?src=\ref[src];op=botlist'><img src=pda_refresh.png>Scan for active bots</A><BR><BR>"
var/turf/current_turf = get_turf(src)
var/zlevel = current_turf.z
var/botcount = 0
for(Bot in living_mob_list) //Git da botz
if(!Bot.on || Bot.z != zlevel || Bot.remote_disabled || !(bot_access_flags & Bot.bot_type)) //Only non-emagged bots on the same Z-level are detected!
continue //Also, the PDA must have access to the bot type.
menu += "<A href='byond://?src=\ref[src];op=control;bot=\ref[Bot]'><b>[Bot.name]</b> ([Bot.get_mode()])<BR>"
botcount++
if(!botcount) //No bots at all? Lame.
menu += "No bots found.<BR>"
return
return menu
@@ -0,0 +1,70 @@
/obj/item/radio/integrated
name = "\improper PDA radio module"
desc = "An electronic radio system of nanotrasen origin."
icon = 'icons/obj/module.dmi'
icon_state = "power_mod"
var/obj/item/device/pda/hostpda = null
var/on = 0 //Are we currently active??
var/menu_message = ""
/obj/item/radio/integrated/New()
..()
if (istype(loc.loc, /obj/item/device/pda))
hostpda = loc.loc
/obj/item/radio/integrated/Destroy()
hostpda = null
return ..()
/*
* Radio Cartridge, essentially a signaler.
*/
/obj/item/radio/integrated/signal
var/frequency = 1457
var/code = 30
var/last_transmission
var/datum/radio_frequency/radio_connection
/obj/item/radio/integrated/signal/New()
..()
if(SSradio)
initialize()
/obj/item/radio/integrated/signal/Destroy()
if(SSradio)
SSradio.remove_object(src, frequency)
radio_connection = null
return ..()
/obj/item/radio/integrated/signal/initialize()
if (src.frequency < 1200 || src.frequency > 1600)
src.frequency = sanitize_frequency(src.frequency)
set_frequency(frequency)
/obj/item/radio/integrated/signal/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
radio_connection = SSradio.add_object(src, frequency)
/obj/item/radio/integrated/signal/proc/send_signal(message="ACTIVATE")
if(last_transmission && world.time < (last_transmission + 5))
return
last_transmission = world.time
var/time = time2text(world.realtime,"hh:mm:ss")
var/turf/T = get_turf(src)
lastsignalers.Add("[time] <B>:</B> [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(frequency)]/[code]")
var/datum/signal/signal = new
signal.source = src
signal.encryption = code
signal.data["message"] = message
radio_connection.post_signal(src, signal)
return
+85
View File
@@ -0,0 +1,85 @@
/obj/item/device/aicard
name = "intelliCard"
desc = "A storage device for AIs. Patent pending."
icon = 'icons/obj/aicards.dmi'
icon_state = "aicard" // aicard-full
item_state = "electronic"
w_class = 2
slot_flags = SLOT_BELT
flags = NOBLUDGEON
var/flush = FALSE
var/mob/living/silicon/ai/AI
origin_tech = "programming=3;materials=3"
/obj/item/device/aicard/afterattack(atom/target, mob/user, proximity)
..()
if(!proximity || !target)
return
if(AI) //AI is on the card, implies user wants to upload it.
target.transfer_ai(AI_TRANS_FROM_CARD, user, AI, src)
add_logs(user, AI, "carded", src)
else //No AI on the card, therefore the user wants to download one.
target.transfer_ai(AI_TRANS_TO_CARD, user, null, src)
update_icon() //Whatever happened, update the card's state (icon, name) to match.
/obj/item/device/aicard/update_icon()
if(AI)
name = "[initial(name)]- [AI.name]"
if(AI.stat == DEAD)
icon_state = "aicard-404"
else
icon_state = "aicard-full"
if(!AI.control_disabled)
add_overlay(image('icons/obj/aicards.dmi', "aicard-on"))
AI.cancel_camera()
else
name = initial(name)
icon_state = initial(icon_state)
cut_overlays()
/obj/item/device/aicard/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "intellicard", name, 500, 500, master_ui, state)
ui.open()
/obj/item/device/aicard/ui_data()
var/list/data = list()
if(AI)
data["name"] = AI.name
data["laws"] = AI.laws.get_law_list(include_zeroth = 1)
data["health"] = (AI.health + 100) / 2
data["wireless"] = !AI.control_disabled //todo disabled->enabled
data["radio"] = AI.radio_enabled
data["isDead"] = AI.stat == DEAD
data["isBraindead"] = AI.client ? TRUE : FALSE
data["wiping"] = flush
return data
/obj/item/device/aicard/ui_act(action,params)
if(..())
return
switch(action)
if("wipe")
var/confirm = alert("Are you sure you want to wipe this card's memory? This cannot be undone once started.", name, "Yes", "No")
if(confirm == "Yes" && !..())
flush = TRUE
if(AI && AI.loc == src)
AI.suiciding = TRUE
AI << "Your core files are being wiped!"
while(AI.stat != DEAD)
AI.adjustOxyLoss(2)
AI.updatehealth()
sleep(10)
flush = FALSE
. = TRUE
if("wireless")
AI.control_disabled = !AI.control_disabled
AI << "[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!"
. = TRUE
if("radio")
AI.radio_enabled = !AI.radio_enabled
AI << "Your Subspace Transceiver has been [AI.radio_enabled ? "enabled" : "disabled"]!"
. = TRUE
update_icon()
@@ -0,0 +1,282 @@
#define BUGMODE_LIST 0
#define BUGMODE_MONITOR 1
#define BUGMODE_TRACK 2
/obj/item/device/camera_bug
name = "camera bug"
desc = "For illicit snooping through the camera network."
icon = 'icons/obj/device.dmi'
icon_state = "camera_bug"
w_class = 1
item_state = "camera_bug"
throw_speed = 4
throw_range = 20
origin_tech = "syndicate=1;engineering=3"
flags = NOBLUDGEON
var/obj/machinery/camera/current = null
var/last_net_update = 0
var/list/bugged_cameras = list()
var/track_mode = BUGMODE_LIST
var/last_tracked = 0
var/refresh_interval = 50
var/tracked_name = null
var/atom/tracking = null
var/last_found = null
var/last_seen = null
/obj/item/device/camera_bug/New()
..()
START_PROCESSING(SSobj, src)
/obj/item/device/camera_bug/Destroy()
get_cameras()
for(var/cam_tag in bugged_cameras)
var/obj/machinery/camera/camera = bugged_cameras[cam_tag]
if(camera.bug == src)
camera.bug = null
bugged_cameras = list()
if(tracking)
tracking = null
return ..()
/obj/item/device/camera_bug/interact(mob/user = usr)
var/datum/browser/popup = new(user, "camerabug","Camera Bug",nref=src)
popup.set_content(menu(get_cameras()))
popup.open()
/obj/item/device/camera_bug/attack_self(mob/user)
user.set_machine(src)
interact(user)
/obj/item/device/camera_bug/check_eye(mob/user)
if ( loc != user || user.incapacitated() || user.eye_blind || !current )
user.unset_machine()
return
var/turf/T = get_turf(user.loc)
if(T.z != current.z || !current.can_use())
user << "<span class='danger'>[src] has lost the signal.</span>"
current = null
user.unset_machine()
/obj/item/device/camera_bug/on_unset_machine(mob/user)
user.reset_perspective(null)
/obj/item/device/camera_bug/proc/get_cameras()
if( world.time > (last_net_update + 100))
bugged_cameras = list()
for(var/obj/machinery/camera/camera in cameranet.cameras)
if(camera.stat || !camera.can_use())
continue
if(length(list("SS13","MINE")&camera.network))
bugged_cameras[camera.c_tag] = camera
sortList(bugged_cameras)
return bugged_cameras
/obj/item/device/camera_bug/proc/menu(list/cameras)
if(!cameras || !cameras.len)
return "No bugged cameras found."
var/html
switch(track_mode)
if(BUGMODE_LIST)
html = "<h3>Select a camera:</h3> <a href='?src=\ref[src];view'>\[Cancel camera view\]</a><hr><table>"
for(var/entry in cameras)
var/obj/machinery/camera/C = cameras[entry]
var/functions = ""
if(C.bug == src)
functions = " - <a href='?src=\ref[src];monitor=\ref[C]'>\[Monitor\]</a> <a href='?src=\ref[src];emp=\ref[C]'>\[Disable\]</a>"
else
functions = " - <a href='?src=\ref[src];monitor=\ref[C]'>\[Monitor\]</a>"
html += "<tr><td><a href='?src=\ref[src];view=\ref[C]'>[entry]</a></td><td>[functions]</td></tr>"
if(BUGMODE_MONITOR)
if(current)
html = "Analyzing Camera '[current.c_tag]' <a href='?\ref[src];mode=0'>\[Select Camera\]</a><br>"
html += camera_report()
else
track_mode = BUGMODE_LIST
return .(cameras)
if(BUGMODE_TRACK)
if(tracking)
html = "Tracking '[tracked_name]' <a href='?\ref[src];mode=0'>\[Cancel Tracking\]</a> <a href='?src=\ref[src];view'>\[Cancel camera view\]</a><br>"
if(last_found)
var/time_diff = round((world.time - last_seen) / 150)
var/obj/machinery/camera/C = bugged_cameras[last_found]
var/outstring
if(C)
outstring = "<a href='?\ref[src];view=\ref[C]'>[last_found]</a>"
else
outstring = last_found
if(!time_diff)
html += "Last seen near [outstring] (now)<br>"
else
// 15 second intervals ~ 1/4 minute
var/m = round(time_diff/4)
var/s = (time_diff - 4*m) * 15
if(!s) s = "00"
html += "Last seen near [outstring] ([m]:[s] minute\s ago)<br>"
if( C && (C.bug == src)) //Checks to see if the camera has a bug
html += "<a href='?src=\ref[src];emp=\ref[C]'>\[Disable\]</a>"
else
html += "Not yet seen."
else
track_mode = BUGMODE_LIST
return .(cameras)
return html
/obj/item/device/camera_bug/proc/camera_report()
// this should only be called if current exists
var/dat = ""
if(current && current.can_use())
var/list/seen = current.can_see()
var/list/names = list()
for(var/obj/singularity/S in seen) // god help you if you see more than one
if(S.name in names)
names[S.name]++
dat += "[S.name] ([names[S.name]])"
else
names[S.name] = 1
dat += "[S.name]"
var/stage = round(S.current_size / 2)+1
dat += " (Stage [stage])"
dat += " <a href='?\ref[src];track=\ref[S]'>\[Track\]</a><br>"
for(var/obj/mecha/M in seen)
if(M.name in names)
names[M.name]++
dat += "[M.name] ([names[M.name]])"
else
names[M.name] = 1
dat += "[M.name]"
dat += " <a href='?\ref[src];track=\ref[M]'>\[Track\]</a><br>"
for(var/mob/living/M in seen)
if(M.name in names)
names[M.name]++
dat += "[M.name] ([names[M.name]])"
else
names[M.name] = 1
dat += "[M.name]"
if(M.buckled && !M.lying)
dat += " (Sitting)"
if(M.lying)
dat += " (Laying down)"
dat += " <a href='?\ref[src];track=\ref[M]'>\[Track\]</a><br>"
if(length(dat) == 0)
dat += "No motion detected."
return dat
else
return "Camera Offline<br>"
/obj/item/device/camera_bug/Topic(href,list/href_list)
if(usr != loc)
usr.unset_machine()
usr << browse(null, "window=camerabug")
return
usr.set_machine(src)
if("mode" in href_list)
track_mode = text2num(href_list["mode"])
if("monitor" in href_list)
var/obj/machinery/camera/C = locate(href_list["monitor"])
if(C)
track_mode = BUGMODE_MONITOR
current = C
usr.reset_perspective(null)
interact()
if("track" in href_list)
var/atom/A = locate(href_list["track"])
if(A)
tracking = A
tracked_name = A.name
last_found = current.c_tag
last_seen = world.time
track_mode = BUGMODE_TRACK
if("emp" in href_list)
var/obj/machinery/camera/C = locate(href_list["emp"])
if(istype(C) && C.bug == src)
C.emp_act(1)
C.bug = null
bugged_cameras -= C.c_tag
interact()
return
if("close" in href_list)
usr.unset_machine()
current = null
return
if("view" in href_list)
var/obj/machinery/camera/C = locate(href_list["view"])
if(istype(C))
if(!C.can_use())
usr << "<span class='warning'>Something's wrong with that camera! You can't get a feed.</span>"
return
var/turf/T = get_turf(loc)
if(!T || C.z != T.z)
usr << "<span class='warning'>You can't get a signal!</span>"
return
current = C
spawn(6)
if(src.check_eye(usr))
usr.reset_perspective(C)
interact()
else
usr.unset_machine()
usr << browse(null, "window=camerabug")
return
else
usr.unset_machine()
interact()
/obj/item/device/camera_bug/process()
if(track_mode == BUGMODE_LIST || (world.time < (last_tracked + refresh_interval)))
return
last_tracked = world.time
if(track_mode == BUGMODE_TRACK ) // search for user
// Note that it will be tricked if your name appears to change.
// This is not optimal but it is better than tracking you relentlessly despite everything.
if(!tracking)
src.updateSelfDialog()
return
if(tracking.name != tracked_name) // Hiding their identity, tricksy
var/mob/M = tracking
if(istype(M))
if(!(tracked_name == "Unknown" && findtext(tracking.name,"Unknown"))) // we saw then disguised before
if(!(tracked_name == M.real_name && findtext(tracking.name,M.real_name))) // or they're still ID'd
src.updateSelfDialog()//But if it's neither of those cases
return // you won't find em on the cameras
else
src.updateSelfDialog()
return
var/list/tracking_cams = list()
var/list/b_cams = get_cameras()
for(var/entry in b_cams)
tracking_cams += b_cams[entry]
var/list/target_region = view(tracking)
for(var/obj/machinery/camera/C in (target_region & tracking_cams))
if(!can_see(C,tracking)) // target may have xray, that doesn't make them visible to cameras
continue
if(C.can_use())
last_found = C.c_tag
last_seen = world.time
break
src.updateSelfDialog()
#undef BUGMODE_LIST
#undef BUGMODE_MONITOR
#undef BUGMODE_TRACK
@@ -0,0 +1,138 @@
/obj/item/device/chameleon
name = "chameleon-projector"
icon_state = "shield0"
flags = CONDUCT | NOBLUDGEON
slot_flags = SLOT_BELT
item_state = "electronic"
throwforce = 5
throw_speed = 3
throw_range = 5
w_class = 2
origin_tech = "syndicate=4;magnets=4"
var/can_use = 1
var/obj/effect/dummy/chameleon/active_dummy = null
var/saved_appearance = null
/obj/item/device/chameleon/New()
..()
var/obj/item/weapon/cigbutt/butt = /obj/item/weapon/cigbutt
saved_appearance = initial(butt.appearance)
/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(get_turf(src), 'sound/weapons/flash.ogg', 100, 1, -6)
user << "<span class='notice'>Scanned [target].</span>"
var/obj/temp = new/obj()
temp.appearance = target.appearance
temp.layer = initial(target.layer) // scanning things in your inventory
saved_appearance = temp.appearance
/obj/item/device/chameleon/proc/toggle()
if(!can_use || !saved_appearance) return
if(active_dummy)
eject_all()
playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6)
qdel(active_dummy)
active_dummy = null
usr << "<span class='notice'>You deactivate \the [src].</span>"
PoolOrNew(/obj/effect/overlay/temp/emp/pulse, get_turf(src))
else
playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6)
var/obj/effect/dummy/chameleon/C = new/obj/effect/dummy/chameleon(usr.loc)
C.activate(usr, saved_appearance, src)
usr << "<span class='notice'>You activate \the [src].</span>"
PoolOrNew(/obj/effect/overlay/temp/emp/pulse, get_turf(src))
/obj/item/device/chameleon/proc/disrupt(delete_dummy = 1)
if(active_dummy)
for(var/mob/M in active_dummy)
M << "<span class='danger'>Your chameleon-projector deactivates.</span>"
var/datum/effect_system/spark_spread/spark_system = new /datum/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_perspective(null)
/obj/effect/dummy/chameleon
name = ""
desc = ""
density = 0
var/can_move = 1
var/obj/item/device/chameleon/master = null
/obj/effect/dummy/chameleon/proc/activate(mob/M, saved_appearance, obj/item/device/chameleon/C)
appearance = saved_appearance
M.loc = src
master = C
master.active_dummy = src
/obj/effect/dummy/chameleon/attackby()
master.disrupt()
/obj/effect/dummy/chameleon/attack_hand()
master.disrupt()
/obj/effect/dummy/chameleon/attack_animal()
master.disrupt()
/obj/effect/dummy/chameleon/attack_slime()
master.disrupt()
/obj/effect/dummy/chameleon/attack_alien()
master.disrupt()
/obj/effect/dummy/chameleon/ex_act(S, T)
contents_explosion(S, T)
master.disrupt()
/obj/effect/dummy/chameleon/bullet_act()
..()
master.disrupt()
/obj/effect/dummy/chameleon/relaymove(mob/user, direction)
if(istype(loc, /turf/open/space) || !direction)
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)
return ..()
@@ -0,0 +1,33 @@
/obj/item/device/doorCharge
name = "airlock charge"
desc = null //Different examine for traitors
item_state = "electronic"
icon_state = "doorCharge"
w_class = 2
throw_range = 4
throw_speed = 1
flags = NOBLUDGEON
force = 3
attack_verb = list("blown up", "exploded", "detonated")
materials = list(MAT_METAL=50, MAT_GLASS=30)
origin_tech = "syndicate=1;combat=3;engineering=3"
/obj/item/device/doorCharge/ex_act(severity, target)
switch(severity)
if(1)
visible_message("<span class='warning'>[src] detonates!</span>")
explosion(src.loc,0,2,1,flame_range = 4)
qdel(src)
if(2)
if(prob(50))
ex_act(1)
if(3)
if(prob(25))
ex_act(1)
/obj/item/device/doorCharge/examine(mob/user)
..()
if(user.mind in ticker.mode.traitors) //No nuke ops because the device is excluded from nuclear
user << "A small explosive device that can be used to sabotage airlocks to cause an explosion upon opening. To apply, remove the airlock's maintenance panel and place it within."
else
user << "A small, suspicious object that feels lukewarm when held."
@@ -0,0 +1,324 @@
/obj/item/device/flashlight
name = "flashlight"
desc = "A hand-held emergency light."
icon = 'icons/obj/lighting.dmi'
icon_state = "flashlight"
item_state = "flashlight"
w_class = 2
flags = CONDUCT
slot_flags = SLOT_BELT
materials = list(MAT_METAL=50, MAT_GLASS=20)
actions_types = list(/datum/action/item_action/toggle_light)
var/on = 0
var/brightness_on = 4 //luminosity when on
/obj/item/device/flashlight/initialize()
..()
if(on)
icon_state = "[initial(icon_state)]-on"
SetLuminosity(brightness_on)
else
icon_state = initial(icon_state)
SetLuminosity(0)
/obj/item/device/flashlight/proc/update_brightness(mob/user = null)
if(on)
icon_state = "[initial(icon_state)]-on"
if(loc == user)
user.AddLuminosity(brightness_on)
else if(isturf(loc))
SetLuminosity(brightness_on)
else
icon_state = initial(icon_state)
if(loc == user)
user.AddLuminosity(-brightness_on)
else if(isturf(loc))
SetLuminosity(0)
/obj/item/device/flashlight/attack_self(mob/user)
if(!isturf(user.loc))
user << "<span class='warning'>You cannot turn the light on while in this [user.loc]!</span>" //To prevent some lighting anomalities.
return 0
on = !on
update_brightness(user)
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
return 1
/obj/item/device/flashlight/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
add_fingerprint(user)
if(on && user.zone_selected == "eyes")
if((user.disabilities & CLUMSY || user.getBrainLoss() >= 60) && prob(50)) //too dumb to use flashlight properly
return ..() //just hit them in the head
if(!user.IsAdvancedToolUser())
user << "<span class='warning'>You don't have the dexterity to do this!</span>"
return
var/mob/living/carbon/human/H = M //mob has protective eyewear
if(istype(M, /mob/living/carbon/human) && ((H.head && H.head.flags_cover & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || (H.glasses && H.glasses.flags_cover & GLASSESCOVERSEYES)))
user << "<span class='notice'>You're going to need to remove that [(H.head && H.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first.</span>"
return
if(M == user) //they're using it on themselves
if(M.flash_eyes(visual = 1))
M.visible_message("[M] directs [src] to \his eyes.", \
"<span class='notice'>You wave the light in front of your eyes! Trippy!</span>")
else
M.visible_message("[M] directs [src] to \his eyes.", \
"<span class='notice'>You wave the light in front of your eyes.</span>")
else
user.visible_message("<span class='warning'>[user] directs [src] to [M]'s eyes.</span>", \
"<span class='danger'>You direct [src] to [M]'s eyes.</span>")
var/mob/living/carbon/C = M
if(istype(C))
if(C.stat == DEAD || (C.disabilities & BLIND)) //mob is dead or fully blind
user << "<span class='warning'>[C] pupils don't react to the light!</span>"
else if(C.dna.check_mutation(XRAY)) //mob has X-RAY vision
user << "<span class='danger'>[C] pupils give an eerie glow!</span>"
else //they're okay!
if(C.flash_eyes(visual = 1))
user << "<span class='notice'>[C]'s pupils narrow.</span>"
else
return ..()
/obj/item/device/flashlight/pickup(mob/user)
..()
if(on)
user.AddLuminosity(brightness_on)
SetLuminosity(0)
/obj/item/device/flashlight/dropped(mob/user)
..()
if(on)
user.AddLuminosity(-brightness_on)
SetLuminosity(brightness_on)
/obj/item/device/flashlight/pen
name = "penlight"
desc = "A pen-sized light, used by medical staff. It can also be used to create a hologram to alert people of incoming medical assistance."
icon_state = "penlight"
item_state = ""
flags = CONDUCT
brightness_on = 2
var/holo_cooldown = 0
/obj/item/device/flashlight/pen/afterattack(atom/target, mob/user, proximity_flag)
if(!proximity_flag)
if(holo_cooldown > world.time)
user << "<span class='warning'>[src] is not ready yet!</span>"
return
var/T = get_turf(target)
if(locate(/mob/living) in T)
PoolOrNew(/obj/effect/overlay/temp/medical_holosign, list(T,user)) //produce a holographic glow
holo_cooldown = world.time + 100
return
..()
/obj/effect/overlay/temp/medical_holosign
name = "medical holosign"
desc = "A small holographic glow that indicates a medic is coming to treat a patient."
icon_state = "medi_holo"
duration = 30
/obj/effect/overlay/temp/medical_holosign/New(loc, creator)
..()
playsound(loc, 'sound/machines/ping.ogg', 50, 0) //make some noise!
if(creator)
visible_message("<span class='danger'>[creator] created a medical hologram!</span>")
/obj/item/device/flashlight/seclite
name = "seclite"
desc = "A robust flashlight used by security."
icon_state = "seclite"
item_state = "seclite"
force = 9 // Not as good as a stun baton.
brightness_on = 5 // A little better than the standard flashlight.
hitsound = 'sound/weapons/genhit1.ogg'
// the desk lamps are a bit special
/obj/item/device/flashlight/lamp
name = "desk lamp"
desc = "A desk lamp with an adjustable mount."
icon_state = "lamp"
item_state = "lamp"
brightness_on = 5
w_class = 4
flags = CONDUCT
materials = list()
on = 1
// green-shaded desk lamp
/obj/item/device/flashlight/lamp/green
desc = "A classic green-shaded desk lamp."
icon_state = "lampgreen"
item_state = "lampgreen"
/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)
//Bananalamp
obj/item/device/flashlight/lamp/bananalamp
name = "banana lamp"
desc = "Only a clown would think to make a ghetto banana-shaped lamp. Even has a goofy pullstring."
icon_state = "bananalamp"
item_state = "bananalamp"
// FLARES
/obj/item/device/flashlight/flare
name = "flare"
desc = "A red Nanotrasen issued flare. There are instructions on the side, it reads 'pull cord, make light'."
w_class = 2
brightness_on = 7 // Pretty bright.
icon_state = "flare"
item_state = "flare"
actions_types = list()
var/fuel = 0
var/on_damage = 7
var/produce_heat = 1500
heat = 1000
/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)
icon_state = "[initial(icon_state)]-empty"
STOP_PROCESSING(SSobj, src)
/obj/item/device/flashlight/flare/proc/turn_off()
on = 0
force = initial(src.force)
damtype = initial(src.damtype)
if(ismob(loc))
var/mob/U = loc
update_brightness(U)
else
update_brightness(null)
/obj/item/device/flashlight/flare/update_brightness(mob/user = null)
..()
if(on)
item_state = "[initial(item_state)]-on"
else
item_state = "[initial(item_state)]"
/obj/item/device/flashlight/flare/attack_self(mob/user)
// Usual checks
if(!fuel)
user << "<span class='warning'>It's out of fuel!</span>"
return
if(on)
return
. = ..()
// All good, turn it on.
if(.)
user.visible_message("<span class='notice'>[user] lights \the [src].</span>", "<span class='notice'>You light \the [src]!</span>")
force = on_damage
damtype = "fire"
START_PROCESSING(SSobj, src)
/obj/item/device/flashlight/flare/is_hot()
return on * heat
/obj/item/device/flashlight/flare/torch
name = "torch"
desc = "A torch fashioned from some leaves and a log."
w_class = 4
brightness_on = 4
icon_state = "torch"
item_state = "torch"
on_damage = 10
slot_flags = null
/obj/item/device/flashlight/lantern
name = "lantern"
icon_state = "lantern"
item_state = "lantern"
desc = "A mining lantern."
brightness_on = 6 // luminosity when on
/obj/item/device/flashlight/slime
gender = PLURAL
name = "glowing slime extract"
desc = "Extract from a yellow slime. It emits a strong light when squeezed."
icon = 'icons/obj/lighting.dmi'
icon_state = "slime"
item_state = "slime"
w_class = 2
slot_flags = SLOT_BELT
materials = list()
brightness_on = 6 //luminosity when on
/obj/item/device/flashlight/emp
origin_tech = "magnets=3;syndicate=´1"
var/emp_max_charges = 4
var/emp_cur_charges = 4
var/charge_tick = 0
/obj/item/device/flashlight/emp/New()
..()
START_PROCESSING(SSobj, src)
/obj/item/device/flashlight/emp/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/device/flashlight/emp/process()
charge_tick++
if(charge_tick < 10) return 0
charge_tick = 0
emp_cur_charges = min(emp_cur_charges+1, emp_max_charges)
return 1
/obj/item/device/flashlight/emp/attack(mob/living/M, mob/living/user)
if(on && user.zone_selected == "eyes") // call original attack proc only if aiming at the eyes
..()
return
/obj/item/device/flashlight/emp/afterattack(atom/movable/A, mob/user, proximity)
if(!proximity)
return
if(emp_cur_charges > 0)
emp_cur_charges -= 1
if(ismob(A))
var/mob/M = A
add_logs(user, M, "attacked", "EMP-light")
M.visible_message("<span class='danger'>[user] blinks \the [src] at \the [A].", \
"<span class='userdanger'>[user] blinks \the [src] at you.")
else
A.visible_message("<span class='danger'>[user] blinks \the [src] at \the [A].")
user << "\The [src] now has [emp_cur_charges] charge\s."
A.emp_act(1)
else
user << "<span class='warning'>\The [src] needs time to recharge!</span>"
return
@@ -0,0 +1,158 @@
#define RAD_LEVEL_NORMAL 10
#define RAD_LEVEL_MODERATE 30
#define RAD_LEVEL_HIGH 75
#define RAD_LEVEL_VERY_HIGH 125
#define RAD_LEVEL_CRITICAL 200
/obj/item/device/geiger_counter //DISCLAIMER: I know nothing about how real-life Geiger counters work. This will not be realistic. ~Xhuis
name = "geiger counter"
desc = "A handheld device used for detecting and measuring radiation pulses."
icon_state = "geiger_off"
item_state = "multitool"
w_class = 2
slot_flags = SLOT_BELT
materials = list(MAT_METAL = 150, MAT_GLASS = 150)
var/scanning = 0
var/radiation_count = 0
var/emagged = 0
/obj/item/device/geiger_counter/New()
..()
START_PROCESSING(SSobj, src)
/obj/item/device/geiger_counter/Destroy()
STOP_PROCESSING(SSobj, src)
..()
/obj/item/device/geiger_counter/process()
if(emagged)
if(radiation_count < 20)
radiation_count++
return 0
if(radiation_count > 0)
radiation_count--
update_icon()
/obj/item/device/geiger_counter/examine(mob/user)
..()
if(!scanning)
return 1
user << "<span class='info'>Alt-click it to clear stored radiation levels.</span>"
if(emagged)
user << "<span class='warning'>The display seems to be incomprehensible.</span>"
return 1
switch(radiation_count)
if(-INFINITY to RAD_LEVEL_NORMAL)
user << "<span class='notice'>Ambient radiation level count reports that all is well.</span>"
if(RAD_LEVEL_NORMAL + 1 to RAD_LEVEL_MODERATE)
user << "<span class='disarm'>Ambient radiation levels slightly above average.</span>"
if(RAD_LEVEL_MODERATE + 1 to RAD_LEVEL_HIGH)
user << "<span class='warning'>Ambient radiation levels above average.</span>"
if(RAD_LEVEL_HIGH + 1 to RAD_LEVEL_VERY_HIGH)
user << "<span class='danger'>Ambient radiation levels highly above average.</span>"
if(RAD_LEVEL_VERY_HIGH + 1 to RAD_LEVEL_CRITICAL)
user << "<span class='suicide'>Ambient radiation levels nearing critical level.</span>"
if(RAD_LEVEL_CRITICAL + 1 to INFINITY)
user << "<span class='boldannounce'>Ambient radiation levels above critical level!</span>"
/obj/item/device/geiger_counter/update_icon()
if(!scanning)
icon_state = "geiger_off"
return 1
if(emagged)
icon_state = "geiger_on_emag"
return 1
switch(radiation_count)
if(-INFINITY to RAD_LEVEL_NORMAL)
icon_state = "geiger_on_1"
if(RAD_LEVEL_NORMAL + 1 to RAD_LEVEL_MODERATE)
icon_state = "geiger_on_2"
if(RAD_LEVEL_MODERATE + 1 to RAD_LEVEL_HIGH)
icon_state = "geiger_on_3"
if(RAD_LEVEL_HIGH + 1 to RAD_LEVEL_VERY_HIGH)
icon_state = "geiger_on_4"
if(RAD_LEVEL_VERY_HIGH + 1 to RAD_LEVEL_CRITICAL)
icon_state = "geiger_on_4"
if(RAD_LEVEL_CRITICAL + 1 to INFINITY)
icon_state = "geiger_on_5"
..()
/obj/item/device/geiger_counter/rad_act(amount)
if(!amount && scanning)
return 0
if(emagged)
amount = Clamp(amount, 0, 25) //Emagged geiger counters can only accept 25 radiation at a time
radiation_count += amount
if(isliving(loc))
var/mob/living/M = loc
if(!emagged)
M << "<span class='boldannounce'>\icon[src] RADIATION PULSE DETECTED.</span>"
M << "<span class='boldannounce'>\icon[src] Severity: [amount]</span>"
else
M << "<span class='boldannounce'>\icon[src] !@%$AT!(N P!LS! D/TEC?ED.</span>"
M << "<span class='boldannounce'>\icon[src] &!F2rity: <=[amount]#1</span>"
update_icon()
/obj/item/device/geiger_counter/attack_self(mob/user)
scanning = !scanning
update_icon()
user << "<span class='notice'>\icon[src] You switch [scanning ? "on" : "off"] [src].</span>"
/obj/item/device/geiger_counter/attack(mob/living/M, mob/user)
if(user.a_intent == "help")
if(!emagged)
user.visible_message("<span class='notice'>[user] scans [M] with [src].</span>", "<span class='notice'>You scan [M]'s radiation levels with [src]...</span>")
if(!M.radiation)
user << "<span class='notice'>\icon[src] Radiation levels within normal boundaries.</span>"
return 1
else
user << "<span class='boldannounce'>\icon[src] Subject is irradiated. Radiation levels: [M.radiation].</span>"
return 1
else
user.visible_message("<span class='notice'>[user] scans [M] with [src].</span>", "<span class='danger'>You project [src]'s stored radiation into [M]'s body!</span>")
M.rad_act(radiation_count)
radiation_count = 0
return 1
..()
/obj/item/device/geiger_counter/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/screwdriver) && emagged)
if(scanning)
user << "<span class='warning'>Turn off [src] before you perform this action!</span>"
return 0
user.visible_message("<span class='notice'>[user] unscrews [src]'s maintenance panel and begins fiddling with its innards...</span>", "<span class='notice'>You begin resetting [src]...</span>")
playsound(user, 'sound/items/Screwdriver.ogg', 50, 1)
if(!do_after(user, 40/I.toolspeed, target = user))
return 0
user.visible_message("<span class='notice'>[user] refastens [src]'s maintenance panel!</span>", "<span class='notice'>You reset [src] to its factory settings!</span>")
playsound(user, 'sound/items/Screwdriver2.ogg', 50, 1)
emagged = 0
radiation_count = 0
update_icon()
return 1
else
return ..()
/obj/item/device/geiger_counter/AltClick(mob/living/user)
if(!istype(user) || user.incapacitated())
return ..()
if(!scanning)
usr << "<span class='warning'>[src] must be on to reset its radiation level!</span>"
return 0
radiation_count = 0
usr << "<span class='notice'>You flush [src]'s radiation counts, resetting it to normal.</span>"
update_icon()
/obj/item/device/geiger_counter/emag_act(mob/user)
if(!emagged)
if(scanning)
user << "<span class='warning'>Turn off [src] before you perform this action!</span>"
return 0
user << "<span class='warning'>You override [src]'s radiation storing protocols. It will now generate small doses of radiation, and stored rads are now projected into creatures you scan.</span>"
emagged = 1
#undef RAD_LEVEL_NORMAL
#undef RAD_LEVEL_MODERATE
#undef RAD_LEVEL_HIGH
#undef RAD_LEVEL_VERY_HIGH
#undef RAD_LEVEL_CRITICAL
@@ -0,0 +1,73 @@
//copy pasta of the space piano, don't hurt me -Pete
/obj/item/device/instrument
name = "generic instrument"
burn_state = FLAMMABLE
burntime = 20
var/datum/song/handheld/song
var/instrumentId = "generic"
var/instrumentExt = "ogg"
/obj/item/device/instrument/New()
song = new(instrumentId, src)
song.instrumentExt = instrumentExt
/obj/item/device/instrument/Destroy()
qdel(song)
song = null
return ..()
/obj/item/device/instrument/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] begins to play 'Gloomy Sunday'! It looks like \he's trying to commit suicide..</span>")
return (BRUTELOSS)
/obj/item/device/instrument/initialize()
song.tempo = song.sanitize_tempo(song.tempo) // tick_lag isn't set when the map is loaded
..()
/obj/item/device/instrument/attack_self(mob/user)
if(!user.IsAdvancedToolUser())
user << "<span class='warning'>You don't have the dexterity to do this!</span>"
return 1
interact(user)
/obj/item/device/instrument/interact(mob/user)
if(!user)
return
if(!isliving(user) || user.stat || user.restrained() || user.lying)
return
user.set_machine(src)
song.interact(user)
/obj/item/device/instrument/violin
name = "space violin"
desc = "A wooden musical instrument with four strings and a bow. \"The devil went down to space, he was looking for an assistant to grief.\""
icon = 'icons/obj/musician.dmi'
icon_state = "violin"
item_state = "violin"
force = 10
hitsound = "swing_hit"
instrumentId = "violin"
/obj/item/device/instrument/guitar
name = "guitar"
desc = "It's made of wood and has bronze strings."
icon = 'icons/obj/musician.dmi'
icon_state = "guitar"
item_state = "guitar"
force = 10
attack_verb = list("played metal on", "serenaded", "crashed", "smashed")
hitsound = 'sound/weapons/stringsmash.ogg'
instrumentId = "guitar"
/obj/item/device/instrument/eguitar
name = "eletric guitar"
desc = "Makes all your shredding needs possible."
icon = 'icons/obj/musician.dmi'
icon_state = "eguitar"
item_state = "eguitar"
force = 12
attack_verb = list("played metal on", "shredded", "crashed", "smashed")
hitsound = 'sound/weapons/stringsmash.ogg'
instrumentId = "eguitar"
@@ -0,0 +1,172 @@
/obj/item/device/laser_pointer
name = "laser pointer"
desc = "Don't shine it in your eyes!"
icon = 'icons/obj/device.dmi'
icon_state = "pointer"
item_state = "pen"
var/pointer_icon_state
flags = CONDUCT | NOBLUDGEON
slot_flags = SLOT_BELT
materials = list(MAT_METAL=500, MAT_GLASS=500)
w_class = 2 //Increased to 2, because diodes are w_class 2. Conservation of matter.
origin_tech = "combat=1;magnets=2"
var/turf/pointer_loc
var/energy = 5
var/max_energy = 5
var/effectchance = 33
var/recharging = 0
var/recharge_locked = 0
var/obj/item/weapon/stock_parts/micro_laser/diode //used for upgrading!
/obj/item/device/laser_pointer/red
pointer_icon_state = "red_laser"
/obj/item/device/laser_pointer/green
pointer_icon_state = "green_laser"
/obj/item/device/laser_pointer/blue
pointer_icon_state = "blue_laser"
/obj/item/device/laser_pointer/purple
pointer_icon_state = "purple_laser"
/obj/item/device/laser_pointer/New()
..()
diode = new(src)
if(!pointer_icon_state)
pointer_icon_state = pick("red_laser","green_laser","blue_laser","purple_laser")
/obj/item/device/laser_pointer/upgraded/New()
..()
diode = new /obj/item/weapon/stock_parts/micro_laser/ultra
/obj/item/device/laser_pointer/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weapon/stock_parts/micro_laser))
if(!diode)
if(!user.unEquip(W))
return
W.loc = src
diode = W
user << "<span class='notice'>You install a [diode.name] in [src].</span>"
else
user << "<span class='notice'>[src] already has a diode installed.</span>"
else if(istype(W, /obj/item/weapon/screwdriver))
if(diode)
user << "<span class='notice'>You remove the [diode.name] from \the [src].</span>"
diode.loc = get_turf(src.loc)
diode = null
else
return ..()
/obj/item/device/laser_pointer/afterattack(atom/target, mob/living/user, flag, params)
laser_act(target, user, params)
/obj/item/device/laser_pointer/proc/laser_act(atom/target, mob/living/user, params)
if( !(user in (viewers(7,target))) )
return
if (!diode)
user << "<span class='notice'>You point [src] at [target], but nothing happens!</span>"
return
if (!user.IsAdvancedToolUser())
user << "<span class='warning'>You don't have the dexterity to do this!</span>"
return
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(H.dna.check_mutation(HULK) || (NOGUNS in H.dna.species.specflags))
user << "<span class='warning'>Your fingers can't press the button!</span>"
return
add_fingerprint(user)
//nothing happens if the battery is drained
if(recharge_locked)
user << "<span class='notice'>You point [src] at [target], but it's still charging.</span>"
return
var/outmsg
var/turf/targloc = get_turf(target)
//human/alien mobs
if(iscarbon(target))
var/mob/living/carbon/C = target
if(user.zone_selected == "eyes")
add_logs(user, C, "shone in the eyes", src)
var/severity = 1
if(prob(33))
severity = 2
else if(prob(50))
severity = 0
//20% chance to actually hit the eyes
if(prob(effectchance * diode.rating) && C.flash_eyes(severity))
outmsg = "<span class='notice'>You blind [C] by shining [src] in their eyes.</span>"
if(C.weakeyes)
C.Stun(1)
else
outmsg = "<span class='warning'>You fail to blind [C] by shining [src] at their eyes!</span>"
//robots
else if(isrobot(target))
var/mob/living/silicon/S = target
//20% chance to actually hit the sensors
if(prob(effectchance * diode.rating))
S.flash_eyes(affect_silicon = 1)
S.Weaken(rand(5,10))
S << "<span class='danger'>Your sensors were overloaded by a laser!</span>"
outmsg = "<span class='notice'>You overload [S] by shining [src] at their sensors.</span>"
add_logs(user, S, "shone in the sensors", src)
else
outmsg = "<span class='warning'>You fail to overload [S] by shining [src] at their sensors!</span>"
//cameras
else if(istype(target, /obj/machinery/camera))
var/obj/machinery/camera/C = target
if(prob(effectchance * diode.rating))
C.emp_act(1)
outmsg = "<span class='notice'>You hit the lens of [C] with [src], temporarily disabling the camera!</span>"
add_logs(user, C, "EMPed", src)
else
outmsg = "<span class='warning'>You miss the lens of [C] with [src]!</span>"
//laser pointer image
icon_state = "pointer_[pointer_icon_state]"
var/list/showto = list()
for(var/mob/M in viewers(7,targloc))
if(M.client)
showto.Add(M.client)
var/image/I = image('icons/obj/projectiles.dmi',targloc,pointer_icon_state,10)
var/list/click_params = params2list(params)
if(click_params)
if(click_params["icon-x"])
I.pixel_x = (text2num(click_params["icon-x"]) - 16)
if(click_params["icon-y"])
I.pixel_y = (text2num(click_params["icon-y"]) - 16)
else
I.pixel_x = target.pixel_x + rand(-5,5)
I.pixel_y = target.pixel_y + rand(-5,5)
if(outmsg)
user << outmsg
else
user << "<span class='info'>You point [src] at [target].</span>"
energy -= 1
if(energy <= max_energy)
if(!recharging)
recharging = 1
START_PROCESSING(SSobj, src)
if(energy <= 0)
user << "<span class='warning'>[src]'s battery is overused, it needs time to recharge!</span>"
recharge_locked = 1
flick_overlay(I, showto, 10)
icon_state = "pointer"
/obj/item/device/laser_pointer/process()
if(prob(20 - recharge_locked*5))
energy += 1
if(energy >= max_energy)
energy = max_energy
recharging = 0
recharge_locked = 0
..()
@@ -0,0 +1,264 @@
// 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 will need to be manually refilled with 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 broken or working lightbulbs, or sheets of glass."
icon = 'icons/obj/janitor.dmi'
icon_state = "lightreplacer0"
item_state = "electronic"
flags = CONDUCT
slot_flags = SLOT_BELT
origin_tech = "magnets=3;engineering=4"
var/max_uses = 20
var/uses = 0
var/emagged = 0
var/failmsg = ""
// How much to increase per each glass?
var/increment = 5
// How much to take from the glass?
var/decrement = 1
var/charge = 1
// 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()
uses = max_uses / 2
failmsg = "The [name]'s refill light blinks red."
..()
/obj/item/device/lightreplacer/examine(mob/user)
..()
user << status_string()
/obj/item/device/lightreplacer/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stack/sheet/glass))
var/obj/item/stack/sheet/glass/G = W
if(uses >= max_uses)
user << "<span class='warning'>[src.name] is full.</span>"
return
else if(G.use(decrement))
AddUses(increment)
user << "<span class='notice'>You insert a piece of glass into the [src.name]. You have [uses] light\s remaining.</span>"
return
else
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
AddUses(1)
qdel(L)
else
if(!user.unEquip(W))
return
new_bulbs += AddShards(1)
qdel(L)
if(new_bulbs != 0)
playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
user << "<span class='notice'>You insert the [L.name] into the [src.name]. " + status_string() + "</span>"
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
AddUses(1)
qdel(L)
else if(L.status == LIGHT_BROKEN || L.status == LIGHT_BURNED)
replaced_something = TRUE
AddShards(1)
qdel(L)
if(!found_lightbulbs)
user << "<span class='warning'>\The [S] contains no bulbs.</span>"
return
if(!replaced_something && src.uses == max_uses)
user << "<span class='warning'>\The [src] is full!</span>"
return
user << "<span class='notice'>You fill \the [src] with lights from \the [S]. " + status_string() + "</span>"
/obj/item/device/lightreplacer/emag_act()
if(!emagged)
Emag()
/obj/item/device/lightreplacer/attack_self(mob/user)
user << status_string()
/obj/item/device/lightreplacer/update_icon()
icon_state = "lightreplacer[emagged]"
/obj/item/device/lightreplacer/proc/status_string()
return "It has [uses] light\s remaining (plus [bulb_shards] fragment\s)."
/obj/item/device/lightreplacer/proc/Use(mob/user)
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
AddUses(-1)
return 1
// Negative numbers will subtract
/obj/item/device/lightreplacer/proc/AddUses(amount = 1)
uses = Clamp(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)
AddUses(new_bulbs)
bulb_shards = bulb_shards % shards_required
return new_bulbs
/obj/item/device/lightreplacer/proc/Charge(var/mob/user)
charge += 1
if(charge > 3)
AddUses(1)
charge = 1
/obj/item/device/lightreplacer/proc/ReplaceLight(obj/machinery/light/target, mob/living/U)
if(target.status != LIGHT_OK)
if(CanUse(U))
if(!Use(U)) return
U << "<span class='notice'>You replace the [target.fitting] with \the [src].</span>"
if(target.status != LIGHT_EMPTY)
var/new_bulbs = AddShards(1)
if(new_bulbs != 0)
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.loc, 'sound/machines/ding.ogg', 50, 1)
target.status = LIGHT_EMPTY
target.update()
var/obj/item/weapon/light/L2 = new target.light_type()
target.status = L2.status
target.switchcount = L2.switchcount
target.rigged = emagged
target.brightness = L2.brightness
target.on = target.has_power()
target.update()
qdel(L2)
if(target.on && target.rigged)
target.explode()
return
else
U << failmsg
return
else
U << "<span class='warning'>There is a working [target.fitting] already inserted!</span>"
return
/obj/item/device/lightreplacer/proc/Emag()
emagged = !emagged
playsound(src.loc, "sparks", 100, 1)
if(emagged)
name = "shortcircuited [initial(name)]"
else
name = initial(name)
update_icon()
//Can you use it?
/obj/item/device/lightreplacer/proc/CanUse(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
/obj/item/device/lightreplacer/afterattack(atom/T, mob/U, proximity)
if(!proximity)
return
if(!isturf(T))
return
var/used = FALSE
for(var/atom/A in T)
if(!CanUse(U))
break
used = TRUE
if(istype(A, /obj/machinery/light))
ReplaceLight(A, U)
if(!used)
U << failmsg
/obj/item/device/lightreplacer/proc/janicart_insert(mob/user, obj/structure/janitorialcart/J)
J.put_in_cart(src, user)
J.myreplacer = src
J.update_icon()
/obj/item/device/lightreplacer/cyborg/janicart_insert(mob/user, obj/structure/janitorialcart/J)
return
#undef LIGHT_OK
#undef LIGHT_EMPTY
#undef LIGHT_BROKEN
#undef LIGHT_BURNED
@@ -0,0 +1,7 @@
/obj/item/device/machineprototype
name = "machine prototype"
desc = "A complicated machine prototype. You have no idea how it works."
icon = 'icons/obj/machineprototype.dmi'
icon_state = "machineprototype"
materials = list(MAT_METAL=1000, MAT_GLASS=500)
origin_tech = "engineering=6"
@@ -0,0 +1,74 @@
/obj/item/device/megaphone
name = "megaphone"
desc = "A device used to project your voice. Loudly."
icon_state = "megaphone"
item_state = "radio"
w_class = 2
flags = FPRINT
siemens_coefficient = 1
var/spamcheck = 0
var/emagged = 0
var/insults = 0
var/voicespan = "command_headset" // sic
var/list/insultmsg = list("FUCK EVERYONE!", "DEATH TO LIZARDS!", "ALL SECURITY TO SHOOT ME ON SIGHT!", "I HAVE A BOMB!", "CAPTAIN IS A COMDOM!", "FOR THE SYNDICATE!", "VIVA!", "HONK!")
/obj/item/device/megaphone/attack_self(mob/living/carbon/human/user)
if(user.client)
if(user.client.prefs.muted & MUTE_IC)
src << "<span class='warning'>You cannot speak in IC (muted).</span>"
return
if(!ishuman(user))
user << "<span class='warning'>You don't know how to use this!</span>"
return
if(spamcheck > world.time)
user << "<span class='warning'>\The [src] needs to recharge!</span>"
return
var/message = copytext(sanitize(input(user, "Shout a message?", "Megaphone", null) as text),1,MAX_MESSAGE_LEN)
if(!message)
return
message = capitalize(message)
if(!user.can_speak(message))
user << "<span class='warning'>You find yourself unable to speak at all!</span>"
return
if ((src.loc == user && user.stat == 0))
if(emagged)
if(insults)
user.say(pick(insultmsg),"machine", list(voicespan))
insults--
else
user << "<span class='warning'>*BZZZZzzzzzt*</span>"
else
user.say(message,"machine", list(voicespan))
playsound(loc, 'sound/items/megaphone.ogg', 100, 0, 1)
spamcheck = world.time + 50
return
/obj/item/device/megaphone/emag_act(mob/user)
user << "<span class='warning'>You overload \the [src]'s voice synthesizer.</span>"
emagged = 1
insults = rand(1, 3) //to prevent dickflooding
/obj/item/device/megaphone/sec
name = "security megaphone"
icon_state = "megaphone-sec"
/obj/item/device/megaphone/command
name = "command megaphone"
icon_state = "megaphone-command"
/obj/item/device/megaphone/cargo
name = "supply megaphone"
icon_state = "megaphone-cargo"
/obj/item/device/megaphone/clown
name = "clown's megaphone"
desc = "Something that should not exist."
icon_state = "megaphone-clown"
voicespan = "clown"
@@ -0,0 +1,35 @@
/obj/item/modkit
name = "modification kit"
desc = "A one-use kit, which enables kinetic accelerators to retain their \
charge when away from a bioelectric source, renders them immune to \
interference with other accelerators, as well as allowing less \
dextrous races to use the tool."
icon = 'icons/obj/objects.dmi'
icon_state = "modkit"
origin_tech = "programming=2;materials=2;magnets=4"
var/uses = 1
/obj/item/modkit/afterattack(obj/item/weapon/gun/energy/kinetic_accelerator/C, mob/user)
..()
if(!uses)
qdel(src)
return
if(!istype(C))
user << "<span class='warning'>This kit can only modify kinetic \
accelerators!</span>"
return ..()
// RIP the 'improved improved improved improved kinetic accelerator
if(C.holds_charge && C.unique_frequency)
user << "<span class='warning'>This kinetic accelerator already has \
these upgrades.</span>"
return ..()
user <<"<span class='notice'>You modify the [C], adjusting the trigger \
guard and internal capacitor.</span>"
C.name = "improved [C.name]"
C.holds_charge = TRUE
C.unique_frequency = TRUE
C.trigger_guard = TRIGGER_GUARD_ALLOW_ALL
uses--
if(!uses)
qdel(src)
@@ -0,0 +1,92 @@
#define PROXIMITY_NONE ""
#define PROXIMITY_ON_SCREEN "_red"
#define PROXIMITY_NEAR "_yellow"
/**
* 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."
icon_state = "multitool"
force = 5
w_class = 2
throwforce = 0
throw_range = 7
throw_speed = 3
materials = list(MAT_METAL=50, MAT_GLASS=20)
origin_tech = "magnets=1;engineering=2"
var/obj/machinery/buffer // simple machine buffer for device linkage
hitsound = 'sound/weapons/tap.ogg'
toolspeed = 1
// Syndicate device disguised as a multitool; it will turn red when an AI camera is nearby.
/obj/item/device/multitool/ai_detect
var/track_cooldown = 0
var/track_delay = 10 //How often it checks for proximity
var/detect_state = PROXIMITY_NONE
var/rangealert = 8 //Glows red when inside
var/rangewarning = 20 //Glows yellow when inside
origin_tech = "magnets=1;engineering=2;syndicate=1"
/obj/item/device/multitool/ai_detect/New()
..()
START_PROCESSING(SSobj, src)
/obj/item/device/multitool/ai_detect/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/device/multitool/ai_detect/process()
if(track_cooldown > world.time)
return
detect_state = PROXIMITY_NONE
multitool_detect()
icon_state = "[initial(icon_state)][detect_state]"
track_cooldown = world.time + track_delay
/obj/item/device/multitool/ai_detect/proc/multitool_detect()
var/turf/our_turf = get_turf(src)
for(var/mob/living/silicon/ai/AI in ai_list)
if(AI.cameraFollow == src)
detect_state = PROXIMITY_ON_SCREEN
break
if(!detect_state && cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z))
var/datum/camerachunk/chunk = cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z)
if(chunk)
if(chunk.seenby.len)
for(var/mob/camera/aiEye/A in chunk.seenby)
var/turf/detect_turf = get_turf(A)
if(get_dist(our_turf, detect_turf) < rangealert)
detect_state = PROXIMITY_ON_SCREEN
break
if(get_dist(our_turf, detect_turf) < rangewarning)
detect_state = PROXIMITY_NEAR
break
/obj/item/device/multitool/ai_detect/admin
desc = "Used for pulsing wires to test which to cut. Not recommended by doctors. Has a strange tag that says 'Grief in Safety'" //What else should I say for a meme item?
track_delay = 5
/obj/item/device/multitool/ai_detect/admin/multitool_detect()
var/turf/our_turf = get_turf(src)
for(var/mob/J in urange(rangewarning,our_turf))
if(admin_datums[J.ckey])
detect_state = PROXIMITY_NEAR
var/turf/detect_turf = get_turf(J)
if(get_dist(our_turf, detect_turf) < rangealert)
detect_state = PROXIMITY_ON_SCREEN
break
/obj/item/device/multitool/cyborg
name = "multitool"
desc = "Optimised and stripped-down version of a regular multitool."
icon = 'icons/obj/items_cyborg.dmi'
toolspeed = 2
+140
View File
@@ -0,0 +1,140 @@
/obj/item/device/paicard
name = "personal AI device"
icon = 'icons/obj/aicards.dmi'
icon_state = "pai"
item_state = "electronic"
w_class = 2
slot_flags = SLOT_BELT
origin_tech = "programming=2"
var/obj/item/device/radio/radio
var/looking_for_personality = 0
var/mob/living/silicon/pai/pai
/obj/item/device/paicard/New()
..()
add_overlay("pai-off")
/obj/item/device/paicard/Destroy()
//Will stop people throwing friend pAIs into the singularity so they can respawn
if(!isnull(pai))
pai.death(0)
return ..()
/obj/item/device/paicard/attack_self(mob/user)
if (!in_range(src, user))
return
user.set_machine(src)
var/dat = "<TT><B>Personal AI Device</B><BR>"
if(pai && (!pai.master_dna || !pai.master))
dat += "<a href='byond://?src=\ref[src];setdna=1'>Imprint Master DNA</a><br>"
if(pai)
dat += "Installed Personality: [pai.name]<br>"
dat += "Prime directive: <br>[pai.laws.zeroth]<br>"
for(var/slaws in pai.laws.supplied)
dat += "Additional directives: <br>[slaws]<br>"
dat += "<a href='byond://?src=\ref[src];setlaws=1'>Configure Directives</a><br>"
dat += "<br>"
dat += "<h3>Device Settings</h3><br>"
if(radio)
dat += "<b>Radio Uplink</b><br>"
dat += "Transmit: <A href='byond://?src=\ref[src];wires=[WIRE_TX]'>[(radio.wires.is_cut(WIRE_TX)) ? "Disabled" : "Enabled"]</A><br>"
dat += "Receive: <A href='byond://?src=\ref[src];wires=[WIRE_RX]'>[(radio.wires.is_cut(WIRE_RX)) ? "Disabled" : "Enabled"]</A><br>"
else
dat += "<b>Radio Uplink</b><br>"
dat += "<font color=red><i>Radio firmware not loaded. Please install a pAI personality to load firmware.</i></font><br>"
dat += "<A href='byond://?src=\ref[src];wipe=1'>\[Wipe current pAI personality\]</a><br>"
else
if(looking_for_personality)
dat += "Searching for a personality..."
dat += "<A href='byond://?src=\ref[src];request=1'>\[View available personalities\]</a><br>"
else
dat += "No personality is installed.<br>"
dat += "<A href='byond://?src=\ref[src];request=1'>\[Request personal AI personality\]</a><br>"
dat += "Each time this button is pressed, a request will be sent out to any available personalities. Check back often and give a lot of time for personalities to respond. This process could take anywhere from 15 seconds to several minutes, depending on the available personalities' timeliness."
user << browse(dat, "window=paicard")
onclose(user, "paicard")
return
/obj/item/device/paicard/Topic(href, href_list)
if(!usr || usr.stat)
return
if(href_list["request"])
src.looking_for_personality = 1
SSpai.findPAI(src, usr)
if(pai)
if(href_list["setdna"])
if(pai.master_dna)
return
if(!istype(usr, /mob/living/carbon))
usr << "<span class='warning'>You don't have any DNA, or your DNA is incompatible with this device!</span>"
else
var/mob/living/carbon/M = usr
pai.master = M.real_name
pai.master_dna = M.dna.unique_enzymes
pai << "<span class='notice'>You have been bound to a new master.</span>"
if(href_list["wipe"])
var/confirm = input("Are you CERTAIN you wish to delete the current personality? This action cannot be undone.", "Personality Wipe") in list("Yes", "No")
if(confirm == "Yes")
if(pai)
pai << "<span class='warning'>You feel yourself slipping away from reality.</span>"
pai << "<span class='danger'>Byte by byte you lose your sense of self.</span>"
pai << "<span class='userdanger'>Your mental faculties leave you.</span>"
pai << "<span class='rose'>oblivion... </span>"
pai.death(0)
removePersonality()
if(href_list["wires"])
var/wire = text2num(href_list["wires"])
if(radio)
radio.wires.cut(wire)
if(href_list["setlaws"])
var/newlaws = copytext(sanitize(input("Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", pai.laws.supplied[1]) as message),1,MAX_MESSAGE_LEN)
if(newlaws && pai)
pai.add_supplied_law(0,newlaws)
pai << "Your supplemental directives have been updated. Your new directives are:"
pai << "Prime Directive : <br>[pai.laws.zeroth]"
for(var/slaws in pai.laws.supplied)
pai << "Supplemental Directives: <br>[slaws]"
attack_self(usr)
// WIRE_SIGNAL = 1
// WIRE_RECEIVE = 2
// WIRE_TRANSMIT = 4
/obj/item/device/paicard/proc/setPersonality(mob/living/silicon/pai/personality)
src.pai = personality
src.add_overlay("pai-null")
playsound(loc, 'sound/effects/pai_boot.ogg', 50, 1, -1)
audible_message("\The [src] plays a cheerful startup noise!")
/obj/item/device/paicard/proc/removePersonality()
src.pai = null
src.cut_overlays()
src.add_overlay("pai-off")
/obj/item/device/paicard/proc/setEmotion(emotion)
if(pai)
src.cut_overlays()
switch(emotion)
if(1) src.add_overlay("pai-happy")
if(2) src.add_overlay("pai-cat")
if(3) src.add_overlay("pai-extremely-happy")
if(4) src.add_overlay("pai-face")
if(5) src.add_overlay("pai-laugh")
if(6) src.add_overlay("pai-off")
if(7) src.add_overlay("pai-sad")
if(8) src.add_overlay("pai-angry")
if(9) src.add_overlay("pai-what")
if(10) src.add_overlay("pai-null")
/obj/item/device/paicard/proc/alertUpdate()
visible_message("<span class ='info'>[src] flashes a message across its screen, \"Additional personalities available for download.\"", "<span class='notice'>[src] bleeps electronically.</span>")
/obj/item/device/paicard/emp_act(severity)
if(pai)
pai.emp_act(severity)
..()
@@ -0,0 +1,41 @@
/obj/item/device/pipe_painter
name = "pipe painter"
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "labeler1"
item_state = "flight"
flags = NOBLUDGEON
var/list/modes = list(
"grey" = rgb(255,255,255),
"red" = rgb(255,0,0),
"blue" = rgb(0,0,255),
"cyan" = rgb(0,256,249),
"green" = rgb(30,255,0),
"yellow" = rgb(255,198,0),
"purple" = rgb(130,43,255)
)
var/mode = "grey"
materials = list(MAT_METAL=5000, MAT_GLASS=2000)
/obj/item/device/pipe_painter/afterattack(atom/A, mob/user, proximity_flag)
//Make sure we only paint adjacent items
if(!proximity_flag)
return
if(!istype(A,/obj/machinery/atmospherics/pipe))
return
var/obj/machinery/atmospherics/pipe/P = A
P.color = modes[mode]
P.pipe_color = modes[mode]
P.stored.color = modes[mode]
user.visible_message("<span class='notice'>[user] paints \the [P] [mode].</span>","<span class='notice'>You paint \the [P] [mode].</span>")
P.update_node_icon() //updates the neighbors
/obj/item/device/pipe_painter/attack_self(mob/user)
mode = input("Which colour do you want to use?","Pipe painter") in modes
/obj/item/device/pipe_painter/examine()
..()
usr << "It is set to [mode]."
@@ -0,0 +1,145 @@
// Powersink - used to drain station power
/obj/item/device/powersink
desc = "A nulling power sink which drains energy from electrical systems."
name = "power sink"
icon_state = "powersink0"
item_state = "electronic"
w_class = 4
flags = CONDUCT
throwforce = 5
throw_speed = 1
throw_range = 2
materials = list(MAT_METAL=750)
origin_tech = "powerstorage=5;syndicate=5"
var/drain_rate = 1600000 // amount of power to drain per tick
var/power_drained = 0 // has drained this much power
var/max_power = 1e10 // maximum power that can be drained before exploding
var/mode = 0 // 0 = off, 1=clamped (off), 2=operating
var/admins_warned = 0 // stop spam, only warn the admins once that we are about to boom
var/const/DISCONNECTED = 0
var/const/CLAMPED_OFF = 1
var/const/OPERATING = 2
var/obj/structure/cable/attached // the attached cable
/obj/item/device/powersink/update_icon()
icon_state = "powersink[mode == OPERATING]"
/obj/item/device/powersink/proc/set_mode(value)
if(value == mode)
return
switch(value)
if(DISCONNECTED)
attached = null
if(mode == OPERATING)
STOP_PROCESSING(SSobj, src)
anchored = 0
if(CLAMPED_OFF)
if(!attached)
return
if(mode == OPERATING)
STOP_PROCESSING(SSobj, src)
anchored = 1
if(OPERATING)
if(!attached)
return
START_PROCESSING(SSobj, src)
anchored = 1
mode = value
update_icon()
SetLuminosity(0)
/obj/item/device/powersink/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/screwdriver))
if(mode == DISCONNECTED)
var/turf/T = loc
if(isturf(T) && !T.intact)
attached = locate() in T
if(!attached)
user << "<span class='warning'>This device must be placed over an exposed, powered cable node!</span>"
else
set_mode(CLAMPED_OFF)
user.visible_message( \
"[user] attaches \the [src] to the cable.", \
"<span class='notice'>You attach \the [src] to the cable.</span>",
"<span class='italics'>You hear some wires being connected to something.</span>")
else
user << "<span class='warning'>This device must be placed over an exposed, powered cable node!</span>"
else
set_mode(DISCONNECTED)
user.visible_message( \
"[user] detaches \the [src] from the cable.", \
"<span class='notice'>You detach \the [src] from the cable.</span>",
"<span class='italics'>You hear some wires being disconnected from something.</span>")
else
return ..()
/obj/item/device/powersink/attack_paw()
return
/obj/item/device/powersink/attack_ai()
return
/obj/item/device/powersink/attack_hand(mob/user)
switch(mode)
if(DISCONNECTED)
..()
if(CLAMPED_OFF)
user.visible_message( \
"[user] activates \the [src]!", \
"<span class='notice'>You activate \the [src].</span>",
"<span class='italics'>You hear a click.</span>")
message_admins("Power sink activated by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
log_game("Power sink activated by [key_name(user)] at ([x],[y],[z])")
set_mode(OPERATING)
if(OPERATING)
user.visible_message( \
"[user] deactivates \the [src]!", \
"<span class='notice'>You deactivate \the [src].</span>",
"<span class='italics'>You hear a click.</span>")
set_mode(CLAMPED_OFF)
/obj/item/device/powersink/process()
if(!attached)
set_mode(DISCONNECTED)
return
var/datum/powernet/PN = attached.powernet
if(PN)
SetLuminosity(5)
// found a powernet, so drain up to max power from it
var/drained = min ( drain_rate, PN.avail )
PN.load += drained
power_drained += drained
// 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)
if(istype(T.master, /obj/machinery/power/apc))
var/obj/machinery/power/apc/A = T.master
if(A.operating && A.cell)
A.cell.charge = max(0, A.cell.charge - 50)
power_drained += 50
if(A.charging == 2) // If the cell was full
A.charging = 1 // It's no longer full
if(power_drained > max_power * 0.98)
if (!admins_warned)
admins_warned = 1
message_admins("Power sink at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>) is 95% full. Explosion imminent.")
playsound(src, 'sound/effects/screech.ogg', 100, 1, 1)
if(power_drained >= max_power)
STOP_PROCESSING(SSobj, src)
explosion(src.loc, 4,8,16,32)
qdel(src)
@@ -0,0 +1,33 @@
/obj/item/device/radio/beacon
name = "tracking beacon"
desc = "A beacon used by a teleporter."
icon_state = "beacon"
item_state = "beacon"
var/code = "electronic"
origin_tech = "bluespace=1"
dog_fashion = null
/obj/item/device/radio/beacon/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
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
/*
//Probably a better way of doing this, I'm lazy.
/obj/item/device/radio/beacon/bacon/proc/digest_delay()
spawn(600)
qdel(src)*/ //Bacon beacons are no more rip in peace
@@ -0,0 +1,147 @@
/obj/item/device/electropack
name = "electropack"
desc = "Dance my monkeys! DANCE!!!"
icon = 'icons/obj/radio.dmi'
icon_state = "electropack0"
item_state = "electropack"
flags = CONDUCT
slot_flags = SLOT_BACK
w_class = 5
materials = list(MAT_METAL=10000, MAT_GLASS=2500)
var/on = 1
var/code = 2
var/frequency = 1449
var/shock_cooldown = 0
/obj/item/device/electropack/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] hooks \himself to the electropack and spams the trigger! It looks like \he's trying to commit suicide..</span>")
return (FIRELOSS)
/obj/item/device/electropack/initialize()
if(SSradio)
SSradio.add_object(src, frequency, RADIO_CHAT)
/obj/item/device/electropack/Destroy()
if(SSradio)
SSradio.remove_object(src, frequency)
return ..()
/obj/item/device/electropack/attack_hand(mob/user)
if(iscarbon(user))
var/mob/living/carbon/C = user
if(src == C.back)
user << "<span class='warning'>You need help taking this off!</span>"
return
..()
/obj/item/device/electropack/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/clothing/head/helmet))
var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit( user )
A.icon = 'icons/obj/assemblies.dmi'
if(!user.unEquip(W))
user << "<span class='warning'>\the [W] is stuck to your hand, you cannot attach it to \the [src]!</span>"
return
W.loc = A
W.master = A
A.part1 = W
user.unEquip(src)
loc = A
master = A
A.part2 = src
user.put_in_hands(A)
A.add_fingerprint(user)
if(src.flags & NODROP)
A.flags |= NODROP
else
return ..()
/obj/item/device/electropack/Topic(href, href_list)
//..()
var/mob/living/carbon/C = usr
if(usr.stat || usr.restrained() || C.back == src)
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"])
SSradio.remove_object(src, frequency)
frequency = sanitize_frequency(frequency + text2num(href_list["freq"]))
SSradio.add_object(src, frequency, RADIO_CHAT)
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/electropack/receive_signal(datum/signal/signal)
if(!signal || signal.encryption != code)
return
if(ismob(loc) && on)
if(shock_cooldown != 0)
return
shock_cooldown = 1
spawn(100)
shock_cooldown = 0
var/mob/M = loc
step(M, pick(cardinal))
M << "<span class='danger'>You feel a sharp shock!</span>"
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, M)
s.start()
M.Weaken(5)
if(master)
master.receive_signal()
return
/obj/item/device/electropack/attack_self(mob/user)
if(!istype(user, /mob/living/carbon/human))
return
user.set_machine(src)
var/dat = {"<TT>Turned [on ? "On" : "Off"] -
<A href='?src=\ref[src];power=1'>Toggle</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
@@ -0,0 +1,129 @@
/obj/item/device/encryptionkey/
name = "standard encryption key"
desc = "An encryption key for a radio headset. Has no special codes in it. WHY DOES IT EXIST? ASK NANOTRASEN."
icon = 'icons/obj/radio.dmi'
icon_state = "cypherkey"
w_class = 1
origin_tech = "engineering=2;bluespace=1"
var/translate_binary = 0
var/translate_hive = 0
var/syndie = 0
var/centcom = 0
var/list/channels = list()
/obj/item/device/encryptionkey/syndicate
icon_state = "cypherkey"
channels = list("Syndicate" = 1)
origin_tech = "syndicate=1;engineering=3;bluespace=2"
syndie = 1//Signifies that it de-crypts Syndicate transmissions
/obj/item/device/encryptionkey/binary
name = "binary translator key"
desc = "An encryption key for a radio headset. To access the binary channel, use :b."
icon_state = "cypherkey"
translate_binary = 1
origin_tech = "syndicate=3;engineering=4;bluespace=3"
/obj/item/device/encryptionkey/headset_sec
name = "security radio encryption key"
desc = "An encryption key for a radio headset. To access the security channel, use :s."
icon_state = "sec_cypherkey"
channels = list("Security" = 1)
/obj/item/device/encryptionkey/headset_eng
name = "engineering radio encryption key"
desc = "An encryption key for a radio headset. To access the engineering channel, use :e."
icon_state = "eng_cypherkey"
channels = list("Engineering" = 1)
/obj/item/device/encryptionkey/headset_rob
name = "robotics radio encryption key"
desc = "An encryption key for a radio headset. To access the engineering channel, use :e. For research, use :n."
icon_state = "rob_cypherkey"
channels = list("Science" = 1, "Engineering" = 1)
/obj/item/device/encryptionkey/headset_med
name = "medical radio encryption key"
desc = "An encryption key for a radio headset. To access the medical channel, use :m."
icon_state = "med_cypherkey"
channels = list("Medical" = 1)
/obj/item/device/encryptionkey/headset_sci
name = "science radio encryption key"
desc = "An encryption key for a radio headset. To access the science channel, use :n."
icon_state = "sci_cypherkey"
channels = list("Science" = 1)
/obj/item/device/encryptionkey/headset_medsci
name = "medical research radio encryption key"
desc = "An encryption key for a radio headset. To access the medical channel, use :m. For science, use :n."
icon_state = "medsci_cypherkey"
channels = list("Science" = 1, "Medical" = 1)
/obj/item/device/encryptionkey/headset_com
name = "command radio encryption key"
desc = "An encryption key for a radio headset. To access the command channel, use :c."
icon_state = "com_cypherkey"
channels = list("Command" = 1)
/obj/item/device/encryptionkey/heads/captain
name = "\proper the captain's encryption key"
desc = "An encryption key for a radio headset. Channels are as follows: :c - command, :s - security, :e - engineering, :u - supply, :v - service, :m - medical, :n - science."
icon_state = "cap_cypherkey"
channels = list("Command" = 1, "Security" = 1, "Engineering" = 0, "Science" = 0, "Medical" = 0, "Supply" = 0, "Service" = 0)
/obj/item/device/encryptionkey/heads/rd
name = "\proper the research director's encryption key"
desc = "An encryption key for a radio headset. To access the science channel, use :n. For command, use :c."
icon_state = "rd_cypherkey"
channels = list("Science" = 1, "Command" = 1)
/obj/item/device/encryptionkey/heads/hos
name = "\proper the head of security's encryption key"
desc = "An encryption key for a radio headset. To access the security channel, use :s. For command, use :c."
icon_state = "hos_cypherkey"
channels = list("Security" = 1, "Command" = 1)
/obj/item/device/encryptionkey/heads/ce
name = "\proper the chief engineer's encryption key"
desc = "An encryption key for a radio headset. To access the engineering channel, use :e. For command, use :c."
icon_state = "ce_cypherkey"
channels = list("Engineering" = 1, "Command" = 1)
/obj/item/device/encryptionkey/heads/cmo
name = "\proper the chief medical officer's encryption key"
desc = "An encryption key for a radio headset. To access the medical channel, use :m. For command, use :c."
icon_state = "cmo_cypherkey"
channels = list("Medical" = 1, "Command" = 1)
/obj/item/device/encryptionkey/heads/hop
name = "\proper the head of personnel's encryption key"
desc = "An encryption key for a radio headset. Channels are as follows: :u - supply, :v - service, :c - command."
icon_state = "hop_cypherkey"
channels = list("Supply" = 1, "Service" = 1, "Command" = 1)
/obj/item/device/encryptionkey/headset_cargo
name = "supply radio encryption key"
desc = "An encryption key for a radio headset. To access the supply channel, use :u."
icon_state = "cargo_cypherkey"
channels = list("Supply" = 1)
/obj/item/device/encryptionkey/headset_service
name = "service radio encryption key"
desc = "An encryption key for a radio headset. To access the service channel, use :v."
icon_state = "srv_cypherkey"
channels = list("Service" = 1)
/obj/item/device/encryptionkey/headset_cent
name = "centcom radio encryption key"
desc = "An encryption key for a radio headset. To access the centcom channel, use :y."
icon_state = "cent_cypherkey"
centcom = 1
channels = list("Centcom" = 1)
/obj/item/device/encryptionkey/ai //ported from NT, this goes 'inside' the AI.
channels = list("Command" = 1, "Security" = 1, "Engineering" = 1, "Science" = 1, "Medical" = 1, "Supply" = 1, "Service" = 1, "AI Private" = 1)
/obj/item/device/encryptionkey/secbot
channels = list("AI Private"=1,"Security"=1)
@@ -0,0 +1,290 @@
/obj/item/device/radio/headset
name = "radio headset"
desc = "An updated, modular intercom that fits over the head. Takes encryption keys. \nTo speak on the general radio frequency, use ; before speaking."
icon_state = "headset"
item_state = "headset"
materials = list(MAT_METAL=75)
subspace_transmission = 1
canhear_range = 0 // can't hear headsets from very far away
slot_flags = SLOT_EARS
var/obj/item/device/encryptionkey/keyslot2 = null
dog_fashion = null
/obj/item/device/radio/headset/New()
..()
recalculateChannels()
/obj/item/device/radio/headset/Destroy()
qdel(keyslot)
qdel(keyslot2)
keyslot = null
keyslot2 = null
return ..()
/obj/item/device/radio/headset/talk_into(mob/living/M, message, channel, list/spans)
if (!listening)
return
..()
/obj/item/device/radio/headset/receive_range(freq, level, AIuser)
if(ishuman(src.loc))
var/mob/living/carbon/human/H = src.loc
if(H.ears == src)
return ..(freq, level)
else if(AIuser)
return ..(freq, level)
return -1
/obj/item/device/radio/headset/syndicate //disguised to look like a normal headset for stealth ops
origin_tech = "syndicate=3"
/obj/item/device/radio/headset/syndicate/alt //undisguised bowman with flash protection
name = "syndicate headset"
desc = "A syndicate headset that can be used to hear all radio frequencies. Protects ears from flashbangs. \nTo access the syndicate channel, use ; before speaking."
flags = EARBANGPROTECT
origin_tech = "syndicate=3"
icon_state = "syndie_headset"
item_state = "syndie_headset"
/obj/item/device/radio/headset/syndicate/alt/leader
name = "team leader headset"
command = TRUE
/obj/item/device/radio/headset/syndicate/New()
..()
make_syndie()
/obj/item/device/radio/headset/binary
origin_tech = "syndicate=3"
/obj/item/device/radio/headset/binary/New()
..()
qdel(keyslot)
keyslot = new /obj/item/device/encryptionkey/binary
recalculateChannels()
/obj/item/device/radio/headset/headset_sec
name = "security radio headset"
desc = "This is used by your elite security force. \nTo access the security channel, use :s."
icon_state = "sec_headset"
keyslot = new /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. Protects ears from flashbangs. \nTo access the security channel, use :s."
flags = EARBANGPROTECT
icon_state = "sec_headset_alt"
item_state = "sec_headset_alt"
/obj/item/device/radio/headset/headset_eng
name = "engineering radio headset"
desc = "When the engineers wish to chat like girls. \nTo access the engineering channel, use :e. "
icon_state = "eng_headset"
keyslot = new /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. \nTo access the engineering channel, use :e. For research, use :n."
icon_state = "rob_headset"
keyslot = new /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. \nTo access the medical channel, use :m."
icon_state = "med_headset"
keyslot = new /obj/item/device/encryptionkey/headset_med
/obj/item/device/radio/headset/headset_sci
name = "science radio headset"
desc = "A sciency headset. Like usual. \nTo access the science channel, use :n."
icon_state = "sci_headset"
keyslot = new /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. \nTo access the medical channel, use :m. For science, use :n."
icon_state = "medsci_headset"
keyslot = new /obj/item/device/encryptionkey/headset_medsci
/obj/item/device/radio/headset/headset_com
name = "command radio headset"
desc = "A headset with a commanding channel. \nTo access the command channel, use :c."
icon_state = "com_headset"
keyslot = new /obj/item/device/encryptionkey/headset_com
/obj/item/device/radio/headset/heads
command = TRUE
/obj/item/device/radio/headset/heads/captain
name = "\proper the captain's headset"
desc = "The headset of the king. \nChannels are as follows: :c - command, :s - security, :e - engineering, :u - supply, :v - service, :m - medical, :n - science."
icon_state = "com_headset"
keyslot = new /obj/item/device/encryptionkey/heads/captain
/obj/item/device/radio/headset/heads/captain/alt
name = "\proper the captain's bowman headset"
desc = "The headset of the boss. Protects ears from flashbangs. \nChannels are as follows: :c - command, :s - security, :e - engineering, :u - supply, :v - service, :m - medical, :n - science."
flags = EARBANGPROTECT
icon_state = "com_headset_alt"
item_state = "com_headset_alt"
/obj/item/device/radio/headset/heads/rd
name = "\proper the research director's headset"
desc = "Headset of the fellow who keeps society marching towards technological singularity. \nTo access the science channel, use :n. For command, use :c."
icon_state = "com_headset"
keyslot = new /obj/item/device/encryptionkey/heads/rd
/obj/item/device/radio/headset/heads/hos
name = "\proper the head of security's headset"
desc = "The headset of the man in charge of keeping order and protecting the station. \nTo access the security channel, use :s. For command, use :c."
icon_state = "com_headset"
keyslot = new /obj/item/device/encryptionkey/heads/hos
/obj/item/device/radio/headset/heads/hos/alt
name = "\proper the head of security's bowman headset"
desc = "The headset of the man in charge of keeping order and protecting the station. Protects ears from flashbangs. \nTo access the security channel, use :s. For command, use :c."
flags = EARBANGPROTECT
icon_state = "com_headset_alt"
item_state = "com_headset_alt"
/obj/item/device/radio/headset/heads/ce
name = "\proper the chief engineer's headset"
desc = "The headset of the guy in charge of keeping the station powered and undamaged. \nTo access the engineering channel, use :e. For command, use :c."
icon_state = "com_headset"
keyslot = new /obj/item/device/encryptionkey/heads/ce
/obj/item/device/radio/headset/heads/cmo
name = "\proper the chief medical officer's headset"
desc = "The headset of the highly trained medical chief. \nTo access the medical channel, use :m. For command, use :c."
icon_state = "com_headset"
keyslot = new /obj/item/device/encryptionkey/heads/cmo
/obj/item/device/radio/headset/heads/hop
name = "\proper the head of personnel's headset"
desc = "The headset of the guy who will one day be captain. \nChannels are as follows: :u - supply, :v - service, :c - command."
icon_state = "com_headset"
keyslot = new /obj/item/device/encryptionkey/heads/hop
/obj/item/device/radio/headset/headset_cargo
name = "supply radio headset"
desc = "A headset used by the QM and his slaves. \nTo access the supply channel, use :u."
icon_state = "cargo_headset"
keyslot = new /obj/item/device/encryptionkey/headset_cargo
/obj/item/device/radio/headset/headset_cargo/mining
name = "mining radio headset"
desc = "Headset used by shaft miners. \nTo access the supply channel, use :u."
icon_state = "mine_headset"
/obj/item/device/radio/headset/headset_srv
name = "service radio headset"
desc = "Headset used by the service staff, tasked with keeping the station full, happy and clean. \nTo access the service channel, use :v."
icon_state = "srv_headset"
keyslot = new /obj/item/device/encryptionkey/headset_service
/obj/item/device/radio/headset/headset_cent
name = "\improper Centcom headset"
desc = "A headset used by the upper echelons of Nanotrasen. \nTo access the centcom channel, use :y."
icon_state = "cent_headset"
keyslot = new /obj/item/device/encryptionkey/headset_com
keyslot2 = new /obj/item/device/encryptionkey/headset_cent
/obj/item/device/radio/headset/headset_cent/commander
keyslot = new /obj/item/device/encryptionkey/heads/captain
/obj/item/device/radio/headset/headset_cent/alt
name = "\improper Centcom bowman headset"
desc = "A headset especially for emergency response personnel. Protects ears from flashbangs. \nTo access the centcom channel, use :y."
flags = EARBANGPROTECT
icon_state = "cent_headset_alt"
item_state = "cent_headset_alt"
keyslot = null
/obj/item/device/radio/headset/ai
name = "\proper Integrated Subspace Transceiver "
keyslot2 = new /obj/item/device/encryptionkey/ai
/obj/item/device/radio/headset/ai/receive_range(freq, level)
return ..(freq, level, 1)
/obj/item/device/radio/headset/attackby(obj/item/weapon/W, mob/user, params)
user.set_machine(src)
if(istype(W, /obj/item/weapon/screwdriver))
if(keyslot || keyslot2)
for(var/ch_name in channels)
SSradio.remove_object(src, radiochannels[ch_name])
secure_radio_connections[ch_name] = null
if(keyslot)
var/turf/T = get_turf(user)
if(T)
keyslot.loc = T
keyslot = null
if(keyslot2)
var/turf/T = get_turf(user)
if(T)
keyslot2.loc = T
keyslot2 = null
recalculateChannels()
user << "<span class='notice'>You pop out the encryption keys in the headset.</span>"
else
user << "<span class='warning'>This headset doesn't have any unique encryption keys! How useless...</span>"
else if(istype(W, /obj/item/device/encryptionkey/))
if(keyslot && keyslot2)
user << "<span class='warning'>The headset can't hold another key!</span>"
return
if(!keyslot)
if(!user.unEquip(W))
return
W.loc = src
keyslot = W
else
if(!user.unEquip(W))
return
W.loc = src
keyslot2 = W
recalculateChannels()
else
return ..()
/obj/item/device/radio/headset/recalculateChannels()
..()
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
if (keyslot2.centcom)
centcom = 1
for(var/ch_name in channels)
secure_radio_connections[ch_name] = add_radio(src, radiochannels[ch_name])
return
@@ -0,0 +1,71 @@
/obj/item/device/radio/intercom
name = "station intercom"
desc = "Talk through this."
icon_state = "intercom"
anchored = 1
w_class = 4
canhear_range = 2
var/number = 0
var/anyai = 1
var/mob/living/silicon/ai/ai = list()
var/last_tick //used to delay the powercheck
dog_fashion = null
/obj/item/device/radio/intercom/New()
..()
START_PROCESSING(SSobj, src)
/obj/item/device/radio/intercom/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/device/radio/intercom/attack_ai(mob/user)
interact(user)
/obj/item/device/radio/intercom/attack_hand(mob/user)
interact(user)
/obj/item/device/radio/intercom/interact(mob/user)
..()
ui_interact(user, state = default_state)
/obj/item/device/radio/intercom/receive_range(freq, level)
if(!on)
return -1
if(wires.is_cut(WIRE_RX))
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 == SYND_FREQ)
if(!(src.syndie))
return -1//Prevents broadcast of messages over devices lacking the encryption
return canhear_range
/obj/item/device/radio/intercom/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
if(!anyai && !(speaker in ai))
return
..()
/obj/item/device/radio/intercom/process()
if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0))
last_tick = world.timeofday
var/area/A = get_area_master(src)
if(!A || emped)
on = 0
else
on = A.powered(EQUIP) // set "on" to the power status
if(!on)
icon_state = "intercom-p"
else
icon_state = "intercom"
/obj/item/device/radio/intercom/add_blood(list/blood_dna)
return 0
@@ -0,0 +1,591 @@
/obj/item/device/radio
icon = 'icons/obj/radio.dmi'
name = "station bounced radio"
suffix = "\[3\]"
icon_state = "walkietalkie"
item_state = "walkietalkie"
dog_fashion = /datum/dog_fashion/back
var/on = 1 // 0 for off
var/last_transmission
var/frequency = 1459 //common chat
var/traitor_frequency = 0 //tune to frequency to unlock traitor supplies
var/canhear_range = 3 // the range which mobs can hear this radio from
var/obj/item/device/radio/patch_link = null
var/list/secure_radio_connections
var/prison_radio = 0
var/b_stat = 0
var/broadcasting = 0
var/listening = 1
var/translate_binary = 0
var/translate_hive = 0
var/freerange = 0 // 0 - Sanitize frequencies, 1 - Full range
var/list/channels = list() //see communications.dm for full list. First channes is a "default" for :h
var/obj/item/device/encryptionkey/keyslot //To allow the radio to accept encryption keys.
var/subspace_switchable = 0
var/subspace_transmission = 0
var/syndie = 0//Holder to see if it's a syndicate encrpyed radio
var/centcom = 0//Bleh, more dirty booleans
var/freqlock = 0 //Frequency lock to stop the user from untuning specialist radios.
var/emped = 0 //Highjacked to track the number of consecutive EMPs on the radio, allowing consecutive EMP's to stack properly.
// "Example" = FREQ_LISTENING|FREQ_BROADCASTING
flags = CONDUCT | HEAR
slot_flags = SLOT_BELT
languages_spoken = HUMAN | ROBOT
languages_understood = HUMAN | ROBOT
throw_speed = 3
throw_range = 7
w_class = 2
materials = list(MAT_METAL=75, MAT_GLASS=25)
var/const/TRANSMISSION_DELAY = 5 // only 2/second/radio
var/const/FREQ_LISTENING = 1
//FREQ_BROADCASTING = 2
var/command = FALSE //If we are speaking into a command headset, our text can be BOLD
var/use_command = FALSE
/obj/item/device/radio/proc/set_frequency(new_frequency)
remove_radio(src, frequency)
frequency = add_radio(src, new_frequency)
/obj/item/device/radio/New()
wires = new /datum/wires/radio(src)
if(prison_radio)
wires.cut(WIRE_TX) // OH GOD WHY
secure_radio_connections = new
..()
if(SSradio)
initialize()
/obj/item/device/radio/proc/recalculateChannels()
channels = list()
translate_binary = 0
translate_hive = 0
syndie = 0
centcom = 0
if(keyslot)
for(var/ch_name in keyslot.channels)
if(ch_name in src.channels)
continue
channels += ch_name
channels[ch_name] = keyslot.channels[ch_name]
if(keyslot.translate_binary)
translate_binary = 1
if(keyslot.translate_hive)
translate_hive = 1
if(keyslot.syndie)
syndie = 1
if(keyslot.centcom)
centcom = 1
for(var/ch_name in channels)
secure_radio_connections[ch_name] = add_radio(src, radiochannels[ch_name])
/obj/item/device/radio/proc/make_syndie() // Turns normal radios into Syndicate radios!
qdel(keyslot)
keyslot = new /obj/item/device/encryptionkey/syndicate
syndie = 1
recalculateChannels()
/obj/item/device/radio/Destroy()
qdel(wires)
wires = null
remove_radio_all(src) //Just to be sure
patch_link = null
keyslot = null
return ..()
/obj/item/device/radio/initialize()
frequency = sanitize_frequency(frequency, freerange)
set_frequency(frequency)
for(var/ch_name in channels)
secure_radio_connections[ch_name] = add_radio(src, radiochannels[ch_name])
/obj/item/device/radio/interact(mob/user)
if (..())
return
if(b_stat && !istype(user, /mob/living/silicon/ai))
wires.interact(user)
else
ui_interact(user)
/obj/item/device/radio/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = inventory_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "radio", name, 370, 220 + channels.len * 22, master_ui, state)
ui.open()
/obj/item/device/radio/ui_data(mob/user)
var/list/data = list()
data["broadcasting"] = broadcasting
data["listening"] = listening
data["frequency"] = frequency
data["minFrequency"] = freerange ? MIN_FREE_FREQ : MIN_FREQ
data["maxFrequency"] = freerange ? MAX_FREE_FREQ : MAX_FREQ
data["freqlock"] = freqlock
data["channels"] = list()
for(var/channel in channels)
data["channels"][channel] = channels[channel] & FREQ_LISTENING
data["command"] = command
data["useCommand"] = use_command
data["subspace"] = subspace_transmission
data["subspaceSwitchable"] = subspace_switchable
data["headset"] = istype(src, /obj/item/device/radio/headset)
return data
/obj/item/device/radio/ui_act(action, params, datum/tgui/ui)
if(..())
return
switch(action)
if("frequency")
if(freqlock)
return
var/tune = params["tune"]
var/adjust = text2num(params["adjust"])
if(tune == "input")
var/min = format_frequency(freerange ? MIN_FREE_FREQ : MIN_FREQ)
var/max = format_frequency(freerange ? MAX_FREE_FREQ : MAX_FREQ)
tune = input("Tune frequency ([min]-[max]):", name, format_frequency(frequency)) as null|num
if(!isnull(tune) && !..())
. = TRUE
else if(adjust)
tune = frequency + adjust * 10
. = TRUE
else if(text2num(tune) != null)
tune = tune * 10
. = TRUE
if(.)
frequency = sanitize_frequency(tune, freerange)
set_frequency(frequency)
if(frequency == traitor_frequency && hidden_uplink)
hidden_uplink.interact(usr)
ui.close()
if("listen")
listening = !listening
. = TRUE
if("broadcast")
broadcasting = !broadcasting
. = TRUE
if("channel")
var/channel = params["channel"]
if(!(channel in channels))
return
if(channels[channel] & FREQ_LISTENING)
channels[channel] &= ~FREQ_LISTENING
else
channels[channel] |= FREQ_LISTENING
. = TRUE
if("command")
use_command = !use_command
. = TRUE
if("subspace")
if(subspace_switchable)
subspace_transmission = !subspace_transmission
if(!subspace_transmission)
channels = list()
else
recalculateChannels()
. = TRUE
/obj/item/device/radio/talk_into(atom/movable/M, message, channel, list/spans)
if(!on) return // the device has to be on
// Fix for permacell radios, but kinda eh about actually fixing them.
if(!M || !message) return
if(wires.is_cut(WIRE_TX))
return
if(!M.IsVocal())
return
if(use_command)
spans |= SPAN_COMMAND
/* Quick introduction:
This new radio system uses a very robust FTL signaling technology unoriginally
dubbed "subspace" which is somewhat similar to 'blue-space' but can't
actually transmit large mass. Headsets are the only radio devices capable
of sending subspace transmissions to the Communications Satellite.
A headset sends a signal to a subspace listener/reciever elsewhere in space,
the signal gets processed and logged, and an audible transmission gets sent
to each individual headset.
*/
/*
be prepared to disregard any comments in all of tcomms code. i tried my best to keep them somewhat up-to-date, but eh
*/
//get the frequency you buttface. radios no longer use the SSradio. confusing for future generations, convenient for me.
var/freq
if(channel && channels && channels.len > 0)
if(channel == "department")
channel = channels[1]
freq = secure_radio_connections[channel]
if (!channels[channel]) // if the channel is turned off, don't broadcast
return
else
freq = frequency
channel = null
var/freqnum = text2num(freq) //Why should we call text2num three times when we can just do it here?
var/turf/position = get_turf(src)
//#### Tagging the signal with all appropriate identity values ####//
// ||-- The mob's name identity --||
var/real_name = M.name // mob's real name
var/mobkey = "none" // player key associated with mob
var/voicemask = 0 // the speaker is wearing a voice mask
var/voice = M.GetVoice() // Why reinvent the wheel when there is a proc that does nice things already
if(ismob(M))
var/mob/speaker = M
real_name = speaker.real_name
if(speaker.client)
mobkey = speaker.key // assign the mob's key
var/jobname // the mob's "job"
// --- Human: use their job as seen on the crew manifest - makes it unneeded to carry an ID for an AI to see their job
if(ishuman(M))
var/datum/data/record/findjob = find_record("name", voice, data_core.general)
if(voice != real_name)
voicemask = 1
if(findjob)
jobname = findjob.fields["rank"]
else
jobname = "Unknown"
// --- Carbon Nonhuman ---
else if(iscarbon(M)) // Nonhuman carbon mob
jobname = "No id"
// --- AI ---
else if(isAI(M))
jobname = "AI"
// --- Cyborg ---
else if(isrobot(M))
var/mob/living/silicon/robot/B = M
jobname = "[B.designation] Cyborg"
// --- Personal AI (pAI) ---
else if(istype(M, /mob/living/silicon/pai))
jobname = "Personal AI"
// --- Cold, emotionless machines. ---
else if(isobj(M))
jobname = "Machine"
// --- Unidentifiable mob ---
else
jobname = "Unknown"
/* ###### Centcom channel bypasses all comms relays. ###### */
if (freqnum == CENTCOM_FREQ && centcom)
var/datum/signal/signal = new
signal.transmission_method = 2
signal.data = list(
"mob" = M, // store a reference to the mob
"mobtype" = M.type, // the mob's type
"realname" = real_name, // the mob's real name
"name" = voice, // the mob's voice name
"job" = jobname, // the mob's job
"key" = mobkey, // the mob's key
"vmask" = voicemask, // 1 if the mob is using a voice gas mas
"compression" = 0, // uncompressed radio signal
"message" = message, // the actual sent message
"radio" = src, // stores the radio used for transmission
"slow" = 0,
"traffic" = 0,
"type" = 0,
"server" = null,
"reject" = 0,
"level" = 0,
"languages" = languages_spoken,
"spans" = spans,
"verb_say" = M.verb_say,
"verb_ask" = M.verb_ask,
"verb_exclaim" = M.verb_exclaim,
"verb_yell" = M.verb_yell
)
signal.frequency = freqnum // Quick frequency set
Broadcast_Message(M, voicemask,
src, message, voice, jobname, real_name,
5, signal.data["compression"], list(position.z, 0), freq, spans,
verb_say, verb_ask, verb_exclaim, verb_yell)
return
/* ###### Radio headsets can only broadcast through subspace ###### */
if(subspace_transmission)
// First, we want to generate a new radio signal
var/datum/signal/signal = new
signal.transmission_method = 2 // 2 would be a subspace transmission.
// transmission_method could probably be enumerated through #define. Would be neater.
// --- Finally, tag the actual signal with the appropriate values ---
signal.data = list(
// Identity-associated tags:
"mob" = M, // store a reference to the mob
"mobtype" = M.type, // the mob's type
"realname" = real_name, // the mob's real name
"name" = voice, // the mob's voice name
"job" = jobname, // the mob's job
"key" = mobkey, // the mob's key
"vmask" = voicemask, // 1 if the mob is using a voice gas mask
// We store things that would otherwise be kept in the actual mob
// so that they can be logged even AFTER the mob is deleted or something
// Other tags:
"compression" = rand(35,65), // compressed radio signal
"message" = message, // the actual sent message
"radio" = src, // stores the radio used for transmission
"slow" = 0, // how much to sleep() before broadcasting - simulates net lag
"traffic" = 0, // dictates the total traffic sum that the signal went through
"type" = 0, // determines what type of radio input it is: normal broadcast
"server" = null, // the last server to log this signal
"reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery
"level" = position.z, // The source's z level
"languages" = M.languages_spoken, //The languages M is talking in.
"spans" = spans, //the span classes of this message.
"verb_say" = M.verb_say, //the verb used when talking normally
"verb_ask" = M.verb_ask, //the verb used when asking
"verb_exclaim" = M.verb_exclaim, //the verb used when exclaiming
"verb_yell" = M.verb_yell //the verb used when yelling
)
signal.frequency = freq
//#### Sending the signal to all subspace receivers ####//
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
// Allinone can act as receivers.
for(var/obj/machinery/telecomms/allinone/R in telecomms_list)
R.receive_signal(signal)
// Receiving code can be located in Telecommunications.dm
return
/* ###### Intercoms and station-bounced radios ###### */
var/filter_type = 2
var/datum/signal/signal = new
signal.transmission_method = 2
/* --- Try to send a normal subspace broadcast first */
signal.data = list(
"mob" = M, // store a reference to the mob
"mobtype" = M.type, // the mob's type
"realname" = real_name, // the mob's real name
"name" = voice, // the mob's voice name
"job" = jobname, // the mob's job
"key" = mobkey, // the mob's key
"vmask" = voicemask, // 1 if the mob is using a voice gas mas
"compression" = 0, // uncompressed radio signal
"message" = message, // the actual sent message
"radio" = src, // stores the radio used for transmission
"slow" = 0,
"traffic" = 0,
"type" = 0,
"server" = null,
"reject" = 0,
"level" = position.z,
"languages" = languages_spoken,
"spans" = spans,
"verb_say" = M.verb_say,
"verb_ask" = M.verb_ask,
"verb_exclaim" = M.verb_exclaim,
"verb_yell" = M.verb_yell
)
signal.frequency = freqnum // Quick frequency set
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
spawn(20) // wait a little...
if(signal.data["done"] && position.z in signal.data["level"])
// we're done here.
return
// Oh my god; the comms are down or something because the signal hasn't been broadcasted yet in our level.
// Send a mundane broadcast with limited targets:
Broadcast_Message(M, voicemask,
src, message, voice, jobname, real_name,
filter_type, signal.data["compression"], list(position.z), freq, spans,
verb_say, verb_ask, verb_exclaim, verb_yell)
/obj/item/device/radio/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans)
if(radio_freq)
return
if(broadcasting)
if(get_dist(src, speaker) <= canhear_range)
talk_into(speaker, raw_message, , spans)
/*
/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message)
if ((R.frequency == frequency && message))
return 1
else if
else
return null
return
*/
/obj/item/device/radio/proc/receive_range(freq, level)
// check if this radio can receive on the given frequency, and if so,
// what the range is in which mobs will hear the radio
// returns: -1 if can't receive, range otherwise
if (wires.is_cut(WIRE_RX))
return -1
if(!listening)
return -1
if(!(0 in level))
var/turf/position = get_turf(src)
if(!position || !(position.z in level))
return -1
if(freq == SYND_FREQ)
if(!(src.syndie)) //Checks to see if it's allowed on that frequency, based on the encryption keys
return -1
if(freq == CENTCOM_FREQ)
if (!(src.centcom))
return -1
if (!on)
return -1
if (!freq) //received on main frequency
if (!listening)
return -1
else
var/accept = (freq==frequency && listening)
if (!accept)
for(var/ch_name in channels)
if(channels[ch_name] & FREQ_LISTENING)
if(radiochannels[ch_name] == text2num(freq) || syndie) //the radiochannels list is located in communications.dm
accept = 1
break
if (!accept)
return -1
return canhear_range
/obj/item/device/radio/proc/send_hear(freq, level)
var/range = receive_range(freq, level)
if(range > -1)
return get_hearers_in_view(canhear_range, src)
/obj/item/device/radio/examine(mob/user)
..()
if (b_stat)
user << "<span class='notice'>[name] can be attached and modified.</span>"
else
user << "<span class='notice'>[name] can not be modified or attached.</span>"
/obj/item/device/radio/attackby(obj/item/weapon/W, mob/user, params)
add_fingerprint(user)
if(istype(W, /obj/item/weapon/screwdriver))
b_stat = !b_stat
if(b_stat)
user << "<span class='notice'>The radio can now be attached and modified!</span>"
else
user << "<span class='notice'>The radio can no longer be modified or attached!</span>"
else
return ..()
/obj/item/device/radio/emp_act(severity)
emped++ //There's been an EMP; better count it
var/curremp = emped //Remember which EMP this was
if (listening && ismob(loc)) // if the radio is turned on and on someone's person they notice
loc << "<span class='warning'>\The [src] overloads.</span>"
broadcasting = 0
listening = 0
for (var/ch_name in channels)
channels[ch_name] = 0
on = 0
spawn(200)
if(emped == curremp) //Don't fix it if it's been EMP'd again
emped = 0
if (!istype(src, /obj/item/device/radio/intercom)) // intercoms will turn back on on their own
on = 1
..()
///////////////////////////////
//////////Borg Radios//////////
///////////////////////////////
//Giving borgs their own radio to have some more room to work with -Sieve
/obj/item/device/radio/borg
name = "cyborg radio"
subspace_switchable = 1
dog_fashion = null
/obj/item/device/radio/borg/syndicate
syndie = 1
keyslot = new /obj/item/device/encryptionkey/syndicate
/obj/item/device/radio/borg/syndicate/New()
..()
set_frequency(SYND_FREQ)
/obj/item/device/radio/borg/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/screwdriver))
if(keyslot)
for(var/ch_name in channels)
SSradio.remove_object(src, radiochannels[ch_name])
secure_radio_connections[ch_name] = null
if(keyslot)
var/turf/T = get_turf(user)
if(T)
keyslot.loc = T
keyslot = null
recalculateChannels()
user << "<span class='notice'>You pop out the encryption key in the radio.</span>"
else
user << "<span class='warning'>This radio doesn't have any encryption keys!</span>"
else if(istype(W, /obj/item/device/encryptionkey/))
if(keyslot)
user << "<span class='warning'>The radio can't hold another key!</span>"
return
if(!keyslot)
if(!user.unEquip(W))
return
W.loc = src
keyslot = W
recalculateChannels()
/obj/item/device/radio/off // Station bounced radios, their only difference is spawning with the speakers off, this was made to help the lag.
listening = 0 // And it's nice to have a subtype too for future features.
dog_fashion = /datum/dog_fashion/back
+423
View File
@@ -0,0 +1,423 @@
/*
CONTAINS:
T-RAY
DETECTIVE SCANNER
HEALTH ANALYZER
GAS ANALYZER
MASS SPECTROMETER
*/
/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"
var/on = 0
slot_flags = SLOT_BELT
w_class = 2
item_state = "electronic"
materials = list(MAT_METAL=150)
origin_tech = "magnets=1;engineering=1"
/obj/item/device/t_scanner/attack_self(mob/user)
on = !on
icon_state = copytext(icon_state, 1, length(icon_state))+"[on]"
if(on)
START_PROCESSING(SSobj, src)
/obj/item/device/t_scanner/proc/flick_sonar(obj/pipe)
var/image/I = image('icons/effects/effects.dmi', pipe, "blip", pipe.layer+1)
I.alpha = 128
var/list/nearby = list()
for(var/mob/M in viewers(pipe))
if(M.client)
nearby |= M.client
flick_overlay(I,nearby,8)
/obj/item/device/t_scanner/process()
if(!on)
STOP_PROCESSING(SSobj, src)
return null
scan()
/obj/item/device/t_scanner/proc/scan()
for(var/turf/T in range(2, src.loc) )
for(var/obj/O in T.contents)
if(O.level != 1)
continue
var/mob/living/L = locate() in O
if(O.invisibility == INVISIBILITY_MAXIMUM)
O.invisibility = 0
if(L)
flick_sonar(O)
spawn(10)
if(O && O.loc)
var/turf/U = O.loc
if(U.intact)
O.invisibility = INVISIBILITY_MAXIMUM
else
if(L)
flick_sonar(O)
/obj/item/device/healthanalyzer
name = "health analyzer"
icon_state = "health"
item_state = "analyzer"
desc = "A hand-held body scanner able to distinguish vital signs of the subject."
flags = CONDUCT | NOBLUDGEON
slot_flags = SLOT_BELT
throwforce = 3
w_class = 1
throw_speed = 3
throw_range = 7
materials = list(MAT_METAL=200)
origin_tech = "magnets=1;biotech=1"
var/mode = 1
var/scanmode = 0
/obj/item/device/healthanalyzer/attack_self(mob/user)
if(!scanmode)
user << "<span class='notice'>You switch the health analyzer to scan chemical contents.</span>"
scanmode = 1
else
user << "<span class='notice'>You switch the health analyzer to check physical health.</span>"
scanmode = 0
/obj/item/device/healthanalyzer/attack(mob/living/M, mob/living/carbon/human/user)
// Clumsiness/brain damage check
if ((user.disabilities & CLUMSY || user.getBrainLoss() >= 60) && prob(50))
user << "<span class='notice'>You stupidly try to analyze the floor's vitals!</span>"
user.visible_message("<span class='warning'>[user] has analyzed the floor's vitals!</span>")
user << "<span class='info'>Analyzing results for The floor:\n\tOverall status: <b>Healthy</b>"
user << "<span class='info'>Key: <font color='blue'>Suffocation</font>/<font color='green'>Toxin</font>/<font color='#FF8000'>Burn</font>/<font color='red'>Brute</font></span>"
user << "<span class='info'>\tDamage specifics: <font color='blue'>0</font>-<font color='green'>0</font>-<font color='#FF8000'>0</font>-<font color='red'>0</font></span>"
user << "<span class='info'>Body temperature: ???</span>"
return
user.visible_message("<span class='notice'>[user] has analyzed [M]'s vitals.</span>")
if(scanmode == 0)
healthscan(user, M, mode)
else if(scanmode == 1)
chemscan(user, M)
add_fingerprint(user)
// Used by the PDA medical scanner too
/proc/healthscan(mob/living/user, mob/living/M, mode = 1)
if(user.stat || user.eye_blind)
return
//Damage specifics
var/oxy_loss = M.getOxyLoss()
var/tox_loss = M.getToxLoss()
var/fire_loss = M.getFireLoss()
var/brute_loss = M.getBruteLoss()
var/mob_status = (M.stat > 1 ? "<span class='alert'><b>Deceased</b></span>" : "<b>[round(M.health/M.maxHealth,0.01)*100] % healthy</b>")
if(M.status_flags & FAKEDEATH)
mob_status = "<span class='alert'>Deceased</span>"
oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.heart_attack && H.stat != DEAD)
user << "<span class='danger'>Subject suffering from heart attack: Apply defibrillator immediately!</span>"
user << "<span class='info'>Analyzing results for [M]:\n\tOverall status: [mob_status]</span>"
// Damage descriptions
if(brute_loss > 10)
user << "\t<span class='alert'>[brute_loss > 50 ? "Severe" : "Minor"] tissue damage detected.</span>"
if(fire_loss > 10)
user << "\t<span class='alert'>[fire_loss > 50 ? "Severe" : "Minor"] burn damage detected.</span>"
if(oxy_loss > 10)
user << "\t<span class='info'><span class='alert'>[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected.</span>"
if(tox_loss > 10)
user << "\t<span class='alert'>[tox_loss > 50 ? "Critical" : "Dangerous"] amount of toxins detected.</span>"
if(M.getStaminaLoss())
user << "\t<span class='alert'>Subject appears to be suffering from fatigue.</span>"
if (M.getCloneLoss())
user << "\t<span class='alert'>Subject appears to have [M.getCloneLoss() > 30 ? "severe" : "minor"] cellular damage.</span>"
if (M.reagents && M.reagents.get_reagent_amount("epinephrine"))
user << "\t<span class='info'>Bloodstream analysis located [M.reagents:get_reagent_amount("epinephrine")] units of rejuvenation chemicals.</span>"
if (M.getBrainLoss() >= 100 || !M.getorgan(/obj/item/organ/brain))
user << "\t<span class='alert'>Subject brain function is non-existent.</span>"
else if (M.getBrainLoss() >= 60)
user << "\t<span class='alert'>Severe brain damage detected. Subject likely to have mental retardation.</span>"
else if (M.getBrainLoss() >= 10)
user << "\t<span class='alert'>Brain damage detected. Subject may have had a concussion.</span>"
// Organ damage report
if(istype(M, /mob/living/carbon/human) && mode == 1)
var/mob/living/carbon/human/H = M
var/list/damaged = H.get_damaged_bodyparts(1,1)
if(length(damaged)>0 || oxy_loss>0 || tox_loss>0 || fire_loss>0)
user << "<span class='info'>\tDamage: <span class='info'><font color='red'>Brute</font></span>-<font color='#FF8000'>Burn</font>-<font color='green'>Toxin</font>-<font color='blue'>Suffocation</font>\n\t\tSpecifics: <font color='red'>[brute_loss]</font>-<font color='#FF8000'>[fire_loss]</font>-<font color='green'>[tox_loss]</font>-<font color='blue'>[oxy_loss]</font></span>"
for(var/obj/item/bodypart/org in damaged)
user << "\t\t<span class='info'>[capitalize(org.name)]: [(org.brute_dam > 0) ? "<font color='red'>[org.brute_dam]</font></span>" : "<font color='red'>0</font>"]-[(org.burn_dam > 0) ? "<font color='#FF8000'>[org.burn_dam]</font>" : "<font color='#FF8000'>0</font>"]"
// Species and body temperature
if(ishuman(M))
var/mob/living/carbon/human/H = M
user << "<span class='info'>Species: [H.dna.species.name]</span>"
user << "<span class='info'>Body temperature: [round(M.bodytemperature-T0C,0.1)] &deg;C ([round(M.bodytemperature*1.8-459.67,0.1)] &deg;F)</span>"
// Time of death
if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH)))
user << "<span class='info'>Time of Death:</span> [M.tod]"
var/tdelta = round(world.time - M.timeofdeath)
if(tdelta < (DEFIB_TIME_LIMIT * 10))
user << "<span class='danger'>Subject died [tdelta / 10] seconds \
ago, defibrillation may be possible!</span>"
for(var/datum/disease/D in M.viruses)
if(!(D.visibility_flags & HIDDEN_SCANNER))
user << "<span class='alert'><b>Warning: [D.form] detected</b>\nName: [D.name].\nType: [D.spread_text].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure_text]</span>"
// Blood Level
if(M.has_dna())
var/mob/living/carbon/C = M
var/blood_id = C.get_blood_id()
if(blood_id)
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(H.bleed_rate)
user << "<span class='danger'>Subject is bleeding!</span>"
var/blood_percent = round((C.blood_volume / BLOOD_VOLUME_NORMAL)*100)
var/blood_type = C.dna.blood_type
if(blood_id != "blood")//special blood substance
blood_type = blood_id
if(C.blood_volume <= BLOOD_VOLUME_SAFE && C.blood_volume > BLOOD_VOLUME_OKAY)
user << "<span class='danger'>LOW blood level [blood_percent] %, [C.blood_volume] cl,</span> <span class='info'>type: [blood_type]</span>"
else if(C.blood_volume <= BLOOD_VOLUME_OKAY)
user << "<span class='danger'>CRITICAL blood level [blood_percent] %, [C.blood_volume] cl,</span> <span class='info'>type: [blood_type]</span>"
else
user << "<span class='info'>Blood level [blood_percent] %, [C.blood_volume] cl, type: [blood_type]</span>"
var/implant_detect
for(var/obj/item/organ/cyberimp/CI in C.internal_organs)
if(CI.status == ORGAN_ROBOTIC)
implant_detect += "[C.name] is modified with a [CI.name].<br>"
if(implant_detect)
user << "<span class='notice'>Detected cybernetic modifications:</span>"
user << "<span class='notice'>[implant_detect]</span>"
/proc/chemscan(mob/living/user, mob/living/M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.reagents)
if(H.reagents.reagent_list.len)
user << "<span class='notice'>Subject contains the following reagents:</span>"
for(var/datum/reagent/R in H.reagents.reagent_list)
user << "<span class='notice'>[R.volume] units of [R.name][R.overdosed == 1 ? "</span> - <span class='boldannounce'>OVERDOSING</span>" : ".</span>"]"
else
user << "<span class='notice'>Subject contains no reagents.</span>"
if(H.reagents.addiction_list.len)
user << "<span class='boldannounce'>Subject is addicted to the following reagents:</span>"
for(var/datum/reagent/R in H.reagents.addiction_list)
user << "<span class='danger'>[R.name]</span>"
else
user << "<span class='notice'>Subject is not addicted to any reagents.</span>"
/obj/item/device/healthanalyzer/verb/toggle_mode()
set name = "Switch Verbosity"
set category = "Object"
if(usr.stat || !usr.canmove || usr.restrained())
return
mode = !mode
switch (mode)
if(1)
usr << "The scanner now shows specific limb damage."
if(0)
usr << "The scanner no longer shows limb damage."
/obj/item/device/analyzer
desc = "A hand-held environmental scanner which reports current gas levels."
name = "analyzer"
icon_state = "atmos"
item_state = "analyzer"
w_class = 2
flags = CONDUCT | NOBLUDGEON
slot_flags = SLOT_BELT
throwforce = 0
throw_speed = 3
throw_range = 7
materials = list(MAT_METAL=30, MAT_GLASS=20)
origin_tech = "magnets=1;engineering=1"
/obj/item/device/analyzer/attack_self(mob/user)
add_fingerprint(user)
if (user.stat || user.eye_blind)
return
var/turf/location = user.loc
if(!istype(location))
return
var/datum/gas_mixture/environment = location.return_air()
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
user << "<span class='info'><B>Results:</B></span>"
if(abs(pressure - ONE_ATMOSPHERE) < 10)
user << "<span class='info'>Pressure: [round(pressure,0.1)] kPa</span>"
else
user << "<span class='alert'>Pressure: [round(pressure,0.1)] kPa</span>"
if(total_moles)
var/list/env_gases = environment.gases
environment.assert_gases(arglist(hardcoded_gases))
var/o2_concentration = env_gases["o2"][MOLES]/total_moles
var/n2_concentration = env_gases["n2"][MOLES]/total_moles
var/co2_concentration = env_gases["co2"][MOLES]/total_moles
var/plasma_concentration = env_gases["plasma"][MOLES]/total_moles
environment.garbage_collect()
if(abs(n2_concentration - N2STANDARD) < 20)
user << "<span class='info'>Nitrogen: [round(n2_concentration*100, 0.01)] %</span>"
else
user << "<span class='alert'>Nitrogen: [round(n2_concentration*100, 0.01)] %</span>"
if(abs(o2_concentration - O2STANDARD) < 2)
user << "<span class='info'>Oxygen: [round(o2_concentration*100, 0.01)] %</span>"
else
user << "<span class='alert'>Oxygen: [round(o2_concentration*100, 0.01)] %</span>"
if(co2_concentration > 0.01)
user << "<span class='alert'>CO2: [round(co2_concentration*100, 0.01)] %</span>"
else
user << "<span class='info'>CO2: [round(co2_concentration*100, 0.01)] %</span>"
if(plasma_concentration > 0.005)
user << "<span class='alert'>Plasma: [round(plasma_concentration*100, 0.01)] %</span>"
else
user << "<span class='info'>Plasma: [round(plasma_concentration*100, 0.01)] %</span>"
for(var/id in env_gases)
if(id in hardcoded_gases)
continue
var/gas_concentration = env_gases[id][MOLES]/total_moles
user << "<span class='alert'>[env_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_concentration*100, 0.01)] %</span>"
user << "<span class='info'>Temperature: [round(environment.temperature-T0C)] &deg;C</span>"
/obj/item/device/mass_spectrometer
desc = "A hand-held mass spectrometer which identifies trace chemicals in a blood sample."
name = "mass-spectrometer"
icon_state = "spectrometer"
item_state = "analyzer"
w_class = 2
flags = CONDUCT | OPENCONTAINER
slot_flags = SLOT_BELT
throwforce = 0
throw_speed = 3
throw_range = 7
materials = list(MAT_METAL=150, MAT_GLASS=100)
origin_tech = "magnets=2;biotech=1;plasmatech=2"
var/details = 0
/obj/item/device/mass_spectrometer/New()
..()
create_reagents(5)
/obj/item/device/mass_spectrometer/on_reagent_change()
if(reagents.total_volume)
icon_state = initial(icon_state) + "_s"
else
icon_state = initial(icon_state)
/obj/item/device/mass_spectrometer/attack_self(mob/user)
if (user.stat || user.eye_blind)
return
if (!user.IsAdvancedToolUser())
user << "<span class='warning'>You don't have the dexterity to do this!</span>"
return
if(reagents.total_volume)
var/list/blood_traces = list()
for(var/datum/reagent/R in reagents.reagent_list)
if(R.id != "blood")
reagents.clear_reagents()
user << "<span class='warning'>The sample was contaminated! Please insert another sample.</span>"
return
else
blood_traces = params2list(R.data["trace_chem"])
break
var/dat = "<i><b>Trace Chemicals Found:</b>"
if(!blood_traces.len)
dat += "<br>None"
else
for(var/R in blood_traces)
dat += "<br>[chemical_reagents_list[R]]"
if(details)
dat += " ([blood_traces[R]] units)"
dat += "</i>"
user << dat
reagents.clear_reagents()
/obj/item/device/mass_spectrometer/adv
name = "advanced mass-spectrometer"
icon_state = "adv_spectrometer"
details = 1
origin_tech = "magnets=4;biotech=3;plasmatech=3"
/obj/item/device/slime_scanner
name = "slime scanner"
desc = "A device that analyzes a slime's internal composition and measures its stats."
icon_state = "adv_spectrometer"
item_state = "analyzer"
origin_tech = "biotech=2"
w_class = 2
flags = CONDUCT
throwforce = 0
throw_speed = 3
throw_range = 7
materials = list(MAT_METAL=30, MAT_GLASS=20)
/obj/item/device/slime_scanner/attack(mob/living/M, mob/living/user)
if(user.stat || user.eye_blind)
return
if (!isslime(M))
user << "<span class='warning'>This device can only scan slimes!</span>"
return
var/mob/living/simple_animal/slime/T = M
user << "Slime scan results:"
user << "[T.colour] [T.is_adult ? "adult" : "baby"] slime"
user << "Nutrition: [T.nutrition]/[T.get_max_nutrition()]"
if (T.nutrition < T.get_starve_nutrition())
user << "<span class='warning'>Warning: slime is starving!</span>"
else if (T.nutrition < T.get_hunger_nutrition())
user << "<span class='warning'>Warning: slime is hungry</span>"
user << "Electric change strength: [T.powerlevel]"
user << "Health: [round(T.health/T.maxHealth,0.01)*100]"
if (T.slime_mutation[4] == T.colour)
user << "This slime does not evolve any further."
else
if (T.slime_mutation[3] == T.slime_mutation[4])
if (T.slime_mutation[2] == T.slime_mutation[1])
user << "Possible mutation: [T.slime_mutation[3]]"
user << "Genetic destability: [T.mutation_chance/2] % chance of mutation on splitting"
else
user << "Possible mutations: [T.slime_mutation[1]], [T.slime_mutation[2]], [T.slime_mutation[3]] (x2)"
user << "Genetic destability: [T.mutation_chance] % chance of mutation on splitting"
else
user << "Possible mutations: [T.slime_mutation[1]], [T.slime_mutation[2]], [T.slime_mutation[3]], [T.slime_mutation[4]]"
user << "Genetic destability: [T.mutation_chance] % chance of mutation on splitting"
if (T.cores > 1)
user << "Anomalious slime core amount detected"
user << "Growth progress: [T.amount_grown]/[SLIME_EVOLUTION_THRESHOLD]"
@@ -0,0 +1,11 @@
/obj/item/device/sensor_device
name = "handheld crew monitor" //Thanks to Gun Hog for the name!
desc = "A miniature machine that tracks suit sensors across the station."
icon = 'icons/obj/device.dmi'
icon_state = "scanner"
w_class = 2
slot_flags = SLOT_BELT
origin_tech = "programming=3;materials=3;magnets=3"
/obj/item/device/sensor_device/attack_self(mob/user)
crewmonitor.show(user) //Proc already exists, just had to call it
@@ -0,0 +1,280 @@
/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 = 2
flags = HEAR
slot_flags = SLOT_BELT
languages_spoken = ALL //this is a translator, after all.
languages_understood = ALL //this is a translator, after all.
materials = list(MAT_METAL=60, MAT_GLASS=30)
force = 2
throwforce = 0
var/recording = 0
var/playing = 0
var/playsleepseconds = 0
var/obj/item/device/tape/mytape
var/open_panel = 0
var/canprint = 1
/obj/item/device/taperecorder/New()
mytape = new /obj/item/device/tape/random(src)
update_icon()
/obj/item/device/taperecorder/examine(mob/user)
..()
user << "The wire panel is [open_panel ? "opened" : "closed"]."
/obj/item/device/taperecorder/attackby(obj/item/I, mob/user, params)
if(!mytape && istype(I, /obj/item/device/tape))
if(!user.unEquip(I))
return
I.loc = src
mytape = I
user << "<span class='notice'>You insert [I] into [src].</span>"
update_icon()
/obj/item/device/taperecorder/proc/eject(mob/user)
if(mytape)
user << "<span class='notice'>You remove [mytape] from [src].</span>"
stop()
user.put_in_hands(mytape)
mytape = null
update_icon()
/obj/item/device/taperecorder/fire_act()
mytape.ruin() //Fires destroy the tape
return()
/obj/item/device/taperecorder/attack_hand(mob/user)
if(loc == user)
if(mytape)
if(user.l_hand != src && user.r_hand != src)
..()
return
eject(user)
return
..()
/obj/item/device/taperecorder/proc/can_use(mob/user)
if(user && ismob(user))
if(!user.incapacitated())
return 1
return 0
/obj/item/device/taperecorder/verb/ejectverb()
set name = "Eject Tape"
set category = "Object"
if(!can_use(usr))
return
if(!mytape)
return
eject(usr)
/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/taperecorder/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans)
if(mytape && recording)
mytape.timestamp += mytape.used_capacity
mytape.storedinfo += "\[[time2text(mytape.used_capacity * 10,"mm:ss")]\] [message]"
/obj/item/device/taperecorder/verb/record()
set name = "Start Recording"
set category = "Object"
if(!can_use(usr))
return
if(!mytape || mytape.ruined)
return
if(recording)
return
if(playing)
return
if(mytape.used_capacity < mytape.max_capacity)
usr << "<span class='notice'>Recording started.</span>"
recording = 1
update_icon()
mytape.timestamp += mytape.used_capacity
mytape.storedinfo += "\[[time2text(mytape.used_capacity * 10,"mm:ss")]\] Recording started."
var/used = mytape.used_capacity //to stop runtimes when you eject the tape
var/max = mytape.max_capacity
for(used, used < max)
if(recording == 0)
break
mytape.used_capacity++
used++
sleep(10)
recording = 0
update_icon()
else
usr << "<span class='notice'>The tape is full.</span>"
/obj/item/device/taperecorder/verb/stop()
set name = "Stop"
set category = "Object"
if(!can_use(usr))
return
if(recording)
recording = 0
mytape.timestamp += mytape.used_capacity
mytape.storedinfo += "\[[time2text(mytape.used_capacity * 10,"mm:ss")]\] Recording stopped."
usr << "<span class='notice'>Recording stopped.</span>"
return
else if(playing)
playing = 0
var/turf/T = get_turf(src)
T.visible_message("<font color=Maroon><B>Tape Recorder</B>: Playback stopped.</font>")
update_icon()
/obj/item/device/taperecorder/verb/play()
set name = "Play Tape"
set category = "Object"
if(!can_use(usr))
return
if(!mytape || mytape.ruined)
return
if(recording)
return
if(playing)
return
playing = 1
update_icon()
usr << "<span class='notice'>Playing started.</span>"
var/used = mytape.used_capacity //to stop runtimes when you eject the tape
var/max = mytape.max_capacity
for(var/i = 1, used < max, sleep(10 * playsleepseconds))
if(!mytape)
break
if(playing == 0)
break
if(mytape.storedinfo.len < i)
break
say(mytape.storedinfo[i])
if(mytape.storedinfo.len < i + 1)
playsleepseconds = 1
sleep(10)
say("End of recording.")
else
playsleepseconds = mytape.timestamp[i + 1] - mytape.timestamp[i]
if(playsleepseconds > 14)
sleep(10)
say("Skipping [playsleepseconds] seconds of silence")
playsleepseconds = 1
i++
playing = 0
update_icon()
/obj/item/device/taperecorder/attack_self(mob/user)
if(!mytape || mytape.ruined)
return
if(recording)
stop()
else
record()
/obj/item/device/taperecorder/verb/print_transcript()
set name = "Print Transcript"
set category = "Object"
if(!can_use(usr))
return
if(!mytape)
return
if(!canprint)
usr << "<span class='notice'>The recorder can't print that fast!</span>"
return
if(recording || playing)
return
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++)
t1 += "[mytape.storedinfo[i]]<BR>"
P.info = t1
P.name = "paper- 'Transcript'"
usr.put_in_hands(P)
canprint = 0
sleep(300)
canprint = 1
//empty tape recorders
/obj/item/device/taperecorder/empty/New()
return
/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 = 1
materials = list(MAT_METAL=20, MAT_GLASS=5)
force = 1
throwforce = 0
var/max_capacity = 600
var/used_capacity = 0
var/list/storedinfo = list()
var/list/timestamp = list()
var/ruined = 0
/obj/item/device/tape/fire_act()
ruin()
/obj/item/device/tape/attack_self(mob/user)
if(!ruined)
user << "<span class='notice'>You pull out all the tape!</span>"
ruin()
/obj/item/device/tape/proc/ruin()
add_overlay("ribbonoverlay")
ruined = 1
/obj/item/device/tape/proc/fix()
overlays -= "ribbonoverlay"
ruined = 0
/obj/item/device/tape/attackby(obj/item/I, mob/user, params)
if(ruined && istype(I, /obj/item/weapon/screwdriver))
user << "<span class='notice'>You start winding the tape back in...</span>"
if(do_after(user, 120/I.toolspeed, target = src))
user << "<span class='notice'>You wound the tape back in.</span>"
fix()
//Random colour tapes
/obj/item/device/tape/random/New()
icon_state = "tape_[pick("white", "blue", "red", "yellow", "purple")]"
@@ -0,0 +1,225 @@
/*
Miscellaneous traitor devices
BATTERER
RADIOACTIVE MICROLASER
*/
/*
The Batterer, like a flashbang but 50% chance to knock people over. Can be either very
effective or pretty fucking useless.
*/
/obj/item/device/batterer
name = "mind batterer"
desc = "A strange device with twin antennas."
icon_state = "batterer"
throwforce = 5
w_class = 1
throw_speed = 3
throw_range = 7
flags = CONDUCT
item_state = "electronic"
origin_tech = "magnets=3;combat=3;syndicate=3"
var/times_used = 0 //Number of times it's been used.
var/max_uses = 2
/obj/item/device/batterer/attack_self(mob/living/carbon/user, flag = 0, emp = 0)
if(!user) return
if(times_used >= max_uses)
user << "<span class='danger'>The mind batterer has been burnt out!</span>"
return
add_logs(user, null, "knocked down people in the area", src)
for(var/mob/living/carbon/human/M in urange(10, user, 1))
if(prob(50))
M.Weaken(rand(10,20))
if(prob(25))
M.Stun(rand(5,10))
M << "<span class='userdanger'>You feel a tremendous, paralyzing wave flood your mind.</span>"
else
M << "<span class='userdanger'>You feel a sudden, electric jolt travel through your head.</span>"
playsound(src.loc, 'sound/misc/interference.ogg', 50, 1)
user << "<span class='notice'>You trigger [src].</span>"
times_used += 1
if(times_used >= max_uses)
icon_state = "battererburnt"
/*
The radioactive microlaser, a device disguised as a health analyzer used to irradiate people.
The strength of the radiation is determined by the 'intensity' setting, while the delay between
the scan and the irradiation kicking in is determined by the wavelength.
Each scan will cause the microlaser to have a brief cooldown period. Higher intensity will increase
the cooldown, while higher wavelength will decrease it.
Wavelength is also slightly increased by the intensity as well.
*/
/obj/item/device/healthanalyzer/rad_laser
materials = list(MAT_METAL=400)
origin_tech = "magnets=3;biotech=5;syndicate=3"
var/irradiate = 1
var/intensity = 10 // how much damage the radiation does
var/wavelength = 10 // time it takes for the radiation to kick in, in seconds
var/used = 0 // is it cooling down?
/obj/item/device/healthanalyzer/rad_laser/attack(mob/living/M, mob/living/user)
..()
if(!irradiate)
return
if(!used)
add_logs(user, M, "irradiated", src)
var/cooldown = round(max(10, (intensity*5 - wavelength/4))) * 10
used = 1
icon_state = "health1"
handle_cooldown(cooldown) // splits off to handle the cooldown while handling wavelength
user << "<span class='warning'>Successfully irradiated [M].</span>"
spawn((wavelength+(intensity*4))*5)
if(M)
if(intensity >= 5)
M.apply_effect(round(intensity/1.5), PARALYZE)
M.rad_act(intensity*10)
else
user << "<span class='warning'>The radioactive microlaser is still recharging.</span>"
/obj/item/device/healthanalyzer/rad_laser/proc/handle_cooldown(cooldown)
spawn(cooldown)
used = 0
icon_state = "health"
/obj/item/device/healthanalyzer/rad_laser/attack_self(mob/user)
interact(user)
/obj/item/device/healthanalyzer/rad_laser/interact(mob/user)
user.set_machine(src)
var/cooldown = round(max(10, (intensity*5 - wavelength/4)))
var/dat = "Irradiation: <A href='?src=\ref[src];rad=1'>[irradiate ? "On" : "Off"]</A><br>"
dat += "Scan Mode: <a href='?src=\ref[src];mode=1'>"
if(!scanmode)
dat += "Scan Health"
else if(scanmode == 1)
dat += "Scan Reagents"
else
dat += "Disabled"
dat += "</a><br><br>"
dat += {"
Radiation Intensity:
<A href='?src=\ref[src];radint=-5'>-</A><A href='?src=\ref[src];radint=-1'>-</A>
[intensity]
<A href='?src=\ref[src];radint=1'>+</A><A href='?src=\ref[src];radint=5'>+</A><BR>
Radiation Wavelength:
<A href='?src=\ref[src];radwav=-5'>-</A><A href='?src=\ref[src];radwav=-1'>-</A>
[(wavelength+(intensity*4))]
<A href='?src=\ref[src];radwav=1'>+</A><A href='?src=\ref[src];radwav=5'>+</A><BR>
Laser Cooldown: [cooldown] Seconds<BR>
"}
var/datum/browser/popup = new(user, "radlaser", "Radioactive Microlaser Interface", 400, 240)
popup.set_content(dat)
popup.open()
/obj/item/device/healthanalyzer/rad_laser/Topic(href, href_list)
if(!usr.canUseTopic(src))
return 1
usr.set_machine(src)
if(href_list["rad"])
irradiate = !irradiate
else if(href_list["mode"])
scanmode += 1
if(scanmode > 2)
scanmode = 0
else if(href_list["radint"])
var/amount = text2num(href_list["radint"])
amount += intensity
intensity = max(1,(min(20,amount)))
else if(href_list["radwav"])
var/amount = text2num(href_list["radwav"])
amount += wavelength
wavelength = max(0,(min(120,amount)))
attack_self(usr)
add_fingerprint(usr)
return
/obj/item/device/shadowcloak
name = "cloaker belt"
desc = "Makes you invisible for short periods of time. Recharges in darkness."
icon = 'icons/obj/clothing/belts.dmi'
icon_state = "utilitybelt"
item_state = "utility"
slot_flags = SLOT_BELT
attack_verb = list("whipped", "lashed", "disciplined")
var/mob/living/carbon/human/user = null
var/charge = 300
var/max_charge = 300
var/on = 0
var/old_alpha = 0
actions_types = list(/datum/action/item_action/toggle)
/obj/item/device/shadowcloak/ui_action_click(mob/user)
if(user.get_item_by_slot(slot_belt) == src)
if(!on)
Activate(usr)
else
Deactivate()
return
/obj/item/device/shadowcloak/item_action_slot_check(slot, mob/user)
if(slot == slot_belt)
return 1
/obj/item/device/shadowcloak/proc/Activate(mob/living/carbon/human/user)
if(!user)
return
user << "<span class='notice'>You activate [src].</span>"
src.user = user
START_PROCESSING(SSobj, src)
old_alpha = user.alpha
on = 1
/obj/item/device/shadowcloak/proc/Deactivate()
user << "<span class='notice'>You deactivate [src].</span>"
STOP_PROCESSING(SSobj, src)
if(user)
user.alpha = old_alpha
on = 0
user = null
/obj/item/device/shadowcloak/dropped(mob/user)
..()
if(user && user.get_item_by_slot(slot_belt) != src)
Deactivate()
/obj/item/device/shadowcloak/process()
if(user.get_item_by_slot(slot_belt) != src)
Deactivate()
return
var/turf/T = get_turf(src)
if(on)
var/lumcount = T.get_lumcount()
if(lumcount > 3)
charge = max(0,charge - 25)//Quick decrease in light
else
charge = min(max_charge,charge + 50) //Charge in the dark
animate(user,alpha = Clamp(255 - charge,0,255),time = 10)
@@ -0,0 +1,213 @@
/obj/item/device/transfer_valve
icon = 'icons/obj/assemblies.dmi'
name = "tank transfer valve"
icon_state = "valve_1"
item_state = "ttv"
desc = "Regulates the transfer of air between two tanks"
var/obj/item/weapon/tank/tank_one
var/obj/item/weapon/tank/tank_two
var/obj/item/device/attached_device
var/mob/attacher = null
var/valve_open = 0
var/toggle = 1
origin_tech = "materials=1;engineering=1"
/obj/item/device/transfer_valve/IsAssemblyHolder()
return 1
/obj/item/device/transfer_valve/attackby(obj/item/item, mob/user, params)
if(istype(item, /obj/item/weapon/tank))
if(tank_one && tank_two)
user << "<span class='warning'>There are already two tanks attached, remove one first!</span>"
return
if(!tank_one)
if(!user.unEquip(item))
return
tank_one = item
item.loc = src
user << "<span class='notice'>You attach the tank to the transfer valve.</span>"
if(item.w_class > w_class)
w_class = item.w_class
else if(!tank_two)
if(!user.unEquip(item))
return
tank_two = item
item.loc = src
user << "<span class='notice'>You attach the tank to the transfer valve.</span>"
if(item.w_class > w_class)
w_class = item.w_class
update_icon()
//TODO: Have this take an assemblyholder
else if(isassembly(item))
var/obj/item/device/assembly/A = item
if(A.secured)
user << "<span class='notice'>The device is secured.</span>"
return
if(attached_device)
user << "<span class='warning'>There is already a device attached to the valve, remove it first!</span>"
return
user.remove_from_mob(item)
attached_device = A
A.loc = src
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.")
log_game("[key_name_admin(user)] attached a [item] to a transfer valve.")
attacher = user
return
/obj/item/device/transfer_valve/attack_self(mob/user)
user.set_machine(src)
var/dat = {"<B> Valve properties: </B>
<BR> <B> Attachment one:</B> [tank_one] [tank_one ? "<A href='?src=\ref[src];tankone=1'>Remove</A>" : ""]
<BR> <B> Attachment two:</B> [tank_two] [tank_two ? "<A href='?src=\ref[src];tanktwo=1'>Remove</A>" : ""]
<BR> <B> Valve attachment:</B> [attached_device ? "<A href='?src=\ref[src];device=1'>[attached_device]</A>" : "None"] [attached_device ? "<A href='?src=\ref[src];rem_device=1'>Remove</A>" : ""]
<BR> <B> Valve status: </B> [ valve_open ? "<A href='?src=\ref[src];open=1'>Closed</A> <B>Open</B>" : "<B>Closed</B> <A href='?src=\ref[src];open=1'>Open</A>"]"}
var/datum/browser/popup = new(user, "trans_valve", name)
popup.set_content(dat)
popup.open()
return
/obj/item/device/transfer_valve/Topic(href, href_list)
..()
if ( usr.stat || usr.restrained() )
return
if (src.loc == usr)
if(tank_one && href_list["tankone"])
split_gases()
valve_open = 0
tank_one.loc = get_turf(src)
tank_one = null
update_icon()
if((!tank_two || tank_two.w_class < 4) && (w_class > 3))
w_class = 3
else if(tank_two && href_list["tanktwo"])
split_gases()
valve_open = 0
tank_two.loc = get_turf(src)
tank_two = null
update_icon()
if((!tank_one || tank_one.w_class < 4) && (w_class > 3))
w_class = 3
else if(href_list["open"])
toggle_valve()
else if(attached_device)
if(href_list["rem_device"])
attached_device.loc = get_turf(src)
attached_device:holder = null
attached_device = null
update_icon()
if(href_list["device"])
attached_device.attack_self(usr)
src.attack_self(usr)
src.add_fingerprint(usr)
return
return
/obj/item/device/transfer_valve/proc/process_activation(obj/item/device/D)
if(toggle)
toggle = 0
toggle_valve()
spawn(50) // To stop a signal being spammed from a proxy sensor constantly going off or whatever
toggle = 1
/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/merge_gases()
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)
/obj/item/device/transfer_valve/proc/split_gases()
if (!valve_open || !tank_one || !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)
valve_open = 1
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
var/attachment = "no device"
if(attached_device)
if(istype(attached_device, /obj/item/device/assembly/signaler))
attachment = "<A HREF='?_src_=holder;secrets=list_signalers'>[attached_device]</A>"
else
attachment = attached_device
var/attacher_name = ""
if(!attacher)
attacher_name = "Unknown"
else
attacher_name = "[key_name_admin(attacher)]"
var/log_str1 = "Bomb valve opened in "
var/log_str2 = "with [attachment] attacher: [attacher_name]"
var/log_attacher = ""
if(attacher)
log_attacher = "(<A HREF='?_src_=holder;adminmoreinfo=\ref[attacher]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[attacher]'>FLW</A>)"
var/mob/mob = get_mob_by_key(src.fingerprintslast)
var/last_touch_info = ""
if(mob)
last_touch_info = "(<A HREF='?_src_=holder;adminmoreinfo=\ref[mob]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[mob]'>FLW</A>)"
var/log_str3 = " Last touched by: [key_name_admin(mob)]"
var/bomb_message = "[log_str1] <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[bombturf.x];Y=[bombturf.y];Z=[bombturf.z]'>[A.name]</a> [log_str2][log_attacher] [log_str3][last_touch_info]"
bombers += bomb_message
message_admins(bomb_message, 0, 1)
log_game("[log_str1] [A.name]([A.x],[A.y],[A.z]) [log_str2] [log_str3]")
merge_gases()
spawn(20) // In case one tank bursts
for (var/i=0,i<5,i++)
src.update_icon()
sleep(10)
src.update_icon()
else if(valve_open && tank_one && tank_two)
split_gases()
valve_open = 0
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
+57
View File
@@ -0,0 +1,57 @@
/obj/item/documents
name = "secret documents"
desc = "\"Top Secret\" documents."
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "docs_generic"
item_state = "paper"
throwforce = 0
w_class = 1
throw_range = 1
throw_speed = 1
layer = MOB_LAYER
pressure_resistance = 1
/obj/item/documents/nanotrasen
desc = "\"Top Secret\" Nanotrasen documents, filled with complex diagrams and lists of names, dates and coordinates."
icon_state = "docs_verified"
/obj/item/documents/syndicate
desc = "\"Top Secret\" documents detailing sensitive Syndicate operational intelligence."
/obj/item/documents/syndicate/red
name = "red secret documents"
desc = "\"Top Secret\" documents detailing sensitive Syndicate operational intelligence. These documents are verified with a red wax seal."
icon_state = "docs_red"
/obj/item/documents/syndicate/blue
name = "blue secret documents"
desc = "\"Top Secret\" documents detailing sensitive Syndicate operational intelligence. These documents are verified with a blue wax seal."
icon_state = "docs_blue"
/obj/item/documents/syndicate/mining
desc = "\"Top Secret\" documents detailing Syndicate plasma mining operations."
/obj/item/documents/photocopy
desc = "A copy of some top-secret documents. Nobody will notice they aren't the originals... right?"
var/forgedseal = 0
var/copy_type = null
/obj/item/documents/photocopy/New(loc, obj/item/documents/copy=null)
..()
if(copy)
copy_type = copy.type
if(istype(copy, /obj/item/documents/photocopy)) // Copy Of A Copy Of A Copy
var/obj/item/documents/photocopy/C = copy
copy_type = C.copy_type
/obj/item/documents/photocopy/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/toy/crayon/red) || istype(O, /obj/item/toy/crayon/blue))
if (forgedseal)
user << "<span class='warning'>You have already forged a seal on [src]!</span>"
else
var/obj/item/toy/crayon/C = O
name = "[C.item_color] secret documents"
icon_state = "docs_[C.item_color]"
forgedseal = C.item_color
user << "<span class='notice'>You forge the official seal with a [C.item_color] crayon. No one will notice... right?</span>"
update_icon()
+58
View File
@@ -0,0 +1,58 @@
/obj/item/latexballon
name = "latex glove"
desc = "Sterile and airtight."
icon_state = "latexballon"
item_state = "lgloves"
force = 0
throwforce = 0
w_class = 1
throw_speed = 1
throw_range = 7
var/state
var/datum/gas_mixture/air_contents = null
/obj/item/latexballon/proc/blow(obj/item/weapon/tank/tank, mob/user)
if (icon_state == "latexballon_bursted")
return
icon_state = "latexballon_blow"
item_state = "latexballon"
user.update_inv_r_hand()
user.update_inv_l_hand()
user << "<span class='notice'>You blow up [src] with [tank].</span>"
air_contents = tank.remove_air_volume(3)
/obj/item/latexballon/proc/burst()
if (!air_contents || icon_state != "latexballon_blow")
return
playsound(src, 'sound/weapons/Gunshot.ogg', 100, 1)
icon_state = "latexballon_bursted"
item_state = "lgloves"
if(istype(src.loc, /mob/living))
var/mob/living/user = src.loc
user.update_inv_r_hand()
user.update_inv_l_hand()
loc.assume_air(air_contents)
/obj/item/latexballon/ex_act(severity, target)
burst()
switch(severity)
if (1)
qdel(src)
if (2)
if (prob(50))
qdel(src)
/obj/item/latexballon/bullet_act()
burst()
/obj/item/latexballon/temperature_expose(datum/gas_mixture/air, temperature, volume)
if(temperature > T0C+100)
burst()
/obj/item/latexballon/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weapon/tank))
var/obj/item/weapon/tank/T = W
blow(T, user)
return
if (is_sharp(W) || W.is_hot() || is_pointed(W))
burst()
+82
View File
@@ -0,0 +1,82 @@
//Items for nuke theft traitor objective
//the nuke core - objective item
/obj/item/nuke_core
name = "plutonium core"
desc = "Extremely radioactive. Wear goggles."
icon = 'icons/obj/nuke_tools.dmi'
icon_state = "plutonium_core"
item_state = "plutoniumcore"
var/pulse = 0
var/cooldown = 0
/obj/item/nuke_core/New()
..()
START_PROCESSING(SSobj, src)
/obj/item/nuke_core/attackby(obj/item/nuke_core_container/container, mob/user)
if(istype(container))
container.load(src, user)
else
return ..()
/obj/item/nuke_core/process()
if(cooldown < world.time - 60)
cooldown = world.time
flick("plutonium_core_pulse", src)
radiation_pulse(get_turf(src), 1, 4, 40, 1)
//nuke core box, for carrying the core
/obj/item/nuke_core_container
name = "nuke core container"
desc = "Solid container for radioactive objects."
icon = 'icons/obj/nuke_tools.dmi'
icon_state = "core_container_empty"
item_state = "tile"
var/obj/item/nuke_core/core = null
/obj/item/nuke_core_container/proc/load(obj/item/nuke_core/ncore, mob/user)
if(core || !istype(ncore))
return 0
ncore.loc = src
core = ncore
icon_state = "core_container_loaded"
user << "<span class='warning'>Container is sealing...</span>"
addtimer(src, "seal", 50)
return 1
/obj/item/nuke_core_container/proc/seal()
if(istype(core))
STOP_PROCESSING(SSobj, core)
icon_state = "core_container_sealed"
playsound(loc, 'sound/items/Deconstruct.ogg', 60, 1)
if(ismob(loc))
loc << "<span class='warning'>[src] is permanently sealed, [core]'s radiation is contained.</span>"
/obj/item/nuke_core_container/attackby(obj/item/nuke_core/core, mob/user)
if(istype(core))
if(!user.unEquip(core))
user << "<span class='warning'>The [core] is stuck to your hand!</span>"
return
else
load(core, user)
else
return ..()
//snowflake screwdriver, works as a key to start nuke theft, traitor only
/obj/item/weapon/screwdriver/nuke
name = "screwdriver"
desc = "A screwdriver with an ultra thin tip."
icon = 'icons/obj/nuke_tools.dmi'
icon_state = "screwdriver_nuke"
toolspeed = 2
/obj/item/weapon/paper/nuke_instructions
info = "How to break into a Nanotrasen self-destruct terminal and remove its plutonium core:<br>\
<ul>\
<li>Use a screwdriver with a very thin tip (provided) to unscrew the terminal's front panel</li>\
<li>Dislodge and remove the front panel with a crowbar</li>\
<li>Cut the inner metal plate with a welding tool</li>\
<li>Pry off the inner plate with a crowbar to expose the radioactive core</li>\
<li>Use the core container to remove the plutonium core; the container will take some time to seal</li>\
<li>???</li>"
@@ -0,0 +1,40 @@
///AI Upgrades
//Malf Picker
/obj/item/device/malf_upgrade
name = "combat software upgrade"
desc = "A highly illegal, highly dangerous upgrade for artificial intelligence units, granting them a variety of powers as well as the ability to hack APCs."
icon = 'icons/obj/module.dmi'
icon_state = "datadisk3"
/obj/item/device/malf_upgrade/afterattack(mob/living/silicon/ai/AI, mob/user)
if(!istype(AI))
return
if(AI.malf_picker)
AI.malf_picker.processing_time += 50
AI << "<span class='userdanger'>[user] has attempted to upgrade you with combat software that you already possess. You gain 50 points to spend on Malfunction Modules instead.</span>"
else
AI << "<span class='userdanger'>[user] has upgraded you with combat software!</span>"
AI.add_malf_picker()
user << "<span class='notice'>You upgrade [AI]. [src] is consumed in the process.</span>"
qdel(src)
//Lipreading
/obj/item/device/surveillance_upgrade
name = "surveillance software upgrade"
desc = "A software package that will allow an artificial intelligence to 'hear' from its cameras via lip reading."
icon = 'icons/obj/module.dmi'
icon_state = "datadisk3"
/obj/item/device/surveillance_upgrade/afterattack(mob/living/silicon/ai/AI, mob/user)
if(!istype(AI))
return
if(AI.eyeobj)
AI.eyeobj.relay_speech = TRUE
AI << "<span class='userdanger'>[user] has upgraded you with surveillance software!</span>"
AI << "Via a combination of hidden microphones and lip reading software, you are able to use your cameras to listen in on conversations."
user << "<span class='notice'>You upgrade [AI]. [src] is consumed in the process.</span>"
qdel(src)
@@ -0,0 +1,388 @@
/**********************************************************************
Cyborg Spec Items
***********************************************************************/
/obj/item/borg
icon = 'icons/mob/robot_items.dmi'
/obj/item/borg/stun
name = "electrically-charged arm"
icon_state = "elecarm"
/obj/item/borg/stun/attack(mob/living/M, mob/living/silicon/robot/user)
if(!user.cell.use(30)) return
M.Weaken(5)
M.apply_effect(STUTTER, 5)
M.Stun(5)
M.visible_message("<span class='danger'>[user] has prodded [M] with [src]!</span>", \
"<span class='userdanger'>[user] has prodded you with [src]!</span>")
add_logs(user, M, "stunned", src, "(INTENT: [uppertext(user.a_intent)])")
/obj/item/borg/cyborghug
name = "Hugging Module"
icon_state = "hugmodule"
desc = "For when a someone really needs a hug."
var/mode = 0 //0 = Hugs 1 = "Hug" 2 = Shock 3 = CRUSH
var/ccooldown = 0
var/scooldown = 0
var/shockallowed = 0//Can it be a stunarm when emagged. Only PK borgs get this by default.
/obj/item/borg/cyborghug/attack_self(mob/living/user)
if(isrobot(user))
var/mob/living/silicon/robot/P = user
if(P.emagged&&shockallowed == 1)
if(mode < 3)
mode++
else
mode = 0
else if(mode < 1)
mode++
else
mode = 0
switch(mode)
if(0)
user << "Power reset. Hugs!"
if(1)
user << "Power increased!"
if(2)
user << "BZZT. Electrifying arms..."
if(3)
user << "ERROR: ARM ACTUATORS OVERLOADED."
/obj/item/borg/cyborghug/attack(mob/living/M, mob/living/silicon/robot/user)
switch(mode)
if(0)
if(M.health >= 0)
if(ishuman(M))
if(M.lying)
user.visible_message("<span class='notice'>[user] shakes [M] trying to get \him up!</span>", \
"<span class='notice'>You shake [M] trying to get \him up!</span>")
else
user.visible_message("<span class='notice'>[user] hugs [M] to make \him feel better!</span>", \
"<span class='notice'>You hug [M] to make \him feel better!</span>")
if(M.resting)
M.resting = 0
M.update_canmove()
else
user.visible_message("<span class='notice'>[user] pets [M]!</span>", \
"<span class='notice'>You pet [M]!</span>")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(1)
if(M.health >= 0)
if(ishuman(M))
if(M.lying)
user.visible_message("<span class='notice'>[user] shakes [M] trying to get \him up!</span>", \
"<span class='notice'>You shake [M] trying to get \him up!</span>")
else
user.visible_message("<span class='warning'>[user] hugs [M] in a firm bear-hug! [M] looks uncomfortable...</span>", \
"<span class='warning'>You hug [M] firmly to make \him feel better! [M] looks uncomfortable...</span>")
if(M.resting)
M.resting = 0
M.update_canmove()
else
user.visible_message("<span class='warning'>[user] bops [M] on the head!</span>", \
"<span class='warning'>You bop [M] on the head!</span>")
playsound(loc, 'sound/weapons/tap.ogg', 50, 1, -1)
if(2)
if(!scooldown)
if(M.health >= 0)
if(ishuman(M)||ismonkey(M))
M.electrocute_act(5, "[user]", safety = 1)
user.visible_message("<span class='userdanger'>[user] electrocutes [M] with their touch!</span>", \
"<span class='danger'>You electrocute [M] with your touch!</span>")
M.update_canmove()
else
if(!isrobot(M))
M.adjustFireLoss(10)
user.visible_message("<span class='userdanger'>[user] shocks [M]!</span>", \
"<span class='danger'>You shock [M]!</span>")
else
user.visible_message("<span class='userdanger'>[user] shocks [M]. It does not seem to have an effect</span>", \
"<span class='danger'>You shock [M] to no effect.</span>")
playsound(loc, 'sound/effects/sparks2.ogg', 50, 1, -1)
user.cell.charge -= 500
scooldown = 1
spawn(20)
scooldown = 0
if(3)
if(!ccooldown)
if(M.health >= 0)
if(ishuman(M))
user.visible_message("<span class='userdanger'>[user] crushes [M] in their grip!</span>", \
"<span class='danger'>You crush [M] in your grip!</span>")
else
user.visible_message("<span class='userdanger'>[user] crushes [M]!</span>", \
"<span class='danger'>You crush [M]!</span>")
playsound(loc, 'sound/weapons/smash.ogg', 50, 1, -1)
M.adjustBruteLoss(10)
user.cell.charge -= 300
ccooldown = 1
spawn(10)
ccooldown = 0
/obj/item/borg/cyborghug/peacekeeper
shockallowed = 1
/obj/item/borg/charger
name = "power connector"
icon_state = "charger_draw"
flags = NOBLUDGEON
var/mode = "draw"
var/list/charge_machines = list(/obj/machinery/cell_charger, /obj/machinery/recharger,
/obj/machinery/recharge_station, /obj/machinery/mech_bay_recharge_port)
var/list/charge_items = list(/obj/item/weapon/stock_parts/cell, /obj/item/weapon/gun/energy,
)
/obj/item/borg/charger/update_icon()
..()
icon_state = "charger_[mode]"
/obj/item/borg/charger/attack_self(mob/user)
if(mode == "draw")
mode = "charge"
else
mode = "draw"
user << "<span class='notice'>You toggle [src] to \"[mode]\" mode.</span>"
update_icon()
/obj/item/borg/charger/afterattack(obj/item/target, mob/living/silicon/robot/user, proximity_flag)
if(!proximity_flag || !isrobot(user))
return
if(mode == "draw")
if(is_type_in_list(target, charge_machines))
var/obj/machinery/M = target
if((M.stat & (NOPOWER|BROKEN)) || !M.anchored)
user << "<span class='warning'>[M] is unpowered!</span>"
return
user << "<span class='notice'>You connect to [M]'s power line...</span>"
while(do_after(user, 15, target = M, progress = 0))
if(!user || !user.cell || mode != "draw")
return
if((M.stat & (NOPOWER|BROKEN)) || !M.anchored)
break
if(!user.cell.give(150))
break
M.use_power(200)
user << "<span class='notice'>You stop charging youself.</span>"
else if(is_type_in_list(target, charge_items))
var/obj/item/weapon/stock_parts/cell/cell = target
if(!istype(cell))
cell = locate(/obj/item/weapon/stock_parts/cell) in target
if(!cell)
user << "<span class='warning'>[target] has no power cell!</span>"
return
if(istype(target, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/E = target
if(!E.can_charge)
user << "<span class='warning'>[target] has no power port!</span>"
return
if(!cell.charge)
user << "<span class='warning'>[target] has no power!</span>"
user << "<span class='notice'>You connect to [target]'s power port...</span>"
while(do_after(user, 15, target = target, progress = 0))
if(!user || !user.cell || mode != "draw")
return
if(!cell || !target)
return
if(cell != target && cell.loc != target)
return
var/draw = min(cell.charge, cell.chargerate*0.5, user.cell.maxcharge-user.cell.charge)
if(!cell.use(draw))
break
if(!user.cell.give(draw))
break
target.update_icon()
user << "<span class='notice'>You stop charging youself.</span>"
else if(is_type_in_list(target, charge_items))
var/obj/item/weapon/stock_parts/cell/cell = target
if(!istype(cell))
cell = locate(/obj/item/weapon/stock_parts/cell) in target
if(!cell)
user << "<span class='warning'>[target] has no power cell!</span>"
return
if(istype(target, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/E = target
if(!E.can_charge)
user << "<span class='warning'>[target] has no power port!</span>"
return
if(cell.charge >= cell.maxcharge)
user << "<span class='warning'>[target] is already charged!</span>"
user << "<span class='notice'>You connect to [target]'s power port...</span>"
while(do_after(user, 15, target = target, progress = 0))
if(!user || !user.cell || mode != "charge")
return
if(!cell || !target)
return
if(cell != target && cell.loc != target)
return
var/draw = min(user.cell.charge, cell.chargerate*0.5, cell.maxcharge-cell.charge)
if(!user.cell.use(draw))
break
if(!cell.give(draw))
break
target.update_icon()
user << "<span class='notice'>You stop charging [target].</span>"
/obj/item/device/harmalarm
name = "Sonic Harm Prevention Tool"
desc = "Releases a harmless blast that confuses most organics. For when the harm is JUST TOO MUCH"
icon_state = "megaphone"
var/cooldown = 0
var/emagged = 0
/obj/item/device/harmalarm/emag_act(mob/user)
emagged = !emagged
if(emagged)
user << "<font color='red'>You short out the safeties on the [src]!</font>"
else
user << "<font color='red'>You reset the safeties on the [src]!</font>"
/obj/item/device/harmalarm/attack_self(mob/user)
var/safety = !emagged
if(cooldown > world.time)
user << "<font color='red'>The device is still recharging!</font>"
return
if(isrobot(user))
var/mob/living/silicon/robot/R = user
if(R.cell.charge < 1200)
user << "<font color='red'>You don't have enough charge to do this!</font>"
return
R.cell.charge -= 1000
if(R.emagged)
safety = 0
if(safety == 1)
user.visible_message("<font color='red' size='2'>[user] blares out a near-deafening siren from its speakers!</font>", \
"<span class='userdanger'>The siren pierces your hearing and confuses you!</span>", \
"<span class='danger'>The siren pierces your hearing!</span>")
for(var/mob/living/M in get_hearers_in_view(9, user))
if(iscarbon(M))
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
if(istype(H.ears, /obj/item/clothing/ears/earmuffs))
continue
M.confused += 6
M << "<font color='red' size='7'>HUMAN HARM</font>"
playsound(get_turf(src), 'sound/AI/harmalarm.ogg', 70, 3)
cooldown = world.time + 200
log_game("[user.ckey]([user]) used a Cyborg Harm Alarm in ([user.x],[user.y],[user.z])")
if(isrobot(user))
var/mob/living/silicon/robot/R = user
R.connected_ai << "<br><span class='notice'>NOTICE - Peacekeeping 'HARM ALARM' used by: [user]</span><br>"
return
if(safety == 0)
for(var/mob/living/M in get_hearers_in_view(9, user))
if(iscarbon(M))
var/earsafety = 0
if(istype(M, /mob/living/carbon/alien))
continue
if(ishuman(M))
var/mob/living/carbon/human/S = M
if(istype(S.ears, /obj/item/clothing/ears/earmuffs))
continue
if(S.check_ear_prot())
earsafety = 1
if(earsafety)
M.confused += 5
M.stuttering += 10
M.adjustEarDamage(0, 5)
M.Jitter(10)
user.visible_message("<font color='red' size='3'>[user] blares out a sonic screech from its speakers!</font>", \
"<span class='userdanger'>You hear a sharp screech, before your thoughts are interrupted and you find yourself extremely disorientated.</span>", \
"<span class='danger'>You hear a sonic screech and suddenly can't seem to walk straight!")
else
M.Weaken(2)
M.confused += 10
M.stuttering += 15
M.adjustEarDamage(0, 20)
M.Jitter(25)
user.visible_message("<font color='red' size='3'>[user] blares out a sonic screech from its speakers!</font>", \
"<span class='userdanger'>You hear a sharp screech before your thoughts are interrupted and you collapse, your ears ringing!</span>", \
"<span class='danger'>You hear a sonic screech and collapse, your ears riniging!")
M << "<font color='red' size='7'>BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZT</font>"
playsound(get_turf(src), 'sound/machines/warning-buzzer.ogg', 130, 3)
cooldown = world.time + 600
log_game("[user.ckey]([user]) used an emagged Cyborg Harm Alarm in ([user.x],[user.y],[user.z])")
/**********************************************************************
HUD/SIGHT things
***********************************************************************/
/obj/item/borg/sight
var/sight_mode = null
/obj/item/borg/sight/xray
name = "\proper x-ray Vision"
icon = 'icons/obj/decals.dmi'
icon_state = "securearea"
sight_mode = BORGXRAY
/obj/item/borg/sight/thermal
name = "\proper thermal vision"
sight_mode = BORGTHERM
icon_state = "thermal"
/obj/item/borg/sight/meson
name = "\proper meson vision"
sight_mode = BORGMESON
icon_state = "meson"
/obj/item/borg/sight/material
name = "\proper material vision"
sight_mode = BORGMATERIAL
icon_state = "material"
/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"
/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"
/obj/item/borg/sight/hud/sec/New()
..()
hud = new /obj/item/clothing/glasses/hud/security(src)
return
@@ -0,0 +1,379 @@
/obj/item/robot_parts
name = "robot parts"
icon = 'icons/obj/robot_parts.dmi'
force = 4
throwforce = 4
item_state = "buildpipe"
icon_state = "blank"
flags = CONDUCT
slot_flags = SLOT_BELT
var/body_zone
/obj/item/robot_parts/l_arm
name = "cyborg left arm"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
attack_verb = list("slapped", "punched")
icon_state = "l_arm"
body_zone = "l_arm"
/obj/item/robot_parts/r_arm
name = "cyborg right arm"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
attack_verb = list("slapped", "punched")
icon_state = "r_arm"
body_zone = "r_arm"
/obj/item/robot_parts/l_leg
name = "cyborg left leg"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
attack_verb = list("kicked", "stomped")
icon_state = "l_leg"
body_zone = "l_leg"
/obj/item/robot_parts/r_leg
name = "cyborg right leg"
desc = "A skeletal limb wrapped in pseudomuscles, with a low-conductivity case."
attack_verb = list("kicked", "stomped")
icon_state = "r_leg"
body_zone = "r_leg"
/obj/item/robot_parts/chest
name = "cyborg torso"
desc = "A heavily reinforced case containing cyborg logic boards, with space for a standard power cell."
icon_state = "chest"
body_zone = "chest"
var/wired = 0
var/obj/item/weapon/stock_parts/cell/cell = null
/obj/item/robot_parts/head
name = "cyborg head"
desc = "A standard reinforced braincase, with spine-plugged neural socket and sensor gimbals."
icon_state = "head"
body_zone = "head"
var/obj/item/device/assembly/flash/handheld/flash1 = null
var/obj/item/device/assembly/flash/handheld/flash2 = null
/obj/item/robot_parts/robot_suit
name = "cyborg endoskeleton"
desc = "A complex metal backbone with standard limb sockets and pseudomuscle anchors."
icon_state = "robo_suit"
var/obj/item/robot_parts/l_arm/l_arm = null
var/obj/item/robot_parts/r_arm/r_arm = null
var/obj/item/robot_parts/l_leg/l_leg = null
var/obj/item/robot_parts/r_leg/r_leg = null
var/obj/item/robot_parts/chest/chest = null
var/obj/item/robot_parts/head/head = null
var/created_name = ""
var/mob/living/silicon/ai/forced_ai
var/locomotion = 1
var/lawsync = 1
var/aisync = 1
var/panel_locked = 1
/obj/item/robot_parts/robot_suit/New()
..()
src.updateicon()
/obj/item/robot_parts/robot_suit/proc/updateicon()
src.cut_overlays()
if(src.l_arm)
src.add_overlay("l_arm+o")
if(src.r_arm)
src.add_overlay("r_arm+o")
if(src.chest)
src.add_overlay("chest+o")
if(src.l_leg)
src.add_overlay("l_leg+o")
if(src.r_leg)
src.add_overlay("r_leg+o")
if(src.head)
src.add_overlay("head+o")
/obj/item/robot_parts/robot_suit/proc/check_completion()
if(src.l_arm && src.r_arm)
if(src.l_leg && src.r_leg)
if(src.chest && src.head)
feedback_inc("cyborg_frames_built",1)
return 1
return 0
/obj/item/robot_parts/robot_suit/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = W
if(!l_arm && !r_arm && !l_leg && !r_leg && !chest && !head)
if (M.use(1))
var/obj/item/weapon/ed209_assembly/B = new /obj/item/weapon/ed209_assembly
B.loc = get_turf(src)
user << "<span class='notice'>You arm the robot frame.</span>"
if (user.get_inactive_hand()==src)
user.unEquip(src)
user.put_in_inactive_hand(B)
qdel(src)
else
user << "<span class='warning'>You need one sheet of metal to start building ED-209!</span>"
return
else if(istype(W, /obj/item/robot_parts/l_leg))
if(src.l_leg)
return
if(!user.unEquip(W))
return
W.loc = src
src.l_leg = W
src.updateicon()
else if(istype(W, /obj/item/robot_parts/r_leg))
if(src.r_leg)
return
if(!user.unEquip(W))
return
W.loc = src
src.r_leg = W
src.updateicon()
else if(istype(W, /obj/item/robot_parts/l_arm))
if(src.l_arm)
return
if(!user.unEquip(W))
return
W.loc = src
src.l_arm = W
src.updateicon()
else if(istype(W, /obj/item/robot_parts/r_arm))
if(src.r_arm)
return
if(!user.unEquip(W))
return
W.loc = src
src.r_arm = W
src.updateicon()
else if(istype(W, /obj/item/robot_parts/chest))
if(src.chest)
return
if(W:wired && W:cell)
if(!user.unEquip(W))
return
W.loc = src
src.chest = W
src.updateicon()
else if(!W:wired)
user << "<span class='warning'>You need to attach wires to it first!</span>"
else
user << "<span class='warning'>You need to attach a cell to it first!</span>"
else if(istype(W, /obj/item/robot_parts/head))
if(src.head)
return
if(W:flash2 && W:flash1)
if(!user.unEquip(W))
return
W.loc = src
src.head = W
src.updateicon()
else
user << "<span class='warning'>You need to attach a flash to it first!</span>"
else if (istype(W, /obj/item/device/multitool))
if(check_completion())
Interact(user)
else
user << "<span class='warning'>The endoskeleton must be assembled before debugging can begin!</span>"
else if(istype(W, /obj/item/device/mmi))
var/obj/item/device/mmi/M = W
if(check_completion())
if(!istype(loc,/turf))
user << "<span class='warning'>You can't put the MMI in, the frame has to be standing on the ground to be perfectly precise!</span>"
return
if(!M.brainmob)
user << "<span class='warning'>Sticking an empty MMI into the frame would sort of defeat the purpose!</span>"
return
var/mob/living/carbon/brain/BM = M.brainmob
if(!BM.key || !BM.mind)
user << "<span class='warning'>The mmi indicates that their mind is completely unresponsive; there's no point!</span>"
return
if(!BM.client) //braindead
user << "<span class='warning'>The mmi indicates that their mind is currently inactive; it might change!</span>"
return
if(BM.stat == DEAD || (M.brain && M.brain.damaged_brain))
user << "<span class='warning'>Sticking a dead brain into the frame would sort of defeat the purpose!</span>"
return
if(jobban_isbanned(BM, "Cyborg"))
user << "<span class='warning'>This MMI does not seem to fit!</span>"
return
if(!user.unEquip(W))
return
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot(get_turf(loc))
if(!O)
return
if(M.hacked || M.clockwork)
aisync = 0
lawsync = 0
var/datum/ai_laws/L
if(M.clockwork)
L = new/datum/ai_laws/ratvar
else
L = new/datum/ai_laws/syndicate_override
O.laws = L
L.associate(O)
O.invisibility = 0
//Transfer debug settings to new mob
O.custom_name = created_name
O.locked = panel_locked
if(!aisync)
lawsync = 0
O.connected_ai = null
else
O.notify_ai(1)
if(forced_ai)
O.connected_ai = forced_ai
if(!lawsync)
O.lawupdate = 0
if(!M.hacked && !M.clockwork)
O.make_laws()
ticker.mode.remove_antag_for_borging(BM.mind)
BM.mind.transfer_to(O)
if(M.clockwork)
add_servant_of_ratvar(O)
if(O.mind && O.mind.special_role)
O.mind.store_memory("As a cyborg, you must obey your silicon laws and master AI above all else. Your objectives will consider you to be dead.")
O << "<span class='userdanger'>You have been robotized!</span>"
O << "<span class='danger'>You must obey your silicon laws and master AI above all else. Your objectives will consider you to be dead.</span>"
O.job = "Cyborg"
O.cell = chest.cell
chest.cell.loc = O
chest.cell = null
W.loc = O//Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
if(O.mmi) //we delete the mmi created by robot/New()
qdel(O.mmi)
O.mmi = W //and give the real mmi to the borg.
O.updatename()
feedback_inc("cyborg_birth",1)
src.loc = O
O.robot_suit = src
if(!locomotion)
O.lockcharge = 1
O.update_canmove()
O << "<span class='warning'>Error: Servo motors unresponsive.</span>"
else
user << "<span class='warning'>The MMI must go in after everything else!</span>"
else if(istype(W,/obj/item/weapon/pen))
user << "<span class='warning'>You need to use a multitool to name [src]!</span>"
else
return ..()
/obj/item/robot_parts/robot_suit/proc/Interact(mob/user)
var/t1 = text("Designation: <A href='?src=\ref[];Name=1'>[(created_name ? "[created_name]" : "Default Cyborg")]</a><br>\n",src)
t1 += text("Master AI: <A href='?src=\ref[];Master=1'>[(forced_ai ? "[forced_ai.name]" : "Automatic")]</a><br><br>\n",src)
t1 += text("LawSync Port: <A href='?src=\ref[];Law=1'>[(lawsync ? "Open" : "Closed")]</a><br>\n",src)
t1 += text("AI Connection Port: <A href='?src=\ref[];AI=1'>[(aisync ? "Open" : "Closed")]</a><br>\n",src)
t1 += text("Servo Motor Functions: <A href='?src=\ref[];Loco=1'>[(locomotion ? "Unlocked" : "Locked")]</a><br>\n",src)
t1 += text("Panel Lock: <A href='?src=\ref[];Panel=1'>[(panel_locked ? "Engaged" : "Disengaged")]</a><br>\n",src)
var/datum/browser/popup = new(user, "robotdebug", "Cyborg Boot Debug", 310, 220)
popup.set_content(t1)
popup.open()
/obj/item/robot_parts/robot_suit/Topic(href, href_list)
if(usr.lying || usr.stat || usr.stunned || !Adjacent(usr))
return
var/mob/living/living_user = usr
var/obj/item/item_in_hand = living_user.get_active_hand()
if(!istype(item_in_hand, /obj/item/device/multitool))
living_user << "<span class='warning'>You need a multitool!</span>"
return
if(href_list["Name"])
var/new_name = reject_bad_name(input(usr, "Enter new designation. Set to blank to reset to default.", "Cyborg Debug", src.created_name),1)
if(!in_range(src, usr) && src.loc != usr)
return
if(new_name)
created_name = new_name
else
created_name = ""
else if(href_list["Master"])
forced_ai = select_active_ai(usr)
if(!forced_ai)
usr << "<span class='error'>No active AIs detected.</span>"
else if(href_list["Law"])
lawsync = !lawsync
else if(href_list["AI"])
aisync = !aisync
else if(href_list["Loco"])
locomotion = !locomotion
else if(href_list["Panel"])
panel_locked = !panel_locked
add_fingerprint(usr)
Interact(usr)
return
/obj/item/robot_parts/chest/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weapon/stock_parts/cell))
if(src.cell)
user << "<span class='warning'>You have already inserted a cell!</span>"
return
else
if(!user.unEquip(W))
return
W.loc = src
src.cell = W
user << "<span class='notice'>You insert the cell.</span>"
else if(istype(W, /obj/item/stack/cable_coil))
if(src.wired)
user << "<span class='warning'>You have already inserted wire!</span>"
return
var/obj/item/stack/cable_coil/coil = W
if (coil.use(1))
src.wired = 1
user << "<span class='notice'>You insert the wire.</span>"
else
user << "<span class='warning'>You need one length of coil to wire it!</span>"
else
return ..()
/obj/item/robot_parts/head/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/device/assembly/flash/handheld))
var/obj/item/device/assembly/flash/handheld/F = W
if(src.flash1 && src.flash2)
user << "<span class='warning'>You have already inserted the eyes!</span>"
return
else if(F.crit_fail)
user << "<span class='warning'>You can't use a broken flash!</span>"
return
else
if(!user.unEquip(W))
return
F.loc = src
if(src.flash1)
src.flash2 = F
else
src.flash1 = F
user << "<span class='notice'>You insert the flash into the eye socket.</span>"
else
return ..()
@@ -0,0 +1,341 @@
// robot_upgrades.dm
// Contains various borg upgrades.
/obj/item/borg/upgrade
name = "borg upgrade module."
desc = "Protected by FRM."
icon = 'icons/obj/module.dmi'
icon_state = "cyborg_upgrade"
origin_tech = "programming=2"
var/locked = 0
var/installed = 0
var/require_module = 0
var/module_type = null
/obj/item/borg/upgrade/proc/action(mob/living/silicon/robot/R)
if(R.stat == DEAD)
usr << "<span class='notice'>[src] will not function on a deceased cyborg.</span>"
return 1
if(module_type && !istype(R.module, module_type))
R << "Upgrade mounting error! No suitable hardpoint detected!"
usr << "There's no mounting point for the module!"
return 1
/obj/item/borg/upgrade/reset
name = "cyborg module reset board"
desc = "Used to reset a cyborg's module. Destroys any other upgrades applied to the cyborg."
icon_state = "cyborg_upgrade1"
require_module = 1
/obj/item/borg/upgrade/reset/action(mob/living/silicon/robot/R)
if(..())
return
R.notify_ai(2)
R.uneq_all()
R.hands.icon_state = "nomod"
R.icon_state = "robot"
qdel(R.module)
R.module = null
R.modtype = "robot"
R.designation = "Default"
R.updatename("Default")
R.update_icons()
R.update_headlamp()
R.speed = 0 // Remove upgrades.
R.ionpulse = FALSE
R.magpulse = FALSE
R.weather_immunities = initial(R.weather_immunities)
R.status_flags |= CANPUSH
return 1
/obj/item/borg/upgrade/rename
name = "cyborg reclassification board"
desc = "Used to rename a cyborg."
icon_state = "cyborg_upgrade1"
var/heldname = "default name"
/obj/item/borg/upgrade/rename/attack_self(mob/user)
heldname = stripped_input(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN)
/obj/item/borg/upgrade/rename/action(mob/living/silicon/robot/R)
if(..())
return
R.fully_replace_character_name(R.name, heldname)
return 1
/obj/item/borg/upgrade/restart
name = "cyborg emergency reboot module"
desc = "Used to force a reboot of a disabled-but-repaired cyborg, bringing it back online."
icon_state = "cyborg_upgrade1"
/obj/item/borg/upgrade/restart/action(mob/living/silicon/robot/R)
if(R.health < 0)
usr << "<span class='warning'>You have to repair the cyborg before using this module!</span>"
return 0
if(!R.key)
for(var/mob/dead/observer/ghost in player_list)
if(ghost.mind && ghost.mind.current == R)
R.key = ghost.key
R.revive()
return 1
/obj/item/borg/upgrade/vtec
name = "cyborg VTEC module"
desc = "Used to kick in a cyborg's VTEC systems, increasing their speed."
icon_state = "cyborg_upgrade2"
require_module = 1
origin_tech = "engineering=4;materials=5;programming=4"
/obj/item/borg/upgrade/vtec/action(mob/living/silicon/robot/R)
if(..())
return
if(R.speed < 0)
R << "<span class='notice'>A VTEC unit is already installed!</span>"
usr << "<span class='notice'>There's no room for another VTEC unit!</span>"
return
R.speed = -2 // Gotta go fast.
return 1
/obj/item/borg/upgrade/disablercooler
name = "cyborg rapid disabler cooling module"
desc = "Used to cool a mounted disabler, increasing the potential current in it and thus its recharge rate."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = /obj/item/weapon/robot_module/security
origin_tech = "engineering=4;powerstorage=4;combat=4"
/obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R)
if(..())
return
var/obj/item/weapon/gun/energy/disabler/cyborg/T = locate() in R.module.modules
if(!T)
usr << "<span class='notice'>There's no disabler in this unit!</span>"
return
if(T.charge_delay <= 2)
R << "<span class='notice'>A cooling unit is already installed!</span>"
usr << "<span class='notice'>There's no room for another cooling unit!</span>"
return
T.charge_delay = max(2 , T.charge_delay - 4)
return 1
/obj/item/borg/upgrade/thrusters
name = "ion thruster upgrade"
desc = "A energy-operated thruster system for cyborgs."
icon_state = "cyborg_upgrade3"
origin_tech = "engineering=4;powerstorage=4"
/obj/item/borg/upgrade/thrusters/action(mob/living/silicon/robot/R)
if(..())
return
if(R.ionpulse)
usr << "<span class='notice'>This unit already has ion thrusters installed!</span>"
return
R.ionpulse = TRUE
return 1
/obj/item/borg/upgrade/ddrill
name = "mining cyborg diamond drill"
desc = "A diamond drill replacement for the mining module's standard drill."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = /obj/item/weapon/robot_module/miner
origin_tech = "engineering=4;materials=5"
/obj/item/borg/upgrade/ddrill/action(mob/living/silicon/robot/R)
if(..())
return
for(var/obj/item/weapon/pickaxe/drill/cyborg/D in R.module.modules)
qdel(D)
for(var/obj/item/weapon/shovel/S in R.module.modules)
qdel(S)
R.module.modules += new /obj/item/weapon/pickaxe/drill/cyborg/diamond(R.module)
R.module.rebuild()
return 1
/obj/item/borg/upgrade/soh
name = "mining cyborg satchel of holding"
desc = "A satchel of holding replacement for mining cyborg's ore satchel module."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = /obj/item/weapon/robot_module/miner
origin_tech = "engineering=4;materials=4;bluespace=4"
/obj/item/borg/upgrade/soh/action(mob/living/silicon/robot/R)
if(..())
return
for(var/obj/item/weapon/storage/bag/ore/cyborg/S in R.module.modules)
qdel(S)
R.module.modules += new /obj/item/weapon/storage/bag/ore/holding(R.module)
R.module.rebuild()
return 1
/obj/item/borg/upgrade/hyperka
name = "mining cyborg hyper-kinetic accelerator"
desc = "A satchel of holding replacement for mining cyborg's ore satchel module."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = /obj/item/weapon/robot_module/miner
origin_tech = "materials=6;powerstorage=4;engineering=4;magnets=4;combat=4"
/obj/item/borg/upgrade/hyperka/action(mob/living/silicon/robot/R)
if(..())
return
for(var/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg/H in R.module.modules)
qdel(H)
R.module.modules += new /obj/item/weapon/gun/energy/kinetic_accelerator/hyper/cyborg(R.module)
R.module.rebuild()
return 1
/obj/item/borg/upgrade/syndicate
name = "illegal equipment module"
desc = "Unlocks the hidden, deadlier functions of a cyborg"
icon_state = "cyborg_upgrade3"
require_module = 1
origin_tech = "combat=4;syndicate=1"
/obj/item/borg/upgrade/syndicate/action(mob/living/silicon/robot/R)
if(..())
return
if(R.emagged)
return
R.SetEmagged(1)
return 1
/obj/item/borg/upgrade/lavaproof
name = "mining cyborg lavaproof tracks"
desc = "An upgrade kit to apply specialized coolant systems and insulation layers to mining cyborg tracks, enabling them to withstand exposure to molten rock."
icon_state = "ash_plating"
require_module = 1
module_type = /obj/item/weapon/robot_module/miner
origin_tech = "engineering=4;materials=4;plasmatech=4"
/obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R)
if(..())
return
R.weather_immunities += "lava"
return 1
/obj/item/borg/upgrade/selfrepair
name = "self-repair module"
desc = "This module will repair the cyborg over time."
icon_state = "cyborg_upgrade5"
require_module = 1
var/repair_amount = -1
var/repair_tick = 1
var/msg_cooldown = 0
var/on = 0
var/powercost = 10
var/mob/living/silicon/robot/cyborg
/obj/item/borg/upgrade/selfrepair/action(mob/living/silicon/robot/R)
if(..())
return
var/obj/item/borg/upgrade/selfrepair/U = locate() in R
if(U)
usr << "<span class='warning'>This unit is already equipped with a self-repair module.</span>"
return 0
cyborg = R
icon_state = "selfrepair_off"
var/datum/action/A = new /datum/action/item_action/toggle(src)
A.Grant(R)
return 1
/obj/item/borg/upgrade/selfrepair/ui_action_click()
on = !on
if(on)
cyborg << "<span class='notice'>You activate the self-repair module.</span>"
START_PROCESSING(SSobj, src)
else
cyborg << "<span class='notice'>You deactivate the self-repair module.</span>"
STOP_PROCESSING(SSobj, src)
update_icon()
/obj/item/borg/upgrade/selfrepair/update_icon()
if(cyborg)
icon_state = "selfrepair_[on ? "on" : "off"]"
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
else
icon_state = "cyborg_upgrade5"
/obj/item/borg/upgrade/selfrepair/proc/deactivate()
STOP_PROCESSING(SSobj, src)
on = FALSE
update_icon()
/obj/item/borg/upgrade/selfrepair/process()
if(!repair_tick)
repair_tick = 1
return
if(cyborg && (cyborg.stat != DEAD) && on)
if(!cyborg.cell)
cyborg << "<span class='warning'>Self-repair module deactivated. Please, insert the power cell.</span>"
deactivate()
return
if(cyborg.cell.charge < powercost * 2)
cyborg << "<span class='warning'>Self-repair module deactivated. Please recharge.</span>"
deactivate()
return
if(cyborg.health < cyborg.maxHealth)
if(cyborg.health < 0)
repair_amount = -2.5
powercost = 30
else
repair_amount = -1
powercost = 10
cyborg.adjustBruteLoss(repair_amount)
cyborg.adjustFireLoss(repair_amount)
cyborg.updatehealth()
cyborg.cell.use(powercost)
else
cyborg.cell.use(5)
repair_tick = 0
if((world.time - 2000) > msg_cooldown )
var/msgmode = "standby"
if(cyborg.health < 0)
msgmode = "critical"
else if(cyborg.health < cyborg.maxHealth)
msgmode = "normal"
cyborg << "<span class='notice'>Self-repair is active in <span class='boldnotice'>[msgmode]</span> mode.</span>"
msg_cooldown = world.time
else
deactivate()
+92
View File
@@ -0,0 +1,92 @@
/obj/item/target
name = "shooting target"
desc = "A shooting target."
icon = 'icons/obj/objects.dmi'
icon_state = "target_h"
density = 0
var/hp = 1800
var/obj/structure/target_stake/pinnedLoc
/obj/item/target/Destroy()
removeOverlays()
if(pinnedLoc)
pinnedLoc.nullPinnedTarget()
return ..()
/obj/item/target/proc/nullPinnedLoc()
pinnedLoc = null
density = 0
/obj/item/target/proc/removeOverlays()
cut_overlays()
/obj/item/target/Move()
..()
if(pinnedLoc)
pinnedLoc.loc = loc
/obj/item/target/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(WT.remove_fuel(0, user))
removeOverlays()
user << "<span class='notice'>You slice off [src]'s uneven chunks of aluminium and scorch marks.</span>"
else
return ..()
/obj/item/target/attack_hand(mob/user)
if(pinnedLoc)
pinnedLoc.removeTarget(user)
..()
/obj/item/target/syndicate
icon_state = "target_s"
desc = "A shooting target that looks like a syndicate scum."
hp = 2600
/obj/item/target/alien
icon_state = "target_q"
desc = "A shooting target that looks like a xenomorphic alien."
hp = 2350
/obj/item/target/clown
icon_state = "target_c"
desc = "A shooting target that looks like a useless clown."
hp = 2000
#define DECALTYPE_SCORCH 1
#define DECALTYPE_BULLET 2
/obj/item/target/clown/bullet_act(obj/item/projectile/P)
..()
playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1)
/obj/item/target/bullet_act(obj/item/projectile/P)
var/p_x = P.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset P.p_x!"
var/p_y = P.p_y + pick(0,0,0,0,0,-1,1)
var/decaltype = DECALTYPE_SCORCH
if(istype(/obj/item/projectile/bullet, P))
decaltype = DECALTYPE_BULLET
var/icon/C = icon(icon,icon_state)
if(C.GetPixel(p_x, p_y) && P.original == src && overlays.len <= 35) // if the located pixel isn't blank (null)
hp -= P.damage
if(hp <= 0)
visible_message("<span class='danger'>[src] breaks into tiny pieces and collapses!</span>")
qdel(src)
var/image/I = image("icon"='icons/effects/effects.dmi', "icon_state"="scorch", "layer"=OBJ_LAYER+0.5)
I.pixel_x = p_x - 1 //offset correction
I.pixel_y = p_y - 1
if(decaltype == DECALTYPE_SCORCH)
I.setDir(pick(NORTH,SOUTH,EAST,WEST))// random scorch design
if(P.damage >= 20 || istype(P, /obj/item/projectile/beam/practice))
I.setDir(pick(NORTH,SOUTH,EAST,WEST))
else
I.icon_state = "light_scorch"
else
I.icon_state = "dent"
add_overlay(I)
return
return -1
#undef DECALTYPE_SCORCH
#undef DECALTYPE_BULLET
+49
View File
@@ -0,0 +1,49 @@
/obj/item/stack/spacecash
name = "space cash"
desc = "It's worth 1 credit."
singular_name = "bill"
icon = 'icons/obj/economy.dmi'
icon_state = "spacecash"
amount = 1
max_amount = 20
throwforce = 0
throw_speed = 2
throw_range = 2
w_class = 1
burn_state = FLAMMABLE
var/value = 1
/obj/item/stack/spacecash/c10
icon_state = "spacecash10"
desc = "It's worth 10 credits."
value = 10
/obj/item/stack/spacecash/c20
icon_state = "spacecash20"
desc = "It's worth 20 credits."
value = 20
/obj/item/stack/spacecash/c50
icon_state = "spacecash50"
desc = "It's worth 50 credits."
value = 50
/obj/item/stack/spacecash/c100
icon_state = "spacecash100"
desc = "It's worth 100 credits."
value = 100
/obj/item/stack/spacecash/c200
icon_state = "spacecash200"
desc = "It's worth 200 credits."
value = 200
/obj/item/stack/spacecash/c500
icon_state = "spacecash500"
desc = "It's worth 500 credits."
value = 500
/obj/item/stack/spacecash/c1000
icon_state = "spacecash1000"
desc = "It's worth 1000 credits."
value = 1000
+139
View File
@@ -0,0 +1,139 @@
/obj/item/stack/medical
name = "medical pack"
singular_name = "medical pack"
icon = 'icons/obj/items.dmi'
amount = 6
max_amount = 6
w_class = 1
throw_speed = 3
throw_range = 7
burn_state = FLAMMABLE
burntime = 5
var/heal_brute = 0
var/heal_burn = 0
var/stop_bleeding = 0
var/self_delay = 50
/obj/item/stack/medical/attack(mob/living/M, mob/user)
if(M.stat == 2)
var/t_him = "it"
if(M.gender == MALE)
t_him = "him"
else if(M.gender == FEMALE)
t_him = "her"
user << "<span class='danger'>\The [M] is dead, you cannot help [t_him]!</span>"
return
if(!istype(M, /mob/living/carbon) && !istype(M, /mob/living/simple_animal))
user << "<span class='danger'>You don't know how to apply \the [src] to [M]!</span>"
return 1
var/obj/item/bodypart/affecting
if(ishuman(M))
var/mob/living/carbon/human/H = M
affecting = H.get_bodypart(check_zone(user.zone_selected))
if(!affecting) //Missing limb?
user << "<span class='warning'>[H] doesn't have \a [parse_zone(user.zone_selected)]!</span>"
return
if(stop_bleeding)
if(H.bleedsuppress)
user << "<span class='warning'>[H]'s bleeding is already bandaged!</span>"
return
else if(!H.bleed_rate)
user << "<span class='warning'>[H] isn't bleeding!</span>"
return
if(isliving(M))
if(!M.can_inject(user, 1))
return
if(user)
if (M != user)
if (istype(M, /mob/living/simple_animal))
var/mob/living/simple_animal/critter = M
if (!(critter.healable))
user << "<span class='notice'> You cannot use [src] on [M]!</span>"
return
else if (critter.health == critter.maxHealth)
user << "<span class='notice'> [M] is at full health.</span>"
return
else if(src.heal_brute < 1)
user << "<span class='notice'> [src] won't help [M] at all.</span>"
return
user.visible_message("<span class='green'>[user] applies [src] on [M].</span>", "<span class='green'>You apply [src] on [M].</span>")
else
var/t_himself = "itself"
if(user.gender == MALE)
t_himself = "himself"
else if(user.gender == FEMALE)
t_himself = "herself"
user.visible_message("<span class='notice'>[user] starts to apply [src] on [t_himself]...</span>", "<span class='notice'>You begin applying [src] on yourself...</span>")
if(!do_mob(user, M, self_delay))
return
user.visible_message("<span class='green'>[user] applies [src] on [t_himself].</span>", "<span class='green'>You apply [src] on yourself.</span>")
if(ishuman(M))
var/mob/living/carbon/human/H = M
affecting = H.get_bodypart(check_zone(user.zone_selected))
if(!affecting) //Missing limb?
user << "<span class='warning'>[H] doesn't have \a [parse_zone(user.zone_selected)]!</span>"
return
if(stop_bleeding)
if(!H.bleedsuppress) //so you can't stack bleed suppression
H.suppress_bloodloss(stop_bleeding)
if(affecting.status == ORGAN_ORGANIC) //Limb must be organic to be healed - RR
if(affecting.heal_damage(src.heal_brute, src.heal_burn, 0))
H.update_damage_overlays(0)
M.updatehealth()
else
user << "<span class='notice'>Medicine won't work on a robotic limb!</span>"
else
M.heal_organ_damage((src.heal_brute/2), (src.heal_burn/2))
use(1)
/obj/item/stack/medical/bruise_pack
name = "bruise pack"
singular_name = "bruise pack"
desc = "A theraputic gel pack and bandages designed to treat blunt-force trauma."
icon_state = "brutepack"
heal_brute = 40
origin_tech = "biotech=2"
self_delay = 20
/obj/item/stack/medical/gauze
name = "medical gauze"
desc = "A roll of elastic cloth that is extremely effective at stopping bleeding, but does not heal wounds."
gender = PLURAL
singular_name = "medical gauze"
icon_state = "gauze"
stop_bleeding = 1800
self_delay = 20
/obj/item/stack/medical/gauze/improvised
name = "improvised gauze"
singular_name = "improvised gauze"
desc = "A roll of cloth roughly cut from something that can stop bleeding, but does not heal wounds."
stop_bleeding = 900
/obj/item/stack/medical/gauze/cyborg/
materials = list()
is_cyborg = 1
cost = 250
/obj/item/stack/medical/ointment
name = "ointment"
desc = "Used to treat those nasty burn wounds."
gender = PLURAL
singular_name = "ointment"
icon_state = "ointment"
heal_burn = 40
origin_tech = "biotech=2"
self_delay = 20
+75
View File
@@ -0,0 +1,75 @@
var/global/list/datum/stack_recipe/rod_recipes = list ( \
new/datum/stack_recipe("grille", /obj/structure/grille, 2, time = 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("table frame", /obj/structure/table_frame, 2, time = 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("scooter frame", /obj/item/scooter_frame, 10, time = 25, one_per_turf = 0), \
)
/obj/item/stack/rods
name = "metal rod"
desc = "Some rods. Can be used for building, or something."
singular_name = "metal rod"
icon_state = "rods"
item_state = "rods"
flags = CONDUCT
w_class = 3
force = 9
throwforce = 10
throw_speed = 3
throw_range = 7
materials = list(MAT_METAL=1000)
max_amount = 50
attack_verb = list("hit", "bludgeoned", "whacked")
hitsound = 'sound/weapons/grenadelaunch.ogg'
/obj/item/stack/rods/New(var/loc, var/amount=null)
..()
recipes = rod_recipes
update_icon()
/obj/item/stack/rods/update_icon()
var/amount = get_amount()
if((amount <= 5) && (amount > 0))
icon_state = "rods-[amount]"
else
icon_state = "rods"
/obj/item/stack/rods/attackby(obj/item/W, mob/user, params)
if (istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(get_amount() < 2)
user << "<span class='warning'>You need at least two rods to do this!</span>"
return
if(WT.remove_fuel(0,user))
var/obj/item/stack/sheet/metal/new_item = new(usr.loc)
user.visible_message("[user.name] shaped [src] into metal with the welding tool.", \
"<span class='notice'>You shape [src] into metal with the welding tool.</span>", \
"<span class='italics'>You hear welding.</span>")
var/obj/item/stack/rods/R = src
src = null
var/replace = (user.get_inactive_hand()==R)
R.use(2)
if (!R && replace)
user.put_in_hands(new_item)
else if(istype(W,/obj/item/weapon/reagent_containers/food/snacks))
var/obj/item/weapon/reagent_containers/food/snacks/S = W
if(amount != 1)
user << "<span class='warning'>You must use a single rod!</span>"
else if(S.w_class > 2)
user << "<span class='warning'>The ingredient is too big for [src]!</span>"
else
var/obj/item/weapon/reagent_containers/food/snacks/customizable/A = new/obj/item/weapon/reagent_containers/food/snacks/customizable/kebab(get_turf(src))
A.initialize_custom_food(src, S, user)
else
return ..()
/obj/item/stack/rods/cyborg/
materials = list()
is_cyborg = 1
cost = 250
/obj/item/stack/rods/cyborg/update_icon()
return
@@ -0,0 +1,362 @@
/* Glass stack types
* Contains:
* Glass sheets
* Reinforced glass sheets
* Glass shards - TODO: Move this into code/game/object/item/weapons
*/
/*
* Glass sheets
*/
/obj/item/stack/sheet/glass
name = "glass"
desc = "HOLY SHEET! That is a lot of glass."
singular_name = "glass sheet"
icon_state = "sheet-glass"
materials = list(MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
origin_tech = "materials=1"
/obj/item/stack/sheet/glass/cyborg
materials = list()
is_cyborg = 1
cost = 500
/obj/item/stack/sheet/glass/fifty
amount = 50
/obj/item/stack/sheet/glass/attack_self(mob/user)
construct_window(user)
/obj/item/stack/sheet/glass/attackby(obj/item/W, mob/user, params)
add_fingerprint(user)
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/CC = W
if (get_amount() < 1 || CC.get_amount() < 5)
user << "<span class='warning>You need five lengths of coil and one sheet of glass to make wired glass!</span>"
return
CC.use(5)
use(1)
user << "<span class='notice'>You attach wire to the [name].</span>"
var/obj/item/stack/light_w/new_tile = new(user.loc)
new_tile.add_fingerprint(user)
else if(istype(W, /obj/item/stack/rods))
var/obj/item/stack/rods/V = W
if (V.get_amount() >= 1 && src.get_amount() >= 1)
var/obj/item/stack/sheet/rglass/RG = new (user.loc)
RG.add_fingerprint(user)
var/obj/item/stack/sheet/glass/G = src
src = null
var/replace = (user.get_inactive_hand()==G)
V.use(1)
G.use(1)
if (!G && replace)
user.put_in_hands(RG)
else
user << "<span class='warning'>You need one rod and one sheet of glass to make reinforced glass!</span>"
return
else
return ..()
/obj/item/stack/sheet/glass/proc/construct_window(mob/user)
if(!user || !src)
return 0
if(!istype(user.loc,/turf))
return 0
if(!user.IsAdvancedToolUser())
user << "<span class='warning'>You don't have the dexterity to do this!</span>"
return 0
if(zero_amount())
return 0
var/title = "Sheet-Glass"
title += " ([src.get_amount()] sheet\s left)"
switch(alert(title, "Would you like full tile glass or one direction?", "One Direction", "Full Window", "Cancel", null))
if("One Direction")
if(!src)
return 1
if(src.loc != user)
return 1
var/list/directions = new/list(cardinal)
var/i = 0
for (var/obj/structure/window/win in user.loc)
i++
if(i >= 4)
user << "<span class='warning'>There are too many windows in this location.</span>"
return 1
directions-=win.dir
if(!(win.ini_dir in cardinal))
user << "<span class='danger'>Can't let you do that.</span>"
return 1
//Determine the direction. It will first check in the direction the person making the window is facing, if it finds an already made window it will try looking at the next cardinal direction, etc.
var/dir_to_set = 2
for(var/direction in list( user.dir, turn(user.dir,90), turn(user.dir,180), turn(user.dir,270) ))
var/found = 0
for(var/obj/structure/window/WT in user.loc)
if(WT.dir == direction)
found = 1
if(!found)
dir_to_set = direction
break
var/obj/structure/window/W
W = new /obj/structure/window( user.loc, 0 )
W.setDir(dir_to_set)
W.ini_dir = W.dir
W.anchored = 0
W.air_update_turf(1)
src.use(1)
W.add_fingerprint(user)
if("Full Window")
if(!src)
return 1
if(src.loc != user)
return 1
if(src.get_amount() < 2)
user << "<span class='warning'>You need more glass to do that!</span>"
return 1
if(locate(/obj/structure/window) in user.loc)
user << "<span class='warning'>There is a window in the way!</span>"
return 1
var/obj/structure/window/W
W = new /obj/structure/window/fulltile( user.loc, 0 )
W.anchored = 0
W.air_update_turf(1)
W.add_fingerprint(user)
src.use(2)
return 0
/*
* Reinforced glass sheets
*/
/obj/item/stack/sheet/rglass
name = "reinforced glass"
desc = "Glass which seems to have rods or something stuck in them."
singular_name = "reinforced glass sheet"
icon_state = "sheet-rglass"
materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT/2, MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
origin_tech = "materials=2"
/obj/item/stack/sheet/rglass/cyborg
materials = list()
var/datum/robot_energy_storage/metsource
var/datum/robot_energy_storage/glasource
var/metcost = 250
var/glacost = 500
/obj/item/stack/sheet/rglass/cyborg/get_amount()
return min(round(metsource.energy / metcost), round(glasource.energy / glacost))
/obj/item/stack/sheet/rglass/cyborg/use(amount) // Requires special checks, because it uses two storages
metsource.use_charge(amount * metcost)
glasource.use_charge(amount * glacost)
return
/obj/item/stack/sheet/rglass/cyborg/add(amount)
metsource.add_charge(amount * metcost)
glasource.add_charge(amount * glacost)
return
/obj/item/stack/sheet/rglass/attack_self(mob/user)
construct_window(user)
/obj/item/stack/sheet/rglass/proc/construct_window(mob/user)
if(!user || !src)
return 0
if(!istype(user.loc,/turf))
return 0
if(!user.IsAdvancedToolUser())
user << "<span class='warning'>You don't have the dexterity to do this!</span>"
return 0
var/title = "Sheet Reinf. Glass"
title += " ([src.get_amount()] sheet\s left)"
switch(input(title, "Would you like full tile glass a one direction glass pane or a windoor?") in list("One Direction", "Full Window", "Windoor", "Cancel"))
if("One Direction")
if(!src)
return 1
if(src.loc != user)
return 1
var/list/directions = new/list(cardinal)
var/i = 0
for (var/obj/structure/window/win in user.loc)
i++
if(i >= 4)
user << "<span class='danger'>There are too many windows in this location.</span>"
return 1
directions-=win.dir
if(!(win.ini_dir in cardinal))
user << "<span class='danger'>Can't let you do that.</span>"
return 1
//Determine the direction. It will first check in the direction the person making the window is facing, if it finds an already made window it will try looking at the next cardinal direction, etc.
var/dir_to_set = 2
for(var/direction in list( user.dir, turn(user.dir,90), turn(user.dir,180), turn(user.dir,270) ))
var/found = 0
for(var/obj/structure/window/WT in user.loc)
if(WT.dir == direction)
found = 1
if(!found)
dir_to_set = direction
break
var/obj/structure/window/W
W = new /obj/structure/window/reinforced( user.loc, 1 )
W.state = 0
W.setDir(dir_to_set)
W.ini_dir = W.dir
W.anchored = 0
W.add_fingerprint(user)
src.use(1)
if("Full Window")
if(!src)
return 1
if(src.loc != user)
return 1
if(src.get_amount() < 2)
user << "<span class='warning'>You need more glass to do that!</span>"
return 1
if(locate(/obj/structure/window) in user.loc)
user << "<span class='warning'>There is a window in the way!</span>"
return 1
var/obj/structure/window/W
W = new /obj/structure/window/reinforced/fulltile(user.loc, 1)
W.state = 0
W.anchored = 0
W.add_fingerprint(user)
src.use(2)
if("Windoor")
if(!src || src.loc != user || !isturf(user.loc))
return 1
for(var/obj/structure/windoor_assembly/WA in user.loc)
if(WA.dir == user.dir)
user << "<span class='warning'>There is already a windoor assembly in that location!</span>"
return 1
for(var/obj/machinery/door/window/W in user.loc)
if(W.dir == user.dir)
user << "<span class='warning'>There is already a windoor in that location!</span>"
return 1
if(src.get_amount() < 5)
user << "<span class='warning'>You need more glass to do that!</span>"
return 1
var/obj/structure/windoor_assembly/WD = new(user.loc)
WD.state = "01"
WD.anchored = 0
WD.add_fingerprint(user)
src.use(5)
switch(user.dir)
if(SOUTH)
WD.setDir(SOUTH)
WD.ini_dir = SOUTH
if(EAST)
WD.setDir(EAST)
WD.ini_dir = EAST
if(WEST)
WD.setDir(WEST)
WD.ini_dir = WEST
else //If the user is facing northeast. northwest, southeast, southwest or north, default to north
WD.setDir(NORTH)
WD.ini_dir = NORTH
else
return 1
return 0
/obj/item/weapon/shard
name = "shard"
desc = "A nasty looking shard of glass."
icon = 'icons/obj/shards.dmi'
icon_state = "large"
w_class = 1
force = 5
throwforce = 10
item_state = "shard-glass"
materials = list(MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
attack_verb = list("stabbed", "slashed", "sliced", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
var/cooldown = 0
sharpness = IS_SHARP
/obj/item/weapon/shard/suicide_act(mob/user)
user.visible_message(pick("<span class='suicide'>[user] is slitting \his wrists with the shard of glass! It looks like \he's trying to commit suicide.</span>", \
"<span class='suicide'>[user] is slitting \his throat with the shard of glass! It looks like \he's trying to commit suicide.</span>"))
return (BRUTELOSS)
/obj/item/weapon/shard/New()
icon_state = pick("large", "medium", "small")
switch(icon_state)
if("small")
pixel_x = rand(-12, 12)
pixel_y = rand(-12, 12)
if("medium")
pixel_x = rand(-8, 8)
pixel_y = rand(-8, 8)
if("large")
pixel_x = rand(-5, 5)
pixel_y = rand(-5, 5)
/obj/item/weapon/shard/afterattack(atom/A as mob|obj, mob/user, proximity)
if(!proximity || !(src in user))
return
if(isturf(A))
return
if(istype(A, /obj/item/weapon/storage))
return
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(!H.gloves && !(PIERCEIMMUNE in H.dna.species.specflags)) // golems, etc
H << "<span class='warning'>[src] cuts into your hand!</span>"
var/organ = (H.hand ? "l_" : "r_") + "arm"
var/obj/item/bodypart/affecting = H.get_bodypart(organ)
if(affecting && affecting.take_damage(force / 2))
H.update_damage_overlays(0)
else if(ismonkey(user))
var/mob/living/carbon/monkey/M = user
M << "<span class='warning'>[src] cuts into your hand!</span>"
M.adjustBruteLoss(force / 2)
/obj/item/weapon/shard/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = I
if(WT.remove_fuel(0, user))
var/obj/item/stack/sheet/glass/NG = new (user.loc)
for(var/obj/item/stack/sheet/glass/G in user.loc)
if(G == NG)
continue
if(G.amount >= G.max_amount)
continue
G.attackby(NG, user)
user << "<span class='notice'>You add the newly-formed glass to the stack. It now contains [NG.amount] sheet\s.</span>"
qdel(src)
else
return ..()
/obj/item/weapon/shard/Crossed(mob/AM)
if(istype(AM) && has_gravity(loc))
playsound(loc, 'sound/effects/glass_step.ogg', 50, 1)
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
if(PIERCEIMMUNE in H.dna.species.specflags)
return
var/picked_def_zone = pick("l_leg", "r_leg")
var/obj/item/bodypart/O = H.get_bodypart(picked_def_zone)
if(!istype(O))
return
if(!H.shoes)
H.apply_damage(5, BRUTE, picked_def_zone)
H.Weaken(3)
if(cooldown < world.time - 10) //cooldown to avoid message spam.
H.visible_message("<span class='danger'>[H] steps in the broken glass!</span>", \
"<span class='userdanger'>You step in the broken glass!</span>")
cooldown = world.time
@@ -0,0 +1,210 @@
/obj/item/stack/sheet/animalhide
name = "hide"
desc = "Something went wrong."
origin_tech = "biotech=3"
/obj/item/stack/sheet/animalhide/human
name = "human skin"
desc = "The by-product of human farming."
singular_name = "human skin piece"
icon_state = "sheet-hide"
var/global/list/datum/stack_recipe/human_recipes = list( \
new/datum/stack_recipe("bloated human costume", /obj/item/clothing/suit/hooded/bloated_human, 5, on_floor = 1), \
)
/obj/item/stack/sheet/animalhide/human/New(var/loc, var/amount=null)
recipes = human_recipes
return ..()
/obj/item/stack/sheet/animalhide/generic
name = "generic skin"
desc = "A piece of generic skin."
singular_name = "generic skin piece"
icon_state = "sheet-hide"
/obj/item/stack/sheet/animalhide/corgi
name = "corgi hide"
desc = "The by-product of corgi farming."
singular_name = "corgi hide piece"
icon_state = "sheet-corgi"
var/global/list/datum/stack_recipe/corgi_recipes = list ( \
new/datum/stack_recipe("corgi costume", /obj/item/clothing/suit/hooded/ian_costume, 3, on_floor = 1), \
)
/obj/item/stack/sheet/animalhide/corgi/New(var/loc, var/amount=null)
recipes = corgi_recipes
return ..()
/obj/item/stack/sheet/animalhide/cat
name = "cat hide"
desc = "The by-product of cat farming."
singular_name = "cat hide piece"
icon_state = "sheet-cat"
/obj/item/stack/sheet/animalhide/monkey
name = "monkey hide"
desc = "The by-product of monkey farming."
singular_name = "monkey hide piece"
icon_state = "sheet-monkey"
var/global/list/datum/stack_recipe/monkey_recipes = list ( \
new/datum/stack_recipe("monkey mask", /obj/item/clothing/mask/gas/monkeymask, 1, on_floor = 1), \
new/datum/stack_recipe("monkey suit", /obj/item/clothing/suit/monkeysuit, 2, on_floor = 1), \
)
/obj/item/stack/sheet/animalhide/monkey/New(var/loc, var/amount=null)
recipes = monkey_recipes
return ..()
/obj/item/stack/sheet/animalhide/lizard
name = "lizard skin"
desc = "Sssssss..."
singular_name = "lizard skin piece"
icon_state = "sheet-lizard"
/obj/item/stack/sheet/animalhide/xeno
name = "alien hide"
desc = "The skin of a terrible creature."
singular_name = "alien hide piece"
icon_state = "sheet-xeno"
var/global/list/datum/stack_recipe/xeno_recipes = list ( \
new/datum/stack_recipe("alien helmet", /obj/item/clothing/head/xenos, 1, on_floor = 1), \
new/datum/stack_recipe("alien suit", /obj/item/clothing/suit/xenos, 2, on_floor = 1), \
)
/obj/item/stack/sheet/animalhide/xeno/New(var/loc, var/amount=null)
recipes = xeno_recipes
return ..()
//don't see anywhere else to put these, maybe together they could be used to make the xenos suit?
/obj/item/stack/sheet/xenochitin
name = "alien chitin"
desc = "A piece of the hide of a terrible creature."
singular_name = "alien hide piece"
icon = 'icons/mob/alien.dmi'
icon_state = "chitin"
origin_tech = null
/obj/item/xenos_claw
name = "alien claw"
desc = "The claw of a terrible creature."
icon = 'icons/mob/alien.dmi'
icon_state = "claw"
origin_tech = null
/obj/item/weed_extract
name = "weed extract"
desc = "A piece of slimy, purplish weed."
icon = 'icons/mob/alien.dmi'
icon_state = "weed_extract"
origin_tech = null
/obj/item/stack/sheet/hairlesshide
name = "hairless hide"
desc = "This hide was stripped of it's hair, but still needs tanning."
singular_name = "hairless hide piece"
icon_state = "sheet-hairlesshide"
origin_tech = null
/obj/item/stack/sheet/wetleather
name = "wet leather"
desc = "This leather has been cleaned but still needs to be dried."
singular_name = "wet leather piece"
icon_state = "sheet-wetleather"
origin_tech = null
var/wetness = 30 //Reduced when exposed to high temperautres
var/drying_threshold_temperature = 500 //Kelvin to start drying
/obj/item/stack/sheet/leather
name = "leather"
desc = "The by-product of mob grinding."
singular_name = "leather piece"
icon_state = "sheet-leather"
origin_tech = "materials=2"
/obj/item/stack/sheet/sinew
name = "watcher sinew"
icon = 'icons/obj/mining.dmi'
desc = "Long stringy filaments which presumably came from a watcher's wings."
singular_name = "watcher sinew"
icon_state = "sinew"
origin_tech = "biotech=4"
var/global/list/datum/stack_recipe/sinew_recipes = list ( \
new/datum/stack_recipe("sinew restraints", /obj/item/weapon/restraints/handcuffs/sinew, 1, on_floor = 1), \
)
/obj/item/stack/sheet/sinew/New(var/loc, var/amount=null)
recipes = sinew_recipes
return ..()
/*
* Plates
*/
/obj/item/stack/sheet/animalhide/goliath_hide
name = "goliath hide plates"
desc = "Pieces of a goliath's rocky hide, these might be able to make your suit a bit more durable to attack from the local fauna."
icon = 'icons/obj/mining.dmi'
icon_state = "goliath_hide"
singular_name = "hide plate"
flags = NOBLUDGEON
w_class = 3
layer = MOB_LAYER
/obj/item/stack/sheet/animalhide/ashdrake
name = "ash drake hide"
desc = "The strong, scaled hide of an ash drake."
icon = 'icons/obj/mining.dmi'
icon_state = "dragon_hide"
singular_name = "drake plate"
flags = NOBLUDGEON
w_class = 3
layer = MOB_LAYER
//Step one - dehairing.
/obj/item/stack/sheet/animalhide/attackby(obj/item/weapon/W, mob/user, params)
if(is_sharp(W))
playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1)
user.visible_message("[user] starts cutting hair off \the [src].", "<span class='notice'>You start cutting the hair off \the [src]...</span>", "<span class='italics'>You hear the sound of a knife rubbing against flesh.</span>")
if(do_after(user,50, target = src))
user << "<span class='notice'>You cut the hair from this [src.singular_name].</span>"
//Try locating an exisitng stack on the tile and add to there if possible
for(var/obj/item/stack/sheet/hairlesshide/HS in user.loc)
if(HS.amount < 50)
HS.amount++
use(1)
break
//If it gets to here it means it did not find a suitable stack on the tile.
var/obj/item/stack/sheet/hairlesshide/HS = new(user.loc)
HS.amount = 1
use(1)
else
return ..()
//Step two - washing..... it's actually in washing machine code.
//Step three - drying
/obj/item/stack/sheet/wetleather/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
if(exposed_temperature >= drying_threshold_temperature)
wetness--
if(wetness == 0)
//Try locating an exisitng stack on the tile and add to there if possible
for(var/obj/item/stack/sheet/leather/HS in src.loc)
if(HS.amount < 50)
HS.amount++
src.use(1)
wetness = initial(wetness)
break
//If it gets to here it means it did not find a suitable stack on the tile.
var/obj/item/stack/sheet/leather/HS = new(src.loc)
HS.amount = 1
wetness = initial(wetness)
src.use(1)
@@ -0,0 +1,38 @@
/obj/item/stack/light_w
name = "wired glass tile"
singular_name = "wired glass floor tile"
desc = "A glass tile, which is wired, somehow."
icon = 'icons/obj/tiles.dmi'
icon_state = "glass_wire"
w_class = 3
force = 3
throwforce = 5
throw_speed = 3
throw_range = 7
flags = CONDUCT
max_amount = 60
/obj/item/stack/light_w/attackby(obj/item/O, mob/user, params)
if(istype(O,/obj/item/weapon/wirecutters))
var/obj/item/stack/cable_coil/CC = new (user.loc)
CC.amount = 5
CC.add_fingerprint(user)
amount--
var/obj/item/stack/sheet/glass/G = new (user.loc)
G.add_fingerprint(user)
if(amount <= 0)
user.unEquip(src, 1)
qdel(src)
else if(istype(O, /obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/M = O
if (M.use(1))
use(1)
var/obj/item/stack/tile/light/L = new (user.loc)
user << "<span class='notice'>You make a light tile.</span>"
L.add_fingerprint(user)
else
user << "<span class='warning'>You need one metal sheet to finish the light tile!</span>"
else
return ..()
@@ -0,0 +1,320 @@
/*
Mineral Sheets
Contains:
- Sandstone
- Sandbags
- Diamond
- Snow
- Uranium
- Plasma
- Gold
- Silver
- Clown
Others:
- Adamantine
- Mythril
- Enriched Uranium
- Abductor
*/
/obj/item/stack/sheet/mineral
icon = 'icons/obj/mining.dmi'
/*
* Sandstone
*/
var/global/list/datum/stack_recipe/sandstone_recipes = list ( \
new/datum/stack_recipe("pile of dirt", /obj/machinery/hydroponics/soil, 3, time = 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("sandstone door", /obj/structure/mineral_door/sandstone, 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("Assistant Statue", /obj/structure/statue/sandstone/assistant, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("Breakdown into sand", /obj/item/weapon/ore/glass, 1, one_per_turf = 0, on_floor = 1), \
/* new/datum/stack_recipe("sandstone wall", ???), \
new/datum/stack_recipe("sandstone floor", ???),\ */
)
/obj/item/stack/sheet/mineral/sandstone
name = "sandstone brick"
desc = "This appears to be a combination of both sand and stone."
singular_name = "sandstone brick"
icon_state = "sheet-sandstone"
throw_speed = 3
throw_range = 5
origin_tech = "materials=1"
materials = list(MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
sheettype = "sandstone"
/obj/item/stack/sheet/mineral/sandstone/New(var/loc, var/amount=null)
recipes = sandstone_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
/obj/item/stack/sheet/mineral/sandstone/thirty
amount = 30
/*
* Sandbags
*/
/obj/item/stack/sheet/mineral/sandbags
name = "sandbags"
icon = 'icons/obj/items.dmi'
icon_state = "sandbags"
singular_name = "sandbag"
layer = LOW_ITEM_LAYER
origin_tech = "materials=2"
var/global/list/datum/stack_recipe/sandbag_recipes = list ( \
new/datum/stack_recipe("sandbags", /obj/structure/barricade/sandbags, 1, time = 25, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/sandbags/New(var/loc, var/amount=null)
recipes = sandbag_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
/*
* Diamond
*/
/obj/item/stack/sheet/mineral/diamond
name = "diamond"
icon_state = "sheet-diamond"
singular_name = "diamond"
origin_tech = "materials=6"
sheettype = "diamond"
materials = list(MAT_DIAMOND=MINERAL_MATERIAL_AMOUNT)
var/global/list/datum/stack_recipe/diamond_recipes = list ( \
new/datum/stack_recipe("diamond door", /obj/structure/mineral_door/transparent/diamond, 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("diamond tile", /obj/item/stack/tile/mineral/diamond, 1, 4, 20), \
new/datum/stack_recipe("Captain Statue", /obj/structure/statue/diamond/captain, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("AI Hologram Statue", /obj/structure/statue/diamond/ai1, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("AI Core Statue", /obj/structure/statue/diamond/ai2, 5, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/diamond/New(var/loc, var/amount=null)
recipes = diamond_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
/*
* Uranium
*/
/obj/item/stack/sheet/mineral/uranium
name = "uranium"
icon_state = "sheet-uranium"
singular_name = "uranium sheet"
origin_tech = "materials=5"
sheettype = "uranium"
materials = list(MAT_URANIUM=MINERAL_MATERIAL_AMOUNT)
var/global/list/datum/stack_recipe/uranium_recipes = list ( \
new/datum/stack_recipe("uranium door", /obj/structure/mineral_door/uranium, 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("uranium tile", /obj/item/stack/tile/mineral/uranium, 1, 4, 20), \
new/datum/stack_recipe("Nuke Statue", /obj/structure/statue/uranium/nuke, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("Engineer Statue", /obj/structure/statue/uranium/eng, 5, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/uranium/New(var/loc, var/amount=null)
recipes = uranium_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
/*
* Plasma
*/
/obj/item/stack/sheet/mineral/plasma
name = "solid plasma"
icon_state = "sheet-plasma"
singular_name = "plasma sheet"
origin_tech = "plasmatech=2;materials=2"
sheettype = "plasma"
burn_state = FLAMMABLE
burntime = 5
materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT)
var/global/list/datum/stack_recipe/plasma_recipes = list ( \
new/datum/stack_recipe("plasma door", /obj/structure/mineral_door/transparent/plasma, 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("plasma tile", /obj/item/stack/tile/mineral/plasma, 1, 4, 20), \
new/datum/stack_recipe("Scientist Statue", /obj/structure/statue/plasma/scientist, 5, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/plasma/New(var/loc, var/amount=null)
recipes = plasma_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
/obj/item/stack/sheet/mineral/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma sheets ignited by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) in ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
log_game("Plasma sheets ignited by [key_name(user)] in ([x],[y],[z])")
fire_act()
else
return ..()
/obj/item/stack/sheet/mineral/plasma/fire_act()
atmos_spawn_air("plasma=[amount*10];TEMP=1000")
qdel(src)
/*
* Gold
*/
/obj/item/stack/sheet/mineral/gold
name = "gold"
icon_state = "sheet-gold"
singular_name = "gold bar"
origin_tech = "materials=4"
sheettype = "gold"
materials = list(MAT_GOLD=MINERAL_MATERIAL_AMOUNT)
var/global/list/datum/stack_recipe/gold_recipes = list ( \
new/datum/stack_recipe("golden door", /obj/structure/mineral_door/gold, 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("gold tile", /obj/item/stack/tile/mineral/gold, 1, 4, 20), \
new/datum/stack_recipe("HoS Statue", /obj/structure/statue/gold/hos, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("HoP Statue", /obj/structure/statue/gold/hop, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("CE Statue", /obj/structure/statue/gold/ce, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("RD Statue", /obj/structure/statue/gold/rd, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("CMO Statue", /obj/structure/statue/gold/cmo, 5, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/gold/New(var/loc, var/amount=null)
recipes = gold_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
/*
* Silver
*/
/obj/item/stack/sheet/mineral/silver
name = "silver"
icon_state = "sheet-silver"
singular_name = "silver bar"
origin_tech = "materials=4"
sheettype = "silver"
materials = list(MAT_SILVER=MINERAL_MATERIAL_AMOUNT)
var/global/list/datum/stack_recipe/silver_recipes = list ( \
new/datum/stack_recipe("silver door", /obj/structure/mineral_door/silver, 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("silver tile", /obj/item/stack/tile/mineral/silver, 1, 4, 20), \
new/datum/stack_recipe("Med Officer Statue", /obj/structure/statue/silver/md, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("Janitor Statue", /obj/structure/statue/silver/janitor, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("Sec Officer Statue", /obj/structure/statue/silver/sec, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("Sec Borg Statue", /obj/structure/statue/silver/secborg, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("Med Borg Statue", /obj/structure/statue/silver/medborg, 5, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/silver/New(var/loc, var/amount=null)
recipes = silver_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
/*
* Clown
*/
/obj/item/stack/sheet/mineral/bananium
name = "bananium"
icon_state = "sheet-clown"
singular_name = "bananium sheet"
origin_tech = "materials=4"
sheettype = "clown"
materials = list(MAT_BANANIUM=MINERAL_MATERIAL_AMOUNT)
var/global/list/datum/stack_recipe/clown_recipes = list ( \
new/datum/stack_recipe("bananium tile", /obj/item/stack/tile/mineral/bananium, 1, 4, 20), \
new/datum/stack_recipe("Clown Statue", /obj/structure/statue/bananium/clown, 5, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/mineral/bananium/New(var/loc, var/amount=null)
recipes = clown_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
/*
* Snow
*/
/obj/item/stack/sheet/mineral/snow
name = "snow"
icon_state = "sheet-snow"
singular_name = "snow block"
force = 1
throwforce = 2
origin_tech = "materials=1"
sheettype = "snow"
var/global/list/datum/stack_recipe/snow_recipes = list ( \
new/datum/stack_recipe("Snow Wall",/turf/closed/wall/mineral/snow, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("Snowman", /obj/structure/statue/snow/snowman, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("Snowball", /obj/item/toy/snowball, 1), \
)
/obj/item/stack/sheet/mineral/snow/New(var/loc, var/amount=null)
recipes = snow_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
..()
/****************************** Others ****************************/
/*
* Enriched Uranium
*/
/obj/item/stack/sheet/mineral/enruranium
name = "enriched uranium"
icon_state = "sheet-enruranium"
singular_name = "enriched uranium sheet"
origin_tech = "materials=6"
materials = list(MAT_URANIUM=3000)
/*
* Adamantine
*/
/obj/item/stack/sheet/mineral/adamantine
name = "adamantine"
icon_state = "sheet-adamantine"
singular_name = "adamantine sheet"
origin_tech = "materials=4"
/*
* Mythril
*/
/obj/item/stack/sheet/mineral/mythril
name = "mythril"
icon_state = "sheet-mythril"
singular_name = "mythril sheet"
origin_tech = "materials=4"
/*
* Alien Alloy
*/
/obj/item/stack/sheet/mineral/abductor
name = "alien alloy"
icon = 'icons/obj/abductor.dmi'
icon_state = "sheet-abductor"
singular_name = "alien alloy sheet"
origin_tech = "materials=6;abductor=1"
sheettype = "abductor"
var/global/list/datum/stack_recipe/abductor_recipes = list ( \
/* new/datum/stack_recipe("alien chair", /obj/structure/chair, one_per_turf = 1, on_floor = 1), \ */
new/datum/stack_recipe("alien bed", /obj/structure/bed/abductor, 2, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("alien locker", /obj/structure/closet/abductor, 1, time = 15, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("alien table frame", /obj/structure/table_frame/abductor, 1, time = 15, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("alien airlock assembly", /obj/structure/door_assembly/door_assembly_abductor, 4, time = 20, one_per_turf = 1, on_floor = 1), \
null, \
new/datum/stack_recipe("alien floor tile", /obj/item/stack/tile/mineral/abductor, 1, 4, 20), \
/* null, \
new/datum/stack_recipe("Abductor Agent Statue", /obj/structure/statue/bananium/clown, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("Abductor Sciencist Statue", /obj/structure/statue/bananium/clown, 5, one_per_turf = 1, on_floor = 1)*/
)
/obj/item/stack/sheet/mineral/abductor/New(var/loc, var/amount=null)
recipes = abductor_recipes
..()
@@ -0,0 +1,290 @@
/* Diffrent misc types of sheets
* Contains:
* Metal
* Plasteel
* Wood
* Cloth
* Cardboard
* Runed Metal (cult)
*/
/*
* Metal
*/
var/global/list/datum/stack_recipe/metal_recipes = list ( \
new/datum/stack_recipe("stool", /obj/structure/chair/stool, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("bar stool", /obj/structure/chair/stool/bar, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("chair", /obj/structure/chair, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("swivel chair", /obj/structure/chair/office/dark, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("comfy chair", /obj/structure/chair/comfy/beige, 2, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("bed", /obj/structure/bed, 2, one_per_turf = 1, on_floor = 1), \
null, \
new/datum/stack_recipe("rack parts", /obj/item/weapon/rack_parts), \
new/datum/stack_recipe("closet", /obj/structure/closet, 2, time = 15, one_per_turf = 1, on_floor = 1), \
null, \
new/datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, time = 15, one_per_turf = 1, on_floor = 1), \
null, \
new/datum/stack_recipe("floor tile", /obj/item/stack/tile/plasteel, 1, 4, 20), \
new/datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60), \
null, \
new/datum/stack_recipe("wall girders", /obj/structure/girder, 2, time = 40, one_per_turf = 1, on_floor = 1), \
null, \
new/datum/stack_recipe("computer frame", /obj/structure/frame/computer, 5, time = 25, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("machine frame", /obj/structure/frame/machine, 5, time = 25, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("airlock assembly", /obj/structure/door_assembly, 4, time = 50, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("firelock frame", /obj/structure/firelock_frame, 3, time = 50, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("turret frame", /obj/machinery/porta_turret_construct, 5, time = 25, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("meatspike frame", /obj/structure/kitchenspike_frame, 5, time = 25, one_per_turf = 1, on_floor = 1), \
/* new/datum/stack_recipe("reflector frame", /obj/structure/reflector, 5, time = 25, one_per_turf = 1, on_floor = 1), \*/
null, \
new/datum/stack_recipe("grenade casing", /obj/item/weapon/grenade/chem_grenade), \
new/datum/stack_recipe("light fixture frame", /obj/item/wallframe/light_fixture, 2), \
new/datum/stack_recipe("small light fixture frame", /obj/item/wallframe/light_fixture/small, 1), \
null, \
new/datum/stack_recipe("apc frame", /obj/item/wallframe/apc, 2), \
new/datum/stack_recipe("air alarm frame", /obj/item/wallframe/airalarm, 2), \
new/datum/stack_recipe("fire alarm frame", /obj/item/wallframe/firealarm, 2), \
new/datum/stack_recipe("extinguisher cabinet frame", /obj/item/wallframe/extinguisher_cabinet, 2), \
new/datum/stack_recipe("button frame", /obj/item/wallframe/button, 1), \
null, \
new/datum/stack_recipe("iron door", /obj/structure/mineral_door/iron, 20, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/metal
name = "metal"
desc = "Sheets made out of metal."
singular_name = "metal sheet"
icon_state = "sheet-metal"
materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT)
throwforce = 10
flags = CONDUCT
origin_tech = "materials=1"
/obj/item/stack/sheet/metal/narsie_act()
if(prob(20))
new /obj/item/stack/sheet/runed_metal(loc, amount)
qdel(src)
/obj/item/stack/sheet/metal/fifty
amount = 50
/obj/item/stack/sheet/metal/five
amount = 5
/obj/item/stack/sheet/metal/cyborg
materials = list()
is_cyborg = 1
cost = 500
/obj/item/stack/sheet/metal/New(var/loc, var/amount=null)
recipes = metal_recipes
return ..()
/*
* Plasteel
*/
var/global/list/datum/stack_recipe/plasteel_recipes = list ( \
new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = 1), \
new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50), \
)
/obj/item/stack/sheet/plasteel
name = "plasteel"
singular_name = "plasteel sheet"
desc = "This sheet is an alloy of iron and plasma."
icon_state = "sheet-plasteel"
item_state = "sheet-metal"
materials = list(MAT_METAL=6000, MAT_PLASMA=6000)
throwforce = 10
flags = CONDUCT
origin_tech = "materials=2"
/obj/item/stack/sheet/plasteel/New(var/loc, var/amount=null)
recipes = plasteel_recipes
return ..()
/obj/item/stack/sheet/plasteel/twenty
amount = 20
/obj/item/stack/sheet/plasteel/fifty
amount = 50
/*
* Wood
*/
var/global/list/datum/stack_recipe/wood_recipes = list ( \
new/datum/stack_recipe("wooden sandals", /obj/item/clothing/shoes/sandal, 1), \
new/datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20), \
new/datum/stack_recipe("wood table frame", /obj/structure/table_frame/wood, 2, time = 10), \
new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 40), \
new/datum/stack_recipe("wooden chair", /obj/structure/chair/wood/normal, 3, time = 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("wooden barricade", /obj/structure/barricade/wooden, 5, time = 50, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("coffin", /obj/structure/closet/coffin, 5, time = 15, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("book case", /obj/structure/bookcase, 4, time = 15, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("drying rack", /obj/machinery/smartfridge/drying_rack, 10, time = 15, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("dog bed", /obj/structure/bed/dogbed, 10, time = 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("display case chassis", /obj/structure/displaycase_chassis, 5, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("wooden buckler", /obj/item/weapon/shield/riot/buckler, 20, time = 40), \
new/datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50),\
new/datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 10),\
new/datum/stack_recipe("ore box", /obj/structure/ore_box, 4, time = 50, one_per_turf = 1, on_floor = 1),\
)
/obj/item/stack/sheet/mineral/wood
name = "wooden plank"
desc = "One can only guess that this is a bunch of wood."
singular_name = "wood plank"
icon_state = "sheet-wood"
icon = 'icons/obj/items.dmi'
origin_tech = "materials=1;biotech=1"
sheettype = "wood"
burn_state = FLAMMABLE
/obj/item/stack/sheet/mineral/wood/New(var/loc, var/amount=null)
recipes = wood_recipes
return ..()
/obj/item/stack/sheet/mineral/wood/fifty
amount = 50
/*
* Cloth
*/
var/global/list/datum/stack_recipe/cloth_recipes = list ( \
new/datum/stack_recipe("grey jumpsuit", /obj/item/clothing/under/color/grey, 3), \
null, \
new/datum/stack_recipe("backpack", /obj/item/weapon/storage/backpack, 4), \
new/datum/stack_recipe("dufflebag", /obj/item/weapon/storage/backpack/dufflebag, 6), \
null, \
new/datum/stack_recipe("plant bag", /obj/item/weapon/storage/bag/plants, 4), \
new/datum/stack_recipe("book bag", /obj/item/weapon/storage/bag/books, 4), \
new/datum/stack_recipe("mining satchel", /obj/item/weapon/storage/bag/ore, 4), \
new/datum/stack_recipe("chemistry bag", /obj/item/weapon/storage/bag/chemistry, 4), \
new/datum/stack_recipe("bio bag", /obj/item/weapon/storage/bag/bio, 4), \
null, \
new/datum/stack_recipe("improvised gauze", /obj/item/stack/medical/gauze/improvised, 1, 2, 6), \
new/datum/stack_recipe("rag", /obj/item/weapon/reagent_containers/glass/rag, 1), \
new/datum/stack_recipe("black shoes", /obj/item/clothing/shoes/sneakers/black, 2), \
new/datum/stack_recipe("bedsheet", /obj/item/weapon/bedsheet, 3), \
new/datum/stack_recipe("empty sandbag", /obj/item/weapon/emptysandbag, 4), \
)
/obj/item/stack/sheet/cloth
name = "cloth"
desc = "Is it cotton? Linen? Denim? Burlap? Canvas? You can't tell."
singular_name = "cloth roll"
icon_state = "sheet-cloth"
origin_tech = "materials=2"
burn_state = FLAMMABLE
force = 0
throwforce = 0
/obj/item/stack/sheet/cloth/New(var/loc, var/amount=null)
recipes = cloth_recipes
return ..()
/obj/item/stack/sheet/cloth/ten
amount = 10
/*
* Cardboard
*/
var/global/list/datum/stack_recipe/cardboard_recipes = list ( \
new/datum/stack_recipe("box", /obj/item/weapon/storage/box), \
new/datum/stack_recipe("light tubes", /obj/item/weapon/storage/box/lights/tubes), \
new/datum/stack_recipe("light bulbs", /obj/item/weapon/storage/box/lights/bulbs), \
new/datum/stack_recipe("mouse traps", /obj/item/weapon/storage/box/mousetraps), \
new/datum/stack_recipe("cardborg suit", /obj/item/clothing/suit/cardborg, 3), \
new/datum/stack_recipe("cardborg helmet", /obj/item/clothing/head/cardborg), \
new/datum/stack_recipe("pizza box", /obj/item/pizzabox), \
new/datum/stack_recipe("folder", /obj/item/weapon/folder), \
new/datum/stack_recipe("large box", /obj/structure/closet/cardboard, 4), \
new/datum/stack_recipe("cardboard cutout", /obj/item/cardboard_cutout, 5), \
)
/obj/item/stack/sheet/cardboard //BubbleWrap //it's cardboard you fuck
name = "cardboard"
desc = "Large sheets of card, like boxes folded flat."
singular_name = "cardboard sheet"
icon_state = "sheet-card"
origin_tech = "materials=1"
burn_state = FLAMMABLE
/obj/item/stack/sheet/cardboard/New(var/loc, var/amount=null)
recipes = cardboard_recipes
return ..()
/obj/item/stack/sheet/cardboard/fifty
amount = 50
/*
* Runed Metal
*/
var/global/list/datum/stack_recipe/runed_metal_recipes = list ( \
new/datum/stack_recipe("runed door", /obj/machinery/door/airlock/cult, 3, time = 50, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("runed girder", /obj/structure/girder/cult, 1, time = 50, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("pylon", /obj/structure/cult/pylon, 3, time = 40, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("forge", /obj/structure/cult/forge, 5, time = 40, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("archives", /obj/structure/cult/tome, 2, time = 40, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("altar", /obj/structure/cult/talisman, 5, time = 40, one_per_turf = 1, on_floor = 1), \
)
/obj/item/stack/sheet/runed_metal
name = "runed metal"
desc = "Sheets of cold metal with shifting inscriptions writ upon them."
singular_name = "runed metal"
icon_state = "sheet-runed"
icon = 'icons/obj/items.dmi'
sheettype = "runed"
/obj/item/stack/sheet/runed_metal/attack_self(mob/living/user)
if(!iscultist(user))
user << "<span class='warning'>Only one with forbidden knowledge could hope to work this metal...</span>"
return
return ..()
/obj/item/stack/sheet/runed_metal/attack(atom/target, mob/living/user)
if(!iscultist(user))
user << "<span class='warning'>Only one with forbidden knowledge could hope to work this metal...</span>"
return
..()
/obj/item/stack/sheet/runed_metal/fifty
amount = 50
/obj/item/stack/sheet/runed_metal/New(var/loc, var/amount=null)
recipes = runed_metal_recipes
return ..()
/obj/item/stack/sheet/lessergem
name = "lesser gems"
desc = "Rare kind of gems which are only gained by blood sacrifice to minor deities. They are needed in crafting powerful objects."
singular_name = "lesser gem"
icon_state = "sheet-lessergem"
origin_tech = "materials=4"
/obj/item/stack/sheet/greatergem
name = "greater gems"
desc = "Rare kind of gems which are only gained by blood sacrifice to minor deities. They are needed in crafting powerful objects."
singular_name = "greater gem"
icon_state = "sheet-greatergem"
origin_tech = "materials=7"
/*
* Bones
*/
/obj/item/stack/sheet/bone
name = "bones"
icon = 'icons/obj/mining.dmi'
icon_state = "bone"
singular_name = "bone"
desc = "Someone's been drinking their milk."
force = 7
throwforce = 5
w_class = 3
throw_speed = 1
throw_range = 3
origin_tech = "materials=2;biotech=2"
@@ -0,0 +1,11 @@
/obj/item/stack/sheet
name = "sheet"
w_class = 3
force = 5
throwforce = 5
max_amount = 50
throw_speed = 1
throw_range = 3
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed")
var/perunit = MINERAL_MATERIAL_AMOUNT
var/sheettype = null //this is used for girders in the creation of walls/false walls
+277
View File
@@ -0,0 +1,277 @@
/* Stack type objects!
* Contains:
* Stacks
* Recipe datum
*/
/*
* Stacks
*/
/obj/item/stack
origin_tech = "materials=1"
gender = PLURAL
var/list/datum/stack_recipe/recipes
var/singular_name
var/amount = 1
var/max_amount = 50 //also see stack recipes initialisation, param "max_res_amount" must be equal to this max_amount
var/is_cyborg = 0 // It's 1 if module is used by a cyborg, and uses its storage
var/datum/robot_energy_storage/source
var/cost = 1 // How much energy from storage it costs
var/merge_type = null // This path and its children should merge with this stack, defaults to src.type
/obj/item/stack/New(var/loc, var/amount=null)
..()
if (amount)
src.amount = amount
if(!merge_type)
merge_type = src.type
return
/obj/item/stack/Destroy()
if (usr && usr.machine==src)
usr << browse(null, "window=stack")
return ..()
/obj/item/stack/examine(mob/user)
..()
if (is_cyborg)
if(src.singular_name)
user << "There is enough energy for [src.get_amount()] [src.singular_name]\s."
else
user << "There is enough energy for [src.get_amount()]."
return
if(src.singular_name)
if(src.get_amount()>1)
user << "There are [src.get_amount()] [src.singular_name]\s in the stack."
else
user << "There is [src.get_amount()] [src.singular_name] in the stack."
else if(src.get_amount()>1)
user << "There are [src.get_amount()] in the stack."
else
user << "There is [src.get_amount()] in the stack."
/obj/item/stack/proc/get_amount()
if (is_cyborg)
return round(source.energy / cost)
else
return (amount)
/obj/item/stack/attack_self(mob/user)
interact(user)
/obj/item/stack/interact(mob/user)
if (!recipes)
return
if (!src || get_amount() <= 0)
user << browse(null, "window=stack")
return
user.set_machine(src) //for correct work of onclose
var/t1 = text("<HTML><HEAD><title>Constructions from []</title></HEAD><body><TT>Amount Left: []<br>", src, src.get_amount())
for(var/i=1;i<=recipes.len,i++)
var/datum/stack_recipe/R = recipes[i]
if (isnull(R))
t1 += "<hr>"
continue
if (i>1 && !isnull(recipes[i-1]))
t1+="<br>"
var/max_multiplier = round(src.get_amount() / R.req_amount)
var/title as text
var/can_build = 1
can_build = can_build && (max_multiplier>0)
/*
if (R.one_per_turf)
can_build = can_build && !(locate(R.result_type) in usr.loc)
if (R.on_floor)
can_build = can_build && istype(usr.loc, /turf/open/floor)
*/
if (R.res_amount>1)
title+= "[R.res_amount]x [R.title]\s"
else
title+= "[R.title]"
title+= " ([R.req_amount] [src.singular_name]\s)"
if (can_build)
t1 += text("<A href='?src=\ref[];make=[];multiplier=1'>[]</A> ", src, i, title)
else
t1 += text("[]", title)
continue
if (R.max_res_amount>1 && max_multiplier>1)
max_multiplier = min(max_multiplier, round(R.max_res_amount/R.res_amount))
t1 += " |"
var/list/multipliers = list(5,10,25)
for (var/n in multipliers)
if (max_multiplier>=n)
t1 += " <A href='?src=\ref[src];make=[i];multiplier=[n]'>[n*R.res_amount]x</A>"
if (!(max_multiplier in multipliers))
t1 += " <A href='?src=\ref[src];make=[i];multiplier=[max_multiplier]'>[max_multiplier*R.res_amount]x</A>"
t1 += "</TT></body></HTML>"
user << browse(t1, "window=stack")
onclose(user, "stack")
return
/obj/item/stack/Topic(href, href_list)
..()
if ((usr.restrained() || usr.stat || usr.get_active_hand() != src))
return
if (href_list["make"])
if (src.get_amount() < 1) qdel(src) //Never should happen
var/datum/stack_recipe/R = recipes[text2num(href_list["make"])]
var/multiplier = text2num(href_list["multiplier"])
if (!multiplier ||(multiplier <= 0)) //href protection
return
if(!building_checks(R, multiplier))
return
if (R.time)
usr.visible_message("<span class='notice'>[usr] starts building [R.title].</span>", "<span class='notice'>You start building [R.title]...</span>")
if (!do_after(usr, R.time, target = usr))
return
if(!building_checks(R, multiplier))
return
var/atom/O = new R.result_type( usr.loc )
O.setDir(usr.dir)
use(R.req_amount * multiplier)
//is it a stack ?
if (R.max_res_amount > 1)
var/obj/item/stack/new_item = O
new_item.amount = R.res_amount*multiplier
if(new_item.amount <= 0)//if the stack is empty, i.e it has been merged with an existing stack and has been garbage collected
return
if (istype(O,/obj/item))
usr.put_in_hands(O)
O.add_fingerprint(usr)
//BubbleWrap - so newly formed boxes are empty
if ( istype(O, /obj/item/weapon/storage) )
for (var/obj/item/I in O)
qdel(I)
//BubbleWrap END
if (src && usr.machine==src) //do not reopen closed window
spawn( 0 )
src.interact(usr)
return
return
/obj/item/stack/proc/building_checks(datum/stack_recipe/R, multiplier)
if (src.get_amount() < R.req_amount*multiplier)
if (R.req_amount*multiplier>1)
usr << "<span class='warning'>You haven't got enough [src] to build \the [R.req_amount*multiplier] [R.title]\s!</span>"
else
usr << "<span class='warning'>You haven't got enough [src] to build \the [R.title]!</span>"
return 0
if (R.one_per_turf && (locate(R.result_type) in usr.loc))
usr << "<span class='warning'>There is another [R.title] here!</span>"
return 0
if (R.on_floor && !istype(usr.loc, /turf/open/floor))
usr << "<span class='warning'>\The [R.title] must be constructed on the floor!</span>"
return 0
return 1
/obj/item/stack/proc/use(var/used) // return 0 = borked; return 1 = had enough
if(zero_amount())
return 0
if (is_cyborg)
return source.use_charge(used * cost)
if (amount < used)
return 0
amount -= used
zero_amount()
update_icon()
return 1
/obj/item/stack/proc/zero_amount()
if(is_cyborg)
return source.energy < cost
if(amount < 1)
qdel(src)
return 1
return 0
/obj/item/stack/proc/add(amount)
if (is_cyborg)
source.add_charge(amount * cost)
else
src.amount += amount
update_icon()
/obj/item/stack/proc/merge(obj/item/stack/S) //Merge src into S, as much as possible
var/transfer = get_amount()
if(S.is_cyborg)
transfer = min(transfer, round((S.source.max_energy - S.source.energy) / S.cost))
else
transfer = min(transfer, S.max_amount - S.amount)
if(pulledby)
pulledby.start_pulling(S)
S.copy_evidences(src)
use(transfer)
S.add(transfer)
/obj/item/stack/Crossed(obj/o)
if(istype(o, merge_type) && !o.throwing)
merge(o)
return ..()
/obj/item/stack/hitby(atom/movable/AM, skip, hitpush)
if(istype(AM, merge_type))
merge(AM)
return ..()
/obj/item/stack/attack_hand(mob/user)
if (user.get_inactive_hand() == src)
if(zero_amount())
return
var/obj/item/stack/F = new src.type(user, 1)
. = F
F.copy_evidences(src)
user.put_in_hands(F)
src.add_fingerprint(user)
F.add_fingerprint(user)
use(1)
if (src && usr.machine==src)
spawn(0) src.interact(usr)
else
..()
return
/obj/item/stack/attackby(obj/item/W, mob/user, params)
if(istype(W, merge_type))
var/obj/item/stack/S = W
merge(S)
user << "<span class='notice'>Your [S.name] stack now contains [S.get_amount()] [S.singular_name]\s.</span>"
else
return ..()
/obj/item/stack/proc/copy_evidences(obj/item/stack/from as obj)
src.blood_DNA = from.blood_DNA
src.fingerprints = from.fingerprints
src.fingerprintshidden = from.fingerprintshidden
src.fingerprintslast = from.fingerprintslast
//TODO bloody overlay
/*
* Recipe datum
*/
/datum/stack_recipe
var/title = "ERROR"
var/result_type
var/req_amount = 1
var/res_amount = 1
var/max_res_amount = 1
var/time = 0
var/one_per_turf = 0
var/on_floor = 0
/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0)
src.title = title
src.result_type = result_type
src.req_amount = req_amount
src.res_amount = res_amount
src.max_res_amount = max_res_amount
src.time = time
src.one_per_turf = one_per_turf
src.on_floor = on_floor

Some files were not shown because too many files have changed in this diff Show More