mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-25 13:07:46 +01:00
git-svn-id: http://tgstation13.googlecode.com/svn/trunk@2 316c924e-a436-60f5-8080-3fe189b3f50e
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
/proc/getbrokeninhands()
|
||||
var/icon/IL = new('items_lefthand.dmi')
|
||||
var/list/Lstates = IL.IconStates()
|
||||
var/icon/IR = new('items_righthand.dmi')
|
||||
var/list/Rstates = IR.IconStates()
|
||||
|
||||
|
||||
var/text
|
||||
for(var/A in typesof(/obj/item))
|
||||
var/obj/item/O = new A( locate(1,1,1) )
|
||||
if(!O) continue
|
||||
var/icon/J = new(O.icon)
|
||||
var/list/istates = J.IconStates()
|
||||
if(!Lstates.Find(O.icon_state) && !Lstates.Find(O.item_state))
|
||||
if(O.icon_state)
|
||||
text += "[O.type] WANTS IN LEFT HAND CALLED\n\"[O.icon_state]\".\n"
|
||||
if(!Rstates.Find(O.icon_state) && !Rstates.Find(O.item_state))
|
||||
if(O.icon_state)
|
||||
text += "[O.type] WANTS IN RIGHT HAND CALLED\n\"[O.icon_state]\".\n"
|
||||
|
||||
|
||||
if(O.icon_state)
|
||||
if(!istates.Find(O.icon_state))
|
||||
text += "[O.type] MISSING NORMAL ICON CALLED\n\"[O.icon_state]\" IN \"[O.icon]\"\n"
|
||||
if(O.item_state)
|
||||
if(!istates.Find(O.item_state))
|
||||
text += "[O.type] MISSING NORMAL ICON CALLED\n\"[O.item_state]\" IN \"[O.icon]\"\n"
|
||||
text+="\n"
|
||||
del(O)
|
||||
if(text)
|
||||
var/F = file("broken_icons.txt")
|
||||
fdel(F)
|
||||
F << text
|
||||
world << "Completely successfully and written to [F]"
|
||||
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
/obj/item/weapon/storage/photo_album
|
||||
name = "Photo album"
|
||||
icon = 'old_or_unused.dmi'
|
||||
icon_state = "album"
|
||||
item_state = "briefcase"
|
||||
|
||||
/obj/item/weapon/storage/photo_album/MouseDrop(obj/over_object as obj)
|
||||
|
||||
if ((istype(usr, /mob/living/carbon/human) || (ticker && ticker.mode.name == "monkey")))
|
||||
var/mob/M = usr
|
||||
if (!( istype(over_object, /obj/screen) ))
|
||||
return ..()
|
||||
playsound(src.loc, "rustle", 50, 1, -5)
|
||||
if ((!( M.restrained() ) && !( M.stat ) && M.back == src))
|
||||
if (over_object.name == "r_hand")
|
||||
if (!( M.r_hand ))
|
||||
M.u_equip(src)
|
||||
M.r_hand = src
|
||||
else
|
||||
if (over_object.name == "l_hand")
|
||||
if (!( M.l_hand ))
|
||||
M.u_equip(src)
|
||||
M.l_hand = src
|
||||
M.update_clothing()
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
if(over_object == usr && in_range(src, usr) || usr.contents.Find(src))
|
||||
if (usr.s_active)
|
||||
usr.s_active.close(usr)
|
||||
src.show_to(usr)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/item/weapon/storage/photo_album/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
|
||||
if (src.contents.len >= 7)
|
||||
return
|
||||
|
||||
if (!istype(W,/obj/item/weapon/photo))
|
||||
user << "\red You can only put photos in a photo album."
|
||||
return
|
||||
|
||||
var/t
|
||||
for(var/obj/item/weapon/O in src)
|
||||
t += O.w_class
|
||||
|
||||
playsound(src.loc, "rustle", 50, 1, -5)
|
||||
user.u_equip(W)
|
||||
W.loc = src
|
||||
if ((user.client && user.s_active != src))
|
||||
user.client.screen -= W
|
||||
src.orient2hud(user)
|
||||
W.dropped(user)
|
||||
add_fingerprint(user)
|
||||
for(var/mob/O in viewers(user, null))
|
||||
O.show_message(text("\blue [] has added [] to []!", user, W, src), 1)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/camera_test
|
||||
name = "camera"
|
||||
icon = 'old_or_unused.dmi'
|
||||
desc = "A one use - polaroid camera. 10 photos left."
|
||||
icon_state = "camera"
|
||||
item_state = "electropack"
|
||||
w_class = 2.0
|
||||
flags = 466.0
|
||||
m_amt = 2000
|
||||
throwforce = 5
|
||||
throw_speed = 4
|
||||
throw_range = 10
|
||||
var/pictures_left = 10
|
||||
var/can_use = 1
|
||||
|
||||
/obj/item/weapon/photo
|
||||
name = "photo"
|
||||
icon = 'old_or_unused.dmi'
|
||||
icon_state = "photo"
|
||||
item_state = "clipboard"
|
||||
w_class = 1.0
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/obj/item/weapon/camera_test/proc/build_composite_icon(var/atom/C)
|
||||
var/icon/composite = icon(C.icon, C.icon_state, C.dir, 1)
|
||||
for(var/O in C.overlays)
|
||||
var/image/I = O
|
||||
composite.Blend(icon(I.icon, I.icon_state, I.dir, 1), ICON_OVERLAY)
|
||||
return composite
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/obj/item/weapon/camera_test/attack(mob/living/carbon/human/M as mob, mob/user as mob)
|
||||
return
|
||||
|
||||
/obj/item/weapon/camera_test/afterattack(atom/target as mob|obj|turf|area, mob/user as mob, flag)
|
||||
if (!can_use || !pictures_left || ismob(target.loc)) return
|
||||
|
||||
var/turf/the_turf = get_turf(target)
|
||||
|
||||
var/icon/photo = icon('old_or_unused.dmi',"photo")
|
||||
|
||||
var/icon/turficon = build_composite_icon(the_turf)
|
||||
turficon.Scale(22,20)
|
||||
|
||||
photo.Blend(turficon,ICON_OVERLAY,6,8)
|
||||
|
||||
var/mob_title = null
|
||||
var/mob_detail = null
|
||||
|
||||
var/item_title = null
|
||||
var/item_detail = null
|
||||
|
||||
var/itemnumber = 0
|
||||
for(var/atom/A in the_turf)
|
||||
if(A.invisibility) continue
|
||||
if(ismob(A))
|
||||
var/icon/X = build_composite_icon(A)
|
||||
X.Scale(22,20)
|
||||
photo.Blend(X,ICON_OVERLAY,6,8)
|
||||
del(X)
|
||||
|
||||
if(!mob_title)
|
||||
mob_title = "[A]"
|
||||
else
|
||||
mob_title += " and [A]"
|
||||
|
||||
if(!mob_detail)
|
||||
|
||||
var/holding = null
|
||||
if(istype(A, /mob/living/carbon))
|
||||
var/mob/living/carbon/temp = A
|
||||
if(temp.l_hand || temp.r_hand)
|
||||
if(temp.l_hand) holding = "They are holding \a [temp.l_hand]"
|
||||
if(temp.r_hand)
|
||||
if(holding)
|
||||
holding += " and \a [temp.r_hand]."
|
||||
else
|
||||
holding = "They are holding \a [temp.r_hand]."
|
||||
|
||||
if(!mob_detail)
|
||||
mob_detail = "You can see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]"
|
||||
else
|
||||
mob_detail += "You can also see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]"
|
||||
|
||||
else
|
||||
if(itemnumber < 5)
|
||||
var/icon/X = build_composite_icon(A)
|
||||
X.Scale(22,20)
|
||||
photo.Blend(X,ICON_OVERLAY,6,8)
|
||||
del(X)
|
||||
itemnumber++
|
||||
|
||||
if(!item_title)
|
||||
item_title = " \a [A]"
|
||||
else
|
||||
item_title = " some objects"
|
||||
|
||||
if(!item_detail)
|
||||
item_detail = "\a [A]"
|
||||
else
|
||||
item_detail += " and \a [A]"
|
||||
|
||||
var/finished_title = null
|
||||
var/finished_detail = null
|
||||
|
||||
if(!item_title && !mob_title)
|
||||
finished_title = "boring photo"
|
||||
finished_detail = "This is a pretty boring photo of \a [the_turf]."
|
||||
else
|
||||
if(mob_title)
|
||||
finished_title = "photo of [mob_title][item_title ? " and[item_title]":""]"
|
||||
finished_detail = "[mob_detail][item_detail ? " Theres also [item_detail].":"."]"
|
||||
else if(item_title)
|
||||
finished_title = "photo of[item_title]"
|
||||
finished_detail = "You can see [item_detail]."
|
||||
|
||||
var/obj/item/weapon/photo/P = new/obj/item/weapon/photo( get_turf(src) )
|
||||
|
||||
P.icon = photo
|
||||
P.name = finished_title
|
||||
P.desc = finished_detail
|
||||
|
||||
playsound(src.loc, pick('polaroid1.ogg','polaroid2.ogg'), 75, 1, -3)
|
||||
|
||||
pictures_left--
|
||||
src.desc = "A one use - polaroid camera. [pictures_left] photos left."
|
||||
user << "\blue [pictures_left] photos left."
|
||||
can_use = 0
|
||||
spawn(50) can_use = 1
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
#define TOUCH 1
|
||||
#define INGEST 2
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
datum
|
||||
reagents
|
||||
var/list/reagent_list = new/list()
|
||||
var/total_volume = 0
|
||||
var/maximum_volume = 100
|
||||
var/atom/my_atom = null
|
||||
|
||||
New(maximum=100)
|
||||
maximum_volume = maximum
|
||||
|
||||
proc
|
||||
|
||||
remove_any(var/amount=1)
|
||||
var/total_transfered = 0
|
||||
var/current_list_element = 1
|
||||
|
||||
current_list_element = rand(1,reagent_list.len)
|
||||
|
||||
while(total_transfered != amount)
|
||||
if(total_transfered >= amount) break
|
||||
if(total_volume <= 0 || !reagent_list.len) break
|
||||
|
||||
if(current_list_element > reagent_list.len) current_list_element = 1
|
||||
var/datum/reagent/current_reagent = reagent_list[current_list_element]
|
||||
|
||||
src.remove_reagent(current_reagent.id, 1)
|
||||
|
||||
current_list_element++
|
||||
total_transfered++
|
||||
src.update_total()
|
||||
|
||||
handle_reactions()
|
||||
return total_transfered
|
||||
|
||||
get_master_reagent_name()
|
||||
var/the_name = null
|
||||
var/the_volume = 0
|
||||
for(var/datum/reagent/A in reagent_list)
|
||||
if(A.volume > the_volume)
|
||||
the_volume = A.volume
|
||||
the_name = A.name
|
||||
|
||||
return the_name
|
||||
|
||||
trans_to(var/obj/target, var/amount=1, var/multiplier=1)
|
||||
var/total_transfered = 0
|
||||
var/current_list_element = 1
|
||||
var/datum/reagents/R = target.reagents
|
||||
//if(R.total_volume + amount > R.maximum_volume) return 0
|
||||
|
||||
current_list_element = rand(1,reagent_list.len) //Eh, bandaid fix.
|
||||
|
||||
while(total_transfered != amount)
|
||||
if(total_transfered >= amount) break //Better safe than sorry.
|
||||
if(total_volume <= 0 || !reagent_list.len) break
|
||||
if(R.total_volume >= R.maximum_volume) break
|
||||
|
||||
if(current_list_element > reagent_list.len) current_list_element = 1
|
||||
var/datum/reagent/current_reagent = reagent_list[current_list_element]
|
||||
|
||||
R.add_reagent(current_reagent.id, (1 * multiplier) )
|
||||
src.remove_reagent(current_reagent.id, 1)
|
||||
|
||||
current_list_element++
|
||||
total_transfered++
|
||||
src.update_total()
|
||||
R.update_total()
|
||||
|
||||
R.handle_reactions()
|
||||
handle_reactions()
|
||||
|
||||
return total_transfered
|
||||
|
||||
metabolize(var/mob/M)
|
||||
for(var/A in reagent_list)
|
||||
var/datum/reagent/R = A
|
||||
R.on_mob_life(M)
|
||||
update_total()
|
||||
|
||||
handle_reactions()
|
||||
|
||||
if(ismob(my_atom)) return //No reactions inside mobs :I
|
||||
|
||||
for(var/A in typesof(/datum/chemical_reaction) - /datum/chemical_reaction)
|
||||
var/datum/chemical_reaction/C = new A()
|
||||
var/total_required_reagents = C.required_reagents.len
|
||||
var/total_matching_reagents = 0
|
||||
var/list/multipliers = new/list()
|
||||
|
||||
for(var/B in C.required_reagents)
|
||||
if(has_reagent(B, C.required_reagents[B]))
|
||||
total_matching_reagents++
|
||||
multipliers += round(get_reagent_amount(B) / C.required_reagents[B])
|
||||
|
||||
if(total_matching_reagents == total_required_reagents)
|
||||
var/multiplier = min(multipliers)
|
||||
for(var/B in C.required_reagents)
|
||||
del_reagent(B)
|
||||
|
||||
var/created_volume = C.result_amount*multiplier
|
||||
if(C.result)
|
||||
multiplier = max(multiplier, 1) //this shouldnt happen ...
|
||||
add_reagent(C.result, C.result_amount*multiplier)
|
||||
|
||||
for(var/mob/M in viewers(4, get_turf(my_atom)) )
|
||||
M << "\blue \icon[my_atom] The solution begins to bubble."
|
||||
playsound(get_turf(my_atom), 'bubbles.ogg', 80, 1)
|
||||
|
||||
C.on_reaction(src, created_volume)
|
||||
|
||||
update_total()
|
||||
return 0
|
||||
|
||||
isolate_reagent(var/reagent)
|
||||
for(var/A in reagent_list)
|
||||
var/datum/reagent/R = A
|
||||
if (R.id != reagent)
|
||||
del_reagent(R.id)
|
||||
update_total()
|
||||
|
||||
del_reagent(var/reagent)
|
||||
for(var/A in reagent_list)
|
||||
var/datum/reagent/R = A
|
||||
if (R.id == reagent)
|
||||
reagent_list -= A
|
||||
del(A)
|
||||
update_total()
|
||||
my_atom.on_reagent_change()
|
||||
return 0
|
||||
|
||||
|
||||
return 1
|
||||
|
||||
update_total()
|
||||
total_volume = 0
|
||||
for(var/datum/reagent/R in reagent_list)
|
||||
if(R.volume < 1)
|
||||
del_reagent(R.id)
|
||||
else
|
||||
total_volume += R.volume
|
||||
|
||||
return 0
|
||||
|
||||
clear_reagents()
|
||||
for(var/datum/reagent/R in reagent_list)
|
||||
del_reagent(R.id)
|
||||
return 0
|
||||
|
||||
reaction(var/atom/A, var/method=TOUCH, var/volume_modifier=0)
|
||||
switch(method)
|
||||
if(TOUCH)
|
||||
for(var/datum/reagent/R in reagent_list)
|
||||
if(ismob(A)) spawn(0) R.reaction_mob(A, TOUCH, R.volume+volume_modifier)
|
||||
if(isturf(A)) spawn(0) R.reaction_turf(A, R.volume+volume_modifier)
|
||||
if(isobj(A)) spawn(0) R.reaction_obj(A, R.volume+volume_modifier)
|
||||
if(INGEST)
|
||||
for(var/datum/reagent/R in reagent_list)
|
||||
if(ismob(A)) spawn(0) R.reaction_mob(A, INGEST, R.volume+volume_modifier)
|
||||
if(isturf(A)) spawn(0) R.reaction_turf(A, R.volume+volume_modifier)
|
||||
if(isobj(A)) spawn(0) R.reaction_obj(A, R.volume+volume_modifier)
|
||||
return
|
||||
|
||||
add_reagent(var/reagent, var/amount)
|
||||
if(!isnum(amount)) return 1
|
||||
update_total()
|
||||
if(total_volume + amount > maximum_volume) amount = (maximum_volume - total_volume) //Doesnt fit in. Make it disappear. Shouldnt happen. Will happen.
|
||||
|
||||
for(var/A in reagent_list)
|
||||
var/datum/reagent/R = A
|
||||
if (R.id == reagent)
|
||||
R.volume += amount
|
||||
update_total()
|
||||
my_atom.on_reagent_change()
|
||||
return 0
|
||||
|
||||
for(var/A in typesof(/datum/reagent) - /datum/reagent)
|
||||
var/datum/reagent/R = new A()
|
||||
if (R.id == reagent)
|
||||
reagent_list += R
|
||||
R.holder = src
|
||||
R.volume = amount
|
||||
update_total()
|
||||
my_atom.on_reagent_change()
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
remove_reagent(var/reagent, var/amount)
|
||||
|
||||
if(!isnum(amount)) return 1
|
||||
|
||||
for(var/A in reagent_list)
|
||||
var/datum/reagent/R = A
|
||||
if (R.id == reagent)
|
||||
R.volume -= amount
|
||||
update_total()
|
||||
handle_reactions()
|
||||
my_atom.on_reagent_change()
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
has_reagent(var/reagent, var/amount = -1)
|
||||
|
||||
for(var/A in reagent_list)
|
||||
var/datum/reagent/R = A
|
||||
if (R.id == reagent)
|
||||
if(!amount) return 1
|
||||
else
|
||||
if(R.volume >= amount) return 1
|
||||
else return 0
|
||||
|
||||
return 0
|
||||
|
||||
get_reagent_amount(var/reagent)
|
||||
for(var/A in reagent_list)
|
||||
var/datum/reagent/R = A
|
||||
if (R.id == reagent)
|
||||
return R.volume
|
||||
|
||||
return 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Convenience proc to create a reagents holder for an atom
|
||||
// Max vol is maximum volume of holder
|
||||
atom/proc/create_reagents(var/max_vol)
|
||||
reagents = new/datum/reagents(max_vol)
|
||||
reagents.my_atom = src
|
||||
@@ -0,0 +1,231 @@
|
||||
#define SOLID 1
|
||||
#define LIQUID 2
|
||||
#define GAS 3
|
||||
|
||||
/obj/machinery/chem_dispenser/
|
||||
name = "chem dispenser"
|
||||
density = 1
|
||||
anchored = 1
|
||||
icon = 'chemical.dmi'
|
||||
icon_state = "dispenser"
|
||||
var/energy = 25
|
||||
var/max_energy = 25
|
||||
var/list/dispensable_reagents = list("water","oxygen","nitrogen","hydrogen","potassium","mercury","sulfur","carbon","chlorine","fluorine","phosphorus","lithium","acid","radium","iron","aluminium","silicon","plasma","sugar","ethanol")
|
||||
|
||||
proc
|
||||
recharge()
|
||||
if(stat & BROKEN) return
|
||||
if(energy != max_energy)
|
||||
energy++
|
||||
use_power(50)
|
||||
spawn(600) recharge()
|
||||
|
||||
New()
|
||||
recharge()
|
||||
|
||||
ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
del(src)
|
||||
return
|
||||
|
||||
blob_act()
|
||||
if (prob(25))
|
||||
del(src)
|
||||
|
||||
meteorhit()
|
||||
del(src)
|
||||
return
|
||||
|
||||
Topic(href, href_list)
|
||||
if(stat & BROKEN) return
|
||||
if(usr.stat || usr.restrained()) return
|
||||
if(!in_range(src, usr)) return
|
||||
|
||||
usr.machine = src
|
||||
|
||||
if (href_list["dispense"])
|
||||
if(!energy)
|
||||
var/dat = "Not enough energy.<BR><A href='?src=\ref[src];ok=1'>OK</A>"
|
||||
usr << browse("<TITLE>Chemical Dispenser</TITLE>Chemical dispenser:<BR>Energy = [energy]/[max_energy]<BR><BR>[dat]", "window=chem_dispenser")
|
||||
return
|
||||
var/id = href_list["dispense"]
|
||||
var/obj/item/weapon/reagent_containers/glass/dispenser/G = new/obj/item/weapon/reagent_containers/glass/dispenser(src.loc)
|
||||
switch(text2num(href_list["state"]))
|
||||
if(LIQUID)
|
||||
G.icon_state = "liquid"
|
||||
if(GAS)
|
||||
G.icon_state = "vapour"
|
||||
if(SOLID)
|
||||
G.icon_state = "solid"
|
||||
G.name += " ([lowertext(href_list["name"])])"
|
||||
G.reagents.add_reagent(id,30)
|
||||
energy--
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
else
|
||||
usr << browse(null, "window=chem_dispenser")
|
||||
return
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
attack_ai(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
attack_paw(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
user.machine = src
|
||||
var/dat = ""
|
||||
for(var/re in dispensable_reagents)
|
||||
for(var/da in typesof(/datum/reagent) - /datum/reagent)
|
||||
var/datum/reagent/temp = new da()
|
||||
if(temp.id == re)
|
||||
dat += "<A href='?src=\ref[src];dispense=[temp.id];state=[temp.reagent_state];name=[temp.name]'>[temp.name]</A><BR>"
|
||||
dat += "[temp.description]<BR><BR>"
|
||||
user << browse("<TITLE>Chemical Dispenser</TITLE>Chemical dispenser:<BR>Energy = [energy]/[max_energy]<BR><BR>[dat]", "window=chem_dispenser")
|
||||
|
||||
onclose(user, "chem_dispenser")
|
||||
return
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/obj/machinery/chem_master/
|
||||
name = "CheMaster 3000"
|
||||
density = 1
|
||||
anchored = 1
|
||||
icon = 'chemical.dmi'
|
||||
icon_state = "mixer0"
|
||||
var/beaker = null
|
||||
|
||||
ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
del(src)
|
||||
return
|
||||
|
||||
blob_act()
|
||||
if (prob(25))
|
||||
del(src)
|
||||
|
||||
meteorhit()
|
||||
del(src)
|
||||
return
|
||||
|
||||
attackby(var/obj/item/weapon/reagent_containers/glass/B as obj, var/mob/user as mob)
|
||||
if(!istype(B, /obj/item/weapon/reagent_containers/glass))
|
||||
return
|
||||
|
||||
if(src.beaker)
|
||||
user << "A beaker is already loaded into the machine."
|
||||
return
|
||||
|
||||
src.beaker = B
|
||||
user.drop_item()
|
||||
B.loc = src
|
||||
user << "You add the beaker to the machine!"
|
||||
src.updateUsrDialog()
|
||||
icon_state = "mixer1"
|
||||
|
||||
Topic(href, href_list)
|
||||
if(stat & BROKEN) return
|
||||
if(usr.stat || usr.restrained()) return
|
||||
if(!in_range(src, usr)) return
|
||||
|
||||
usr.machine = src
|
||||
if(!beaker) return
|
||||
var/datum/reagents/R = beaker:reagents
|
||||
|
||||
if (href_list["isolate"])
|
||||
R.isolate_reagent(href_list["isolate"])
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
else if (href_list["remove"])
|
||||
R.del_reagent(href_list["remove"])
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
else if (href_list["remove5"])
|
||||
R.remove_reagent(href_list["remove5"], 5)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
else if (href_list["remove1"])
|
||||
R.remove_reagent(href_list["remove1"], 1)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
else if (href_list["analyze"])
|
||||
var/dat = "<TITLE>Chemmaster 3000</TITLE>Chemical infos:<BR><BR>Name:<BR>[href_list["name"]]<BR><BR>Description:<BR>[href_list["desc"]]<BR><BR><BR><A href='?src=\ref[src];main=1'>(Back)</A>"
|
||||
usr << browse(dat, "window=chem_master;size=575x400")
|
||||
return
|
||||
else if (href_list["main"])
|
||||
attack_hand(usr)
|
||||
return
|
||||
else if (href_list["eject"])
|
||||
beaker:loc = src.loc
|
||||
beaker = null
|
||||
icon_state = "mixer0"
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
else if (href_list["createpill"])
|
||||
var/obj/item/weapon/reagent_containers/pill/P = new/obj/item/weapon/reagent_containers/pill(src.loc)
|
||||
var/name = input(usr,"Name:","Name your pill!",R.get_master_reagent_name())
|
||||
if(!name || name == " ") name = R.get_master_reagent_name()
|
||||
P.name = "[name] pill"
|
||||
R.trans_to(P,R.total_volume)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
else if (href_list["createbottle"])
|
||||
var/obj/item/weapon/reagent_containers/glass/bottle/P = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc)
|
||||
var/name = input(usr,"Name:","Name your bottle!",R.get_master_reagent_name())
|
||||
if(!name || name == " ") name = R.get_master_reagent_name()
|
||||
P.name = "[name] bottle"
|
||||
R.trans_to(P,30)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
else
|
||||
usr << browse(null, "window=chem_master")
|
||||
return
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
attack_ai(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
attack_paw(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
user.machine = src
|
||||
var/dat = ""
|
||||
if(!beaker)
|
||||
dat = "Please insert beaker.<BR>"
|
||||
dat += "<A href='?src=\ref[src];close=1'>Close</A>"
|
||||
else
|
||||
var/datum/reagents/R = beaker:reagents
|
||||
dat += "<A href='?src=\ref[src];eject=1'>Eject beaker</A><BR><BR>"
|
||||
if(!R.total_volume)
|
||||
dat += "Beaker is empty."
|
||||
else
|
||||
dat += "Contained reagents:<BR>"
|
||||
for(var/datum/reagent/G in R.reagent_list)
|
||||
dat += "[G.name] , [G.volume] Units - <A href='?src=\ref[src];isolate=[G.id]'>(Isolate)</A> <A href='?src=\ref[src];remove=[G.id]'>(Remove all)</A> <A href='?src=\ref[src];remove5=[G.id]'>(Remove 5)</A> <A href='?src=\ref[src];remove1=[G.id]'>(Remove 1)</A> <A href='?src=\ref[src];analyze=1;desc=[G.description];name=[G.name]'>(Analyze)</A><BR>"
|
||||
dat += "<BR><A href='?src=\ref[src];createpill=1'>Create pill</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];createbottle=1'>Create bottle (30 units max)</A>"
|
||||
user << browse("<TITLE>Chemmaster 3000</TITLE>Chemmaster menu:<BR><BR>[dat]", "window=chem_master;size=575x400")
|
||||
onclose(user, "chem_master")
|
||||
return
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
NOTE: IF YOU UPDATE THE REAGENT-SYSTEM, ALSO UPDATE THIS README.
|
||||
|
||||
Structure: /////////////////// //////////////////////////
|
||||
// Mob or object // -------> // Reagents var (datum) // Is a reference to the datum that holds the reagents.
|
||||
/////////////////// //////////////////////////
|
||||
| |
|
||||
The object that holds everything. V
|
||||
reagent_list var (list) A List of datums, each datum is a reagent.
|
||||
|
||||
| | |
|
||||
V V V
|
||||
|
||||
reagents (datums) Reagents. I.e. Water , antitoxins or mercury.
|
||||
|
||||
|
||||
Random important notes:
|
||||
|
||||
An objects on_reagent_change will be called every time the objects reagents change.
|
||||
Useful if you want to update the objects icon etc.
|
||||
|
||||
About the Holder:
|
||||
|
||||
The holder (reagents datum) is the datum that holds a list of all reagents
|
||||
currently in the object.It also has all the procs needed to manipulate reagents
|
||||
|
||||
remove_any(var/amount)
|
||||
This proc removes reagents from the holder until the passed amount
|
||||
is matched. It'll try to remove some of ALL reagents contained.
|
||||
|
||||
trans_to(var/obj/target, var/amount)
|
||||
This proc equally transfers the contents of the holder to another
|
||||
objects holder. You need to pass it the object (not the holder) you want
|
||||
to transfer to and the amount you want to transfer. Its return value is the
|
||||
actual amount transfered (if one of the objects is full/empty)
|
||||
|
||||
metabolize(var/mob/M)
|
||||
This proc is called by the mobs life proc. It simply calls on_mob_life for
|
||||
all contained reagents. You shouldnt have to use this one directly.
|
||||
|
||||
handle_reactions()
|
||||
This proc check all recipes and, on a match, uses them.
|
||||
It will also call the recipe's on_reaction proc (for explosions or w/e).
|
||||
Currently, this proc is automatically called by trans_to.
|
||||
|
||||
isolate_reagent(var/reagent)
|
||||
Pass it a reagent id and it will remove all reagents but that one.
|
||||
It's that simple.
|
||||
|
||||
del_reagent(var/reagent)
|
||||
Completely remove the reagent with the matching id.
|
||||
|
||||
reaction_fire(exposed_temp)
|
||||
Simply calls the reaction_fire procs of all contained reagents.
|
||||
|
||||
update_total()
|
||||
This one simply updates the total volume of the holder.
|
||||
(the volume of all reagents added together)
|
||||
|
||||
clear_reagents()
|
||||
This proc removes ALL reagents from the holder.
|
||||
|
||||
reaction(var/atom/A, var/method=TOUCH, var/volume_modifier=0)
|
||||
This proc calls the appropriate reaction procs of the reagents.
|
||||
I.e. if A is an object, it will call the reagents reaction_obj
|
||||
proc. The method var is used for reaction on mobs. It simply tells
|
||||
us if the mob TOUCHed the reagent or if it INGESTed the reagent.
|
||||
Since the volume can be checked in a reagents proc, you might want to
|
||||
use the volume_modifier var to modifiy the passed value without actually
|
||||
changing the volume of the reagents.
|
||||
If you're not sure if you need to use this the answer is very most likely 'No'.
|
||||
You'll want to use this proc whenever an atom first comes in
|
||||
contact with the reagents of a holder. (in the 'splash' part of a beaker i.e.)
|
||||
More on the reaction in the reagent part of this readme.
|
||||
|
||||
add_reagent(var/reagent, var/amount)
|
||||
Attempts to add X of the matching reagent to the holder.
|
||||
You wont use this much. Mostly in new procs for pre-filled
|
||||
objects.
|
||||
|
||||
remove_reagent(var/reagent, var/amount)
|
||||
The exact opposite of the add_reagent proc.
|
||||
|
||||
has_reagent(var/reagent, var/amount)
|
||||
Returns 1 if the holder contains this reagent.
|
||||
Or 0 if not.
|
||||
If you pass it an amount it will additionally check
|
||||
if the amount is matched. This is optional.
|
||||
|
||||
get_reagent_amount(var/reagent)
|
||||
Returns the amount of the matching reagent inside the
|
||||
holder. Returns 0 if the reagent is missing.
|
||||
|
||||
Important variables:
|
||||
|
||||
total_volume
|
||||
This variable contains the total volume of all reagents in this holder.
|
||||
|
||||
reagent_list
|
||||
This is a list of all contained reagents. More specifically, references
|
||||
to the reagent datums.
|
||||
|
||||
maximum_volume
|
||||
This is the maximum volume of the holder.
|
||||
|
||||
my_atom
|
||||
This is the atom the holder is 'in'. Useful if you need to find the location.
|
||||
(i.e. for explosions)
|
||||
|
||||
|
||||
About Reagents:
|
||||
|
||||
Reagents are all the things you can mix and fille in bottles etc. This can be anything from
|
||||
rejuvs over water to ... iron. Each reagent also has a few procs - i'll explain those below.
|
||||
|
||||
reaction_mob(var/mob/M, var/method=TOUCH)
|
||||
This is called by the holder's reation proc.
|
||||
This version is only called when the reagent
|
||||
reacts with a mob. The method var can be either
|
||||
TOUCH or INGEST. You'll want to put stuff like
|
||||
acid-facemelting in here.
|
||||
|
||||
reaction_obj(var/obj/O)
|
||||
This is called by the holder's reation proc.
|
||||
This version is called when the reagents reacts
|
||||
with an object. You'll want to put stuff like
|
||||
object melting in here ... or something. i dunno.
|
||||
|
||||
reaction_turf(var/turf/T)
|
||||
This is called by the holder's reation proc.
|
||||
This version is called when the reagents reacts
|
||||
with a turf. You'll want to put stuff like extra
|
||||
slippery floors for lube or something in here.
|
||||
|
||||
on_mob_life(var/mob/M)
|
||||
This proc is called everytime the mobs life proc executes.
|
||||
This is the place where you put damage for toxins ,
|
||||
drowsyness for sleep toxins etc etc.
|
||||
You'll want to call the parents proc by using ..() .
|
||||
If you dont, the chemical will stay in the mob forever -
|
||||
unless you write your own piece of code to slowly remove it.
|
||||
(Should be pretty easy, 1 line of code)
|
||||
|
||||
Important variables:
|
||||
|
||||
holder
|
||||
This variable contains a reference to the holder the chemical is 'in'
|
||||
|
||||
volume
|
||||
This is the volume of the reagent.
|
||||
|
||||
id
|
||||
The id of the reagent
|
||||
|
||||
name
|
||||
The name of the reagent.
|
||||
|
||||
data
|
||||
This var can be used for whatever the fuck you want. I used it for the sleep
|
||||
toxins to make them work slowly instead of instantly. You could also use this
|
||||
for DNA in a blood reagent or ... well whatever you want.
|
||||
|
||||
|
||||
About Recipes:
|
||||
|
||||
Recipes are simple datums that contain a list of required reagents and a result.
|
||||
They also have a proc that is called when the recipe is matched.
|
||||
|
||||
on_reaction(var/datum/reagents/holder, var/created_volume)
|
||||
This proc is called when the recipe is matched.
|
||||
You'll want to add explosions etc here.
|
||||
To find the location you'll have to do something
|
||||
like get_turf(holder.my_atom)
|
||||
|
||||
name & id
|
||||
Should be pretty obvious.
|
||||
|
||||
result
|
||||
This var contains the id of the resulting reagent.
|
||||
|
||||
required_reagents
|
||||
This is a list of ids of the required reagents.
|
||||
Each id also needs an associated value that gives us the minimum required amount
|
||||
of that reagent. The handle_reaction proc can detect mutiples of the same recipes
|
||||
so for most cases you want to set the required amount to 1.
|
||||
|
||||
result_amount
|
||||
This is the amount of the resulting reagent this recipe will produce.
|
||||
I recommend you set this to the total volume of all required reagent.
|
||||
|
||||
|
||||
About the Tools:
|
||||
|
||||
By default, all atom have a reagents var - but its empty. if you want to use an object for the chem.
|
||||
system you'll need to add something like this in its new proc:
|
||||
|
||||
var/datum/reagents/R = new/datum/reagents(100) <<<<< create a new datum , 100 is the maximum_volume of the new holder datum.
|
||||
reagents = R <<<<< assign the new datum to the objects reagents var
|
||||
R.my_atom = src <<<<< set the holders my_atom to src so that we know where we are.
|
||||
|
||||
This can also be done by calling a convenience proc:
|
||||
atom/proc/create_reagents(var/max_volume)
|
||||
|
||||
Other important stuff:
|
||||
|
||||
amount_per_transfer_from_this var
|
||||
This var is mostly used by beakers and bottles.
|
||||
It simply tells us how much to transfer when
|
||||
'pouring' our reagents into something else.
|
||||
|
||||
atom/proc/is_open_container()
|
||||
Checks atom/var/flags & OPENCONTAINER.
|
||||
If this returns 1 , you can use syringes, beakers etc
|
||||
to manipulate the contents of this object.
|
||||
If it's 0, you'll need to write your own custom reagent
|
||||
transfer code since you will not be able to use the standard
|
||||
tools to manipulate it.
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,920 @@
|
||||
#define SOLID 1
|
||||
#define LIQUID 2
|
||||
#define GAS 3
|
||||
|
||||
//The reaction procs must ALWAYS set src = null, this detaches the proc from the object (the reagent)
|
||||
//so that it can continue working when the reagent is deleted while the proc is still active.
|
||||
|
||||
datum
|
||||
reagent
|
||||
var/name = "Reagent"
|
||||
var/id = "reagent"
|
||||
var/description = ""
|
||||
var/datum/reagents/holder = null
|
||||
var/reagent_state = SOLID
|
||||
var/data = null
|
||||
var/volume = 0
|
||||
|
||||
proc
|
||||
reaction_mob(var/mob/M, var/method=TOUCH, var/volume) //By default we have a chance to transfer some
|
||||
var/datum/reagent/self = src
|
||||
src = null //of the reagent to the mob on TOUCHING it.
|
||||
if(method == TOUCH)
|
||||
|
||||
var/chance = 1
|
||||
for(var/obj/item/clothing/C in M.get_equipped_items())
|
||||
if(C.permeability_coefficient < chance) chance = C.permeability_coefficient
|
||||
chance = chance * 100
|
||||
|
||||
if(prob(chance))
|
||||
if(M.reagents)
|
||||
M.reagents.add_reagent(self.id,self.volume/2)
|
||||
return
|
||||
|
||||
reaction_obj(var/obj/O, var/volume) //By default we transfer a small part of the reagent to the object
|
||||
src = null //if it can hold reagents. nope!
|
||||
//if(O.reagents)
|
||||
// O.reagents.add_reagent(id,volume/3)
|
||||
return
|
||||
|
||||
reaction_turf(var/turf/T, var/volume)
|
||||
src = null
|
||||
return
|
||||
|
||||
on_mob_life(var/mob/M)
|
||||
holder.remove_reagent(src.id, 0.4) //By default it slowly disappears.
|
||||
return
|
||||
|
||||
milk
|
||||
name = "Milk"
|
||||
id = "milk"
|
||||
description = "An opaque white liquid produced by the mammary glands of mammals."
|
||||
reagent_state = LIQUID
|
||||
|
||||
beer
|
||||
name = "Beer"
|
||||
id = "beer"
|
||||
description = "An alcoholic beverage made from malted grains, hops, yeast, and water."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!data) data = 1
|
||||
data++
|
||||
M.make_dizzy(3)
|
||||
M:jitteriness = max(M:jitteriness-3,0)
|
||||
if(data >= 25)
|
||||
if (!M:stuttering) M:stuttering = 1
|
||||
M:stuttering += 3
|
||||
if(data >= 40 && prob(33))
|
||||
if (!M:confused) M:confused = 1
|
||||
M:confused += 2
|
||||
..()
|
||||
|
||||
water
|
||||
name = "Water"
|
||||
id = "water"
|
||||
description = "A ubiquitous chemical substance that is composed of hydrogen and oxygen."
|
||||
reagent_state = LIQUID
|
||||
|
||||
reaction_turf(var/turf/T, var/volume)
|
||||
src = null
|
||||
if(volume >= 3)
|
||||
if(T:wet >= 1) return
|
||||
T:wet = 1
|
||||
if(T:wet_overlay)
|
||||
T:overlays -= T:wet_overlay
|
||||
T:wet_overlay = null
|
||||
T:wet_overlay = image('water.dmi',T,"wet_floor")
|
||||
T:overlays += T:wet_overlay
|
||||
|
||||
spawn(800)
|
||||
if(T:wet >= 2) return
|
||||
T:wet = 0
|
||||
if(T:wet_overlay)
|
||||
T:overlays -= T:wet_overlay
|
||||
T:wet_overlay = null
|
||||
|
||||
var/hotspot = (locate(/obj/hotspot) in T)
|
||||
if(hotspot)
|
||||
var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles() )
|
||||
lowertemp.temperature = max( min(lowertemp.temperature-2000,lowertemp.temperature / 2) ,0)
|
||||
lowertemp.react()
|
||||
T.assume_air(lowertemp)
|
||||
del(hotspot)
|
||||
return
|
||||
reaction_obj(var/obj/O, var/volume)
|
||||
src = null
|
||||
var/turf/T = get_turf(O)
|
||||
var/hotspot = (locate(/obj/hotspot) in T)
|
||||
if(hotspot)
|
||||
var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles() )
|
||||
lowertemp.temperature = max( min(lowertemp.temperature-2000,lowertemp.temperature / 2) ,0)
|
||||
lowertemp.react()
|
||||
T.assume_air(lowertemp)
|
||||
del(hotspot)
|
||||
return
|
||||
|
||||
lube
|
||||
name = "Space Lube"
|
||||
id = "lube"
|
||||
description = "Lubricant is a substance introduced between two moving surfaces to reduce the friction and wear between them. giggity."
|
||||
reagent_state = LIQUID
|
||||
|
||||
reaction_turf(var/turf/T, var/volume)
|
||||
src = null
|
||||
if(T:wet >= 2) return
|
||||
T:wet = 2
|
||||
spawn(800)
|
||||
T:wet = 0
|
||||
if(T:wet_overlay)
|
||||
T:overlays -= T:wet_overlay
|
||||
T:wet_overlay = null
|
||||
|
||||
return
|
||||
|
||||
bilk
|
||||
name = "Bilk"
|
||||
id = "bilk"
|
||||
description = "This appears to be beer mixed with milk. Disgusting."
|
||||
reagent_state = LIQUID
|
||||
|
||||
anti_toxin
|
||||
name = "Anti-Toxin (Dylovene)"
|
||||
id = "anti_toxin"
|
||||
description = "Dylovene is a broad-spectrum antitoxin."
|
||||
reagent_state = LIQUID
|
||||
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:drowsyness = max(M:drowsyness-2, 0)
|
||||
if(holder.has_reagent("toxin"))
|
||||
holder.remove_reagent("toxin", 2)
|
||||
if(holder.has_reagent("stoxin"))
|
||||
holder.remove_reagent("stoxin", 2)
|
||||
if(holder.has_reagent("plasma"))
|
||||
holder.remove_reagent("plasma", 1)
|
||||
if(holder.has_reagent("acid"))
|
||||
holder.remove_reagent("acid", 1)
|
||||
if(holder.has_reagent("cyanide"))
|
||||
holder.remove_reagent("cyanide", 1)
|
||||
M:toxloss = max(M:toxloss-2,0)
|
||||
..()
|
||||
return
|
||||
|
||||
toxin
|
||||
name = "Toxin"
|
||||
id = "toxin"
|
||||
description = "A Toxic chemical."
|
||||
reagent_state = LIQUID
|
||||
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:toxloss += 1.5
|
||||
..()
|
||||
return
|
||||
|
||||
cyanide
|
||||
name = "Cyanide"
|
||||
id = "cyanide"
|
||||
description = "A highly toxic chemical."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:toxloss += 3
|
||||
M:oxyloss += 3
|
||||
..()
|
||||
return
|
||||
|
||||
stoxin
|
||||
name = "Sleep Toxin"
|
||||
id = "stoxin"
|
||||
description = "An effective hypnotic used to treat insomnia."
|
||||
reagent_state = LIQUID
|
||||
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if(!data) data = 1
|
||||
switch(data)
|
||||
if(1 to 15)
|
||||
M.eye_blurry = max(M.eye_blurry, 10)
|
||||
if(15 to 25)
|
||||
M:drowsyness = max(M:drowsyness, 20)
|
||||
if(25 to INFINITY)
|
||||
M:paralysis = max(M:paralysis, 20)
|
||||
M:drowsyness = max(M:drowsyness, 30)
|
||||
data++
|
||||
..()
|
||||
return
|
||||
|
||||
inaprovaline
|
||||
name = "Inaprovaline"
|
||||
id = "inaprovaline"
|
||||
description = "Inaprovaline is a synaptic stimulant and cardiostimulant. Commonly used to stabilize patients."
|
||||
reagent_state = LIQUID
|
||||
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if(M.losebreath >= 10)
|
||||
M.losebreath = max(10, M.losebreath-5)
|
||||
holder.remove_reagent(src.id, 0.2)
|
||||
return
|
||||
|
||||
space_drugs
|
||||
name = "Space drugs"
|
||||
id = "space_drugs"
|
||||
description = "An illegal chemical compound used as drug."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M.druggy = max(M.druggy, 15)
|
||||
if(M.canmove) step(M, pick(cardinal))
|
||||
if(prob(7)) M:emote(pick("twitch","drool","moan","giggle"))
|
||||
holder.remove_reagent(src.id, 0.2)
|
||||
return
|
||||
|
||||
silicate
|
||||
name = "Silicate"
|
||||
id = "silicate"
|
||||
description = "A compound that can be used to reinforce glass."
|
||||
reagent_state = LIQUID
|
||||
reaction_obj(var/obj/O, var/volume)
|
||||
src = null
|
||||
if(istype(O,/obj/window))
|
||||
O:health = O:health * 2
|
||||
var/icon/I = icon(O.icon,O.icon_state,O.dir)
|
||||
I.SetIntensity(1.15,1.50,1.75)
|
||||
O.icon = I
|
||||
return
|
||||
|
||||
oxygen
|
||||
name = "Oxygen"
|
||||
id = "oxygen"
|
||||
description = "A colorless, odorless gas."
|
||||
reagent_state = GAS
|
||||
|
||||
nitrogen
|
||||
name = "Nitrogen"
|
||||
id = "nitrogen"
|
||||
description = "A colorless, odorless, tasteless gas."
|
||||
reagent_state = GAS
|
||||
|
||||
hydrogen
|
||||
name = "Hydrogen"
|
||||
id = "hydrogen"
|
||||
description = "A colorless, odorless, nonmetallic, tasteless, highly combustible diatomic gas."
|
||||
reagent_state = GAS
|
||||
|
||||
potassium
|
||||
name = "Potassium"
|
||||
id = "potassium"
|
||||
description = "A soft, low-melting solid that can easily be cut with a knife. Reacts violently with water."
|
||||
reagent_state = SOLID
|
||||
|
||||
mercury
|
||||
name = "Mercury"
|
||||
id = "mercury"
|
||||
description = "A chemical element."
|
||||
reagent_state = LIQUID
|
||||
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if(M.canmove) step(M, pick(cardinal))
|
||||
if(prob(5)) M:emote(pick("twitch","drool","moan"))
|
||||
..()
|
||||
return
|
||||
|
||||
sulfur
|
||||
name = "Sulfur"
|
||||
id = "sulfur"
|
||||
description = "A chemical element."
|
||||
reagent_state = SOLID
|
||||
|
||||
carbon
|
||||
name = "Carbon"
|
||||
id = "carbon"
|
||||
description = "A chemical element."
|
||||
reagent_state = SOLID
|
||||
|
||||
reaction_turf(var/turf/T, var/volume)
|
||||
src = null
|
||||
if(!istype(T, /turf/space))
|
||||
new /obj/decal/cleanable/dirt(T)
|
||||
|
||||
chlorine
|
||||
name = "Chlorine"
|
||||
id = "chlorine"
|
||||
description = "A chemical element."
|
||||
reagent_state = GAS
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:bruteloss++
|
||||
..()
|
||||
return
|
||||
|
||||
fluorine
|
||||
name = "Fluorine"
|
||||
id = "fluorine"
|
||||
description = "A highly-reactive chemical element."
|
||||
reagent_state = GAS
|
||||
on_mob_life(var/mob.M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:toxloss++
|
||||
..()
|
||||
return
|
||||
|
||||
phosphorus
|
||||
name = "Phosphorus"
|
||||
id = "phosphorus"
|
||||
description = "A chemical element."
|
||||
reagent_state = SOLID
|
||||
|
||||
lithium
|
||||
name = "Lithium"
|
||||
id = "lithium"
|
||||
description = "A chemical element."
|
||||
reagent_state = SOLID
|
||||
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if(M.canmove) step(M, pick(cardinal))
|
||||
if(prob(5)) M:emote(pick("twitch","drool","moan"))
|
||||
..()
|
||||
return
|
||||
|
||||
sugar
|
||||
name = "Sugar"
|
||||
id = "sugar"
|
||||
description = "The organic compound commonly known as table sugar and sometimes called saccharose. This white, odorless, crystalline powder has a pleasing, sweet taste."
|
||||
reagent_state = SOLID
|
||||
|
||||
acid
|
||||
name = "Sulphuric acid"
|
||||
id = "acid"
|
||||
description = "A strong mineral acid with the molecular formula H2SO4."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:toxloss++
|
||||
M:fireloss++
|
||||
..()
|
||||
return
|
||||
reaction_mob(var/mob/M, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
if(istype(M, /mob/living/carbon/human))
|
||||
if(M:wear_mask)
|
||||
del (M:wear_mask)
|
||||
M << "\red Your mask melts away but protects you from the acid!"
|
||||
return
|
||||
if(M:head)
|
||||
del (M:head)
|
||||
M << "\red Your helmet melts into uselessness but protects you from the acid!"
|
||||
return
|
||||
|
||||
if(prob(75))
|
||||
var/datum/organ/external/affecting = M:organs["head"]
|
||||
affecting.take_damage(25, 0)
|
||||
M:UpdateDamage()
|
||||
M:UpdateDamageIcon()
|
||||
M:emote("scream")
|
||||
M << "\red Your face has become disfigured!"
|
||||
M.real_name = "Unknown"
|
||||
else
|
||||
M:bruteloss += 15
|
||||
else
|
||||
M:bruteloss += 15
|
||||
|
||||
reaction_obj(var/obj/O, var/volume)
|
||||
if(istype(O,/obj/item) && prob(40))
|
||||
var/obj/decal/cleanable/molten_item/I = new/obj/decal/cleanable/molten_item(O.loc)
|
||||
I.desc = "Looks like this was \an [O] some time ago."
|
||||
for(var/mob/M in viewers(5, O))
|
||||
M << "\red \the [O] melts."
|
||||
del(O)
|
||||
|
||||
pacid
|
||||
name = "Polytrinic acid"
|
||||
id = "pacid"
|
||||
description = "Polytrinic acid is a an extremely corrosive chemical substance."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:toxloss++
|
||||
M:fireloss++
|
||||
..()
|
||||
return
|
||||
reaction_mob(var/mob/M, var/method=TOUCH, var/volume)
|
||||
if(method == TOUCH)
|
||||
if(istype(M, /mob/living/carbon/human))
|
||||
if(M:wear_mask)
|
||||
del (M:wear_mask)
|
||||
M << "\red Your mask melts away!"
|
||||
return
|
||||
if(M:head)
|
||||
del (M:head)
|
||||
M << "\red Your helmet melts into uselessness!"
|
||||
return
|
||||
var/datum/organ/external/affecting = M:organs["head"]
|
||||
affecting.take_damage(75, 0)
|
||||
M:UpdateDamage()
|
||||
M:UpdateDamageIcon()
|
||||
M:emote("scream")
|
||||
M << "\red Your face has become disfigured!"
|
||||
M.real_name = "Unknown"
|
||||
else
|
||||
M:bruteloss += 15
|
||||
else
|
||||
if(istype(M, /mob/living/carbon/human))
|
||||
var/datum/organ/external/affecting = M:organs["head"]
|
||||
affecting.take_damage(75, 0)
|
||||
M:UpdateDamage()
|
||||
M:UpdateDamageIcon()
|
||||
M:emote("scream")
|
||||
M << "\red Your face has become disfigured!"
|
||||
M.real_name = "Unknown"
|
||||
else
|
||||
M:bruteloss += 15
|
||||
|
||||
reaction_obj(var/obj/O, var/volume)
|
||||
if(istype(O,/obj/item))
|
||||
var/obj/decal/cleanable/molten_item/I = new/obj/decal/cleanable/molten_item(O.loc)
|
||||
I.desc = "Looks like this was \an [O] some time ago."
|
||||
for(var/mob/M in viewers(5, O))
|
||||
M << "\red \the [O] melts."
|
||||
del(O)
|
||||
|
||||
radium
|
||||
name = "Radium"
|
||||
id = "radium"
|
||||
description = "Radium is an alkaline earth metal. It is extremely radioactive."
|
||||
reagent_state = SOLID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M.radiation += 3
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
reaction_turf(var/turf/T, var/volume)
|
||||
src = null
|
||||
if(!istype(T, /turf/space))
|
||||
new /obj/decal/cleanable/greenglow(T)
|
||||
|
||||
|
||||
ryetalyn
|
||||
name = "Ryetalyn"
|
||||
id = "ryetalyn"
|
||||
description = "Ryetalyn can cure all genetic abnomalities."
|
||||
reagent_state = SOLID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M.mutations = 0
|
||||
M.disabilities = 0
|
||||
M.sdisabilities = 0
|
||||
..()
|
||||
return
|
||||
|
||||
thermite
|
||||
name = "Thermite"
|
||||
id = "thermite"
|
||||
description = "Thermite produces an aluminothermic reaction known as a thermite reaction. Can be used to melt walls."
|
||||
reagent_state = SOLID
|
||||
reaction_turf(var/turf/T, var/volume)
|
||||
src = null
|
||||
if(istype(T, /turf/simulated/wall))
|
||||
T:thermite = 1
|
||||
T.overlays = null
|
||||
T.overlays = image('effects.dmi',icon_state = "thermite")
|
||||
return
|
||||
|
||||
mutagen
|
||||
name = "Unstable mutagen"
|
||||
id = "mutagen"
|
||||
description = "Might cause unpredictable mutations. Keep away from children."
|
||||
reagent_state = LIQUID
|
||||
reaction_mob(var/mob/M, var/method=TOUCH, var/volume)
|
||||
src = null
|
||||
if ( (method==TOUCH && prob(33)) || method==INGEST)
|
||||
randmuti(M)
|
||||
if(prob(98))
|
||||
randmutb(M)
|
||||
else
|
||||
randmutg(M)
|
||||
domutcheck(M, null, 1)
|
||||
updateappearance(M,M.dna.uni_identity)
|
||||
return
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M.radiation += 3
|
||||
..()
|
||||
return
|
||||
|
||||
iron
|
||||
name = "Iron"
|
||||
id = "iron"
|
||||
description = "Pure iron is a metal."
|
||||
reagent_state = SOLID
|
||||
|
||||
aluminium
|
||||
name = "Aluminium"
|
||||
id = "aluminium"
|
||||
description = "A silvery white and ductile member of the boron group of chemical elements."
|
||||
reagent_state = SOLID
|
||||
|
||||
silicon
|
||||
name = "Silicon"
|
||||
id = "silicon"
|
||||
description = "A tetravalent metalloid, silicon is less reactive than its chemical analog carbon."
|
||||
reagent_state = SOLID
|
||||
|
||||
fuel
|
||||
name = "Welding fuel"
|
||||
id = "fuel"
|
||||
description = "Required for welders. Flamable."
|
||||
reagent_state = LIQUID
|
||||
reaction_obj(var/obj/O, var/volume)
|
||||
src = null
|
||||
var/turf/the_turf = get_turf(O)
|
||||
var/datum/gas_mixture/napalm = new
|
||||
var/datum/gas/volatile_fuel/fuel = new
|
||||
fuel.moles = 15
|
||||
napalm.trace_gases += fuel
|
||||
the_turf.assume_air(napalm)
|
||||
reaction_turf(var/turf/T, var/volume)
|
||||
src = null
|
||||
var/datum/gas_mixture/napalm = new
|
||||
var/datum/gas/volatile_fuel/fuel = new
|
||||
fuel.moles = 15
|
||||
napalm.trace_gases += fuel
|
||||
T.assume_air(napalm)
|
||||
return
|
||||
|
||||
coffee
|
||||
name = "Coffee"
|
||||
id = "coffee"
|
||||
description = "Coffee is a brewed drink prepared from roasted seeds, commonly called coffee beans, of the coffee plant."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
..()
|
||||
M.dizziness = max(0,M.dizziness-5)
|
||||
M:drowsyness = max(0,M:drowsyness-3)
|
||||
M:sleeping = 0
|
||||
M.bodytemperature = min(310, M.bodytemperature+5) //310 is the normal bodytemp. 310.055
|
||||
M.make_jittery(5)
|
||||
|
||||
space_cleaner
|
||||
name = "Space cleaner"
|
||||
id = "cleaner"
|
||||
description = "A compound used to clean things. Now with 50% more sodium hypochlorite!"
|
||||
reagent_state = LIQUID
|
||||
reaction_obj(var/obj/O, var/volume)
|
||||
if(istype(O,/obj/decal/cleanable))
|
||||
del(O)
|
||||
else
|
||||
O.clean_blood()
|
||||
reaction_turf(var/turf/T, var/volume)
|
||||
T.overlays = null
|
||||
T.clean_blood()
|
||||
for(var/obj/decal/cleanable/C in src)
|
||||
del(C)
|
||||
reaction_mob(var/mob/M, var/method=TOUCH, var/volume)
|
||||
M.clean_blood()
|
||||
if(istype(M, /mob/living/carbon))
|
||||
var/mob/living/carbon/C = M
|
||||
if(C.r_hand)
|
||||
C.r_hand.clean_blood()
|
||||
if(C.l_hand)
|
||||
C.l_hand.clean_blood()
|
||||
if(C.wear_mask)
|
||||
C.wear_mask.clean_blood()
|
||||
if(istype(M, /mob/living/carbon/human))
|
||||
if(C:w_uniform)
|
||||
C:w_uniform.clean_blood()
|
||||
if(C:wear_suit)
|
||||
C:wear_suit.clean_blood()
|
||||
if(C:shoes)
|
||||
C:shoes.clean_blood()
|
||||
if(C:gloves)
|
||||
C:gloves.clean_blood()
|
||||
if(C:head)
|
||||
C:head.clean_blood()
|
||||
|
||||
|
||||
space_cola
|
||||
name = "Cola"
|
||||
id = "cola"
|
||||
description = "A refreshing beverage."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
M:drowsyness = max(0,M:drowsyness-5)
|
||||
M.bodytemperature = max(310, M.bodytemperature-5) //310 is the normal bodytemp. 310.055
|
||||
|
||||
plasma
|
||||
name = "Plasma"
|
||||
id = "plasma"
|
||||
description = "Plasma in its liquid form."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if(holder.has_reagent("inaprovaline"))
|
||||
holder.remove_reagent("inaprovaline", 2)
|
||||
M:toxloss++
|
||||
..()
|
||||
return
|
||||
reaction_obj(var/obj/O, var/volume)
|
||||
src = null
|
||||
var/turf/the_turf = get_turf(O)
|
||||
var/datum/gas_mixture/napalm = new
|
||||
var/datum/gas/volatile_fuel/fuel = new
|
||||
fuel.moles = 5
|
||||
napalm.trace_gases += fuel
|
||||
the_turf.assume_air(napalm)
|
||||
reaction_turf(var/turf/T, var/volume)
|
||||
src = null
|
||||
var/datum/gas_mixture/napalm = new
|
||||
var/datum/gas/volatile_fuel/fuel = new
|
||||
fuel.moles = 5
|
||||
napalm.trace_gases += fuel
|
||||
T.assume_air(napalm)
|
||||
return
|
||||
|
||||
leporazine
|
||||
name = "Leporazine"
|
||||
id = "leporazine"
|
||||
description = "Leporazine can be use to stabilize an individuals body temperature."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if(M.bodytemperature < 310)
|
||||
M.bodytemperature = max(310, M.bodytemperature-10)
|
||||
else if(M.bodytemperature > 311)
|
||||
M.bodytemperature = min(310, M.bodytemperature+10)
|
||||
..()
|
||||
return
|
||||
|
||||
cryptobiolin
|
||||
name = "Cryptobiolin"
|
||||
id = "cryptobiolin"
|
||||
description = "Cryptobiolin causes confusion and dizzyness."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M.make_dizzy(1)
|
||||
if(!M.confused) M.confused = 1
|
||||
M.confused = max(M.confused, 20)
|
||||
holder.remove_reagent(src.id, 0.2)
|
||||
return
|
||||
|
||||
lexorin
|
||||
name = "Lexorin"
|
||||
id = "lexorin"
|
||||
description = "Lexorin temporarily stops respiration. Causes tissue damage."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if(prob(33)) M.bruteloss++
|
||||
holder.remove_reagent(src.id, 0.3)
|
||||
return
|
||||
|
||||
kelotane
|
||||
name = "Kelotane"
|
||||
id = "kelotane"
|
||||
description = "Kelotane is a drug used to treat burns."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:fireloss = max(M:fireloss-2,0)
|
||||
..()
|
||||
return
|
||||
|
||||
dexalin
|
||||
name = "Dexalin"
|
||||
id = "dexalin"
|
||||
description = "Dexalin is used in the treatment of oxygen deprivation."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:oxyloss = max(M:oxyloss-2, 0)
|
||||
..()
|
||||
return
|
||||
|
||||
dexalinp
|
||||
name = "Dexalin Plus"
|
||||
id = "dexalinp"
|
||||
description = "Dexalin Plus is used in the treatment of oxygen deprivation. Its highly effective."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:oxyloss = 0
|
||||
..()
|
||||
return
|
||||
|
||||
tricordrazine
|
||||
name = "Tricordrazine"
|
||||
id = "tricordrazine"
|
||||
description = "Tricordrazine is a highly potent stimulant, originally derived from cordrazine. Can be used to treat a wide range of injuries."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if(M:oxyloss && prob(40)) M:oxyloss--
|
||||
if(M:bruteloss && prob(40)) M:bruteloss--
|
||||
if(M:fireloss && prob(40)) M:fireloss--
|
||||
if(M:toxloss && prob(40)) M:toxloss--
|
||||
..()
|
||||
return
|
||||
|
||||
synaptizine
|
||||
name = "Synaptizine"
|
||||
id = "synaptizine"
|
||||
description = "Synaptizine is used to treat neuroleptic shock. Can be used to help remove disabling symptoms such as paralysis."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:drowsyness = max(M:drowsyness-5, 0)
|
||||
if(M:paralysis) M:paralysis--
|
||||
if(M:stunned) M:stunned--
|
||||
if(M:weakened) M:weakened--
|
||||
..()
|
||||
return
|
||||
|
||||
impedrezene
|
||||
name = "Impedrezene"
|
||||
id = "impedrezene"
|
||||
description = "Impedrezene is a narcotic that impedes one's ability by slowing down the higher brain cell functions."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:jitteriness = max(M:jitteriness-5,0)
|
||||
if(prob(80)) M:brainloss++
|
||||
if(prob(50)) M:drowsyness = max(M:drowsyness, 3)
|
||||
if(prob(10)) M:emote("drool")
|
||||
..()
|
||||
return
|
||||
|
||||
hyronalin
|
||||
name = "Hyronalin"
|
||||
id = "hyronalin"
|
||||
description = "Hyronalin is a medicinal drug used to counter the effects of radiation poisoning."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if(M:radiation && prob(80)) M:radiation--
|
||||
..()
|
||||
return
|
||||
|
||||
alkysine
|
||||
name = "Alkysine"
|
||||
id = "alkysine"
|
||||
description = "Alkysine is a drug used to lessen the damage to neurological tissue after a catastrophic injury. Can heal brain tissue."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:brainloss = max(M:brainloss-3 , 0)
|
||||
..()
|
||||
return
|
||||
|
||||
arithrazine
|
||||
name = "Arithrazine"
|
||||
id = "arithrazine"
|
||||
description = "Arithrazine is an unstable medication used for the most extreme cases of radiation poisoning."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
M:radiation = max(M:radiation-3,0)
|
||||
if(M:toxloss && prob(50)) M:toxloss--
|
||||
if(prob(15)) M:bruteloss++
|
||||
..()
|
||||
return
|
||||
|
||||
bicaridine
|
||||
name = "Bicaridine"
|
||||
id = "bicaridine"
|
||||
description = "Bicaridine is an analgesic medication and can be used to treat blunt trauma."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if(M:bruteloss && prob(40)) M:bruteloss--
|
||||
..()
|
||||
return
|
||||
|
||||
hyperzine
|
||||
name = "Hyperzine"
|
||||
id = "hyperzine"
|
||||
description = "Hyperzine is a highly effective, long lasting, muscle stimulant."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if(prob(5)) M:emote(pick("twitch","blink_r","shiver"))
|
||||
holder.remove_reagent(src.id, 0.2)
|
||||
return
|
||||
|
||||
cryoxadone
|
||||
name = "Cryoxadone"
|
||||
id = "cryoxadone"
|
||||
description = "A chemical mixture with almost magical healing powers. Its main limitation is that the targets body temperature must be under 170K for it to metabolise correctly."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if(M.bodytemperature < 170)
|
||||
if(M:oxyloss) M:oxyloss = max(0, M:oxyloss-3)
|
||||
if(M:bruteloss) M:bruteloss = max(0, M:bruteloss-3)
|
||||
if(M:fireloss) M:fireloss = max(0, M:fireloss-3)
|
||||
if(M:toxloss) M:toxloss = max(0, M:toxloss-3)
|
||||
|
||||
return
|
||||
|
||||
spaceacillin
|
||||
name = "Spaceacillin"
|
||||
id = "spaceacillin"
|
||||
description = "An all-purpose antiviral agent."
|
||||
reagent_state = LIQUID
|
||||
|
||||
on_mob_life(var/mob/M)
|
||||
if(!M) M = holder.my_atom
|
||||
if((M.virus) && (prob(8)))
|
||||
if(M.virus.spread == "Airborne")
|
||||
M.virus.spread = "Remissive"
|
||||
M.virus.stage--
|
||||
if(M.virus.stage <= 0)
|
||||
M.resistances += M.virus.type
|
||||
M.virus = null
|
||||
holder.remove_reagent(src.id, 0.2)
|
||||
return
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nanites
|
||||
name = "Nanomachines"
|
||||
id = "nanites"
|
||||
description = "Microscopic construction robots."
|
||||
reagent_state = LIQUID
|
||||
reaction_mob(var/mob/M, var/method=TOUCH, var/volume)
|
||||
src = null
|
||||
if( (prob(10) && method==TOUCH) || method==INGEST)
|
||||
if(!M.virus)
|
||||
M.virus = new /datum/disease/robotic_transformation
|
||||
M.virus.affected_mob = M
|
||||
|
||||
xenomicrobes
|
||||
name = "Xenomicrobes"
|
||||
id = "xenomicrobes"
|
||||
description = "Microbes with an entirely alien cellular structure."
|
||||
reagent_state = LIQUID
|
||||
reaction_mob(var/mob/M, var/method=TOUCH, var/volume)
|
||||
src = null
|
||||
if( (prob(10) && method==TOUCH) || method==INGEST)
|
||||
if(!M.virus)
|
||||
M.virus = new /datum/disease/xeno_transformation
|
||||
M.virus.affected_mob = M
|
||||
|
||||
//foam precursor
|
||||
|
||||
fluorosurfactant
|
||||
name = "Fluorosurfactant"
|
||||
id = "fluorosurfactant"
|
||||
description = "A perfluoronated sulfonic acid that forms a foam when mixed with water."
|
||||
reagent_state = LIQUID
|
||||
|
||||
|
||||
// metal foaming agent
|
||||
// this is lithium hydride. Add other recipies (e.g. LiH + H2O -> LiOH + H2) eventually
|
||||
|
||||
foaming_agent
|
||||
name = "Foaming agent"
|
||||
id = "foaming_agent"
|
||||
description = "A agent that yields metallic foam when mixed with light metal and a strong acid."
|
||||
reagent_state = SOLID
|
||||
|
||||
nicotine
|
||||
name = "Nicotine"
|
||||
id = "nicotine"
|
||||
description = "A highly addictive stimulant extracted from the tobacco plant."
|
||||
reagent_state = LIQUID
|
||||
|
||||
ethanol
|
||||
name = "Ethanol"
|
||||
id = "ethanol"
|
||||
description = "A well-known alcohol with a variety of applications."
|
||||
reagent_state = LIQUID
|
||||
on_mob_life(var/mob/M)
|
||||
if(!data) data = 1
|
||||
data++
|
||||
M.make_dizzy(5)
|
||||
M:jitteriness = max(M:jitteriness-5,0)
|
||||
if(data >= 25)
|
||||
if (!M:stuttering) M:stuttering = 1
|
||||
M:stuttering += 4
|
||||
if(data >= 40 && prob(33))
|
||||
if (!M:confused) M:confused = 1
|
||||
M:confused += 3
|
||||
..()
|
||||
|
||||
ammonia
|
||||
name = "Ammonia"
|
||||
id = "ammonia"
|
||||
description = "A caustic substance commonly used in fertilizer or household cleaners."
|
||||
reagent_state = GAS
|
||||
|
||||
diethylamine
|
||||
name = "Diethylamine"
|
||||
id = "diethylamine"
|
||||
description = "A secondary amine, mildly corrosive."
|
||||
reagent_state = LIQUID
|
||||
@@ -0,0 +1,390 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
datum
|
||||
chemical_reaction
|
||||
var/name = null
|
||||
var/id = null
|
||||
var/result = null
|
||||
var/list/required_reagents = new/list()
|
||||
var/result_amount = 0
|
||||
|
||||
proc
|
||||
on_reaction(var/datum/reagents/holder, var/created_volume)
|
||||
return
|
||||
|
||||
//I recommend you set the result amount to the total volume of all components.
|
||||
|
||||
bilk
|
||||
name = "Bilk"
|
||||
id = "bilk"
|
||||
result = "bilk"
|
||||
required_reagents = list("milk" = 1, "beer" = 1)
|
||||
result_amount = 2
|
||||
|
||||
explosion_potassium
|
||||
name = "Explosion"
|
||||
id = "explosion_potassium"
|
||||
result = null
|
||||
required_reagents = list("water" = 1, "potassium" = 1)
|
||||
result_amount = null
|
||||
on_reaction(var/datum/reagents/holder, var/created_volume)
|
||||
var/location = get_turf(holder.my_atom)
|
||||
var/datum/effects/system/spark_spread/s = new /datum/effects/system/spark_spread
|
||||
s.set_up(2, 1, location)
|
||||
s.start()
|
||||
for(var/mob/M in viewers(5, location))
|
||||
M << "\red The solution violently explodes."
|
||||
for(var/mob/M in viewers(1, location))
|
||||
M << "\red The explosion knocks you down."
|
||||
M:weakened += 3
|
||||
return
|
||||
|
||||
silicate
|
||||
name = "Silicate"
|
||||
id = "silicate"
|
||||
result = "silicate"
|
||||
required_reagents = list("aluminium" = 1, "silicon" = 1, "oxygen" = 1)
|
||||
result_amount = 3
|
||||
|
||||
mutagen
|
||||
name = "Unstable mutagen"
|
||||
id = "mutagen"
|
||||
result = "mutagen"
|
||||
required_reagents = list("radium" = 1, "phosphorus" = 1, "chlorine" = 1)
|
||||
result_amount = 3
|
||||
|
||||
//cyanide
|
||||
// name = "Cyanide"
|
||||
// id = "cyanide"
|
||||
// result = "cyanide"
|
||||
// required_reagents = list("hydrogen" = 1, "carbon" = 1, "nitrogen" = 1)
|
||||
// result_amount = 3
|
||||
|
||||
thermite
|
||||
name = "Thermite"
|
||||
id = "thermite"
|
||||
result = "thermite"
|
||||
required_reagents = list("aluminium" = 1, "iron" = 1, "oxygen" = 1)
|
||||
result_amount = 3
|
||||
|
||||
lexorin
|
||||
name = "Lexorin"
|
||||
id = "lexorin"
|
||||
result = "lexorin"
|
||||
required_reagents = list("plasma" = 1, "hydrogen" = 1, "nitrogen" = 1)
|
||||
result_amount = 3
|
||||
|
||||
space_drugs
|
||||
name = "Space Drugs"
|
||||
id = "space_drugs"
|
||||
result = "space_drugs"
|
||||
required_reagents = list("mercury" = 1, "sugar" = 1, "lithium" = 1)
|
||||
result_amount = 3
|
||||
|
||||
lube
|
||||
name = "Space Lube"
|
||||
id = "lube"
|
||||
result = "lube"
|
||||
required_reagents = list("water" = 1, "silicon" = 1, "oxygen" = 1)
|
||||
result_amount = 4
|
||||
|
||||
pacid
|
||||
name = "Polytrinic acid"
|
||||
id = "pacid"
|
||||
result = "pacid"
|
||||
required_reagents = list("acid" = 1, "chlorine" = 1, "potassium" = 1)
|
||||
result_amount = 3
|
||||
|
||||
synaptizine
|
||||
name = "Synaptizine"
|
||||
id = "synaptizine"
|
||||
result = "synaptizine"
|
||||
required_reagents = list("sugar" = 1, "lithium" = 1, "water" = 1)
|
||||
result_amount = 3
|
||||
|
||||
hyronalin
|
||||
name = "Hyronalin"
|
||||
id = "hyronalin"
|
||||
result = "hyronalin"
|
||||
required_reagents = list("radium" = 1, "anti_toxin" = 1)
|
||||
result_amount = 2
|
||||
|
||||
arithrazine
|
||||
name = "Arithrazine"
|
||||
id = "arithrazine"
|
||||
result = "arithrazine"
|
||||
required_reagents = list("hyronalin" = 1, "hydrogen" = 1)
|
||||
result_amount = 2
|
||||
|
||||
impedrezene
|
||||
name = "Impedrezene"
|
||||
id = "impedrezene"
|
||||
result = "impedrezene"
|
||||
required_reagents = list("mercury" = 1, "oxygen" = 1, "sugar" = 1)
|
||||
result_amount = 2
|
||||
|
||||
kelotane
|
||||
name = "Kelotane"
|
||||
id = "kelotane"
|
||||
result = "kelotane"
|
||||
required_reagents = list("silicon" = 1, "carbon" = 1)
|
||||
result_amount = 2
|
||||
|
||||
leporazine
|
||||
name = "Leporazine"
|
||||
id = "leporazine"
|
||||
result = "leporazine"
|
||||
required_reagents = list("silicon" = 1, "plasma" = 1, )
|
||||
result_amount = 2
|
||||
|
||||
cryptobiolin
|
||||
name = "Cryptobiolin"
|
||||
id = "cryptobiolin"
|
||||
result = "cryptobiolin"
|
||||
required_reagents = list("potassium" = 1, "oxygen" = 1, "sugar" = 1)
|
||||
result_amount = 3
|
||||
|
||||
tricordrazine
|
||||
name = "Tricordrazine"
|
||||
id = "tricordrazine"
|
||||
result = "tricordrazine"
|
||||
required_reagents = list("inaprovaline" = 1, "anti_toxin" = 1)
|
||||
result_amount = 2
|
||||
|
||||
alkysine
|
||||
name = "Alkysine"
|
||||
id = "alkysine"
|
||||
result = "alkysine"
|
||||
required_reagents = list("chlorine" = 1, "nitrogen" = 1, "anti_toxin" = 1)
|
||||
result_amount = 2
|
||||
|
||||
dexalin
|
||||
name = "Dexalin"
|
||||
id = "dexalin"
|
||||
result = "dexalin"
|
||||
required_reagents = list("plasma" = 1, "oxygen" = 1)
|
||||
result_amount = 2
|
||||
|
||||
dexalinp
|
||||
name = "Dexalin Plus"
|
||||
id = "dexalinp"
|
||||
result = "dexalinp"
|
||||
required_reagents = list("dexalin" = 1, "carbon" = 1, "iron" = 1)
|
||||
result_amount = 3
|
||||
|
||||
bicaridine
|
||||
name = "Bicaridine"
|
||||
id = "bicaridine"
|
||||
result = "bicaridine"
|
||||
required_reagents = list("inaprovaline" = 1, "carbon" = 1)
|
||||
result_amount = 2
|
||||
|
||||
hyperzine
|
||||
name = "Hyperzine"
|
||||
id = "hyperzine"
|
||||
result = "hyperzine"
|
||||
required_reagents = list("sugar" = 1, "phosphorus" = 1, "sulfur" = 1,)
|
||||
result_amount = 3
|
||||
|
||||
ryetalyn
|
||||
name = "Ryetalyn"
|
||||
id = "ryetalyn"
|
||||
result = "ryetalyn"
|
||||
required_reagents = list("arithrazine" = 1, "carbon" = 1)
|
||||
result_amount = 2
|
||||
|
||||
cryoxadone
|
||||
name = "Cryoxadone"
|
||||
id = "cryoxadone"
|
||||
result = "cryoxadone"
|
||||
required_reagents = list("dexalin" = 1, "water" = 1, "oxygen" = 1)
|
||||
result_amount = 10
|
||||
|
||||
spaceacillin
|
||||
name = "spaceacillin"
|
||||
id = "spaceacillin"
|
||||
result = "spaceacillin"
|
||||
required_reagents = list("cryptobiolin" = 1, "inaprovaline" = 1)
|
||||
result_amount = 2
|
||||
|
||||
flash_powder
|
||||
name = "Flash powder"
|
||||
id = "flash_powder"
|
||||
result = null
|
||||
required_reagents = list("aluminium" = 1, "potassium" = 1, "sulfur" = 1 )
|
||||
result_amount = null
|
||||
on_reaction(var/datum/reagents/holder, var/created_volume)
|
||||
var/location = get_turf(holder.my_atom)
|
||||
var/datum/effects/system/spark_spread/s = new /datum/effects/system/spark_spread
|
||||
s.set_up(2, 1, location)
|
||||
s.start()
|
||||
for(var/mob/living/carbon/M in viewers(world.view, location))
|
||||
switch(get_dist(M, location))
|
||||
if(0 to 3)
|
||||
if(hasvar(M, "glasses"))
|
||||
if(istype(M:glasses, /obj/item/clothing/glasses/sunglasses))
|
||||
continue
|
||||
|
||||
flick("e_flash", M.flash)
|
||||
M.weakened = 15
|
||||
|
||||
if(4 to 5)
|
||||
if(hasvar(M, "glasses"))
|
||||
if(istype(M:glasses, /obj/item/clothing/glasses/sunglasses))
|
||||
continue
|
||||
|
||||
flick("e_flash", M.flash)
|
||||
M.stunned = 5
|
||||
|
||||
napalm
|
||||
name = "Napalm"
|
||||
id = "napalm"
|
||||
result = null
|
||||
required_reagents = list("aluminium" = 1, "plasma" = 1, "acid" = 1 )
|
||||
result_amount = null
|
||||
on_reaction(var/datum/reagents/holder, var/created_volume)
|
||||
var/location = get_turf(holder.my_atom)
|
||||
for(var/turf/simulated/floor/target_tile in range(1,location))
|
||||
if(target_tile.parent && target_tile.parent.group_processing)
|
||||
target_tile.parent.suspend_group_processing()
|
||||
|
||||
var/datum/gas_mixture/napalm = new
|
||||
var/datum/gas/volatile_fuel/fuel = new
|
||||
|
||||
fuel.moles = 15
|
||||
napalm.trace_gases += fuel
|
||||
|
||||
target_tile.assume_air(napalm)
|
||||
|
||||
spawn (0) target_tile.hotspot_expose(700, 400)
|
||||
|
||||
return
|
||||
|
||||
smoke
|
||||
name = "Smoke"
|
||||
id = "smoke"
|
||||
result = null
|
||||
required_reagents = list("potassium" = 1, "sugar" = 1, "phosphorus" = 1 )
|
||||
result_amount = null
|
||||
on_reaction(var/datum/reagents/holder, var/created_volume)
|
||||
var/location = get_turf(holder.my_atom)
|
||||
var/datum/effects/system/bad_smoke_spread/S = new /datum/effects/system/bad_smoke_spread
|
||||
S.attach(location)
|
||||
S.set_up(10, 0, location)
|
||||
playsound(location, 'smoke.ogg', 50, 1, -3)
|
||||
spawn(0)
|
||||
S.start()
|
||||
sleep(10)
|
||||
S.start()
|
||||
sleep(10)
|
||||
S.start()
|
||||
sleep(10)
|
||||
S.start()
|
||||
sleep(10)
|
||||
S.start()
|
||||
return
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// foam and foam precursor
|
||||
|
||||
surfactant
|
||||
name = "Foam surfactant"
|
||||
id = "foam surfactant"
|
||||
result = "fluorosurfactant"
|
||||
required_reagents = list("fluorine" = 2, "carbon" = 2, "acid" = 1)
|
||||
result_amount = 5
|
||||
|
||||
|
||||
foam
|
||||
name = "Foam"
|
||||
id = "foam"
|
||||
result = null
|
||||
required_reagents = list("fluorosurfactant" = 1, "water" = 1)
|
||||
result_amount = 2
|
||||
|
||||
on_reaction(var/datum/reagents/holder, var/created_volume)
|
||||
|
||||
|
||||
var/location = get_turf(holder.my_atom)
|
||||
for(var/mob/M in viewers(5, location))
|
||||
M << "\red The solution violently bubbles!"
|
||||
|
||||
location = get_turf(holder.my_atom)
|
||||
|
||||
for(var/mob/M in viewers(5, location))
|
||||
M << "\red The solution spews out foam!"
|
||||
|
||||
//world << "Holder volume is [holder.total_volume]"
|
||||
//for(var/datum/reagent/R in holder.reagent_list)
|
||||
// world << "[R.name] = [R.volume]"
|
||||
|
||||
var/datum/effects/system/foam_spread/s = new()
|
||||
s.set_up(created_volume, location, holder, 0)
|
||||
s.start()
|
||||
holder.clear_reagents()
|
||||
return
|
||||
|
||||
|
||||
metalfoam
|
||||
name = "Metal Foam"
|
||||
id = "metalfoam"
|
||||
result = null
|
||||
required_reagents = list("aluminium" = 3, "foaming_agent" = 1, "pacid" = 1)
|
||||
result_amount = 5
|
||||
|
||||
on_reaction(var/datum/reagents/holder, var/created_volume)
|
||||
|
||||
|
||||
var/location = get_turf(holder.my_atom)
|
||||
|
||||
for(var/mob/M in viewers(5, location))
|
||||
M << "\red The solution spews out a metalic foam!"
|
||||
|
||||
var/datum/effects/system/foam_spread/s = new()
|
||||
s.set_up(created_volume/2, location, holder, 1)
|
||||
s.start()
|
||||
return
|
||||
|
||||
ironfoam
|
||||
name = "Iron Foam"
|
||||
id = "ironlfoam"
|
||||
result = null
|
||||
required_reagents = list("iron" = 3, "foaming_agent" = 1, "pacid" = 1)
|
||||
result_amount = 5
|
||||
|
||||
on_reaction(var/datum/reagents/holder, var/created_volume)
|
||||
|
||||
|
||||
var/location = get_turf(holder.my_atom)
|
||||
|
||||
for(var/mob/M in viewers(5, location))
|
||||
M << "\red The solution spews out a metalic foam!"
|
||||
|
||||
var/datum/effects/system/foam_spread/s = new()
|
||||
s.set_up(created_volume/2, location, holder, 2)
|
||||
s.start()
|
||||
return
|
||||
|
||||
|
||||
|
||||
foaming_agent
|
||||
name = "Foaming Agent"
|
||||
id = "foaming_agent"
|
||||
result = "foaming_agent"
|
||||
required_reagents = list("lithium" = 1, "hydrogen" = 1)
|
||||
result_amount = 1
|
||||
|
||||
// Synthesizing these three chemicals is pretty complex in real life, but fuck it, it's just a game!
|
||||
ammonia
|
||||
name = "Ammonia"
|
||||
id = "ammonia"
|
||||
result = "ammonia"
|
||||
required_reagents = list("hydrogen" = 3, "nitrogen" = 1)
|
||||
result_amount = 3
|
||||
|
||||
space_cleaner
|
||||
name = "Space cleaner"
|
||||
id = "cleaner"
|
||||
result = "cleaner"
|
||||
required_reagents = list("ammonia" = 1, "water" = 1)
|
||||
result_amount = 1
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,490 @@
|
||||
/obj/signpost
|
||||
icon = 'old_or_unused.dmi'
|
||||
icon_state = "signpost"
|
||||
anchored = 1
|
||||
density = 1
|
||||
|
||||
attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
switch(alert("Travel back to ss13?",,"Yes","No"))
|
||||
if("Yes")
|
||||
user.loc.loc.Exited(user)
|
||||
user.loc = pick(latejoin)
|
||||
if("No")
|
||||
return
|
||||
|
||||
/area/beach
|
||||
name = "Keelin's private beach"
|
||||
icon_state = "null"
|
||||
luminosity = 1
|
||||
sd_lighting = 0
|
||||
requires_power = 0
|
||||
var/sound/mysound = null
|
||||
|
||||
New()
|
||||
..()
|
||||
var/sound/S = new/sound()
|
||||
mysound = S
|
||||
S.file = 'shore.ogg'
|
||||
S.repeat = 1
|
||||
S.wait = 0
|
||||
S.channel = 123
|
||||
S.volume = 100
|
||||
S.priority = 255
|
||||
S.status = SOUND_UPDATE
|
||||
process()
|
||||
|
||||
Entered(atom/movable/Obj,atom/OldLoc)
|
||||
if(ismob(Obj))
|
||||
if(Obj:client)
|
||||
mysound.status = SOUND_UPDATE
|
||||
Obj << mysound
|
||||
return
|
||||
|
||||
Exited(atom/movable/Obj)
|
||||
if(ismob(Obj))
|
||||
if(Obj:client)
|
||||
mysound.status = SOUND_PAUSED | SOUND_UPDATE
|
||||
Obj << mysound
|
||||
|
||||
proc/process()
|
||||
set background = 1
|
||||
|
||||
var/sound/S = null
|
||||
var/sound_delay = 0
|
||||
if(prob(25))
|
||||
S = sound(file=pick('seag1.ogg','seag2.ogg','seag3.ogg'), volume=100)
|
||||
sound_delay = rand(0, 50)
|
||||
|
||||
for(var/mob/living/carbon/human/H in src)
|
||||
if(H.s_tone > -55)
|
||||
H.s_tone--
|
||||
H.update_body()
|
||||
if(H.client)
|
||||
mysound.status = SOUND_UPDATE
|
||||
H << mysound
|
||||
if(S)
|
||||
spawn(sound_delay)
|
||||
H << S
|
||||
|
||||
spawn(60) .()
|
||||
|
||||
/obj/item/weapon/beach_ball
|
||||
icon = 'beach.dmi'
|
||||
icon_state = "ball"
|
||||
name = "beach ball"
|
||||
item_state = "clown"
|
||||
density = 0
|
||||
anchored = 0
|
||||
w_class = 1.0
|
||||
force = 0.0
|
||||
throwforce = 0.0
|
||||
throw_speed = 1
|
||||
throw_range = 20
|
||||
flags = FPRINT | USEDELAY | TABLEPASS | CONDUCT
|
||||
afterattack(atom/target as mob|obj|turf|area, mob/user as mob)
|
||||
user.drop_item()
|
||||
src.throw_at(target, throw_range, throw_speed)
|
||||
|
||||
/obj/item/weapon/hand_labeler
|
||||
icon = 'old_or_unused.dmi'
|
||||
icon_state = "labeler"
|
||||
item_state = "flight"
|
||||
name = "Hand labeler"
|
||||
var/label = null
|
||||
var/labels_left = 10
|
||||
|
||||
/obj/item/weapon/hand_labeler/afterattack(atom/A, mob/user as mob)
|
||||
if(A==loc) // if placing the labeller into something (e.g. backpack)
|
||||
return // don't set a label
|
||||
|
||||
if(!labels_left)
|
||||
user << "\red No labels left."
|
||||
return
|
||||
if(!label || !length(label))
|
||||
user << "\red No text set."
|
||||
return
|
||||
if(length(A.name) + length(label) > 64)
|
||||
user << "\red Label too big."
|
||||
return
|
||||
|
||||
for(var/mob/M in viewers())
|
||||
M << "\blue [user] puts a label on [A]."
|
||||
A.name = "[A.name] ([label])"
|
||||
|
||||
/obj/item/weapon/hand_labeler/attack_self()
|
||||
var/str = input(usr,"Label text?","Set label","")
|
||||
if(!str || !length(str))
|
||||
usr << "\red Invalid text."
|
||||
return
|
||||
if(length(str) > 10)
|
||||
usr << "\red Text too long."
|
||||
return
|
||||
label = str
|
||||
usr << "\blue You set the text to '[str]'."
|
||||
|
||||
/proc/testa()
|
||||
fake_attack(usr)
|
||||
|
||||
/proc/testb()
|
||||
fake_attack(input(usr) as mob in world)
|
||||
|
||||
/obj/fake_attacker
|
||||
icon = null
|
||||
icon_state = null
|
||||
name = ""
|
||||
desc = ""
|
||||
density = 0
|
||||
anchored = 1
|
||||
opacity = 0
|
||||
var/mob/living/carbon/human/my_target = null
|
||||
var/weapon_name = null
|
||||
|
||||
/obj/fake_attacker/attackby()
|
||||
step_away(src,my_target,2)
|
||||
for(var/mob/M in oviewers(world.view,my_target))
|
||||
M << "\red <B>[my_target] flails around wildly.</B>"
|
||||
my_target.show_message("\red <B>[src] has been attacked by [my_target] </B>", 1) //Lazy.
|
||||
return
|
||||
|
||||
/obj/fake_attacker/HasEntered(var/mob/M, somenumber)
|
||||
if(M == my_target)
|
||||
step_away(src,my_target,2)
|
||||
if(prob(30))
|
||||
for(var/mob/O in oviewers(world.view , my_target))
|
||||
O << "\red <B>[my_target] stumbles around.</B>"
|
||||
|
||||
/obj/fake_attacker/New()
|
||||
spawn(300) del(src)
|
||||
step_away(src,my_target,2)
|
||||
proccess()
|
||||
|
||||
/obj/fake_attacker/proc/proccess()
|
||||
if(!my_target) spawn(5) .()
|
||||
if(get_dist(src,my_target) > 1)
|
||||
step_towards(src,my_target)
|
||||
else
|
||||
if(prob(15))
|
||||
if(weapon_name)
|
||||
my_target << sound(pick('genhit1.ogg', 'genhit2.ogg', 'genhit3.ogg'))
|
||||
my_target.show_message("\red <B>[my_target] has been attacked with [weapon_name] by [src.name] </B>", 1)
|
||||
if(prob(20)) my_target.eye_blurry += 3
|
||||
if(prob(33))
|
||||
if(!locate(/obj/overlay) in my_target.loc)
|
||||
fake_blood(my_target)
|
||||
else
|
||||
my_target << sound(pick('punch1.ogg','punch2.ogg','punch3.ogg','punch4.ogg'))
|
||||
my_target.show_message("\red <B>[src.name] has punched [my_target]!</B>", 1)
|
||||
if(prob(33))
|
||||
if(!locate(/obj/overlay) in my_target.loc)
|
||||
fake_blood(my_target)
|
||||
|
||||
if(prob(15)) step_away(src,my_target,2)
|
||||
spawn(5) .()
|
||||
|
||||
/proc/fake_blood(var/mob/target)
|
||||
var/obj/overlay/O = new/obj/overlay(target.loc)
|
||||
O.name = "blood"
|
||||
var/image/I = image('blood.dmi',O,"floor[rand(1,7)]",O.dir,1)
|
||||
target << I
|
||||
spawn(300)
|
||||
del(O)
|
||||
return
|
||||
|
||||
/proc/fake_attack(var/mob/target)
|
||||
var/list/possible_clones = new/list()
|
||||
var/mob/living/carbon/human/clone = null
|
||||
var/clone_weapon = null
|
||||
|
||||
for(var/mob/living/carbon/human/H in world)
|
||||
if(H.stat || H.lying || H.dir == NORTH) continue
|
||||
possible_clones += H
|
||||
|
||||
if(!possible_clones.len) return
|
||||
clone = pick(possible_clones)
|
||||
|
||||
if(clone.l_hand)
|
||||
clone_weapon = clone.l_hand.name
|
||||
else if (clone.r_hand)
|
||||
clone_weapon = clone.r_hand.name
|
||||
|
||||
var/obj/fake_attacker/F = new/obj/fake_attacker(target.loc)
|
||||
|
||||
F.name = clone.name
|
||||
F.my_target = target
|
||||
F.weapon_name = clone_weapon
|
||||
|
||||
var/image/O = image(clone,F)
|
||||
target << O
|
||||
|
||||
|
||||
/proc/can_see(var/atom/source, var/atom/target, var/length=5) // I couldnt be arsed to do actual raycasting :I This is horribly inaccurate.
|
||||
var/turf/current = get_turf(source)
|
||||
var/turf/target_turf = get_turf(target)
|
||||
var/steps = 0
|
||||
|
||||
while(current != target_turf)
|
||||
if(steps > length) return 0
|
||||
if(current.opacity) return 0
|
||||
for(var/atom/A in current)
|
||||
if(A.opacity) return 0
|
||||
current = get_step_towards(current, target_turf)
|
||||
steps++
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/mob/proc/get_equipped_items()
|
||||
var/list/items = new/list()
|
||||
|
||||
if(hasvar(src,"back")) if(src:back) items += src:back
|
||||
if(hasvar(src,"belt")) if(src:belt) items += src:belt
|
||||
if(hasvar(src,"ears")) if(src:ears) items += src:ears
|
||||
if(hasvar(src,"glasses")) if(src:glasses) items += src:glasses
|
||||
if(hasvar(src,"gloves")) if(src:gloves) items += src:gloves
|
||||
if(hasvar(src,"head")) if(src:head) items += src:head
|
||||
if(hasvar(src,"shoes")) if(src:shoes) items += src:shoes
|
||||
if(hasvar(src,"wear_id")) if(src:wear_id) items += src:wear_id
|
||||
if(hasvar(src,"wear_mask")) if(src:wear_mask) items += src:wear_mask
|
||||
if(hasvar(src,"wear_suit")) if(src:wear_suit) items += src:wear_suit
|
||||
// if(hasvar(src,"w_radio")) if(src:w_radio) items += src:w_radio commenting this out since headsets go on your ears now PLEASE DON'T BE MAD KEELIN
|
||||
if(hasvar(src,"w_uniform")) if(src:w_uniform) items += src:w_uniform
|
||||
|
||||
//if(hasvar(src,"l_hand")) if(src:l_hand) items += src:l_hand
|
||||
//if(hasvar(src,"r_hand")) if(src:r_hand) items += src:r_hand
|
||||
|
||||
return items
|
||||
|
||||
/proc/is_blocked_turf(var/turf/T)
|
||||
var/cant_pass = 0
|
||||
if(T.density) cant_pass = 1
|
||||
for(var/atom/A in T)
|
||||
if(A.density)//&&A.anchored
|
||||
cant_pass = 1
|
||||
return cant_pass
|
||||
|
||||
/proc/get_step_towards2(var/atom/ref , var/atom/trg)
|
||||
var/base_dir = get_dir(ref, get_step_towards(ref,trg))
|
||||
var/turf/temp = get_step_towards(ref,trg)
|
||||
|
||||
if(is_blocked_turf(temp))
|
||||
var/dir_alt1 = turn(base_dir, 90)
|
||||
var/dir_alt2 = turn(base_dir, -90)
|
||||
var/turf/turf_last1 = temp
|
||||
var/turf/turf_last2 = temp
|
||||
var/free_tile = null
|
||||
var/breakpoint = 0
|
||||
|
||||
while(!free_tile && breakpoint < 10)
|
||||
if(!is_blocked_turf(turf_last1))
|
||||
free_tile = turf_last1
|
||||
break
|
||||
if(!is_blocked_turf(turf_last2))
|
||||
free_tile = turf_last2
|
||||
break
|
||||
turf_last1 = get_step(turf_last1,dir_alt1)
|
||||
turf_last2 = get_step(turf_last2,dir_alt2)
|
||||
breakpoint++
|
||||
|
||||
if(!free_tile) return get_step(ref, base_dir)
|
||||
else return get_step_towards(ref,free_tile)
|
||||
|
||||
else return get_step(ref, base_dir)
|
||||
|
||||
/proc/do_mob(var/mob/user , var/mob/target, var/time = 30) //This is quite an ugly solution but i refuse to use the old request system.
|
||||
if(!user || !target) return 0
|
||||
var/user_loc = user.loc
|
||||
var/target_loc = target.loc
|
||||
var/holding = user.equipped()
|
||||
sleep(time)
|
||||
if ( user.loc == user_loc && target.loc == target_loc && user.equipped() == holding && !( user.stat ) && ( !user.stunned && !user.weakened && !user.paralysis && !user.lying ) )
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/proc/do_after(mob/M as mob, time as num)
|
||||
var/turf/T = M.loc
|
||||
var/holding = M.equipped()
|
||||
sleep(time)
|
||||
if ((M.loc == T && M.equipped() == holding && !( M.stat )))
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/proc/hasvar(var/datum/A, var/varname)
|
||||
//Takes: Anything that could possibly have variables and a varname to check.
|
||||
//Returns: 1 if found, 0 if not.
|
||||
//Notes: Do i really need to explain this?
|
||||
if(A.vars.Find(lowertext(varname))) return 1
|
||||
else return 0
|
||||
|
||||
/proc/get_areas(var/areatype)
|
||||
//Takes: Area type as text string or as typepath OR an instance of the area.
|
||||
//Returns: A list of all areas of that type in the world.
|
||||
//Notes: Simple!
|
||||
if(!areatype) return null
|
||||
if(istext(areatype)) areatype = text2path(areatype)
|
||||
if(isarea(areatype))
|
||||
var/area/areatemp = areatype
|
||||
areatype = areatemp.type
|
||||
|
||||
var/list/areas = new/list()
|
||||
for(var/area/N in world)
|
||||
if(istype(N, areatype)) areas += N
|
||||
return areas
|
||||
|
||||
/proc/get_area_turfs(var/areatype)
|
||||
//Takes: Area type as text string or as typepath OR an instance of the area.
|
||||
//Returns: A list of all turfs in areas of that type of that type in the world.
|
||||
//Notes: Simple!
|
||||
|
||||
if(!areatype) return null
|
||||
if(istext(areatype)) areatype = text2path(areatype)
|
||||
if(isarea(areatype))
|
||||
var/area/areatemp = areatype
|
||||
areatype = areatemp.type
|
||||
|
||||
var/list/turfs = new/list()
|
||||
for(var/area/N in world)
|
||||
if(istype(N, areatype))
|
||||
for(var/turf/T in N) turfs += T
|
||||
return turfs
|
||||
|
||||
/proc/get_area_all_atoms(var/areatype)
|
||||
//Takes: Area type as text string or as typepath OR an instance of the area.
|
||||
//Returns: A list of all atoms (objs, turfs, mobs) in areas of that type of that type in the world.
|
||||
//Notes: Simple!
|
||||
|
||||
if(!areatype) return null
|
||||
if(istext(areatype)) areatype = text2path(areatype)
|
||||
if(isarea(areatype))
|
||||
var/area/areatemp = areatype
|
||||
areatype = areatemp.type
|
||||
|
||||
var/list/atoms = new/list()
|
||||
for(var/area/N in world)
|
||||
if(istype(N, areatype))
|
||||
for(var/atom/A in N)
|
||||
atoms += A
|
||||
return atoms
|
||||
|
||||
/datum/coords //Simple datum for storing coordinates.
|
||||
var/x_pos = null
|
||||
var/y_pos = null
|
||||
var/z_pos = null
|
||||
|
||||
/area/proc/move_contents_to(var/area/A, var/turftoleave=null)
|
||||
//Takes: Area. Optional: turf type to leave behind.
|
||||
//Returns: Nothing.
|
||||
//Notes: Attempts to move the contents of one area to another area.
|
||||
// Movement based on lower left corner. Tiles that do not fit
|
||||
// into the new area will not be moved.
|
||||
|
||||
if(!A || !src) return 0
|
||||
|
||||
var/list/turfs_src = get_area_turfs(src.type)
|
||||
var/list/turfs_trg = get_area_turfs(A.type)
|
||||
|
||||
var/src_min_x = 0
|
||||
var/src_min_y = 0
|
||||
for (var/turf/T in turfs_src)
|
||||
if(T.x < src_min_x || !src_min_x) src_min_x = T.x
|
||||
if(T.y < src_min_y || !src_min_y) src_min_y = T.y
|
||||
|
||||
var/trg_min_x = 0
|
||||
var/trg_min_y = 0
|
||||
for (var/turf/T in turfs_trg)
|
||||
if(T.x < trg_min_x || !trg_min_x) trg_min_x = T.x
|
||||
if(T.y < trg_min_y || !trg_min_y) trg_min_y = T.y
|
||||
|
||||
var/list/refined_src = new/list()
|
||||
for(var/turf/T in turfs_src)
|
||||
refined_src += T
|
||||
refined_src[T] = new/datum/coords
|
||||
var/datum/coords/C = refined_src[T]
|
||||
C.x_pos = (T.x - src_min_x)
|
||||
C.y_pos = (T.y - src_min_y)
|
||||
|
||||
var/list/refined_trg = new/list()
|
||||
for(var/turf/T in turfs_trg)
|
||||
refined_trg += T
|
||||
refined_trg[T] = new/datum/coords
|
||||
var/datum/coords/C = refined_trg[T]
|
||||
C.x_pos = (T.x - trg_min_x)
|
||||
C.y_pos = (T.y - trg_min_y)
|
||||
|
||||
var/list/fromupdate = new/list()
|
||||
var/list/toupdate = new/list()
|
||||
|
||||
moving:
|
||||
for (var/turf/T in refined_src)
|
||||
var/datum/coords/C_src = refined_src[T]
|
||||
for (var/turf/B in refined_trg)
|
||||
var/datum/coords/C_trg = refined_trg[B]
|
||||
if(C_src.x_pos == C_trg.x_pos && C_src.y_pos == C_trg.y_pos)
|
||||
|
||||
var/old_dir1 = T.dir
|
||||
var/old_icon_state1 = T.icon_state
|
||||
|
||||
var/turf/X = new T.type(B)
|
||||
X.dir = old_dir1
|
||||
X.icon_state = old_icon_state1
|
||||
|
||||
for(var/obj/O in T)
|
||||
if(!istype(O,/obj)) continue
|
||||
O.loc = X
|
||||
for(var/mob/M in T)
|
||||
if(!istype(M,/mob)) continue
|
||||
M.loc = X
|
||||
|
||||
var/area/AR = X.loc
|
||||
|
||||
if(AR.sd_lighting)
|
||||
X.opacity = !X.opacity
|
||||
X.sd_SetOpacity(!X.opacity)
|
||||
|
||||
toupdate += X
|
||||
|
||||
if(turftoleave)
|
||||
var/turf/ttl = new turftoleave(T)
|
||||
|
||||
var/area/AR2 = ttl.loc
|
||||
|
||||
if(AR2.sd_lighting)
|
||||
ttl.opacity = !ttl.opacity
|
||||
ttl.sd_SetOpacity(!ttl.opacity)
|
||||
|
||||
fromupdate += ttl
|
||||
|
||||
else
|
||||
T.ReplaceWithSpace()
|
||||
|
||||
refined_src -= T
|
||||
refined_trg -= B
|
||||
continue moving
|
||||
|
||||
var/list/doors = new/list()
|
||||
|
||||
if(toupdate.len)
|
||||
for(var/turf/simulated/T1 in toupdate)
|
||||
for(var/obj/machinery/door/D2 in T1)
|
||||
doors += D2
|
||||
if(T1.parent)
|
||||
air_master.groups_to_rebuild += T1.parent
|
||||
else
|
||||
air_master.tiles_to_update += T1
|
||||
|
||||
if(fromupdate.len)
|
||||
for(var/turf/simulated/T2 in fromupdate)
|
||||
for(var/obj/machinery/door/D2 in T2)
|
||||
doors += D2
|
||||
if(T2.parent)
|
||||
air_master.groups_to_rebuild += T2.parent
|
||||
else
|
||||
air_master.tiles_to_update += T2
|
||||
|
||||
for(var/obj/O in doors)
|
||||
O:update_nearby_tiles(1)
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
var/CMinutes = null
|
||||
var/savefile/Banlist
|
||||
|
||||
|
||||
/proc/CheckBan(var/client/clientvar)
|
||||
|
||||
var/id = clientvar.computer_id
|
||||
var/key = clientvar.ckey
|
||||
|
||||
Banlist.cd = "/base"
|
||||
if (Banlist.dir.Find("[key][id]"))
|
||||
Banlist.cd = "[key][id]"
|
||||
if (Banlist["temp"])
|
||||
if (!GetExp(Banlist["minutes"]))
|
||||
ClearTempbans()
|
||||
return 0
|
||||
else
|
||||
return "[Banlist["reason"]]\n(This ban will be automatically removed in [GetExp(Banlist["minutes"])].)"
|
||||
else
|
||||
Banlist.cd = "/base/[key][id]"
|
||||
return "[Banlist["reason"]]\n(This is a permanent ban)"
|
||||
|
||||
Banlist.cd = "/base"
|
||||
for (var/A in Banlist.dir)
|
||||
Banlist.cd = "/base/[A]"
|
||||
if (id == Banlist["id"] || key == Banlist["key"])
|
||||
if(Banlist["temp"])
|
||||
if (!GetExp(Banlist["minutes"]))
|
||||
ClearTempbans()
|
||||
return 0
|
||||
else
|
||||
return "[Banlist["reason"]]\n(This ban will be automatically removed in [GetExp(Banlist["minutes"])].)"
|
||||
else
|
||||
return "[Banlist["reason"]]\n(This is a permanent ban)"
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
/proc/UpdateTime() //No idea why i made this a proc.
|
||||
CMinutes = (world.realtime / 10) / 60
|
||||
return 1
|
||||
|
||||
/proc/LoadBans()
|
||||
|
||||
Banlist = new("data/banlist.bdb")
|
||||
log_admin("Loading Banlist")
|
||||
|
||||
if (!length(Banlist.dir)) log_admin("Banlist is empty.")
|
||||
|
||||
if (!Banlist.dir.Find("base"))
|
||||
log_admin("Banlist missing base dir.")
|
||||
Banlist.dir.Add("base")
|
||||
Banlist.cd = "/base"
|
||||
else if (Banlist.dir.Find("base"))
|
||||
Banlist.cd = "/base"
|
||||
|
||||
ClearTempbans()
|
||||
return 1
|
||||
|
||||
/proc/ClearTempbans()
|
||||
UpdateTime()
|
||||
|
||||
Banlist.cd = "/base"
|
||||
for (var/A in Banlist.dir)
|
||||
Banlist.cd = "/base/[A]"
|
||||
if (!Banlist["key"] || !Banlist["id"])
|
||||
RemoveBan(A)
|
||||
log_admin("Invalid Ban.")
|
||||
message_admins("Invalid Ban.")
|
||||
continue
|
||||
|
||||
if (!Banlist["temp"]) continue
|
||||
if (CMinutes >= Banlist["minutes"]) RemoveBan(A)
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
/proc/AddBan(ckey, computerid, reason, bannedby, temp, minutes)
|
||||
|
||||
var/bantimestamp
|
||||
|
||||
if (temp)
|
||||
UpdateTime()
|
||||
bantimestamp = CMinutes + minutes
|
||||
|
||||
Banlist.cd = "/base"
|
||||
if ( Banlist.dir.Find("[ckey][computerid]") )
|
||||
usr << text("\red Ban already exists.")
|
||||
return 0
|
||||
else
|
||||
Banlist.dir.Add("[ckey][computerid]")
|
||||
Banlist.cd = "/base/[ckey][computerid]"
|
||||
Banlist["key"] << ckey
|
||||
Banlist["id"] << computerid
|
||||
Banlist["reason"] << reason
|
||||
Banlist["bannedby"] << bannedby
|
||||
Banlist["temp"] << temp
|
||||
if (temp)
|
||||
Banlist["minutes"] << bantimestamp
|
||||
|
||||
return 1
|
||||
|
||||
/proc/RemoveBan(foldername)
|
||||
var/key
|
||||
var/id
|
||||
|
||||
Banlist.cd = "/base/[foldername]"
|
||||
Banlist["key"] >> key
|
||||
Banlist["id"] >> id
|
||||
Banlist.cd = "/base"
|
||||
|
||||
if (!Banlist.dir.Remove(foldername)) return 0
|
||||
|
||||
if(!usr)
|
||||
log_admin("Ban Expired: [key]")
|
||||
message_admins("Ban Expired: [key]")
|
||||
else
|
||||
log_admin("[key_name_admin(usr)] unbanned [key]")
|
||||
message_admins("[key_name_admin(usr)] unbanned: [key]")
|
||||
|
||||
for (var/A in Banlist.dir)
|
||||
Banlist.cd = "/base/[A]"
|
||||
if (key == Banlist["key"] || id == Banlist["id"])
|
||||
Banlist.cd = "/base"
|
||||
Banlist.dir.Remove(A)
|
||||
continue
|
||||
|
||||
return 1
|
||||
|
||||
/proc/GetExp(minutes as num)
|
||||
UpdateTime()
|
||||
var/exp = minutes - CMinutes
|
||||
if (exp <= 0)
|
||||
return 0
|
||||
else
|
||||
var/timeleftstring
|
||||
if (exp >= 1440) //1440 = 1 day in minutes
|
||||
timeleftstring = "[round(exp / 1440, 0.1)] Days"
|
||||
else if (exp >= 60) //60 = 1 hour in minutes
|
||||
timeleftstring = "[round(exp / 60, 0.1)] Hours"
|
||||
else
|
||||
timeleftstring = "[exp] Minutes"
|
||||
return timeleftstring
|
||||
|
||||
/obj/admins/proc/unbanpanel()
|
||||
var/count = 0
|
||||
var/dat
|
||||
//var/dat = "<HR><B>Unban Player:</B> \blue(U) = Unban , (E) = Edit Ban\green (Total<HR><table border=1 rules=all frame=void cellspacing=0 cellpadding=3 >"
|
||||
Banlist.cd = "/base"
|
||||
for (var/A in Banlist.dir)
|
||||
count++
|
||||
Banlist.cd = "/base/[A]"
|
||||
dat += text("<tr><td><A href='?src=\ref[src];unbanf=[Banlist["key"]][Banlist["id"]]'>(U)</A><A href='?src=\ref[src];unbane=[Banlist["key"]][Banlist["id"]]'>(E)</A> Key: <B>[Banlist["key"]]</B></td><td> ([Banlist["temp"] ? "[GetExp(Banlist["minutes"]) ? GetExp(Banlist["minutes"]) : "Removal pending" ]" : "Permaban"])</td><td>(By: [Banlist["bannedby"]])</td><td>(Reason: [Banlist["reason"]])</td></tr>")
|
||||
|
||||
dat += "</table>"
|
||||
dat = "<HR><B>Bans:</B> <FONT COLOR=blue>(U) = Unban , (E) = Edit Ban</FONT> - <FONT COLOR=green>([count] Bans)</FONT><HR><table border=1 rules=all frame=void cellspacing=0 cellpadding=3 >[dat]"
|
||||
usr << browse(dat, "window=unbanp;size=875x400")
|
||||
|
||||
//////////////////////////////////// DEBUG ////////////////////////////////////
|
||||
|
||||
/proc/CreateBans()
|
||||
|
||||
UpdateTime()
|
||||
|
||||
var/i
|
||||
var/last
|
||||
|
||||
for(i=0, i<1001, i++)
|
||||
var/a = pick(1,0)
|
||||
var/b = pick(1,0)
|
||||
if(b)
|
||||
Banlist.cd = "/base"
|
||||
Banlist.dir.Add("trash[i]trashid[i]")
|
||||
Banlist.cd = "/base/trash[i]trashid[i]"
|
||||
Banlist["key"] << "trash[i]"
|
||||
else
|
||||
Banlist.cd = "/base"
|
||||
Banlist.dir.Add("[last]trashid[i]")
|
||||
Banlist.cd = "/base/[last]trashid[i]"
|
||||
Banlist["key"] << last
|
||||
Banlist["id"] << "trashid[i]"
|
||||
Banlist["reason"] << "Trashban[i]."
|
||||
Banlist["temp"] << a
|
||||
Banlist["minutes"] << CMinutes + rand(1,2000)
|
||||
Banlist["bannedby"] << "trashmin"
|
||||
last = "trash[i]"
|
||||
|
||||
Banlist.cd = "/base"
|
||||
|
||||
/proc/ClearAllBans()
|
||||
Banlist.cd = "/base"
|
||||
for (var/A in Banlist.dir)
|
||||
RemoveBan(A)
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
/proc/togglebuildmode(mob/M as mob in world)
|
||||
if(M.client)
|
||||
if(M.client.buildmode)
|
||||
M.client.buildmode = 0
|
||||
M.client.show_popup_menus = 1
|
||||
for(var/obj/buildholder/H)
|
||||
if(H.cl == M.client)
|
||||
del(H)
|
||||
else
|
||||
M.client.buildmode = 1
|
||||
M.client.show_popup_menus = 0
|
||||
|
||||
var/obj/buildholder/H = new/obj/buildholder()
|
||||
var/obj/builddir/A = new/obj/builddir(H)
|
||||
A.master = H
|
||||
var/obj/buildhelp/B = new/obj/buildhelp(H)
|
||||
B.master = H
|
||||
var/obj/buildmode/C = new/obj/buildmode(H)
|
||||
C.master = H
|
||||
var/obj/buildquit/D = new/obj/buildquit(H)
|
||||
D.master = H
|
||||
|
||||
H.builddir = A
|
||||
H.buildhelp = B
|
||||
H.buildmode = C
|
||||
H.buildquit = D
|
||||
M.client.screen += A
|
||||
M.client.screen += B
|
||||
M.client.screen += C
|
||||
M.client.screen += D
|
||||
H.cl = M.client
|
||||
|
||||
/obj/builddir
|
||||
density = 1
|
||||
anchored = 1
|
||||
layer = 20
|
||||
dir = NORTH
|
||||
icon = 'buildmode.dmi'
|
||||
icon_state = "build"
|
||||
screen_loc = "NORTH,WEST"
|
||||
var/obj/buildholder/master = null
|
||||
/obj/buildhelp
|
||||
density = 1
|
||||
anchored = 1
|
||||
layer = 20
|
||||
dir = NORTH
|
||||
icon = 'buildmode.dmi'
|
||||
icon_state = "buildhelp"
|
||||
screen_loc = "NORTH,WEST+1"
|
||||
var/obj/buildholder/master = null
|
||||
/obj/buildmode
|
||||
density = 1
|
||||
anchored = 1
|
||||
layer = 20
|
||||
dir = NORTH
|
||||
icon = 'buildmode.dmi'
|
||||
icon_state = "buildmode1"
|
||||
screen_loc = "NORTH,WEST+2"
|
||||
var/obj/buildholder/master = null
|
||||
var/varholder = "name"
|
||||
var/valueholder = "derp"
|
||||
var/objholder = "/obj/closet"
|
||||
/obj/buildquit
|
||||
density = 1
|
||||
anchored = 1
|
||||
layer = 20
|
||||
dir = NORTH
|
||||
icon = 'buildmode.dmi'
|
||||
icon_state = "buildquit"
|
||||
screen_loc = "NORTH,WEST+3"
|
||||
var/obj/buildholder/master = null
|
||||
|
||||
/obj/buildquit/Click()
|
||||
togglebuildmode(master.cl.mob)
|
||||
|
||||
/obj/buildholder
|
||||
density = 0
|
||||
anchored = 1
|
||||
var/client/cl = null
|
||||
var/obj/builddir/builddir = null
|
||||
var/obj/buildhelp/buildhelp = null
|
||||
var/obj/buildmode/buildmode = null
|
||||
var/obj/buildquit/buildquit = null
|
||||
|
||||
/obj/builddir/Click()
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
dir = EAST
|
||||
if(EAST)
|
||||
dir = SOUTH
|
||||
if(SOUTH)
|
||||
dir = WEST
|
||||
if(WEST)
|
||||
dir = NORTHWEST
|
||||
if(NORTHWEST)
|
||||
dir = NORTH
|
||||
|
||||
/obj/buildhelp/Click()
|
||||
switch(master.cl.buildmode)
|
||||
if(1)
|
||||
usr << "\blue ***********************************************************"
|
||||
usr << "\blue Left Mouse Button = Construct / Upgrade"
|
||||
usr << "\blue Right Mouse Button = Deconstruct / Delete / Downgrade"
|
||||
usr << "\blue Left Mouse Button + ctrl = R-Window"
|
||||
usr << "\blue Left Mouse Button + alt = Airlock"
|
||||
usr << ""
|
||||
usr << "\blue Use the button in the upper left corner to"
|
||||
usr << "\blue change the direction of built objects."
|
||||
usr << "\blue ***********************************************************"
|
||||
if(2)
|
||||
usr << "\blue ***********************************************************"
|
||||
usr << "\blue Right Mouse Button on buildmode button = Set object type"
|
||||
usr << "\blue Left Mouse Button on turf/obj = Place objects"
|
||||
usr << "\blue Right Mouse Button = Delete objects"
|
||||
usr << ""
|
||||
usr << "\blue Use the button in the upper left corner to"
|
||||
usr << "\blue change the direction of built objects."
|
||||
usr << "\blue ***********************************************************"
|
||||
if(3)
|
||||
usr << "\blue ***********************************************************"
|
||||
usr << "\blue Right Mouse Button on buildmode button = Select var(type) & value"
|
||||
usr << "\blue Left Mouse Button on turf/obj/mob = Set var(type) & value"
|
||||
usr << "\blue Right Mouse Button on turf/obj/mob = Reset var's value"
|
||||
usr << "\blue ***********************************************************"
|
||||
|
||||
/obj/buildmode/Click(location, control, params)
|
||||
var/list/pa = params2list(params)
|
||||
|
||||
if(pa.Find("left"))
|
||||
switch(master.cl.buildmode)
|
||||
if(1)
|
||||
master.cl.buildmode = 2
|
||||
src.icon_state = "buildmode2"
|
||||
if(2)
|
||||
master.cl.buildmode = 3
|
||||
src.icon_state = "buildmode3"
|
||||
if(3)
|
||||
master.cl.buildmode = 1
|
||||
src.icon_state = "buildmode1"
|
||||
else if(pa.Find("right"))
|
||||
switch(master.cl.buildmode)
|
||||
if(1)
|
||||
return
|
||||
if(2)
|
||||
objholder = input(usr,"Enter typepath:" ,"Typepath","/obj/closet")
|
||||
var/list/removed_paths = list("/obj/bhole")
|
||||
if(objholder in removed_paths)
|
||||
alert("That path is not allowed.")
|
||||
objholder = "/obj/closet"
|
||||
else if (dd_hasprefix(objholder, "/mob") && !(usr.client.holder.rank in list("Host", "Coder", "Shit Guy")))
|
||||
objholder = "/obj/closet"
|
||||
if(3)
|
||||
var/list/locked = list("vars", "key", "ckey", "client", "firemut", "ishulk", "telekinesis", "xray", "virus", "cuffed", "ka", "last_eaten", "urine")
|
||||
|
||||
master.buildmode.varholder = input(usr,"Enter variable name:" ,"Name", "name")
|
||||
if(master.buildmode.varholder in locked && !(usr.client.holder.rank in list("Host", "Coder")))
|
||||
return
|
||||
var/thetype = input(usr,"Select variable type:" ,"Type") in list("text","number","mob-reference","obj-reference","turf-reference")
|
||||
if(!thetype) return
|
||||
switch(thetype)
|
||||
if("text")
|
||||
master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value", "value") as text
|
||||
if("number")
|
||||
master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value", 123) as num
|
||||
if("mob-reference")
|
||||
master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value") as mob in world
|
||||
if("obj-reference")
|
||||
master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value") as obj in world
|
||||
if("turf-reference")
|
||||
master.buildmode.valueholder = input(usr,"Enter variable value:" ,"Value") as turf in world
|
||||
|
||||
|
||||
/proc/build_click(var/mob/user, buildmode, location, control, params, var/obj/object)
|
||||
|
||||
var/obj/buildholder/holder = null
|
||||
|
||||
for(var/obj/buildholder/H)
|
||||
if(H.cl == user.client)
|
||||
holder = H
|
||||
break
|
||||
|
||||
if(!holder) return
|
||||
var/list/pa = params2list(params)
|
||||
|
||||
|
||||
switch(buildmode)
|
||||
|
||||
if(1)
|
||||
if(istype(object,/turf) && pa.Find("left") && !pa.Find("alt") && !pa.Find("ctrl") )
|
||||
if(istype(object,/turf/space))
|
||||
var/turf/T = object
|
||||
T.ReplaceWithFloor()
|
||||
return
|
||||
else if(istype(object,/turf/simulated/floor))
|
||||
var/turf/T = object
|
||||
T.ReplaceWithWall()
|
||||
return
|
||||
else if(istype(object,/turf/simulated/wall))
|
||||
var/turf/T = object
|
||||
T.ReplaceWithRWall()
|
||||
return
|
||||
|
||||
else if(pa.Find("right"))
|
||||
if(istype(object,/turf/simulated/wall))
|
||||
var/turf/T = object
|
||||
T.ReplaceWithFloor()
|
||||
return
|
||||
else if(istype(object,/turf/simulated/floor))
|
||||
var/turf/T = object
|
||||
T.ReplaceWithSpace()
|
||||
return
|
||||
else if(istype(object,/turf/simulated/wall/r_wall))
|
||||
var/turf/T = object
|
||||
T.ReplaceWithWall()
|
||||
return
|
||||
else if(istype(object,/obj))
|
||||
del(object)
|
||||
return
|
||||
|
||||
else if(istype(object,/turf) && pa.Find("alt") && pa.Find("left"))
|
||||
new/obj/machinery/door/airlock(get_turf(object))
|
||||
|
||||
else if(istype(object,/turf) && pa.Find("ctrl") && pa.Find("left"))
|
||||
switch(holder.builddir.dir)
|
||||
if(NORTH)
|
||||
new/obj/window/reinforced/north(get_turf(object))
|
||||
if(EAST)
|
||||
new/obj/window/reinforced/east(get_turf(object))
|
||||
if(SOUTH)
|
||||
new/obj/window/reinforced/south(get_turf(object))
|
||||
if(WEST)
|
||||
new/obj/window/reinforced/west(get_turf(object))
|
||||
if(NORTHWEST)
|
||||
new/obj/window/reinforced/northwest(get_turf(object))
|
||||
if(2)
|
||||
if(pa.Find("left"))
|
||||
var/obj/A = new holder.buildmode.objholder (get_turf(object))
|
||||
A.dir = holder.builddir.dir
|
||||
blink(A)
|
||||
else if(pa.Find("right"))
|
||||
if(isobj(object)) del(object)
|
||||
|
||||
if(3)
|
||||
if(pa.Find("left")) //I cant believe this shit actually compiles.
|
||||
if(object.vars.Find(holder.buildmode.varholder))
|
||||
log_admin("[key_name(usr)] modified [object.name]'s [holder.buildmode.varholder] to [holder.buildmode.valueholder]")
|
||||
// message_admins("[key_name_admin(usr)] modified [object.name]'s [holder.buildmode.varholder] to [holder.buildmode.valueholder]", 1)
|
||||
object.vars[holder.buildmode.varholder] = holder.buildmode.valueholder
|
||||
blink(object)
|
||||
else
|
||||
usr << "\red [initial(object.name)] does not have a var called '[holder.buildmode.varholder]'"
|
||||
if(pa.Find("right"))
|
||||
if(object.vars.Find(holder.buildmode.varholder))
|
||||
log_admin("[key_name(usr)] modified [object.name]'s [holder.buildmode.varholder] to [holder.buildmode.valueholder]")
|
||||
// message_admins("[key_name_admin(usr)] modified [object.name]'s [holder.buildmode.varholder] to [holder.buildmode.valueholder]", 1)
|
||||
object.vars[holder.buildmode.varholder] = initial(object.vars[holder.buildmode.varholder])
|
||||
blink(object)
|
||||
else
|
||||
usr << "\red [initial(object.name)] does not have a var called '[holder.buildmode.varholder]'"
|
||||
|
||||
/proc/blink(atom/A)
|
||||
A.icon += rgb(0,75,75)
|
||||
spawn(10) A.icon = initial(A.icon)
|
||||
@@ -0,0 +1,724 @@
|
||||
//Cloning revival method.
|
||||
//The pod handles the actual cloning while the computer manages the clone profiles
|
||||
|
||||
//Potential replacement for genetics revives or something I dunno (?)
|
||||
|
||||
/obj/machinery/clonepod
|
||||
anchored = 1
|
||||
name = "cloning pod"
|
||||
desc = "An electronically-lockable pod for growing organic tissue."
|
||||
density = 1
|
||||
icon = 'cloning.dmi'
|
||||
icon_state = "pod_0"
|
||||
req_access = list(access_medlab) //For premature unlocking.
|
||||
var/mob/living/occupant
|
||||
var/heal_level = 90 //The clone is released once its health reaches this level.
|
||||
var/locked = 0
|
||||
var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine.
|
||||
var/mess = 0 //Need to clean out it if it's full of exploded clone.
|
||||
var/attempting = 0 //One clone attempt at a time thanks
|
||||
var/eject_wait = 0 //Don't eject them as soon as they are created fuckkk
|
||||
|
||||
/obj/machinery/computer/cloning
|
||||
name = "Cloning console"
|
||||
icon = 'computer.dmi'
|
||||
icon_state = "dna"
|
||||
req_access = list(access_heads) //Only used for record deletion right now.
|
||||
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
|
||||
var/obj/machinery/clonepod/pod1 = null //Linked cloning pod.
|
||||
var/temp = "Initializing System..."
|
||||
var/menu = 1 //Which menu screen to display
|
||||
var/list/records = list()
|
||||
var/datum/data/record/active_record = null
|
||||
var/obj/item/weapon/disk/data/diskette = null //Mostly so the geneticist can steal everything.
|
||||
|
||||
//The return of data disks?? Just for transferring between genetics machine/cloning machine.
|
||||
//TO-DO: Make the genetics machine accept them.
|
||||
/obj/item/weapon/disk/data
|
||||
name = "data disk"
|
||||
icon = 'cloning.dmi'
|
||||
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
|
||||
item_state = "card-id"
|
||||
w_class = 1.0
|
||||
var/data = ""
|
||||
var/ue = 0
|
||||
var/data_type = "ui" //ui|se
|
||||
var/owner = "God Emperor of Mankind"
|
||||
var/read_only = 0 //Well,it's still a floppy disk
|
||||
|
||||
/obj/item/weapon/disk/data/demo
|
||||
name = "data disk - 'God Emperor of Mankind'"
|
||||
data = "066000033000000000AF00330660FF4DB002690"
|
||||
//data = "0C80C80C80C80C80C8000000000000161FBDDEF" - Farmer Jeff
|
||||
ue = 1
|
||||
read_only = 1
|
||||
|
||||
/obj/item/weapon/disk/data/monkey
|
||||
name = "data disk - 'Mr. Muggles'"
|
||||
data_type = "se"
|
||||
data = "0983E840344C39F4B059D5145FC5785DC6406A4FFF"
|
||||
read_only = 1
|
||||
|
||||
/obj/machinery/computer/cloning/New()
|
||||
..()
|
||||
spawn(5)
|
||||
src.scanner = locate(/obj/machinery/dna_scannernew, get_step(src, WEST))
|
||||
src.pod1 = locate(/obj/machinery/clonepod, get_step(src, EAST))
|
||||
|
||||
src.temp = ""
|
||||
if (isnull(src.scanner))
|
||||
src.temp += " <font color=red>SCNR-ERROR</font>"
|
||||
if (isnull(src.pod1))
|
||||
src.temp += " <font color=red>POD1-ERROR</font>"
|
||||
else
|
||||
src.pod1.connected = src
|
||||
|
||||
if (src.temp == "")
|
||||
src.temp = "System ready."
|
||||
return
|
||||
return
|
||||
|
||||
/obj/machinery/computer/cloning/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (istype(W, /obj/item/weapon/disk/data)) //INSERT SOME DISKETTES
|
||||
if (!src.diskette)
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
src.diskette = W
|
||||
user << "You insert [W]."
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
else if((istype(W, /obj/item/weapon/screwdriver)) && (src.stat & BROKEN))
|
||||
playsound(src.loc, 'Screwdriver.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
user << "\blue The broken glass falls out."
|
||||
var/obj/computerframe/A = new /obj/computerframe( src.loc )
|
||||
new /obj/item/weapon/shard( src.loc )
|
||||
var/obj/item/weapon/circuitboard/cloning/M = new /obj/item/weapon/circuitboard/cloning( A )
|
||||
for (var/obj/C in src)
|
||||
C.loc = src.loc
|
||||
M.records = src.records
|
||||
A.circuit = M
|
||||
A.state = 3
|
||||
A.icon_state = "3"
|
||||
A.anchored = 1
|
||||
del(src)
|
||||
else
|
||||
src.attack_hand(user)
|
||||
return
|
||||
|
||||
/obj/machinery/computer/cloning/attack_paw(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/cloning/attack_ai(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer/cloning/attack_hand(mob/user as mob)
|
||||
user.machine = src
|
||||
add_fingerprint(user)
|
||||
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
|
||||
var/dat = "<h3>Cloning System Control</h3>"
|
||||
dat += "<font size=-1><a href='byond://?src=\ref[src];refresh=1'>Refresh</a></font>"
|
||||
|
||||
dat += "<br><tt>[temp]</tt><br>"
|
||||
|
||||
switch(src.menu)
|
||||
if(1)
|
||||
dat += "<h4>Scanner Functions</h4>"
|
||||
|
||||
if (isnull(src.scanner))
|
||||
dat += "No scanner connected!"
|
||||
else
|
||||
if (src.scanner.occupant)
|
||||
dat += "<a href='byond://?src=\ref[src];scan=1'>Scan - [src.scanner.occupant]</a>"
|
||||
else
|
||||
dat += "Scanner unoccupied"
|
||||
|
||||
dat += "<br>Lock status: <a href='byond://?src=\ref[src];lock=1'>[src.scanner.locked ? "Locked" : "Unlocked"]</a>"
|
||||
|
||||
dat += "<h4>Database Functions</h4>"
|
||||
dat += "<a href='byond://?src=\ref[src];menu=2'>View Records</a><br>"
|
||||
if (src.diskette)
|
||||
dat += "<a href='byond://?src=\ref[src];disk=eject'>Eject Disk</a>"
|
||||
|
||||
|
||||
if(2)
|
||||
dat += "<h4>Current records</h4>"
|
||||
dat += "<a href='byond://?src=\ref[src];menu=1'>Back</a><br><br>"
|
||||
for(var/datum/data/record/R in src.records)
|
||||
dat += "<a href='byond://?src=\ref[src];view_rec=\ref[R]'>[R.fields["id"]]-[R.fields["name"]]</a><br>"
|
||||
|
||||
if(3)
|
||||
dat += "<h4>Selected Record</h4>"
|
||||
dat += "<a href='byond://?src=\ref[src];menu=2'>Back</a><br>"
|
||||
|
||||
if (!src.active_record)
|
||||
dat += "<font color=red>ERROR: Record not found.</font>"
|
||||
else
|
||||
dat += "<br><font size=1><a href='byond://?src=\ref[src];del_rec=1'>Delete Record</a></font><br>"
|
||||
dat += "<b>Name:</b> [src.active_record.fields["name"]]<br>"
|
||||
|
||||
var/obj/item/weapon/implant/health/H = locate(src.active_record.fields["imp"])
|
||||
|
||||
if ((H) && (istype(H)))
|
||||
dat += "<b>Health:</b> [H.sensehealth()] | OXY-BURN-TOX-BRUTE<br>"
|
||||
else
|
||||
dat += "<font color=red>Unable to locate implant.</font><br>"
|
||||
|
||||
if (!isnull(src.diskette))
|
||||
dat += "<a href='byond://?src=\ref[src];disk=load'>Load from disk.</a>"
|
||||
|
||||
dat += " | Save: <a href='byond://?src=\ref[src];save_disk=ue'>UI + UE</a>"
|
||||
dat += " | Save: <a href='byond://?src=\ref[src];save_disk=ui'>UI</a>"
|
||||
dat += " | Save: <a href='byond://?src=\ref[src];save_disk=se'>SE</a>"
|
||||
dat += "<br>"
|
||||
else
|
||||
dat += "<br>" //Keeping a line empty for appearances I guess.
|
||||
|
||||
dat += {"<b>UI:</b> [src.active_record.fields["UI"]]<br>
|
||||
<b>SE:</b> [src.active_record.fields["SE"]]<br><br>
|
||||
<a href='byond://?src=\ref[src];clone=\ref[src.active_record]'>Clone</a><br>"}
|
||||
|
||||
if(4)
|
||||
if (!src.active_record)
|
||||
src.menu = 2
|
||||
dat = "[src.temp]<br>"
|
||||
dat += "<h4>Confirm Record Deletion</h4>"
|
||||
|
||||
dat += "<b><a href='byond://?src=\ref[src];del_rec=1'>Scan card to confirm.</a></b><br>"
|
||||
dat += "<b><a href='byond://?src=\ref[src];menu=3'>No</a></b>"
|
||||
|
||||
|
||||
user << browse(dat, "window=cloning")
|
||||
onclose(user, "cloning")
|
||||
return
|
||||
|
||||
/obj/machinery/computer/cloning/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if ((href_list["scan"]) && (!isnull(src.scanner)))
|
||||
src.scan_mob(src.scanner.occupant)
|
||||
|
||||
//No locking an open scanner.
|
||||
else if ((href_list["lock"]) && (!isnull(src.scanner)))
|
||||
if ((!src.scanner.locked) && (src.scanner.occupant))
|
||||
src.scanner.locked = 1
|
||||
else
|
||||
src.scanner.locked = 0
|
||||
|
||||
else if (href_list["view_rec"])
|
||||
src.active_record = locate(href_list["view_rec"])
|
||||
if ((isnull(src.active_record.fields["ckey"])) || (src.active_record.fields["ckey"] == ""))
|
||||
del(src.active_record)
|
||||
src.temp = "ERROR: Record Corrupt"
|
||||
else
|
||||
src.menu = 3
|
||||
|
||||
else if (href_list["del_rec"])
|
||||
if ((!src.active_record) || (src.menu < 3))
|
||||
return
|
||||
if (src.menu == 3) //If we are viewing a record, confirm deletion
|
||||
src.temp = "Delete record?"
|
||||
src.menu = 4
|
||||
|
||||
else if (src.menu == 4)
|
||||
var/obj/item/weapon/card/id/C = usr.equipped()
|
||||
if (istype(C))
|
||||
if(src.check_access(C))
|
||||
src.records.Remove(src.active_record)
|
||||
del(src.active_record)
|
||||
src.temp = "Record deleted."
|
||||
src.menu = 2
|
||||
else
|
||||
src.temp = "Access Denied."
|
||||
|
||||
else if (href_list["disk"]) //Load or eject.
|
||||
switch(href_list["disk"])
|
||||
if("load")
|
||||
if ((isnull(src.diskette)) || (src.diskette.data == ""))
|
||||
src.temp = "Load error."
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
if (isnull(src.active_record))
|
||||
src.temp = "Record error."
|
||||
src.menu = 1
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
if (src.diskette.data_type == "ui")
|
||||
src.active_record.fields["UI"] = src.diskette.data
|
||||
if (src.diskette.ue)
|
||||
src.active_record.fields["name"] = src.diskette.owner
|
||||
else if (src.diskette.data_type == "se")
|
||||
src.active_record.fields["SE"] = src.diskette.data
|
||||
|
||||
src.temp = "Load successful."
|
||||
if("eject")
|
||||
if (!isnull(src.diskette))
|
||||
src.diskette.loc = src.loc
|
||||
src.diskette = null
|
||||
|
||||
else if (href_list["save_disk"]) //Save to disk!
|
||||
if ((isnull(src.diskette)) || (src.diskette.read_only) || (isnull(src.active_record)))
|
||||
src.temp = "Save error."
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
switch(href_list["save_disk"]) //Save as Ui/Ui+Ue/Se
|
||||
if("ui")
|
||||
src.diskette.data = src.active_record.fields["UI"]
|
||||
src.diskette.ue = 0
|
||||
src.diskette.data_type = "ui"
|
||||
if("ue")
|
||||
src.diskette.data = src.active_record.fields["UI"]
|
||||
src.diskette.ue = 1
|
||||
src.diskette.data_type = "ui"
|
||||
if("se")
|
||||
src.diskette.data = src.active_record.fields["SE"]
|
||||
src.diskette.ue = 0
|
||||
src.diskette.data_type = "se"
|
||||
src.diskette.owner = src.active_record.fields["name"]
|
||||
src.diskette.name = "data disk - '[src.diskette.owner]'"
|
||||
src.temp = "Save \[[href_list["save_disk"]]\] successful."
|
||||
|
||||
else if (href_list["refresh"])
|
||||
src.updateUsrDialog()
|
||||
|
||||
else if (href_list["clone"])
|
||||
var/datum/data/record/C = locate(href_list["clone"])
|
||||
//Look for that player! They better be dead!
|
||||
var/mob/selected = find_dead_player("[C.fields["ckey"]]")
|
||||
|
||||
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
|
||||
if ((!selected) || (!src.pod1) || (src.pod1.occupant) || (src.pod1.mess))
|
||||
src.temp = "Unable to initiate cloning cycle." // most helpful error message in THE HISTORY OF THE WORLD
|
||||
else if (src.pod1.growclone(selected, C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"]))
|
||||
src.temp = "Cloning cycle activated."
|
||||
src.records.Remove(C)
|
||||
del(C)
|
||||
src.menu = 1
|
||||
|
||||
else if (href_list["menu"])
|
||||
src.menu = text2num(href_list["menu"])
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/cloning/proc/scan_mob(mob/living/carbon/human/subject as mob)
|
||||
if ((isnull(subject)) || (!istype(subject, /mob/living/carbon/human)) || (!subject.dna))
|
||||
src.temp = "Error: Unable to locate valid genetic data."
|
||||
return
|
||||
if ((!subject.ckey) || (!subject.client))
|
||||
src.temp = "Error: Mental interface failure."
|
||||
return
|
||||
if (!isnull(find_record(subject.ckey)))
|
||||
src.temp = "Subject already in database."
|
||||
return
|
||||
|
||||
subject.dna.check_integrity()
|
||||
|
||||
var/datum/data/record/R = new /datum/data/record( )
|
||||
R.fields["ckey"] = subject.ckey
|
||||
R.fields["name"] = subject.real_name
|
||||
R.fields["id"] = copytext(md5(subject.real_name), 2, 6)
|
||||
R.fields["UI"] = subject.dna.uni_identity
|
||||
R.fields["SE"] = subject.dna.struc_enzymes
|
||||
|
||||
//Add an implant if needed
|
||||
var/obj/item/weapon/implant/health/imp =locate(/obj/item/weapon/implant/health, subject)
|
||||
if (isnull(imp))
|
||||
imp = new /obj/item/weapon/implant/health(subject)
|
||||
imp.implanted = subject
|
||||
R.fields["imp"] = "\ref[imp]"
|
||||
//Update it if needed
|
||||
else
|
||||
R.fields["imp"] = "\ref[imp]"
|
||||
|
||||
if (!isnull(subject.mind)) //Save that mind so traitors can continue traitoring after cloning.
|
||||
R.fields["mind"] = "\ref[subject.mind]"
|
||||
|
||||
src.records += R
|
||||
src.temp = "Subject successfully scanned."
|
||||
|
||||
//Find a specific record by key.
|
||||
/obj/machinery/computer/cloning/proc/find_record(var/find_key)
|
||||
var/selected_record = null
|
||||
for(var/datum/data/record/R in src.records)
|
||||
if (R.fields["ckey"] == find_key)
|
||||
selected_record = R
|
||||
break
|
||||
return selected_record
|
||||
|
||||
/obj/machinery/computer/cloning/power_change()
|
||||
|
||||
if(stat & BROKEN)
|
||||
icon_state = "commb"
|
||||
else
|
||||
if( powered() )
|
||||
icon_state = initial(icon_state)
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
spawn(rand(0, 15))
|
||||
src.icon_state = "c_unpowered"
|
||||
stat |= NOPOWER
|
||||
|
||||
|
||||
//Find a dead mob with a brain and client.
|
||||
/proc/find_dead_player(var/find_key)
|
||||
if (isnull(find_key))
|
||||
return
|
||||
|
||||
var/mob/selected = null
|
||||
for(var/mob/M in world)
|
||||
//Dead people only thanks!
|
||||
if ((M.stat != 2) || (!M.client))
|
||||
continue
|
||||
//They need a brain!
|
||||
if ((istype(M, /mob/living/carbon/human)) && (M:brain_op_stage >= 4.0))
|
||||
continue
|
||||
|
||||
if (M.ckey == find_key)
|
||||
selected = M
|
||||
break
|
||||
return selected
|
||||
|
||||
//Disk stuff.
|
||||
/obj/item/weapon/disk/data/New()
|
||||
..()
|
||||
var/diskcolor = pick(0,1,2)
|
||||
src.icon_state = "datadisk[diskcolor]"
|
||||
|
||||
/obj/item/weapon/disk/data/attack_self(mob/user as mob)
|
||||
src.read_only = !src.read_only
|
||||
user << "You flip the write-protect tab to [src.read_only ? "protected" : "unprotected"]."
|
||||
|
||||
/obj/item/weapon/disk/data/examine()
|
||||
set src in oview(5)
|
||||
..()
|
||||
usr << text("The write-protect tab is set to [src.read_only ? "protected" : "unprotected"].")
|
||||
return
|
||||
|
||||
//Health Tracker Implant
|
||||
|
||||
/obj/item/weapon/implant/health
|
||||
name = "health implant"
|
||||
var/healthstring = ""
|
||||
|
||||
/obj/item/weapon/implant/health/proc/sensehealth()
|
||||
if (!src.implanted)
|
||||
return "ERROR"
|
||||
else
|
||||
src.healthstring = "[round(src.implanted:oxyloss)] - [round(src.implanted:fireloss)] - [round(src.implanted:toxloss)] - [round(src.implanted:bruteloss)]"
|
||||
if (!src.healthstring)
|
||||
src.healthstring = "ERROR"
|
||||
return src.healthstring
|
||||
|
||||
/obj/machinery/clonepod/attack_ai(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
/obj/machinery/clonepod/attack_paw(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
/obj/machinery/clonepod/attack_hand(mob/user as mob)
|
||||
if ((isnull(src.occupant)) || (stat & NOPOWER))
|
||||
return
|
||||
if ((!isnull(src.occupant)) && (src.occupant.stat != 2))
|
||||
var/completion = (100 * ((src.occupant.health + 100) / (src.heal_level + 100)))
|
||||
user << "Current clone cycle is [round(completion)]% complete."
|
||||
return
|
||||
|
||||
//Clonepod
|
||||
|
||||
//Start growing a human clone in the pod!
|
||||
/obj/machinery/clonepod/proc/growclone(mob/ghost as mob, var/clonename, var/ui, var/se, var/mindref)
|
||||
if (((!ghost) || (!ghost.client)) || src.mess || src.attempting)
|
||||
return 0
|
||||
|
||||
src.attempting = 1 //One at a time!!
|
||||
src.locked = 1
|
||||
|
||||
src.eject_wait = 1
|
||||
spawn(30)
|
||||
src.eject_wait = 0
|
||||
|
||||
src.occupant = new /mob/living/carbon/human(src)
|
||||
ghost.client.mob = src.occupant
|
||||
|
||||
src.icon_state = "pod_1"
|
||||
//Get the clone body ready
|
||||
src.occupant.rejuv = 10
|
||||
src.occupant.bruteloss += 90
|
||||
src.occupant.toxloss += 50
|
||||
src.occupant.oxyloss += 40
|
||||
src.occupant.brainloss += 90
|
||||
src.occupant.paralysis += 4
|
||||
|
||||
//Here let's calculate their health so the pod doesn't immediately eject them!!!
|
||||
src.occupant.health = (src.occupant.bruteloss + src.occupant.toxloss + src.occupant.oxyloss)
|
||||
|
||||
src.occupant << "\blue <b>Clone generation process initiated.</b>"
|
||||
src.occupant << "\blue This will take a moment, please hold."
|
||||
|
||||
if (clonename)
|
||||
src.occupant.real_name = clonename
|
||||
else
|
||||
src.occupant.real_name = "clone" //No null names!!
|
||||
|
||||
var/datum/mind/clonemind = (locate(mindref) in ticker.minds)
|
||||
|
||||
if ((clonemind) && (istype(clonemind))) //Move that mind over!!
|
||||
clonemind.transfer_to(src.occupant)
|
||||
else //welp
|
||||
src.occupant.mind = new /datum/mind( )
|
||||
src.occupant.mind.key = src.occupant.key
|
||||
src.occupant.mind.current = src.occupant
|
||||
src.occupant.mind.transfer_to(src.occupant)
|
||||
ticker.minds += src.occupant.mind
|
||||
|
||||
// -- Mode/mind specific stuff goes here
|
||||
switch(ticker.mode.name)
|
||||
if ("revolution")
|
||||
if ((src.occupant.mind in ticker.mode:revolutionaries) || (src.occupant.mind in ticker.mode:head_revolutionaries))
|
||||
ticker.mode:add_revolutionary(src.occupant.mind)
|
||||
ticker.mode:update_all_rev_icons() //So the icon actually appears
|
||||
|
||||
// -- End mode specific stuff
|
||||
|
||||
if (istype(ghost, /mob/dead/observer))
|
||||
del(ghost) //Don't leave ghosts everywhere!!
|
||||
|
||||
if (!src.occupant.dna)
|
||||
src.occupant.dna = new /datum/dna( )
|
||||
if (ui)
|
||||
src.occupant.dna.uni_identity = ui
|
||||
updateappearance(src.occupant, ui)
|
||||
if (se)
|
||||
src.occupant.dna.struc_enzymes = se
|
||||
randmutb(src.occupant) //Sometimes the clones come out wrong.
|
||||
|
||||
src.attempting = 0
|
||||
return 1
|
||||
|
||||
//Grow clones to maturity then kick them out. FREELOADERS
|
||||
/obj/machinery/clonepod/process()
|
||||
|
||||
if (stat & NOPOWER) //Autoeject if power is lost
|
||||
if (src.occupant)
|
||||
src.locked = 0
|
||||
src.go_out()
|
||||
return
|
||||
|
||||
if ((src.occupant) && (src.occupant.loc == src))
|
||||
if((src.occupant.stat == 2) || (src.occupant.suiciding)) //Autoeject corpses and suiciding dudes.
|
||||
src.locked = 0
|
||||
src.go_out()
|
||||
src.connected_message("Clone Rejected: Deceased.")
|
||||
return
|
||||
|
||||
else if(src.occupant.health < src.heal_level)
|
||||
src.occupant.paralysis = 4
|
||||
|
||||
//Slowly get that clone healed and finished.
|
||||
src.occupant.bruteloss = max(src.occupant.bruteloss-1, 0)
|
||||
|
||||
//At this rate one clone takes about 95 seconds to produce.(with heal_level 90)
|
||||
src.occupant.toxloss = max(src.occupant.toxloss-0.5, 0)
|
||||
|
||||
//Premature clones may have brain damage.
|
||||
src.occupant.brainloss = max(src.occupant.brainloss-1, 0)
|
||||
|
||||
//So clones don't die of oxyloss in a running pod.
|
||||
if (src.occupant.reagents.get_reagent_amount("inaprovaline") < 30)
|
||||
src.occupant.reagents.add_reagent("inaprovaline", 60)
|
||||
|
||||
//Also heal some oxyloss ourselves because inaprovaline is so bad at preventing it!!
|
||||
src.occupant.oxyloss = max(src.occupant.oxyloss-2, 0)
|
||||
|
||||
//Stop baking in the tubes you jerks.
|
||||
src.occupant.fireloss = max(src.occupant.fireloss-2, 0)
|
||||
|
||||
use_power(7500) //This might need tweaking.
|
||||
return
|
||||
|
||||
else if((src.occupant.health >= src.heal_level) && (!src.eject_wait))
|
||||
src.connected_message("Cloning Process Complete.")
|
||||
src.locked = 0
|
||||
src.go_out()
|
||||
return
|
||||
|
||||
else if ((!src.occupant) || (src.occupant.loc != src))
|
||||
src.occupant = null
|
||||
if (src.locked)
|
||||
src.locked = 0
|
||||
if (!src.mess)
|
||||
icon_state = "pod_0"
|
||||
use_power(200)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
//Let's unlock this early I guess. Might be too early, needs tweaking.
|
||||
/obj/machinery/clonepod/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if (istype(W, /obj/item/weapon/card/id))
|
||||
if (!src.check_access(W))
|
||||
user << "\red Access Denied."
|
||||
return
|
||||
if ((!src.locked) || (isnull(src.occupant)))
|
||||
return
|
||||
if ((src.occupant.health < -20) && (src.occupant.stat != 2))
|
||||
user << "\red Access Refused."
|
||||
return
|
||||
else
|
||||
src.locked = 0
|
||||
user << "System unlocked."
|
||||
else if (istype(W, /obj/item/weapon/card/emag))
|
||||
if (isnull(src.occupant))
|
||||
return
|
||||
user << "You force an emergency ejection."
|
||||
src.locked = 0
|
||||
src.go_out()
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
//Put messages in the connected computer's temp var for display.
|
||||
/obj/machinery/clonepod/proc/connected_message(var/message)
|
||||
if ((isnull(src.connected)) || (!istype(src.connected, /obj/machinery/computer/cloning)))
|
||||
return 0
|
||||
if (!message)
|
||||
return 0
|
||||
|
||||
src.connected.temp = message
|
||||
src.connected.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
/obj/machinery/clonepod/verb/eject()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat != 0)
|
||||
return
|
||||
src.go_out()
|
||||
add_fingerprint(usr)
|
||||
return
|
||||
|
||||
/obj/machinery/clonepod/proc/go_out()
|
||||
if (src.locked)
|
||||
return
|
||||
|
||||
if (src.mess) //Clean that mess and dump those gibs!
|
||||
src.mess = 0
|
||||
gibs(src.loc)
|
||||
src.icon_state = "pod_0"
|
||||
for(var/obj/O in src)
|
||||
O.loc = src.loc
|
||||
return
|
||||
|
||||
if (!(src.occupant))
|
||||
return
|
||||
for(var/obj/O in src)
|
||||
O.loc = src.loc
|
||||
|
||||
if (src.occupant.client)
|
||||
src.occupant.client.eye = src.occupant.client.mob
|
||||
src.occupant.client.perspective = MOB_PERSPECTIVE
|
||||
src.occupant.loc = src.loc
|
||||
src.icon_state = "pod_0"
|
||||
src.eject_wait = 0 //If it's still set somehow.
|
||||
domutcheck(src.occupant) //Waiting until they're out before possible monkeyizing.
|
||||
src.occupant = null
|
||||
return
|
||||
|
||||
/obj/machinery/clonepod/proc/malfunction()
|
||||
if (src.occupant)
|
||||
src.connected_message("Critical Error!")
|
||||
src.mess = 1
|
||||
src.icon_state = "pod_g"
|
||||
src.occupant.ghostize()
|
||||
spawn(5)
|
||||
del(src.occupant)
|
||||
return
|
||||
|
||||
/obj/machinery/clonepod/relaymove(mob/user as mob)
|
||||
if (user.stat)
|
||||
return
|
||||
src.go_out()
|
||||
return
|
||||
|
||||
/obj/machinery/clonepod/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
for(var/atom/movable/A as mob|obj in src)
|
||||
A.loc = src.loc
|
||||
ex_act(severity)
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
for(var/atom/movable/A as mob|obj in src)
|
||||
A.loc = src.loc
|
||||
ex_act(severity)
|
||||
del(src)
|
||||
return
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
for(var/atom/movable/A as mob|obj in src)
|
||||
A.loc = src.loc
|
||||
ex_act(severity)
|
||||
del(src)
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
/*
|
||||
* Diskette Box
|
||||
*/
|
||||
/obj/item/weapon/storage/diskbox
|
||||
name = "Diskette Box"
|
||||
icon_state = "disk_kit"
|
||||
item_state = "syringe_kit"
|
||||
|
||||
/obj/item/weapon/storage/diskbox/New()
|
||||
..()
|
||||
new /obj/item/weapon/disk/data(src)
|
||||
new /obj/item/weapon/disk/data(src)
|
||||
new /obj/item/weapon/disk/data(src)
|
||||
new /obj/item/weapon/disk/data(src)
|
||||
new /obj/item/weapon/disk/data(src)
|
||||
new /obj/item/weapon/disk/data(src)
|
||||
new /obj/item/weapon/disk/data(src)
|
||||
|
||||
/*
|
||||
* Manual -- A big ol' manual.
|
||||
*/
|
||||
|
||||
/obj/item/weapon/paper/Cloning
|
||||
name = "paper - 'H-87 Cloning Apparatus Manual"
|
||||
info = {"<h4>Getting Started</h4>
|
||||
Congratulations, your station has purchased the H-87 industrial cloning device!<br>
|
||||
Using the H-87 is almost as simple as brain surgery! Simply insert the target humanoid into the scanning chamber and select the scan option to create a new profile!<br>
|
||||
<b>That's all there is to it!</b><br>
|
||||
<i>Notice, cloning system cannot scan inorganic life or small primates. Scan may fail if subject has suffered extreme brain damage.</i><br>
|
||||
<p>Clone profiles may be viewed through the profiles menu. Scanning implants a complementary HEALTH MONITOR IMPLANT into the subject, which may be viewed from each profile.
|
||||
Profile Deletion has been restricted to \[Station Head\] level access.</p>
|
||||
<h4>Cloning from a profile</h4>
|
||||
Cloning is as simple as pressing the CLONE option at the bottom of the desired profile.<br>
|
||||
Per your company's EMPLOYEE PRIVACY RIGHTS agreement, the H-87 has been blocked from cloning crewmembers while they are still alive.<br>
|
||||
<br>
|
||||
<p>The provided CLONEPOD SYSTEM will produce the desired clone. Standard clone maturation times (With SPEEDCLONE technology) are roughly 90 seconds.
|
||||
The cloning pod may be unlocked early with any \[Medical Researcher\] ID after initial maturation is complete.</p><br>
|
||||
<i>Please note that resulting clones may have a small DEVELOPMENTAL DEFECT as a result of genetic drift.</i><br>
|
||||
<h4>Profile Management</h4>
|
||||
<p>The H-87 (as well as your station's standard genetics machine) can accept STANDARD DATA DISKETTES.
|
||||
These diskettes are used to transfer genetic information between machines and profiles.
|
||||
A load/save dialog will become available in each profile if a disk is inserted.</p><br>
|
||||
<i>A good diskette is a great way to counter aforementioned genetic drift!</i><br>
|
||||
<br>
|
||||
<font size=1>This technology produced under license from Thinktronic Systems, LTD.</font>"}
|
||||
|
||||
//SOME SCRAPS I GUESS
|
||||
/* EMP grenade/spell effect
|
||||
if(istype(A, /obj/machinery/clonepod))
|
||||
A:malfunction()
|
||||
*/
|
||||
@@ -0,0 +1,60 @@
|
||||
/datum/computer/file/computer_program/airlock_control
|
||||
name = "Airlock Master"
|
||||
size = 16.0
|
||||
id_tag = "TAG"
|
||||
|
||||
|
||||
return_text()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/dat = "<a href='byond://?src=\ref[src];close=1'>Close</a> | "
|
||||
dat += "<a href='byond://?src=\ref[src];quit=1'>Quit</a>"
|
||||
|
||||
/*
|
||||
dat += "<br><TT>Frequency: "
|
||||
dat += "<a href='?src=\ref[src];adj_freq=-10'>--</a> "
|
||||
dat += "<a href='?src=\ref[src];adj_freq=-2'>-</a> "
|
||||
dat += "[format_frequency(src.master.frequency)] "
|
||||
dat += "<a href='?src=\ref[src];adj_freq=2'>+</a> "
|
||||
dat += "<a href='?src=\ref[src];adj_freq=10'>++</a>"
|
||||
dat += "</TT><br>"
|
||||
*/
|
||||
|
||||
|
||||
dat += "<br>ID:<a href='byond://?src=\ref[src];set_tag=1'>[src.id_tag]</a><br>"
|
||||
|
||||
dat += "<a href='byond://?src=\ref[src];send_command=cycle'>Cycle</a>"
|
||||
|
||||
|
||||
dat += "</b></center>"
|
||||
|
||||
return dat
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["set_tag"])
|
||||
var/t = input(usr, "Please enter new tag", src.id_tag, null) as text
|
||||
t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN)
|
||||
if (!t)
|
||||
return
|
||||
if (!in_range(src.master, usr))
|
||||
return
|
||||
|
||||
src.id_tag = t
|
||||
|
||||
// if(href_list["adj_freq"])
|
||||
// var/new_frequency = (src.master.frequency + text2num(href_list["adj_freq"]))
|
||||
// src.master.set_frequency(new_frequency)
|
||||
|
||||
if(href_list["send_command"])
|
||||
var/datum/signal/signal = new
|
||||
signal.data["tag"] = id_tag
|
||||
signal.data["command"] = href_list["send_command"]
|
||||
peripheral_command("send signal", signal)
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
@@ -0,0 +1,136 @@
|
||||
/datum/computer/file/computer_program/arcade
|
||||
name = "Arcade 500"
|
||||
size = 8.0
|
||||
var/enemy_name = "Space Villian"
|
||||
var/temp = "Winners Don't Use Spacedrugs" //Temporary message, for attack messages, etc
|
||||
var/player_hp = 30 //Player health/attack points
|
||||
var/player_mp = 10
|
||||
var/enemy_hp = 45 //Enemy health/attack points
|
||||
var/enemy_mp = 20
|
||||
var/gameover = 0
|
||||
var/blocked = 0 //Player cannot attack/heal while set
|
||||
|
||||
New(obj/holding as obj)
|
||||
if(holding)
|
||||
src.holder = holding
|
||||
|
||||
if(istype(src.holder.loc,/obj/machinery/computer2))
|
||||
src.master = src.holder.loc
|
||||
|
||||
// var/name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ")
|
||||
|
||||
var/name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Evil ", "the Dread King ", "the Space ", "Lord ")
|
||||
var/name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon")
|
||||
|
||||
src.enemy_name = dd_replacetext((name_part1 + name_part2), "the ", "")
|
||||
// src.name = (name_action + name_part1 + name_part2)
|
||||
|
||||
|
||||
|
||||
/datum/computer/file/computer_program/arcade/return_text()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/dat = "<a href='byond://?src=\ref[src];close=1'>Close</a> | "
|
||||
dat += "<a href='byond://?src=\ref[src];quit=1'>Quit</a>"
|
||||
|
||||
dat += "<center><h4>[src.enemy_name]</h4></center>"
|
||||
|
||||
dat += "<br><center><h3>[src.temp]</h3></center>"
|
||||
dat += "<br><center>Health: [src.player_hp] | Magic: [src.player_mp] | Enemy Health: [src.enemy_hp]</center>"
|
||||
|
||||
if (src.gameover)
|
||||
dat += "<center><b><a href='byond://?src=\ref[src];newgame=1'>New Game</a>"
|
||||
else
|
||||
dat += "<center><b><a href='byond://?src=\ref[src];attack=1'>Attack</a> | "
|
||||
dat += "<a href='byond://?src=\ref[src];heal=1'>Heal</a> | "
|
||||
dat += "<a href='byond://?src=\ref[src];charge=1'>Recharge Power</a>"
|
||||
|
||||
dat += "</b></center>"
|
||||
|
||||
return dat
|
||||
|
||||
/datum/computer/file/computer_program/arcade/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if (!src.blocked)
|
||||
if (href_list["attack"])
|
||||
src.blocked = 1
|
||||
var/attackamt = rand(2,6)
|
||||
src.temp = "You attack for [attackamt] damage!"
|
||||
src.master.updateUsrDialog()
|
||||
|
||||
sleep(10)
|
||||
src.enemy_hp -= attackamt
|
||||
src.arcade_action()
|
||||
|
||||
else if (href_list["heal"])
|
||||
src.blocked = 1
|
||||
var/pointamt = rand(1,3)
|
||||
var/healamt = rand(6,8)
|
||||
src.temp = "You use [pointamt] magic to heal for [healamt] damage!"
|
||||
src.master.updateUsrDialog()
|
||||
|
||||
sleep(10)
|
||||
src.player_mp -= pointamt
|
||||
src.player_hp += healamt
|
||||
src.blocked = 1
|
||||
src.master.updateUsrDialog()
|
||||
src.arcade_action()
|
||||
|
||||
else if (href_list["charge"])
|
||||
src.blocked = 1
|
||||
var/chargeamt = rand(4,7)
|
||||
src.temp = "You regain [chargeamt] points"
|
||||
src.player_mp += chargeamt
|
||||
|
||||
src.master.updateUsrDialog()
|
||||
sleep(10)
|
||||
src.arcade_action()
|
||||
|
||||
if (href_list["newgame"]) //Reset everything
|
||||
temp = "New Round"
|
||||
player_hp = 30
|
||||
player_mp = 10
|
||||
enemy_hp = 45
|
||||
enemy_mp = 20
|
||||
gameover = 0
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
|
||||
/datum/computer/file/computer_program/arcade/proc/arcade_action()
|
||||
if ((src.enemy_mp <= 0) || (src.enemy_hp <= 0))
|
||||
src.gameover = 1
|
||||
src.temp = "[src.enemy_name] has fallen! Rejoice!"
|
||||
src.peripheral_command("vend prize")
|
||||
|
||||
else if ((src.enemy_mp <= 5) && (prob(70)))
|
||||
var/stealamt = rand(2,3)
|
||||
src.temp = "[src.enemy_name] steals [stealamt] of your power!"
|
||||
src.player_mp -= stealamt
|
||||
src.master.updateUsrDialog()
|
||||
|
||||
if (src.player_mp <= 0)
|
||||
src.gameover = 1
|
||||
sleep(10)
|
||||
src.temp = "You have been drained! GAME OVER"
|
||||
|
||||
else if ((src.enemy_hp <= 10) && (src.enemy_mp > 4))
|
||||
src.temp = "[src.enemy_name] heals for 4 health!"
|
||||
src.enemy_hp += 4
|
||||
src.enemy_mp -= 4
|
||||
|
||||
else
|
||||
var/attackamt = rand(3,6)
|
||||
src.temp = "[src.enemy_name] attacks for [attackamt] damage!"
|
||||
src.player_hp -= attackamt
|
||||
|
||||
if ((src.player_mp <= 0) || (src.player_hp <= 0))
|
||||
src.gameover = 1
|
||||
src.temp = "You have been crushed! GAME OVER"
|
||||
|
||||
src.blocked = 0
|
||||
return
|
||||
@@ -0,0 +1,263 @@
|
||||
/datum/computer
|
||||
var/size = 4.0
|
||||
var/obj/item/weapon/disk/data/holder = null
|
||||
var/datum/computer/folder/holding_folder = null
|
||||
folder
|
||||
name = "Folder"
|
||||
size = 0.0
|
||||
var/gen = 0
|
||||
Del()
|
||||
for(var/datum/computer/F in src.contents)
|
||||
del(F)
|
||||
..()
|
||||
proc
|
||||
add_file(datum/computer/R)
|
||||
if(!holder || holder.read_only || !R)
|
||||
return 0
|
||||
if(istype(R,/datum/computer/folder) && (src.gen>=10))
|
||||
return 0
|
||||
if((holder.file_used + R.size) <= holder.file_amount)
|
||||
src.contents.Add(R)
|
||||
R.holder = holder
|
||||
R.holding_folder = src
|
||||
src.holder.file_used -= src.size
|
||||
src.size += R.size
|
||||
src.holder.file_used += src.size
|
||||
if(istype(R,/datum/computer/folder))
|
||||
R:gen = (src.gen+1)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
remove_file(datum/computer/R)
|
||||
if(holder && !holder.read_only || !R)
|
||||
// world << "Removing file [R]. File_used: [src.holder.file_used]"
|
||||
src.contents.Remove(R)
|
||||
src.holder.file_used -= src.size
|
||||
src.size -= R.size
|
||||
src.holder.file_used += src.size
|
||||
src.holder.file_used = max(src.holder.file_used, 0)
|
||||
// world << "Removed file [R]. File_used: [src.holder.file_used]"
|
||||
return 1
|
||||
return 0
|
||||
file
|
||||
name = "File"
|
||||
var/extension = "FILE" //Differentiate between types of files, why not
|
||||
proc
|
||||
copy_file_to_folder(datum/computer/folder/newfolder)
|
||||
if(!newfolder || (!istype(newfolder)) || (!newfolder.holder) || (newfolder.holder.read_only))
|
||||
return 0
|
||||
|
||||
if((newfolder.holder.file_used + src.size) <= newfolder.holder.file_amount)
|
||||
var/datum/computer/file/newfile = new src.type
|
||||
|
||||
for(var/V in src.vars)
|
||||
if (issaved(src.vars[V]) && V != "holder")
|
||||
newfile.vars[V] = src.vars[V]
|
||||
|
||||
if(!newfolder.add_file(newfile))
|
||||
del(newfile)
|
||||
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
Del()
|
||||
if(holder && holding_folder)
|
||||
holding_folder.remove_file(src)
|
||||
..()
|
||||
|
||||
|
||||
/datum/computer/file/computer_program
|
||||
name = "blank program"
|
||||
extension = "PROG"
|
||||
//var/size = 4.0
|
||||
//var/obj/item/weapon/disk/data/holder = null
|
||||
var/obj/machinery/computer2/master = null
|
||||
var/active_icon = null
|
||||
var/id_tag = null
|
||||
var/list/req_access = list()
|
||||
|
||||
New(obj/holding as obj)
|
||||
if(holding)
|
||||
src.holder = holding
|
||||
|
||||
if(istype(src.holder.loc,/obj/machinery/computer2))
|
||||
src.master = src.holder.loc
|
||||
|
||||
Del()
|
||||
if(master)
|
||||
master.processing_programs.Remove(src)
|
||||
..()
|
||||
|
||||
proc
|
||||
return_text()
|
||||
if((!src.holder) || (!src.master))
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(master.stat & (NOPOWER|BROKEN))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
//world << "Holder [holder] not in [master] of prg:[src]"
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
return 1
|
||||
|
||||
if(!src.holder.root)
|
||||
src.holder.root = new /datum/computer/folder
|
||||
src.holder.root.holder = src
|
||||
src.holder.root.name = "root"
|
||||
|
||||
return 0
|
||||
|
||||
process()
|
||||
if((!src.holder) || (!src.master))
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
master.processing_programs.Remove(src)
|
||||
return 1
|
||||
|
||||
if(!src.holder.root)
|
||||
src.holder.root = new /datum/computer/folder
|
||||
src.holder.root.holder = src
|
||||
src.holder.root.name = "root"
|
||||
|
||||
return 0
|
||||
|
||||
receive_command(obj/source, command, datum/signal/signal)
|
||||
if((!src.holder) || (!src.master) || (!source) || (source != src.master))
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(master.stat & (NOPOWER|BROKEN))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
peripheral_command(command, datum/signal/signal)
|
||||
if(master)
|
||||
master.send_command(command, signal)
|
||||
else
|
||||
del(signal)
|
||||
|
||||
transfer_holder(obj/item/weapon/disk/data/newholder,datum/computer/folder/newfolder)
|
||||
|
||||
if((newholder.file_used + src.size) > newholder.file_amount)
|
||||
return 0
|
||||
|
||||
if(!newholder.root)
|
||||
newholder.root = new /datum/computer/folder
|
||||
newholder.root.holder = newholder
|
||||
newholder.root.name = "root"
|
||||
|
||||
if(!newfolder)
|
||||
newfolder = newholder.root
|
||||
|
||||
if((src.holder && src.holder.read_only) || newholder.read_only)
|
||||
return 0
|
||||
|
||||
if((src.holder) && (src.holder.root))
|
||||
src.holder.root.remove_file(src)
|
||||
|
||||
newfolder.add_file(src)
|
||||
|
||||
if(istype(newholder.loc,/obj/machinery/computer2))
|
||||
src.master = newholder.loc
|
||||
|
||||
//world << "Setting [src.holder] to [newholder]"
|
||||
src.holder = newholder
|
||||
return 1
|
||||
|
||||
//Check access per program.
|
||||
allowed(mob/M)
|
||||
//check if it doesn't require any access at all
|
||||
if(src.check_access(null))
|
||||
return 1
|
||||
if(istype(M, /mob/living/silicon))
|
||||
//AI can do whatever he wants
|
||||
return 1
|
||||
else if(istype(M, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = M
|
||||
//if they are holding or wearing a card that has access, that works
|
||||
if(src.check_access(H.equipped()) || src.check_access(H.wear_id))
|
||||
return 1
|
||||
else if(istype(M, /mob/living/carbon/monkey))
|
||||
var/mob/living/carbon/monkey/george = M
|
||||
//they can only hold things :(
|
||||
if(george.equipped() && istype(george.equipped(), /obj/item/weapon/card/id) && src.check_access(george.equipped()))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
check_access(obj/item/weapon/card/id/I)
|
||||
if(!src.req_access) //no requirements
|
||||
return 1
|
||||
if(!istype(src.req_access, /list)) //something's very wrong
|
||||
return 1
|
||||
|
||||
var/list/L = src.req_access
|
||||
if(!L.len) //no requirements
|
||||
return 1
|
||||
if(!I || !istype(I, /obj/item/weapon/card/id) || !I.access) //not ID or no access
|
||||
return 0
|
||||
for(var/req in src.req_access)
|
||||
if(!(req in I.access)) //doesn't have this access
|
||||
return 0
|
||||
return 1
|
||||
|
||||
Topic(href, href_list)
|
||||
if((!src.holder) || (!src.master))
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(master.stat & (NOPOWER|BROKEN))
|
||||
return 1
|
||||
|
||||
if(src.master.active_program != src)
|
||||
return 1
|
||||
|
||||
if ((!usr.contents.Find(src.master) && (!in_range(src.master, usr) || !istype(src.master.loc, /turf))) && (!istype(usr, /mob/living/silicon)))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
return 1
|
||||
|
||||
usr.machine = src.master
|
||||
|
||||
if (href_list["close"])
|
||||
usr.machine = null
|
||||
usr << browse(null, "window=comp2")
|
||||
return 0
|
||||
|
||||
if (href_list["quit"])
|
||||
// src.master.processing_programs.Remove(src)
|
||||
if(src.master.host_program && src.master.host_program.holder && (src.master.host_program.holder in src.master.contents))
|
||||
src.master.run_program(src.master.host_program)
|
||||
src.master.updateUsrDialog()
|
||||
return 1
|
||||
else
|
||||
src.master.active_program = null
|
||||
src.master.updateUsrDialog()
|
||||
return 1
|
||||
|
||||
return 0
|
||||
@@ -0,0 +1,153 @@
|
||||
//Motherboard is just used in assembly/disassembly, doesn't exist in the actual computer object.
|
||||
/obj/item/weapon/motherboard
|
||||
name = "Computer mainboard"
|
||||
desc = "A computer motherboard."
|
||||
icon = 'module.dmi'
|
||||
icon_state = "mainboard"
|
||||
item_state = "electronic"
|
||||
w_class = 3
|
||||
var/created_name = null //If defined, result computer will have this name.
|
||||
|
||||
/obj/computer2frame
|
||||
density = 1
|
||||
anchored = 0
|
||||
name = "Computer-frame"
|
||||
icon = 'computer_frame.dmi'
|
||||
icon_state = "0"
|
||||
var/state = 0
|
||||
var/obj/item/weapon/motherboard/mainboard = null
|
||||
var/obj/item/weapon/disk/data/fixed_disk/hd = null
|
||||
var/list/peripherals = list()
|
||||
var/created_icon_state = "aiupload"
|
||||
|
||||
/obj/computer2frame/attackby(obj/item/weapon/P as obj, mob/user as mob)
|
||||
switch(state)
|
||||
if(0)
|
||||
if(istype(P, /obj/item/weapon/wrench))
|
||||
playsound(src.loc, 'Ratchet.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
user << "\blue You wrench the frame into place."
|
||||
src.anchored = 1
|
||||
src.state = 1
|
||||
if(istype(P, /obj/item/weapon/weldingtool))
|
||||
playsound(src.loc, 'Welder.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
user << "\blue You deconstruct the frame."
|
||||
var/obj/item/weapon/sheet/metal/A = new /obj/item/weapon/sheet/metal( src.loc )
|
||||
A.amount = 5
|
||||
del(src)
|
||||
if(1)
|
||||
if(istype(P, /obj/item/weapon/wrench))
|
||||
playsound(src.loc, 'Ratchet.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
user << "\blue You unfasten the frame."
|
||||
src.anchored = 0
|
||||
src.state = 0
|
||||
if(istype(P, /obj/item/weapon/motherboard) && !mainboard)
|
||||
playsound(src.loc, 'Deconstruct.ogg', 50, 1)
|
||||
user << "\blue You place the mainboard inside the frame."
|
||||
src.icon_state = "1"
|
||||
src.mainboard = P
|
||||
user.drop_item()
|
||||
P.loc = src
|
||||
if(istype(P, /obj/item/weapon/screwdriver) && mainboard)
|
||||
playsound(src.loc, 'Screwdriver.ogg', 50, 1)
|
||||
user << "\blue You screw the mainboard into place."
|
||||
src.state = 2
|
||||
src.icon_state = "2"
|
||||
if(istype(P, /obj/item/weapon/crowbar) && mainboard)
|
||||
playsound(src.loc, 'Crowbar.ogg', 50, 1)
|
||||
user << "\blue You remove the mainboard."
|
||||
src.state = 1
|
||||
src.icon_state = "0"
|
||||
mainboard.loc = src.loc
|
||||
src.mainboard = null
|
||||
if(2)
|
||||
if(istype(P, /obj/item/weapon/screwdriver) && mainboard && (!peripherals.len))
|
||||
playsound(src.loc, 'Screwdriver.ogg', 50, 1)
|
||||
user << "\blue You unfasten the mainboard."
|
||||
src.state = 1
|
||||
src.icon_state = "1"
|
||||
|
||||
if(istype(P, /obj/item/weapon/peripheral))
|
||||
if(src.peripherals.len < 3)
|
||||
user.drop_item()
|
||||
src.peripherals.Add(P)
|
||||
P.loc = src
|
||||
user << "\blue You add [P] to the frame."
|
||||
else
|
||||
user << "\red There is no more room for peripheral cards."
|
||||
|
||||
if(istype(P, /obj/item/weapon/crowbar) && src.peripherals.len)
|
||||
playsound(src.loc, 'Crowbar.ogg', 50, 1)
|
||||
user << "\blue You remove the peripheral boards."
|
||||
for(var/obj/item/weapon/peripheral/W in src.peripherals)
|
||||
W.loc = src.loc
|
||||
src.peripherals.Remove(W)
|
||||
|
||||
if(istype(P, /obj/item/weapon/cable_coil))
|
||||
if(P:amount >= 5)
|
||||
playsound(src.loc, 'Deconstruct.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
P:amount -= 5
|
||||
if(!P:amount) del(P)
|
||||
user << "\blue You add cables to the frame."
|
||||
src.state = 3
|
||||
src.icon_state = "3"
|
||||
if(3)
|
||||
if(istype(P, /obj/item/weapon/wirecutters))
|
||||
playsound(src.loc, 'wirecutter.ogg', 50, 1)
|
||||
user << "\blue You remove the cables."
|
||||
src.state = 2
|
||||
src.icon_state = "2"
|
||||
var/obj/item/weapon/cable_coil/A = new /obj/item/weapon/cable_coil( src.loc )
|
||||
A.amount = 5
|
||||
if(src.hd)
|
||||
src.hd.loc = src.loc
|
||||
src.hd = null
|
||||
|
||||
if(istype(P, /obj/item/weapon/disk/data/fixed_disk) && !src.hd)
|
||||
user.drop_item()
|
||||
src.hd = P
|
||||
P.loc = src
|
||||
user << "\blue You connect the drive to the cabling."
|
||||
|
||||
if(istype(P, /obj/item/weapon/crowbar) && src.hd)
|
||||
playsound(src.loc, 'Crowbar.ogg', 50, 1)
|
||||
user << "\blue You remove the hard drive."
|
||||
src.hd.loc = src.loc
|
||||
src.hd = null
|
||||
|
||||
if(istype(P, /obj/item/weapon/sheet/glass))
|
||||
if(P:amount >= 2)
|
||||
playsound(src.loc, 'Deconstruct.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
P:amount -= 2
|
||||
if(!P:amount) del(P)
|
||||
user << "\blue You put in the glass panel."
|
||||
src.state = 4
|
||||
src.icon_state = "4"
|
||||
if(4)
|
||||
if(istype(P, /obj/item/weapon/crowbar))
|
||||
playsound(src.loc, 'Crowbar.ogg', 50, 1)
|
||||
user << "\blue You remove the glass panel."
|
||||
src.state = 3
|
||||
src.icon_state = "3"
|
||||
var/obj/item/weapon/sheet/glass/A = new /obj/item/weapon/sheet/glass( src.loc )
|
||||
A.amount = 2
|
||||
if(istype(P, /obj/item/weapon/screwdriver))
|
||||
playsound(src.loc, 'Screwdriver.ogg', 50, 1)
|
||||
user << "\blue You connect the monitor."
|
||||
var/obj/machinery/computer2/C= new /obj/machinery/computer2( src.loc )
|
||||
C.setup_drive_size = 0
|
||||
C.icon_state = src.created_icon_state
|
||||
if(mainboard.created_name) C.name = mainboard.created_name
|
||||
del(mainboard)
|
||||
if(hd)
|
||||
C.hd = hd
|
||||
hd.loc = C
|
||||
for(var/obj/item/weapon/peripheral/W in src.peripherals)
|
||||
W.loc = C
|
||||
W.host = C
|
||||
C.peripherals.Add(W)
|
||||
del(src)
|
||||
@@ -0,0 +1,414 @@
|
||||
|
||||
/obj/machinery/computer2
|
||||
name = "computer"
|
||||
desc = "A computer workstation."
|
||||
icon = 'computer.dmi'
|
||||
icon_state = "aiupload"
|
||||
density = 1
|
||||
anchored = 1.0
|
||||
req_access = list() //This doesn't determine PROGRAM req access, just the access needed to install/delete programs.
|
||||
var/base_icon_state = "aiupload" //Assembly creates a new computer2 and not a child typepath, so initial doesn't work!!
|
||||
var/datum/radio_frequency/radio_connection
|
||||
var/obj/item/weapon/disk/data/fixed_disk/hd = null
|
||||
var/datum/computer/file/computer_program/active_program
|
||||
var/datum/computer/file/computer_program/host_program //active is set to this when the normal active quits, if available
|
||||
var/list/processing_programs = list()
|
||||
var/obj/item/weapon/card/id/authid = null //For records computers etc
|
||||
var/obj/item/weapon/card/id/auxid = null //For computers that need two ids for some reason.
|
||||
var/obj/item/weapon/disk/data/diskette = null
|
||||
var/list/peripherals = list()
|
||||
//Setup for Starting program & peripherals
|
||||
var/setup_starting_program = null //If set to a program path it will start with this one active.
|
||||
var/setup_starting_peripheral = null //Spawn with radio card and whatever path is here.
|
||||
var/setup_drive_size = 64.0 //How big is the drive (set to 0 for no drive)
|
||||
var/setup_id_tag
|
||||
var/setup_has_radio = 0 //Does it spawn with a radio peripheral?
|
||||
var/setup_radio_tag
|
||||
var/setup_frequency = 1411
|
||||
|
||||
/obj/item/weapon/disk/data
|
||||
var/datum/computer/folder/root = null
|
||||
var/file_amount = 32.0
|
||||
var/file_used = 0.0
|
||||
var/portable = 1
|
||||
var/title = "Data Disk"
|
||||
New()
|
||||
src.root = new /datum/computer/folder
|
||||
src.root.holder = src
|
||||
src.root.name = "root"
|
||||
|
||||
/obj/item/weapon/disk/data/fixed_disk
|
||||
name = "Storage Drive"
|
||||
icon_state = "harddisk"
|
||||
title = "Storage Drive"
|
||||
file_amount = 80.0
|
||||
portable = 0
|
||||
|
||||
attack_self(mob/user as mob)
|
||||
return
|
||||
|
||||
/obj/item/weapon/disk/data/computer2test
|
||||
name = "Programme Diskette"
|
||||
file_amount = 128.0
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/computer_program/arcade(src))
|
||||
src.root.add_file( new /datum/computer/file/computer_program/med_data(src))
|
||||
src.root.add_file( new /datum/computer/file/computer_program/airlock_control(src))
|
||||
src.root.add_file( new /datum/computer/file/computer_program/messenger(src))
|
||||
src.root.add_file( new /datum/computer/file/computer_program/progman(src))
|
||||
|
||||
/obj/machinery/computer2/medical
|
||||
name = "Medical computer"
|
||||
icon_state = "dna"
|
||||
setup_has_radio = 1
|
||||
setup_starting_program = /datum/computer/file/computer_program/med_data
|
||||
setup_starting_peripheral = /obj/item/weapon/peripheral/printer
|
||||
|
||||
/obj/machinery/computer2/arcade
|
||||
name = "arcade machine"
|
||||
icon_state = "arcade"
|
||||
desc = "An arcade machine."
|
||||
setup_drive_size = 16.0
|
||||
setup_starting_program = /datum/computer/file/computer_program/arcade
|
||||
setup_starting_peripheral = /obj/item/weapon/peripheral/prize_vendor
|
||||
|
||||
|
||||
/obj/machinery/computer2/New()
|
||||
..()
|
||||
|
||||
spawn(4)
|
||||
if(setup_has_radio)
|
||||
var/obj/item/weapon/peripheral/radio/radio = new /obj/item/weapon/peripheral/radio(src)
|
||||
radio.frequency = setup_frequency
|
||||
radio.code = setup_radio_tag
|
||||
|
||||
if(!hd && (setup_drive_size > 0))
|
||||
src.hd = new /obj/item/weapon/disk/data/fixed_disk(src)
|
||||
src.hd.file_amount = src.setup_drive_size
|
||||
|
||||
if(ispath(src.setup_starting_program))
|
||||
src.active_program = new src.setup_starting_program
|
||||
src.active_program.id_tag = setup_id_tag
|
||||
|
||||
src.hd.file_amount = max(src.hd.file_amount, src.active_program.size)
|
||||
|
||||
src.active_program.transfer_holder(src.hd)
|
||||
|
||||
if(ispath(src.setup_starting_peripheral))
|
||||
new src.setup_starting_peripheral(src)
|
||||
|
||||
src.base_icon_state = src.icon_state
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/computer2/attack_hand(mob/user as mob)
|
||||
if(..())
|
||||
return
|
||||
|
||||
user.machine = src
|
||||
|
||||
var/dat
|
||||
if((src.active_program) && (src.active_program.master == src) && (src.active_program.holder in src))
|
||||
dat = src.active_program.return_text()
|
||||
else
|
||||
dat = "<TT><b>Thinktronic BIOS V1.4</b><br><br>"
|
||||
|
||||
dat += "Current ID: <a href='?src=\ref[src];id=auth'>[src.authid ? "[src.authid.name]" : "----------"]</a><br>"
|
||||
dat += "Auxiliary ID: <a href='?src=\ref[src];id=aux'>[src.auxid ? "[src.auxid.name]" : "----------"]</a><br><br>"
|
||||
|
||||
var/progdat
|
||||
if((src.hd) && (src.hd.root))
|
||||
for(var/datum/computer/file/computer_program/P in src.hd.root.contents)
|
||||
progdat += "<tr><td>[P.name]</td><td>Size: [P.size]</td>"
|
||||
|
||||
progdat += "<td><a href='byond://?src=\ref[src];prog=\ref[P];function=run'>Run</a></td>"
|
||||
|
||||
if(P in src.processing_programs)
|
||||
progdat += "<td><a href='byond://?src=\ref[src];prog=\ref[P];function=unload'>Halt</a></td>"
|
||||
else
|
||||
progdat += "<td><a href='byond://?src=\ref[src];prog=\ref[P];function=load'>Load</a></td>"
|
||||
|
||||
progdat += "<td><a href='byond://?src=\ref[src];file=\ref[P];function=delete'>Del</a></td></tr>"
|
||||
|
||||
continue
|
||||
|
||||
dat += "Disk Space: \[[src.hd.file_used]/[src.hd.file_amount]\]<br>"
|
||||
dat += "<b>Programs on Fixed Disk:</b><br>"
|
||||
|
||||
if(!progdat)
|
||||
progdat = "No programs found.<br>"
|
||||
dat += "<center><table cellspacing=4>[progdat]</table></center>"
|
||||
|
||||
else
|
||||
|
||||
dat += "<b>Programs on Fixed Disk:</b><br>"
|
||||
dat += "<center>No fixed disk detected.</center><br>"
|
||||
|
||||
dat += "<br>"
|
||||
|
||||
progdat = null
|
||||
if((src.diskette) && (src.diskette.root))
|
||||
|
||||
dat += "<font size=1><a href='byond://?src=\ref[src];disk=1'>Eject</a></font><br>"
|
||||
|
||||
for(var/datum/computer/file/computer_program/P in src.diskette.root.contents)
|
||||
progdat += "<tr><td>[P.name]</td><td>Size: [P.size]</td>"
|
||||
progdat += "<td><a href='byond://?src=\ref[src];prog=\ref[P];function=run'>Run</a></td>"
|
||||
|
||||
if(P in src.processing_programs)
|
||||
progdat += "<td><a href='byond://?src=\ref[src];prog=\ref[P];function=unload'>Halt</a></td>"
|
||||
else
|
||||
progdat += "<td><a href='byond://?src=\ref[src];prog=\ref[P];function=load'>Load</a></td>"
|
||||
|
||||
progdat += "<td><a href='byond://?src=\ref[src];file=\ref[P];function=install'>Install</a></td></tr>"
|
||||
|
||||
continue
|
||||
|
||||
dat += "Disk Space: \[[src.diskette.file_used]/[src.diskette.file_amount]\]<br>"
|
||||
dat += "<b>Programs on Disk:</b><br>"
|
||||
|
||||
if(!progdat)
|
||||
progdat = "No data found.<br>"
|
||||
dat += "<center><table cellspacing=4>[progdat]</table></center>"
|
||||
|
||||
else
|
||||
|
||||
dat += "<b>Programs on Disk:</b><br>"
|
||||
dat += "<center>No diskette loaded.</center><br>"
|
||||
|
||||
dat += "</TT>"
|
||||
|
||||
user << browse(dat,"window=comp2")
|
||||
onclose(user,"comp2")
|
||||
return
|
||||
|
||||
/obj/machinery/computer2/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!src.active_program)
|
||||
if((href_list["prog"]) && (href_list["function"]))
|
||||
var/datum/computer/file/computer_program/newprog = locate(href_list["prog"])
|
||||
if(newprog && istype(newprog))
|
||||
switch(href_list["function"])
|
||||
if("run")
|
||||
src.run_program(newprog)
|
||||
if("load")
|
||||
src.load_program(newprog)
|
||||
if("unload")
|
||||
src.unload_program(newprog)
|
||||
if((href_list["file"]) && (href_list["function"]))
|
||||
var/datum/computer/file/newfile = locate(href_list["file"])
|
||||
if(!newfile)
|
||||
return
|
||||
switch(href_list["function"])
|
||||
if("install")
|
||||
if((src.hd) && (src.hd.root) && (src.allowed(usr)))
|
||||
newfile.copy_file_to_folder(src.hd.root)
|
||||
|
||||
if("delete")
|
||||
if(src.allowed(usr))
|
||||
src.delete_file(newfile)
|
||||
|
||||
//If there is already one loaded eject, or if not and they have one insert it.
|
||||
if (href_list["id"])
|
||||
switch(href_list["id"])
|
||||
if("auth")
|
||||
if(!isnull(src.authid))
|
||||
src.authid.loc = get_turf(src)
|
||||
src.authid = null
|
||||
else
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
src.authid = I
|
||||
if("aux")
|
||||
if(!isnull(src.auxid))
|
||||
src.auxid.loc = get_turf(src)
|
||||
src.auxid = null
|
||||
else
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
src.auxid = I
|
||||
|
||||
//Same but for a data disk
|
||||
else if (href_list["disk"])
|
||||
if(!isnull(src.diskette))
|
||||
src.diskette.loc = get_turf(src)
|
||||
src.diskette = null
|
||||
/* else
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/weapon/disk/data))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
src.diskette = I
|
||||
*/
|
||||
src.add_fingerprint(usr)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/computer2/process()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
use_power(250)
|
||||
|
||||
for(var/datum/computer/file/computer_program/P in src.processing_programs)
|
||||
P.process()
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/computer2/power_change()
|
||||
if(stat & BROKEN)
|
||||
icon_state = src.base_icon_state
|
||||
src.icon_state += "b"
|
||||
|
||||
else if(powered())
|
||||
icon_state = src.base_icon_state
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
spawn(rand(0, 15))
|
||||
icon_state = src.base_icon_state
|
||||
src.icon_state += "0"
|
||||
stat |= NOPOWER
|
||||
|
||||
|
||||
/obj/machinery/computer2/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if (istype(W, /obj/item/weapon/disk/data)) //INSERT SOME DISKETTES
|
||||
if ((!src.diskette) && W:portable)
|
||||
user.machine = src
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
src.diskette = W
|
||||
user << "You insert [W]."
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
else if (istype(W, /obj/item/weapon/screwdriver))
|
||||
playsound(src.loc, 'Screwdriver.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
var/obj/computer2frame/A = new /obj/computer2frame( src.loc )
|
||||
A.created_icon_state = src.base_icon_state
|
||||
if (src.stat & BROKEN)
|
||||
user << "\blue The broken glass falls out."
|
||||
new /obj/item/weapon/shard( src.loc )
|
||||
A.state = 3
|
||||
A.icon_state = "3"
|
||||
else
|
||||
user << "\blue You disconnect the monitor."
|
||||
A.state = 4
|
||||
A.icon_state = "4"
|
||||
|
||||
for (var/obj/item/weapon/peripheral/C in src.peripherals)
|
||||
C.loc = A
|
||||
A.peripherals.Add(C)
|
||||
|
||||
if(src.diskette)
|
||||
src.diskette.loc = src.loc
|
||||
|
||||
//TO-DO: move card reading to peripheral cards instead
|
||||
if(src.authid)
|
||||
src.authid.loc = src.loc
|
||||
|
||||
if(src.auxid)
|
||||
src.auxid.loc = src.loc
|
||||
|
||||
if(src.hd)
|
||||
src.hd.loc = A
|
||||
A.hd = src.hd
|
||||
|
||||
A.mainboard = new /obj/item/weapon/motherboard(A)
|
||||
A.mainboard.created_name = src.name
|
||||
|
||||
|
||||
A.anchored = 1
|
||||
del(src)
|
||||
|
||||
else
|
||||
src.attack_hand(user)
|
||||
return
|
||||
|
||||
/obj/machinery/computer2/proc/send_command(command, datum/signal/signal)
|
||||
for(var/obj/item/weapon/peripheral/P in src.peripherals)
|
||||
P.receive_command(src, command, signal)
|
||||
|
||||
del(signal)
|
||||
|
||||
/obj/machinery/computer2/proc/receive_command(obj/source, command, datum/signal/signal)
|
||||
if(source in src.contents)
|
||||
|
||||
for(var/datum/computer/file/computer_program/P in src.processing_programs)
|
||||
P.receive_command(src, command, signal)
|
||||
|
||||
del(signal)
|
||||
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/computer2/proc/run_program(datum/computer/file/computer_program/program,datum/computer/file/computer_program/host)
|
||||
if(!program)
|
||||
return 0
|
||||
|
||||
// src.unload_program(src.active_program)
|
||||
|
||||
if(src.load_program(program))
|
||||
if(host && istype(host))
|
||||
src.host_program = host
|
||||
else
|
||||
src.host_program = null
|
||||
|
||||
src.active_program = program
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/computer2/proc/load_program(datum/computer/file/computer_program/program)
|
||||
if((!program) || (!program.holder))
|
||||
return 0
|
||||
|
||||
if(!(program.holder in src))
|
||||
// world << "Not in src"
|
||||
program = new program.type
|
||||
program.transfer_holder(src.hd)
|
||||
|
||||
if(program.master != src)
|
||||
program.master = src
|
||||
|
||||
if(program in src.processing_programs)
|
||||
return 1
|
||||
else
|
||||
src.processing_programs.Add(program)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/computer2/proc/unload_program(datum/computer/file/computer_program/program)
|
||||
if((!program) || (!src.hd))
|
||||
return 0
|
||||
|
||||
if(program in src.processing_programs)
|
||||
src.processing_programs.Remove(program)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/computer2/proc/delete_file(datum/computer/file/file)
|
||||
//world << "Deleting [file]..."
|
||||
if((!file) || (!file.holder) || (file.holder.read_only))
|
||||
//world << "Cannot delete :("
|
||||
return 0
|
||||
|
||||
if(file in src.processing_programs)
|
||||
src.processing_programs.Remove(file)
|
||||
|
||||
if(src.active_program == file)
|
||||
src.active_program = null
|
||||
|
||||
// file.holder.root.remove_file(file)
|
||||
|
||||
//world << "Now calling del on [file]..."
|
||||
del(file)
|
||||
return 1
|
||||
@@ -0,0 +1,164 @@
|
||||
/datum/computer/file/computer_program/progman
|
||||
name = "ProgManager"
|
||||
size = 16.0
|
||||
var/datum/computer/folder/current_folder
|
||||
var/mode = 0
|
||||
var/datum/computer/file/clipboard
|
||||
|
||||
|
||||
return_text()
|
||||
if(..())
|
||||
return
|
||||
|
||||
if((!src.current_folder) || !(src.current_folder.holder in src.master))
|
||||
src.current_folder = src.holder.root
|
||||
|
||||
var/dat = "<a href='byond://?src=\ref[src];close=1'>Close</a> | "
|
||||
dat += "<a href='byond://?src=\ref[src];quit=1'>Quit</a>"
|
||||
|
||||
switch(mode)
|
||||
if(0)
|
||||
dat += " |<a href='byond://?src=\ref[src];create=folder'>Create Folder</a>"
|
||||
//dat += " | <a href='byond://?src=\ref[src];create=file'>Create File</a>"
|
||||
dat += " | <a href='byond://?src=\ref[src];file=\ref[src.current_folder];function=paste'>Paste</a>"
|
||||
dat += " | <a href='byond://?src=\ref[src];top_folder=1'>Root</a>"
|
||||
dat += " | <a href='byond://?src=\ref[src];mode=1'>Drive</a><br>"
|
||||
|
||||
dat += "<b>Contents of [current_folder] | Drive:\[[src.current_folder.holder.title]]</b><br>"
|
||||
dat += "<b>Used: \[[src.current_folder.holder.file_used]/[src.current_folder.holder.file_amount]\]</b><hr>"
|
||||
|
||||
dat += "<table cellspacing=5>"
|
||||
for(var/datum/computer/P in current_folder.contents)
|
||||
if(P == src)
|
||||
dat += "<tr><td>System</td><td>Size: [src.size]</td><td>SYSTEM</td></tr>"
|
||||
continue
|
||||
dat += "<tr><td><a href='byond://?src=\ref[src];file=\ref[P];function=open'>[P.name]</a></td>"
|
||||
dat += "<td>Size: [P.size]</td>"
|
||||
|
||||
dat += "<td>[(istype(P,/datum/computer/folder)) ? "FOLDER" : "[P:extension]"]</td>"
|
||||
|
||||
dat += "<td><a href='byond://?src=\ref[src];file=\ref[P];function=delete'>Del</a></td>"
|
||||
dat += "<td><a href='byond://?src=\ref[src];file=\ref[P];function=rename'>Rename</a></td>"
|
||||
|
||||
|
||||
if(istype(P,/datum/computer/file))
|
||||
dat += "<td><a href='byond://?src=\ref[src];file=\ref[P];function=copy'>Copy</a></td>"
|
||||
|
||||
dat += "</tr>"
|
||||
|
||||
dat += "</table>"
|
||||
|
||||
if(1)
|
||||
dat += " | <a href='byond://?src=\ref[src];mode=0'>Main</a>"
|
||||
dat += " | <a href='byond://?src=\ref[master];disk=1'>Eject</a><br>"
|
||||
|
||||
for(var/obj/item/weapon/disk/data/D in src.master)
|
||||
if(D == current_folder.holder)
|
||||
dat += "[D.name]<br>"
|
||||
else
|
||||
dat += "<a href='byond://?src=\ref[src];drive=\ref[D]'>[D.title]</a><br>"
|
||||
|
||||
|
||||
return dat
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["create"])
|
||||
if(current_folder)
|
||||
var/datum/computer/F = null
|
||||
switch(href_list["create"])
|
||||
if("folder")
|
||||
F = new /datum/computer/folder
|
||||
if(!current_folder.add_file(F))
|
||||
//world << "Couldn't add folder :("
|
||||
del(F)
|
||||
if("file")
|
||||
F = new /datum/computer/file
|
||||
if(!current_folder.add_file(F))
|
||||
//world << "Couldn't add file :("
|
||||
del(F)
|
||||
|
||||
if(href_list["file"] && href_list["function"])
|
||||
var/datum/computer/F = locate(href_list["file"])
|
||||
if(!F || !istype(F))
|
||||
return
|
||||
switch(href_list["function"])
|
||||
if("open")
|
||||
if(istype(F,/datum/computer/folder))
|
||||
src.current_folder = F
|
||||
else if(istype(F,/datum/computer/file/computer_program))
|
||||
src.master.run_program(F,src)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
|
||||
if("delete")
|
||||
src.master.delete_file(F)
|
||||
|
||||
if("copy")
|
||||
if(istype(F,/datum/computer/file) && (!F.holder || (F.holder in src.master.contents)))
|
||||
src.clipboard = F
|
||||
|
||||
if("paste")
|
||||
if(istype(F,/datum/computer/folder))
|
||||
if(!src.clipboard || !src.clipboard.holder || !(src.clipboard.holder in src.master.contents))
|
||||
return
|
||||
|
||||
if(!istype(src.clipboard))
|
||||
return
|
||||
|
||||
src.clipboard.copy_file_to_folder(F)
|
||||
|
||||
if("rename")
|
||||
spawn(0)
|
||||
var/t = input(usr, "Please enter new name", F.name, null) as text
|
||||
t = copytext(sanitize(t), 1, 16)
|
||||
if (!t)
|
||||
return
|
||||
if (!in_range(src.master, usr) || !(F.holder in src.master))
|
||||
return
|
||||
if(F.holder.read_only)
|
||||
return
|
||||
F.name = capitalize(lowertext(t))
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
if(href_list["open"])
|
||||
var/datum/computer/F = locate(href_list["open"])
|
||||
if(!F || !istype(F))
|
||||
return
|
||||
|
||||
if(istype(F,/datum/computer/folder))
|
||||
src.current_folder = F
|
||||
else if(istype(F,/datum/computer/file/computer_program))
|
||||
src.master.run_program(F)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
|
||||
if(href_list["delete"])
|
||||
var/datum/computer/F = locate(href_list["delete"])
|
||||
if(!F || !istype(F))
|
||||
return
|
||||
|
||||
src.master.delete_file(F)
|
||||
*/
|
||||
if(href_list["top_folder"])
|
||||
src.current_folder = src.current_folder.holder.root
|
||||
|
||||
if(href_list["mode"])
|
||||
var/newmode = text2num(href_list["mode"])
|
||||
newmode = max(newmode,0)
|
||||
src.mode = newmode
|
||||
|
||||
if(href_list["drive"])
|
||||
var/obj/item/weapon/disk/data/D = locate(href_list["drive"])
|
||||
if(D && istype(D) && D.root)
|
||||
current_folder = D.root
|
||||
src.mode = 0
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
@@ -0,0 +1,463 @@
|
||||
/datum/computer/file/computer_program/med_data
|
||||
name = "Medical Records"
|
||||
size = 32.0
|
||||
active_icon = "dna"
|
||||
req_access = list(access_medical)
|
||||
var/authenticated = null
|
||||
var/rank = null
|
||||
var/screen = null
|
||||
var/datum/data/record/active1 = null
|
||||
var/datum/data/record/active2 = null
|
||||
var/a_id = null
|
||||
var/temp = null
|
||||
|
||||
/datum/computer/file/computer_program/med_data/return_text()
|
||||
if(..())
|
||||
return
|
||||
var/dat
|
||||
if (src.temp)
|
||||
dat = text("<TT>[src.temp]</TT><BR><BR><A href='?src=\ref[src];temp=1'>Clear Screen</A>")
|
||||
else
|
||||
dat = text("Confirm Identity: <A href='?src=\ref[];id=auth'>[]</A><HR>", master, (src.master.authid ? text("[]", src.master.authid.name) : "----------"))
|
||||
if (src.authenticated)
|
||||
switch(src.screen)
|
||||
if(1.0)
|
||||
dat += {"
|
||||
<A href='?src=\ref[src];search=1'>Search Records</A>
|
||||
<BR><A href='?src=\ref[src];screen=2'>List Records</A>
|
||||
<BR>
|
||||
<BR><A href='?src=\ref[src];screen=5'>Virus Database</A>
|
||||
<BR><A href='?src=\ref[src];screen=6'>Medbot Tracking</A>
|
||||
<BR>
|
||||
<BR><A href='?src=\ref[src];screen=3'>Record Maintenance</A>
|
||||
<BR><A href='?src=\ref[src];logout=1'>{Log Out}</A><BR>
|
||||
"}
|
||||
if(2.0)
|
||||
dat += "<B>Record List</B>:<HR>"
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
dat += text("<A href='?src=\ref[];d_rec=\ref[]'>[]: []<BR>", src, R, R.fields["id"], R.fields["name"])
|
||||
//Foreach goto(132)
|
||||
dat += text("<HR><A href='?src=\ref[];screen=1'>Back</A>", src)
|
||||
if(3.0)
|
||||
dat += text("<B>Records Maintenance</B><HR>\n<A href='?src=\ref[];back=1'>Backup To Disk</A><BR>\n<A href='?src=\ref[];u_load=1'>Upload From disk</A><BR>\n<A href='?src=\ref[];del_all=1'>Delete All Records</A><BR>\n<BR>\n<A href='?src=\ref[];screen=1'>Back</A>", src, src, src, src)
|
||||
if(4.0)
|
||||
dat += "<CENTER><B>Medical Record</B></CENTER><BR>"
|
||||
if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
|
||||
dat += text("Name: [] ID: []<BR>\nSex: <A href='?src=\ref[];field=sex'>[]</A><BR>\nAge: <A href='?src=\ref[];field=age'>[]</A><BR>\nFingerprint: <A href='?src=\ref[];field=fingerprint'>[]</A><BR>\nPhysical Status: <A href='?src=\ref[];field=p_stat'>[]</A><BR>\nMental Status: <A href='?src=\ref[];field=m_stat'>[]</A><BR>", src.active1.fields["name"], src.active1.fields["id"], src, src.active1.fields["sex"], src, src.active1.fields["age"], src, src.active1.fields["fingerprint"], src, src.active1.fields["p_stat"], src, src.active1.fields["m_stat"])
|
||||
else
|
||||
dat += "<B>General Record Lost!</B><BR>"
|
||||
if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)))
|
||||
dat += text("<BR>\n<CENTER><B>Medical Data</B></CENTER><BR>\nBlood Type: <A href='?src=\ref[];field=b_type'>[]</A><BR>\n<BR>\nMinor Disabilities: <A href='?src=\ref[];field=mi_dis'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=mi_dis_d'>[]</A><BR>\n<BR>\nMajor Disabilities: <A href='?src=\ref[];field=ma_dis'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=ma_dis_d'>[]</A><BR>\n<BR>\nAllergies: <A href='?src=\ref[];field=alg'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=alg_d'>[]</A><BR>\n<BR>\nCurrent Diseases: <A href='?src=\ref[];field=cdi'>[]</A> (per disease info placed in log/comment section)<BR>\nDetails: <A href='?src=\ref[];field=cdi_d'>[]</A><BR>\n<BR>\nImportant Notes:<BR>\n\t<A href='?src=\ref[];field=notes'>[]</A><BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>", src, src.active2.fields["b_type"], src, src.active2.fields["mi_dis"], src, src.active2.fields["mi_dis_d"], src, src.active2.fields["ma_dis"], src, src.active2.fields["ma_dis_d"], src, src.active2.fields["alg"], src, src.active2.fields["alg_d"], src, src.active2.fields["cdi"], src, src.active2.fields["cdi_d"], src, src.active2.fields["notes"])
|
||||
var/counter = 1
|
||||
while(src.active2.fields[text("com_[]", counter)])
|
||||
dat += text("[]<BR><A href='?src=\ref[];del_c=[]'>Delete Entry</A><BR><BR>", src.active2.fields[text("com_[]", counter)], src, counter)
|
||||
counter++
|
||||
dat += text("<A href='?src=\ref[];add_c=1'>Add Entry</A><BR><BR>", src)
|
||||
dat += text("<A href='?src=\ref[];del_r=1'>Delete Record (Medical Only)</A><BR><BR>", src)
|
||||
else
|
||||
dat += "<B>Medical Record Lost!</B><BR>"
|
||||
dat += text("<A href='?src=\ref[src];new=1'>New Record</A><BR><BR>")
|
||||
dat += text("\n<A href='?src=\ref[];print_p=1'>Print Record</A><BR>\n<A href='?src=\ref[];screen=2'>Back</A><BR>", src, src)
|
||||
if(5.0)
|
||||
dat += {"<CENTER><B>Virus Database</B></CENTER>
|
||||
<br><a href='?src=\ref[src];vir=gbs'>GBS</a>
|
||||
<br><a href='?src=\ref[src];vir=cc'>Common Cold</a>
|
||||
<br><a href='?src=\ref[src];vir=f'>Flu</A>
|
||||
<br><a href='?src=\ref[src];vir=jf'>Jungle Fever</a>
|
||||
<br><a href='?src=\ref[src];vir=ca'>Clowning Around</a>
|
||||
<br><a href='?src=\ref[src];vir=p'>Plasmatoid</a>
|
||||
<br><a href='?src=\ref[src];vir=dna'>Space Rhinovirus</a>
|
||||
<br><a href='?src=\ref[src];vir=bot'>Robot Transformation</a>
|
||||
<br><a href='?src=\ref[src];screen=1'>Back</a>"}
|
||||
if(6.0)
|
||||
dat += "<center><b>Medical Robot Monitor</b></center>"
|
||||
dat += "<a href='?src=\ref[src];screen=1'>Back</a>"
|
||||
dat += "<br><b>Medical Robots:</b>"
|
||||
var/bdat = null
|
||||
for(var/obj/machinery/bot/medbot/M in world)
|
||||
var/turf/bl = get_turf(M)
|
||||
bdat += "[M.name] - <b>\[[bl.x],[bl.y]\]</b> - [M.on ? "Online" : "Offline"]<br>"
|
||||
if(!isnull(M.reagent_glass))
|
||||
bdat += "Reservoir: \[[M.reagent_glass.reagents.total_volume]/[M.reagent_glass.reagents.maximum_volume]\]"
|
||||
else
|
||||
bdat += "Using Internal Synthesizer."
|
||||
|
||||
if(!bdat)
|
||||
dat += "<br><center>None detected</center>"
|
||||
else
|
||||
dat += "[bdat]"
|
||||
|
||||
else
|
||||
else
|
||||
dat += text("<A href='?src=\ref[];login=1'>{Log In}</A>", src)
|
||||
dat += "<br><a href='byond://?src=\ref[src];quit=1'>{Quit}</a>"
|
||||
|
||||
return dat
|
||||
|
||||
/datum/computer/file/computer_program/med_data/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if (!( data_core.general.Find(src.active1) ))
|
||||
src.active1 = null
|
||||
if (!( data_core.medical.Find(src.active2) ))
|
||||
src.active2 = null
|
||||
if (href_list["temp"])
|
||||
src.temp = null
|
||||
else if (href_list["logout"])
|
||||
src.authenticated = null
|
||||
src.screen = null
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
else if (href_list["login"])
|
||||
if (istype(usr, /mob/living/silicon))
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
src.authenticated = 1
|
||||
src.rank = "AI"
|
||||
src.screen = 1
|
||||
else if (istype(src.master.authid, /obj/item/weapon/card/id))
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
if (src.check_access(src.master.authid))
|
||||
src.authenticated = src.master.authid.registered
|
||||
src.rank = src.master.authid.assignment
|
||||
src.screen = 1
|
||||
if (src.authenticated)
|
||||
|
||||
if(href_list["screen"])
|
||||
src.screen = text2num(href_list["screen"])
|
||||
if(src.screen < 1)
|
||||
src.screen = 1
|
||||
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
|
||||
if(href_list["vir"])
|
||||
switch(href_list["vir"])
|
||||
if("gbs")
|
||||
src.temp = {"<b>Name:</b> GBS
|
||||
<BR><b>Number of stages:</b> 5
|
||||
<BR><b>Spread:</b> Airborne Transmission
|
||||
<BR><b>Possible Cure:</b> Spaceacillin
|
||||
<BR><b>Affected Species:</b> Human
|
||||
<BR>
|
||||
<BR><b>Notes:</b> If left untreated death will occur.
|
||||
<BR>
|
||||
<BR><b>Severity:</b> Major"}
|
||||
if("cc")
|
||||
src.temp = {"<b>Name:</b> Common Cold
|
||||
<BR><b>Number of stages:</b> 3
|
||||
<BR><b>Spread:</b> Airborne Transmission
|
||||
<BR><b>Possible Cure:</b> Rest
|
||||
<BR><b>Affected Species:</b> Human
|
||||
<BR>
|
||||
<BR><b>Notes:</b> If left untreated the subject will contract the flu.
|
||||
<BR>
|
||||
<BR><b>Severity:</b> Minor"}
|
||||
if("f")
|
||||
src.temp = {"<b>Name:</b> The Flu
|
||||
<BR><b>Number of stages:</b> 3
|
||||
<BR><b>Spread:</b> Airborne Transmission
|
||||
<BR><b>Possible Cure:</b> Rest
|
||||
<BR><b>Affected Species:</b> Human
|
||||
<BR>
|
||||
<BR><b>Notes:</b> If left untreated the subject will feel quite unwell.
|
||||
<BR>
|
||||
<BR><b>Severity:</b> Medium"}
|
||||
if("jf")
|
||||
src.temp = {"<b>Name:</b> Jungle Fever
|
||||
<BR><b>Number of stages:</b> 1
|
||||
<BR><b>Spread:</b> Airborne Transmission
|
||||
<BR><b>Possible Cure:</b> None
|
||||
<BR><b>Affected Species:</b> Monkey
|
||||
<BR>
|
||||
<BR><b>Notes:</b> Monkies with this disease will bite humans, causing humans to spontaneously to mutate into a monkey.
|
||||
<BR>
|
||||
<BR><b>Severity:</b> Medium"}
|
||||
if("ca")
|
||||
src.temp = {"<b>Name:</b> Clowning Around
|
||||
<BR><b>Number of stages:</b> 4
|
||||
<BR><b>Spread:</b> Airborne Transmission
|
||||
<BR><b>Possible Cure:</b> Spaceacillin
|
||||
<BR><b>Affected Species:</b> Human
|
||||
<BR>
|
||||
<BR><b>Notes:</b> Subjects are affected by rampant honking and a fondness for shenanigans. They may also spontaneously phase through closed airlocks.
|
||||
<BR>
|
||||
<BR><b>Severity:</b> Laughable"}
|
||||
if("p")
|
||||
src.temp = {"<b>Name:</b> Plasmatoid
|
||||
<BR><b>Number of stages:</b> 3
|
||||
<BR><b>Spread:</b> Airborne Transmission
|
||||
<BR><b>Possible Cure:</b> Inaprovaline
|
||||
<BR><b>Affected Species:</b> Human and Monkey
|
||||
<BR>
|
||||
<BR><b>Notes:</b> With this disease the victim will need plasma to breathe.
|
||||
<BR>
|
||||
<BR><b>Severity:</b> Major"}
|
||||
if("dna")
|
||||
src.temp = {"<b>Name:</b> Space Rhinovirus
|
||||
<BR><b>Number of stages:</b> 4
|
||||
<BR><b>Spread:</b> Airborne Transmission
|
||||
<BR><b>Possible Cure:</b> Spaceacillin
|
||||
<BR><b>Affected Species:</b> Human
|
||||
<BR>
|
||||
<BR><b>Notes:</b> This disease transplants the genetic code of the intial vector into new hosts.
|
||||
<BR>
|
||||
<BR><b>Severity:</b> Medium"}
|
||||
if("bot")
|
||||
src.temp = {"<b>Name:</b> Robot Transformation
|
||||
<BR><b>Number of stages:</b> 5
|
||||
<BR><b>Spread:</b> Infected food
|
||||
<BR><b>Possible Cure:</b> None
|
||||
<BR><b>Affected Species:</b> Human
|
||||
<BR>
|
||||
<BR><b>Notes:</b> This disease, actually acute nanomachine infection, converts the victim into a cyborg.
|
||||
<BR>
|
||||
<BR><b>Severity:</b> Major"}
|
||||
|
||||
if (href_list["del_all"])
|
||||
src.temp = text("Are you sure you wish to delete all records?<br>\n\t<A href='?src=\ref[];temp=1;del_all2=1'>Yes</A><br>\n\t<A href='?src=\ref[];temp=1'>No</A><br>", src, src)
|
||||
|
||||
if (href_list["del_all2"])
|
||||
for(var/datum/data/record/R in data_core.medical)
|
||||
del(R)
|
||||
src.temp = "All records deleted."
|
||||
|
||||
if (href_list["field"])
|
||||
var/a1 = src.active1
|
||||
var/a2 = src.active2
|
||||
switch(href_list["field"])
|
||||
if("fingerprint")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
var/t1 = input("Please input fingerprint hash:", "Med. records", src.active1.fields["id"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1))
|
||||
return
|
||||
src.active1.fields["fingerprint"] = t1
|
||||
if("sex")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
if (src.active1.fields["sex"] == "Male")
|
||||
src.active1.fields["sex"] = "Female"
|
||||
else
|
||||
src.active1.fields["sex"] = "Male"
|
||||
if("age")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
var/t1 = input("Please input age:", "Med. records", src.active1.fields["age"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active1 != a1))
|
||||
return
|
||||
src.active1.fields["age"] = t1
|
||||
if("mi_dis")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please input minor disabilities list:", "Med. records", src.active2.fields["mi_dis"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["mi_dis"] = t1
|
||||
if("mi_dis_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["mi_dis_d"] = t1
|
||||
if("ma_dis")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please input major diabilities list:", "Med. records", src.active2.fields["ma_dis"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["ma_dis"] = t1
|
||||
if("ma_dis_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["ma_dis_d"] = t1
|
||||
if("alg")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please state allergies:", "Med. records", src.active2.fields["alg"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["alg"] = t1
|
||||
if("alg_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["alg_d"] = t1
|
||||
if("cdi")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please state diseases:", "Med. records", src.active2.fields["cdi"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["cdi"] = t1
|
||||
if("cdi_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["cdi_d"] = t1
|
||||
if("notes")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize notes:", "Med. records", src.active2.fields["notes"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || (!src.master) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["notes"] = t1
|
||||
if("p_stat")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
src.temp = text("<B>Physical Condition:</B><BR>\n\t<A href='?src=\ref[];temp=1;p_stat=deceased'>*Deceased*</A><BR>\n\t<A href='?src=\ref[];temp=1;p_stat=unconscious'>*Unconscious*</A><BR>\n\t<A href='?src=\ref[];temp=1;p_stat=active'>Active</A><BR>\n\t<A href='?src=\ref[];temp=1;p_stat=unfit'>Physically Unfit</A><BR>", src, src, src, src)
|
||||
if("m_stat")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
src.temp = text("<B>Mental Condition:</B><BR>\n\t<A href='?src=\ref[];temp=1;m_stat=insane'>*Insane*</A><BR>\n\t<A href='?src=\ref[];temp=1;m_stat=unstable'>*Unstable*</A><BR>\n\t<A href='?src=\ref[];temp=1;m_stat=watch'>*Watch*</A><BR>\n\t<A href='?src=\ref[];temp=1;m_stat=stable'>Stable</A><BR>", src, src, src, src)
|
||||
if("b_type")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
src.temp = text("<B>Blood Type:</B><BR>\n\t<A href='?src=\ref[];temp=1;b_type=an'>A-</A> <A href='?src=\ref[];temp=1;b_type=ap'>A+</A><BR>\n\t<A href='?src=\ref[];temp=1;b_type=bn'>B-</A> <A href='?src=\ref[];temp=1;b_type=bp'>B+</A><BR>\n\t<A href='?src=\ref[];temp=1;b_type=abn'>AB-</A> <A href='?src=\ref[];temp=1;b_type=abp'>AB+</A><BR>\n\t<A href='?src=\ref[];temp=1;b_type=on'>O-</A> <A href='?src=\ref[];temp=1;b_type=op'>O+</A><BR>", src, src, src, src, src, src, src, src)
|
||||
else
|
||||
|
||||
if (href_list["p_stat"])
|
||||
if (src.active1)
|
||||
switch(href_list["p_stat"])
|
||||
if("deceased")
|
||||
src.active1.fields["p_stat"] = "*Deceased*"
|
||||
if("unconscious")
|
||||
src.active1.fields["p_stat"] = "*Unconscious*"
|
||||
if("active")
|
||||
src.active1.fields["p_stat"] = "Active"
|
||||
if("unfit")
|
||||
src.active1.fields["p_stat"] = "Physically Unfit"
|
||||
|
||||
if (href_list["m_stat"])
|
||||
if (src.active1)
|
||||
switch(href_list["m_stat"])
|
||||
if("insane")
|
||||
src.active1.fields["m_stat"] = "*Insane*"
|
||||
if("unstable")
|
||||
src.active1.fields["m_stat"] = "*Unstable*"
|
||||
if("watch")
|
||||
src.active1.fields["m_stat"] = "*Watch*"
|
||||
if("stable")
|
||||
src.active2.fields["m_stat"] = "Stable"
|
||||
|
||||
|
||||
if (href_list["b_type"])
|
||||
if (src.active2)
|
||||
switch(href_list["b_type"])
|
||||
if("an")
|
||||
src.active2.fields["b_type"] = "A-"
|
||||
if("bn")
|
||||
src.active2.fields["b_type"] = "B-"
|
||||
if("abn")
|
||||
src.active2.fields["b_type"] = "AB-"
|
||||
if("on")
|
||||
src.active2.fields["b_type"] = "O-"
|
||||
if("ap")
|
||||
src.active2.fields["b_type"] = "A+"
|
||||
if("bp")
|
||||
src.active2.fields["b_type"] = "B+"
|
||||
if("abp")
|
||||
src.active2.fields["b_type"] = "AB+"
|
||||
if("op")
|
||||
src.active2.fields["b_type"] = "O+"
|
||||
|
||||
|
||||
if (href_list["del_r"])
|
||||
if (src.active2)
|
||||
src.temp = "Are you sure you wish to delete the record (Medical Portion Only)?<br>\n\t<A href='?src=\ref[src];temp=1;del_r2=1'>Yes</A><br>\n\t<A href='?src=\ref[src];temp=1'>No</A><br>"
|
||||
|
||||
if (href_list["del_r2"])
|
||||
if (src.active2)
|
||||
del(src.active2)
|
||||
|
||||
if (href_list["d_rec"])
|
||||
var/datum/data/record/R = locate(href_list["d_rec"])
|
||||
var/datum/data/record/M = locate(href_list["d_rec"])
|
||||
if (!( data_core.general.Find(R) ))
|
||||
src.temp = "Record Not Found!"
|
||||
return
|
||||
for(var/datum/data/record/E in data_core.medical)
|
||||
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
|
||||
M = E
|
||||
else
|
||||
//Foreach continue //goto(2540)
|
||||
src.active1 = R
|
||||
src.active2 = M
|
||||
src.screen = 4
|
||||
|
||||
if (href_list["new"])
|
||||
if ((istype(src.active1, /datum/data/record) && !( istype(src.active2, /datum/data/record) )))
|
||||
var/datum/data/record/R = new /datum/data/record( )
|
||||
R.fields["name"] = src.active1.fields["name"]
|
||||
R.fields["id"] = src.active1.fields["id"]
|
||||
R.name = text("Medical Record #[]", R.fields["id"])
|
||||
R.fields["b_type"] = "Unknown"
|
||||
R.fields["mi_dis"] = "None"
|
||||
R.fields["mi_dis_d"] = "No minor disabilities have been declared."
|
||||
R.fields["ma_dis"] = "None"
|
||||
R.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
|
||||
R.fields["alg"] = "None"
|
||||
R.fields["alg_d"] = "No allergies have been detected in this patient."
|
||||
R.fields["cdi"] = "None"
|
||||
R.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
|
||||
R.fields["notes"] = "No notes."
|
||||
data_core.medical += R
|
||||
src.active2 = R
|
||||
src.screen = 4
|
||||
|
||||
if (href_list["add_c"])
|
||||
if (!( istype(src.active2, /datum/data/record) ))
|
||||
return
|
||||
var/a2 = src.active2
|
||||
var/t1 = input("Add Comment:", "Med. records", null, null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!in_range(src.master, usr) && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
var/counter = 1
|
||||
while(src.active2.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
src.active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], 2053<BR>[]", src.authenticated, src.rank, time2text(world.realtime, "DDD MMM DD hh:mm:ss"), t1)
|
||||
|
||||
if (href_list["del_c"])
|
||||
if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])]))
|
||||
src.active2.fields[text("com_[]", href_list["del_c"])] = "<B>Deleted</B>"
|
||||
|
||||
if (href_list["search"])
|
||||
var/t1 = input("Search String: (Name or ID)", "Med. records", null, null) as text
|
||||
if ((!( t1 ) || usr.stat || (!src.master) || !( src.authenticated ) || usr.restrained() || ((!in_range(src.master, usr)) && (!istype(usr, /mob/living/silicon)))))
|
||||
return
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
t1 = lowertext(t1)
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
if ((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"])))
|
||||
src.active1 = R
|
||||
else
|
||||
|
||||
if (!( src.active1 ))
|
||||
src.temp = text("Could not locate record [].", t1)
|
||||
else
|
||||
for(var/datum/data/record/E in data_core.medical)
|
||||
if ((E.fields["name"] == src.active1.fields["name"] || E.fields["id"] == src.active1.fields["id"]))
|
||||
src.active2 = E
|
||||
else
|
||||
|
||||
src.screen = 4
|
||||
|
||||
if (href_list["print_p"])
|
||||
var/info = "<CENTER><B>Medical Record</B></CENTER><BR>"
|
||||
if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
|
||||
info += text("Name: [] ID: []<BR>\nSex: []<BR>\nAge: []<BR>\nFingerprint: []<BR>\nPhysical Status: []<BR>\nMental Status: []<BR>", src.active1.fields["name"], src.active1.fields["id"], src.active1.fields["sex"], src.active1.fields["age"], src.active1.fields["fingerprint"], src.active1.fields["p_stat"], src.active1.fields["m_stat"])
|
||||
else
|
||||
info += "<B>General Record Lost!</B><BR>"
|
||||
if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)))
|
||||
info += text("<BR>\n<CENTER><B>Medical Data</B></CENTER><BR>\nBlood Type: []<BR>\n<BR>\nMinor Disabilities: []<BR>\nDetails: []<BR>\n<BR>\nMajor Disabilities: []<BR>\nDetails: []<BR>\n<BR>\nAllergies: []<BR>\nDetails: []<BR>\n<BR>\nCurrent Diseases: [] (per disease info placed in log/comment section)<BR>\nDetails: []<BR>\n<BR>\nImportant Notes:<BR>\n\t[]<BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>", src.active2.fields["b_type"], src.active2.fields["mi_dis"], src.active2.fields["mi_dis_d"], src.active2.fields["ma_dis"], src.active2.fields["ma_dis_d"], src.active2.fields["alg"], src.active2.fields["alg_d"], src.active2.fields["cdi"], src.active2.fields["cdi_d"], src.active2.fields["notes"])
|
||||
var/counter = 1
|
||||
while(src.active2.fields[text("com_[]", counter)])
|
||||
info += text("[]<BR>", src.active2.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
else
|
||||
info += "<B>Medical Record Lost!</B><BR>"
|
||||
info += "</TT>"
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.data["data"] = info
|
||||
signal.data["title"] = "Medical Record"
|
||||
src.peripheral_command("print",signal)
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
@@ -0,0 +1,96 @@
|
||||
/datum/computer/file/computer_program/messenger
|
||||
name = "Messenger"
|
||||
size = 8.0
|
||||
var/messages = null
|
||||
var/screen_name = "User"
|
||||
|
||||
//To-do: take screen_name from inserted id card??
|
||||
//Saving log to file datum
|
||||
|
||||
return_text()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/dat = "<a href='byond://?src=\ref[src];close=1'>Close</a> | "
|
||||
dat += "<a href='byond://?src=\ref[src];quit=1'>Quit</a><br>"
|
||||
|
||||
dat += "<b>SpaceMessenger V4.1.2</b><br>"
|
||||
|
||||
dat += "<a href='byond://?src=\ref[src];send_msg=1'>Send Message</a>"
|
||||
|
||||
dat += " | <a href='byond://?src=\ref[src];func_msg=clear'>Clear</a>"
|
||||
dat += " | <a href='byond://?src=\ref[src];func_msg=print'>Print</a>"
|
||||
|
||||
dat += " | Name:<a href='byond://?src=\ref[src];set_name=1'>[src.screen_name]</a><hr>"
|
||||
|
||||
dat += messages
|
||||
|
||||
dat += "</center>"
|
||||
|
||||
return dat
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["send_msg"])
|
||||
var/t = input(usr, "Please enter messenger", src.id_tag, null) as text
|
||||
t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN)
|
||||
if (!t)
|
||||
return
|
||||
if (!in_range(src.master, usr))
|
||||
return
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.data["type"] = "message"
|
||||
signal.data["data"] = t
|
||||
signal.data["sender"] = src.screen_name
|
||||
src.messages += "<i><b>→ You:</b></i><br>[t]<br>"
|
||||
peripheral_command("send signal", signal)
|
||||
|
||||
if(href_list["func_msg"])
|
||||
switch(href_list["func_msg"])
|
||||
if("clear")
|
||||
src.messages = null
|
||||
|
||||
if("print")
|
||||
var/datum/signal/signal = new
|
||||
signal.data["data"] = src.messages
|
||||
signal.data["title"] = "Chatlog"
|
||||
peripheral_command("print", signal)
|
||||
|
||||
//if("save")
|
||||
//TO-DO
|
||||
|
||||
|
||||
if(href_list["set_name"])
|
||||
var/t = input(usr, "Please enter screen name", src.id_tag, null) as text
|
||||
t = copytext(sanitize(t), 1, 20)
|
||||
if (!t)
|
||||
return
|
||||
if (!in_range(src.master, usr))
|
||||
return
|
||||
|
||||
src.screen_name = t
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateUsrDialog()
|
||||
return
|
||||
|
||||
receive_command(obj/source, command, datum/signal/signal)
|
||||
if(..() || !signal)
|
||||
return
|
||||
|
||||
if(command == "radio signal")
|
||||
switch(signal.data["type"])
|
||||
if("message")
|
||||
var/sender = signal.data["sender"]
|
||||
if(!sender)
|
||||
sender = "Unknown"
|
||||
|
||||
src.messages += "<i><b>← From [sender]:</b></i><br>[signal.data["data"]]<br>"
|
||||
if(src.master.active_program == src)
|
||||
playsound(src.master.loc, 'twobeep.ogg', 50, 1)
|
||||
src.master.updateUsrDialog()
|
||||
|
||||
return
|
||||
@@ -0,0 +1,209 @@
|
||||
/obj/item/weapon/peripheral
|
||||
name = "Peripheral card"
|
||||
desc = "A computer circuit board."
|
||||
icon = 'module.dmi'
|
||||
icon_state = "id_mod"
|
||||
item_state = "electronic"
|
||||
w_class = 2
|
||||
var/obj/machinery/computer2/host
|
||||
var/id = null
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn(2)
|
||||
if(istype(src.loc,/obj/machinery/computer2))
|
||||
host = src.loc
|
||||
host.peripherals.Add(src)
|
||||
// var/setup_id = "\ref[src]"
|
||||
// src.id = copytext(setup_id,4,(length(setup_id)-1) )
|
||||
|
||||
Del()
|
||||
if(host)
|
||||
host.peripherals.Remove(src)
|
||||
..()
|
||||
|
||||
|
||||
proc
|
||||
receive_command(obj/source, command, datum/signal/signal)
|
||||
if((source != host) || !(src in host))
|
||||
return 1
|
||||
|
||||
if(!command)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
send_command(command, datum/signal/signal)
|
||||
if(!command || !host)
|
||||
return
|
||||
|
||||
src.host.receive_command(src, command, signal)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/peripheral/radio
|
||||
name = "Wireless card"
|
||||
var/frequency = 1419
|
||||
var/code = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
New()
|
||||
..()
|
||||
if(radio_controller)
|
||||
initialize()
|
||||
|
||||
initialize()
|
||||
set_frequency(frequency)
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, "[frequency]")
|
||||
frequency = new_frequency
|
||||
radio_connection = radio_controller.add_object(src, "[frequency]")
|
||||
|
||||
receive_command(obj/source, command, datum/signal/signal)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!signal || !radio_connection)
|
||||
return
|
||||
|
||||
switch(command)
|
||||
if("send signal")
|
||||
src.radio_connection.post_signal(src, signal)
|
||||
|
||||
return
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(!signal || (signal.encryption && signal.encryption != code))
|
||||
return
|
||||
|
||||
var/datum/signal/newsignal = new
|
||||
newsignal.data = signal.data
|
||||
if(src.code)
|
||||
newsignal.encryption = src.code
|
||||
|
||||
send_command("radio signal",newsignal)
|
||||
return
|
||||
|
||||
/obj/item/weapon/peripheral/printer
|
||||
name = "Printer module"
|
||||
desc = "A small printer designed to fit into a computer casing."
|
||||
icon_state = "card_mod"
|
||||
var/printing = 0
|
||||
|
||||
receive_command(obj/source,command, datum/signal/signal)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!signal)
|
||||
return
|
||||
|
||||
if((command == "print") && !src.printing)
|
||||
src.printing = 1
|
||||
|
||||
var/print_data = signal.data["data"]
|
||||
var/print_title = signal.data["title"]
|
||||
if(!print_data)
|
||||
src.printing = 0
|
||||
return
|
||||
spawn(50)
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.host.loc )
|
||||
P.info = print_data
|
||||
if(print_title)
|
||||
P.name = "paper- '[print_title]'"
|
||||
|
||||
src.printing = 0
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/peripheral/prize_vendor
|
||||
name = "Prize vending module"
|
||||
desc = "An arcade prize dispenser designed to fit inside a computer casing."
|
||||
icon_state = "power_mod"
|
||||
var/last_vend = 0 //Delay between vends if manually activated(ie a dude is holding it and shaking stuff out)
|
||||
|
||||
receive_command(obj/source,command, datum/signal/signal)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(command == "vend prize")
|
||||
src.vend_prize()
|
||||
|
||||
return
|
||||
|
||||
attack_self(mob/user as mob)
|
||||
if( (last_vend + 400) < world.time)
|
||||
user << "You shake something out of [src]!"
|
||||
src.vend_prize()
|
||||
src.last_vend = world.time
|
||||
else
|
||||
user << "\red [src] isn't ready to dispense a prize yet."
|
||||
|
||||
return
|
||||
|
||||
proc/vend_prize()
|
||||
var/obj/item/prize
|
||||
var/prizeselect = rand(1,4)
|
||||
var/turf/prize_location = null
|
||||
|
||||
if(src.host)
|
||||
prize_location = src.host.loc
|
||||
else
|
||||
prize_location = get_turf(src)
|
||||
|
||||
switch(prizeselect)
|
||||
if(1)
|
||||
prize = new /obj/item/weapon/spacecash( prize_location )
|
||||
prize.name = "space ticket"
|
||||
prize.desc = "It's almost like actual currency!"
|
||||
if(2)
|
||||
prize = new /obj/item/device/radio/beacon( prize_location )
|
||||
prize.name = "electronic blink toy game"
|
||||
prize.desc = "Blink. Blink. Blink."
|
||||
if(3)
|
||||
prize = new /obj/item/weapon/zippo( prize_location )
|
||||
prize.name = "Burno Lighter"
|
||||
prize.desc = "Almost like a decent lighter!"
|
||||
if(4)
|
||||
prize = new /obj/item/weapon/c_tube( prize_location )
|
||||
prize.name = "toy sword"
|
||||
prize.icon = 'weapons.dmi'
|
||||
prize.icon_state = "sword1"
|
||||
prize.desc = "A sword made of cheap plastic."
|
||||
|
||||
/*
|
||||
/obj/item/weapon/peripheral/card_scanner
|
||||
name = "ID scanner module"
|
||||
icon_state = "card_mod"
|
||||
var/obj/item/weapon/card/id/authid = null
|
||||
|
||||
attack_self(mob/user as mob)
|
||||
if(authid)
|
||||
user << "The card falls out."
|
||||
src.authid.loc = get_turf(user)
|
||||
src.authid = null
|
||||
|
||||
return
|
||||
|
||||
receive_command(obj/source,command, datum/signal/signal)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!signal || (signal.data["ref_id"] != "\ref[src]") )
|
||||
return
|
||||
|
||||
switch(command)
|
||||
if("eject card")
|
||||
if(src.authid)
|
||||
src.authid.loc = src.host.loc
|
||||
src.authid = null
|
||||
if("add card access")
|
||||
var/new_access = signal.data["access"]
|
||||
if(!new_access)
|
||||
return
|
||||
|
||||
|
||||
|
||||
return
|
||||
*/
|
||||
@@ -0,0 +1,70 @@
|
||||
/obj/effects/expl_particles
|
||||
name = "fire"
|
||||
icon = 'effects.dmi'
|
||||
icon_state = "explosion_particle"
|
||||
opacity = 1
|
||||
anchored = 1
|
||||
mouse_opacity = 0
|
||||
|
||||
/obj/effects/expl_particles/New()
|
||||
..()
|
||||
spawn (15)
|
||||
del(src)
|
||||
return
|
||||
|
||||
/obj/effects/expl_particles/Move()
|
||||
..()
|
||||
return
|
||||
|
||||
/datum/effects/system/expl_particles
|
||||
var/number = 10
|
||||
var/turf/location
|
||||
var/total_particles = 0
|
||||
|
||||
/datum/effects/system/expl_particles/proc/set_up(n = 10, loca)
|
||||
number = n
|
||||
if(istype(loca, /turf/)) location = loca
|
||||
else location = get_turf(loca)
|
||||
|
||||
/datum/effects/system/expl_particles/proc/start()
|
||||
var/i = 0
|
||||
for(i=0, i<src.number, i++)
|
||||
spawn(0)
|
||||
var/obj/effects/expl_particles/expl = new /obj/effects/expl_particles(src.location)
|
||||
var/direct = pick(alldirs)
|
||||
for(i=0, i<pick(1;25,2;50,3,4;200), i++)
|
||||
sleep(1)
|
||||
step(expl,direct)
|
||||
|
||||
/obj/effects/explosion
|
||||
name = "fire"
|
||||
icon = '96x96.dmi'
|
||||
icon_state = "explosion"
|
||||
opacity = 1
|
||||
anchored = 1
|
||||
mouse_opacity = 0
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
|
||||
/obj/effects/explosion/New()
|
||||
..()
|
||||
spawn (10)
|
||||
del(src)
|
||||
return
|
||||
|
||||
/datum/effects/system/explosion
|
||||
var/turf/location
|
||||
|
||||
/datum/effects/system/explosion/proc/set_up(loca)
|
||||
if(istype(loca, /turf/)) location = loca
|
||||
else location = get_turf(loca)
|
||||
|
||||
/datum/effects/system/explosion/proc/start()
|
||||
new/obj/effects/explosion( location )
|
||||
var/datum/effects/system/expl_particles/P = new/datum/effects/system/expl_particles()
|
||||
P.set_up(10,location)
|
||||
P.start()
|
||||
spawn(5)
|
||||
var/datum/effects/system/harmless_smoke_spread/S = new/datum/effects/system/harmless_smoke_spread()
|
||||
S.set_up(5,0,location,null)
|
||||
S.start()
|
||||
@@ -0,0 +1,179 @@
|
||||
// the laser beam
|
||||
|
||||
|
||||
/obj/beam/laser
|
||||
name = "laser beam"
|
||||
icon = 'beam.dmi'
|
||||
icon_state = "full"
|
||||
density = 0
|
||||
mouse_opacity = 0
|
||||
|
||||
flags = TABLEPASS
|
||||
|
||||
var/wavelength // the (vaccuum) wavelength of the beam
|
||||
var/width = 1 // 1=thin, 2=medium, 3=wide
|
||||
|
||||
var/obj/beam/laser/next
|
||||
var/obj/beam/laser/prev
|
||||
var/obj/master
|
||||
|
||||
New(var/atom/newloc, var/dirn, var/lambda, var/omega=1, var/half=0)
|
||||
|
||||
if(!isturf(loc))
|
||||
return
|
||||
|
||||
//world << "creating beam at ([newloc.x],[newloc.y]) with [dirn] [lambda] [omega] [half]"
|
||||
|
||||
icon_state = "[omega]-[half ? "half" : "full"]"
|
||||
dir = dirn
|
||||
set_wavelength(lambda)
|
||||
..(newloc)
|
||||
spawn(0)
|
||||
src.propagate()
|
||||
src.verbs -= /atom/movable/verb/pull
|
||||
|
||||
|
||||
|
||||
proc/propagate()
|
||||
var/turf/T = get_step(src, dir)
|
||||
if(T)
|
||||
if(T.Enter(src))
|
||||
next = new(T, dir, wavelength, width, 0)
|
||||
next.prev = src
|
||||
next.master = src.master
|
||||
else
|
||||
spawn(5)
|
||||
propagate()
|
||||
|
||||
|
||||
proc/remove()
|
||||
if(next)
|
||||
next.remove()
|
||||
del(src)
|
||||
|
||||
|
||||
|
||||
proc/blocked(var/atom/A)
|
||||
return density || opacity
|
||||
/*
|
||||
/turf/Enter(atom/movable/mover as mob|obj)
|
||||
if (!mover || !isturf(mover.loc))
|
||||
return 1
|
||||
|
||||
|
||||
//First, check objects to block exit that are not on the border
|
||||
for(var/obj/obstacle in mover.loc)
|
||||
if((obstacle.flags & ~ON_BORDER) && (mover != obstacle) && (forget != obstacle))
|
||||
if(!obstacle.CheckExit(mover, src))
|
||||
mover.Bump(obstacle, 1)
|
||||
return 0
|
||||
|
||||
//Now, check objects to block exit that are on the border
|
||||
for(var/obj/border_obstacle in mover.loc)
|
||||
if((border_obstacle.flags & ON_BORDER) && (mover != border_obstacle) && (forget != border_obstacle))
|
||||
if(!border_obstacle.CheckExit(mover, src))
|
||||
mover.Bump(border_obstacle, 1)
|
||||
return 0
|
||||
|
||||
//Next, check objects to block entry that are on the border
|
||||
for(var/obj/border_obstacle in src)
|
||||
if(border_obstacle.flags & ON_BORDER)
|
||||
if(!border_obstacle.CanPass(mover, mover.loc, 1, 0) && (forget != border_obstacle))
|
||||
mover.Bump(border_obstacle, 1)
|
||||
return 0
|
||||
|
||||
//Then, check the turf itself
|
||||
if (!src.CanPass(mover, src))
|
||||
mover.Bump(src, 1)
|
||||
return 0
|
||||
|
||||
//Finally, check objects/mobs to block entry that are not on the border
|
||||
for(var/atom/movable/obstacle in src)
|
||||
if(obstacle.flags & ~ON_BORDER)
|
||||
if(!obstacle.CanPass(mover, mover.loc, 1, 0) && (forget != obstacle))
|
||||
mover.Bump(obstacle, 1)
|
||||
return 0
|
||||
return 1 //Nothing found to block so return success!
|
||||
*/
|
||||
|
||||
|
||||
HasEntered(var/atom/movable/AM)
|
||||
if(istype(AM, /obj/beam))
|
||||
return
|
||||
if(blocked(AM))
|
||||
remove(src)
|
||||
if(prev)
|
||||
prev.propagate()
|
||||
else if(master)
|
||||
master:turn_on()
|
||||
|
||||
proc/set_wavelength(var/lambda)
|
||||
|
||||
var/w = round(lambda,1) // integer wavelength
|
||||
wavelength = lambda
|
||||
// first look for cached version of the icon at this wavelength
|
||||
var/icon/cached = beam_icons["[w]"]
|
||||
if(cached)
|
||||
icon = cached
|
||||
|
||||
return
|
||||
|
||||
// no cached version, so generate a new one
|
||||
|
||||
// this maps a wavelength in the range 380-780 nm to an R,G,B,A value
|
||||
var/red = 0
|
||||
var/green = 0
|
||||
var/blue = 0
|
||||
var/alpha = 0
|
||||
|
||||
switch(w)
|
||||
if(380 to 439)
|
||||
red = (440-w) / 60
|
||||
green = 0
|
||||
blue = 1
|
||||
if(440 to 489)
|
||||
red = 0
|
||||
green = (w-440) / 50
|
||||
blue = 1
|
||||
if(490 to 509)
|
||||
red = 0
|
||||
green = 1
|
||||
blue = (510 - w) / 20
|
||||
if(510 to 579)
|
||||
red = (w-510) / 70
|
||||
green = 1
|
||||
blue = 0
|
||||
if(580 to 644)
|
||||
red = 1
|
||||
green = (645-w) / 65
|
||||
blue = 0
|
||||
if(645 to 780)
|
||||
red = 1
|
||||
green = 0
|
||||
blue = 0
|
||||
|
||||
// colour is done, now calculate intensity
|
||||
switch(w)
|
||||
if(380 to 419)
|
||||
alpha = 0.75*(w-380)/40
|
||||
if(420 to 700)
|
||||
alpha = 0.75
|
||||
if(701 to 780)
|
||||
alpha = 0.75*(780-w)/80
|
||||
|
||||
// remap alpha by intensity gamma
|
||||
if(alpha != 0)
|
||||
alpha = alpha**0.80
|
||||
|
||||
var/icon/I = icon('beam.dmi')
|
||||
I.MapColors(red,0,0,0, 0,green,0,0, 0,0,blue,0, 0,0,0,alpha, 0,0,0,0)
|
||||
icon = I
|
||||
|
||||
beam_icons["[w]"] = I
|
||||
|
||||
|
||||
|
||||
// global cache of beam icons
|
||||
// this is an assoc list mapping (integer) wavelength to icons
|
||||
|
||||
var/list/beam_icons = new()
|
||||
@@ -0,0 +1,72 @@
|
||||
// A laser pointer. Emits a (tunable) low-power laser beam
|
||||
// Used for alignment and testing of the optics system
|
||||
|
||||
/obj/item/device/laser_pointer
|
||||
name = "laser pointer"
|
||||
desc = "A portable low-power laser used for optical system alignment. The label reads: 'Danger: Class IIIa laser device. Avoid direct eye exposure."
|
||||
icon = 'optics.dmi'
|
||||
icon_state = "pointer0"
|
||||
var/on = 0 // true if operating
|
||||
var/wavelength = 632 // operation wavelength (nm)
|
||||
|
||||
var/gain_peak = 632 // gain peak (nm)
|
||||
var/gain_width = 35 // gain bandwidth (nm)
|
||||
var/peak_output = 0.005 // max output 5 mW
|
||||
layer = OBJ_LAYER + 0.1
|
||||
|
||||
w_class = 4
|
||||
m_amt = 500
|
||||
g_amt = 100
|
||||
w_amt = 200
|
||||
|
||||
var/obj/beam/laser/beam // the created beam
|
||||
|
||||
flags = FPRINT | CONDUCT | TABLEPASS
|
||||
|
||||
attack_ai()
|
||||
return
|
||||
|
||||
attack_paw()
|
||||
return
|
||||
|
||||
attack_self(var/mob/user)
|
||||
|
||||
|
||||
on = !on
|
||||
if(on)
|
||||
turn_on()
|
||||
else
|
||||
turn_off()
|
||||
|
||||
updateicon()
|
||||
|
||||
verb/rotate()
|
||||
set src in view(1)
|
||||
turn_off()
|
||||
dir = turn(dir, -90)
|
||||
if(on) turn_on()
|
||||
|
||||
Move(var/atom/newloc,var/newdir)
|
||||
. = ..(newloc,newdir)
|
||||
if(on && . && isturf(newloc))
|
||||
turn_off()
|
||||
turn_on()
|
||||
return .
|
||||
|
||||
proc/turn_on()
|
||||
if(!isturf(loc))
|
||||
return
|
||||
|
||||
beam = new(loc, dir, wavelength, 1, 1)
|
||||
beam.master = src
|
||||
|
||||
proc/turn_off()
|
||||
if(beam)
|
||||
beam.remove()
|
||||
|
||||
dropped()
|
||||
turn_off()
|
||||
turn_on()
|
||||
|
||||
proc/updateicon()
|
||||
icon_state = "pointer[on]"
|
||||
@@ -0,0 +1,83 @@
|
||||
// Mirror object
|
||||
// Part of the optics system
|
||||
//
|
||||
// reflects laser beams
|
||||
// 16 directional states 0/22.5/45/67.5deg to allow for 0/45deg beam angles
|
||||
|
||||
|
||||
// ideas:
|
||||
// frame/stand icon w/ mirror directional overlay
|
||||
// two sets of overlay icons for 0/45 and 22.5/67.5 deg angles
|
||||
|
||||
// can rotate cw/acw - need screwdriver to loosen/tighten mirror
|
||||
// use wrench to anchor/unanchor frame
|
||||
// if touched, gets dirty - fingerprints, which reduce reflectivity
|
||||
// if dirty and hit with high-power beam, mirror may shatter
|
||||
// some kind of dust accumulation with HasProximity? Could check for mob w/o labcoat etc.
|
||||
// can clean with acetone+wipes
|
||||
|
||||
/obj/optical/mirror
|
||||
icon = 'optical.dmi'
|
||||
icon_state = "mirrorA"
|
||||
dir = 1
|
||||
desc = "A large, optical-grade mirror firmly mounted on a stand."
|
||||
flags = FPRINT
|
||||
anchored = 0
|
||||
var/rotatable = 0 // true if mirror can be rotated
|
||||
var/angle = 0 // normal of mirror, 0-15. 0=N, 1=NNE, 2=NE, 3=ENE, 4=E etc
|
||||
|
||||
|
||||
New()
|
||||
..()
|
||||
set_angle()
|
||||
|
||||
|
||||
|
||||
//set the angle from icon_state and dir
|
||||
proc/set_angle()
|
||||
switch(dir)
|
||||
if(1)
|
||||
angle = 0
|
||||
if(5)
|
||||
angle = 2
|
||||
if(4)
|
||||
angle = 4
|
||||
if(6)
|
||||
angle = 6
|
||||
if(2)
|
||||
angle = 8
|
||||
if(10)
|
||||
angle = 10
|
||||
if(8)
|
||||
angle = 12
|
||||
if(9)
|
||||
angle = 14
|
||||
|
||||
if(icon_state == "mirrorB") // 22.5deg turned states
|
||||
angle++
|
||||
return
|
||||
|
||||
// set the dir and icon_state from the angle
|
||||
proc/set_dir()
|
||||
if(angle%2 == 1)
|
||||
icon_state = "mirrorB"
|
||||
else
|
||||
icon_state = "mirrorA"
|
||||
switch(round(angle/2)*2)
|
||||
if(0)
|
||||
dir = 1
|
||||
if(2)
|
||||
dir = 5
|
||||
if(4)
|
||||
dir = 4
|
||||
if(6)
|
||||
dir = 6
|
||||
if(8)
|
||||
dir = 2
|
||||
if(10)
|
||||
dir = 10
|
||||
if(12)
|
||||
dir = 8
|
||||
if(14)
|
||||
dir = 9
|
||||
return
|
||||
@@ -0,0 +1,445 @@
|
||||
/datum/computer/file/pda_program/os
|
||||
proc
|
||||
receive_os_command(list/command_list)
|
||||
if((!src.holder) || (!src.master) || (!command_list) || !(command_list["command"]))
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
//Main os program: Provides old pda interface and four programs including file browser, notes, messenger, and atmos scan
|
||||
main_os
|
||||
name = "ThinkOS 7"
|
||||
size = 8.0
|
||||
var/mode = 0
|
||||
//Note vars
|
||||
var/note = "Congratulations, your station has chosen the Thinktronic 5150 Personal Data Assistant!"
|
||||
var/note_mode = 0 //0 For note editor, 1 for note browser
|
||||
var/datum/computer/file/text/note_file = null //If set, save to this file.
|
||||
//Messenger vars
|
||||
var/list/detected_pdas = list()
|
||||
var/message_on = 1
|
||||
var/message_silent = 0 //To beep or not to beep, that is the question
|
||||
var/message_mode = 0 //0 for pda list, 1 for messages
|
||||
var/message_tone = "beep" //Custom ringtone
|
||||
var/message_note = null //Current messages in memory (Store as separate file only later??)
|
||||
//File browser vars
|
||||
var/datum/computer/folder/browse_folder = null
|
||||
var/datum/computer/file/clipboard = null //Current file to copy
|
||||
|
||||
|
||||
|
||||
receive_os_command(list/command_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
//world << "[command_list["command"]]"
|
||||
return
|
||||
|
||||
return_text()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/dat = src.return_text_header()
|
||||
|
||||
switch(src.mode)
|
||||
if(0)
|
||||
dat += "<h2>PERSONAL DATA ASSISTANT</h2>"
|
||||
dat += "Owner: [src.master.owner]<br><br>"
|
||||
|
||||
dat += "<h4>General Functions</h4>"
|
||||
dat += "<ul>"
|
||||
dat += "<li><a href='byond://?src=\ref[src];mode=1'>Notekeeper</a></li>"
|
||||
dat += "<li><a href='byond://?src=\ref[src];mode=2'>Messenger</a></li>"
|
||||
dat += "<li><a href='byond://?src=\ref[src];mode=3'>File Browser</a></li>"
|
||||
dat += "</ul>"
|
||||
|
||||
dat += "<h4>Utilities</h4>"
|
||||
dat += "<ul>"
|
||||
dat += "<li><a href='byond://?src=\ref[src];mode=4'>Atmospheric Scan</a></li>"
|
||||
dat += "<li>Scanner: [src.master.scan_program ? "<a href='byond://?src=\ref[src];scanner=1'>[src.master.scan_program.name]</a>" : "None loaded"]</li>"
|
||||
dat += "<li><a href='byond://?src=\ref[src];flight=1'>[src.master.fon ? "Disable" : "Enable"] Flashlight</a></li>"
|
||||
|
||||
dat += "</ul>"
|
||||
|
||||
if(1)
|
||||
//Note Program. Can save/load note files.
|
||||
dat += "<h4>Notekeeper V2.5</h4>"
|
||||
|
||||
if(!src.note_mode)
|
||||
dat += "<a href='byond://?src=\ref[src];input=note'>Edit</a>"
|
||||
dat += " | <a href='byond://?src=\ref[src];note_func=new'>New File</a>"
|
||||
dat += " | <a href='byond://?src=\ref[src];note_func=save'>Save</a>"
|
||||
dat += " | <a href='byond://?src=\ref[src];note_func=switchmenu'>Load</a><br>"
|
||||
|
||||
dat += src.note
|
||||
else
|
||||
dat += " <a href='byond://?src=\ref[src];note_func=switchmenu'>Back</a>"
|
||||
dat += " | \[[src.holding_folder.holder.file_amount - src.holding_folder.holder.file_used]\] Free<br>"
|
||||
dat += "<table cellspacing=5>"
|
||||
|
||||
for(var/datum/computer/file/text/T in src.holding_folder.contents)
|
||||
dat += "<tr><td><a href='byond://?src=\ref[src];target=\ref[T];note_func=load'>[T.name]</a></td>"
|
||||
dat += "<td>[T.extension]</td>"
|
||||
dat += "<td>Length: [T.data ? (length(T.data)) : "0"]</td></tr>"
|
||||
|
||||
dat += "</table>"
|
||||
|
||||
if(2)
|
||||
//Messenger. Uses Radio. Is a messenger.
|
||||
//TO-DO: ~file sharing~
|
||||
src.master.overlays = null //Remove existing alerts
|
||||
dat += "<h4>SpaceMessenger V4.0.5</h4>"
|
||||
|
||||
if (!src.message_mode)
|
||||
|
||||
dat += "<a href='byond://?src=\ref[src];message_func=ringer'>Ringer: [src.message_silent == 1 ? "Off" : "On"]</a> | "
|
||||
dat += "<a href='byond://?src=\ref[src];message_func=on'>Send / Receive: [src.message_on == 1 ? "On" : "Off"]</a> | "
|
||||
dat += "<a href='byond://?src=\ref[src];input=tone'>Set Ringtone</a> | "
|
||||
dat += "<a href='byond://?src=\ref[src];message_mode=1'>Messages</a><br>"
|
||||
|
||||
dat += "<font size=2><a href='byond://?src=\ref[src];message_func=scan'>Scan</a></font><br>"
|
||||
dat += "<b>Detected PDAs</b><br>"
|
||||
|
||||
dat += "<ul>"
|
||||
|
||||
var/count = 0
|
||||
|
||||
if (src.message_on)
|
||||
for (var/obj/item/device/pda2/P in src.detected_pdas)
|
||||
if (!P.owner)
|
||||
src.detected_pdas -= P
|
||||
continue
|
||||
else if (P == src) //I guess this can happen if somebody copies the system file.
|
||||
src.detected_pdas -= P
|
||||
continue
|
||||
|
||||
dat += "<li><a href='byond://?src=\ref[src];input=message;target=\ref[P]'>[P]</a>"
|
||||
|
||||
dat += "</li>"
|
||||
count++
|
||||
|
||||
dat += "</ul>"
|
||||
|
||||
if (count == 0)
|
||||
dat += "None detected.<br>"
|
||||
|
||||
else
|
||||
dat += "<a href='byond://?src=\ref[src];message_func=clear'>Clear</a> | "
|
||||
dat += "<a href='byond://?src=\ref[src];message_mode=0'>Back</a><br>"
|
||||
|
||||
dat += "<h4>Messages</h4>"
|
||||
|
||||
dat += src.message_note
|
||||
dat += "<br>"
|
||||
|
||||
if(3)
|
||||
//File Browser.
|
||||
//To-do(?): Setting "favorite" programs to access straight from main menu
|
||||
//Not sure how needed it is, not like they have to go through 500 subfolders or whatever
|
||||
if((!src.browse_folder) || !(src.browse_folder.holder in src.master))
|
||||
src.browse_folder = src.holding_folder
|
||||
|
||||
dat += " | <a href='byond://?src=\ref[src];target=\ref[src.browse_folder];browse_func=paste'>Paste</a>"
|
||||
dat += " | Drive: "
|
||||
dat += "\[<a href='byond://?src=\ref[src];browse_func=drive'>[src.browse_folder.holder == src.master.hd ? "MAIN" : "CART"]</a>\]<br>"
|
||||
|
||||
dat += "<b>Contents of [browse_folder] | Drive ID:\[[src.browse_folder.holder.title]]</b><br>"
|
||||
dat += "<b>Used: \[[src.browse_folder.holder.file_used]/[src.browse_folder.holder.file_amount]\]</b><hr>"
|
||||
|
||||
dat += "<table cellspacing=5>"
|
||||
for(var/datum/computer/file/F in browse_folder.contents)
|
||||
if(F == src)
|
||||
dat += "<tr><td>System</td><td>Size: [src.size]</td><td>SYSTEM</td></tr>"
|
||||
continue
|
||||
dat += "<tr><td><a href='byond://?src=\ref[src];target=\ref[F];browse_func=open'>[F.name]</a></td>"
|
||||
dat += "<td>Size: [F.size]</td>"
|
||||
|
||||
dat += "<td>[F.extension]</td>"
|
||||
|
||||
dat += "<td><a href='byond://?src=\ref[src];target=\ref[F];browse_func=delete'>Del</a></td>"
|
||||
dat += "<td><a href='byond://?src=\ref[src];target=\ref[F];input=rename'>Rename</a></td>"
|
||||
|
||||
dat += "<td><a href='byond://?src=\ref[src];target=\ref[F];browse_func=copy'>Copy</a></td>"
|
||||
|
||||
dat += "</tr>"
|
||||
|
||||
dat += "</table>"
|
||||
|
||||
if(4)
|
||||
//Atmos Scanner
|
||||
dat += "<h4>Atmospheric Readings</h4>"
|
||||
|
||||
var/turf/T = get_turf_or_move(get_turf(src.master))
|
||||
if (isnull(T))
|
||||
dat += "Unable to obtain a reading.<br>"
|
||||
else
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
|
||||
var/pressure = environment.return_pressure()
|
||||
var/total_moles = environment.total_moles()
|
||||
|
||||
dat += "Air Pressure: [round(pressure,0.1)] kPa<br>"
|
||||
|
||||
if (total_moles)
|
||||
var/o2_level = environment.oxygen/total_moles
|
||||
var/n2_level = environment.nitrogen/total_moles
|
||||
var/co2_level = environment.carbon_dioxide/total_moles
|
||||
var/plasma_level = environment.toxins/total_moles
|
||||
var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level)
|
||||
|
||||
dat += "Nitrogen: [round(n2_level*100)]%<br>"
|
||||
|
||||
dat += "Oxygen: [round(o2_level*100)]%<br>"
|
||||
|
||||
dat += "Carbon Dioxide: [round(co2_level*100)]%<br>"
|
||||
|
||||
dat += "Plasma: [round(plasma_level*100)]%<br>"
|
||||
|
||||
if(unknown_level > 0.01)
|
||||
dat += "OTHER: [round(unknown_level)]%<br>"
|
||||
|
||||
dat += "Temperature: [round(environment.temperature-T0C)]°C<br>"
|
||||
|
||||
dat += "<br>"
|
||||
|
||||
return dat
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["mode"])
|
||||
var/newmode = text2num(href_list["mode"])
|
||||
src.mode = max(newmode, 0)
|
||||
|
||||
else if(href_list["flight"])
|
||||
src.master.toggle_light()
|
||||
|
||||
else if(href_list["scanner"])
|
||||
if(src.master.scan_program)
|
||||
src.master.scan_program = null
|
||||
|
||||
else if(href_list["input"])
|
||||
switch(href_list["input"])
|
||||
if("tone")
|
||||
var/t = input(usr, "Please enter new ringtone", src.name, src.message_tone) as text
|
||||
if (!t)
|
||||
return
|
||||
|
||||
if (!src.master || !in_range(src.master, usr) && src.master.loc != usr)
|
||||
return
|
||||
|
||||
if(!(src.holder in src.master))
|
||||
return
|
||||
|
||||
t = copytext(sanitize(t), 1, 20)
|
||||
src.message_tone = t
|
||||
|
||||
if("note")
|
||||
var/t = input(usr, "Please enter note", src.name, src.note) as message
|
||||
if (!t)
|
||||
return
|
||||
|
||||
if (!src.master || !in_range(src.master, usr) && src.master.loc != usr)
|
||||
return
|
||||
|
||||
if(!(src.holder in src.master))
|
||||
return
|
||||
|
||||
t = copytext(adminscrub(t), 1, MAX_MESSAGE_LEN)
|
||||
src.note = t
|
||||
|
||||
|
||||
if("message")
|
||||
var/obj/item/device/pda2/P = locate(href_list["target"])
|
||||
if(!P || !istype(P))
|
||||
return
|
||||
|
||||
var/t = input(usr, "Please enter message", P.name, null) as text
|
||||
if (!t)
|
||||
return
|
||||
|
||||
if (!src.master || !in_range(src.master, usr) && src.master.loc != usr)
|
||||
return
|
||||
|
||||
if(!(src.holder in src.master))
|
||||
return
|
||||
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.data["command"] = "text message"
|
||||
signal.data["message"] = t
|
||||
signal.data["sender"] = src.master.owner
|
||||
signal.data["tag"] = "\ref[P]"
|
||||
src.post_signal(signal)
|
||||
src.message_note += "<i><b>→ To [P.owner]:</b></i><br>[t]<br>"
|
||||
|
||||
if("rename")
|
||||
var/datum/computer/file/F = locate(href_list["target"])
|
||||
if(!F || !istype(F))
|
||||
return
|
||||
|
||||
var/t = input(usr, "Please enter new name", src.name, F.name) as text
|
||||
t = copytext(sanitize(t), 1, 16)
|
||||
if (!t)
|
||||
return
|
||||
if (!in_range(src.master, usr) || !(F.holder in src.master))
|
||||
return
|
||||
if(F.holder.read_only)
|
||||
return
|
||||
F.name = capitalize(lowertext(t))
|
||||
|
||||
|
||||
else if(href_list["message_func"]) //Messenger specific topic junk
|
||||
switch(href_list["message_func"])
|
||||
if("ringer")
|
||||
src.message_silent = !src.message_silent
|
||||
if("on")
|
||||
src.message_on = !src.message_on
|
||||
if("clear")
|
||||
src.message_note = null
|
||||
if("scan")
|
||||
if(src.message_on)
|
||||
src.detected_pdas = list()
|
||||
var/datum/signal/signal = new
|
||||
signal.data["command"] = "report pda"
|
||||
src.post_signal(signal)
|
||||
|
||||
else if(href_list["note_func"]) //Note program specific topic junk
|
||||
switch(href_list["note_func"])
|
||||
if("new")
|
||||
src.note_file = null
|
||||
src.note = null
|
||||
if("save")
|
||||
if(src.note_file && src.note_file.holder in src.master)
|
||||
src.note_file.data = src.note
|
||||
else
|
||||
var/datum/computer/file/text/F = new /datum/computer/file/text
|
||||
if(!src.holding_folder.add_file(F))
|
||||
del(F)
|
||||
else
|
||||
src.note_file = F
|
||||
F.data = src.note
|
||||
|
||||
if("load")
|
||||
var/datum/computer/file/text/T = locate(href_list["target"])
|
||||
if(!T || !istype(T))
|
||||
return
|
||||
|
||||
src.note_file = T
|
||||
src.note = note_file.data
|
||||
src.note_mode = 0
|
||||
|
||||
if("switchmenu")
|
||||
src.note_mode = !src.note_mode
|
||||
|
||||
else if(href_list["browse_func"]) //File browser specific topic junk
|
||||
var/datum/computer/target = locate(href_list["target"])
|
||||
switch(href_list["browse_func"])
|
||||
if("drive")
|
||||
if(src.browse_folder.holder == src.master.hd && src.master.cartridge && (src.master.cartridge.root))
|
||||
src.browse_folder = src.master.cartridge.root
|
||||
else
|
||||
src.browse_folder = src.holding_folder
|
||||
if("open")
|
||||
if(!target || !istype(target))
|
||||
return
|
||||
if(istype(target, /datum/computer/file/pda_program))
|
||||
if(istype(target,/datum/computer/file/pda_program/os) && (src.master.host_program))
|
||||
return
|
||||
else
|
||||
src.master.run_program(target)
|
||||
src.master.updateSelfDialog()
|
||||
return
|
||||
|
||||
if("delete")
|
||||
if(!target || !istype(target))
|
||||
return
|
||||
src.master.delete_file(target)
|
||||
|
||||
if("copy")
|
||||
if(istype(target,/datum/computer/file) && (!target.holder || (target.holder in src.master.contents)))
|
||||
src.clipboard = target
|
||||
|
||||
if("paste")
|
||||
if(istype(target,/datum/computer/folder))
|
||||
if(!src.clipboard || !src.clipboard.holder || !(src.clipboard.holder in src.master.contents))
|
||||
return
|
||||
|
||||
if(!istype(src.clipboard))
|
||||
return
|
||||
|
||||
src.clipboard.copy_file_to_folder(target)
|
||||
|
||||
|
||||
else if(href_list["message_mode"])
|
||||
var/newmode = text2num(href_list["message_mode"])
|
||||
src.message_mode = max(newmode, 0)
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateSelfDialog()
|
||||
return
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(..())
|
||||
return
|
||||
|
||||
switch(signal.data["command"])
|
||||
if("text message")
|
||||
if(!message_on || !signal.data["message"])
|
||||
return
|
||||
var/sender = signal.data["sender"]
|
||||
if(!sender)
|
||||
sender = "!Unknown!"
|
||||
|
||||
src.message_note += "<i><b>← From <a href='byond://?src=\ref[src];input=message;target=\ref[signal.source]'>[sender]</a>:</b></i><br>[signal.data["message"]]<br>"
|
||||
var/alert_beep = null //Don't beep if set to silent.
|
||||
if(!src.message_silent)
|
||||
alert_beep = src.message_tone
|
||||
|
||||
src.master.display_alert(alert_beep)
|
||||
src.master.updateSelfDialog()
|
||||
|
||||
if("report pda")
|
||||
if(!message_on)
|
||||
return
|
||||
|
||||
var/datum/signal/newsignal = new
|
||||
newsignal.data["command"] = "reporting pda"
|
||||
newsignal.data["tag"] = "\ref[signal.source]"
|
||||
src.post_signal(newsignal)
|
||||
|
||||
if("reporting pda")
|
||||
if(!detected_pdas)
|
||||
detected_pdas = new()
|
||||
|
||||
if(!(signal.source in detected_pdas))
|
||||
detected_pdas += signal.source
|
||||
|
||||
src.master.updateSelfDialog()
|
||||
|
||||
return
|
||||
|
||||
return_text_header()
|
||||
if(!src.master)
|
||||
return
|
||||
|
||||
var/dat
|
||||
|
||||
if(src.mode)
|
||||
dat += " | <a href='byond://?src=\ref[src];mode=0'>Main Menu</a>"
|
||||
|
||||
else if (!isnull(src.master.cartridge))
|
||||
dat += " | <a href='byond://?src=\ref[src.master];eject_cart=1'>Eject [src.master.cartridge]</a>"
|
||||
|
||||
dat += " | <a href='byond://?src=\ref[src.master];refresh=1'>Refresh</a>"
|
||||
|
||||
return dat
|
||||
@@ -0,0 +1,185 @@
|
||||
//Eventual plan: Convert all datum/data to datum/computer/file
|
||||
/datum/computer/file/text
|
||||
name = "text"
|
||||
extension = "TEXT"
|
||||
size = 2.0
|
||||
var/data = null
|
||||
|
||||
/datum/computer/file/record
|
||||
name = "record"
|
||||
extension = "REC"
|
||||
|
||||
var/list/fields = list( )
|
||||
|
||||
|
||||
//base pda program
|
||||
|
||||
/datum/computer/file/pda_program
|
||||
name = "blank program"
|
||||
extension = "PPROG"
|
||||
var/obj/item/device/pda2/master = null
|
||||
var/id_tag = null
|
||||
|
||||
os
|
||||
name = "blank system program"
|
||||
extension = "PSYS"
|
||||
|
||||
scan
|
||||
name = "blank scan program"
|
||||
extension = "PSCAN"
|
||||
|
||||
New(obj/holding as obj)
|
||||
if(holding)
|
||||
src.holder = holding
|
||||
|
||||
if(istype(src.holder.loc,/obj/item/device/pda2))
|
||||
src.master = src.holder.loc
|
||||
|
||||
proc
|
||||
return_text()
|
||||
if((!src.holder) || (!src.master))
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
//world << "Holder [holder] not in [master] of prg:[src]"
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
return 1
|
||||
|
||||
if(!src.holder.root)
|
||||
src.holder.root = new /datum/computer/folder
|
||||
src.holder.root.holder = src
|
||||
src.holder.root.name = "root"
|
||||
|
||||
return 0
|
||||
|
||||
process() //This isn't actually used at the moment
|
||||
if((!src.holder) || (!src.master))
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
return 1
|
||||
|
||||
if(!src.holder.root)
|
||||
src.holder.root = new /datum/computer/folder
|
||||
src.holder.root.holder = src
|
||||
src.holder.root.name = "root"
|
||||
|
||||
return 0
|
||||
|
||||
//maybe remove this, I haven't found a good use for it yet
|
||||
send_os_command(list/command_list)
|
||||
if(!src.master || !src.holder || src.master.host_program || !command_list)
|
||||
return 1
|
||||
|
||||
if(!istype(src.master.host_program) || src.master.host_program == src)
|
||||
return 1
|
||||
|
||||
src.master.host_program.receive_os_command()
|
||||
|
||||
return 0
|
||||
|
||||
return_text_header()
|
||||
if(!src.master || !src.holder)
|
||||
return
|
||||
|
||||
var/dat = " | <a href='byond://?src=\ref[src];quit=1'>Main Menu</a>"
|
||||
dat += " | <a href='byond://?src=\ref[src.master];refresh=1'>Refresh</a>"
|
||||
|
||||
return dat
|
||||
|
||||
post_signal(datum/signal/signal, newfreq)
|
||||
if(master)
|
||||
master.post_signal(signal, newfreq)
|
||||
else
|
||||
del(signal)
|
||||
|
||||
transfer_holder(obj/item/weapon/disk/data/newholder,datum/computer/folder/newfolder)
|
||||
|
||||
if((newholder.file_used + src.size) > newholder.file_amount)
|
||||
return 0
|
||||
|
||||
if(!newholder.root)
|
||||
newholder.root = new /datum/computer/folder
|
||||
newholder.root.holder = newholder
|
||||
newholder.root.name = "root"
|
||||
|
||||
if(!newfolder)
|
||||
newfolder = newholder.root
|
||||
|
||||
if((src.holder && src.holder.read_only) || newholder.read_only)
|
||||
return 0
|
||||
|
||||
if((src.holder) && (src.holder.root))
|
||||
src.holder.root.remove_file(src)
|
||||
|
||||
newfolder.add_file(src)
|
||||
|
||||
if(istype(newholder.loc,/obj/item/device/pda2))
|
||||
src.master = newholder.loc
|
||||
|
||||
//world << "Setting [src.holder] to [newholder]"
|
||||
src.holder = newholder
|
||||
return 1
|
||||
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if((!src.holder) || (!src.master))
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
Topic(href, href_list)
|
||||
if((!src.holder) || (!src.master))
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(src.master.active_program != src)
|
||||
return 1
|
||||
|
||||
if ((!usr.contents.Find(src.master) && (!in_range(src.master, usr) || !istype(src.master.loc, /turf))) && (!istype(usr, /mob/living/silicon)))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
if(master.active_program == src)
|
||||
master.active_program = null
|
||||
return 1
|
||||
|
||||
usr.machine = src.master
|
||||
|
||||
if (href_list["close"])
|
||||
usr.machine = null
|
||||
usr << browse(null, "window=pda2")
|
||||
return 0
|
||||
|
||||
if (href_list["quit"])
|
||||
// src.master.processing_programs.Remove(src)
|
||||
if(src.master.host_program && src.master.host_program.holder && (src.master.host_program.holder in src.master.contents))
|
||||
src.master.run_program(src.master.host_program)
|
||||
src.master.updateSelfDialog()
|
||||
return 1
|
||||
else
|
||||
src.master.active_program = null
|
||||
src.master.updateSelfDialog()
|
||||
return 1
|
||||
|
||||
return 0
|
||||
@@ -0,0 +1,297 @@
|
||||
//The advanced pea-green monochrome lcd of tomorrow.
|
||||
|
||||
|
||||
//TO-DO: rearrange all this disk/data stuff so that fixed disks are the parent type
|
||||
//because otherwise you have carts going into floppy drives and it's ALL MAD
|
||||
/obj/item/weapon/disk/data/cartridge
|
||||
name = "Cart 2.0"
|
||||
desc = "A data cartridge for portable microcomputers."
|
||||
icon = 'pda.dmi'
|
||||
icon_state = "cart"
|
||||
item_state = "electronic"
|
||||
file_amount = 80.0
|
||||
title = "ROM Cart"
|
||||
|
||||
pda2test
|
||||
name = "Test Cart"
|
||||
New()
|
||||
..()
|
||||
src.root.add_file( new /datum/computer/file/computer_program/arcade(src))
|
||||
src.root.add_file( new /datum/computer/file/pda_program/manifest(src))
|
||||
src.root.add_file( new /datum/computer/file/pda_program/status_display(src))
|
||||
src.root.add_file( new /datum/computer/file/pda_program/signaler(src))
|
||||
src.root.add_file( new /datum/computer/file/pda_program/qm_records(src))
|
||||
src.root.add_file( new /datum/computer/file/pda_program/scan/health_scan(src))
|
||||
src.root.add_file( new /datum/computer/file/pda_program/records/security(src))
|
||||
src.root.add_file( new /datum/computer/file/pda_program/records/medical(src))
|
||||
src.read_only = 1
|
||||
|
||||
|
||||
/obj/item/device/pda2
|
||||
name = "PDA"
|
||||
desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by an EEPROM cartridge."
|
||||
icon = 'pda.dmi'
|
||||
icon_state = "pda"
|
||||
item_state = "electronic"
|
||||
w_class = 2.0
|
||||
flags = FPRINT | TABLEPASS | ONBELT
|
||||
|
||||
var/owner = null
|
||||
var/default_cartridge = null // Access level defined by cartridge
|
||||
var/obj/item/weapon/disk/data/cartridge/cartridge = null //current cartridge
|
||||
var/datum/computer/file/pda_program/active_program = null
|
||||
var/datum/computer/file/pda_program/os/host_program = null
|
||||
var/datum/computer/file/pda_program/scan/scan_program = null
|
||||
var/obj/item/weapon/disk/data/fixed_disk/hd = null
|
||||
var/fon = 0 //Is the flashlight function on?
|
||||
var/f_lum = 3 //Luminosity for the flashlight function
|
||||
// var/datum/data/record/active1 = null //General
|
||||
// var/datum/data/record/active2 = null //Medical
|
||||
// var/datum/data/record/active3 = null //Security
|
||||
// var/obj/item/weapon/integrated_uplink/uplink = null //Maybe replace uplink with some remote ~syndicate~ server
|
||||
var/frequency = 1149
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
var/setup_default_cartridge = null //Cartridge contains job-specific programs
|
||||
var/setup_drive_size = 24.0 //PDAs don't have much work room at all, really.
|
||||
var/setup_system_os_path = /datum/computer/file/pda_program/os/main_os //Needs an operating system to...operate!!
|
||||
|
||||
|
||||
/obj/item/device/pda2/pickup(mob/user)
|
||||
if (src.fon)
|
||||
src.sd_SetLuminosity(0)
|
||||
user.sd_SetLuminosity(user.luminosity + src.f_lum)
|
||||
|
||||
/obj/item/device/pda2/dropped(mob/user)
|
||||
if (src.fon)
|
||||
user.sd_SetLuminosity(user.luminosity - src.f_lum)
|
||||
src.sd_SetLuminosity(src.f_lum)
|
||||
|
||||
/obj/item/device/pda2/New()
|
||||
..()
|
||||
spawn(5)
|
||||
src.hd = new /obj/item/weapon/disk/data/fixed_disk(src)
|
||||
src.hd.file_amount = src.setup_drive_size
|
||||
src.hd.name = "Minidrive"
|
||||
src.hd.title = "Minidrive"
|
||||
|
||||
if(src.setup_system_os_path)
|
||||
src.host_program = new src.setup_system_os_path
|
||||
|
||||
src.hd.file_amount = max(src.hd.file_amount, src.host_program.size)
|
||||
|
||||
src.host_program.transfer_holder(src.hd)
|
||||
|
||||
if(radio_controller)
|
||||
radio_controller.add_object(src, "[frequency]")
|
||||
|
||||
|
||||
if (src.default_cartridge)
|
||||
src.cartridge = new src.setup_default_cartridge(src)
|
||||
// if(src.owner)
|
||||
// processing_items.Add(src)
|
||||
|
||||
/obj/item/device/pda2/attack_self(mob/user as mob)
|
||||
user.machine = src
|
||||
|
||||
var/dat = "<html><head><title>Personal Data Assistant</title></head><body>"
|
||||
|
||||
dat += "<a href='byond://?src=\ref[src];close=1'>Close</a>"
|
||||
|
||||
if (!src.owner)
|
||||
if(src.cartridge)
|
||||
dat += " | <a href='byond://?src=\ref[src];eject_cart=1'>Eject [src.cartridge]</a>"
|
||||
dat += "<br>Warning: No owner information entered. Please swipe card.<br><br>"
|
||||
dat += "<a href='byond://?src=\ref[src];refresh=1'>Retry</a>"
|
||||
else
|
||||
if(src.active_program)
|
||||
dat += src.active_program.return_text()
|
||||
else
|
||||
if(src.host_program)
|
||||
src.run_program(src.host_program)
|
||||
dat += src.active_program.return_text()
|
||||
else
|
||||
if(src.cartridge)
|
||||
dat += " | <a href='byond://?src=\ref[src];eject_cart=1'>Eject [src.cartridge]</a><br>"
|
||||
dat += "<center><font color=red>Fatal Error 0x17<br>"
|
||||
dat += "No System Software Loaded</font></center>"
|
||||
//To-do: System recovery shit (maybe have a dedicated computer for this kind of thing)
|
||||
|
||||
|
||||
user << browse(dat,"window=pda2")
|
||||
onclose(user,"pda2")
|
||||
return
|
||||
|
||||
/obj/item/device/pda2/Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if (usr.contents.Find(src) || usr.contents.Find(src.master) || (istype(src.loc, /turf) && get_dist(src, usr) <= 1))
|
||||
if (usr.stat || usr.restrained())
|
||||
return
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
usr.machine = src
|
||||
|
||||
|
||||
if(href_list["return_to_host"])
|
||||
if(src.host_program)
|
||||
src.active_program = src.host_program
|
||||
src.host_program = null
|
||||
|
||||
else if (href_list["eject_cart"])
|
||||
src.eject_cartridge()
|
||||
|
||||
else if (href_list["refresh"])
|
||||
src.updateSelfDialog()
|
||||
|
||||
else if (href_list["close"])
|
||||
usr << browse(null, "window=pda2")
|
||||
usr.machine = null
|
||||
|
||||
src.updateSelfDialog()
|
||||
return
|
||||
|
||||
/obj/item/device/pda2/attackby(obj/item/weapon/C as obj, mob/user as mob)
|
||||
if (istype(C, /obj/item/weapon/disk/data/cartridge) && isnull(src.cartridge))
|
||||
user.drop_item()
|
||||
C.loc = src
|
||||
user << "\blue You insert [C] into [src]."
|
||||
src.cartridge = C
|
||||
src.updateSelfDialog()
|
||||
|
||||
else if (istype(C, /obj/item/weapon/card/id) && !src.owner && C:registered)
|
||||
src.owner = C:registered
|
||||
src.name = "PDA-[src.owner]"
|
||||
user << "\blue Card scanned."
|
||||
src.updateSelfDialog()
|
||||
|
||||
/obj/item/device/pda2/receive_signal(datum/signal/signal)
|
||||
if(!signal || signal.encryption || !src.owner) return
|
||||
|
||||
if(signal.data["tag"] && signal.data["tag"] != "\ref[src]") return
|
||||
|
||||
if(src.host_program)
|
||||
src.host_program.receive_signal(signal)
|
||||
|
||||
if(src.active_program && (src.active_program != src.host_program))
|
||||
src.host_program.receive_signal(signal)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/device/pda2/attack(mob/M as mob, mob/user as mob)
|
||||
if(src.scan_program)
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/pda2/afterattack(atom/A as mob|obj|turf|area, mob/user as mob)
|
||||
var/scan_dat = null
|
||||
if(src.scan_program && istype(src.scan_program))
|
||||
scan_dat = src.scan_program.scan_atom(A)
|
||||
|
||||
if(scan_dat)
|
||||
A.visible_message("\red [user] has scanned [A]!")
|
||||
user.show_message(scan_dat, 1)
|
||||
|
||||
return
|
||||
|
||||
|
||||
/obj/item/device/pda2/proc
|
||||
|
||||
post_signal(datum/signal/signal,var/newfreq)
|
||||
if(!signal)
|
||||
return
|
||||
var/freq = newfreq
|
||||
if(!freq)
|
||||
freq = src.frequency
|
||||
|
||||
signal.source = src
|
||||
|
||||
var/datum/radio_frequency/frequency = radio_controller.return_frequency("[freq]")
|
||||
|
||||
signal.transmission_method = TRANSMISSION_RADIO
|
||||
if(frequency)
|
||||
return frequency.post_signal(src, signal)
|
||||
else
|
||||
del(signal)
|
||||
|
||||
eject_cartridge()
|
||||
if(src.cartridge)
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
if(src.active_program && (src.active_program.holder == src.cartridge))
|
||||
src.active_program = null
|
||||
|
||||
if(src.host_program && (src.host_program.holder == src.cartridge))
|
||||
src.host_program = null
|
||||
|
||||
if(src.scan_program && (src.scan_program.holder == src.cartridge))
|
||||
src.scan_program = null
|
||||
|
||||
src.cartridge.loc = T
|
||||
src.cartridge = null
|
||||
|
||||
return
|
||||
|
||||
//Toggle the built-in flashlight
|
||||
toggle_light()
|
||||
src.fon = (!src.fon)
|
||||
|
||||
if (ismob(src.loc))
|
||||
if (src.fon)
|
||||
src.loc.sd_SetLuminosity(src.loc.luminosity + src.f_lum)
|
||||
else
|
||||
src.loc.sd_SetLuminosity(src.loc.luminosity - src.f_lum)
|
||||
else
|
||||
src.sd_SetLuminosity(src.fon * src.f_lum)
|
||||
|
||||
src.updateSelfDialog()
|
||||
|
||||
display_alert(var/alert_message) //Add alert overlay and beep
|
||||
if (alert_message)
|
||||
playsound(src.loc, 'twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(3, src.loc))
|
||||
O.show_message(text("\icon[src] *[alert_message]*"))
|
||||
|
||||
src.overlays = null
|
||||
src.overlays += image('pda.dmi', "pda-r")
|
||||
return
|
||||
|
||||
run_program(datum/computer/file/pda_program/program)
|
||||
if((!program) || (!program.holder))
|
||||
return 0
|
||||
|
||||
if(!(program.holder in src))
|
||||
// world << "Not in src"
|
||||
program = new program.type
|
||||
program.transfer_holder(src.hd)
|
||||
|
||||
if(program.master != src)
|
||||
program.master = src
|
||||
|
||||
if(!src.host_program && istype(program, /datum/computer/file/pda_program/os))
|
||||
src.host_program = program
|
||||
|
||||
if(istype(program, /datum/computer/file/pda_program/scan))
|
||||
if(program == src.scan_program)
|
||||
src.scan_program = null
|
||||
else
|
||||
src.scan_program = program
|
||||
return 1
|
||||
|
||||
src.active_program = program
|
||||
return 1
|
||||
|
||||
delete_file(datum/computer/file/file)
|
||||
//world << "Deleting [file]..."
|
||||
if((!file) || (!file.holder) || (file.holder.read_only))
|
||||
//world << "Cannot delete :("
|
||||
return 0
|
||||
|
||||
//Don't delete the running program you jerk
|
||||
if(src.active_program == file || src.host_program == file)
|
||||
src.active_program = null
|
||||
|
||||
//world << "Now calling del on [file]..."
|
||||
del(file)
|
||||
return 1
|
||||
@@ -0,0 +1,181 @@
|
||||
//CONTENTS:
|
||||
//Generic records
|
||||
//Security records
|
||||
//Medical records
|
||||
|
||||
|
||||
/datum/computer/file/pda_program/records
|
||||
var/mode = 0
|
||||
var/datum/data/record/active1 = null //General
|
||||
var/datum/data/record/active2 = null //Security/Medical/Whatever
|
||||
|
||||
//To-do: editing arrest status/etc from pda.
|
||||
/datum/computer/file/pda_program/records/security
|
||||
name = "Security Records"
|
||||
size = 12.0
|
||||
|
||||
return_text()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/dat = src.return_text_header()
|
||||
|
||||
switch(src.mode)
|
||||
if(0)
|
||||
dat += "<h4>Security Record List</h4>"
|
||||
|
||||
for (var/datum/data/record/R in data_core.general)
|
||||
dat += "<a href='byond://?src=\ref[src];select_rec=\ref[R]'>[R.fields["id"]]: [R.fields["name"]]<br>"
|
||||
|
||||
dat += "<br>"
|
||||
|
||||
if(1)
|
||||
|
||||
dat += "<h4>Security Record</h4>"
|
||||
|
||||
dat += "<a href='byond://?src=\ref[src];mode=0'>Back</a><br>"
|
||||
|
||||
if (istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))
|
||||
dat += "Name: [src.active1.fields["name"]] ID: [src.active1.fields["id"]]<br>"
|
||||
dat += "Sex: [src.active1.fields["sex"]]<br>"
|
||||
dat += "Age: [src.active1.fields["age"]]<br>"
|
||||
dat += "Fingerprint: [src.active1.fields["fingerprint"]]<br>"
|
||||
dat += "Physical Status: [src.active1.fields["p_stat"]]<br>"
|
||||
dat += "Mental Status: [src.active1.fields["m_stat"]]<br>"
|
||||
else
|
||||
dat += "<b>Record Lost!</b><br>"
|
||||
|
||||
dat += "<br>"
|
||||
|
||||
dat += "<h4>Security Data</h4>"
|
||||
if (istype(src.active2, /datum/data/record) && data_core.security.Find(src.active2))
|
||||
dat += "Criminal Status: [src.active2.fields["criminal"]]<br>"
|
||||
|
||||
dat += "Minor Crimes: [src.active2.fields["mi_crim"]]<br>"
|
||||
dat += "Details: [src.active2.fields["mi_crim"]]<br><br>"
|
||||
|
||||
dat += "Major Crimes: [src.active2.fields["ma_crim"]]<br>"
|
||||
dat += "Details: [src.active2.fields["ma_crim_d"]]<br><br>"
|
||||
|
||||
dat += "Important Notes:<br>"
|
||||
dat += "[src.active2.fields["notes"]]"
|
||||
else
|
||||
dat += "<b>Record Lost!</b><br>"
|
||||
|
||||
dat += "<br>"
|
||||
|
||||
return dat
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["mode"])
|
||||
var/newmode = text2num(href_list["mode"])
|
||||
src.mode = max(newmode, 0)
|
||||
|
||||
else if(href_list["select_rec"])
|
||||
var/datum/data/record/R = locate(href_list["select_rec"])
|
||||
var/datum/data/record/S = locate(href_list["select_rec"])
|
||||
|
||||
if (data_core.general.Find(R))
|
||||
for (var/datum/data/record/E in data_core.security)
|
||||
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
|
||||
S = E
|
||||
break
|
||||
|
||||
src.active1 = R
|
||||
src.active2 = S
|
||||
|
||||
src.mode = 1
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateSelfDialog()
|
||||
return
|
||||
|
||||
/datum/computer/file/pda_program/records/medical
|
||||
name = "Medical Records"
|
||||
size = 8.0
|
||||
|
||||
return_text()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/dat = src.return_text_header()
|
||||
|
||||
switch(src.mode)
|
||||
if(0)
|
||||
|
||||
dat += "<h4>Medical Record List</h4>"
|
||||
for (var/datum/data/record/R in data_core.general)
|
||||
dat += "<a href='byond://?src=\ref[src];select_rec=\ref[R]'>[R.fields["id"]]: [R.fields["name"]]<br>"
|
||||
dat += "<br>"
|
||||
|
||||
if(1)
|
||||
|
||||
dat += "<h4>Medical Record</h4>"
|
||||
|
||||
dat += "<a href='byond://?src=\ref[src];mode=0'>Back</a><br>"
|
||||
|
||||
if (istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1))
|
||||
dat += "Name: [src.active1.fields["name"]] ID: [src.active1.fields["id"]]<br>"
|
||||
dat += "Sex: [src.active1.fields["sex"]]<br>"
|
||||
dat += "Age: [src.active1.fields["age"]]<br>"
|
||||
dat += "Fingerprint: [src.active1.fields["fingerprint"]]<br>"
|
||||
dat += "Physical Status: [src.active1.fields["p_stat"]]<br>"
|
||||
dat += "Mental Status: [src.active1.fields["m_stat"]]<br>"
|
||||
else
|
||||
dat += "<b>Record Lost!</b><br>"
|
||||
|
||||
dat += "<br>"
|
||||
|
||||
dat += "<h4>Medical Data</h4>"
|
||||
if (istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2))
|
||||
dat += "Blood Type: [src.active2.fields["b_type"]]<br><br>"
|
||||
|
||||
dat += "Minor Disabilities: [src.active2.fields["mi_dis"]]<br>"
|
||||
dat += "Details: [src.active2.fields["mi_dis_d"]]<br><br>"
|
||||
|
||||
dat += "Major Disabilities: [src.active2.fields["ma_dis"]]<br>"
|
||||
dat += "Details: [src.active2.fields["ma_dis_d"]]<br><br>"
|
||||
|
||||
dat += "Allergies: [src.active2.fields["alg"]]<br>"
|
||||
dat += "Details: [src.active2.fields["alg_d"]]<br><br>"
|
||||
|
||||
dat += "Current Diseases: [src.active2.fields["cdi"]]<br>"
|
||||
dat += "Details: [src.active2.fields["cdi_d"]]<br><br>"
|
||||
|
||||
dat += "Important Notes: [src.active2.fields["notes"]]<br>"
|
||||
else
|
||||
dat += "<b>Record Lost!</b><br>"
|
||||
|
||||
dat += "<br>"
|
||||
|
||||
return dat
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["mode"])
|
||||
var/newmode = text2num(href_list["mode"])
|
||||
src.mode = max(newmode, 0)
|
||||
|
||||
else if(href_list["select_rec"])
|
||||
var/datum/data/record/R = locate(href_list["select_rec"])
|
||||
var/datum/data/record/M = locate(href_list["select_rec"])
|
||||
|
||||
if (data_core.general.Find(R))
|
||||
for (var/datum/data/record/E in data_core.medical)
|
||||
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
|
||||
M = E
|
||||
break
|
||||
|
||||
src.active1 = R
|
||||
src.active2 = M
|
||||
|
||||
src.mode = 1
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateSelfDialog()
|
||||
return
|
||||
@@ -0,0 +1,101 @@
|
||||
//CONTENTS:
|
||||
//Base scanner stuff
|
||||
//Health scanner
|
||||
//Forensic scanner
|
||||
//Reagent scanner
|
||||
|
||||
/datum/computer/file/pda_program/scan
|
||||
return_text()
|
||||
return src.return_text_header()
|
||||
|
||||
proc/scan_atom(atom/A as mob|obj|turf|area)
|
||||
|
||||
if( !A || (!src.holder) || (!src.master))
|
||||
return 1
|
||||
|
||||
if((!istype(holder)) || (!istype(master)))
|
||||
return 1
|
||||
|
||||
if(!(holder in src.master.contents))
|
||||
if(master.scan_program == src)
|
||||
master.scan_program = null
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
//Health analyzer program
|
||||
health_scan
|
||||
name = "Health Scan"
|
||||
size = 8.0
|
||||
|
||||
scan_atom(atom/A as mob|obj|turf|area)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/mob/living/carbon/C = A
|
||||
if(!istype(C))
|
||||
return
|
||||
|
||||
var/dat = "\blue Analyzing Results for [C]:\n"
|
||||
dat += "\blue \t Overall Status: [C.stat > 1 ? "dead" : "[C.health]% healthy"]\n"
|
||||
dat += "\blue \t Damage Specifics: [C.oxyloss > 50 ? "\red" : "\blue"][C.oxyloss]-[C.toxloss > 50 ? "\red" : "\blue"][C.toxloss]-[C.fireloss > 50 ? "\red" : "\blue"][C.fireloss]-[C.bruteloss > 50 ? "\red" : "\blue"][C.bruteloss]\n"
|
||||
dat += "\blue \t Key: Suffocation/Toxin/Burns/Brute\n"
|
||||
dat += "\blue \t Body Temperature: [C.bodytemperature-T0C]°C ([C.bodytemperature*1.8-459.67]°F)"
|
||||
if(C.virus)
|
||||
dat += "\red \n<b>Warning Virus Detected.</b>\nName: [C.virus.name].\nType: [C.virus.spread].\nStage: [C.virus.stage]/[C.virus.max_stages].\nPossible Cure: [C.virus.cure]"
|
||||
|
||||
return dat
|
||||
|
||||
//Forensic scanner
|
||||
forensic_scan
|
||||
name = "Forensic Scan"
|
||||
size = 8.0
|
||||
|
||||
scan_atom(atom/A as mob|obj|turf|area)
|
||||
if(..())
|
||||
return
|
||||
var/dat = null
|
||||
|
||||
if(istype(A,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = A
|
||||
if (!istype(H.dna, /datum/dna) || !isnull(H.gloves))
|
||||
dat += "\blue Unable to scan [A]'s fingerprints.\n"
|
||||
else
|
||||
dat += "\blue [H]'s Fingerprints: [md5(H.dna.uni_identity)]\n"
|
||||
if ( !(H.blood_DNA) )
|
||||
dat += "\blue No blood found on [H]\n"
|
||||
else
|
||||
dat += "\blue Blood type: [H.blood_type]\nDNA: [H.blood_DNA]\n"
|
||||
|
||||
if (!A.fingerprints)
|
||||
dat += "\blue Unable to locate any fingerprints on [A]!\n"
|
||||
else
|
||||
var/list/L = params2list(A:fingerprints)
|
||||
dat += "\blue Isolated [L.len] fingerprints.\n"
|
||||
for(var/i in L)
|
||||
dat += "\blue \t [i]\n"
|
||||
|
||||
return dat
|
||||
|
||||
|
||||
//Reagent scanning program
|
||||
reagent_scan
|
||||
name = "Reagent Scan"
|
||||
size = 6.0
|
||||
|
||||
scan_atom(atom/A as mob|obj|turf|area)
|
||||
if(..())
|
||||
return
|
||||
var/dat = null
|
||||
if(!isnull(A.reagents))
|
||||
if(A.reagents.reagent_list.len > 0)
|
||||
var/reagents_length = A.reagents.reagent_list.len
|
||||
dat += "\blue [reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found.\n"
|
||||
for (var/datum/reagent/re in A.reagents.reagent_list)
|
||||
dat += "\blue \t [re] - [re.volume]\n"
|
||||
else
|
||||
dat = "\blue No active chemical agents found in [A]."
|
||||
else
|
||||
dat = "\blue No significant chemical agents found in [A]."
|
||||
|
||||
return dat
|
||||
@@ -0,0 +1,204 @@
|
||||
//Assorted small programs not worthy of their own file
|
||||
//CONTENTS:
|
||||
//Crew Manifest viewer
|
||||
//Status display controller
|
||||
//Remote signaling program
|
||||
//Cargo orders monitor
|
||||
|
||||
//Manifest
|
||||
/datum/computer/file/pda_program/manifest
|
||||
name = "Manifest"
|
||||
|
||||
return_text()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/dat = src.return_text_header()
|
||||
|
||||
dat += "<h4>Crew Manifest</h4>"
|
||||
dat += "Entries cannot be modified from this terminal.<br><br>"
|
||||
|
||||
for (var/datum/data/record/t in data_core.general)
|
||||
dat += "[t.fields["name"]] - [t.fields["rank"]]<br>"
|
||||
dat += "<br>"
|
||||
|
||||
return dat
|
||||
|
||||
//Status Display
|
||||
/datum/computer/file/pda_program/status_display
|
||||
name = "Status Controller"
|
||||
size = 8.0
|
||||
var/message1 // For custom messages on the displays.
|
||||
var/message2
|
||||
|
||||
return_text()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/dat = src.return_text_header()
|
||||
|
||||
dat += "<h4>Station Status Display Interlink</h4>"
|
||||
|
||||
dat += "\[ <A HREF='?src=\ref[src];statdisp=blank'>Clear</A> \]<BR>"
|
||||
dat += "\[ <A HREF='?src=\ref[src];statdisp=shuttle'>Shuttle ETA</A> \]<BR>"
|
||||
dat += "\[ <A HREF='?src=\ref[src];statdisp=message'>Message</A> \]"
|
||||
|
||||
dat += "<ul><li> Line 1: <A HREF='?src=\ref[src];statdisp=setmsg1'>[ message1 ? message1 : "(none)"]</A>"
|
||||
dat += "<li> Line 2: <A HREF='?src=\ref[src];statdisp=setmsg2'>[ message2 ? message2 : "(none)"]</A></ul><br>"
|
||||
dat += "\[ Alert: <A HREF='?src=\ref[src];statdisp=alert;alert=default'>None</A> |"
|
||||
|
||||
dat += " <A HREF='?src=\ref[src];statdisp=alert;alert=redalert'>Red Alert</A> |"
|
||||
dat += " <A HREF='?src=\ref[src];statdisp=alert;alert=lockdown'>Lockdown</A> |"
|
||||
dat += " <A HREF='?src=\ref[src];statdisp=alert;alert=biohazard'>Biohazard</A> \]<BR>"
|
||||
|
||||
return dat
|
||||
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["statdisp"])
|
||||
switch(href_list["statdisp"])
|
||||
if("message")
|
||||
post_status("message", message1, message2)
|
||||
if("alert")
|
||||
post_status("alert", href_list["alert"])
|
||||
|
||||
if("setmsg1")
|
||||
message1 = input("Line 1", "Enter Message Text", message1) as text|null
|
||||
if (!src.master || !in_range(src.master, usr) && src.master.loc != usr)
|
||||
return
|
||||
|
||||
if(!(src.holder in src.master))
|
||||
return
|
||||
src.master.updateSelfDialog()
|
||||
|
||||
if("setmsg2")
|
||||
message2 = input("Line 2", "Enter Message Text", message2) as text|null
|
||||
if (!src.master || !in_range(src.master, usr) && src.master.loc != usr)
|
||||
return
|
||||
|
||||
if(!(src.holder in src.master))
|
||||
return
|
||||
|
||||
src.master.updateSelfDialog()
|
||||
else
|
||||
post_status(href_list["statdisp"])
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateSelfDialog()
|
||||
return
|
||||
|
||||
proc/post_status(var/command, var/data1, var/data2)
|
||||
if(!src.master)
|
||||
return
|
||||
|
||||
var/datum/signal/status_signal = new
|
||||
status_signal.source = src.master
|
||||
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
|
||||
|
||||
src.post_signal(status_signal,"1435")
|
||||
|
||||
//Signaler
|
||||
/datum/computer/file/pda_program/signaler
|
||||
name = "Signalix 5"
|
||||
size = 8.0
|
||||
var/send_freq = 1457 //Frequency signal is sent at, should be kept within normal radio ranges.
|
||||
var/send_code = 30
|
||||
var/last_transmission = 0 //No signal spamming etc
|
||||
|
||||
return_text()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/dat = src.return_text_header()
|
||||
|
||||
dat += "<h4>Remote Signaling System</h4>"
|
||||
dat += {"
|
||||
<a href='byond://?src=\ref[src];send=1'>Send Signal</A><BR>
|
||||
|
||||
Frequency:
|
||||
<a href='byond://?src=\ref[src];adj_freq=-10'>-</a>
|
||||
<a href='byond://?src=\ref[src];adj_freq=-2'>-</a>
|
||||
[format_frequency(send_freq)]
|
||||
<a href='byond://?src=\ref[src];adj_freq=2'>+</a>
|
||||
<a href='byond://?src=\ref[src];adj_freq=10'>+</a><br>
|
||||
<br>
|
||||
Code:
|
||||
<a href='byond://?src=\ref[src];adj_code=-5'>-</a>
|
||||
<a href='byond://?src=\ref[src];adj_code=-1'>-</a>
|
||||
[send_code]
|
||||
<a href='byond://?src=\ref[src];adj_code=1'>+</a>
|
||||
<a href='byond://?src=\ref[src];adj_code=5'>+</a><br>"}
|
||||
|
||||
return dat
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if (href_list["send"])
|
||||
if(last_transmission && world.time < (last_transmission + 5))
|
||||
return
|
||||
last_transmission = world.time
|
||||
spawn( 0 )
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
lastsignalers.Add("[time] <B>:</B> [usr.key] used [src.master] @ location ([src.master.loc.x],[src.master.loc.y],[src.master.loc.z]) <B>:</B> [format_frequency(send_freq)]/[send_code]")
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.source = src
|
||||
signal.encryption = send_code
|
||||
signal.data["message"] = "ACTIVATE"
|
||||
|
||||
src.post_signal(signal,"[send_freq]")
|
||||
return
|
||||
|
||||
else if (href_list["adj_freq"])
|
||||
src.send_freq = sanitize_frequency(src.send_freq + text2num(href_list["adj_freq"]))
|
||||
|
||||
else if (href_list["adj_code"])
|
||||
src.send_code += text2num(href_list["adj_code"])
|
||||
src.send_code = round(src.send_code)
|
||||
src.send_code = min(100, src.send_code)
|
||||
src.send_code = max(1, src.send_code)
|
||||
|
||||
src.master.add_fingerprint(usr)
|
||||
src.master.updateSelfDialog()
|
||||
return
|
||||
|
||||
//Supply record monitor
|
||||
/datum/computer/file/pda_program/qm_records
|
||||
name = "Supply Records"
|
||||
size = 8.0
|
||||
|
||||
return_text()
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/dat = src.return_text_header()
|
||||
dat += "<h4>Supply Record Interlink</h4>"
|
||||
|
||||
dat += "<BR><B>Supply shuttle</B><BR>"
|
||||
dat += "Location: [supply_shuttle_moving ? "Moving to station ([supply_shuttle_timeleft] Mins.)":supply_shuttle_at_station ? "Station":"Dock"]<BR>"
|
||||
dat += "Current approved orders: <BR><ol>"
|
||||
for(var/S in supply_shuttle_shoppinglist)
|
||||
var/datum/supply_order/SO = S
|
||||
dat += "<li>[SO.object.name] approved by [SO.orderedby] [SO.comment ? "([SO.comment])":""]</li>"
|
||||
dat += "</ol>"
|
||||
|
||||
dat += "Current requests: <BR><ol>"
|
||||
for(var/S in supply_shuttle_requestlist)
|
||||
var/datum/supply_order/SO = S
|
||||
dat += "<li>[SO.object.name] requested by [SO.orderedby]</li>"
|
||||
dat += "</ol><font size=\"-3\">Upgrade NOW to Space Parts & Space Vendors PLUS for full remote order control and inventory management."
|
||||
|
||||
return dat
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
/obj/plant
|
||||
name = "plant"
|
||||
icon = 'plants.dmi'
|
||||
flags = FPRINT | TABLEPASS
|
||||
var/health = 100
|
||||
var/bruteloss = 0
|
||||
var/toxloss = 0
|
||||
var/generation = 1
|
||||
var/life_stage = 0
|
||||
var/datum/disease/virus = null
|
||||
|
||||
/obj/item/seedpacket
|
||||
name = "seed packet"
|
||||
icon = 'plants.dmi'
|
||||
icon_state = "packet"
|
||||
flags = FPRINT | TABLEPASS
|
||||
*/
|
||||
@@ -0,0 +1,389 @@
|
||||
// converyor belt
|
||||
|
||||
// moves items/mobs/movables in set direction every ptick
|
||||
|
||||
|
||||
/obj/machinery/conveyor
|
||||
icon = 'recycling.dmi'
|
||||
icon_state = "conveyor0"
|
||||
name = "conveyor belt"
|
||||
desc = "A conveyor belt."
|
||||
anchored = 1
|
||||
var/operating = 0 // 1 if running forward, -1 if backwards, 0 if off
|
||||
var/operable = 1 // true if can operate (no broken segments in this belt run)
|
||||
var/basedir // this is the default (forward) direction, set by the map dir
|
||||
// note dir var can vary when the direction changes
|
||||
|
||||
var/list/affecting // the list of all items that will be moved this ptick
|
||||
var/id = "" // the control ID - must match controller ID
|
||||
// following two only used if a diverter is present
|
||||
var/divert = 0 // if non-zero, direction to divert items
|
||||
var/divdir = 0 // if diverting, will be conveyer dir needed to divert (otherwise dense)
|
||||
|
||||
|
||||
|
||||
// create a conveyor
|
||||
|
||||
/obj/machinery/conveyor/New()
|
||||
..()
|
||||
basedir = dir
|
||||
setdir()
|
||||
|
||||
// set the dir and target turf depending on the operating direction
|
||||
|
||||
/obj/machinery/conveyor/proc/setdir()
|
||||
if(operating == -1)
|
||||
dir = turn(basedir,180)
|
||||
else
|
||||
dir = basedir
|
||||
update()
|
||||
|
||||
|
||||
// update the icon depending on the operating condition
|
||||
|
||||
/obj/machinery/conveyor/proc/update()
|
||||
if(stat & BROKEN)
|
||||
icon_state = "conveyor-b"
|
||||
operating = 0
|
||||
return
|
||||
if(!operable)
|
||||
operating = 0
|
||||
icon_state = "conveyor[(operating != 0) && !(stat & NOPOWER)]"
|
||||
|
||||
|
||||
// machine process
|
||||
// move items to the target location
|
||||
/obj/machinery/conveyor/process()
|
||||
if(stat & (BROKEN | NOPOWER))
|
||||
return
|
||||
if(!operating)
|
||||
return
|
||||
use_power(100)
|
||||
|
||||
var/movedir = dir // base movement dir
|
||||
if(divert && dir==divdir) // update if diverter present
|
||||
movedir = divert
|
||||
|
||||
|
||||
affecting = loc.contents - src // moved items will be all in loc
|
||||
spawn(1) // slight delay to prevent infinite propagation due to map order
|
||||
for(var/atom/movable/A in affecting)
|
||||
if(!A.anchored)
|
||||
if(ismob(A))
|
||||
var/mob/M = A
|
||||
if(M.buckled == src)
|
||||
var/obj/machinery/conveyor/C = locate() in get_step(src, dir)
|
||||
M.buckled = null
|
||||
step(M,dir)
|
||||
if(C)
|
||||
M.buckled = C
|
||||
else
|
||||
new/obj/item/weapon/cable_coil/cut(M.loc)
|
||||
else
|
||||
step(M,movedir)
|
||||
else
|
||||
step(A,movedir)
|
||||
|
||||
// attack with item, place item on conveyor
|
||||
|
||||
/obj/machinery/conveyor/attackby(var/obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/weapon/grab)) // special handling if grabbing a mob
|
||||
var/obj/item/weapon/grab/G = I
|
||||
G.affecting.Move(src.loc)
|
||||
del(G)
|
||||
return
|
||||
else if(istype(I, /obj/item/weapon/cable_coil)) // if cable, see if a mob is present
|
||||
var/mob/M = locate() in src.loc
|
||||
if(M)
|
||||
if (M == user)
|
||||
src.visible_message("\blue [M] ties \himself to the conveyor.")
|
||||
// note don't check for lying if self-tying
|
||||
else
|
||||
if(M.lying)
|
||||
user.visible_message("\blue [M] has been tied to the conveyor by [user].", "\blue You tie [M] to the converyor!")
|
||||
else
|
||||
user << "\blue [M] must be lying down to be tied to the converyor!"
|
||||
return
|
||||
M.buckled = src
|
||||
src.add_fingerprint(user)
|
||||
I:use(1)
|
||||
M.lying = 1
|
||||
return
|
||||
|
||||
// else if no mob in loc, then allow coil to be placed
|
||||
|
||||
else if(istype(I, /obj/item/weapon/wirecutters))
|
||||
var/mob/M = locate() in src.loc
|
||||
if(M && M.buckled == src)
|
||||
M.buckled = null
|
||||
src.add_fingerprint(user)
|
||||
if (M == user)
|
||||
src.visible_message("\blue [M] cuts \himself free from the conveyor.")
|
||||
else
|
||||
src.visible_message("\blue [M] had been cut free from the conveyor by [user].")
|
||||
return
|
||||
// otherwise drop and place on conveyor
|
||||
user.drop_item()
|
||||
if(I && I.loc) I.loc = src.loc
|
||||
return
|
||||
|
||||
// attack with hand, move pulled object onto conveyor
|
||||
|
||||
/obj/machinery/conveyor/attack_hand(mob/user as mob)
|
||||
if ((!( user.canmove ) || user.restrained() || !( user.pulling )))
|
||||
return
|
||||
if (user.pulling.anchored)
|
||||
return
|
||||
if ((user.pulling.loc != user.loc && get_dist(user, user.pulling) > 1))
|
||||
return
|
||||
if (ismob(user.pulling))
|
||||
var/mob/M = user.pulling
|
||||
M.pulling = null
|
||||
step(user.pulling, get_dir(user.pulling.loc, src))
|
||||
user.pulling = null
|
||||
else
|
||||
step(user.pulling, get_dir(user.pulling.loc, src))
|
||||
user.pulling = null
|
||||
return
|
||||
|
||||
|
||||
// make the conveyor broken
|
||||
// also propagate inoperability to any connected conveyor with the same ID
|
||||
/obj/machinery/conveyor/proc/broken()
|
||||
stat |= BROKEN
|
||||
update()
|
||||
|
||||
var/obj/machinery/conveyor/C = locate() in get_step(src, basedir)
|
||||
if(C)
|
||||
C.set_operable(basedir, id, 0)
|
||||
|
||||
C = locate() in get_step(src, turn(basedir,180))
|
||||
if(C)
|
||||
C.set_operable(turn(basedir,180), id, 0)
|
||||
|
||||
|
||||
//set the operable var if ID matches, propagating in the given direction
|
||||
|
||||
/obj/machinery/conveyor/proc/set_operable(stepdir, match_id, op)
|
||||
|
||||
if(id != match_id)
|
||||
return
|
||||
operable = op
|
||||
|
||||
update()
|
||||
var/obj/machinery/conveyor/C = locate() in get_step(src, stepdir)
|
||||
if(C)
|
||||
C.set_operable(stepdir, id, op)
|
||||
|
||||
/*
|
||||
/obj/machinery/conveyor/verb/destroy()
|
||||
set src in view()
|
||||
src.broken()
|
||||
*/
|
||||
|
||||
/obj/machinery/conveyor/power_change()
|
||||
..()
|
||||
update()
|
||||
|
||||
|
||||
// converyor diverter
|
||||
// extendable arm that can be switched so items on the conveyer are diverted sideways
|
||||
// situate in same turf as conveyor
|
||||
// only works if belts is running proper direction
|
||||
//
|
||||
//
|
||||
/obj/machinery/diverter
|
||||
icon = 'recycling.dmi'
|
||||
icon_state = "diverter0"
|
||||
name = "diverter"
|
||||
desc = "A diverter arm for a conveyor belt."
|
||||
anchored = 1
|
||||
layer = FLY_LAYER
|
||||
var/obj/machinery/conveyor/conv // the conveyor this diverter works on
|
||||
var/deployed = 0 // true if diverter arm is extended
|
||||
var/operating = 0 // true if arm is extending/contracting
|
||||
var/divert_to // the dir that diverted items will be moved
|
||||
var/divert_from // the dir items must be moving to divert
|
||||
|
||||
|
||||
// create a diverter
|
||||
// set up divert_to and divert_from directions depending on dir state
|
||||
/obj/machinery/diverter/New()
|
||||
|
||||
..()
|
||||
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
divert_to = WEST // stuff will be moved to the west
|
||||
divert_from = NORTH // if entering from the north
|
||||
if(SOUTH)
|
||||
divert_to = EAST
|
||||
divert_from = NORTH
|
||||
if(EAST)
|
||||
divert_to = EAST
|
||||
divert_from = SOUTH
|
||||
if(WEST)
|
||||
divert_to = WEST
|
||||
divert_from = SOUTH
|
||||
if(NORTHEAST)
|
||||
divert_to = NORTH
|
||||
divert_from = EAST
|
||||
if(NORTHWEST)
|
||||
divert_to = NORTH
|
||||
divert_from = WEST
|
||||
if(SOUTHEAST)
|
||||
divert_to = SOUTH
|
||||
divert_from = EAST
|
||||
if(SOUTHWEST)
|
||||
divert_to = SOUTH
|
||||
divert_from = WEST
|
||||
spawn(2)
|
||||
// wait for map load then find the conveyor in this turf
|
||||
conv = locate() in src.loc
|
||||
if(conv) // divert_from dir must match possible conveyor movement
|
||||
if(conv.basedir != divert_from && conv.basedir != turn(divert_from,180) )
|
||||
del(src) // if no dir match, then delete self
|
||||
set_divert()
|
||||
update()
|
||||
|
||||
// update the icon state depending on whether the diverter is extended
|
||||
/obj/machinery/diverter/proc/update()
|
||||
icon_state = "diverter[deployed]"
|
||||
|
||||
// call to set the diversion vars of underlying conveyor
|
||||
/obj/machinery/diverter/proc/set_divert()
|
||||
if(conv)
|
||||
if(deployed)
|
||||
conv.divert = divert_to
|
||||
conv.divdir = divert_from
|
||||
else
|
||||
conv.divert= 0
|
||||
|
||||
|
||||
// *** TESTING click to toggle
|
||||
/obj/machinery/diverter/Click()
|
||||
toggle()
|
||||
|
||||
|
||||
// toggle between arm deployed and not deployed, showing animation
|
||||
//
|
||||
/obj/machinery/diverter/proc/toggle()
|
||||
if( stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(operating)
|
||||
return
|
||||
|
||||
use_power(50)
|
||||
operating = 1
|
||||
if(deployed)
|
||||
flick("diverter10",src)
|
||||
icon_state = "diverter0"
|
||||
sleep(10)
|
||||
deployed = 0
|
||||
else
|
||||
flick("diverter01",src)
|
||||
icon_state = "diverter1"
|
||||
sleep(10)
|
||||
deployed = 1
|
||||
operating = 0
|
||||
update()
|
||||
set_divert()
|
||||
|
||||
// don't allow movement into the 'backwards' direction if deployed
|
||||
/obj/machinery/diverter/CanPass(atom/movable/O, var/turf/target)
|
||||
var/direct = get_dir(O, target)
|
||||
if(direct == divert_to) // prevent movement through body of diverter
|
||||
return 0
|
||||
if(!deployed)
|
||||
return 1
|
||||
return(direct != turn(divert_from,180))
|
||||
|
||||
// don't allow movement through the arm if deployed
|
||||
/obj/machinery/diverter/CheckExit(atom/movable/O, var/turf/target)
|
||||
var/direct = get_dir(O, target)
|
||||
if(direct == turn(divert_to,180)) // prevent movement through body of diverter
|
||||
return 0
|
||||
if(!deployed)
|
||||
return 1
|
||||
return(direct != divert_from)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// the conveyor control switch
|
||||
//
|
||||
//
|
||||
|
||||
/obj/machinery/conveyor_switch
|
||||
|
||||
name = "conveyor switch"
|
||||
desc = "A conveyor control switch."
|
||||
icon = 'recycling.dmi'
|
||||
icon_state = "switch-off"
|
||||
var/position = 0 // 0 off, -1 reverse, 1 forward
|
||||
var/last_pos = -1 // last direction setting
|
||||
var/operated = 1 // true if just operated
|
||||
|
||||
var/id = "" // must match conveyor IDs to control them
|
||||
|
||||
var/list/conveyors // the list of converyors that are controlled by this switch
|
||||
anchored = 1
|
||||
|
||||
|
||||
|
||||
/obj/machinery/conveyor_switch/New()
|
||||
..()
|
||||
update()
|
||||
|
||||
spawn(5) // allow map load
|
||||
conveyors = list()
|
||||
for(var/obj/machinery/conveyor/C in world)
|
||||
if(C.id == id)
|
||||
conveyors += C
|
||||
|
||||
// update the icon depending on the position
|
||||
|
||||
/obj/machinery/conveyor_switch/proc/update()
|
||||
if(position<0)
|
||||
icon_state = "switch-rev"
|
||||
else if(position>0)
|
||||
icon_state = "switch-fwd"
|
||||
else
|
||||
icon_state = "switch-off"
|
||||
|
||||
|
||||
// timed process
|
||||
// if the switch changed, update the linked conveyors
|
||||
|
||||
/obj/machinery/conveyor_switch/process()
|
||||
if(!operated)
|
||||
return
|
||||
operated = 0
|
||||
|
||||
for(var/obj/machinery/conveyor/C in conveyors)
|
||||
C.operating = position
|
||||
C.setdir()
|
||||
|
||||
// attack with hand, switch position
|
||||
/obj/machinery/conveyor_switch/attack_hand(mob/user)
|
||||
if(position == 0)
|
||||
if(last_pos < 0)
|
||||
position = 1
|
||||
last_pos = 0
|
||||
else
|
||||
position = -1
|
||||
last_pos = 0
|
||||
else
|
||||
last_pos = position
|
||||
position = 0
|
||||
|
||||
operated = 1
|
||||
update()
|
||||
|
||||
// find any switches with same id as this one, and set their positions to match us
|
||||
for(var/obj/machinery/conveyor_switch/S in world)
|
||||
if(S.id == src.id)
|
||||
S.position = position
|
||||
S.update()
|
||||
@@ -0,0 +1,162 @@
|
||||
// Disposal pipe construction
|
||||
|
||||
/obj/disposalconstruct
|
||||
|
||||
name = "disposal pipe segment"
|
||||
desc = "A huge pipe segment used for constructing disposal systems."
|
||||
icon = 'disposal.dmi'
|
||||
icon_state = "conpipe-s"
|
||||
anchored = 0
|
||||
density = 1
|
||||
pressure_resistance = 5*ONE_ATMOSPHERE
|
||||
m_amt = 1850
|
||||
level = 2
|
||||
var/ptype = 0
|
||||
// 0=straight, 1=bent, 2=junction-j1, 3=junction-j2, 4=junction-y, 5=trunk
|
||||
|
||||
var/dpdir = 0 // directions as disposalpipe
|
||||
var/base_state = "pipe-s"
|
||||
|
||||
// update iconstate and dpdir due to dir and type
|
||||
proc/update()
|
||||
var/flip = turn(dir, 180)
|
||||
var/left = turn(dir, 90)
|
||||
var/right = turn(dir, -90)
|
||||
|
||||
switch(ptype)
|
||||
if(0)
|
||||
base_state = "pipe-s"
|
||||
dpdir = dir | flip
|
||||
if(1)
|
||||
base_state = "pipe-c"
|
||||
dpdir = dir | right
|
||||
if(2)
|
||||
base_state = "pipe-j1"
|
||||
dpdir = dir | right | flip
|
||||
if(3)
|
||||
base_state = "pipe-j2"
|
||||
dpdir = dir | left | flip
|
||||
if(4)
|
||||
base_state = "pipe-y"
|
||||
dpdir = dir | left | right
|
||||
if(5)
|
||||
base_state = "pipe-t"
|
||||
dpdir = dir
|
||||
|
||||
|
||||
icon_state = "con[base_state]"
|
||||
|
||||
if(invisibility) // if invisible, fade icon
|
||||
icon -= rgb(0,0,0,128)
|
||||
|
||||
// hide called by levelupdate if turf intact status changes
|
||||
// change visibility status and force update of icon
|
||||
hide(var/intact)
|
||||
invisibility = (intact && level==1) ? 101: 0 // hide if floor is intact
|
||||
update()
|
||||
|
||||
|
||||
// flip and rotate verbs
|
||||
verb/rotate()
|
||||
set src in view(1)
|
||||
|
||||
if(usr.stat)
|
||||
return
|
||||
if(anchored)
|
||||
usr << "You must unfasten the pipe before rotating it."
|
||||
dir = turn(dir, -90)
|
||||
update()
|
||||
|
||||
verb/flip()
|
||||
set src in view(1)
|
||||
if(usr.stat)
|
||||
return
|
||||
|
||||
if(anchored)
|
||||
usr << "You must unfasten the pipe before flipping it."
|
||||
|
||||
dir = turn(dir, 180)
|
||||
if(ptype == 2)
|
||||
ptype = 3
|
||||
else if(ptype == 3)
|
||||
ptype = 2
|
||||
update()
|
||||
|
||||
// returns the type path of disposalpipe corresponding to this item dtype
|
||||
proc/dpipetype()
|
||||
switch(ptype)
|
||||
if(0,1)
|
||||
return /obj/disposalpipe/segment
|
||||
if(2,3,4)
|
||||
return /obj/disposalpipe/junction
|
||||
if(5)
|
||||
return /obj/disposalpipe/trunk
|
||||
return
|
||||
|
||||
|
||||
|
||||
// attackby item
|
||||
// wrench: (un)anchor
|
||||
// weldingtool: convert to real pipe
|
||||
|
||||
attackby(var/obj/item/I, var/mob/user)
|
||||
var/turf/T = src.loc
|
||||
if(T.intact)
|
||||
user << "You can only attach the pipe if the floor plating is removed."
|
||||
return
|
||||
|
||||
var/obj/disposalpipe/CP = locate() in T
|
||||
if(CP)
|
||||
update()
|
||||
var/pdir = CP.dpdir
|
||||
if(istype(CP, /obj/disposalpipe/broken))
|
||||
pdir = CP.dir
|
||||
if(pdir & dpdir)
|
||||
user << "There is already a pipe at that location."
|
||||
return
|
||||
|
||||
if(istype(I, /obj/item/weapon/wrench))
|
||||
if(anchored)
|
||||
anchored = 0
|
||||
level = 2
|
||||
density = 1
|
||||
user << "You detach the pipe from the underfloor."
|
||||
else
|
||||
anchored = 1
|
||||
level = 1
|
||||
density = 0
|
||||
user << "You attach the pipe to the underfloor."
|
||||
playsound(src.loc, 'Ratchet.ogg', 100, 1)
|
||||
|
||||
else if(istype(I, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/W = I
|
||||
if(W.welding)
|
||||
if(W.get_fuel() > 2)
|
||||
W.use_fuel(2)
|
||||
playsound(src.loc, 'Welder2.ogg', 100, 1)
|
||||
|
||||
// check if anything changed over 2 seconds
|
||||
var/turf/uloc = user.loc
|
||||
var/atom/wloc = W.loc
|
||||
user << "Welding the pipe in place."
|
||||
sleep(20)
|
||||
if(user.loc == uloc && wloc == W.loc)
|
||||
|
||||
update()
|
||||
var/pipetype = dpipetype()
|
||||
var/obj/disposalpipe/P = new pipetype(src.loc)
|
||||
P.base_icon_state = base_state
|
||||
P.dir = dir
|
||||
P.dpdir = dpdir
|
||||
P.updateicon()
|
||||
|
||||
del(src)
|
||||
else
|
||||
user << "You must stay still while welding."
|
||||
return
|
||||
|
||||
|
||||
|
||||
else
|
||||
user << "You need more welding fuel to complete this task."
|
||||
return
|
||||
@@ -0,0 +1,936 @@
|
||||
// Disposal bin
|
||||
// Holds items for disposal into pipe system
|
||||
// Draws air from turf, gradually charges internal reservoir
|
||||
// Once full (~1 atm), uses air resv to flush items into the pipes
|
||||
// Automatically recharges air (unless off), will flush when ready if pre-set
|
||||
// Can hold items and human size things, no other draggables
|
||||
|
||||
/obj/machinery/disposal
|
||||
name = "disposal unit"
|
||||
desc = "A pneumatic waste disposal unit."
|
||||
icon = 'disposal.dmi'
|
||||
icon_state = "disposal"
|
||||
anchored = 1
|
||||
density = 1
|
||||
var/datum/gas_mixture/air_contents // internal reservoir
|
||||
var/mode = 1 // item mode 0=off 1=charging 2=charged
|
||||
var/flush = 0 // true if flush handle is pulled
|
||||
var/obj/disposalpipe/trunk/trunk = null // the attached pipe trunk
|
||||
var/flushing = 0 // true if flushing in progress
|
||||
|
||||
// create a new disposal
|
||||
// find the attached trunk (if present) and init gas resvr.
|
||||
New()
|
||||
..()
|
||||
spawn(5)
|
||||
trunk = locate() in src.loc
|
||||
if(!trunk)
|
||||
mode = 0
|
||||
flush = 0
|
||||
else
|
||||
trunk.linked = src // link the pipe trunk to self
|
||||
|
||||
air_contents = new/datum/gas_mixture()
|
||||
//gas.volume = 1.05 * CELLSTANDARD
|
||||
update()
|
||||
|
||||
|
||||
// attack by item places it in to disposal
|
||||
attackby(var/obj/item/I, var/mob/user)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
var/obj/item/weapon/grab/G = I
|
||||
if(istype(G)) // handle grabbed mob
|
||||
if(ismob(G.affecting))
|
||||
var/mob/GM = G.affecting
|
||||
if (GM.client)
|
||||
GM.client.perspective = EYE_PERSPECTIVE
|
||||
GM.client.eye = src
|
||||
GM.loc = src
|
||||
for (var/mob/C in viewers(src))
|
||||
C.show_message("\red [GM.name] has been placed in the [src] by [user].", 3)
|
||||
del(G)
|
||||
|
||||
|
||||
else
|
||||
user.drop_item()
|
||||
I.loc = src
|
||||
user << "You place \the [I] into the [src]."
|
||||
for(var/mob/M in viewers(src))
|
||||
if(M == user)
|
||||
continue
|
||||
M.show_message("[user.name] places \the [I] into the [src].", 3)
|
||||
|
||||
update()
|
||||
|
||||
// mouse drop another mob or self
|
||||
//
|
||||
MouseDrop_T(mob/target, mob/user)
|
||||
if (!istype(target) || target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || istype(user, /mob/living/silicon/ai))
|
||||
return
|
||||
|
||||
var/msg
|
||||
|
||||
if(target == user && !user.stat) // if drop self, then climbed in
|
||||
// must be awake
|
||||
msg = "[user.name] climbs into the [src]."
|
||||
user << "You climb into the [src]."
|
||||
else if(target != user && !user.restrained())
|
||||
msg = "[user.name] stuffs [target.name] into the [src]!"
|
||||
user << "You stuff [target.name] into the [src]!"
|
||||
else
|
||||
return
|
||||
if (target.client)
|
||||
target.client.perspective = EYE_PERSPECTIVE
|
||||
target.client.eye = src
|
||||
target.loc = src
|
||||
|
||||
for (var/mob/C in viewers(src))
|
||||
if(C == user)
|
||||
continue
|
||||
C.show_message(msg, 3)
|
||||
|
||||
update()
|
||||
return
|
||||
|
||||
// can breath normally in the disposal
|
||||
alter_health()
|
||||
return get_turf(src)
|
||||
|
||||
// attempt to move while inside
|
||||
relaymove(mob/user as mob)
|
||||
if(user.stat || src.flushing)
|
||||
return
|
||||
src.go_out(user)
|
||||
return
|
||||
|
||||
// leave the disposal
|
||||
proc/go_out(mob/user)
|
||||
|
||||
if (user.client)
|
||||
user.client.eye = user.client.mob
|
||||
user.client.perspective = MOB_PERSPECTIVE
|
||||
user.loc = src.loc
|
||||
update()
|
||||
return
|
||||
|
||||
|
||||
// monkeys can only pull the flush lever
|
||||
attack_paw(mob/user as mob)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
flush = !flush
|
||||
update()
|
||||
return
|
||||
|
||||
// ai as human but can't flush
|
||||
attack_ai(mob/user as mob)
|
||||
interact(user, 1)
|
||||
|
||||
// human interact with machine
|
||||
attack_hand(mob/user as mob)
|
||||
interact(user, 0)
|
||||
|
||||
// user interaction
|
||||
proc/interact(mob/user, var/ai=0)
|
||||
src.add_fingerprint(user)
|
||||
if(stat & BROKEN)
|
||||
user.machine = null
|
||||
return
|
||||
|
||||
var/dat = "<head><title>Waste Disposal Unit</title></head><body><TT><B>Waste Disposal Unit</B><HR>"
|
||||
|
||||
if(!ai) // AI can't pull flush handle
|
||||
if(flush)
|
||||
dat += "Disposal handle: <A href='?src=\ref[src];handle=0'>Disengage</A> <B>Engaged</B>"
|
||||
else
|
||||
dat += "Disposal handle: <B>Disengaged</B> <A href='?src=\ref[src];handle=1'>Engage</A>"
|
||||
|
||||
dat += "<BR><HR><A href='?src=\ref[src];eject=1'>Eject contents</A><HR>"
|
||||
|
||||
if(mode == 0)
|
||||
dat += "Pump: <B>Off</B> <A href='?src=\ref[src];pump=1'>On</A><BR>"
|
||||
else if(mode == 1)
|
||||
dat += "Pump: <A href='?src=\ref[src];pump=0'>Off</A> <B>On</B> (pressurizing)<BR>"
|
||||
else
|
||||
dat += "Pump: <A href='?src=\ref[src];pump=0'>Off</A> <B>On</B> (idle)<BR>"
|
||||
|
||||
var/per = 100* air_contents.return_pressure() / (2*ONE_ATMOSPHERE)
|
||||
|
||||
dat += "Pressure: [round(per, 1)]%<BR></body>"
|
||||
|
||||
|
||||
user.machine = src
|
||||
user << browse(dat, "window=disposal;size=360x170")
|
||||
onclose(user, "disposal")
|
||||
|
||||
// handle machine interaction
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
src.add_fingerprint(usr)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
if(usr.stat || usr.restrained() || src.flushing)
|
||||
return
|
||||
|
||||
if (in_range(src, usr) && istype(src.loc, /turf))
|
||||
usr.machine = src
|
||||
|
||||
if(href_list["close"])
|
||||
usr.machine = null
|
||||
usr << browse(null, "window=disposal")
|
||||
return
|
||||
|
||||
if(href_list["pump"])
|
||||
if(text2num(href_list["pump"]))
|
||||
mode = 1
|
||||
else
|
||||
mode = 0
|
||||
update()
|
||||
|
||||
if(href_list["handle"])
|
||||
flush = text2num(href_list["handle"])
|
||||
update()
|
||||
|
||||
if(href_list["eject"])
|
||||
eject()
|
||||
else
|
||||
usr << browse(null, "window=disposal")
|
||||
usr.machine = null
|
||||
return
|
||||
return
|
||||
|
||||
// eject the contents of the disposal unit
|
||||
proc/eject()
|
||||
for(var/atom/movable/AM in src)
|
||||
AM.loc = src.loc
|
||||
AM.pipe_eject(0)
|
||||
update()
|
||||
|
||||
// update the icon & overlays to reflect mode & status
|
||||
proc/update()
|
||||
overlays = null
|
||||
if(stat & BROKEN)
|
||||
icon_state = "disposal-broken"
|
||||
mode = 0
|
||||
flush = 0
|
||||
return
|
||||
|
||||
// flush handle
|
||||
if(flush)
|
||||
overlays += image('disposal.dmi', "dispover-handle")
|
||||
|
||||
// only handle is shown if no power
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
|
||||
// check for items in disposal - occupied light
|
||||
if(contents.len > 0)
|
||||
overlays += image('disposal.dmi', "dispover-full")
|
||||
|
||||
// charging and ready light
|
||||
if(mode == 1)
|
||||
overlays += image('disposal.dmi', "dispover-charge")
|
||||
else if(mode == 2)
|
||||
overlays += image('disposal.dmi', "dispover-ready")
|
||||
|
||||
// timed process
|
||||
// charge the gas reservoir and perform flush if ready
|
||||
process()
|
||||
if(stat & BROKEN) // nothing can happen if broken
|
||||
return
|
||||
|
||||
src.updateDialog()
|
||||
|
||||
if(flush && air_contents.return_pressure() >= 2*ONE_ATMOSPHERE) // flush can happen even without power
|
||||
flush()
|
||||
|
||||
if(stat & NOPOWER) // won't charge if no power
|
||||
return
|
||||
|
||||
use_power(100) // base power usage
|
||||
|
||||
if(mode != 1) // if off or ready, no need to charge
|
||||
return
|
||||
|
||||
// otherwise charge
|
||||
use_power(500) // charging power usage
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var/atom/L = loc // recharging from loc turf
|
||||
|
||||
var/datum/gas_mixture/env = L.return_air()
|
||||
var/pressure_delta = (ONE_ATMOSPHERE*2.1) - air_contents.return_pressure()
|
||||
|
||||
if(env.temperature > 0)
|
||||
var/transfer_moles = 0.1 * pressure_delta*air_contents.volume/(env.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
//Actually transfer the gas
|
||||
var/datum/gas_mixture/removed = env.remove(transfer_moles)
|
||||
air_contents.merge(removed)
|
||||
|
||||
|
||||
// if full enough, switch to ready mode
|
||||
if(air_contents.return_pressure() >= 2*ONE_ATMOSPHERE)
|
||||
mode = 2
|
||||
update()
|
||||
return
|
||||
|
||||
// perform a flush
|
||||
proc/flush()
|
||||
|
||||
flushing = 1
|
||||
flick("disposal-flush", src)
|
||||
|
||||
var/obj/disposalholder/H = new() // virtual holder object which actually
|
||||
// travels through the pipes.
|
||||
|
||||
H.init(src) // copy the contents of disposer to holder
|
||||
|
||||
air_contents = new() // new empty gas resv.
|
||||
|
||||
sleep(10)
|
||||
playsound(src, 'disposalflush.ogg', 50, 0, 0)
|
||||
sleep(5) // wait for animation to finish
|
||||
|
||||
|
||||
H.start(src) // start the holder processing movement
|
||||
flushing = 0
|
||||
// now reset disposal state
|
||||
flush = 0
|
||||
if(mode == 2) // if was ready,
|
||||
mode = 1 // switch to charging
|
||||
update()
|
||||
return
|
||||
|
||||
|
||||
// called when area power changes
|
||||
power_change()
|
||||
..() // do default setting/reset of stat NOPOWER bit
|
||||
update() // update icon
|
||||
return
|
||||
|
||||
|
||||
// called when holder is expelled from a disposal
|
||||
// should usually only occur if the pipe network is modified
|
||||
proc/expel(var/obj/disposalholder/H)
|
||||
|
||||
var/turf/target
|
||||
playsound(src, 'hiss.ogg', 50, 0, 0)
|
||||
for(var/atom/movable/AM in H)
|
||||
target = get_offset_target_turf(src.loc, rand(5)-rand(5), rand(5)-rand(5))
|
||||
|
||||
AM.loc = src.loc
|
||||
AM.pipe_eject(0)
|
||||
spawn(1)
|
||||
if(AM)
|
||||
AM.throw_at(target, 5, 1)
|
||||
|
||||
H.vent_gas(loc)
|
||||
del(H)
|
||||
|
||||
|
||||
|
||||
// virtual disposal object
|
||||
// travels through pipes in lieu of actual items
|
||||
// contents will be items flushed by the disposal
|
||||
// this allows the gas flushed to be tracked
|
||||
|
||||
/obj/disposalholder
|
||||
invisibility = 101
|
||||
var/datum/gas_mixture/gas = null // gas used to flush, will appear at exit point
|
||||
var/active = 0 // true if the holder is moving, otherwise inactive
|
||||
dir = 0
|
||||
var/count = 1000 //*** can travel 1000 steps before going inactive (in case of loops)
|
||||
var/has_fat_guy = 0 // true if contains a fat person
|
||||
|
||||
|
||||
// initialize a holder from the contents of a disposal unit
|
||||
proc/init(var/obj/machinery/disposal/D)
|
||||
gas = D.air_contents // transfer gas resv. into holder object
|
||||
|
||||
|
||||
// now everything inside the disposal gets put into the holder
|
||||
// note AM since can contain mobs or objs
|
||||
for(var/atom/movable/AM in D)
|
||||
AM.loc = src
|
||||
if(istype(AM, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = AM
|
||||
if(H.mutations & 32) // is a human and fat?
|
||||
has_fat_guy = 1 // set flag on holder
|
||||
|
||||
|
||||
|
||||
// start the movement process
|
||||
// argument is the disposal unit the holder started in
|
||||
proc/start(var/obj/machinery/disposal/D)
|
||||
if(!D.trunk)
|
||||
D.expel(src) // no trunk connected, so expel immediately
|
||||
return
|
||||
|
||||
loc = D.trunk
|
||||
active = 1
|
||||
dir = DOWN
|
||||
spawn(1)
|
||||
process() // spawn off the movement process
|
||||
|
||||
return
|
||||
|
||||
// movement process, persists while holder is moving through pipes
|
||||
proc/process()
|
||||
var/obj/disposalpipe/last
|
||||
while(active)
|
||||
if(has_fat_guy && prob(2)) // chance of becoming stuck per segment if contains a fat guy
|
||||
active = 0
|
||||
// find the fat guys
|
||||
for(var/mob/living/carbon/human/H in src)
|
||||
|
||||
break
|
||||
sleep(1) // was 1
|
||||
var/obj/disposalpipe/curr = loc
|
||||
last = curr
|
||||
curr = curr.transfer(src)
|
||||
if(!curr)
|
||||
last.expel(src, loc, dir)
|
||||
|
||||
//
|
||||
if(!(count--))
|
||||
active = 0
|
||||
return
|
||||
|
||||
|
||||
|
||||
// find the turf which should contain the next pipe
|
||||
proc/nextloc()
|
||||
return get_step(loc,dir)
|
||||
|
||||
// find a matching pipe on a turf
|
||||
proc/findpipe(var/turf/T)
|
||||
|
||||
if(!T)
|
||||
return null
|
||||
|
||||
var/fdir = turn(dir, 180) // flip the movement direction
|
||||
for(var/obj/disposalpipe/P in T)
|
||||
if(fdir & P.dpdir) // find pipe direction mask that matches flipped dir
|
||||
return P
|
||||
// if no matching pipe, return null
|
||||
return null
|
||||
|
||||
// merge two holder objects
|
||||
// used when a a holder meets a stuck holder
|
||||
proc/merge(var/obj/disposalholder/other)
|
||||
for(var/atom/movable/AM in other)
|
||||
AM.loc = src // move everything in other holder to this one
|
||||
if(ismob(AM))
|
||||
var/mob/M = AM
|
||||
if(M.client) // if a client mob, update eye to follow this holder
|
||||
M.client.eye = src
|
||||
|
||||
if(other.has_fat_guy)
|
||||
has_fat_guy = 1
|
||||
del(other)
|
||||
|
||||
|
||||
// called when player tries to move while in a pipe
|
||||
relaymove(mob/user as mob)
|
||||
if (user.stat)
|
||||
return
|
||||
|
||||
for (var/mob/M in hearers(src.loc.loc))
|
||||
M << "<FONT size=[max(0, 5 - get_dist(src, M))]>CLONG, clong!</FONT>"
|
||||
|
||||
playsound(src.loc, 'clang.ogg', 50, 0, 0)
|
||||
|
||||
// called to vent all gas in holder to a location
|
||||
proc/vent_gas(var/atom/location)
|
||||
location.assume_air(gas) // vent all gas to turf
|
||||
return
|
||||
|
||||
// Disposal pipes
|
||||
|
||||
/obj/disposalpipe
|
||||
icon = 'disposal.dmi'
|
||||
name = "disposal pipe"
|
||||
desc = "An underfloor disposal pipe."
|
||||
anchored = 1
|
||||
density = 0
|
||||
|
||||
level = 1 // underfloor only
|
||||
var/dpdir = 0 // bitmask of pipe directions
|
||||
dir = 0 // dir will contain dominant direction for junction pipes
|
||||
var/health = 10 // health points 0-10
|
||||
layer = 2.4 // slightly lower than wires
|
||||
var/base_icon_state // initial icon state on map
|
||||
|
||||
// new pipe, set the icon_state as on map
|
||||
New()
|
||||
..()
|
||||
base_icon_state = icon_state
|
||||
return
|
||||
|
||||
|
||||
// pipe is deleted
|
||||
// ensure if holder is present, it is expelled
|
||||
Del()
|
||||
var/obj/disposalholder/H = locate() in src
|
||||
if(H)
|
||||
// holder was present
|
||||
H.active = 0
|
||||
var/turf/T = src.loc
|
||||
if(T.density)
|
||||
// deleting pipe is inside a dense turf (wall)
|
||||
// this is unlikely, but just dump out everything into the turf in case
|
||||
|
||||
for(var/atom/movable/AM in H)
|
||||
AM.loc = T
|
||||
AM.pipe_eject(0)
|
||||
del(H)
|
||||
..()
|
||||
return
|
||||
|
||||
// otherswise, do normal expel from turf
|
||||
expel(H, T, 0)
|
||||
..()
|
||||
|
||||
// returns the direction of the next pipe object, given the entrance dir
|
||||
// by default, returns the bitmask of remaining directions
|
||||
proc/nextdir(var/fromdir)
|
||||
return dpdir & (~turn(fromdir, 180))
|
||||
|
||||
// transfer the holder through this pipe segment
|
||||
// overriden for special behaviour
|
||||
//
|
||||
proc/transfer(var/obj/disposalholder/H)
|
||||
var/nextdir = nextdir(H.dir)
|
||||
H.dir = nextdir
|
||||
var/turf/T = H.nextloc()
|
||||
var/obj/disposalpipe/P = H.findpipe(T)
|
||||
|
||||
if(P)
|
||||
// find other holder in next loc, if inactive merge it with current
|
||||
var/obj/disposalholder/H2 = locate() in P
|
||||
if(H2 && !H2.active)
|
||||
H.merge(H2)
|
||||
|
||||
H.loc = P
|
||||
else // if wasn't a pipe, then set loc to turf
|
||||
H.loc = T
|
||||
return null
|
||||
|
||||
return P
|
||||
|
||||
|
||||
// update the icon_state to reflect hidden status
|
||||
proc/update()
|
||||
var/turf/T = src.loc
|
||||
hide(T.intact && !istype(T,/turf/space)) // space never hides pipes
|
||||
|
||||
// hide called by levelupdate if turf intact status changes
|
||||
// change visibility status and force update of icon
|
||||
hide(var/intact)
|
||||
invisibility = intact ? 101: 0 // hide if floor is intact
|
||||
updateicon()
|
||||
|
||||
// update actual icon_state depending on visibility
|
||||
// if invisible, append "f" to icon_state to show faded version
|
||||
// this will be revealed if a T-scanner is used
|
||||
// if visible, use regular icon_state
|
||||
proc/updateicon()
|
||||
if(invisibility)
|
||||
icon_state = "[base_icon_state]f"
|
||||
else
|
||||
icon_state = base_icon_state
|
||||
return
|
||||
|
||||
|
||||
// expel the held objects into a turf
|
||||
// called when there is a break in the pipe
|
||||
//
|
||||
|
||||
proc/expel(var/obj/disposalholder/H, var/turf/T, var/direction)
|
||||
|
||||
var/turf/target
|
||||
|
||||
if(T.density) // dense ouput turf, so stop holder
|
||||
H.active = 0
|
||||
H.loc = src
|
||||
return
|
||||
if(T.intact && istype(T,/turf/simulated/floor)) //intact floor, pop the tile
|
||||
var/turf/simulated/floor/F = T
|
||||
//F.health = 100
|
||||
F.burnt = 1
|
||||
F.intact = 0
|
||||
F.levelupdate()
|
||||
new /obj/item/weapon/tile(H) // add to holder so it will be thrown with other stuff
|
||||
F.icon_state = "Floor[F.burnt ? "1" : ""]"
|
||||
|
||||
if(direction) // direction is specified
|
||||
if(istype(T, /turf/space)) // if ended in space, then range is unlimited
|
||||
target = get_edge_target_turf(T, direction)
|
||||
else // otherwise limit to 10 tiles
|
||||
target = get_ranged_target_turf(T, direction, 10)
|
||||
|
||||
playsound(src, 'hiss.ogg', 50, 0, 0)
|
||||
for(var/atom/movable/AM in H)
|
||||
AM.loc = T
|
||||
AM.pipe_eject(direction)
|
||||
spawn(1)
|
||||
if(AM)
|
||||
AM.throw_at(target, 100, 1)
|
||||
H.vent_gas(T)
|
||||
del(H)
|
||||
|
||||
else // no specified direction, so throw in random direction
|
||||
|
||||
playsound(src, 'hiss.ogg', 50, 0, 0)
|
||||
for(var/atom/movable/AM in H)
|
||||
target = get_offset_target_turf(T, rand(5)-rand(5), rand(5)-rand(5))
|
||||
|
||||
AM.loc = T
|
||||
AM.pipe_eject(0)
|
||||
spawn(1)
|
||||
if(AM)
|
||||
AM.throw_at(target, 5, 1)
|
||||
|
||||
H.vent_gas(T) // all gas vent to turf
|
||||
del(H)
|
||||
|
||||
return
|
||||
|
||||
// call to break the pipe
|
||||
// will expel any holder inside at the time
|
||||
// then delete the pipe
|
||||
// remains : set to leave broken pipe pieces in place
|
||||
proc/broken(var/remains = 0)
|
||||
if(remains)
|
||||
for(var/D in cardinal)
|
||||
if(D & dpdir)
|
||||
var/obj/disposalpipe/broken/P = new(src.loc)
|
||||
P.dir = D
|
||||
|
||||
src.invisibility = 101 // make invisible (since we won't delete the pipe immediately)
|
||||
var/obj/disposalholder/H = locate() in src
|
||||
if(H)
|
||||
// holder was present
|
||||
H.active = 0
|
||||
var/turf/T = src.loc
|
||||
if(T.density)
|
||||
// broken pipe is inside a dense turf (wall)
|
||||
// this is unlikely, but just dump out everything into the turf in case
|
||||
|
||||
for(var/atom/movable/AM in H)
|
||||
AM.loc = T
|
||||
AM.pipe_eject(0)
|
||||
del(H)
|
||||
return
|
||||
|
||||
// otherswise, do normal expel from turf
|
||||
expel(H, T, 0)
|
||||
|
||||
spawn(2) // delete pipe after 2 ticks to ensure expel proc finished
|
||||
del(src)
|
||||
|
||||
|
||||
// pipe affected by explosion
|
||||
ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
broken(0)
|
||||
return
|
||||
if(2.0)
|
||||
health -= rand(5,15)
|
||||
healthcheck()
|
||||
return
|
||||
if(3.0)
|
||||
health -= rand(0,15)
|
||||
healthcheck()
|
||||
return
|
||||
|
||||
|
||||
// test health for brokenness
|
||||
proc/healthcheck()
|
||||
if(health < -2)
|
||||
broken(0)
|
||||
else if(health<1)
|
||||
broken(1)
|
||||
return
|
||||
|
||||
//attack by item
|
||||
//weldingtool: unfasten and convert to obj/disposalconstruct
|
||||
|
||||
attackby(var/obj/item/I, var/mob/user)
|
||||
|
||||
var/turf/T = src.loc
|
||||
if(T.intact)
|
||||
return // prevent interaction with T-scanner revealed pipes
|
||||
|
||||
if(istype(I, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/W = I
|
||||
|
||||
if(W.welding)
|
||||
if(W.get_fuel() > 3)
|
||||
W.use_fuel(3)
|
||||
playsound(src.loc, 'Welder2.ogg', 100, 1)
|
||||
|
||||
// check if anything changed over 2 seconds
|
||||
var/turf/uloc = user.loc
|
||||
var/atom/wloc = W.loc
|
||||
user << "Slicing the disposal pipe."
|
||||
sleep(30)
|
||||
if(user.loc == uloc && wloc == W.loc)
|
||||
|
||||
welded()
|
||||
else
|
||||
user << "You must stay still while welding the pipe."
|
||||
return
|
||||
else
|
||||
user << "You need more welding fuel to cut the pipe."
|
||||
return
|
||||
|
||||
// called when pipe is cut with welder
|
||||
proc/welded()
|
||||
|
||||
var/obj/disposalconstruct/C = new (src.loc)
|
||||
switch(base_icon_state)
|
||||
if("pipe-s")
|
||||
C.ptype = 0
|
||||
if("pipe-c")
|
||||
C.ptype = 1
|
||||
if("pipe-j1")
|
||||
C.ptype = 2
|
||||
if("pipe-j2")
|
||||
C.ptype = 3
|
||||
if("pipe-y")
|
||||
C.ptype = 4
|
||||
if("pipe-t")
|
||||
C.ptype = 5
|
||||
|
||||
C.dir = dir
|
||||
C.update()
|
||||
|
||||
del(src)
|
||||
|
||||
// *** TEST verb
|
||||
//client/verb/dispstop()
|
||||
// for(var/obj/disposalholder/H in world)
|
||||
// H.active = 0
|
||||
|
||||
// a straight or bent segment
|
||||
/obj/disposalpipe/segment
|
||||
icon_state = "pipe-s"
|
||||
|
||||
New()
|
||||
..()
|
||||
if(icon_state == "pipe-s")
|
||||
dpdir = dir | turn(dir, 180)
|
||||
else
|
||||
dpdir = dir | turn(dir, -90)
|
||||
|
||||
update()
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
//a three-way junction with dir being the dominant direction
|
||||
/obj/disposalpipe/junction
|
||||
icon_state = "pipe-j1"
|
||||
|
||||
New()
|
||||
..()
|
||||
if(icon_state == "pipe-j1")
|
||||
dpdir = dir | turn(dir, -90) | turn(dir,180)
|
||||
else if(icon_state == "pipe-j2")
|
||||
dpdir = dir | turn(dir, 90) | turn(dir,180)
|
||||
else // pipe-y
|
||||
dpdir = dir | turn(dir,90) | turn(dir, -90)
|
||||
update()
|
||||
return
|
||||
|
||||
|
||||
// next direction to move
|
||||
// if coming in from secondary dirs, then next is primary dir
|
||||
// if coming in from primary dir, then next is equal chance of other dirs
|
||||
|
||||
nextdir(var/fromdir)
|
||||
var/flipdir = turn(fromdir, 180)
|
||||
if(flipdir != dir) // came from secondary dir
|
||||
return dir // so exit through primary
|
||||
else // came from primary
|
||||
// so need to choose either secondary exit
|
||||
var/mask = ..(fromdir)
|
||||
|
||||
// find a bit which is set
|
||||
var/setbit = 0
|
||||
if(mask & NORTH)
|
||||
setbit = NORTH
|
||||
else if(mask & SOUTH)
|
||||
setbit = SOUTH
|
||||
else if(mask & EAST)
|
||||
setbit = EAST
|
||||
else
|
||||
setbit = WEST
|
||||
|
||||
if(prob(50)) // 50% chance to choose the found bit or the other one
|
||||
return setbit
|
||||
else
|
||||
return mask & (~setbit)
|
||||
|
||||
|
||||
|
||||
|
||||
//a trunk joining to a disposal bin or outlet on the same turf
|
||||
/obj/disposalpipe/trunk
|
||||
icon_state = "pipe-t"
|
||||
var/obj/linked // the linked obj/machinery/disposal or obj/disposaloutlet
|
||||
|
||||
New()
|
||||
..()
|
||||
dpdir = dir
|
||||
spawn(1)
|
||||
getlinked()
|
||||
|
||||
update()
|
||||
return
|
||||
|
||||
proc/getlinked()
|
||||
linked = null
|
||||
var/obj/machinery/disposal/D = locate() in src.loc
|
||||
if(D)
|
||||
linked = D
|
||||
|
||||
var/obj/disposaloutlet/O = locate() in src.loc
|
||||
if(O)
|
||||
linked = O
|
||||
|
||||
update()
|
||||
return
|
||||
|
||||
// would transfer to next pipe segment, but we are in a trunk
|
||||
// if not entering from disposal bin,
|
||||
// transfer to linked object (outlet or bin)
|
||||
|
||||
transfer(var/obj/disposalholder/H)
|
||||
|
||||
if(H.dir == DOWN) // we just entered from a disposer
|
||||
return ..() // so do base transfer proc
|
||||
// otherwise, go to the linked object
|
||||
if(linked)
|
||||
var/obj/disposaloutlet/O = linked
|
||||
if(istype(O))
|
||||
O.expel(H) // expel at outlet
|
||||
else
|
||||
var/obj/machinery/disposal/D = linked
|
||||
D.expel(H) // expel at disposal
|
||||
else
|
||||
src.expel(H, src.loc, 0) // expel at turf
|
||||
return null
|
||||
|
||||
// nextdir
|
||||
|
||||
nextdir(var/fromdir)
|
||||
if(fromdir == DOWN)
|
||||
return dir
|
||||
else
|
||||
return 0
|
||||
|
||||
// a broken pipe
|
||||
/obj/disposalpipe/broken
|
||||
icon_state = "pipe-b"
|
||||
dpdir = 0 // broken pipes have dpdir=0 so they're not found as 'real' pipes
|
||||
// i.e. will be treated as an empty turf
|
||||
desc = "A broken piece of disposal pipe."
|
||||
|
||||
New()
|
||||
..()
|
||||
update()
|
||||
return
|
||||
|
||||
// called when welded
|
||||
// for broken pipe, remove and turn into scrap
|
||||
|
||||
welded()
|
||||
var/obj/item/scrap/S = new(src.loc)
|
||||
S.set_components(200,0,0)
|
||||
del(src)
|
||||
|
||||
// the disposal outlet machine
|
||||
|
||||
/obj/disposaloutlet
|
||||
name = "disposal outlet"
|
||||
desc = "An outlet for the pneumatic disposal system."
|
||||
icon = 'disposal.dmi'
|
||||
icon_state = "outlet"
|
||||
density = 1
|
||||
anchored = 1
|
||||
var/active = 0
|
||||
var/turf/target // this will be where the output objects are 'thrown' to.
|
||||
|
||||
New()
|
||||
..()
|
||||
|
||||
spawn(1)
|
||||
target = get_ranged_target_turf(src, dir, 10)
|
||||
|
||||
// expel the contents of the holder object, then delete it
|
||||
// called when the holder exits the outlet
|
||||
proc/expel(var/obj/disposalholder/H)
|
||||
|
||||
flick("outlet-open", src)
|
||||
playsound(src, 'warning-buzzer.ogg', 50, 0, 0)
|
||||
sleep(20) //wait until correct animation frame
|
||||
playsound(src, 'hiss.ogg', 50, 0, 0)
|
||||
|
||||
|
||||
for(var/atom/movable/AM in H)
|
||||
AM.loc = src.loc
|
||||
AM.pipe_eject(dir)
|
||||
spawn(1)
|
||||
AM.throw_at(target, 3, 1)
|
||||
H.vent_gas(src.loc)
|
||||
del(H)
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
// called when movable is expelled from a disposal pipe or outlet
|
||||
// by default does nothing, override for special behaviour
|
||||
|
||||
/atom/movable/proc/pipe_eject(var/direction)
|
||||
return
|
||||
|
||||
// check if mob has client, if so restore client view on eject
|
||||
/mob/pipe_eject(var/direction)
|
||||
if (src.client)
|
||||
src.client.perspective = MOB_PERSPECTIVE
|
||||
src.client.eye = src
|
||||
|
||||
return
|
||||
|
||||
/obj/decal/cleanable/blood/gibs/pipe_eject(var/direction)
|
||||
var/list/dirs
|
||||
if(direction)
|
||||
dirs = list( direction, turn(direction, -45), turn(direction, 45))
|
||||
else
|
||||
dirs = alldirs.Copy()
|
||||
|
||||
src.streak(dirs)
|
||||
|
||||
/obj/decal/cleanable/robot_debris/gib/pipe_eject(var/direction)
|
||||
var/list/dirs
|
||||
if(direction)
|
||||
dirs = list( direction, turn(direction, -45), turn(direction, 45))
|
||||
else
|
||||
dirs = alldirs.Copy()
|
||||
|
||||
src.streak(dirs)
|
||||
@@ -0,0 +1,288 @@
|
||||
// The scrap item
|
||||
// a single object type represents all combinations of size and composition of scrap
|
||||
//
|
||||
|
||||
|
||||
/obj/item/scrap
|
||||
name = "scrap"
|
||||
icon = 'scrap.dmi'
|
||||
icon_state = "1metal0"
|
||||
item_state = "scrap-metal"
|
||||
desc = "A piece of scrap"
|
||||
var/classtext = ""
|
||||
throwforce = 14.0
|
||||
m_amt = 0
|
||||
g_amt = 0
|
||||
w_amt = 0
|
||||
var/size = 1 // 1=piece, 2= few pieces, 3=small pile, 4=large pile
|
||||
var/blood = 0 // 0=none, 1=blood-stained, 2=bloody
|
||||
|
||||
throwforce = 8.0
|
||||
throw_speed = 1
|
||||
throw_range = 4
|
||||
w_class = 1
|
||||
flags = FPRINT | TABLEPASS | CONDUCT
|
||||
|
||||
#define MAX_SCRAP 15000 // maximum content amount of a scrap pile
|
||||
|
||||
|
||||
/obj/item/scrap/New()
|
||||
src.verbs -= /atom/movable/verb/pull
|
||||
..()
|
||||
update()
|
||||
|
||||
// return a copy
|
||||
/obj/item/scrap/proc/copy()
|
||||
var/obj/item/scrap/ret = new()
|
||||
ret.set_components(m_amt, g_amt, w_amt)
|
||||
return ret
|
||||
|
||||
|
||||
// set the metal, glass and waste content
|
||||
/obj/item/scrap/proc/set_components(var/m, var/g, var/w)
|
||||
m_amt = m
|
||||
g_amt = g
|
||||
w_amt = w
|
||||
update()
|
||||
|
||||
// returns the total amount of scrap in this pile
|
||||
/obj/item/scrap/proc/total()
|
||||
return m_amt + g_amt + w_amt
|
||||
|
||||
|
||||
// sets the size, appearance, and description of the scrap depending on component amounts
|
||||
/obj/item/scrap/proc/update()
|
||||
var/total = total()
|
||||
|
||||
|
||||
// determine size of pile
|
||||
if(total<=400)
|
||||
size = 1
|
||||
else if(total<=1600)
|
||||
size = 2
|
||||
else
|
||||
size = 3
|
||||
|
||||
w_class = size
|
||||
|
||||
var/sizetext = ""
|
||||
|
||||
switch(size)
|
||||
if(1)
|
||||
sizetext = "A piece of"
|
||||
if(2)
|
||||
sizetext = "A few pieces of"
|
||||
if(3)
|
||||
sizetext = "A pile of"
|
||||
|
||||
// determine bloodiness
|
||||
var/bloodtext = ""
|
||||
switch(blood)
|
||||
if(0)
|
||||
bloodtext = ""
|
||||
if(1)
|
||||
bloodtext = "blood-stained "
|
||||
if(2)
|
||||
bloodtext = "bloody "
|
||||
|
||||
|
||||
// find mixture and composition
|
||||
var/class = 0 // 0 = mixed, 1=mostly. 2=pure
|
||||
var/major = "waste" // the major component type
|
||||
|
||||
var/max = 0
|
||||
|
||||
if(m_amt > max)
|
||||
max = m_amt
|
||||
else if(g_amt > max)
|
||||
max = g_amt
|
||||
else if(w_amt > max)
|
||||
max = w_amt
|
||||
|
||||
if(max == total)
|
||||
class = 2 // pure
|
||||
else if(max/total > 0.6)
|
||||
class = 1 // mostly
|
||||
else
|
||||
class = 0 // mixed
|
||||
|
||||
if(class>0)
|
||||
var/remain = total - max
|
||||
if(m_amt > remain)
|
||||
major = "metal"
|
||||
else if(g_amt > remain)
|
||||
major = "glass"
|
||||
else
|
||||
major = "waste"
|
||||
|
||||
|
||||
if(class == 1)
|
||||
desc = "[sizetext] mostly [major] [bloodtext]scrap."
|
||||
classtext = "mostly [major] [bloodtext]"
|
||||
else
|
||||
desc = "[sizetext] [bloodtext][major] scrap."
|
||||
classtext = "[bloodtext][major] "
|
||||
icon_state = "[size][major][blood]"
|
||||
else
|
||||
desc = "[sizetext] [bloodtext]mixed scrap."
|
||||
classtext = "[bloodtext]mixed"
|
||||
icon_state = "[size]mixed[blood]"
|
||||
|
||||
if(size==0)
|
||||
pixel_x = rand(-5,5)
|
||||
pixel_y = rand(-5,5)
|
||||
else
|
||||
pixel_x = 0
|
||||
pixel_y = 0
|
||||
|
||||
// clear or set conduction flag depending on whether scrap is mostly metal
|
||||
if(major=="metal")
|
||||
flags |= CONDUCT
|
||||
else
|
||||
flags &= ~CONDUCT
|
||||
|
||||
item_state = "scrap-[major]"
|
||||
|
||||
// add a scrap item to this one
|
||||
// if the resulting pile is too big, transfer only what will fit
|
||||
// otherwise add them and deleted the added pile
|
||||
|
||||
/obj/item/scrap/proc/add_scrap(var/obj/item/scrap/other, var/limit = MAX_SCRAP)
|
||||
var/total = total()
|
||||
var/other_total = other.total()
|
||||
|
||||
if( (total + other_total) <= limit )
|
||||
m_amt += other.m_amt
|
||||
g_amt += other.g_amt
|
||||
w_amt += other.w_amt
|
||||
|
||||
blood = (total*blood + other_total*other.blood) / (total + other_total)
|
||||
del(other)
|
||||
|
||||
else
|
||||
var/space = limit - total
|
||||
|
||||
var/m = round(other.m_amt/other_total*space, 1)
|
||||
var/g = round(other.g_amt/other_total*space, 1)
|
||||
var/w = round(other.w_amt/other_total*space, 1)
|
||||
|
||||
m_amt += m
|
||||
g_amt += g
|
||||
w_amt += w
|
||||
|
||||
other.m_amt -= m
|
||||
other.g_amt -= g
|
||||
other.w_amt -= w
|
||||
|
||||
var/other_trans = m + g + w
|
||||
other.update()
|
||||
blood = (total*blood + other_trans*other.blood) / (total + other_trans)
|
||||
|
||||
|
||||
blood = round(blood,1)
|
||||
src.update()
|
||||
|
||||
// limit this pile to maximum size
|
||||
// return any remainder as a new scrap item (or null if none)
|
||||
// note return item is not necessarily smaller than max size
|
||||
|
||||
/obj/item/scrap/proc/remainder(var/limit = MAX_SCRAP)
|
||||
var/total = total()
|
||||
if(total > limit)
|
||||
var/m = round( m_amt/total * limit, 1)
|
||||
var/g = round( g_amt/total * limit, 1)
|
||||
var/w = round( w_amt/total * limit, 1)
|
||||
|
||||
var/obj/item/scrap/S = new()
|
||||
S.set_components(m_amt - m,g_amt - g,w_amt - w)
|
||||
src.set_components(m,g,w)
|
||||
|
||||
return S
|
||||
return null
|
||||
|
||||
// if other pile of scrap tries to enter the same turf, then add that pile to this one
|
||||
|
||||
/obj/item/scrap/CanPass(var/obj/item/scrap/O)
|
||||
|
||||
if(istype(O))
|
||||
|
||||
src.add_scrap(O)
|
||||
if(O)
|
||||
return 0 // O still exists if not all could be transfered, so block it
|
||||
return 1
|
||||
|
||||
/obj/item/scrap/proc/to_text()
|
||||
return "[m_amt],[g_amt],[w_amt] ([total()])"
|
||||
|
||||
|
||||
// attack with hand removes a single piece from a pile
|
||||
/obj/item/scrap/attack_hand(mob/user)
|
||||
add_fingerprint(user)
|
||||
if(src.is_single_piece())
|
||||
return ..(user)
|
||||
var/obj/item/scrap/S = src.get_single_piece()
|
||||
S.attack_hand(user)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/scrap/attackby(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/scrap))
|
||||
var/obj/item/scrap/S = I
|
||||
if( (S.total()+src.total() ) > MAX_SCRAP )
|
||||
user << "The pile is full."
|
||||
return
|
||||
if(ismob(src.loc)) // can't combine scrap in hand
|
||||
return
|
||||
|
||||
src.add_scrap(S)
|
||||
|
||||
// when dropped, try to make a pile if scrap is already there
|
||||
/obj/item/scrap/dropped()
|
||||
|
||||
spawn(2) // delay to allow drop postprocessing (since src may be destroyed)
|
||||
for(var/obj/item/scrap/S in oview(0,src)) // excludes src itself
|
||||
S.add_scrap(src)
|
||||
|
||||
// return true if this is a single piece of scrap
|
||||
// must be total<=400 and of single composition
|
||||
/obj/item/scrap/proc/is_single_piece()
|
||||
if(total() > 400)
|
||||
return 0
|
||||
|
||||
var/empty = (m_amt == 0) + (g_amt == 0) + (w_amt == 0)
|
||||
|
||||
return (empty==2) // must be 2 components with zero amount
|
||||
|
||||
|
||||
// get a single piece of scrap from a pile
|
||||
/obj/item/scrap/proc/get_single_piece()
|
||||
|
||||
var/obj/item/scrap/S = new()
|
||||
|
||||
var/cmp = pick(m_amt;1 , g_amt;2, w_amt;3)
|
||||
|
||||
var/amount = 400
|
||||
switch(cmp)
|
||||
if(1)
|
||||
if(m_amt < amount)
|
||||
amount = m_amt
|
||||
|
||||
S.set_components(amount, 0, 0)
|
||||
src.set_components(m_amt - amount, g_amt, w_amt)
|
||||
|
||||
if(2)
|
||||
if(g_amt < amount)
|
||||
amount = g_amt
|
||||
S.set_components(0, amount, 0)
|
||||
src.set_components(m_amt, g_amt - amount, w_amt)
|
||||
|
||||
if(3)
|
||||
if(w_amt < amount)
|
||||
amount = w_amt
|
||||
S.set_components(0, 0, amount)
|
||||
src.set_components(m_amt, g_amt, w_amt - amount)
|
||||
|
||||
|
||||
return S
|
||||
|
||||
|
||||
Reference in New Issue
Block a user