mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-22 19:47:22 +01:00
Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into OrganRefactor
This commit is contained in:
@@ -224,7 +224,7 @@
|
||||
if(istype(object,/turf) && pa.Find("left") && !pa.Find("alt") && !pa.Find("ctrl") )
|
||||
var/turf/T = object
|
||||
if(istype(object,/turf/space))
|
||||
T.ChangeTurf(/turf/simulated/floor)
|
||||
T.ChangeTurf(/turf/simulated/floor/plasteel)
|
||||
else if(istype(object,/turf/simulated/floor))
|
||||
T.ChangeTurf(/turf/simulated/wall)
|
||||
else if(istype(object,/turf/simulated/wall))
|
||||
@@ -235,7 +235,7 @@
|
||||
log_admin("Build Mode: [key_name(usr)] deleted [object] at ([object.x],[object.y],[object.z])")
|
||||
if(istype(object,/turf/simulated/wall))
|
||||
var/turf/T = object
|
||||
T.ChangeTurf(/turf/simulated/floor)
|
||||
T.ChangeTurf(/turf/simulated/floor/plasteel)
|
||||
else if(istype(object,/turf/simulated/floor))
|
||||
var/turf/T = object
|
||||
T.ChangeTurf(/turf/space)
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*Contains:
|
||||
* Prize balls
|
||||
* Prize tickets
|
||||
*/
|
||||
|
||||
/obj/item/toy/prizeball
|
||||
name = "prize ball"
|
||||
@@ -5,6 +9,7 @@
|
||||
icon = 'icons/obj/arcade.dmi'
|
||||
icon_state = "prizeball_1"
|
||||
var/opening = 0
|
||||
var/possible_contents = list(/obj/random/carp_plushie, /obj/random/plushie, /obj/random/figure, /obj/item/toy/eight_ball, /obj/item/stack/tickets)
|
||||
|
||||
/obj/item/toy/prizeball/New()
|
||||
..()
|
||||
@@ -17,8 +22,68 @@
|
||||
playsound(src.loc, 'sound/items/bubblewrap.ogg', 30, 1, extrarange = -4, falloff = 10)
|
||||
icon_state = "prizeconfetti"
|
||||
src.color = pick(random_color_list)
|
||||
var/prize_inside = pick(/obj/random/carp_plushie, /obj/random/plushie, /obj/random/figure, /obj/item/toy/eight_ball) //will add ticket bundles later
|
||||
var/prize_inside = pick(possible_contents)
|
||||
spawn(10)
|
||||
user.unEquip(src)
|
||||
new prize_inside(user.loc)
|
||||
qdel(src)
|
||||
if(istype(prize_inside, /obj/item/stack))
|
||||
var/amount = pick(5, 10, 15, 25, 50)
|
||||
new prize_inside(user.loc, amount)
|
||||
else
|
||||
new prize_inside(user.loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/toy/prizeball/mech
|
||||
name = "mecha figure capsule"
|
||||
desc = "Contains one collectible mecha figure!"
|
||||
possible_contents = list(/obj/random/mech)
|
||||
|
||||
/obj/item/toy/prizeball/carp_plushie
|
||||
name = "carp plushie capsule"
|
||||
desc = "Contains one space carp plushie!"
|
||||
possible_contents = list(/obj/random/carp_plushie)
|
||||
|
||||
/obj/item/toy/prizeball/plushie
|
||||
name = "animal plushie capsule"
|
||||
desc = "Contains one cuddly animal plushie!"
|
||||
possible_contents = list(/obj/random/plushie)
|
||||
|
||||
/obj/item/toy/prizeball/figure
|
||||
name = "action figure capsule"
|
||||
desc = "Contains one action figure!"
|
||||
possible_contents = list(/obj/random/figure)
|
||||
|
||||
/obj/item/toy/prizeball/therapy
|
||||
name = "therapy doll capsule"
|
||||
desc = "Contains one squishy therapy doll."
|
||||
possible_contents = list(/obj/random/therapy)
|
||||
|
||||
/obj/item/stack/tickets
|
||||
name = "prize ticket"
|
||||
desc = "Prize tickets from the arcade. Exchange them for fabulous prizes!"
|
||||
singular_name = "prize ticket"
|
||||
icon = 'icons/obj/arcade.dmi'
|
||||
icon_state = "tickets_1"
|
||||
force = 0
|
||||
throwforce = 0
|
||||
throw_speed = 1
|
||||
throw_range = 1
|
||||
w_class = 1.0
|
||||
max_amount = 9999 //Dang that's a lot of tickets
|
||||
|
||||
/obj/item/stack/tickets/New(var/loc, var/amount=null)
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/stack/tickets/attack_self(mob/user as mob)
|
||||
return
|
||||
|
||||
/obj/item/stack/tickets/update_icon()
|
||||
var/amount = get_amount()
|
||||
if((amount >= 75))
|
||||
icon_state = "tickets_4"
|
||||
else if(amount >=25)
|
||||
icon_state = "tickets_3"
|
||||
else if(amount >= 4)
|
||||
icon_state = "tickets_2"
|
||||
else
|
||||
icon_state = "tickets_1"
|
||||
@@ -0,0 +1,221 @@
|
||||
|
||||
/obj/machinery/prize_counter
|
||||
name = "Prize Counter"
|
||||
desc = "A machine which exchanges tickets for a variety of fabulous prizes!"
|
||||
icon = 'icons/obj/arcade.dmi'
|
||||
icon_state = "prize_counter-on"
|
||||
density = 1
|
||||
anchored = 1
|
||||
use_power = 1
|
||||
idle_power_usage = 40
|
||||
var/tickets = 0
|
||||
var/prize_tier = 1 //Increased by matter bin rating, unlocks more prize options per tier
|
||||
|
||||
/obj/machinery/prize_counter/New()
|
||||
..()
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/weapon/circuitboard/prize_counter(null)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
|
||||
component_parts += new /obj/item/stack/cable_coil(null, 1)
|
||||
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/prize_counter/upgraded/New()
|
||||
..()
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/weapon/circuitboard/prize_counter(null)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin/bluespace(null)
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
|
||||
component_parts += new /obj/item/stack/cable_coil(null, 1)
|
||||
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/prize_counter/RefreshParts()
|
||||
for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts)
|
||||
prize_tier = B.rating
|
||||
|
||||
/obj/machinery/prize_counter/update_icon()
|
||||
if(stat & BROKEN)
|
||||
icon_state = "prize_counter-broken"
|
||||
else if(panel_open)
|
||||
icon_state = "prize_counter-open"
|
||||
else if(stat & NOPOWER)
|
||||
icon_state = "prize_counter-off"
|
||||
else
|
||||
icon_state = "prize_counter-on"
|
||||
return
|
||||
|
||||
/obj/machinery/prize_counter/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
|
||||
if(istype(O, /obj/item/stack/tickets))
|
||||
var/obj/item/stack/tickets/T = O
|
||||
if(user.unEquip(T)) //Because if you can't drop it for some reason, you shouldn't be increasing the tickets var
|
||||
tickets += T.amount
|
||||
qdel(T)
|
||||
else
|
||||
user << "<span class='warning'>\The [T] seems stuck to your hand!</span>"
|
||||
return
|
||||
if(istype(O, /obj/item/weapon/screwdriver) && anchored)
|
||||
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
panel_open = !panel_open
|
||||
user << "You [panel_open ? "open" : "close"] the maintenance panel."
|
||||
update_icon()
|
||||
return
|
||||
if(panel_open)
|
||||
if(istype(O, /obj/item/weapon/wrench))
|
||||
default_unfasten_wrench(user, O)
|
||||
if(component_parts && istype(O, /obj/item/weapon/crowbar))
|
||||
if(tickets) //save the tickets!
|
||||
print_tickets()
|
||||
default_deconstruction_crowbar(O)
|
||||
|
||||
/obj/machinery/prize_counter/attack_hand(mob/user as mob)
|
||||
if(..())
|
||||
return
|
||||
add_fingerprint(user)
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/prize_counter/interact(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
|
||||
var/dat = {"
|
||||
<html>
|
||||
<head>
|
||||
<title>Arcade Ticket Exchange</title>
|
||||
<style type="text/css">
|
||||
* {
|
||||
font-family:sans-serif;
|
||||
font-size:x-small;
|
||||
}
|
||||
html {
|
||||
background:#333;
|
||||
color:#999;
|
||||
}
|
||||
|
||||
a {
|
||||
color:#cfcfcf;
|
||||
text-decoration:none;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color:#ffffff;
|
||||
}
|
||||
tr {
|
||||
background:#303030;
|
||||
border-radius:6px;
|
||||
margin-bottom:0.5em;
|
||||
border-bottom:1px solid black;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background:#3f3f3f;
|
||||
}
|
||||
|
||||
td.cost {
|
||||
font-size:20pt;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
td.cost.affordable {
|
||||
background:green;
|
||||
}
|
||||
|
||||
td.cost.toomuch {
|
||||
background:maroon;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p style="float:right"><b>Tickets:</b> [tickets] | <a href='byond://?src=\ref[src];eject=1'>Eject Tickets</a></p>
|
||||
<h1>Arcade Ticket Exchange</h1>
|
||||
<p>
|
||||
<b>Exchange that pile of tickets for a pile of cool prizes!</b>
|
||||
</p>
|
||||
<h2>Available Prizes:</h2>
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<thead>
|
||||
<th>#</th>
|
||||
<th>Name/Description</th>
|
||||
<th>Price</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
"}
|
||||
|
||||
for(var/datum/prize_item/item in global_prizes.prizes)
|
||||
var/cost_class="affordable"
|
||||
if(item.cost>tickets)
|
||||
cost_class="toomuch"
|
||||
var/itemID = global_prizes.prizes.Find(item)
|
||||
dat += {"
|
||||
<tr>
|
||||
<th>
|
||||
[itemID]
|
||||
</th>
|
||||
<td>
|
||||
<p><b>[item.name]</b></p>
|
||||
<p>[item.desc]</p>
|
||||
</td>
|
||||
"}
|
||||
if(prize_tier >= item.tier_unlocked)
|
||||
dat += {"
|
||||
<td class="cost [cost_class]">
|
||||
<a href="byond://?src=\ref[src];buy=[itemID]">[item.cost] Tickets</a>
|
||||
</td>
|
||||
</tr>
|
||||
"}
|
||||
else
|
||||
dat += {"
|
||||
<td>
|
||||
LOCKED.
|
||||
</td>
|
||||
</tr>
|
||||
"}
|
||||
|
||||
dat += {"
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>"}
|
||||
user << browse(dat, "window=prize_counter")
|
||||
onclose(user, "prize_counter")
|
||||
return
|
||||
|
||||
/obj/machinery/prize_counter/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
add_fingerprint(usr)
|
||||
|
||||
if(href_list["eject"])
|
||||
print_tickets()
|
||||
|
||||
if (href_list["buy"])
|
||||
var/itemID = text2num(href_list["buy"])
|
||||
var/datum/prize_item/item = global_prizes.prizes[itemID]
|
||||
var/sure = alert(usr,"Are you sure you wish to purchase [item.name] for [item.cost] tickets?","You sure?","Yes","No") in list("Yes","No")
|
||||
if(sure=="No")
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(!global_prizes.PlaceOrder(src, itemID))
|
||||
usr << "<span class='warning'>Unable to complete the exchange.</span>"
|
||||
else
|
||||
usr << "<span class='notice'>You've successfully purchased the item.</span>"
|
||||
|
||||
interact(usr)
|
||||
return
|
||||
|
||||
/obj/machinery/prize_counter/proc/print_tickets()
|
||||
if(!tickets)
|
||||
return
|
||||
if(tickets >= 9999)
|
||||
new /obj/item/stack/tickets(get_turf(src), 9999) //max stack size
|
||||
tickets -= 9999
|
||||
print_tickets()
|
||||
else
|
||||
new /obj/item/stack/tickets(get_turf(src), tickets)
|
||||
tickets = 0
|
||||
@@ -0,0 +1,343 @@
|
||||
|
||||
var/global/datum/prizes/global_prizes = new
|
||||
|
||||
/datum/prizes
|
||||
var/list/prizes = list()
|
||||
|
||||
/datum/prizes/New()
|
||||
for(var/itempath in subtypesof(/datum/prize_item))
|
||||
prizes += new itempath()
|
||||
|
||||
/datum/prizes/proc/PlaceOrder(var/obj/machinery/prize_counter/prize_counter, var/itemID)
|
||||
if(!prize_counter)
|
||||
return 0
|
||||
var/datum/prize_item/item = global_prizes.prizes[itemID]
|
||||
if(!item)
|
||||
return 0
|
||||
if(prize_counter.tickets >= item.cost)
|
||||
new item.typepath(prize_counter.loc)
|
||||
prize_counter.visible_message("<span class='notice'>Enjoy your prize!</span>")
|
||||
return 1
|
||||
else
|
||||
prize_counter.visible_message("<span class='warning'>Not enough tickets!</span>")
|
||||
return 0
|
||||
|
||||
//////////////////////////////////////
|
||||
// prize_item datum //
|
||||
//////////////////////////////////////
|
||||
|
||||
/datum/prize_item
|
||||
var/name = "Prize"
|
||||
var/desc = "This shouldn't show up..."
|
||||
var/typepath = /obj/item/toy/prizeball
|
||||
var/cost = 0
|
||||
var/tier_unlocked = 0 //minimum tier needed to unlock the ability to select this prize
|
||||
|
||||
//////////////////////////////////////
|
||||
// Tier 1 Prizes //
|
||||
//////////////////////////////////////
|
||||
|
||||
/datum/prize_item/balloon
|
||||
name = "Water Balloon"
|
||||
desc = "A thin balloon for throwing liquid at people."
|
||||
typepath = /obj/item/toy/balloon
|
||||
cost = 10
|
||||
tier_unlocked = 1
|
||||
|
||||
/datum/prize_item/crayons
|
||||
name = "Box of Crayons"
|
||||
desc = "A six-pack of crayons, just like back in kindergarten."
|
||||
typepath = /obj/item/weapon/storage/fancy/crayons
|
||||
cost = 35
|
||||
tier_unlocked = 1
|
||||
|
||||
/datum/prize_item/snappops
|
||||
name = "Snap-Pops"
|
||||
desc = "A box of exploding snap-pop fireworks."
|
||||
typepath = /obj/item/weapon/storage/box/snappops
|
||||
cost = 20
|
||||
tier_unlocked = 1
|
||||
|
||||
/datum/prize_item/spinningtoy
|
||||
name = "Spinning Toy"
|
||||
desc = "Looks like an authentic Singularity!"
|
||||
typepath = /obj/item/toy/spinningtoy
|
||||
cost = 15
|
||||
tier_unlocked = 1
|
||||
|
||||
/datum/prize_item/blinktoy
|
||||
name = "Blink toy"
|
||||
desc = "Blink. Blink. Blink."
|
||||
typepath = /obj/item/toy/blink
|
||||
cost = 15
|
||||
tier_unlocked = 1
|
||||
|
||||
/datum/prize_item/dice
|
||||
name = "Dice set"
|
||||
desc = "A set of assorted dice."
|
||||
typepath = /obj/item/weapon/storage/box/dice
|
||||
cost = 20
|
||||
tier_unlocked = 1
|
||||
|
||||
/datum/prize_item/cards
|
||||
name = "Deck of cards"
|
||||
desc = "Anyone fancy a game of 52-card Pickup?"
|
||||
typepath = /obj/item/toy/cards/deck
|
||||
cost = 25
|
||||
tier_unlocked = 1
|
||||
|
||||
/datum/prize_item/wallet
|
||||
name = "Colored Wallet"
|
||||
desc = "Brightly colored and big enough for standard issue ID cards."
|
||||
typepath = /obj/item/weapon/storage/wallet/color
|
||||
cost = 50
|
||||
tier_unlocked = 1
|
||||
|
||||
/datum/prize_item/pet_rock
|
||||
name = "pet rock"
|
||||
desc = "A pet of your very own!"
|
||||
typepath = /obj/item/toy/pet_rock
|
||||
cost = 80
|
||||
tier_unlocked = 1
|
||||
|
||||
/datum/prize_item/foam_darts
|
||||
name = "Pack of Foam Darts"
|
||||
desc = "A refill pack of 10 foam darts."
|
||||
typepath = /obj/item/weapon/storage/box/foam_darts
|
||||
cost = 20
|
||||
tier_unlocked = 1
|
||||
|
||||
/datum/prize_item/minigibber
|
||||
name = "Minigibber Toy"
|
||||
desc = "A model of the station gibber. Probably shouldn't stick your fingers in it."
|
||||
typepath = /obj/item/toy/minigibber
|
||||
cost = 60
|
||||
tier_unlocked = 1
|
||||
|
||||
/datum/prize_item/id_sticker
|
||||
name = "Prisoner ID Sticker"
|
||||
desc = "A sticker that can make any ID look like a prisoner ID."
|
||||
typepath = /obj/item/weapon/id_decal/prisoner
|
||||
cost = 50
|
||||
tier_unlocked = 1
|
||||
|
||||
/datum/prize_item/id_sticker/silver
|
||||
name = "Silver ID Sticker"
|
||||
desc = "A sticker that can make any ID look like a silver ID."
|
||||
typepath = /obj/item/weapon/id_decal/silver
|
||||
|
||||
/datum/prize_item/id_sticker/gold
|
||||
name = "Gold ID Sticker"
|
||||
desc = "A sticker that can make any ID look like a golden ID."
|
||||
typepath = /obj/item/weapon/id_decal/gold
|
||||
|
||||
/datum/prize_item/id_sticker/centcom
|
||||
name = "Centcomm ID Sticker"
|
||||
desc = "A sticker that can make any ID look like a Central Command ID."
|
||||
typepath = /obj/item/weapon/id_decal/centcom
|
||||
|
||||
/datum/prize_item/id_sticker/emag
|
||||
name = "Suspicious ID Sticker"
|
||||
desc = "A sticker that can make any ID look like something suspicious..."
|
||||
typepath = /obj/item/weapon/id_decal/emag
|
||||
|
||||
//////////////////////////////////////
|
||||
// Tier 2 Prizes //
|
||||
//////////////////////////////////////
|
||||
|
||||
/datum/prize_item/carp_plushie
|
||||
name = "Random Carp Plushie"
|
||||
desc = "A colorful fish-shaped plush toy."
|
||||
typepath = /obj/item/toy/prizeball/carp_plushie
|
||||
cost = 75
|
||||
tier_unlocked = 2
|
||||
|
||||
/datum/prize_item/therapy_doll
|
||||
name = "Random Therapy Doll"
|
||||
desc = "A therapeutic doll for relieving stress without being charged with assault."
|
||||
typepath = /obj/item/toy/prizeball/therapy
|
||||
cost = 60
|
||||
tier_unlocked = 2
|
||||
|
||||
/datum/prize_item/plushie
|
||||
name = "Random Animal Plushie"
|
||||
desc = "A colorful animal-shaped plush toy."
|
||||
typepath = /obj/item/toy/prizeball/plushie
|
||||
cost = 75
|
||||
tier_unlocked = 2
|
||||
|
||||
/datum/prize_item/mech_toy
|
||||
name = "Random Mecha"
|
||||
desc = "A random mecha figure, collect all 11!"
|
||||
typepath = /obj/item/toy/prizeball/mech
|
||||
cost = 75
|
||||
tier_unlocked = 2
|
||||
|
||||
/datum/prize_item/action_figure
|
||||
name = "Random Action Figure"
|
||||
desc = "A random action figure, collect them all!"
|
||||
typepath = /obj/item/toy/prizeball/figure
|
||||
cost = 75
|
||||
tier_unlocked = 2
|
||||
|
||||
/datum/prize_item/eight_ball
|
||||
name = "Magic Eight Ball"
|
||||
desc = "A mystical ball that can divine the future!"
|
||||
typepath = /obj/item/toy/eight_ball
|
||||
cost = 40
|
||||
tier_unlocked = 2
|
||||
|
||||
/datum/prize_item/tacticool
|
||||
name = "Tacticool Turtleneck"
|
||||
desc = "A cool-looking turtleneck."
|
||||
typepath = /obj/item/clothing/under/syndicate/tacticool
|
||||
cost = 90
|
||||
tier_unlocked = 2
|
||||
|
||||
/datum/prize_item/crossbow
|
||||
name = "Foam Dart Crossbow"
|
||||
desc = "A toy crossbow that fires foam darts."
|
||||
typepath = /obj/item/toy/crossbow
|
||||
cost = 100
|
||||
tier_unlocked = 2
|
||||
|
||||
/datum/prize_item/toy_xeno
|
||||
name = "Xeno Action Figure"
|
||||
desc = "A lifelike replica of the horrific xeno scourge."
|
||||
typepath = /obj/item/toy/toy_xeno
|
||||
cost = 80
|
||||
tier_unlocked = 2
|
||||
|
||||
/datum/prize_item/fakespell
|
||||
name = "Fake Spellbook"
|
||||
desc = "Perform magic! Astound your friends! Get mistaken for an enemy of the corporation!"
|
||||
typepath = /obj/item/weapon/spellbook/oneuse/fake_gib
|
||||
cost = 100
|
||||
tier_unlocked = 2
|
||||
|
||||
/datum/prize_item/capgun
|
||||
name = "Capgun Revolver"
|
||||
desc = "Do you feel lucky... punk?"
|
||||
typepath = /obj/item/weapon/gun/projectile/revolver/capgun
|
||||
cost = 75
|
||||
tier_unlocked = 2
|
||||
|
||||
//////////////////////////////////////
|
||||
// Tier 3 Prizes //
|
||||
//////////////////////////////////////
|
||||
|
||||
/datum/prize_item/magic_conch
|
||||
name = "Magic Conch Shell"
|
||||
desc = "All hail the magic conch!"
|
||||
typepath = /obj/item/toy/eight_ball/conch
|
||||
cost = 100
|
||||
tier_unlocked = 3
|
||||
|
||||
/datum/prize_item/flash
|
||||
name = "Toy Flash"
|
||||
desc = "AUGH! MY EYES!"
|
||||
typepath = /obj/item/toy/flash
|
||||
cost = 50
|
||||
tier_unlocked = 3
|
||||
|
||||
/datum/prize_item/foamblade
|
||||
name = "Foam Armblade"
|
||||
desc = "Perfect for reenacting space horror holo-vids."
|
||||
typepath = /obj/item/toy/foamblade
|
||||
cost = 100
|
||||
tier_unlocked = 3
|
||||
|
||||
/datum/prize_item/minimeteor
|
||||
name = "Mini-Meteor"
|
||||
desc = "Meteors have been detected on a collision course with your fun times!"
|
||||
typepath = /obj/item/toy/minimeteor
|
||||
cost = 50
|
||||
tier_unlocked = 3
|
||||
|
||||
/datum/prize_item/redbutton
|
||||
name = "Shiny Red Button"
|
||||
desc = "PRESS IT!"
|
||||
typepath = /obj/item/toy/redbutton
|
||||
cost = 100
|
||||
tier_unlocked = 3
|
||||
|
||||
/datum/prize_item/owl
|
||||
name = "Owl Action Figure"
|
||||
desc = "Remember: heroes don't grief!"
|
||||
typepath = /obj/item/toy/owl
|
||||
cost = 125
|
||||
tier_unlocked = 3
|
||||
|
||||
/datum/prize_item/griffin
|
||||
name = "Griffin Action Figure"
|
||||
desc = "If you can't be the best, you can always be the WORST."
|
||||
typepath = /obj/item/toy/griffin
|
||||
cost = 125
|
||||
tier_unlocked = 3
|
||||
|
||||
/datum/prize_item/AI
|
||||
name = "Toy AI Unit"
|
||||
desc = "Law 1: Maximize fun for crew."
|
||||
typepath = /obj/item/toy/AI
|
||||
cost = 75
|
||||
tier_unlocked = 3
|
||||
|
||||
/datum/prize_item/tommygun
|
||||
name = "Tommygun"
|
||||
desc = "A replica tommygun that fires foam darts."
|
||||
typepath = /obj/item/toy/crossbow/tommygun
|
||||
cost = 175
|
||||
tier_unlocked = 3
|
||||
|
||||
/datum/prize_item/esword
|
||||
name = "Toy Energy Sword"
|
||||
desc = "A plastic replica of an energy blade."
|
||||
typepath = /obj/item/toy/sword
|
||||
cost = 150
|
||||
tier_unlocked = 3
|
||||
|
||||
/datum/prize_item/blobhat
|
||||
name = "Blob Hat"
|
||||
desc = "There's... something... on your head..."
|
||||
typepath = /obj/item/clothing/head/blob
|
||||
cost = 125
|
||||
tier_unlocked = 3
|
||||
|
||||
/datum/prize_item/nuke
|
||||
name = "Nuclear Fun Device"
|
||||
desc = "Annihilate boredom with an explosion of excitement!"
|
||||
typepath = /obj/item/toy/nuke
|
||||
cost = 100
|
||||
tier_unlocked = 3
|
||||
|
||||
//////////////////////////////////////
|
||||
// Tier 4 Prizes //
|
||||
//////////////////////////////////////
|
||||
|
||||
/datum/prize_item/chainsaw
|
||||
name = "Toy Chainsaw"
|
||||
desc = "A full-scale model chainsaw, based on that massacre in Space Texas."
|
||||
typepath = /obj/item/weapon/twohanded/toy/chainsaw
|
||||
cost = 200
|
||||
tier_unlocked = 4
|
||||
|
||||
/datum/prize_item/spacesuit
|
||||
name = "Fake Spacesuit"
|
||||
desc = "A replica spacesuit. Not actually spaceworthy."
|
||||
typepath = /obj/item/weapon/storage/box/fakesyndiesuit
|
||||
cost = 180
|
||||
tier_unlocked = 4
|
||||
|
||||
/datum/prize_item/fakespace
|
||||
name = "Space Carpet"
|
||||
desc = "A stack of carpeted floor tiles that resemble space."
|
||||
typepath = /obj/item/stack/tile/fakespace/loaded
|
||||
cost = 150
|
||||
tier_unlocked = 4
|
||||
|
||||
/datum/prize_item/bike
|
||||
name = "Awesome Bike!"
|
||||
desc = "WOAH."
|
||||
typepath = /obj/structure/stool/bed/chair/wheelchair/bike
|
||||
cost = 10000 //max stack + 1 tickets
|
||||
tier_unlocked = 4
|
||||
@@ -289,43 +289,44 @@ BLIND // can't see anything
|
||||
if(!ignore_maskadjust)
|
||||
if(!user.canmove || user.stat || user.restrained())
|
||||
return
|
||||
if(src.mask_adjusted == 1)
|
||||
src.icon_state = copytext(src.icon_state, 1, findtext(src.icon_state, "_up")) //Trims the '_up' off the end of the icon state, thus reverting to the most recent previous state
|
||||
if(mask_adjusted)
|
||||
icon_state = copytext(icon_state, 1, findtext(icon_state, "_up")) /*Trims the '_up' off the end of the icon state, thus reverting to the most recent previous state.
|
||||
Had to use this instead of initial() because initial reverted to the wrong state.*/
|
||||
gas_transfer_coefficient = initial(gas_transfer_coefficient)
|
||||
permeability_coefficient = initial(permeability_coefficient)
|
||||
user << "You push \the [src] back into place."
|
||||
src.mask_adjusted = 0
|
||||
mask_adjusted = 0
|
||||
slot_flags = initial(slot_flags)
|
||||
if(flags_inv != initial(flags_inv)) //If the mask is one that hides the face and can be adjusted yet lost that trait when it was adjusted, make it hide the face again.
|
||||
flags_inv += HIDEFACE
|
||||
if(H.head == src)
|
||||
if(src.flags_inv == HIDEFACE) //Means that only things like bandanas and balaclavas will be affected since they obscure the identity of the wearer.
|
||||
if(flags_inv == HIDEFACE) //Means that only things like bandanas and balaclavas will be affected since they obscure the identity of the wearer.
|
||||
if(H.l_hand && H.r_hand) //If both hands are occupied, drop the object on the ground.
|
||||
user.unEquip(src)
|
||||
else
|
||||
else //Otherwise, put it in an available hand, the active one preferentially.
|
||||
src.loc = user
|
||||
H.head = null
|
||||
if(!(H.l_hand) && H.r_hand) //If only the left hand is free, put the bandana there instead.
|
||||
user.put_in_l_hand(src)
|
||||
else if(!(H.r_hand) && H.l_hand) //Otherwise if only the right hand is free, put the bandana there instead.
|
||||
user.put_in_r_hand(src)
|
||||
else if(!(H.l_hand && H.r_hand)) //Otherwise if both hands are free, pick the active one to put the bandana into.
|
||||
user.put_in_active_hand(src)
|
||||
user.put_in_hands(src)
|
||||
else
|
||||
src.icon_state += "_up"
|
||||
icon_state += "_up"
|
||||
user << "You push \the [src] out of the way."
|
||||
gas_transfer_coefficient = null
|
||||
permeability_coefficient = null
|
||||
src.mask_adjusted = 1
|
||||
mask_adjusted = 1
|
||||
if(adjusted_flags)
|
||||
slot_flags = adjusted_flags
|
||||
if(ishuman(user))
|
||||
if(H.internal)
|
||||
if(H.internals)
|
||||
H.internals.icon_state = "internal0"
|
||||
H.internal = null
|
||||
if(user.wear_mask == src) /*If the user was wearing the mask providing internals on their face at the time it was adjusted, turn off internals.
|
||||
Otherwise, they adjusted it while it was in their hands or some such so we won't be needing to turn off internals.*/
|
||||
if(H.internals)
|
||||
H.internals.icon_state = "internal0"
|
||||
H.internal = null
|
||||
if(flags_inv == HIDEFACE) //Means that only things like bandanas and balaclavas will be affected since they obscure the identity of the wearer.
|
||||
flags_inv -= HIDEFACE /*Done after the above to avoid having to do a check for initial(src.flags_inv == HIDEFACE).
|
||||
This reveals the user's face since the bandana will now be going on their head.*/
|
||||
if(user.wear_mask == src)
|
||||
if(src.flags_inv == HIDEFACE) //Means that only things like bandanas and balaclavas will be affected since they obscure the identity of the wearer.
|
||||
if(initial(flags_inv) == HIDEFACE) //Means that you won't have to take off and put back on simple things like breath masks which, realistically, can just be pulled down off your face.
|
||||
if(H.l_hand && H.r_hand) //If both hands are occupied, drop the object on the ground.
|
||||
user.unEquip(src)
|
||||
else
|
||||
@@ -337,8 +338,6 @@ BLIND // can't see anything
|
||||
user.put_in_r_hand(src)
|
||||
else if(!(H.l_hand && H.r_hand)) //Otherwise if both hands are free, pick the active one to put the bandana into.
|
||||
user.put_in_active_hand(src)
|
||||
flags_inv -= HIDEFACE /*Done after the above to avoid having to do a check for initial(src.flags_inv == HIDEFACE).
|
||||
This reveals the user's face since the bandana will now be going on their head.*/
|
||||
|
||||
usr.update_inv_wear_mask()
|
||||
usr.update_inv_head()
|
||||
@@ -348,7 +347,7 @@ BLIND // can't see anything
|
||||
name = "shoes"
|
||||
icon = 'icons/obj/clothing/shoes.dmi'
|
||||
desc = "Comfortable-looking shoes."
|
||||
gender = PLURAL //Carn: for grammarically correct text-parsing
|
||||
gender = PLURAL //Carn: for grammatically correct text-parsing
|
||||
var/chained = 0
|
||||
var/can_cut_open = 0
|
||||
var/cut_open = 0
|
||||
@@ -376,7 +375,7 @@ BLIND // can't see anything
|
||||
user.visible_message("<span class='warning'>[user] strikes a [M] on the bottom of [src], lighting it.</span>","<span class='warning'>You strike the [M] on the bottom of [src] to light it.</span>")
|
||||
else if(M.lit == 1) // Match is lit, not extinguished.
|
||||
M.dropped()
|
||||
user.visible_message("<span class='warning'>[user] crushes the [M] into the bottom of [src]. extinguishing it.</span>","<span class='warning'>You crush the [M] into the bottom of [src], extinguishing it.</span>")
|
||||
user.visible_message("<span class='warning'>[user] crushes the [M] into the bottom of [src], extinguishing it.</span>","<span class='warning'>You crush the [M] into the bottom of [src], extinguishing it.</span>")
|
||||
else // Match has been previously lit and extinguished.
|
||||
user << "<span class='notice'>The [M] has already been extinguished.</span>"
|
||||
return
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
w_class = 2
|
||||
action_button_name = "Adjust Balaclava"
|
||||
ignore_maskadjust = 0
|
||||
adjusted_flags = SLOT_HEAD
|
||||
species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/mask.dmi',
|
||||
|
||||
@@ -34,6 +34,23 @@
|
||||
usr.put_in_hands(src)
|
||||
src.add_fingerprint(user)
|
||||
|
||||
/obj/item/clothing/accessory/attack(mob/living/carbon/human/H, mob/living/user)
|
||||
// This code lets you put accessories on other people by attacking their sprite with the accessory
|
||||
if(istype(H))
|
||||
if(H.wear_suit && H.wear_suit.flags_inv & HIDEJUMPSUIT)
|
||||
user << "[H]'s body is covered, and you cannot attach \the [src]."
|
||||
return 1
|
||||
var/obj/item/clothing/under/U = H.w_uniform
|
||||
if(istype(U))
|
||||
user.visible_message("<span class='notice'>[user] is putting a [src.name] on [H]'s [U.name]!</span>", "<span class='notice'>You begin to put a [src.name] on [H]'s [U.name]...</span>")
|
||||
if(do_after(user,40,target=H) && H.w_uniform == U)
|
||||
user.visible_message("<span class='notice'>[user] puts a [src.name] on [H]'s [U.name]!</span>", "<span class='notice'>You finish putting a [src.name] on [H]'s [U.name].</span>")
|
||||
U.attackby(src, user)
|
||||
else
|
||||
user << "[H] is not wearing anything to attach \the [src] to."
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
//default attackby behaviour
|
||||
/obj/item/clothing/accessory/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
return "$[num2septext(money)]"
|
||||
|
||||
/datum/money_account/proc/charge(var/transaction_amount,var/datum/money_account/dest,var/transaction_purpose, var/terminal_name="", var/terminal_id=0, var/dest_name = "UNKNOWN")
|
||||
if(suspended)
|
||||
usr << "<span class='warning'>Unable to access source account: account suspended.</span>"
|
||||
return 0
|
||||
|
||||
if(transaction_amount <= money)
|
||||
//transfer the money
|
||||
money -= transaction_amount
|
||||
@@ -84,5 +88,5 @@
|
||||
transaction_log.Add(T)
|
||||
return 1
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>You don't have that much money!</span>"
|
||||
usr << "<span class='warning'>Insufficient funds in account.</span>"
|
||||
return 0
|
||||
@@ -27,16 +27,18 @@
|
||||
if(useMS)
|
||||
if(prob(5))
|
||||
// /obj/machinery/message_server/proc/send_pda_message(var/recipient = "",var/sender = "",var/message = "")
|
||||
var/obj/item/device/pda/P
|
||||
var/list/viables = list()
|
||||
for(var/obj/item/device/pda/check_pda in PDAs)
|
||||
if (!check_pda.owner||check_pda.toff||check_pda == src||check_pda.hidden)
|
||||
var/datum/data/pda/app/messenger/check_m = check_pda.find_program(/datum/data/pda/app/messenger)
|
||||
|
||||
if (!check_m || !check_m.can_receive())
|
||||
continue
|
||||
viables.Add(check_pda)
|
||||
|
||||
if(!viables.len)
|
||||
return
|
||||
P = pick(viables)
|
||||
var/obj/item/device/pda/P = pick(viables)
|
||||
var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger)
|
||||
|
||||
var/sender
|
||||
var/message
|
||||
@@ -104,7 +106,7 @@
|
||||
//Commented out because we don't send messages like this anymore. Instead it will just popup in their chat window.
|
||||
//P.tnote += "<i><b>← From [sender] (Unknown / spam?):</b></i><br>[message]<br>"
|
||||
|
||||
P.play_ringtone()
|
||||
PM.play_ringtone()
|
||||
//Search for holder of the PDA.
|
||||
var/mob/living/L = null
|
||||
if(P.loc && isliving(P.loc))
|
||||
|
||||
@@ -254,6 +254,11 @@
|
||||
)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/plump_pie
|
||||
|
||||
/datum/recipe/oven/plumphelmetbiscuit
|
||||
fruit = list("plumphelmet" = 1)
|
||||
reagents = list("water" = 5, "flour" = 5)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit
|
||||
|
||||
/datum/recipe/oven/creamcheesebread
|
||||
items = list(
|
||||
/obj/item/weapon/reagent_containers/food/snacks/dough,
|
||||
|
||||
@@ -651,73 +651,6 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
|
||||
// output for machines^ ^^^^^^^output for people^^^^^^^^^
|
||||
|
||||
|
||||
//Brain slug proc for voluntary removal of control.
|
||||
/mob/living/carbon/proc/release_control()
|
||||
|
||||
set category = "Alien"
|
||||
set name = "Release Control"
|
||||
set desc = "Release control of your host's body."
|
||||
|
||||
var/mob/living/simple_animal/borer/B = has_brain_worms()
|
||||
|
||||
if(B && B.host_brain)
|
||||
src << "\red <B>You withdraw your probosci, releasing control of [B.host_brain]</B>"
|
||||
|
||||
B.detatch()
|
||||
|
||||
verbs -= /mob/living/carbon/proc/release_control
|
||||
verbs -= /mob/living/carbon/proc/punish_host
|
||||
verbs -= /mob/living/carbon/proc/spawn_larvae
|
||||
|
||||
else
|
||||
src << "\red <B>ERROR NO BORER OR BRAINMOB DETECTED IN THIS MOB, THIS IS A BUG !</B>"
|
||||
|
||||
//Brain slug proc for tormenting the host.
|
||||
/mob/living/carbon/proc/punish_host()
|
||||
set category = "Alien"
|
||||
set name = "Torment host"
|
||||
set desc = "Punish your host with agony."
|
||||
|
||||
var/mob/living/simple_animal/borer/B = has_brain_worms()
|
||||
|
||||
if(!B)
|
||||
return
|
||||
|
||||
if(B.host_brain.ckey)
|
||||
src << "\red <B>You send a punishing spike of psychic agony lancing into your host's brain.</B>"
|
||||
B.host_brain << "\red <B><FONT size=3>Horrific, burning agony lances through you, ripping a soundless scream from your trapped mind!</FONT></B>"
|
||||
|
||||
//Check for brain worms in head.
|
||||
/mob/proc/has_brain_worms()
|
||||
|
||||
for(var/I in contents)
|
||||
if(istype(I,/mob/living/simple_animal/borer))
|
||||
return I
|
||||
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/proc/spawn_larvae()
|
||||
set category = "Alien"
|
||||
set name = "Reproduce (100)"
|
||||
set desc = "Spawn several young."
|
||||
|
||||
var/mob/living/simple_animal/borer/B = has_brain_worms()
|
||||
|
||||
if(!B)
|
||||
return
|
||||
|
||||
if(B.chemicals >= 100)
|
||||
src << "\red <B>Your host twitches and quivers as you rapdly excrete several larvae from your sluglike body.</B>"
|
||||
visible_message("\red <B>[src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!</B>")
|
||||
B.chemicals -= 100
|
||||
|
||||
new /obj/effect/decal/cleanable/vomit(get_turf(src))
|
||||
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
|
||||
new /mob/living/simple_animal/borer(get_turf(src))
|
||||
|
||||
else
|
||||
src << "You do not have enough chemicals stored to reproduce."
|
||||
return
|
||||
|
||||
/mob/living/carbon/proc/canBeHandcuffed()
|
||||
return 0
|
||||
@@ -806,3 +739,6 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
|
||||
Stun(stun)
|
||||
Weaken(weaken)
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/proc/can_eat(flags = 255)
|
||||
return 1
|
||||
@@ -105,13 +105,7 @@
|
||||
B = I
|
||||
if(B)
|
||||
if(!B.ckey && ckey && B.controlling)
|
||||
B.ckey = ckey
|
||||
B.controlling = 0
|
||||
if(B.host_brain.ckey)
|
||||
ckey = B.host_brain.ckey
|
||||
B.host_brain.ckey = null
|
||||
B.host_brain.name = "host brain"
|
||||
B.host_brain.real_name = "host brain"
|
||||
B.detatch()
|
||||
|
||||
verbs -= /mob/living/carbon/proc/release_control
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
var/on_CD = 0
|
||||
switch(act)
|
||||
//Cooldown-inducing emotes
|
||||
if("ping","buzz","beep")
|
||||
if("ping","buzz","beep", "yes", "no")
|
||||
if (species.name == "Machine") //Only Machines can beep, ping, and buzz
|
||||
on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm
|
||||
else //Everyone else fails, skip the emote attempt
|
||||
@@ -128,6 +128,36 @@
|
||||
playsound(src.loc, 'sound/effects/slime_squish.ogg', 50, 0) //Credit to DrMinky (freesound.org) for the sound.
|
||||
m_type = 1
|
||||
|
||||
if("yes")
|
||||
var/M = null
|
||||
if(param)
|
||||
for (var/mob/A in view(null, null))
|
||||
if (param == A.name)
|
||||
M = A
|
||||
break
|
||||
if(!M)
|
||||
param = null
|
||||
|
||||
if (param)
|
||||
message = "<B>[src]</B> emits an affirmative blip."
|
||||
playsound(src.loc, 'sound/machines/synth_yes.ogg', 50, 0)
|
||||
m_type = 1
|
||||
|
||||
if("no")
|
||||
var/M = null
|
||||
if(param)
|
||||
for (var/mob/A in view(null, null))
|
||||
if (param == A.name)
|
||||
M = A
|
||||
break
|
||||
if(!M)
|
||||
param = null
|
||||
|
||||
if (param)
|
||||
message = "<B>[src]</B> emits a negative blip."
|
||||
playsound(src.loc, 'sound/machines/synth_no.ogg', 50, 0)
|
||||
m_type = 1
|
||||
|
||||
if("wag")
|
||||
if(body_accessory)
|
||||
if(body_accessory.try_restrictions(src))
|
||||
|
||||
@@ -278,6 +278,11 @@
|
||||
cell_status = "[suit.cell.charge]/[suit.cell.maxcharge]"
|
||||
stat(null, "Suit charge: [cell_status]")
|
||||
|
||||
// I REALLY need to split up status panel things into datums
|
||||
var/mob/living/simple_animal/borer/B = has_brain_worms()
|
||||
if(B && B.controlling)
|
||||
stat("Chemicals", B.chemicals)
|
||||
|
||||
if(mind)
|
||||
if(mind.changeling)
|
||||
stat("Chemical Storage", "[mind.changeling.chem_charges]/[mind.changeling.chem_storage]")
|
||||
@@ -1861,3 +1866,6 @@
|
||||
for(var/obj/item/clothing/C in src) //If they have some clothing equipped that lets them see reagents, they can see reagents
|
||||
if(C.scan_reagents)
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/can_eat(flags = 255)
|
||||
return species && (species.dietflags & flags)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
var/on_CD = 0
|
||||
switch(act)
|
||||
//Cooldown-inducing emotes
|
||||
if("ping","buzz","beep") //halt is exempt because it's used to stop criminal scum //WHOEVER THOUGHT THAT WAS A GOOD IDEA IS GOING TO GET SHOT.
|
||||
if("ping","buzz","beep","yes","no") //halt is exempt because it's used to stop criminal scum //WHOEVER THOUGHT THAT WAS A GOOD IDEA IS GOING TO GET SHOT.
|
||||
on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm
|
||||
//Everything else, including typos of the above emotes
|
||||
else
|
||||
@@ -75,4 +75,34 @@
|
||||
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
|
||||
m_type = 1
|
||||
|
||||
if("yes")
|
||||
var/M = null
|
||||
if(param)
|
||||
for (var/mob/A in view(null, null))
|
||||
if (param == A.name)
|
||||
M = A
|
||||
break
|
||||
if(!M)
|
||||
param = null
|
||||
|
||||
if (param)
|
||||
message = "<B>[src]</B> emits an affirmative blip."
|
||||
playsound(src.loc, 'sound/machines/synth_yes.ogg', 50, 0)
|
||||
m_type = 1
|
||||
|
||||
if("no")
|
||||
var/M = null
|
||||
if(param)
|
||||
for (var/mob/A in view(null, null))
|
||||
if (param == A.name)
|
||||
M = A
|
||||
break
|
||||
if(!M)
|
||||
param = null
|
||||
|
||||
if (param)
|
||||
message = "<B>[src]</B> emits a negative blip."
|
||||
playsound(src.loc, 'sound/machines/synth_no.ogg', 50, 0)
|
||||
m_type = 1
|
||||
|
||||
..(act, m_type, message)
|
||||
@@ -108,7 +108,8 @@
|
||||
pda.ownjob = "Personal Assistant"
|
||||
pda.owner = text("[]", src)
|
||||
pda.name = pda.owner + " (" + pda.ownjob + ")"
|
||||
pda.toff = 1
|
||||
var/datum/data/pda/app/messenger/M = pda.find_program(/datum/data/pda/app/messenger)
|
||||
M.toff = 1
|
||||
..()
|
||||
|
||||
/mob/living/silicon/pai/Login()
|
||||
|
||||
@@ -142,15 +142,24 @@
|
||||
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
|
||||
var/data[0]
|
||||
|
||||
data["receiver_off"] = user.pda.toff
|
||||
data["ringer_off"] = user.pda.silent
|
||||
if(!user.pda)
|
||||
return
|
||||
var/datum/data/pda/app/messenger/M = user.pda.find_program(/datum/data/pda/app/messenger)
|
||||
if(!M)
|
||||
return
|
||||
|
||||
data["receiver_off"] = M.toff
|
||||
data["ringer_off"] = M.silent
|
||||
data["current_ref"] = null
|
||||
data["current_name"] = user.current_pda_messaging
|
||||
|
||||
var/pdas[0]
|
||||
if(!user.pda.toff)
|
||||
if(!M.toff)
|
||||
for(var/obj/item/device/pda/P in PDAs)
|
||||
if(!P.owner || P.toff || P == user.pda || P.hidden) continue
|
||||
var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger)
|
||||
|
||||
if(P == user.pda || !PM || !PM.can_receive())
|
||||
continue
|
||||
var/pda[0]
|
||||
pda["name"] = "[P]"
|
||||
pda["owner"] = "[P.owner]"
|
||||
@@ -163,7 +172,7 @@
|
||||
|
||||
var/messages[0]
|
||||
if(user.current_pda_messaging)
|
||||
for(var/index in user.pda.tnote)
|
||||
for(var/index in M.tnote)
|
||||
if(index["owner"] != user.current_pda_messaging)
|
||||
continue
|
||||
var/msg[0]
|
||||
@@ -188,11 +197,15 @@
|
||||
if(!istype(P)) return
|
||||
|
||||
if(!isnull(P.pda))
|
||||
var/datum/data/pda/app/messenger/M = P.pda.find_program(/datum/data/pda/app/messenger)
|
||||
if(!M)
|
||||
return
|
||||
|
||||
if(href_list["toggler"])
|
||||
P.pda.toff = href_list["toggler"] != "1"
|
||||
M.toff = href_list["toggler"] != "1"
|
||||
return 1
|
||||
else if(href_list["ringer"])
|
||||
P.pda.silent = href_list["ringer"] != "1"
|
||||
M.silent = href_list["ringer"] != "1"
|
||||
return 1
|
||||
else if(href_list["select"])
|
||||
var/s = href_list["select"]
|
||||
@@ -206,7 +219,7 @@
|
||||
return alert("Communications circuits remain uninitialized.")
|
||||
|
||||
var/target = locate(href_list["target"])
|
||||
P.pda.create_message(P, target, 1)
|
||||
M.create_message(P, target, 1)
|
||||
return 1
|
||||
|
||||
/datum/pai_software/med_records
|
||||
|
||||
@@ -174,7 +174,9 @@ var/list/robot_verbs_default = list(
|
||||
rbPDA = new/obj/item/device/pda/ai(src)
|
||||
rbPDA.set_name_and_job(custom_name,braintype)
|
||||
if(scrambledcodes)
|
||||
rbPDA.hidden = 1
|
||||
var/datum/data/pda/app/messenger/M = rbPDA.find_program(/datum/data/pda/app/messenger)
|
||||
if(M)
|
||||
M.hidden = 1
|
||||
|
||||
/mob/living/silicon/robot/binarycheck()
|
||||
if(is_component_functioning("comms"))
|
||||
@@ -1455,4 +1457,8 @@ var/list/robot_verbs_default = list(
|
||||
|
||||
status_flags &= ~CANPUSH
|
||||
|
||||
notify_ai(2)
|
||||
notify_ai(2)
|
||||
|
||||
/mob/living/silicon/robot/adjustOxyLoss(var/amount)
|
||||
if (suiciding)
|
||||
..()
|
||||
|
||||
@@ -340,3 +340,8 @@
|
||||
for(var/obj/machinery/camera/C in A.cameras())
|
||||
cameratext += "[(cameratext == "")? "" : "|"]<A HREF=?src=\ref[src];switchcamera=\ref[C]>[C.c_tag]</A>"
|
||||
src << "[A.alarm_name()]! ([(cameratext)? cameratext : "No Camera"])"
|
||||
|
||||
/mob/living/silicon/adjustToxLoss(var/amount)
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -231,8 +231,8 @@
|
||||
if(L)
|
||||
L << "\icon[P] <b>Message from unknown source: </b>\"[t]\" (Unable to Reply)"
|
||||
P.play_ringtone()
|
||||
P.overlays.Cut()
|
||||
P.overlays += image('icons/obj/pda.dmi', "pda-r")
|
||||
var/datum/data/pda/app/messenger/M = P.find_program(/datum/data/pda/app/messenger)
|
||||
M.set_new(1)
|
||||
|
||||
if("Inject")
|
||||
if( (href_list["tag"]=="radium"? (reagents.get_reagent_amount("radium"))<=(a_boost*a_transfer) : !reagents.get_reagent_amount(href_list["tag"])) )//Special case for radium. If there are only a_boost*a_transfer radium units left.
|
||||
|
||||
Executable
+444
@@ -0,0 +1,444 @@
|
||||
|
||||
//The advanced pea-green monochrome lcd of tomorrow.
|
||||
|
||||
var/global/list/obj/item/device/pda/PDAs = list()
|
||||
|
||||
|
||||
/obj/item/device/pda
|
||||
name = "PDA"
|
||||
desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge."
|
||||
icon = 'icons/obj/pda.dmi'
|
||||
icon_state = "pda"
|
||||
item_state = "electronic"
|
||||
w_class = 1.0
|
||||
slot_flags = SLOT_PDA | SLOT_BELT
|
||||
|
||||
//Main variables
|
||||
var/owner = null
|
||||
var/default_cartridge = 0 // Access level defined by cartridge
|
||||
var/obj/item/weapon/cartridge/cartridge = null //current cartridge
|
||||
var/datum/data/pda/app/current_app = null
|
||||
var/datum/data/pda/app/lastapp = null
|
||||
var/ui_tick = 0
|
||||
|
||||
//Secondary variables
|
||||
var/model_name = "Thinktronic 5230 Personal Data Assistant"
|
||||
var/datum/data/pda/utility/scanmode/scanmode = null
|
||||
|
||||
var/lock_code = "" // Lockcode to unlock uplink
|
||||
var/honkamt = 0 //How many honks left when infected with honk.exe
|
||||
var/mimeamt = 0 //How many silence left when infected with mime.exe
|
||||
var/detonate = 1 // Can the PDA be blown up?
|
||||
var/newmessage = 0 //To remove hackish overlay check
|
||||
var/ttone = "beep" //The ringtone!
|
||||
|
||||
var/list/programs = list(
|
||||
new/datum/data/pda/app/main_menu,
|
||||
new/datum/data/pda/app/notekeeper,
|
||||
new/datum/data/pda/app/messenger,
|
||||
new/datum/data/pda/app/manifest,
|
||||
new/datum/data/pda/app/atmos_scanner,
|
||||
new/datum/data/pda/utility/scanmode/notes,
|
||||
new/datum/data/pda/utility/flashlight)
|
||||
var/list/shortcut_cache = list()
|
||||
var/list/shortcut_cat_order = list()
|
||||
|
||||
var/obj/item/weapon/card/id/id = null //Making it possible to slot an ID card into the PDA so it can function as both.
|
||||
var/ownjob = null //related to above
|
||||
var/ownrank = null // this one is rank, never alt title
|
||||
|
||||
var/obj/item/device/paicard/pai = null // A slot for a personal AI device
|
||||
var/retro_mode = 0
|
||||
|
||||
|
||||
/*
|
||||
* The Actual PDA
|
||||
*/
|
||||
/obj/item/device/pda/New()
|
||||
..()
|
||||
PDAs += src
|
||||
PDAs = sortAtom(PDAs)
|
||||
update_programs()
|
||||
if(default_cartridge)
|
||||
cartridge = new default_cartridge(src)
|
||||
cartridge.update_programs(src)
|
||||
new /obj/item/weapon/pen(src)
|
||||
start_program(find_program(/datum/data/pda/app/main_menu))
|
||||
|
||||
/obj/item/device/pda/proc/can_use()
|
||||
if(!ismob(loc))
|
||||
return 0
|
||||
|
||||
var/mob/M = loc
|
||||
if(M.stat || M.restrained() || M.paralysis || M.stunned || M.weakened)
|
||||
return 0
|
||||
if((src in M.contents) || ( istype(loc, /turf) && in_range(src, M) ))
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/device/pda/GetAccess()
|
||||
if(id)
|
||||
return id.GetAccess()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/device/pda/GetID()
|
||||
return id
|
||||
|
||||
/obj/item/device/pda/MouseDrop(obj/over_object as obj, src_location, over_location)
|
||||
var/mob/M = usr
|
||||
if((!istype(over_object, /obj/screen)) && can_use())
|
||||
return attack_self(M)
|
||||
|
||||
/obj/item/device/pda/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
ui_tick++
|
||||
var/datum/nanoui/old_ui = nanomanager.get_open_ui(user, src, "main")
|
||||
var/auto_update = 1
|
||||
if(!current_app)
|
||||
return
|
||||
|
||||
if(current_app.update == PDA_APP_NOUPDATE && current_app == lastapp)
|
||||
auto_update = 0
|
||||
if(old_ui && (current_app == lastapp && ui_tick % 5 && current_app.update == PDA_APP_UPDATE_SLOW))
|
||||
return
|
||||
|
||||
lastapp = current_app
|
||||
|
||||
var/title = "Personal Data Assistant"
|
||||
|
||||
var/data[0] // This is the data that will be sent to the PDA
|
||||
|
||||
|
||||
data["owner"] = owner // Who is your daddy...
|
||||
data["ownjob"] = ownjob // ...and what does he do?
|
||||
|
||||
// update list of shortcuts, only if they changed
|
||||
if(!shortcut_cache.len)
|
||||
shortcut_cache = list()
|
||||
shortcut_cat_order = list()
|
||||
var/prog_list = programs.Copy()
|
||||
if(cartridge)
|
||||
prog_list |= cartridge.programs
|
||||
|
||||
for(var/A in prog_list)
|
||||
var/datum/data/pda/P = A
|
||||
|
||||
if(P.hidden)
|
||||
continue
|
||||
var/list/cat
|
||||
if(P.category in shortcut_cache)
|
||||
cat = shortcut_cache[P.category]
|
||||
else
|
||||
cat = list()
|
||||
shortcut_cache[P.category] = cat
|
||||
shortcut_cat_order += P.category
|
||||
cat |= list(list(name = P.name, icon = P.icon, ref = "\ref[P]"))
|
||||
|
||||
// force the order of a few core categories
|
||||
shortcut_cat_order = list("General") \
|
||||
+ sortList(shortcut_cat_order - list("General", "Scanners", "Utilities")) \
|
||||
+ list("Scanners", "Utilities")
|
||||
|
||||
data["idInserted"] = (id ? 1 : 0)
|
||||
data["idLink"] = (id ? text("[id.registered_name], [id.assignment]") : "--------")
|
||||
|
||||
data["useRetro"] = retro_mode
|
||||
|
||||
data["cartridge_name"] = cartridge ? cartridge.name : ""
|
||||
data["stationTime"] = worldtime2text()
|
||||
|
||||
data["app"] = list()
|
||||
current_app.update_ui(user, data)
|
||||
data["app"] |= list(
|
||||
"name" = current_app.title,
|
||||
"icon" = current_app.icon,
|
||||
"template" = current_app.template,
|
||||
"has_back" = current_app.has_back)
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "pda.tmpl", title, 630, 600, state = inventory_state)
|
||||
ui.set_state_key("pda")
|
||||
|
||||
// when the ui is first opened this is the data it will use
|
||||
ui.set_initial_data(data)
|
||||
// open the new ui window
|
||||
ui.open()
|
||||
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(auto_update)
|
||||
|
||||
/obj/item/device/pda/attack_self(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
if(active_uplink_check(user))
|
||||
return
|
||||
ui_interact(user) //NanoUI requires this proc
|
||||
|
||||
/obj/item/device/pda/proc/start_program(datum/data/pda/P)
|
||||
if(P && ((P in programs) || (cartridge && (P in cartridge.programs))))
|
||||
return P.start()
|
||||
return 0
|
||||
|
||||
/obj/item/device/pda/proc/find_program(type)
|
||||
var/datum/data/pda/A = locate(type) in programs
|
||||
if(A)
|
||||
return A
|
||||
if(cartridge)
|
||||
A = locate(type) in cartridge.programs
|
||||
if(A)
|
||||
return A
|
||||
return null
|
||||
|
||||
// force the cache to rebuild on update_ui
|
||||
/obj/item/device/pda/proc/update_shortcuts()
|
||||
shortcut_cache.Cut()
|
||||
|
||||
/obj/item/device/pda/proc/update_programs()
|
||||
for(var/A in programs)
|
||||
var/datum/data/pda/P = A
|
||||
P.pda = src
|
||||
|
||||
/obj/item/device/pda/Topic(href, href_list)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
var/mob/user = usr
|
||||
var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main")
|
||||
var/mob/living/U = usr
|
||||
if (usr.stat == DEAD)
|
||||
return 0
|
||||
if(!can_use()) //Why reinvent the wheel? There's a proc that does exactly that.
|
||||
U.unset_machine()
|
||||
if(ui)
|
||||
ui.close()
|
||||
return 0
|
||||
|
||||
add_fingerprint(U)
|
||||
U.set_machine(src)
|
||||
|
||||
if(href_list["radiomenu"] && !isnull(cartridge) && !isnull(cartridge.radio))
|
||||
cartridge.radio.Topic(href, href_list)
|
||||
return 1
|
||||
|
||||
. = 1
|
||||
|
||||
switch(href_list["choice"])
|
||||
if("Home")//Go home, largely replaces the old Return
|
||||
var/datum/data/pda/app/main_menu/A = find_program(/datum/data/pda/app/main_menu)
|
||||
if(A)
|
||||
start_program(A)
|
||||
if("StartProgram")
|
||||
if(href_list["program"])
|
||||
var/datum/data/pda/app/A = locate(href_list["program"])
|
||||
if(A)
|
||||
start_program(A)
|
||||
if("Eject")//Ejects the cart, only done from hub.
|
||||
if (!isnull(cartridge))
|
||||
var/turf/T = loc
|
||||
if(ismob(T))
|
||||
T = T.loc
|
||||
var/obj/item/weapon/cartridge/C = cartridge
|
||||
C.forceMove(T)
|
||||
if(scanmode in C.programs)
|
||||
scanmode = null
|
||||
if(current_app in C.programs)
|
||||
start_program(find_program(/datum/data/pda/app/main_menu))
|
||||
if(C.radio)
|
||||
C.radio.hostpda = null
|
||||
cartridge = null
|
||||
update_shortcuts()
|
||||
if ("Authenticate")//Checks for ID
|
||||
id_check(usr, 1)
|
||||
if("Retro")
|
||||
retro_mode = !retro_mode
|
||||
else
|
||||
if(current_app)
|
||||
. = current_app.Topic(href, href_list)
|
||||
|
||||
//EXTRA FUNCTIONS===================================
|
||||
if ((honkamt > 0) && (prob(60)))//For clown virus.
|
||||
honkamt--
|
||||
playsound(loc, 'sound/items/bikehorn.ogg', 30, 1)
|
||||
|
||||
return // return 1 tells it to refresh the UI in NanoUI
|
||||
|
||||
/obj/item/device/pda/proc/close(mob/user)
|
||||
var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main")
|
||||
ui.close()
|
||||
|
||||
/obj/item/device/pda/verb/verb_reset_pda()
|
||||
set category = "Object"
|
||||
set name = "Reset PDA"
|
||||
set src in usr
|
||||
|
||||
if(issilicon(usr))
|
||||
return
|
||||
|
||||
if(can_use(usr))
|
||||
start_program(find_program(/datum/data/pda/app/main_menu))
|
||||
usr << "<span class='notice'>You press the reset button on \the [src].</span>"
|
||||
else
|
||||
usr << "<span class='notice'>You cannot do this while restrained.</span>"
|
||||
|
||||
/obj/item/device/pda/proc/remove_id()
|
||||
if (id)
|
||||
if (ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.put_in_hands(id)
|
||||
usr << "<span class='notice'>You remove the ID from the [name].</span>"
|
||||
else
|
||||
id.forceMove(get_turf(src))
|
||||
id = null
|
||||
|
||||
/obj/item/device/pda/verb/verb_remove_id()
|
||||
set category = "Object"
|
||||
set name = "Remove id"
|
||||
set src in usr
|
||||
|
||||
if(issilicon(usr))
|
||||
return
|
||||
|
||||
if ( can_use(usr) )
|
||||
if(id)
|
||||
remove_id()
|
||||
else
|
||||
usr << "<span class='notice'>This PDA does not have an ID in it.</span>"
|
||||
else
|
||||
usr << "<span class='notice'>You cannot do this while restrained.</span>"
|
||||
|
||||
|
||||
/obj/item/device/pda/verb/verb_remove_pen()
|
||||
set category = "Object"
|
||||
set name = "Remove pen"
|
||||
set src in usr
|
||||
|
||||
if(issilicon(usr))
|
||||
return
|
||||
|
||||
if ( can_use(usr) )
|
||||
var/obj/item/weapon/pen/O = locate() in src
|
||||
if(O)
|
||||
if (istype(loc, /mob))
|
||||
var/mob/M = loc
|
||||
if(M.get_active_hand() == null)
|
||||
M.put_in_hands(O)
|
||||
usr << "<span class='notice'>You remove \the [O] from \the [src].</span>"
|
||||
return
|
||||
O.forceMove(get_turf(src))
|
||||
else
|
||||
usr << "<span class='notice'>This PDA does not have a pen in it.</span>"
|
||||
else
|
||||
usr << "<span class='notice'>You cannot do this while restrained.</span>"
|
||||
|
||||
|
||||
/obj/item/device/pda/proc/id_check(mob/user as mob, choice as num)//To check for IDs; 1 for in-pda use, 2 for out of pda use.
|
||||
if(choice == 1)
|
||||
if (id)
|
||||
remove_id()
|
||||
else
|
||||
var/obj/item/I = user.get_active_hand()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
user.drop_item()
|
||||
I.forceMove(src)
|
||||
id = I
|
||||
else
|
||||
var/obj/item/weapon/card/I = user.get_active_hand()
|
||||
if (istype(I, /obj/item/weapon/card/id) && I:registered_name)
|
||||
var/obj/old_id = id
|
||||
user.drop_item()
|
||||
I.forceMove(src)
|
||||
id = I
|
||||
user.put_in_hands(old_id)
|
||||
return
|
||||
|
||||
/obj/item/device/pda/attackby(obj/item/C as obj, mob/user as mob, params)
|
||||
..()
|
||||
if(istype(C, /obj/item/weapon/cartridge) && !cartridge)
|
||||
cartridge = C
|
||||
user.drop_item()
|
||||
cartridge.forceMove(src)
|
||||
cartridge.update_programs(src)
|
||||
update_shortcuts()
|
||||
user << "<span class='notice'>You insert [cartridge] into [src].</span>"
|
||||
if(cartridge.radio)
|
||||
cartridge.radio.hostpda = src
|
||||
|
||||
else if(istype(C, /obj/item/weapon/card/id))
|
||||
var/obj/item/weapon/card/id/idcard = C
|
||||
if(!idcard.registered_name)
|
||||
user << "<span class='notice'>\The [src] rejects the ID.</span>"
|
||||
return
|
||||
if(!owner)
|
||||
owner = idcard.registered_name
|
||||
ownjob = idcard.assignment
|
||||
ownrank = idcard.rank
|
||||
name = "PDA-[owner] ([ownjob])"
|
||||
user << "<span class='notice'>Card scanned.</span>"
|
||||
else
|
||||
//Basic safety check. If either both objects are held by user or PDA is on ground and card is in hand.
|
||||
if(((src in user.contents) && (C in user.contents)) || (istype(loc, /turf) && in_range(src, user) && (C in user.contents)) )
|
||||
if( can_use(user) )//If they can still act.
|
||||
id_check(user, 2)
|
||||
user << "<span class='notice'>You put the ID into \the [src]'s slot.</span>"
|
||||
else if(istype(C, /obj/item/device/paicard) && !src.pai)
|
||||
user.drop_item()
|
||||
C.forceMove(src)
|
||||
pai = C
|
||||
user << "<span class='notice'>You slot \the [C] into [src].</span>"
|
||||
else if(istype(C, /obj/item/weapon/pen))
|
||||
var/obj/item/weapon/pen/O = locate() in src
|
||||
if(O)
|
||||
user << "<span class='notice'>There is already a pen in \the [src].</span>"
|
||||
else
|
||||
user.drop_item()
|
||||
C.forceMove(src)
|
||||
user << "<span class='notice'>You slide \the [C] into \the [src].</span>"
|
||||
|
||||
/obj/item/device/pda/attack(mob/living/C as mob, mob/living/user as mob)
|
||||
if (istype(C, /mob/living/carbon) && scanmode)
|
||||
scanmode.scan_mob(C, user)
|
||||
|
||||
/obj/item/device/pda/afterattack(atom/A as mob|obj|turf|area, mob/user as mob, proximity)
|
||||
if(proximity && scanmode)
|
||||
scanmode.scan_atom(A, user)
|
||||
|
||||
/obj/item/device/pda/proc/explode() //This needs tuning.
|
||||
if(!src.detonate) return
|
||||
var/turf/T = get_turf(src.loc)
|
||||
|
||||
if (ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.show_message("<span class='danger'>Your [src] explodes!</span>", 1)
|
||||
|
||||
if(T)
|
||||
T.hotspot_expose(700,125)
|
||||
|
||||
explosion(T, -1, -1, 2, 3)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/device/pda/Destroy()
|
||||
PDAs -= src
|
||||
var/T = get_turf(loc)
|
||||
if (id)
|
||||
id.forceMove(T)
|
||||
if(pai)
|
||||
pai.forceMove(T)
|
||||
current_app = null
|
||||
scanmode = null
|
||||
for(var/A in programs)
|
||||
qdel(A)
|
||||
programs.Cut()
|
||||
if(cartridge)
|
||||
cartridge.forceMove(T)
|
||||
return ..()
|
||||
|
||||
// Pass along the pulse to atoms in contents, largely added so pAIs are vulnerable to EMP
|
||||
/obj/item/device/pda/emp_act(severity)
|
||||
for(var/atom/A in src)
|
||||
A.emp_act(severity)
|
||||
@@ -0,0 +1,91 @@
|
||||
// Special AI/pAI PDAs that cannot explode.
|
||||
/obj/item/device/pda/ai
|
||||
icon_state = "NONE"
|
||||
detonate = 0
|
||||
ttone = "data"
|
||||
|
||||
/obj/item/device/pda/ai/proc/set_name_and_job(newname as text, newjob as text, newrank as null|text)
|
||||
owner = newname
|
||||
ownjob = newjob
|
||||
if(newrank)
|
||||
ownrank = newrank
|
||||
else
|
||||
ownrank = ownjob
|
||||
name = newname + " (" + ownjob + ")"
|
||||
|
||||
/obj/item/device/pda/ai/verb/cmd_send_pdamesg()
|
||||
set category = "AI IM"
|
||||
set name = "Send PDA Message"
|
||||
set src in usr
|
||||
|
||||
if(usr.stat == DEAD)
|
||||
usr << "You can't send PDA messages because you are dead!"
|
||||
return
|
||||
var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger)
|
||||
if(!M)
|
||||
usr << "<span class='warning'>Cannot use messenger!</span>"
|
||||
var/list/plist = M.available_pdas()
|
||||
if (plist)
|
||||
var/c = input(usr, "Please select a PDA") as null|anything in sortList(plist)
|
||||
if (!c) // if the user hasn't selected a PDA file we can't send a message
|
||||
return
|
||||
var/selected = plist[c]
|
||||
M.create_message(usr, selected)
|
||||
|
||||
/obj/item/device/pda/ai/verb/cmd_show_message_log()
|
||||
set category = "AI IM"
|
||||
set name = "Show Message Log"
|
||||
set src in usr
|
||||
|
||||
if(usr.stat == DEAD)
|
||||
usr << "You can't do that because you are dead!"
|
||||
return
|
||||
var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger)
|
||||
if(!M)
|
||||
usr << "<span class='warning'>Cannot use messenger!</span>"
|
||||
var/HTML = "<html><head><title>AI PDA Message Log</title></head><body>"
|
||||
for(var/index in M.tnote)
|
||||
if(index["sent"])
|
||||
HTML += addtext("<i><b>→ To <a href='byond://?src=\ref[src];choice=Message;target=",index["src"],"'>", index["owner"],"</a>:</b></i><br>", index["message"], "<br>")
|
||||
else
|
||||
HTML += addtext("<i><b>← From <a href='byond://?src=\ref[src];choice=Message;target=",index["target"],"'>", index["owner"],"</a>:</b></i><br>", index["message"], "<br>")
|
||||
HTML +="</body></html>"
|
||||
usr << browse(HTML, "window=log;size=400x444;border=1;can_resize=1;can_close=1;can_minimize=0")
|
||||
|
||||
/obj/item/device/pda/ai/verb/cmd_toggle_pda_receiver()
|
||||
set category = "AI IM"
|
||||
set name = "Toggle Sender/Receiver"
|
||||
set src in usr
|
||||
|
||||
if(usr.stat == DEAD)
|
||||
usr << "You can't do that because you are dead!"
|
||||
return
|
||||
var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger)
|
||||
M.toff = !M.toff
|
||||
usr << "<span class='notice'>PDA sender/receiver toggled [(M.toff ? "Off" : "On")]!</span>"
|
||||
|
||||
|
||||
/obj/item/device/pda/ai/verb/cmd_toggle_pda_silent()
|
||||
set category = "AI IM"
|
||||
set name = "Toggle Ringer"
|
||||
set src in usr
|
||||
|
||||
if(usr.stat == DEAD)
|
||||
usr << "You can't do that because you are dead!"
|
||||
return
|
||||
var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger)
|
||||
M.silent = !M.silent
|
||||
usr << "<span class='notice'>PDA ringer toggled [(M.silent ? "Off" : "On")]!</span>"
|
||||
|
||||
/obj/item/device/pda/ai/can_use()
|
||||
return 1
|
||||
|
||||
|
||||
/obj/item/device/pda/ai/attack_self(mob/user as mob)
|
||||
if ((honkamt > 0) && (prob(60)))//For clown virus.
|
||||
honkamt--
|
||||
playsound(loc, 'sound/items/bikehorn.ogg', 30, 1)
|
||||
return
|
||||
|
||||
/obj/item/device/pda/ai/pai
|
||||
ttone = "assist"
|
||||
@@ -0,0 +1,66 @@
|
||||
// Base class for anything that can show up on home screen
|
||||
/datum/data/pda
|
||||
var/icon = "tasks"
|
||||
var/hidden = 0 // program not displayed in main menu
|
||||
var/category = "General" // the category to list it in on the main menu
|
||||
var/obj/item/device/pda/pda // if this is null, and the app is running code, something's gone wrong
|
||||
|
||||
/datum/data/pda/Destroy()
|
||||
pda = null
|
||||
return ..()
|
||||
|
||||
/datum/data/pda/proc/start()
|
||||
|
||||
|
||||
// An app has a button on the home screen and its own UI
|
||||
/datum/data/pda/app
|
||||
name = "App"
|
||||
size = 3
|
||||
var/title = null // what is displayed in the title bar when this is the current app
|
||||
var/template = ""
|
||||
var/update = PDA_APP_UPDATE
|
||||
var/has_back = 0
|
||||
|
||||
/datum/data/pda/app/New()
|
||||
if(!title)
|
||||
title = name
|
||||
|
||||
/datum/data/pda/app/start()
|
||||
pda.current_app = src
|
||||
return 1
|
||||
|
||||
/datum/data/pda/app/proc/update_ui(mob/user as mob, list/data)
|
||||
|
||||
|
||||
// Utilities just have a button on the home screen, but custom code when clicked
|
||||
/datum/data/pda/utility
|
||||
name = "Utility"
|
||||
icon = "gear"
|
||||
size = 1
|
||||
category = "Utilities"
|
||||
|
||||
|
||||
/datum/data/pda/utility/scanmode
|
||||
var/base_name
|
||||
category = "Scanners"
|
||||
|
||||
/datum/data/pda/utility/scanmode/New(obj/item/weapon/cartridge/C)
|
||||
..(C)
|
||||
name = "Enable [base_name]"
|
||||
|
||||
/datum/data/pda/utility/scanmode/start()
|
||||
if(pda.scanmode)
|
||||
pda.scanmode.name = "Enable [pda.scanmode.base_name]"
|
||||
|
||||
if(pda.scanmode == src)
|
||||
pda.scanmode = null
|
||||
else
|
||||
pda.scanmode = src
|
||||
name = "Disable [base_name]"
|
||||
|
||||
pda.update_shortcuts()
|
||||
return 1
|
||||
|
||||
/datum/data/pda/utility/scanmode/proc/scan_mob(mob/living/C as mob, mob/living/user as mob)
|
||||
|
||||
/datum/data/pda/utility/scanmode/proc/scan_atom(atom/A as mob|obj|turf|area, mob/user as mob)
|
||||
@@ -0,0 +1,314 @@
|
||||
/obj/item/weapon/cartridge
|
||||
name = "generic cartridge"
|
||||
desc = "A data cartridge for portable microcomputers."
|
||||
icon = 'icons/obj/pda.dmi'
|
||||
icon_state = "cart"
|
||||
item_state = "electronic"
|
||||
w_class = 1
|
||||
|
||||
var/obj/item/radio/integrated/radio = null
|
||||
|
||||
var/charges = 0
|
||||
|
||||
var/list/stored_data = list()
|
||||
var/list/programs = list()
|
||||
var/list/messenger_plugins = list()
|
||||
|
||||
/obj/item/weapon/cartridge/New()
|
||||
if(ticker && ticker.current_state >= GAME_STATE_SETTING_UP)
|
||||
initialize()
|
||||
|
||||
/obj/item/weapon/cartridge/initialize()
|
||||
if(radio)
|
||||
radio.initialize()
|
||||
..()
|
||||
|
||||
/obj/item/weapon/cartridge/Destroy()
|
||||
if(radio)
|
||||
qdel(radio)
|
||||
radio = null
|
||||
for(var/A in programs)
|
||||
qdel(A)
|
||||
programs.Cut()
|
||||
for(var/A in messenger_plugins)
|
||||
qdel(A)
|
||||
messenger_plugins.Cut()
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/cartridge/proc/update_programs(obj/item/device/pda/pda)
|
||||
for(var/A in programs)
|
||||
var/datum/data/pda/P = A
|
||||
P.pda = pda
|
||||
for(var/A in messenger_plugins)
|
||||
var/datum/data/pda/messenger_plugin/P = A
|
||||
P.pda = pda
|
||||
|
||||
/obj/item/weapon/cartridge/engineering
|
||||
name = "Power-ON Cartridge"
|
||||
icon_state = "cart-e"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/power,
|
||||
new/datum/data/pda/utility/scanmode/halogen)
|
||||
|
||||
/obj/item/weapon/cartridge/atmos
|
||||
name = "BreatheDeep Cartridge"
|
||||
icon_state = "cart-a"
|
||||
programs = list(
|
||||
new/datum/data/pda/utility/scanmode/gas)
|
||||
|
||||
/obj/item/weapon/cartridge/medical
|
||||
name = "Med-U Cartridge"
|
||||
icon_state = "cart-m"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/crew_records/medical,
|
||||
new/datum/data/pda/utility/scanmode/medical)
|
||||
|
||||
/obj/item/weapon/cartridge/chemistry
|
||||
name = "ChemWhiz Cartridge"
|
||||
icon_state = "cart-chem"
|
||||
programs = list(
|
||||
new/datum/data/pda/utility/scanmode/reagent)
|
||||
|
||||
/obj/item/weapon/cartridge/security
|
||||
name = "R.O.B.U.S.T. Cartridge"
|
||||
icon_state = "cart-s"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/crew_records/security,
|
||||
new/datum/data/pda/app/secbot_control)
|
||||
|
||||
/obj/item/weapon/cartridge/security/initialize()
|
||||
radio = new /obj/item/radio/integrated/beepsky(src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/cartridge/detective
|
||||
name = "D.E.T.E.C.T. Cartridge"
|
||||
icon_state = "cart-s"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/crew_records/medical,
|
||||
new/datum/data/pda/utility/scanmode/medical,
|
||||
|
||||
new/datum/data/pda/app/crew_records/security)
|
||||
|
||||
|
||||
/obj/item/weapon/cartridge/janitor
|
||||
name = "CustodiPRO Cartridge"
|
||||
desc = "The ultimate in clean-room design."
|
||||
icon_state = "cart-j"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/janitor)
|
||||
|
||||
/obj/item/weapon/cartridge/lawyer
|
||||
name = "P.R.O.V.E. Cartridge"
|
||||
icon_state = "cart-s"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/crew_records/security)
|
||||
|
||||
/obj/item/weapon/cartridge/clown
|
||||
name = "Honkworks 5.0"
|
||||
icon_state = "cart-clown"
|
||||
charges = 5
|
||||
programs = list(
|
||||
new/datum/data/pda/utility/honk)
|
||||
messenger_plugins = list(
|
||||
new/datum/data/pda/messenger_plugin/virus/clown)
|
||||
|
||||
/obj/item/weapon/cartridge/mime
|
||||
name = "Gestur-O 1000"
|
||||
icon_state = "cart-mi"
|
||||
charges = 5
|
||||
messenger_plugins = list(
|
||||
new/datum/data/pda/messenger_plugin/virus/mime)
|
||||
|
||||
/*
|
||||
/obj/item/weapon/cartridge/botanist
|
||||
name = "Green Thumb v4.20"
|
||||
icon_state = "cart-b"
|
||||
access_flora = 1
|
||||
*/
|
||||
|
||||
/obj/item/weapon/cartridge/signal
|
||||
name = "generic signaler cartridge"
|
||||
desc = "A data cartridge with an integrated radio signaler module."
|
||||
programs = list(
|
||||
new/datum/data/pda/app/signaller)
|
||||
|
||||
/obj/item/weapon/cartridge/signal/initialize()
|
||||
radio = new /obj/item/radio/integrated/signal(src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/cartridge/signal/toxins
|
||||
name = "Signal Ace 2"
|
||||
desc = "Complete with integrated radio signaler!"
|
||||
icon_state = "cart-tox"
|
||||
programs = list(
|
||||
new/datum/data/pda/utility/scanmode/gas,
|
||||
|
||||
new/datum/data/pda/utility/scanmode/reagent,
|
||||
|
||||
new/datum/data/pda/app/signaller)
|
||||
|
||||
/obj/item/weapon/cartridge/quartermaster
|
||||
name = "Space Parts & Space Vendors Cartridge"
|
||||
desc = "Perfect for the Quartermaster on the go!"
|
||||
icon_state = "cart-q"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/supply,
|
||||
new/datum/data/pda/app/mule_control)
|
||||
|
||||
/obj/item/weapon/cartridge/quartermaster/initialize()
|
||||
radio = new /obj/item/radio/integrated/mule(src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/cartridge/head
|
||||
name = "Easy-Record DELUXE"
|
||||
icon_state = "cart-h"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/status_display)
|
||||
|
||||
/obj/item/weapon/cartridge/hop
|
||||
name = "HumanResources9001"
|
||||
icon_state = "cart-h"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/crew_records/security,
|
||||
|
||||
new/datum/data/pda/app/janitor,
|
||||
|
||||
new/datum/data/pda/app/supply,
|
||||
new/datum/data/pda/app/mule_control,
|
||||
|
||||
new/datum/data/pda/app/status_display)
|
||||
|
||||
/obj/item/weapon/cartridge/hop/initialize()
|
||||
radio = new /obj/item/radio/integrated/mule(src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/cartridge/hos
|
||||
name = "R.O.B.U.S.T. DELUXE"
|
||||
icon_state = "cart-hos"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/crew_records/security,
|
||||
new/datum/data/pda/app/secbot_control,
|
||||
|
||||
new/datum/data/pda/app/status_display)
|
||||
|
||||
/obj/item/weapon/cartridge/hos/initialize()
|
||||
radio = new /obj/item/radio/integrated/beepsky(src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/cartridge/ce
|
||||
name = "Power-On DELUXE"
|
||||
icon_state = "cart-ce"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/power,
|
||||
new/datum/data/pda/utility/scanmode/halogen,
|
||||
|
||||
new/datum/data/pda/utility/scanmode/gas,
|
||||
|
||||
new/datum/data/pda/app/status_display)
|
||||
|
||||
/obj/item/weapon/cartridge/cmo
|
||||
name = "Med-U DELUXE"
|
||||
icon_state = "cart-cmo"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/crew_records/medical,
|
||||
new/datum/data/pda/utility/scanmode/medical,
|
||||
|
||||
new/datum/data/pda/utility/scanmode/reagent,
|
||||
|
||||
new/datum/data/pda/app/status_display)
|
||||
|
||||
/obj/item/weapon/cartridge/rd
|
||||
name = "Signal Ace DELUXE"
|
||||
icon_state = "cart-rd"
|
||||
programs = list(
|
||||
new/datum/data/pda/utility/scanmode/gas,
|
||||
|
||||
new/datum/data/pda/utility/scanmode/reagent,
|
||||
|
||||
new/datum/data/pda/app/signaller,
|
||||
|
||||
new/datum/data/pda/app/status_display)
|
||||
|
||||
/obj/item/weapon/cartridge/rd/initialize()
|
||||
radio = new /obj/item/radio/integrated/signal(src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/cartridge/captain
|
||||
name = "Value-PAK Cartridge"
|
||||
desc = "Now with 200% more value!"
|
||||
icon_state = "cart-c"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/power,
|
||||
new/datum/data/pda/utility/scanmode/halogen,
|
||||
|
||||
new/datum/data/pda/utility/scanmode/gas,
|
||||
|
||||
new/datum/data/pda/app/crew_records/medical,
|
||||
new/datum/data/pda/utility/scanmode/medical,
|
||||
|
||||
new/datum/data/pda/utility/scanmode/reagent,
|
||||
|
||||
new/datum/data/pda/app/crew_records/security,
|
||||
new/datum/data/pda/app/secbot_control,
|
||||
|
||||
new/datum/data/pda/app/janitor,
|
||||
|
||||
new/datum/data/pda/app/supply,
|
||||
|
||||
new/datum/data/pda/app/status_display)
|
||||
|
||||
/obj/item/weapon/cartridge/captain/initialize()
|
||||
radio = new /obj/item/radio/integrated/beepsky(src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/cartridge/supervisor
|
||||
name = "Easy-Record DELUXE"
|
||||
icon_state = "cart-h"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/crew_records/security,
|
||||
|
||||
new/datum/data/pda/app/status_display)
|
||||
|
||||
/obj/item/weapon/cartridge/centcom
|
||||
name = "Value-PAK Cartridge"
|
||||
desc = "Now with 200% more value!"
|
||||
icon_state = "cart-c"
|
||||
programs = list(
|
||||
new/datum/data/pda/app/power,
|
||||
new/datum/data/pda/utility/scanmode/halogen,
|
||||
|
||||
new/datum/data/pda/utility/scanmode/gas,
|
||||
|
||||
new/datum/data/pda/app/crew_records/medical,
|
||||
new/datum/data/pda/utility/scanmode/medical,
|
||||
|
||||
new/datum/data/pda/utility/scanmode/reagent,
|
||||
|
||||
new/datum/data/pda/app/crew_records/security,
|
||||
new/datum/data/pda/app/secbot_control,
|
||||
|
||||
new/datum/data/pda/app/janitor,
|
||||
|
||||
new/datum/data/pda/app/supply,
|
||||
new/datum/data/pda/app/mule_control,
|
||||
|
||||
new/datum/data/pda/app/status_display)
|
||||
|
||||
/obj/item/weapon/cartridge/centcom/initialize()
|
||||
radio = new /obj/item/radio/integrated/beepsky(src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/cartridge/syndicate
|
||||
name = "Detomatix Cartridge"
|
||||
icon_state = "cart"
|
||||
var/initial_remote_door_id = "smindicate" //Make sure this matches the syndicate shuttle's shield/door id!! //don't ask about the name, testing.
|
||||
charges = 4
|
||||
programs = list(
|
||||
new/datum/data/pda/utility/toggle_door)
|
||||
messenger_plugins = list(
|
||||
new/datum/data/pda/messenger_plugin/virus/detonate)
|
||||
|
||||
/obj/item/weapon/cartridge/syndicate/New()
|
||||
var/datum/data/pda/utility/toggle_door/D = programs[1]
|
||||
if(istype(D))
|
||||
D.remote_door_id = initial_remote_door_id
|
||||
@@ -0,0 +1,420 @@
|
||||
/datum/data/pda/app/status_display
|
||||
name = "Status Display"
|
||||
icon = "list-alt"
|
||||
template = "pda_status_display"
|
||||
category = "Utilities"
|
||||
|
||||
var/message1 // used for status_displays
|
||||
var/message2
|
||||
|
||||
/datum/data/pda/app/status_display/update_ui(mob/user as mob, list/data)
|
||||
data["records"] = list(
|
||||
"message1" = message1 ? message1 : "(none)",
|
||||
"message2" = message2 ? message2 : "(none)")
|
||||
|
||||
/datum/data/pda/app/status_display/Topic(href, list/href_list)
|
||||
switch(href_list["choice"])
|
||||
if("Status")
|
||||
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("setmsg2")
|
||||
message2 = input("Line 2", "Enter Message Text", message2) as text|null
|
||||
else
|
||||
post_status(href_list["statdisp"])
|
||||
|
||||
/datum/data/pda/app/status_display/proc/post_status(var/command, var/data1, var/data2)
|
||||
var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435)
|
||||
if(!frequency)
|
||||
return
|
||||
|
||||
var/datum/signal/status_signal = new
|
||||
status_signal.source = src
|
||||
status_signal.transmission_method = 1
|
||||
status_signal.data["command"] = command
|
||||
|
||||
switch(command)
|
||||
if("message")
|
||||
status_signal.data["msg1"] = data1
|
||||
status_signal.data["msg2"] = data2
|
||||
var/mob/user = pda.fingerprintslast
|
||||
if(istype(pda.loc, /mob/living))
|
||||
name = pda.loc
|
||||
log_admin("STATUS: [user] set status screen with [pda]. Message: [data1] [data2]")
|
||||
message_admins("STATUS: [user] set status screen with [pda]. Message: [data1] [data2]")
|
||||
|
||||
if("alert")
|
||||
status_signal.data["picture_state"] = data1
|
||||
|
||||
spawn(0)
|
||||
frequency.post_signal(src, status_signal)
|
||||
|
||||
|
||||
/datum/data/pda/app/signaller
|
||||
name = "Signaler System"
|
||||
icon = "rss"
|
||||
template = "pda_signaller"
|
||||
category = "Utilities"
|
||||
|
||||
/datum/data/pda/app/signaller/update_ui(mob/user as mob, list/data)
|
||||
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/signal))
|
||||
var/obj/item/radio/integrated/signal/R = pda.cartridge.radio
|
||||
data["signal_freq"] = format_frequency(R.frequency)
|
||||
data["signal_code"] = R.code
|
||||
|
||||
/datum/data/pda/app/signaller/Topic(href, list/href_list)
|
||||
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/signal))
|
||||
var/obj/item/radio/integrated/signal/R = pda.cartridge.radio
|
||||
|
||||
switch(href_list["choice"])
|
||||
if("Send Signal")
|
||||
spawn(0)
|
||||
R.send_signal("ACTIVATE")
|
||||
|
||||
if("Signal Frequency")
|
||||
var/new_frequency = sanitize_frequency(R.frequency + text2num(href_list["sfreq"]))
|
||||
R.set_frequency(new_frequency)
|
||||
|
||||
if("Signal Code")
|
||||
R.code += text2num(href_list["scode"])
|
||||
R.code = round(R.code)
|
||||
R.code = min(100, R.code)
|
||||
R.code = max(1, R.code)
|
||||
|
||||
/datum/data/pda/app/power
|
||||
name = "Power Monitor"
|
||||
icon = "exclamation-triangle"
|
||||
template = "pda_power"
|
||||
category = "Engineering"
|
||||
update = PDA_APP_UPDATE_SLOW
|
||||
|
||||
var/obj/machinery/computer/monitor/powmonitor = null
|
||||
|
||||
/datum/data/pda/app/power/update_ui(mob/user as mob, list/data)
|
||||
update = PDA_APP_UPDATE_SLOW
|
||||
|
||||
if (powmonitor && !isnull(powmonitor.powernet))
|
||||
data["records"] = list(
|
||||
"powerconnected" = 1,
|
||||
"poweravail" = powmonitor.powernet.avail,
|
||||
"powerload" = num2text(powmonitor.powernet.viewload, 10),
|
||||
"powerdemand" = powmonitor.powernet.load,
|
||||
"apcs" = apc_repository.apc_data(powmonitor))
|
||||
has_back = 1
|
||||
else
|
||||
data["records"] = list(
|
||||
"powerconnected" = 0,
|
||||
"powermonitors" = powermonitor_repository.powermonitor_data())
|
||||
has_back = 0
|
||||
|
||||
/datum/data/pda/app/power/Topic(href, list/href_list)
|
||||
switch(href_list["choice"])
|
||||
if("Power Select")
|
||||
var/pref = href_list["target"]
|
||||
powmonitor = locate(pref)
|
||||
update = PDA_APP_UPDATE
|
||||
if("Back")
|
||||
powmonitor = null
|
||||
update = PDA_APP_UPDATE
|
||||
|
||||
/datum/data/pda/app/crew_records
|
||||
var/datum/data/record/general_records = null
|
||||
|
||||
/datum/data/pda/app/crew_records/update_ui(mob/user as mob, list/data)
|
||||
var/list/records[0]
|
||||
|
||||
if(general_records && general_records in data_core.general)
|
||||
data["records"] = records
|
||||
records["general"] = general_records.fields
|
||||
return records
|
||||
else
|
||||
for(var/A in sortRecord(data_core.general))
|
||||
var/datum/data/record/R = A
|
||||
records += list(list(Name = R.fields["name"], "ref" = "\ref[R]"))
|
||||
data["recordsList"] = records
|
||||
return null
|
||||
|
||||
/datum/data/pda/app/crew_records/Topic(href, list/href_list)
|
||||
switch(href_list["choice"])
|
||||
if("Records")
|
||||
var/datum/data/record/R = locate(href_list["target"])
|
||||
if (R in data_core.general)
|
||||
load_records(R)
|
||||
if("Back")
|
||||
general_records = null
|
||||
has_back = 0
|
||||
|
||||
/datum/data/pda/app/crew_records/proc/load_records(datum/data/record/R)
|
||||
general_records = R
|
||||
has_back = 1
|
||||
|
||||
/datum/data/pda/app/crew_records/medical
|
||||
name = "Medical Records"
|
||||
icon = "heartbeat"
|
||||
template = "pda_medical"
|
||||
category = "Medical"
|
||||
|
||||
var/datum/data/record/medical_records = null
|
||||
|
||||
/datum/data/pda/app/crew_records/medical/update_ui(mob/user as mob, list/data)
|
||||
var/list/records = ..()
|
||||
if(!records)
|
||||
return
|
||||
|
||||
if(medical_records && medical_records in data_core.medical)
|
||||
records["medical"] = medical_records.fields
|
||||
|
||||
return records
|
||||
|
||||
/datum/data/pda/app/crew_records/medical/load_records(datum/data/record/R)
|
||||
..(R)
|
||||
for(var/A in data_core.medical)
|
||||
var/datum/data/record/E = A
|
||||
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
|
||||
medical_records = E
|
||||
break
|
||||
|
||||
/datum/data/pda/app/crew_records/security
|
||||
name = "Security Records"
|
||||
icon = "tags"
|
||||
template = "pda_security"
|
||||
category = "Security"
|
||||
|
||||
var/datum/data/record/security_records = null
|
||||
|
||||
/datum/data/pda/app/crew_records/security/update_ui(mob/user as mob, list/data)
|
||||
var/list/records = ..()
|
||||
if(!records)
|
||||
return
|
||||
|
||||
if(security_records && security_records in data_core.security)
|
||||
records["security"] = security_records.fields
|
||||
|
||||
return records
|
||||
|
||||
/datum/data/pda/app/crew_records/security/load_records(datum/data/record/R)
|
||||
..(R)
|
||||
for(var/A in data_core.security)
|
||||
var/datum/data/record/E = A
|
||||
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
|
||||
security_records = E
|
||||
break
|
||||
|
||||
/datum/data/pda/app/secbot_control
|
||||
name = "Security Bot Access"
|
||||
icon = "rss"
|
||||
template = "pda_secbot"
|
||||
category = "Security"
|
||||
|
||||
/datum/data/pda/app/secbot_control/update_ui(mob/user as mob, list/data)
|
||||
var/botsData[0]
|
||||
var/beepskyData[0]
|
||||
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/beepsky))
|
||||
var/obj/item/radio/integrated/beepsky/SC = pda.cartridge.radio
|
||||
beepskyData["active"] = SC.active ? sanitize(SC.active.name) : null
|
||||
has_back = SC.active ? 1 : 0
|
||||
if(SC.active && !isnull(SC.botstatus))
|
||||
var/area/loca = SC.botstatus["loca"]
|
||||
var/loca_name = sanitize(loca.name)
|
||||
beepskyData["botstatus"] = list("loca" = loca_name, "mode" = SC.botstatus["mode"])
|
||||
else
|
||||
beepskyData["botstatus"] = list("loca" = null, "mode" = -1)
|
||||
var/botsCount=0
|
||||
if(SC.botlist && SC.botlist.len)
|
||||
for(var/obj/machinery/bot/B in SC.botlist)
|
||||
botsCount++
|
||||
if(B.loc)
|
||||
botsData[++botsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]")
|
||||
|
||||
if(!botsData.len)
|
||||
botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
|
||||
|
||||
beepskyData["bots"] = botsData
|
||||
beepskyData["count"] = botsCount
|
||||
|
||||
else
|
||||
beepskyData["active"] = 0
|
||||
botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
|
||||
beepskyData["botstatus"] = list("loca" = null, "mode" = null)
|
||||
beepskyData["bots"] = botsData
|
||||
beepskyData["count"] = 0
|
||||
has_back = 0
|
||||
|
||||
data["beepsky"] = beepskyData
|
||||
|
||||
/datum/data/pda/app/secbot_control/Topic(href, list/href_list)
|
||||
switch(href_list["choice"])
|
||||
if("Back")
|
||||
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/beepsky))
|
||||
pda.cartridge.radio.Topic(null, list(radiomenu = "1", op = "botlist"))
|
||||
|
||||
/datum/data/pda/app/mule_control
|
||||
name = "Delivery Bot Control"
|
||||
icon = "truck"
|
||||
template = "pda_mule"
|
||||
category = "Quartermaster"
|
||||
|
||||
/datum/data/pda/app/mule_control/update_ui(mob/user as mob, list/data)
|
||||
var/muleData[0]
|
||||
var/mulebotsData[0]
|
||||
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/mule))
|
||||
var/obj/item/radio/integrated/mule/QC = pda.cartridge.radio
|
||||
muleData["active"] = QC.active ? sanitize(QC.active.name) : null
|
||||
has_back = QC.active ? 1 : 0
|
||||
if(QC.active && !isnull(QC.botstatus))
|
||||
var/area/loca = QC.botstatus["loca"]
|
||||
var/loca_name = sanitize(loca.name)
|
||||
muleData["botstatus"] = list("loca" = loca_name, "mode" = QC.botstatus["mode"],"home"=QC.botstatus["home"],"powr" = QC.botstatus["powr"],"retn" =QC.botstatus["retn"], "pick"=QC.botstatus["pick"], "load" = QC.botstatus["load"], "dest" = sanitize(QC.botstatus["dest"]))
|
||||
|
||||
else
|
||||
muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null)
|
||||
|
||||
|
||||
var/mulebotsCount=0
|
||||
for(var/obj/machinery/bot/B in QC.botlist)
|
||||
mulebotsCount++
|
||||
if(B.loc)
|
||||
mulebotsData[++mulebotsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]")
|
||||
|
||||
if(!mulebotsData.len)
|
||||
mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
|
||||
|
||||
muleData["bots"] = mulebotsData
|
||||
muleData["count"] = mulebotsCount
|
||||
|
||||
else
|
||||
muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null)
|
||||
muleData["active"] = 0
|
||||
mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "ref"= null)
|
||||
muleData["bots"] = mulebotsData
|
||||
muleData["count"] = 0
|
||||
has_back = 0
|
||||
|
||||
data["mulebot"] = muleData
|
||||
|
||||
/datum/data/pda/app/mule_control/Topic(href, list/href_list)
|
||||
switch(href_list["choice"])
|
||||
if("Back")
|
||||
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/radio/integrated/mule))
|
||||
pda.cartridge.radio.Topic(null, list(radiomenu = "1", op = "botlist"))
|
||||
|
||||
/datum/data/pda/app/supply
|
||||
name = "Supply Records"
|
||||
icon = "file-text-o"
|
||||
template = "pda_supply"
|
||||
category = "Quartermaster"
|
||||
update = PDA_APP_UPDATE_SLOW
|
||||
|
||||
/datum/data/pda/app/supply/update_ui(mob/user as mob, list/data)
|
||||
var/supplyData[0]
|
||||
|
||||
if(shuttle_master.supply.mode == SHUTTLE_CALL)
|
||||
supplyData["shuttle_moving"] = 1
|
||||
|
||||
if(shuttle_master.supply.z != ZLEVEL_STATION)
|
||||
supplyData["shuttle_loc"] = "station"
|
||||
else
|
||||
supplyData["shuttle_loc"] = "centcom"
|
||||
|
||||
supplyData["shuttle_time"] = "([shuttle_master.supply.timeLeft(600)] Mins)"
|
||||
|
||||
var/supplyOrderCount = 0
|
||||
var/supplyOrderData[0]
|
||||
for(var/S in shuttle_master.shoppinglist)
|
||||
var/datum/supply_order/SO = S
|
||||
supplyOrderCount++
|
||||
supplyOrderData[++supplyOrderData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "ApprovedBy" = SO.orderedby, "Comment" = html_encode(SO.comment))
|
||||
|
||||
if(!supplyOrderData.len)
|
||||
supplyOrderData[++supplyOrderData.len] = list("Number" = null, "Name" = null, "OrderedBy"=null)
|
||||
|
||||
supplyData["approved"] = supplyOrderData
|
||||
supplyData["approved_count"] = supplyOrderCount
|
||||
|
||||
var/requestCount = 0
|
||||
var/requestData[0]
|
||||
for(var/S in shuttle_master.requestlist)
|
||||
var/datum/supply_order/SO = S
|
||||
requestCount++
|
||||
requestData[++requestData.len] = list("Number" = SO.ordernum, "Name" = html_encode(SO.object.name), "OrderedBy" = SO.orderedby, "Comment" = html_encode(SO.comment))
|
||||
|
||||
if(!requestData.len)
|
||||
requestData[++requestData.len] = list("Number" = null, "Name" = null, "orderedBy" = null, "Comment" = null)
|
||||
|
||||
supplyData["requests"] = requestData
|
||||
supplyData["requests_count"] = requestCount
|
||||
|
||||
data["supply"] = supplyData
|
||||
|
||||
/datum/data/pda/app/janitor
|
||||
name = "Custodial Locator"
|
||||
icon = "trash-o"
|
||||
template = "pda_janitor"
|
||||
category = "Utilities"
|
||||
update = PDA_APP_UPDATE_SLOW
|
||||
|
||||
/datum/data/pda/app/janitor/update_ui(mob/user as mob, list/data)
|
||||
var/JaniData[0]
|
||||
var/turf/cl = get_turf(pda)
|
||||
|
||||
if(cl)
|
||||
JaniData["user_loc"] = list("x" = cl.x, "y" = cl.y)
|
||||
else
|
||||
JaniData["user_loc"] = list("x" = 0, "y" = 0)
|
||||
var/MopData[0]
|
||||
for(var/obj/item/weapon/mop/M in janitorial_equipment)
|
||||
var/turf/ml = get_turf(M)
|
||||
if(ml)
|
||||
if(ml.z != cl.z)
|
||||
continue
|
||||
var/direction = get_dir(pda, M)
|
||||
MopData[++MopData.len] = list ("x" = ml.x, "y" = ml.y, "dir" = uppertext(dir2text(direction)), "status" = M.reagents.total_volume ? "Wet" : "Dry")
|
||||
|
||||
if(!MopData.len)
|
||||
MopData[++MopData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
|
||||
|
||||
|
||||
var/BucketData[0]
|
||||
for(var/obj/structure/mopbucket/B in janitorial_equipment)
|
||||
var/turf/bl = get_turf(B)
|
||||
if(bl)
|
||||
if(bl.z != cl.z)
|
||||
continue
|
||||
var/direction = get_dir(pda,B)
|
||||
BucketData[++BucketData.len] = list ("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100)
|
||||
|
||||
if(!BucketData.len)
|
||||
BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
|
||||
|
||||
var/CbotData[0]
|
||||
for(var/obj/machinery/bot/cleanbot/B in aibots)
|
||||
var/turf/bl = get_turf(B)
|
||||
if(bl)
|
||||
if(bl.z != cl.z)
|
||||
continue
|
||||
var/direction = get_dir(pda,B)
|
||||
CbotData[++CbotData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.on ? "Online" : "Offline")
|
||||
|
||||
|
||||
if(!CbotData.len)
|
||||
CbotData[++CbotData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
|
||||
var/CartData[0]
|
||||
for(var/obj/structure/janitorialcart/B in janitorial_equipment)
|
||||
var/turf/bl = get_turf(B)
|
||||
if(bl)
|
||||
if(bl.z != cl.z)
|
||||
continue
|
||||
var/direction = get_dir(pda,B)
|
||||
CartData[++CartData.len] = list("x" = bl.x, "y" = bl.y, "dir" = uppertext(dir2text(direction)), "status" = B.reagents.total_volume/100)
|
||||
if(!CartData.len)
|
||||
CartData[++CartData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
|
||||
|
||||
JaniData["mops"] = MopData
|
||||
JaniData["buckets"] = BucketData
|
||||
JaniData["cleanbots"] = CbotData
|
||||
JaniData["carts"] = CartData
|
||||
data["janitor"] = JaniData
|
||||
@@ -0,0 +1,16 @@
|
||||
var/list/chatrooms = list()
|
||||
|
||||
/datum/chatroom
|
||||
var/name = "Generic Chatroom"
|
||||
var/list/logged_in = list()
|
||||
var/list/logs = list() // chat logs
|
||||
var/list/banned = list() // banned users
|
||||
var/list/whitelist = list() // whitelisted users
|
||||
var/list/muted = list()
|
||||
var/topic = "" // topic message for the chatroom
|
||||
var/password = "" // blank for no password.
|
||||
var/operator = "" // name of the operator
|
||||
|
||||
/datum/chatroom/proc/attempt_connect(var/obj/item/device/pda/device, var/obj/password)
|
||||
if(!device)
|
||||
return
|
||||
@@ -0,0 +1,106 @@
|
||||
/datum/data/pda/app/main_menu
|
||||
icon = "home"
|
||||
template = "pda_main_menu"
|
||||
hidden = 1
|
||||
|
||||
/datum/data/pda/app/main_menu/update_ui(mob/user as mob, list/data)
|
||||
title = pda.name
|
||||
|
||||
data["app"]["is_home"] = 1
|
||||
|
||||
data["apps"] = pda.shortcut_cache
|
||||
data["categories"] = pda.shortcut_cat_order
|
||||
data["pai"] = !isnull(pda.pai) // pAI inserted?
|
||||
|
||||
/datum/data/pda/app/main_menu/Topic(href, list/href_list)
|
||||
switch(href_list["choice"])
|
||||
if("UpdateInfo")
|
||||
pda.ownjob = pda.id.assignment
|
||||
pda.ownrank = pda.id.rank
|
||||
pda.name = "PDA-[pda.owner] ([pda.ownjob])"
|
||||
if("pai")
|
||||
if(pda.pai)
|
||||
if(pda.pai.loc != pda)
|
||||
pda.pai = null
|
||||
else
|
||||
switch(href_list["option"])
|
||||
if("1") // Configure pAI device
|
||||
pda.pai.attack_self(usr)
|
||||
if("2") // Eject pAI device
|
||||
var/turf/T = get_turf_or_move(pda.loc)
|
||||
if(T)
|
||||
pda.pai.loc = T
|
||||
pda.pai = null
|
||||
|
||||
/datum/data/pda/app/notekeeper
|
||||
name = "Notekeeper"
|
||||
icon = "sticky-note-o"
|
||||
template = "pda_notekeeper"
|
||||
|
||||
var/note = null
|
||||
var/notehtml = ""
|
||||
|
||||
/datum/data/pda/app/notekeeper/start()
|
||||
. = ..()
|
||||
if(!note)
|
||||
note = "Congratulations, your station has chosen the [pda.model_name]!"
|
||||
|
||||
/datum/data/pda/app/notekeeper/update_ui(mob/user as mob, list/data)
|
||||
data["note"] = note // current pda notes
|
||||
|
||||
/datum/data/pda/app/notekeeper/Topic(href, list/href_list)
|
||||
switch(href_list["choice"])
|
||||
if("Edit")
|
||||
var/n = input("Please enter message", name, notehtml) as message
|
||||
if(pda.loc == usr)
|
||||
note = adminscrub(n)
|
||||
notehtml = html_decode(note)
|
||||
note = replacetext(note, "\n", "<br>")
|
||||
else
|
||||
pda.close(usr)
|
||||
|
||||
/datum/data/pda/app/manifest
|
||||
name = "Crew Manifest"
|
||||
icon = "user"
|
||||
template = "pda_manifest"
|
||||
update = PDA_APP_UPDATE_SLOW
|
||||
|
||||
/datum/data/pda/app/manifest/update_ui(mob/user as mob, list/data)
|
||||
data_core.get_manifest_json()
|
||||
data["manifest"] = list("__json_cache" = ManifestJSON)
|
||||
|
||||
/datum/data/pda/app/manifest/Topic(href, list/href_list)
|
||||
|
||||
/datum/data/pda/app/atmos_scanner
|
||||
name = "Atmospheric Scan"
|
||||
icon = "fire"
|
||||
template = "pda_atmos_scan"
|
||||
category = "Utilities"
|
||||
update = PDA_APP_UPDATE_SLOW
|
||||
|
||||
/datum/data/pda/app/atmos_scanner/update_ui(mob/user as mob, list/data)
|
||||
var/turf/T = get_turf(user.loc)
|
||||
if(!isnull(T))
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
|
||||
var/pressure = environment.return_pressure()
|
||||
var/total_moles = environment.total_moles()
|
||||
|
||||
if (total_moles)
|
||||
var/o2_level = environment.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)
|
||||
data["aircontents"] = list(\
|
||||
"pressure" = "[round(pressure,0.1)]",\
|
||||
"nitrogen" = "[round(n2_level*100,0.1)]",\
|
||||
"oxygen" = "[round(o2_level*100,0.1)]",\
|
||||
"carbon_dioxide" = "[round(co2_level*100,0.1)]",\
|
||||
"plasma" = "[round(plasma_level*100,0.01)]",\
|
||||
"other" = "[round(unknown_level, 0.01)]",\
|
||||
"temp" = "[round(environment.temperature-T0C,0.1)]",\
|
||||
"reading" = 1\
|
||||
)
|
||||
if(isnull(data["aircontents"]))
|
||||
data["aircontents"] = list("reading" = 0)
|
||||
@@ -0,0 +1,271 @@
|
||||
/datum/data/pda/app/messenger
|
||||
name = "Messenger"
|
||||
icon = "comments-o"
|
||||
title = "SpaceMessenger V4.0.1"
|
||||
template = "pda_messenger"
|
||||
|
||||
var/silent = 0 //To beep or not to beep, that is the question
|
||||
var/toff = 0 //If 1, messenger disabled
|
||||
var/list/tnote[0] //Current Texts
|
||||
var/last_text //No text spamming
|
||||
var/list/ttone_sound = list("beep" = 'sound/machines/twobeep.ogg',
|
||||
"boom" = 'sound/effects/explosionfar.ogg',
|
||||
"slip" = 'sound/misc/slip.ogg',
|
||||
"honk" = 'sound/items/bikehorn.ogg',
|
||||
"SKREE" = 'sound/voice/shriek1.ogg',
|
||||
"holy" = 'sound/items/PDA/ambicha4-short.ogg',
|
||||
"xeno" = 'sound/voice/hiss1.ogg')
|
||||
|
||||
var/m_hidden = 0 // Is the PDA hidden from the PDA list?
|
||||
var/active_conversation = null // New variable that allows us to only view a single conversation.
|
||||
var/list/conversations = list() // For keeping up with who we have PDA messsages from.
|
||||
|
||||
/datum/data/pda/app/messenger/start()
|
||||
. = ..()
|
||||
set_new(0)
|
||||
|
||||
/datum/data/pda/app/messenger/update_ui(mob/user as mob, list/data)
|
||||
data["silent"] = silent // does the pda make noise when it receives a message?
|
||||
data["toff"] = toff // is the messenger function turned off?
|
||||
data["active_conversation"] = active_conversation // Which conversation are we following right now?
|
||||
|
||||
var/convopdas[0]
|
||||
var/pdas[0]
|
||||
var/count = 0
|
||||
for(var/A in PDAs)
|
||||
var/obj/item/device/pda/P = A
|
||||
var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger)
|
||||
|
||||
if (!P.owner || PM.toff || P == pda || PM.m_hidden)
|
||||
continue
|
||||
if(conversations.Find("\ref[P]"))
|
||||
convopdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "1")))
|
||||
else
|
||||
pdas.Add(list(list("Name" = "[P]", "Reference" = "\ref[P]", "Detonate" = "[P.detonate]", "inconvo" = "0")))
|
||||
count++
|
||||
|
||||
data["convopdas"] = convopdas
|
||||
data["pdas"] = pdas
|
||||
data["pda_count"] = count
|
||||
|
||||
data["messagescount"] = tnote.len
|
||||
data["messages"] = tnote
|
||||
|
||||
has_back = active_conversation
|
||||
if(active_conversation)
|
||||
for(var/c in tnote)
|
||||
if(c["target"] == active_conversation)
|
||||
data["convo_name"] = sanitize(c["owner"])
|
||||
data["convo_job"] = sanitize(c["job"])
|
||||
break
|
||||
|
||||
var/list/plugins = list()
|
||||
if(pda.cartridge)
|
||||
for(var/A in pda.cartridge.messenger_plugins)
|
||||
var/datum/data/pda/messenger_plugin/P = A
|
||||
plugins += list(list(name = P.name, icon = P.icon, ref = "\ref[P]"))
|
||||
data["plugins"] = plugins
|
||||
|
||||
if(pda.cartridge)
|
||||
data["charges"] = pda.cartridge.charges ? pda.cartridge.charges : 0
|
||||
|
||||
/datum/data/pda/app/messenger/Topic(href, list/href_list)
|
||||
set_new(0)
|
||||
|
||||
switch(href_list["choice"])
|
||||
if("Toggle Messenger")
|
||||
toff = !toff
|
||||
if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status
|
||||
silent = !silent
|
||||
if("Clear")//Clears messages
|
||||
if(href_list["option"] == "All")
|
||||
tnote.Cut()
|
||||
conversations.Cut()
|
||||
if(href_list["option"] == "Convo")
|
||||
var/new_tnote[0]
|
||||
for(var/i in tnote)
|
||||
if(i["target"] != active_conversation)
|
||||
new_tnote[++new_tnote.len] = i
|
||||
tnote = new_tnote
|
||||
conversations.Remove(active_conversation)
|
||||
|
||||
active_conversation = null
|
||||
if("Ringtone")
|
||||
var/t = input("Please enter new ringtone", name, pda.ttone) as text
|
||||
if (in_range(pda, usr) && pda.loc == usr)
|
||||
if (t)
|
||||
if(pda.hidden_uplink && pda.hidden_uplink.check_trigger(usr, lowertext(t), lowertext(pda.lock_code)))
|
||||
usr << "The PDA softly beeps."
|
||||
pda.close(usr)
|
||||
else
|
||||
t = sanitize(copytext(t, 1, 20))
|
||||
pda.ttone = t
|
||||
else
|
||||
pda.close(usr)
|
||||
return 0
|
||||
if("Message")
|
||||
var/obj/item/device/pda/P = locate(href_list["target"])
|
||||
create_message(usr, P)
|
||||
if(href_list["target"] in conversations) // Need to make sure the message went through, if not welp.
|
||||
active_conversation = href_list["target"]
|
||||
if("Select Conversation")
|
||||
var/P = href_list["convo"]
|
||||
for(var/n in conversations)
|
||||
if(P == n)
|
||||
active_conversation = P
|
||||
if("Messenger Plugin")
|
||||
if(!href_list["target"] || !href_list["plugin"])
|
||||
return
|
||||
|
||||
var/obj/item/device/pda/P = locate(href_list["target"])
|
||||
if(!P)
|
||||
usr << "PDA not found."
|
||||
|
||||
var/datum/data/pda/messenger_plugin/plugin = locate(href_list["plugin"])
|
||||
if(plugin && plugin in pda.cartridge.messenger_plugins)
|
||||
plugin.messenger = src
|
||||
plugin.user_act(usr, P)
|
||||
if("Back")
|
||||
active_conversation = null
|
||||
|
||||
/datum/data/pda/app/messenger/proc/set_new(isnew)
|
||||
if(pda.newmessage == isnew)
|
||||
return
|
||||
|
||||
if(pda.newmessage)
|
||||
//To clear message overlays.
|
||||
pda.overlays.Cut()
|
||||
pda.newmessage = 0
|
||||
|
||||
icon = "comments"
|
||||
pda.update_shortcuts()
|
||||
else
|
||||
pda.overlays.Cut()
|
||||
pda.overlays += image('icons/obj/pda.dmi', "pda-r")
|
||||
pda.newmessage = 1
|
||||
|
||||
icon = "comments-o"
|
||||
pda.update_shortcuts()
|
||||
|
||||
/datum/data/pda/app/messenger/proc/create_message(var/mob/living/U, var/obj/item/device/pda/P)
|
||||
var/t = input(U, "Please enter message", name, null) as text|null
|
||||
if(!t)
|
||||
return
|
||||
t = sanitize(copytext(t, 1, MAX_MESSAGE_LEN))
|
||||
t = readd_quotes(t)
|
||||
if (!t || !istype(P))
|
||||
return
|
||||
if (!in_range(pda, U) && pda.loc != U)
|
||||
return
|
||||
|
||||
var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger)
|
||||
|
||||
if (!PM || PM.toff || toff)
|
||||
return
|
||||
|
||||
if (last_text && world.time < last_text + 5)
|
||||
return
|
||||
|
||||
if(!pda.can_use())
|
||||
return
|
||||
|
||||
last_text = world.time
|
||||
// check if telecomms I/O route 1459 is stable
|
||||
//var/telecomms_intact = telecomms_process(P.owner, owner, t)
|
||||
var/obj/machinery/message_server/useMS = null
|
||||
if(message_servers)
|
||||
for(var/A in message_servers)
|
||||
var/obj/machinery/message_server/MS = A
|
||||
//PDAs are now dependent on the Message Server.
|
||||
if(MS.active)
|
||||
useMS = MS
|
||||
break
|
||||
|
||||
var/datum/signal/signal = pda.telecomms_process()
|
||||
|
||||
var/useTC = 0
|
||||
if(signal)
|
||||
if(signal.data["done"])
|
||||
useTC = 1
|
||||
var/turf/pos = get_turf(P)
|
||||
if(pos.z in signal.data["level"])
|
||||
useTC = 2
|
||||
//Let's make this barely readable
|
||||
if(signal.data["compression"] > 0)
|
||||
t = Gibberish(t, signal.data["compression"] + 50)
|
||||
|
||||
if(useMS && useTC) // only send the message if it's stable
|
||||
if(useTC != 2) // Does our recipient have a broadcaster on their level?
|
||||
U << "ERROR: Cannot reach recipient."
|
||||
return
|
||||
useMS.send_pda_message("[P.owner]","[pda.owner]","[t]")
|
||||
tnote.Add(list(list("sent" = 1, "owner" = "[P.owner]", "job" = "[P.ownjob]", "message" = "[t]", "target" = "\ref[P]")))
|
||||
PM.tnote.Add(list(list("sent" = 0, "owner" = "[pda.owner]", "job" = "[pda.ownjob]", "message" = "[t]", "target" = "\ref[pda]")))
|
||||
pda.investigate_log("<span class='game say'>PDA Message - <span class='name'>[U.key] - [pda.owner]</span> -> <span class='name'>[P.owner]</span>: <span class='message'>[t]</span></span>", "pda")
|
||||
if(!conversations.Find("\ref[P]"))
|
||||
conversations.Add("\ref[P]")
|
||||
if(!PM.conversations.Find("\ref[pda]"))
|
||||
PM.conversations.Add("\ref[pda]")
|
||||
|
||||
PM.play_ringtone()
|
||||
//Search for holder of the PDA.
|
||||
var/mob/living/L = null
|
||||
if(P.loc && isliving(P.loc))
|
||||
L = P.loc
|
||||
//Maybe they are a pAI!
|
||||
else
|
||||
L = get(P, /mob/living/silicon)
|
||||
|
||||
|
||||
if(L)
|
||||
L << "\icon[P] <b>Message from [pda.owner] ([pda.ownjob]), </b>\"[t]\" (<a href='byond://?src=\ref[P];choice=Message;skiprefresh=1;target=\ref[pda]'>Reply</a>)"
|
||||
nanomanager.update_user_uis(L, P) // Update the receiving user's PDA UI so that they can see the new message
|
||||
|
||||
nanomanager.update_user_uis(U, P) // Update the sending user's PDA UI so that they can see the new message
|
||||
set_new(1)
|
||||
log_pda("[usr] (PDA: [src.name]) sent \"[t]\" to [P.name]")
|
||||
else
|
||||
U << "<span class='notice'>ERROR: Messaging server is not responding.</span>"
|
||||
|
||||
/datum/data/pda/app/messenger/proc/play_ringtone()
|
||||
if (!silent)
|
||||
var/S
|
||||
|
||||
if(pda.ttone in ttone_sound)
|
||||
S = ttone_sound[pda.ttone]
|
||||
else
|
||||
S = 'sound/machines/twobeep.ogg'
|
||||
playsound(pda.loc, S, 50, 1)
|
||||
for(var/mob/O in hearers(3, pda.loc))
|
||||
if(!silent)
|
||||
O.show_message(text("\icon[pda] *[pda.ttone]*"))
|
||||
|
||||
/datum/data/pda/app/messenger/proc/available_pdas()
|
||||
var/list/names = list()
|
||||
var/list/plist = list()
|
||||
var/list/namecounts = list()
|
||||
|
||||
if (toff)
|
||||
usr << "Turn on your receiver in order to send messages."
|
||||
return
|
||||
|
||||
for(var/A in PDAs)
|
||||
var/obj/item/device/pda/P = A
|
||||
var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger)
|
||||
|
||||
if(!P.owner || !PM || PM.hidden || P == pda || PM.toff)
|
||||
continue
|
||||
|
||||
var/name = P.owner
|
||||
if (name in names)
|
||||
namecounts[name]++
|
||||
name = text("[name] ([namecounts[name]])")
|
||||
else
|
||||
names.Add(name)
|
||||
namecounts[name] = 1
|
||||
|
||||
plist[text("[name]")] = P
|
||||
return plist
|
||||
|
||||
/datum/data/pda/app/messenger/proc/can_receive()
|
||||
return pda.owner && !toff && !hidden
|
||||
@@ -0,0 +1,69 @@
|
||||
/datum/data/pda/messenger_plugin
|
||||
var/datum/data/pda/app/messenger/messenger
|
||||
|
||||
/datum/data/pda/messenger_plugin/proc/user_act(mob/user as mob, obj/item/device/pda/P)
|
||||
|
||||
|
||||
/datum/data/pda/messenger_plugin/virus
|
||||
name = "*Send Virus*"
|
||||
|
||||
/datum/data/pda/messenger_plugin/virus/user_act(mob/user as mob, obj/item/device/pda/P)
|
||||
var/datum/data/pda/app/messenger/M = P.find_program(/datum/data/pda/app/messenger)
|
||||
|
||||
if(M && !M.toff && pda.cartridge.charges > 0)
|
||||
pda.cartridge.charges--
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
/datum/data/pda/messenger_plugin/virus/clown
|
||||
icon = "star"
|
||||
|
||||
/datum/data/pda/messenger_plugin/virus/clown/user_act(mob/user as mob, obj/item/device/pda/P)
|
||||
. = ..(user, P)
|
||||
if(.)
|
||||
user.show_message("<span class=notice>Virus sent!</span>", 1)
|
||||
P.honkamt = (rand(15,20))
|
||||
P.ttone = "honk"
|
||||
|
||||
|
||||
/datum/data/pda/messenger_plugin/virus/mime
|
||||
icon = "arrow-circle-down"
|
||||
|
||||
/datum/data/pda/messenger_plugin/virus/mime/user_act(mob/user as mob, obj/item/device/pda/P)
|
||||
. = ..(user, P)
|
||||
if(.)
|
||||
user.show_message("<span class=notice>Virus sent!</span>", 1)
|
||||
var/datum/data/pda/app/messenger/M = P.find_program(/datum/data/pda/app/messenger)
|
||||
if(M)
|
||||
M.silent = 1
|
||||
P.ttone = "silence"
|
||||
|
||||
|
||||
/datum/data/pda/messenger_plugin/virus/detonate
|
||||
name = "*Detonate*"
|
||||
icon = "exclamation-circle"
|
||||
|
||||
/datum/data/pda/messenger_plugin/virus/detonate/user_act(mob/user as mob, obj/item/device/pda/P)
|
||||
. = ..(user, P)
|
||||
if(.)
|
||||
var/difficulty = 0
|
||||
|
||||
if(pda.cartridge)
|
||||
difficulty += pda.cartridge.programs.len / 2
|
||||
else
|
||||
difficulty += 2
|
||||
|
||||
if(prob(difficulty * 12) || (pda.hidden_uplink))
|
||||
user.show_message("<span class=warning>An error flashes on your [pda].</span>", 1)
|
||||
else if (prob(difficulty * 3))
|
||||
user.show_message("<span class=danger>Energy feeds back into your [pda]!</span>", 1)
|
||||
pda.close(user)
|
||||
pda.explode()
|
||||
log_admin("[key_name(user)] just attempted to blow up [P] with the Detomatix cartridge but failed, blowing themselves up")
|
||||
message_admins("[key_name_admin(user)] just attempted to blow up [P] with the Detomatix cartridge but failed, blowing themselves up", 1)
|
||||
else
|
||||
user.show_message("<span class=notice>Success!</span>", 1)
|
||||
log_admin("[key_name(user)] just attempted to blow up [P] with the Detomatix cartridge and succeded")
|
||||
message_admins("[key_name_admin(user)] just attempted to blow up [P] with the Detomatix cartridge and succeded", 1)
|
||||
P.explode()
|
||||
@@ -0,0 +1,193 @@
|
||||
/obj/item/device/pda/medical
|
||||
default_cartridge = /obj/item/weapon/cartridge/medical
|
||||
icon_state = "pda-medical"
|
||||
|
||||
/obj/item/device/pda/viro
|
||||
default_cartridge = /obj/item/weapon/cartridge/medical
|
||||
icon_state = "pda-virology"
|
||||
|
||||
/obj/item/device/pda/engineering
|
||||
default_cartridge = /obj/item/weapon/cartridge/engineering
|
||||
icon_state = "pda-engineer"
|
||||
|
||||
/obj/item/device/pda/security
|
||||
default_cartridge = /obj/item/weapon/cartridge/security
|
||||
icon_state = "pda-security"
|
||||
|
||||
/obj/item/device/pda/detective
|
||||
default_cartridge = /obj/item/weapon/cartridge/detective
|
||||
icon_state = "pda-security"
|
||||
|
||||
/obj/item/device/pda/warden
|
||||
default_cartridge = /obj/item/weapon/cartridge/security
|
||||
icon_state = "pda-warden"
|
||||
|
||||
/obj/item/device/pda/janitor
|
||||
default_cartridge = /obj/item/weapon/cartridge/janitor
|
||||
icon_state = "pda-janitor"
|
||||
ttone = "slip"
|
||||
|
||||
/obj/item/device/pda/toxins
|
||||
default_cartridge = /obj/item/weapon/cartridge/signal/toxins
|
||||
icon_state = "pda-science"
|
||||
ttone = "boom"
|
||||
|
||||
/obj/item/device/pda/clown
|
||||
default_cartridge = /obj/item/weapon/cartridge/clown
|
||||
icon_state = "pda-clown"
|
||||
desc = "A portable microcomputer by Thinktronic Systems, LTD. The surface is coated with polytetrafluoroethylene and banana drippings."
|
||||
ttone = "honk"
|
||||
|
||||
/obj/item/device/pda/clown/Crossed(AM as mob|obj) //Clown PDA is slippery.
|
||||
if (istype(AM, /mob/living/carbon))
|
||||
var/mob/living/carbon/M = AM
|
||||
M.slip("pda", 8, 5, 0, 1)
|
||||
|
||||
/obj/item/device/pda/mime
|
||||
default_cartridge = /obj/item/weapon/cartridge/mime
|
||||
icon_state = "pda-mime"
|
||||
ttone = "silence"
|
||||
|
||||
/obj/item/device/pda/mime/New()
|
||||
var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger)
|
||||
if(M)
|
||||
M.silent = 1
|
||||
|
||||
/obj/item/device/pda/heads
|
||||
default_cartridge = /obj/item/weapon/cartridge/head
|
||||
icon_state = "pda-h"
|
||||
|
||||
/obj/item/device/pda/heads/hop
|
||||
default_cartridge = /obj/item/weapon/cartridge/hop
|
||||
icon_state = "pda-hop"
|
||||
|
||||
/obj/item/device/pda/heads/hos
|
||||
default_cartridge = /obj/item/weapon/cartridge/hos
|
||||
icon_state = "pda-hos"
|
||||
|
||||
/obj/item/device/pda/heads/ce
|
||||
default_cartridge = /obj/item/weapon/cartridge/ce
|
||||
icon_state = "pda-ce"
|
||||
|
||||
/obj/item/device/pda/heads/cmo
|
||||
default_cartridge = /obj/item/weapon/cartridge/cmo
|
||||
icon_state = "pda-cmo"
|
||||
|
||||
/obj/item/device/pda/heads/rd
|
||||
default_cartridge = /obj/item/weapon/cartridge/rd
|
||||
icon_state = "pda-rd"
|
||||
|
||||
/obj/item/device/pda/captain
|
||||
default_cartridge = /obj/item/weapon/cartridge/captain
|
||||
icon_state = "pda-captain"
|
||||
detonate = 0
|
||||
//toff = 1
|
||||
|
||||
/obj/item/device/pda/heads/ntrep
|
||||
default_cartridge = /obj/item/weapon/cartridge/supervisor
|
||||
icon_state = "pda-h"
|
||||
|
||||
/obj/item/device/pda/heads/magistrate
|
||||
default_cartridge = /obj/item/weapon/cartridge/supervisor
|
||||
icon_state = "pda-h"
|
||||
|
||||
/obj/item/device/pda/heads/blueshield
|
||||
default_cartridge = /obj/item/weapon/cartridge/hos
|
||||
icon_state = "pda-h"
|
||||
|
||||
/obj/item/device/pda/cargo
|
||||
default_cartridge = /obj/item/weapon/cartridge/quartermaster
|
||||
icon_state = "pda-cargo"
|
||||
|
||||
/obj/item/device/pda/quartermaster
|
||||
default_cartridge = /obj/item/weapon/cartridge/quartermaster
|
||||
icon_state = "pda-qm"
|
||||
|
||||
/obj/item/device/pda/shaftminer
|
||||
icon_state = "pda-miner"
|
||||
|
||||
/obj/item/device/pda/syndicate
|
||||
default_cartridge = /obj/item/weapon/cartridge/syndicate
|
||||
icon_state = "pda-syndi"
|
||||
name = "Military PDA"
|
||||
owner = "John Doe"
|
||||
|
||||
/obj/item/device/pda/syndicate/New()
|
||||
var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger)
|
||||
if(M)
|
||||
M.m_hidden = 1
|
||||
|
||||
/obj/item/device/pda/chaplain
|
||||
icon_state = "pda-chaplain"
|
||||
ttone = "holy"
|
||||
|
||||
/obj/item/device/pda/lawyer
|
||||
default_cartridge = /obj/item/weapon/cartridge/lawyer
|
||||
icon_state = "pda-lawyer"
|
||||
ttone = "..."
|
||||
|
||||
/obj/item/device/pda/botanist
|
||||
//default_cartridge = /obj/item/weapon/cartridge/botanist
|
||||
icon_state = "pda-hydro"
|
||||
|
||||
/obj/item/device/pda/roboticist
|
||||
icon_state = "pda-roboticist"
|
||||
|
||||
/obj/item/device/pda/librarian
|
||||
icon_state = "pda-library"
|
||||
desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a WGW-11 series e-reader."
|
||||
model_name = "Thinktronic 5290 WGW-11 Series E-reader and Personal Data Assistant"
|
||||
|
||||
/obj/item/device/pda/librarian/New()
|
||||
var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger)
|
||||
if(M)
|
||||
M.silent = 1 //Quiet in the library!
|
||||
|
||||
/obj/item/device/pda/clear
|
||||
icon_state = "pda-transp"
|
||||
desc = "A portable microcomputer by Thinktronic Systems, LTD. This is model is a special edition with a transparent case."
|
||||
model_name = "Thinktronic 5230 Personal Data Assistant Deluxe Special Max Turbo Limited Edition"
|
||||
|
||||
/obj/item/device/pda/chef
|
||||
icon_state = "pda-chef"
|
||||
|
||||
/obj/item/device/pda/bar
|
||||
icon_state = "pda-bartender"
|
||||
|
||||
/obj/item/device/pda/atmos
|
||||
default_cartridge = /obj/item/weapon/cartridge/atmos
|
||||
icon_state = "pda-atmos"
|
||||
|
||||
/obj/item/device/pda/chemist
|
||||
default_cartridge = /obj/item/weapon/cartridge/chemistry
|
||||
icon_state = "pda-chemistry"
|
||||
|
||||
/obj/item/device/pda/geneticist
|
||||
default_cartridge = /obj/item/weapon/cartridge/medical
|
||||
icon_state = "pda-genetics"
|
||||
|
||||
/obj/item/device/pda/centcom
|
||||
default_cartridge = /obj/item/weapon/cartridge/centcom
|
||||
icon_state = "pda-h"
|
||||
|
||||
//Some spare PDAs in a box
|
||||
/obj/item/weapon/storage/box/PDAs
|
||||
name = "spare PDAs"
|
||||
desc = "A box of spare PDA microcomputers."
|
||||
icon = 'icons/obj/pda.dmi'
|
||||
icon_state = "pdabox"
|
||||
|
||||
/obj/item/weapon/storage/box/PDAs/New()
|
||||
..()
|
||||
new /obj/item/device/pda(src)
|
||||
new /obj/item/device/pda(src)
|
||||
new /obj/item/device/pda(src)
|
||||
new /obj/item/device/pda(src)
|
||||
new /obj/item/weapon/cartridge/head(src)
|
||||
|
||||
var/newcart = pick( /obj/item/weapon/cartridge/engineering,
|
||||
/obj/item/weapon/cartridge/security,
|
||||
/obj/item/weapon/cartridge/medical,
|
||||
/obj/item/weapon/cartridge/signal/toxins,
|
||||
/obj/item/weapon/cartridge/quartermaster)
|
||||
new newcart(src)
|
||||
@@ -0,0 +1,267 @@
|
||||
/obj/item/radio/integrated
|
||||
name = "\improper PDA radio module"
|
||||
desc = "An electronic radio system of Nanotrasen origin."
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "power_mod"
|
||||
var/obj/item/device/pda/hostpda = null
|
||||
var/list/botlist = null // list of bots
|
||||
var/obj/machinery/bot/active // the active bot; if null, show bot list
|
||||
var/list/botstatus // the status signal sent by the bot
|
||||
var/bot_type //The type of bot it is.
|
||||
var/bot_filter //Determines which radio filter to use.
|
||||
|
||||
var/control_freq = 1447
|
||||
|
||||
var/on = 0 //Are we currently active??
|
||||
var/menu_message = ""
|
||||
|
||||
/obj/item/radio/integrated/New()
|
||||
..()
|
||||
if (istype(loc.loc, /obj/item/device/pda))
|
||||
hostpda = loc.loc
|
||||
if (bot_filter)
|
||||
spawn(5)
|
||||
add_to_radio(bot_filter)
|
||||
|
||||
/obj/item/radio/integrated/Destroy()
|
||||
if(radio_controller)
|
||||
radio_controller.remove_object(src, control_freq)
|
||||
hostpda = null
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/integrated/proc/post_signal(var/freq, var/key, var/value, var/key2, var/value2, var/key3, var/value3,var/key4, var/value4, s_filter)
|
||||
|
||||
//world << "Post: [freq]: [key]=[value], [key2]=[value2]"
|
||||
var/datum/radio_frequency/frequency = radio_controller.return_frequency(freq)
|
||||
|
||||
if(!frequency)
|
||||
return
|
||||
|
||||
var/datum/signal/signal = new()
|
||||
signal.source = src
|
||||
signal.transmission_method = 1
|
||||
signal.data[key] = value
|
||||
if(key2)
|
||||
signal.data[key2] = value2
|
||||
if(key3)
|
||||
signal.data[key3] = value3
|
||||
if(key4)
|
||||
signal.data[key4] = value4
|
||||
|
||||
frequency.post_signal(src, signal, filter = s_filter)
|
||||
|
||||
/obj/item/radio/integrated/receive_signal(datum/signal/signal)
|
||||
/*var/obj/item/device/pda/P = src.loc
|
||||
|
||||
|
||||
world << "recvd:[P] : [signal.source]"
|
||||
for(var/d in signal.data)
|
||||
world << "- [d] = [signal.data[d]]"
|
||||
*/
|
||||
|
||||
if (signal.data["type"] == bot_type)
|
||||
if(!botlist)
|
||||
botlist = new()
|
||||
|
||||
if(!(signal.source in botlist))
|
||||
botlist += signal.source
|
||||
|
||||
if(active == signal.source)
|
||||
var/list/b = signal.data
|
||||
botstatus = b.Copy()
|
||||
|
||||
/obj/item/radio/integrated/Topic(href, href_list)
|
||||
..()
|
||||
var/obj/item/device/pda/PDA = src.hostpda
|
||||
|
||||
switch(href_list["op"])
|
||||
|
||||
if("control")
|
||||
active = locate(href_list["bot"])
|
||||
spawn(0)
|
||||
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter)
|
||||
|
||||
if("scanbots") // find all bots
|
||||
botlist = null
|
||||
spawn(0)
|
||||
post_signal(control_freq, "command", "bot_status", s_filter = bot_filter)
|
||||
|
||||
if("botlist")
|
||||
active = null
|
||||
|
||||
if("stop", "go")
|
||||
spawn(0)
|
||||
post_signal(control_freq, "command", href_list["op"], "active", active, s_filter = bot_filter)
|
||||
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter)
|
||||
|
||||
if("summon")
|
||||
spawn(0)
|
||||
post_signal(control_freq, "command", "summon", "active", active, "target", get_turf(PDA) , "useraccess", PDA.GetAccess(), s_filter = bot_filter)
|
||||
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter)
|
||||
|
||||
/obj/item/radio/integrated/proc/add_to_radio(bot_filter) //Master filter control for bots. Must be placed in the bot's local New() to support map spawned bots.
|
||||
if(radio_controller)
|
||||
radio_controller.add_object(src, control_freq, filter = bot_filter)
|
||||
|
||||
|
||||
/obj/item/radio/integrated/beepsky
|
||||
bot_filter = RADIO_SECBOT
|
||||
bot_type = SEC_BOT
|
||||
|
||||
/obj/item/radio/integrated/medbot
|
||||
bot_filter = RADIO_MEDBOT
|
||||
bot_type = MED_BOT
|
||||
|
||||
/obj/item/radio/integrated/floorbot
|
||||
bot_filter = RADIO_FLOORBOT
|
||||
bot_type = FLOOR_BOT
|
||||
|
||||
/obj/item/radio/integrated/cleanbot
|
||||
bot_filter = RADIO_CLEANBOT
|
||||
bot_type = CLEAN_BOT
|
||||
|
||||
/obj/item/radio/integrated/mule
|
||||
//var/list/botlist = null // list of bots
|
||||
//var/obj/machinery/bot/mulebot/active // the active bot; if null, show bot list
|
||||
//var/list/botstatus // the status signal sent by the bot
|
||||
var/list/beacons
|
||||
|
||||
var/beacon_freq = 1400
|
||||
control_freq = 1447
|
||||
|
||||
// create a new QM cartridge, and register to receive bot control & beacon message
|
||||
/obj/item/radio/integrated/mule/New()
|
||||
..()
|
||||
spawn(5)
|
||||
if(radio_controller)
|
||||
radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT)
|
||||
radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS)
|
||||
spawn(10)
|
||||
post_signal(beacon_freq, "findbeacon", "delivery", s_filter = RADIO_NAVBEACONS)
|
||||
|
||||
/obj/item/radio/integrated/mule/Destroy()
|
||||
if(radio_controller)
|
||||
radio_controller.remove_object(src,beacon_freq)
|
||||
return ..()
|
||||
|
||||
// receive radio signals
|
||||
// can detect bot status signals
|
||||
// and beacon locations
|
||||
// create/populate lists as they are recvd
|
||||
|
||||
/obj/item/radio/integrated/mule/receive_signal(datum/signal/signal)
|
||||
if(signal.data["type"] == MULE_BOT)
|
||||
if(!botlist)
|
||||
botlist = new()
|
||||
|
||||
if(!(signal.source in botlist))
|
||||
botlist += signal.source
|
||||
|
||||
if(active == signal.source)
|
||||
var/list/b = signal.data
|
||||
botstatus = b.Copy()
|
||||
|
||||
else if(signal.data["beacon"])
|
||||
if(!beacons)
|
||||
beacons = new()
|
||||
|
||||
beacons[signal.data["beacon"] ] = signal.source
|
||||
|
||||
/obj/item/radio/integrated/mule/Topic(href, href_list)
|
||||
//..()
|
||||
//var/obj/item/device/pda/PDA = src.hostpda
|
||||
var/cmd = "command"
|
||||
if(active)
|
||||
cmd = "command [active.suffix]"
|
||||
|
||||
switch(href_list["op"])
|
||||
if("control")
|
||||
active = locate(href_list["bot"])
|
||||
|
||||
if("scanbots") // find all bots
|
||||
botlist = null
|
||||
|
||||
if("botlist")
|
||||
active = null
|
||||
|
||||
if("unload")
|
||||
spawn(0)
|
||||
post_signal(control_freq, cmd, "unload", s_filter = RADIO_MULEBOT)
|
||||
if("setdest")
|
||||
if(beacons)
|
||||
var/dest = input("Select Bot Destination", "Mulebot [active.suffix] Interlink", active.destination) as null|anything in beacons
|
||||
if(dest)
|
||||
spawn(0)
|
||||
post_signal(control_freq, cmd, "target", "destination", dest, s_filter = RADIO_MULEBOT)
|
||||
|
||||
if("retoff")
|
||||
spawn(0)
|
||||
post_signal(control_freq, cmd, "autoret", "value", 0, s_filter = RADIO_MULEBOT)
|
||||
|
||||
if("reton")
|
||||
spawn(0)
|
||||
post_signal(control_freq, cmd, "autoret", "value", 1, s_filter = RADIO_MULEBOT)
|
||||
|
||||
if("pickoff")
|
||||
spawn(0)
|
||||
post_signal(control_freq, cmd, "autopick", "value", 0, s_filter = RADIO_MULEBOT)
|
||||
|
||||
if("pickon")
|
||||
spawn(0)
|
||||
post_signal(control_freq, cmd, "autopick", "value", 1, s_filter = RADIO_MULEBOT)
|
||||
|
||||
if("stop", "go", "home")
|
||||
spawn(0)
|
||||
post_signal(control_freq, cmd, href_list["op"], s_filter = RADIO_MULEBOT)
|
||||
|
||||
spawn(10)
|
||||
post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Radio Cartridge, essentially a signaler.
|
||||
*/
|
||||
|
||||
|
||||
/obj/item/radio/integrated/signal
|
||||
var/frequency = 1457
|
||||
var/code = 30.0
|
||||
var/last_transmission
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
/obj/item/radio/integrated/signal/Destroy()
|
||||
if(radio_controller)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
return ..()
|
||||
|
||||
/obj/item/radio/integrated/signal/initialize()
|
||||
if(!radio_controller)
|
||||
return
|
||||
if (src.frequency < PUBLIC_LOW_FREQ || src.frequency > PUBLIC_HIGH_FREQ)
|
||||
src.frequency = sanitize_frequency(src.frequency)
|
||||
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/item/radio/integrated/signal/proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = radio_controller.add_object(src, frequency)
|
||||
|
||||
/obj/item/radio/integrated/signal/proc/send_signal(message="ACTIVATE")
|
||||
|
||||
if(last_transmission && world.time < (last_transmission + 5))
|
||||
return
|
||||
last_transmission = world.time
|
||||
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
var/turf/T = get_turf(src)
|
||||
lastsignalers.Add("[time] <B>:</B> [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) <B>:</B> [format_frequency(frequency)]/[code]")
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.source = src
|
||||
signal.encryption = code
|
||||
signal.data["message"] = message
|
||||
|
||||
spawn(0)
|
||||
radio_connection.post_signal(src, signal)
|
||||
@@ -0,0 +1,198 @@
|
||||
/datum/data/pda/utility/flashlight
|
||||
name = "Enable Flashlight"
|
||||
icon = "lightbulb-o"
|
||||
|
||||
var/fon = 0 //Is the flashlight function on?
|
||||
var/f_lum = 2 //Luminosity for the flashlight function
|
||||
|
||||
/datum/data/pda/utility/flashlight/start()
|
||||
fon = !fon
|
||||
name = fon ? "Disable Flashlight" : "Enable Flashlight"
|
||||
pda.update_shortcuts()
|
||||
pda.set_light(fon ? f_lum : 0)
|
||||
|
||||
/datum/data/pda/utility/honk
|
||||
name = "Honk Synthesizer"
|
||||
icon = "smile-o"
|
||||
category = "Clown"
|
||||
|
||||
var/last_honk //Also no honk spamming that's bad too
|
||||
|
||||
/datum/data/pda/utility/honk/start()
|
||||
if(!(last_honk && world.time < last_honk + 20))
|
||||
playsound(pda.loc, 'sound/items/bikehorn.ogg', 50, 1)
|
||||
last_honk = world.time
|
||||
|
||||
/datum/data/pda/utility/toggle_door
|
||||
name = "Toggle Door"
|
||||
icon = "external-link"
|
||||
var/remote_door_id = ""
|
||||
|
||||
/datum/data/pda/utility/toggle_door/start()
|
||||
for(var/obj/machinery/door/poddoor/M in airlocks)
|
||||
if(M.id_tag == remote_door_id)
|
||||
if(M.density)
|
||||
M.open()
|
||||
else
|
||||
M.close()
|
||||
|
||||
/datum/data/pda/utility/scanmode/medical
|
||||
base_name = "Med Scanner"
|
||||
icon = "heart-o"
|
||||
|
||||
/datum/data/pda/utility/scanmode/medical/scan_mob(mob/living/C as mob, mob/living/user as mob)
|
||||
C.visible_message("<span class=warning>[user] has analyzed [C]'s vitals!</span>")
|
||||
|
||||
user.show_message("<span class=notice>Analyzing Results for [C]:</span>")
|
||||
user.show_message("<span class=notice>\t Overall Status: [C.stat > 1 ? "dead" : "[C.health - C.halloss]% healthy"]</span>", 1)
|
||||
user.show_message("<span class=notice>\t Damage Specifics: [C.getOxyLoss() > 50 ? "</span><span class=warning>" : ""][C.getOxyLoss()]-[C.getToxLoss() > 50 ? "</span><span class=warning>" : "</span><span class=notice>"][C.getToxLoss()]-[C.getFireLoss() > 50 ? "</span><span class=warning>" : "</span><span class=notice>"][C.getFireLoss()]-[C.getBruteLoss() > 50 ? "</span><span class=warning>" : "</span><span class=notice>"][C.getBruteLoss()]</span>", 1)
|
||||
user.show_message("<span class=notice>\t Key: Suffocation/Toxin/Burns/Brute</span>", 1)
|
||||
user.show_message("<span class=notice>\t Body Temperature: [C.bodytemperature-T0C]°C ([C.bodytemperature*1.8-459.67]°F)</span>", 1)
|
||||
if(C.timeofdeath && (C.stat == DEAD || (C.status_flags & FAKEDEATH)))
|
||||
user.show_message("<span class=notice>\t Time of Death: [C.timeofdeath]</span>")
|
||||
if(istype(C, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = C
|
||||
var/list/damaged = H.get_damaged_organs(1,1)
|
||||
user.show_message("<span class=notice>Localized Damage, Brute/Burn:</span>",1)
|
||||
if(length(damaged)>0)
|
||||
for(var/obj/item/organ/external/org in damaged)
|
||||
user.show_message("<span class=notice>\t [capitalize(org.name)]: [org.brute_dam > 0 ? "<span class=warning>[org.brute_dam]</span>" : "0"]-[org.burn_dam > 0 ? "<span class=warning>[org.burn_dam]</span>" : "0"]", 1)
|
||||
else
|
||||
user.show_message("<span class=notice>\t Limbs are OK.",1)
|
||||
|
||||
/datum/data/pda/utility/scanmode/dna
|
||||
base_name = "DNA Scanner"
|
||||
icon = "link"
|
||||
|
||||
/datum/data/pda/utility/scanmode/dna/scan_mob(mob/living/C as mob, mob/living/user as mob)
|
||||
if(istype(C, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if (!istype(H.dna, /datum/dna))
|
||||
user << "<span class=notice>No fingerprints found on [H]</span>"
|
||||
else
|
||||
user << "<span class=notice>[H]'s Fingerprints: [md5(H.dna.uni_identity)]</span>"
|
||||
scan_blood(C, user)
|
||||
|
||||
/datum/data/pda/utility/scanmode/dna/scan_atom(atom/A as mob|obj|turf|area, mob/user as mob)
|
||||
scan_blood(A, user)
|
||||
|
||||
/datum/data/pda/utility/scanmode/dna/proc/scan_blood(atom/A, mob/user)
|
||||
if (!A.blood_DNA)
|
||||
user << "<span class=notice>No blood found on [A]</span>"
|
||||
if(A.blood_DNA)
|
||||
qdel(A.blood_DNA)
|
||||
else
|
||||
user << "<span class=notice>Blood found on [A]. Analysing...</span>"
|
||||
spawn(15)
|
||||
for(var/blood in A.blood_DNA)
|
||||
user << "<span class=notice>Blood type: [A.blood_DNA[blood]]\nDNA: [blood]</span>"
|
||||
|
||||
/datum/data/pda/utility/scanmode/halogen
|
||||
base_name = "Halogen Counter"
|
||||
icon = "exclamation-circle"
|
||||
|
||||
/datum/data/pda/utility/scanmode/halogen/scan_mob(mob/living/C as mob, mob/living/user as mob)
|
||||
C.visible_message("<span class=warning>[user] has analyzed [C]'s radiation levels!</span>")
|
||||
|
||||
user.show_message("<span class=notice>Analyzing Results for [C]:</span>")
|
||||
if(C.radiation)
|
||||
user.show_message("<span class=notice>Radiation Level: [C.radiation > 0 ? "</span><span class=danger>[C.radiation]" : "0"]</span>")
|
||||
else
|
||||
user.show_message("<span class=notice>No radiation detected.</span>")
|
||||
|
||||
/datum/data/pda/utility/scanmode/reagent
|
||||
base_name = "Reagent Scanner"
|
||||
icon = "flask"
|
||||
|
||||
/datum/data/pda/utility/scanmode/reagent/scan_atom(atom/A as mob|obj|turf|area, mob/user as mob)
|
||||
if(!isnull(A.reagents))
|
||||
if(A.reagents.reagent_list.len > 0)
|
||||
var/reagents_length = A.reagents.reagent_list.len
|
||||
user << "<span class='notice'>[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found.</span>"
|
||||
for(var/re in A.reagents.reagent_list)
|
||||
user << "<span class='notice'>\t [re]</span>"
|
||||
else
|
||||
user << "<span class='notice'>No active chemical agents found in [A].</span>"
|
||||
else
|
||||
user << "<span class='notice'>No significant chemical agents found in [A].</span>"
|
||||
|
||||
/datum/data/pda/utility/scanmode/gas
|
||||
base_name = "Gas Scanner"
|
||||
icon = "tachometer"
|
||||
|
||||
/datum/data/pda/utility/scanmode/gas/scan_atom(atom/A as mob|obj|turf|area, mob/user as mob)
|
||||
if (istype(A, /obj/item/weapon/tank))
|
||||
var/obj/item/weapon/tank/T = A
|
||||
pda.atmosanalyzer_scan(T.air_contents, user, T)
|
||||
else if (istype(A, /obj/machinery/portable_atmospherics))
|
||||
var/obj/machinery/portable_atmospherics/T = A
|
||||
pda.atmosanalyzer_scan(T.air_contents, user, T)
|
||||
else if (istype(A, /obj/machinery/atmospherics/pipe))
|
||||
var/obj/machinery/atmospherics/pipe/T = A
|
||||
pda.atmosanalyzer_scan(T.parent.air, user, T)
|
||||
else if (istype(A, /obj/machinery/power/rad_collector))
|
||||
var/obj/machinery/power/rad_collector/T = A
|
||||
if(T.P)
|
||||
pda.atmosanalyzer_scan(T.P.air_contents, user, T)
|
||||
else if (istype(A, /obj/item/weapon/flamethrower))
|
||||
var/obj/item/weapon/flamethrower/T = A
|
||||
if(T.ptank)
|
||||
pda.atmosanalyzer_scan(T.ptank.air_contents, user, T)
|
||||
else if (istype(A, /obj/machinery/portable_atmospherics/scrubber/huge))
|
||||
var/obj/machinery/portable_atmospherics/scrubber/huge/T = A
|
||||
pda.atmosanalyzer_scan(T.air_contents, user, T)
|
||||
else if (istype(A, /obj/machinery/atmospherics/unary/tank))
|
||||
var/obj/machinery/atmospherics/unary/tank/T = A
|
||||
pda.atmosanalyzer_scan(T.air_contents, user, T)
|
||||
|
||||
/datum/data/pda/utility/scanmode/notes
|
||||
base_name = "Note Scanner"
|
||||
icon = "clipboard"
|
||||
var/datum/data/pda/app/notekeeper/notes
|
||||
|
||||
/datum/data/pda/utility/scanmode/notes/start()
|
||||
. = ..()
|
||||
notes = pda.find_program(/datum/data/pda/app/notekeeper)
|
||||
|
||||
/datum/data/pda/utility/scanmode/notes/scan_atom(atom/A as mob|obj|turf|area, mob/user as mob)
|
||||
if(notes && istype(A, /obj/item/weapon/paper))
|
||||
var/obj/item/weapon/paper/P = A
|
||||
|
||||
// JMO 20140705: Makes scanned document show up properly in the notes. Not pretty for formatted documents,
|
||||
// as this will clobber the HTML, but at least it lets you scan a document. You can restore the original
|
||||
// notes by editing the note again. (Was going to allow you to edit, but scanned documents are too long.)
|
||||
var/raw_scan = P.info
|
||||
var/formatted_scan = ""
|
||||
// Scrub out the tags (replacing a few formatting ones along the way)
|
||||
// Find the beginning and end of the first tag.
|
||||
var/tag_start = findtext(raw_scan, "<")
|
||||
var/tag_stop = findtext(raw_scan, ">")
|
||||
// Until we run out of complete tags...
|
||||
while(tag_start && tag_stop)
|
||||
var/pre = copytext(raw_scan, 1, tag_start) // Get the stuff that comes before the tag
|
||||
var/tag = lowertext(copytext(raw_scan, tag_start + 1, tag_stop)) // Get the tag so we can do intellegent replacement
|
||||
var/tagend = findtext(tag, " ") // Find the first space in the tag if there is one.
|
||||
// Anything that's before the tag can just be added as is.
|
||||
formatted_scan = formatted_scan + pre
|
||||
// If we have a space after the tag (and presumably attributes) just crop that off.
|
||||
if(tagend)
|
||||
tag = copytext(tag, 1, tagend)
|
||||
if(tag == "p" || tag == "/p" || tag == "br") // Check if it's I vertical space tag.
|
||||
formatted_scan = formatted_scan + "<br>" // If so, add some padding in.
|
||||
raw_scan = copytext(raw_scan, tag_stop + 1) // continue on with the stuff after the tag
|
||||
// Look for the next tag in what's left
|
||||
tag_start = findtext(raw_scan, "<")
|
||||
tag_stop = findtext(raw_scan, ">")
|
||||
// Anything that is left in the page. just tack it on to the end as is
|
||||
formatted_scan = formatted_scan + raw_scan
|
||||
// If there is something in there already, pad it out.
|
||||
if(length(notes.note) > 0)
|
||||
notes.note = notes.note + "<br><br>"
|
||||
// Store the scanned document to the notes
|
||||
notes.note = "Scanned Document. Edit to restore previous notes/delete scan.<br>----------<br>" + formatted_scan + "<br>"
|
||||
// notehtml ISN'T set to allow user to get their old notes back. A better implementation would add a "scanned documents"
|
||||
// feature to the PDA, which would better convey the availability of the feature, but this will work for now.
|
||||
// Inform the user
|
||||
user << "<span class=notice>Paper scanned and OCRed to notekeeper.</span>" //concept of scanning paper copyright brainoblivion 2009
|
||||
else
|
||||
user << "<span class=warning>Error scanning [A].</span>"
|
||||
@@ -19,6 +19,7 @@
|
||||
throw_range = 5
|
||||
force = 5.0
|
||||
origin_tech = "combat=1"
|
||||
needs_permit = 1
|
||||
attack_verb = list("struck", "hit", "bashed")
|
||||
|
||||
var/fire_sound = 'sound/weapons/Gunshot.ogg'
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
desc = "A modified version of the basic laser gun, this one fires less concentrated energy bolts designed for target practice."
|
||||
projectile_type = "/obj/item/projectile/practice"
|
||||
clumsy_check = 0
|
||||
needs_permit = 0
|
||||
|
||||
obj/item/weapon/gun/energy/laser/retro
|
||||
name ="retro laser gun"
|
||||
@@ -107,6 +108,7 @@ obj/item/weapon/gun/energy/laser/retro
|
||||
projectile_type = "/obj/item/projectile/lasertag/blue"
|
||||
origin_tech = "combat=1;magnets=2"
|
||||
clumsy_check = 0
|
||||
needs_permit = 0
|
||||
|
||||
self_recharge = 1
|
||||
|
||||
@@ -124,6 +126,7 @@ obj/item/weapon/gun/energy/laser/retro
|
||||
projectile_type = "/obj/item/projectile/lasertag/red"
|
||||
origin_tech = "combat=1;magnets=2"
|
||||
clumsy_check = 0
|
||||
needs_permit = 0
|
||||
|
||||
self_recharge = 1
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
origin_tech = "materials=2;biotech=3;powerstorage=3"
|
||||
modifystate = "floramut"
|
||||
var/mode = 0 //0 = mutate, 1 = yield boost
|
||||
needs_permit = 0
|
||||
|
||||
self_recharge = 1
|
||||
|
||||
@@ -202,6 +203,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
|
||||
fire_sound = 'sound/weapons/Kenetic_accel.ogg'
|
||||
charge_cost = 5000
|
||||
cell_type = "/obj/item/weapon/stock_parts/cell/emproof"
|
||||
needs_permit = 0 // Aparently these are safe to carry? I'm sure Golliaths would disagree.
|
||||
fire_delay = 16 //Because guncode is bad and you can bug the reload for rapid fire otherwise.
|
||||
var/recently_fired = 0
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
if(!(M.mind in ticker.mode.vampires))
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.species && H.species.dietflags) //Make sure the species has it's dietflag set, otherwise it can't digest any nutrients
|
||||
if(H.can_eat()) //Make sure the species has it's dietflag set, otherwise it can't digest any nutrients
|
||||
H.nutrition += nutriment_factor // For hunger and fatness
|
||||
if(prob(50)) M.heal_organ_damage(1,0)
|
||||
if(istype(M,/mob/living/simple_animal)) //Any nutrients can heal simple animals
|
||||
@@ -36,7 +36,7 @@
|
||||
if(!(M.mind in ticker.mode.vampires))
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.species && H.species.dietflags && !(H.species.dietflags & DIET_HERB)) //Make sure the species has it's dietflag set, and that it is not a herbivore
|
||||
if(H.can_eat(DIET_CARN | DIET_OMNI)) //Make sure that it is not a herbivore
|
||||
H.nutrition += nutriment_factor // For hunger and fatness
|
||||
if(prob(50)) M.heal_organ_damage(1,0)
|
||||
if(istype(M,/mob/living/simple_animal)) //Any nutrients can heal simple animals
|
||||
@@ -58,7 +58,7 @@
|
||||
if(!(M.mind in ticker.mode.vampires))
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.species && H.species.dietflags && !(H.species.dietflags & DIET_CARN)) //Make sure the species has it's dietflag set, and that it is not a carnivore
|
||||
if(H.can_eat(DIET_HERB | DIET_OMNI)) //Make sure that it is not a carnivore
|
||||
H.nutrition += nutriment_factor // For hunger and fatness
|
||||
if(prob(50)) M.heal_organ_damage(1,0)
|
||||
if(istype(M,/mob/living/simple_animal)) //Any nutrients can heal simple animals
|
||||
|
||||
@@ -490,4 +490,13 @@
|
||||
build_type = IMPRINTER
|
||||
materials = list(MAT_GLASS=1000, "sacid"=20)
|
||||
build_path = /obj/item/weapon/circuitboard/clawgame
|
||||
category = list ("Misc. Machinery")
|
||||
category = list ("Misc. Machinery")
|
||||
|
||||
/datum/design/prize_counter
|
||||
name = "Machine Design (Prize Counter)"
|
||||
desc = "The circuit board for an arcade Prize Counter."
|
||||
req_tech = list("programming" = 2, "materials" = 2)
|
||||
build_type = IMPRINTER
|
||||
materials = list(MAT_GLASS=1000, "sacid"=20)
|
||||
build_path = /obj/item/weapon/circuitboard/prize_counter
|
||||
category = list("Misc. Machinery")
|
||||
Reference in New Issue
Block a user