Merge branch 'master' into heart_damage

This commit is contained in:
Anewbe
2017-01-30 22:43:09 -06:00
committed by GitHub
122 changed files with 2891 additions and 1460 deletions

View File

@@ -192,3 +192,10 @@
#define NOMUT 0
#define COLORMUT 1
#define SPECIESMUT 2
//carbon taste sensitivity defines, used in mob/living/carbon/proc/ingest
#define TASTE_HYPERSENSITIVE 3 //anything below 5%
#define TASTE_SENSITIVE 2 //anything below 7%
#define TASTE_NORMAL 1 //anything below 15%
#define TASTE_DULL 0.5 //anything below 30%
#define TASTE_NUMB 0.1 //anything below 150%

View File

@@ -33,11 +33,14 @@
#define LANGUAGE_SKRELLIAN "Skrellian"
#define LANGUAGE_TRADEBAND "Tradeband"
#define LANGUAGE_GUTTER "Gutter"
#define LANGUAGE_SIGN "Sign Language"
#define LANGUAGE_SCHECHI "Schechi"
#define LANGUAGE_ROOTLOCAL "Local Rootspeak"
#define LANGUAGE_ROOTGLOBAL "Global Rootspeak"
#define LANGUAGE_CULT "Cult"
#define LANGUAGE_SIGN "Sign Language"
#define LANGUAGE_OCCULT "Occult"
#define LANGUAGE_CHANGELING "Changeling"
#define LANGUAGE_VOX "Vox-Pidgin"
// Language flags.
#define WHITELISTED 1 // Language is available if the speaker is whitelisted.

View File

@@ -573,7 +573,7 @@
name = "subspace wavelength analyzer"
icon_state = "wavelength_analyzer"
desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths."
origin_tech = list(TECH_DATA = 3, TECH_MAGNETS = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
origin_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
/obj/item/weapon/stock_parts/subspace/crystal

View File

@@ -308,7 +308,7 @@ var/datum/antagonist/raider/raiders
player.equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/vox(player), slot_shoes) // REPLACE THESE WITH CODED VOX ALTERNATIVES.
player.equip_to_slot_or_del(new /obj/item/clothing/gloves/vox(player), slot_gloves) // AS ABOVE.
player.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/swat/vox(player), slot_wear_mask)
player.equip_to_slot_or_del(new /obj/item/weapon/tank/phoron/vox(player), slot_back)
player.equip_to_slot_or_del(new /obj/item/weapon/tank/vox(player), slot_back)
player.equip_to_slot_or_del(new /obj/item/device/flashlight(player), slot_r_store)
player.internal = locate(/obj/item/weapon/tank) in player.contents

View File

@@ -47,7 +47,7 @@
..()
/obj/item/clothing/gloves/regen/process()
if(!wearer || wearer.isSynthetic() || wearer.stat == DEAD || wearer.nutrition >= 10)
if(!wearer || wearer.isSynthetic() || wearer.stat == DEAD || wearer.nutrition <= 10)
return // Robots and dead people don't have a metabolism.
if(wearer.getBruteLoss())

View File

@@ -14,8 +14,12 @@
return check_access(id)
return 0
/obj/item/proc/GetAccess()
return list()
///obj/item/proc/GetAccess()
// return list()
/atom/movable/proc/GetAccess()
var/obj/item/weapon/card/id/id = GetIdCard()
return id ? id.GetAccess() : list()
/obj/proc/GetID()
return null
@@ -197,7 +201,7 @@
"Emergency Response Team",
"Emergency Response Team Leader")
/mob/proc/GetIdCard()
/atom/movable/proc/GetIdCard()
return null
/mob/living/bot/GetIdCard()

View File

@@ -8,7 +8,7 @@ obj/machinery/recharger
idle_power_usage = 4
active_power_usage = 40000 //40 kW
var/obj/item/charging = null
var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/device/laptop, /obj/item/weapon/cell, /obj/item/device/flashlight)
var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/device/laptop, /obj/item/weapon/cell, /obj/item/device/flashlight, /obj/item/device/electronic_assembly)
var/icon_state_charged = "recharger2"
var/icon_state_charging = "recharger1"
var/icon_state_idle = "recharger0" //also when unpowered
@@ -60,6 +60,11 @@ obj/machinery/recharger
if(!L.stored_computer.battery)
user << "There's no battery in it!"
return
if(istype(G, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/assembly = G
if(!assembly.battery)
to_chat(user, "<span class='warning'>The assembly doesn't have a power cell.</span>")
return
user.drop_item()
G.loc = src
charging = G
@@ -161,6 +166,21 @@ obj/machinery/recharger
update_use_power(1)
return
if(istype(charging, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/assembly = charging
if(assembly.battery)
if(!assembly.battery.fully_charged())
icon_state = icon_state_charging
assembly.battery.give(active_power_usage*CELLRATE)
update_use_power(2)
else
icon_state = icon_state_charged
update_use_power(1)
else
icon_state = icon_state_idle
update_use_power(1)
return
/obj/machinery/recharger/emp_act(severity)
if(stat & (NOPOWER|BROKEN) || !anchored)
..(severity)

View File

@@ -100,14 +100,21 @@
src.loc = F
return
/obj/item/weapon/tank/phoron/vox
/obj/item/weapon/tank/vox //Can't be a child of phoron or the gas amount gets screwey.
name = "phoron tank"
desc = "Contains dangerous phoron. Do not inhale. Warning: extremely flammable."
icon_state = "oxygen_fr"
gauge_icon = null
flags = CONDUCT
distribute_pressure = ONE_ATMOSPHERE*O2STANDARD
slot_flags = SLOT_BACK //these ones have straps!
/obj/item/weapon/tank/vox/New()
..()
air_contents.adjust_gas("phoron", (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
return
/*
* Emergency Oxygen
*/

View File

@@ -127,6 +127,7 @@
new /obj/item/clothing/head/beret/sec/corporate/hos(src)
new /obj/item/clothing/suit/storage/hooded/wintercoat/security(src)
new /obj/item/device/flashlight/maglight(src)
new /obj/item/clothing/mask/gas/half(src)
return
@@ -173,6 +174,7 @@
new /obj/item/clothing/suit/storage/hooded/wintercoat/security(src)
new /obj/item/device/flashlight/maglight(src)
new /obj/item/device/megaphone(src)
new /obj/item/clothing/mask/gas/half(src)
return

View File

@@ -535,6 +535,7 @@
new /obj/item/clothing/under/pants/black(src)
new /obj/item/clothing/under/pants/tan(src)
new /obj/item/clothing/under/pants/track(src)
new /obj/item/clothing/suit/storage/toggle/track(src)
new /obj/item/clothing/under/pants(src)
new /obj/item/clothing/under/pants/khaki(src)
new /obj/item/clothing/mask/bandana/blue(src)

View File

@@ -147,8 +147,8 @@
slip_stun = 4
slip_dist = 2
if(M.slip("the [floor_type] floor",slip_stun))
for(var/i = 0;i<slip_dist;i++)
if(M.slip("the [floor_type] floor", slip_stun))
for(var/i = 1 to slip_dist)
step(M, M.dir)
sleep(1)
else

View File

@@ -21,11 +21,17 @@
var/savefile/F = new(NEWSFILE)
if(F)
var/title = F["title"]
var/body = F["body"]
var/body = html2paper_markup(F["body"])
var/new_title = sanitize(input(src,"Write a good title for the news update. Note: HTML is NOT supported.","Write News", title) as null|text, extra = 0)
if(!new_title)
return
var/new_body = sanitize(input(src,"Write the body of the news update here. Note: HTML is NOT supported.","Write News", body) as null|message, extra = 0)
var/new_body = sanitize(input(src,"Write the body of the news update here. Note: HTML is NOT supported, however paper markup is supported. \n\
Hitting enter will automatically add a line break. \n\
Valid markup includes: \[b\], \[i\], \[u\], \[large\], \[h1\], \[h2\], \[h3\]\ \[*\], \[hr\], \[small\], \[list\], \[table\], \[grid\], \
\[row\], \[cell\], \[logo\], \[sglogo\].","Write News", body) as null|message, extra = 0)
new_body = paper_markup2html(new_body)
if(findtext(new_body,"<script",1,0) ) // Is this needed with santize()?
return
F["title"] << new_title
@@ -38,5 +44,78 @@
var/savefile/F = new(NEWSFILE)
if(F)
return F
// This is used when submitting the news input, so the safe markup can get past sanitize.
/proc/paper_markup2html(var/text)
text = replacetext(text, "\n", "<br>")
text = replacetext(text, "\[center\]", "<center>")
text = replacetext(text, "\[/center\]", "</center>")
text = replacetext(text, "\[br\]", "<BR>")
text = replacetext(text, "\[b\]", "<B>")
text = replacetext(text, "\[/b\]", "</B>")
text = replacetext(text, "\[i\]", "<I>")
text = replacetext(text, "\[/i\]", "</I>")
text = replacetext(text, "\[u\]", "<U>")
text = replacetext(text, "\[/u\]", "</U>")
text = replacetext(text, "\[large\]", "<font size=\"4\">")
text = replacetext(text, "\[/large\]", "</font>")
text = replacetext(text, "\[h1\]", "<H1>")
text = replacetext(text, "\[/h1\]", "</H1>")
text = replacetext(text, "\[h2\]", "<H2>")
text = replacetext(text, "\[/h2\]", "</H2>")
text = replacetext(text, "\[h3\]", "<H3>")
text = replacetext(text, "\[/h3\]", "</H3>")
text = replacetext(text, "\[*\]", "<li>")
text = replacetext(text, "\[hr\]", "<HR>")
text = replacetext(text, "\[small\]", "<font size = \"1\">")
text = replacetext(text, "\[/small\]", "</font>")
text = replacetext(text, "\[list\]", "<ul>")
text = replacetext(text, "\[/list\]", "</ul>")
text = replacetext(text, "\[table\]", "<table border=1 cellspacing=0 cellpadding=3 style='border: 1px solid black;'>")
text = replacetext(text, "\[/table\]", "</td></tr></table>")
text = replacetext(text, "\[grid\]", "<table>")
text = replacetext(text, "\[/grid\]", "</td></tr></table>")
text = replacetext(text, "\[row\]", "</td><tr>")
text = replacetext(text, "\[cell\]", "<td>")
text = replacetext(text, "\[logo\]", "<img src = ntlogo.png>") // Not sure if these would get used but why not
text = replacetext(text, "\[sglogo\]", "<img src = sglogo.png>")
return text
// This is used when reading text that went through paper_markup2html(), to reverse it so that edits don't need to replace everything once more to avoid sanitization.
/proc/html2paper_markup(var/text)
text = replacetext(text, "<br>", "\[br\]")
text = replacetext(text, "<center>", "\[center\]")
text = replacetext(text, "</center>", "\[/center\]")
text = replacetext(text, "<BR>", "\[br\]")
text = replacetext(text, "<B>", "\[b\]")
text = replacetext(text, "</B>", "\[/b\]")
text = replacetext(text, "<I>", "\[i\]")
text = replacetext(text, "</I>", "\[/i\]")
text = replacetext(text, "<U>", "\[u\]")
text = replacetext(text, "</U>", "\[/u\]")
text = replacetext(text, "<font size=\"4\">", "\[large\]")
text = replacetext(text, "</font>", "\[/large\]")
text = replacetext(text, "<H1>", "\[h1\]")
text = replacetext(text, "</H1>", "\[/h1\]")
text = replacetext(text, "<H2>", "\[h2\]")
text = replacetext(text, "</H2>", "\[/h2\]")
text = replacetext(text, "<H3>", "\[h3\]")
text = replacetext(text, "</H3>", "\[/h3\]")
text = replacetext(text, "<li>", "\[*\]")
text = replacetext(text, "<HR>", "\[hr\]")
text = replacetext(text, "<font size = \"1\">", "\[small\]")
text = replacetext(text, "</font>", "\[/small\]")
text = replacetext(text, "<ul>", "\[list\]")
text = replacetext(text, "</ul>", "\[/list\]")
text = replacetext(text, "<table border=1 cellspacing=0 cellpadding=3 style='border: 1px solid black;'>", "\[table\]")
text = replacetext(text, "</td></tr></table>", "\[/table\]")
text = replacetext(text, "<table>", "\[grid\]")
text = replacetext(text, "</td></tr></table>", "\[/grid\]")
text = replacetext(text, "</td><tr>", "\[row\]")
text = replacetext(text, "<td>", "\[cell\]")
text = replacetext(text, "<img src = ntlogo.png>", "\[logo\]") // Not sure if these would get used but why not
text = replacetext(text, "<img src = sglogo.png>", "\[sglogo\]")
return text
#undef NEWSFILE

View File

@@ -42,15 +42,13 @@
display_name = "Security HUD, sunglasses (Security)"
path = /obj/item/clothing/glasses/sunglasses/sechud
/datum/gear/eyes/secaviators
display_name = "Security HUD Aviators"
/datum/gear/eyes/security/aviator
display_name = "Security HUD Aviators (Security)"
path = /obj/item/clothing/glasses/sunglasses/sechud/aviator
allowed_roles = list("Security Officer","Head of Security","Warden")
/datum/gear/eyes/secaviators/prescription
display_name = "Security HUD Aviators, prescription"
/datum/gear/eyes/security/aviator/prescription
display_name = "Security HUD Aviators, prescription (Security)"
path = /obj/item/clothing/glasses/sunglasses/sechud/aviator/prescription
allowed_roles = list("Security Officer","Head of Security","Warden")
/datum/gear/eyes/medical
display_name = "Medical HUD (Medical)"
@@ -61,10 +59,32 @@
display_name = "Medical HUD, prescription (Medical)"
path = /obj/item/clothing/glasses/hud/health/prescription
/datum/gear/eyes/shades
display_name = "Sunglasses, fat (Security/Command)"
path = /obj/item/clothing/glasses/sunglasses/big
allowed_roles = list("Security Officer","Head of Security","Warden","Colony Director","Head of Personnel","Quartermaster","Internal Affairs Agent","Detective")
/datum/gear/eyes/medical/aviator
display_name = "Medical HUD Aviators (Medical)"
path = /obj/item/clothing/glasses/sunglasses/medhud/aviator
/datum/gear/eyes/medical/aviator
display_name = "Medical HUD Aviators, prescription (Medical)"
path = /obj/item/clothing/glasses/sunglasses/medhud/aviator/prescription
/datum/gear/eyes/meson
display_name = "Optical Meson Scanners (Engineering)"
path = /obj/item/clothing/glasses/meson
allowed_roles = list("Station Engineer","Chief Engineer","Atmospheric Technician")
/datum/gear/eyes/meson/prescription
display_name = "Optical Meson Scanners, prescription (Engineering)"
path = /obj/item/clothing/glasses/meson/prescription
/datum/gear/eyes/meson/aviator
display_name = "Optical Meson Aviators, (Engineering)"
path = /obj/item/clothing/glasses/meson/aviator
/datum/gear/eyes/meson/aviator/prescription
display_name = "Optical Meson Aviators, prescription (Engineering)"
path = /obj/item/clothing/glasses/meson/aviator/prescription
/datum/gear/eyes/meson/aviator/prescription
/datum/gear/eyes/glasses/fakesun
display_name = "Sunglasses, stylish"
@@ -74,7 +94,16 @@
display_name = "Sunglasses, stylish aviators"
path = /obj/item/clothing/glasses/fakesunglasses/aviator
/datum/gear/eyes/shades/prescriptionsun
/datum/gear/eyes/sun
display_name = "Sunglasses (Security/Command)"
path = /obj/item/clothing/glasses/sunglasses
allowed_roles = list("Security Officer","Head of Security","Warden","Colony Director","Head of Personnel","Quartermaster","Internal Affairs Agent","Detective")
/datum/gear/eyes/sun/shades
display_name = "Sunglasses, fat (Security/Command)"
path = /obj/item/clothing/glasses/sunglasses/big
/datum/gear/eyes/sun/prescriptionsun
display_name = "sunglasses, presciption (Security/Command)"
path = /obj/item/clothing/glasses/sunglasses/prescription
cost = 2

View File

@@ -1,4 +1,4 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
#define SAVE_RESET -1
var/list/preferences_datums = list()
@@ -199,7 +199,8 @@ datum/preferences
dat += "Slot - "
dat += "<a href='?src=\ref[src];load=1'>Load slot</a> - "
dat += "<a href='?src=\ref[src];save=1'>Save slot</a> - "
dat += "<a href='?src=\ref[src];reload=1'>Reload slot</a>"
dat += "<a href='?src=\ref[src];reload=1'>Reload slot</a> - "
dat += "<a href='?src=\ref[src];resetslot=1'>Reset slot</a>"
else
dat += "Please create an account to save your preferences."
@@ -248,6 +249,11 @@ datum/preferences
load_character(text2num(href_list["changeslot"]))
sanitize_preferences()
close_load_dialog(usr)
else if(href_list["resetslot"])
if("No" == alert("This will reset the current slot. Continue?", "Reset current slot?", "No", "Yes"))
return 0
load_character(SAVE_RESET)
sanitize_preferences()
else
return 0

View File

@@ -67,11 +67,20 @@
if(!S) return 0
S.cd = "/"
if(!slot) slot = default_slot
slot = sanitize_integer(slot, 1, config.character_slots, initial(default_slot))
if(slot != default_slot)
default_slot = slot
S["default_slot"] << slot
S.cd = "/character[slot]"
if(slot != SAVE_RESET) // SAVE_RESET will reset the slot as though it does not exist, but keep the current slot for saving purposes.
slot = sanitize_integer(slot, 1, config.character_slots, initial(default_slot))
if(slot != default_slot)
default_slot = slot
S["default_slot"] << slot
else
S["default_slot"] << default_slot
if(slot != SAVE_RESET)
S.cd = "/character[slot]"
player_setup.load_character(S)
else
player_setup.load_character(S)
S.cd = "/character[default_slot]"
player_setup.load_character(S)
return 1

View File

@@ -69,6 +69,19 @@ BLIND // can't see anything
desc = "Optical Meson Scanner with prescription lenses."
prescription = 1
/obj/item/clothing/glasses/meson/aviator
name = "Engineering Aviators"
icon_state = "aviator_eng"
off_state = "aviator"
item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses")
action_button_name = "Toggle HUD"
activation_sound = 'sound/effects/pop.ogg'
/obj/item/clothing/glasses/meson/aviator/prescription
name = "Prescription Engineering Aviators"
desc = "Engineering Aviators with prescription lenses."
prescription = 1
/obj/item/clothing/glasses/science
name = "Science Goggles"
desc = "The goggles do nothing!"
@@ -242,20 +255,20 @@ BLIND // can't see anything
icon_state = "bigsunglasses"
/obj/item/clothing/glasses/fakesunglasses //Sunglasses without flash immunity
desc = "A pair of designer sunglasses. Doesn't seem like it'll block flashes."
name = "stylish sunglasses"
desc = "A pair of designer sunglasses. Doesn't seem like it'll block flashes."
icon_state = "sun"
item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses")
/obj/item/clothing/glasses/fakesunglasses/aviator
desc = "A pair of designer sunglasses. Doesn't seem like it'll block flashes."
name = "stylish aviators"
icon_state = "sec_flash"
desc = "A pair of designer sunglasses. Doesn't seem like it'll block flashes."
icon_state = "aviator"
/obj/item/clothing/glasses/sunglasses/sechud
name = "HUDSunglasses"
desc = "Sunglasses with a HUD."
icon_state = "sunhud"
icon_state = "sunSecHud"
var/obj/item/clothing/glasses/hud/security/hud = null
New()
@@ -269,10 +282,10 @@ BLIND // can't see anything
icon_state = "swatgoggles"
/obj/item/clothing/glasses/sunglasses/sechud/aviator
name = "HUD aviators"
name = "Security HUD aviators"
desc = "Modified aviator glasses that can be switch between HUD and flash protection modes."
icon_state = "sec_hud"
off_state = "sec_flash"
icon_state = "aviator_sec"
off_state = "aviator"
action_button_name = "Toggle Mode"
var/on = 1
toggleable = 1
@@ -311,10 +324,68 @@ BLIND // can't see anything
icon_state = off_state
/obj/item/clothing/glasses/sunglasses/sechud/aviator/prescription
name = "Prescription HUD aviators"
name = "Prescription Security HUD aviators"
desc = "Modified aviator glasses that can be switch between HUD and flash protection modes. Comes with bonus prescription lenses."
prescription = 6
/obj/item/clothing/glasses/sunglasses/medhud
name = "HUDSunglasses"
desc = "Sunglasses with a HUD."
icon_state = "sunMedHud"
var/obj/item/clothing/glasses/hud/health/hud = null
/obj/item/clothing/glasses/sunglasses/medhud/New()
..()
src.hud = new/obj/item/clothing/glasses/hud/health(src)
return
/obj/item/clothing/glasses/sunglasses/medhud/aviator
name = "Medical HUD aviators"
desc = "Modified aviator glasses with a toggled health HUD."
icon_state = "aviator_med"
off_state = "aviator"
action_button_name = "Toggle Mode"
var/on = 1
toggleable = 1
activation_sound = 'sound/effects/pop.ogg'
var/hud_holder
/obj/item/clothing/glasses/sunglasses/medhud/aviator/New()
..()
hud_holder = hud
/obj/item/clothing/glasses/sunglasses/medhud/aviator/Destroy()
qdel(hud_holder)
hud_holder = null
hud = null
. = ..()
/obj/item/clothing/glasses/sunglasses/medhud/aviator/attack_self(mob/user)
if(toggleable && !user.incapacitated())
on = !on
if(on)
src.hud = hud_holder
to_chat(user, "You switch the [src] to HUD mode.")
else
src.hud = null
to_chat(user, "You switch \the [src] off.")
update_icon()
user << activation_sound
user.update_inv_glasses()
user.update_action_buttons()
/obj/item/clothing/glasses/sunglasses/medhud/aviator/update_icon()
if(on)
icon_state = initial(icon_state)
else
icon_state = off_state
/obj/item/clothing/glasses/sunglasses/medhud/aviator/prescription
name = "Prescription Medical HUD aviators"
desc = "Modified aviator glasses with a toggled health HUD. Comes with bonus prescription lenses."
prescription = 6
/obj/item/clothing/glasses/thermal
name = "Optical Thermal Scanner"
desc = "Thermals in the shape of glasses."

View File

@@ -92,4 +92,9 @@
siemens_coefficient = 0
phoronproof = 1
permeability_coefficient = 0.05
species_restricted = list("Vox")
species_restricted = list("Vox")
cold_protection = HANDS
min_cold_protection_temperature = GLOVES_MIN_COLD_PROTECTION_TEMPERATURE
heat_protection = HANDS
max_heat_protection_temperature = GLOVES_MAX_HEAT_PROTECTION_TEMPERATURE

View File

@@ -107,7 +107,6 @@
magpulse = 1
canremove = 0 //kinda hard to take off magclaws when you are gripping them tightly.
to_chat(user, "You dig your claws deeply into the flooring, bracing yourself.")
to_chat(user, "It would be hard to take off the [src] without relaxing your grip first.")
user.update_action_buttons()
//In case they somehow come off while enabled.

View File

@@ -33,17 +33,16 @@
w_class = ITEMSIZE_NORMAL
item_flags = STOPPRESSUREDAMAGE | THICKMATERIAL | PHORONGUARD
allowed = list(/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs,/obj/item/weapon/tank)
slowdown = 1
phoronproof = 1
armor = list(melee = 60, bullet = 50, laser = 40,energy = 15, bomb = 30, bio = 30, rad = 30)
siemens_coefficient = 0.6
siemens_coefficient = 0.2
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE
species_restricted = list("Vox")
/obj/item/clothing/head/helmet/space/vox
armor = list(melee = 60, bullet = 50, laser = 40, energy = 15, bomb = 30, bio = 30, rad = 30)
siemens_coefficient = 0.6
siemens_coefficient = 0.2
item_flags = STOPPRESSUREDAMAGE | THICKMATERIAL | AIRTIGHT | PHORONGUARD
flags_inv = 0
phoronproof = 1

View File

@@ -47,9 +47,10 @@
icon_state = "vox_rig"
armor = list(melee = 60, bullet = 50, laser = 40, energy = 15, bomb = 30, bio = 30, rad = 30)
item_flags = THICKMATERIAL
siemens_coefficient = 0.2
phoronproof = 1
air_type = /obj/item/weapon/tank/phoron/vox
air_type = /obj/item/weapon/tank/vox
helm_type = /obj/item/clothing/head/helmet/space/rig/vox
boot_type = /obj/item/clothing/shoes/magboots/rig/vox
@@ -58,10 +59,15 @@
/obj/item/clothing/head/helmet/space/rig/vox
species_restricted = list("Vox")
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
phoronproof = 1
/obj/item/clothing/shoes/magboots/rig/vox
name = "talons"
species_restricted = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/shoes.dmi'
)
phoronproof = 1
/obj/item/clothing/suit/space/rig/vox
@@ -69,14 +75,37 @@
phoronproof = 1
/obj/item/clothing/gloves/gauntlets/rig/vox
name = "talons"
siemens_coefficient = 0
species_restricted = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/gloves.dmi'
)
phoronproof = 1
/obj/item/weapon/rig/vox/carapace
name = "dense alien control module"
suit_type = "dense alien"
armor = list(melee = 60, bullet = 50, laser = 40, energy = 15, bomb = 30, bio = 30, rad = 30)
emp_protection = 40 //change this to 30 if too high.
phoronproof = 1
req_access = list(access_syndicate)
cell_type = /obj/item/weapon/cell/hyper
initial_modules = list(
/obj/item/rig_module/mounted/energy_blade,
/obj/item/rig_module/sprinter,
/obj/item/rig_module/electrowarfare_suite,
/obj/item/rig_module/vision,
/obj/item/rig_module/power_sink,
/obj/item/rig_module/self_destruct
)
/obj/item/weapon/rig/vox/stealth
name = "sinister alien control module"
suit_type = "sinister alien"
icon_state = "voxstealth_rig"
armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 30, bio = 100, rad = 100)
emp_protection = 40 //change this to 30 if too high.
slowdown = 0
@@ -88,6 +117,7 @@
initial_modules = list(
/obj/item/rig_module/stealth_field,
/obj/item/rig_module/electrowarfare_suite,
/obj/item/rig_module/vision,
/obj/item/rig_module/power_sink,
/obj/item/rig_module/self_destruct

View File

@@ -201,6 +201,7 @@
req_access = list(access_medical)
initial_modules = list(
/obj/item/rig_module/sprinter,
/obj/item/rig_module/chem_dispenser/injector,
/obj/item/rig_module/maneuvering_jets,
/obj/item/rig_module/device/healthscanner,

View File

@@ -1,6 +1,8 @@
/obj/item/clothing/under/vox
has_sensor = 0
species_restricted = list("Vox")
valid_accessory_slots = list("vox")
restricted_accessory_slots = list("vox")
phoronproof = 1
/obj/item/clothing/under/vox/vox_casual
@@ -14,4 +16,18 @@
name = "alien robes"
desc = "Weird and flowing!"
icon_state = "vox-casual-2"
item_state = "vox-casual-2"
item_state = "vox-casual-2"
//Vox Accessories
/obj/item/clothing/accessory/storage/vox
name = "alien mesh"
desc = "An alien mesh. Seems to be made up mostly of pockets and writhing flesh."
icon_state = "webbing-vox"
slot = "vox"
slots = 5
/obj/item/clothing/accessory/storage/vox/New()
..()
hold.max_storage_space = slots * ITEMSIZE_COST_NORMAL
hold.max_w_class = ITEMSIZE_NORMAL

View File

@@ -52,9 +52,13 @@
var/list/reagent_data = seed.chems[rid]
if(reagent_data && reagent_data.len)
var/rtotal = reagent_data[1]
var/list/data = list()
if(reagent_data.len > 1 && potency > 0)
rtotal += round(potency/reagent_data[2])
reagents.add_reagent(rid,max(1,rtotal))
if(rid == "nutriment")
data[seed.seed_name] = max(1,rtotal)
reagents.add_reagent(rid,max(1,rtotal),data)
update_desc()
if(reagents.total_volume > 0)
bitesize = 1+round(reagents.total_volume / 2, 1)

View File

@@ -8,6 +8,13 @@
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box.
#define IC_SPAWN_RESEARCH 2 // If the circuit design will be autogenerated for RnD.
#define IC_FORMAT_STRING "\<STRING\>"
#define IC_FORMAT_NUMBER "\<NUM\>"
#define IC_FORMAT_REF "\<REF\>"
#define IC_FORMAT_LIST "\<LIST\>"
#define IC_FORMAT_ANY "\<ANY\>"
#define IC_FORMAT_PULSE "\<PULSE\>"
var/list/all_integrated_circuits = list()
/proc/initialize_integrated_circuits_list()
@@ -20,377 +27,19 @@ var/list/all_integrated_circuits = list()
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "template"
w_class = ITEMSIZE_TINY
var/obj/item/device/electronic_assembly/assembly = null // Reference to the assembly holding this circuit, if any.
var/extended_desc = null
var/list/inputs = list()
var/list/outputs = list()
var/list/activators = list()
var/next_use = 0 //Uses world.time
var/complexity = 1 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'.
var/cooldown_per_use = 1 SECOND
var/spawn_flags = null // Used for world initializing, see the #defines above.
var/category_text = "NO CATEGORY" // To show up on circuit printer, and perhaps other places.
var/autopulse = -1 // When input is received, the circuit will pulse itself if set to 1. 0 means it won't. -1 means it is permanently off.
/obj/item/integrated_circuit/examine(mob/user)
..()
to_chat(user, "This board has [inputs.len] input pin\s and [outputs.len] output pin\s.")
for(var/datum/integrated_io/input/I in inputs)
if(I.linked.len)
to_chat(user, "The [I] is connected to [I.get_linked_to_desc()].")
for(var/datum/integrated_io/output/O in outputs)
if(O.linked.len)
to_chat(user, "The [O] is connected to [O.get_linked_to_desc()].")
for(var/datum/integrated_io/activate/A in activators)
if(A.linked.len)
to_chat(user, "The [A] is connected to [A.get_linked_to_desc()].")
interact(user)
/obj/item/integrated_circuit/New()
setup_io(inputs, /datum/integrated_io/input)
setup_io(outputs, /datum/integrated_io/output)
setup_io(activators, /datum/integrated_io/activate)
..()
/obj/item/integrated_circuit/proc/setup_io(var/list/io_list, var/io_type)
var/list/io_list_copy = io_list.Copy()
io_list.Cut()
for(var/io_entry in io_list_copy)
io_list.Add(new io_type(src, io_entry, io_list_copy[io_entry]))
/obj/item/integrated_circuit/proc/on_data_written() //Override this for special behaviour when new data gets pushed to the circuit.
return
/obj/item/integrated_circuit/Destroy()
for(var/datum/integrated_io/I in inputs)
qdel(I)
for(var/datum/integrated_io/O in outputs)
qdel(O)
for(var/datum/integrated_io/A in activators)
qdel(A)
. = ..()
/obj/item/integrated_circuit/nano_host()
if(istype(src.loc, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/assembly = loc
return assembly.resolve_nano_host()
return ..()
/obj/item/integrated_circuit/emp_act(severity)
for(var/datum/integrated_io/io in inputs + outputs + activators)
io.scramble()
/obj/item/integrated_circuit/verb/rename_component()
set name = "Rename Circuit"
set category = "Object"
set desc = "Rename your circuit, useful to stay organized."
var/mob/M = usr
if(!CanInteract(M, physical_state))
return
var/input = sanitizeSafe(input("What do you want to name the circuit?", "Rename", src.name) as null|text, MAX_NAME_LEN)
if(src && input && CanInteract(M, physical_state))
to_chat(M, "<span class='notice'>The circuit '[src.name]' is now labeled '[input]'.</span>")
name = input
/obj/item/integrated_circuit/proc/get_pin_ref(var/pin_type, var/pin_number)
switch(pin_type)
if(IC_INPUT)
if(pin_number > inputs.len)
return null
return inputs[pin_number]
if(IC_OUTPUT)
if(pin_number > outputs.len)
return null
return outputs[pin_number]
if(IC_ACTIVATOR)
if(pin_number > activators.len)
return null
return activators[pin_number]
return null
/obj/item/integrated_circuit/interact(mob/user)
if(!CanInteract(user, physical_state))
return
var/window_height = 350
var/window_width = 600
//var/table_edge_width = "[(window_width - window_width * 0.1) / 4]px"
//var/table_middle_width = "[(window_width - window_width * 0.1) - (table_edge_width * 2)]px"
var/table_edge_width = "30%"
var/table_middle_width = "40%"
var/HTML = list()
HTML += "<html><head><title>[src.name]</title></head><body>"
HTML += "<div align='center'>"
HTML += "<table border='1' style='undefined;table-layout: fixed; width: 424px'>"
HTML += "<br><a href='?src=\ref[src];'>\[Refresh\]</a> | "
HTML += "<a href='?src=\ref[src];rename=1'>\[Rename\]</a> | "
HTML += "<a href='?src=\ref[src];remove=1'>\[Remove\]</a><br>"
HTML += "<colgroup>"
//HTML += "<col style='width: 121px'>"
//HTML += "<col style='width: 181px'>"
//HTML += "<col style='width: 122px'>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "<col style='width: [table_middle_width]'>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "</colgroup>"
var/column_width = 3
var/row_height = max(inputs.len, outputs.len, 1)
for(var/i = 1 to row_height)
HTML += "<tr>"
for(var/j = 1 to column_width)
var/datum/integrated_io/io = null
var/words = list()
var/height = 1
switch(j)
if(1)
io = get_pin_ref(IC_INPUT, i)
if(io)
if(io.linked.len)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]><b>[io.name] [io.display_data()]</b></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder]</a><br>"
else
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>[io.name] [io.display_data()]</a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder]</a><br>"
if(outputs.len > inputs.len)
height = 1
if(2)
if(i == 1)
words += "[src.name]<br><br>[src.desc]"
height = row_height
else
continue
if(3)
io = get_pin_ref(IC_OUTPUT, i)
if(io)
if(io.linked.len)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]><b>[io.name] [io.display_data()]</b></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;user=\ref[user]>[linked.holder]</a><br>"
else
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>[io.name] [io.display_data()]</a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder]</a><br>"
if(inputs.len > outputs.len)
height = 1
HTML += "<td align='center' rowspan='[height]'>[jointext(words, null)]</td>"
HTML += "</tr>"
for(var/activator in activators)
var/datum/integrated_io/io = activator
var/words = list()
if(io.linked.len)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]><font color='FF0000'><b>[io.name]</b></font></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src[src];examine=1;user=\ref[user]>[linked.holder]</a><br>"
else
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]><font color='FF0000'>[io.name]</font></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder]</a><br>"
HTML += "<tr>"
HTML += "<td colspan='3' align='center'>[jointext(words, null)]</td>"
HTML += "</tr>"
HTML += "</table>"
HTML += "</div>"
if(autopulse != -1)
HTML += "<br><font color='33CC33'>Meta Variables;</font>"
HTML += "<br><font color='33CC33'><a href='?src=\ref[src];autopulse=1'>\[Autopulse\]</a> = <b>[autopulse ? "ON" : "OFF"]</b></font>"
HTML += "<br>"
HTML += "<br><font color='0000AA'>Complexity: [complexity]</font>"
HTML += "<br><font color='0000AA'>[extended_desc]</font>"
HTML += "</body></html>"
user << browse(jointext(HTML, null), "window=circuit-\ref[src];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
onclose(user, "circuit-\ref[src]")
/obj/item/integrated_circuit/Topic(href, href_list, state = physical_state)
if(..())
return 1
var/pin = locate(href_list["pin"]) in inputs + outputs + activators
var/obj/held_item = usr.get_active_hand()
if(href_list["wire"])
if(istype(held_item, /obj/item/device/integrated_electronics/wirer))
var/obj/item/device/integrated_electronics/wirer/wirer = held_item
if(pin)
wirer.wire(pin, usr)
else if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/debugger = held_item
if(pin)
debugger.write_data(pin, usr)
else
to_chat(usr, "<span class='warning'>You can't do a whole lot without the proper tools.</span>")
if(href_list["examine"])
examine(usr)
if(href_list["rename"])
rename_component(usr)
if(href_list["autopulse"])
if(autopulse != -1)
autopulse = !autopulse
if(href_list["remove"])
if(istype(held_item, /obj/item/weapon/screwdriver))
disconnect_all()
var/turf/T = get_turf(src)
forceMove(T)
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "<span class='notice'>You pop \the [src] out of the case, and slide it out.</span>")
else
to_chat(usr, "<span class='warning'>You need a screwdriver to remove components.</span>")
var/obj/item/device/electronic_assembly/ea = loc
if(istype(ea))
ea.interact(usr)
return
interact(usr) // To refresh the UI.
/datum/integrated_io
var/name = "input/output"
var/obj/item/integrated_circuit/holder = null
var/weakref/data = null // This is a weakref, to reduce typecasts. Note that oftentimes numbers and text may also occupy this.
var/list/linked = list()
var/io_type = DATA_CHANNEL
/datum/integrated_io/New(var/newloc, var/name, var/data)
..()
src.name = name
src.data = data
holder = newloc
if(!istype(holder))
message_admins("ERROR: An integrated_io ([src.name]) spawned without a valid holder! This is a bug.")
/datum/integrated_io/Destroy()
disconnect()
data = null
holder = null
. = ..()
/datum/integrated_io/nano_host()
return holder.nano_host()
var/complexity = 1 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'.
var/cooldown_per_use = 1 SECOND // Circuits are limited in how many times they can be work()'d by this variable.
var/power_draw_per_use = 0 // How much power is drawn when work()'d.
var/power_draw_idle = 0 // How much power is drawn when doing nothing.
var/spawn_flags = null // Used for world initializing, see the #defines above.
var/category_text = "NO CATEGORY THIS IS A BUG" // To show up on circuit printer, and perhaps other places.
var/autopulse = -1 // When input is received, the circuit will pulse itself if set to 1. 0 means it won't. -1 means it is permanently off.
var/removable = TRUE // Determines if a circuit is removable from the assembly.
/datum/integrated_io/proc/data_as_type(var/as_type)
if(!isweakref(data))
return
var/weakref/w = data
var/output = w.resolve()
return istype(output, as_type) ? output : null
/datum/integrated_io/proc/display_data()
if(isnull(data))
return "(null)" // Empty data means nothing to show.
if(istext(data))
return "(\"[data]\")" // Wraps the 'string' in escaped quotes, so that people know it's a 'string'.
if(isweakref(data))
var/weakref/w = data
var/atom/A = w.resolve()
//return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed.
return A ? "(\ref[A] \[Ref\])" : "(null)"
return "([data])" // Nothing special needed for numbers or other stuff.
/datum/integrated_io/activate/display_data()
return "(\[pulse\])"
/datum/integrated_io/proc/scramble()
if(isnull(data))
return
if(isnum(data))
write_data_to_pin(rand(-10000, 10000))
if(istext(data))
write_data_to_pin("ERROR")
push_data()
/datum/integrated_io/activate/scramble()
push_data()
/datum/integrated_io/proc/write_data_to_pin(var/new_data)
if(isnull(new_data) || isnum(new_data) || istext(new_data) || isweakref(new_data)) // Anything else is a type we don't want.
data = new_data
holder.on_data_written()
/datum/integrated_io/proc/push_data()
for(var/datum/integrated_io/io in linked)
io.write_data_to_pin(data)
/datum/integrated_io/activate/push_data()
for(var/datum/integrated_io/io in linked)
io.holder.check_then_do_work()
/datum/integrated_io/proc/pull_data()
for(var/datum/integrated_io/io in linked)
write_data_to_pin(io.data)
/datum/integrated_io/proc/get_linked_to_desc()
if(linked.len)
return "the [english_list(linked)]"
return "nothing"
/datum/integrated_io/proc/disconnect()
//First we iterate over everything we are linked to.
for(var/datum/integrated_io/their_io in linked)
//While doing that, we iterate them as well, and disconnect ourselves from them.
for(var/datum/integrated_io/their_linked_io in their_io.linked)
if(their_linked_io == src)
their_io.linked.Remove(src)
else
continue
//Now that we're removed from them, we gotta remove them from us.
src.linked.Remove(their_io)
/datum/integrated_io/input
name = "input pin"
/datum/integrated_io/output
name = "output pin"
/datum/integrated_io/activate
name = "activation pin"
io_type = PULSE_CHANNEL
/obj/item/integrated_circuit/proc/push_data()
for(var/datum/integrated_io/output/O in outputs)
O.push_data()
/obj/item/integrated_circuit/proc/pull_data()
for(var/datum/integrated_io/input/I in inputs)
I.push_data()
/obj/item/integrated_circuit/proc/check_then_do_work()
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
return
next_use = world.time + cooldown_per_use
do_work()
/obj/item/integrated_circuit/proc/do_work()
return
/obj/item/integrated_circuit/proc/disconnect_all()
for(var/datum/integrated_io/input/I in inputs)
I.disconnect()
for(var/datum/integrated_io/output/O in outputs)
O.disconnect()
for(var/datum/integrated_io/activate/A in activators)
A.disconnect()

View File

@@ -11,6 +11,7 @@
var/max_components = IC_COMPONENTS_BASE
var/max_complexity = IC_COMPLEXITY_BASE
var/opened = 0
var/obj/item/weapon/cell/device/battery = null // Internal cell which most circuits need to work.
/obj/item/device/electronic_assembly/medium
name = "electronic mechanism"
@@ -23,8 +24,8 @@
name = "electronic machine"
icon_state = "setup_large"
w_class = ITEMSIZE_LARGE
max_components = IC_COMPONENTS_BASE * 3
max_complexity = IC_COMPLEXITY_BASE * 3
max_components = IC_COMPONENTS_BASE * 4
max_complexity = IC_COMPLEXITY_BASE * 4
/obj/item/device/electronic_assembly/drone
name = "electronic drone"
@@ -41,6 +42,32 @@
max_complexity = IC_COMPLEXITY_BASE / 2
var/obj/item/weapon/implant/integrated_circuit/implant = null
/obj/item/device/electronic_assembly/New()
..()
battery = new(src)
processing_objects |= src
/obj/item/device/electronic_assembly/Destroy()
battery = null
processing_objects -= src
for(var/atom/movable/AM in contents)
qdel(AM)
..()
/obj/item/device/electronic_assembly/process()
handle_idle_power()
/obj/item/device/electronic_assembly/proc/handle_idle_power()
// First we generate power.
for(var/obj/item/integrated_circuit/passive/power/P in contents)
P.make_energy()
// Now spend it.
for(var/obj/item/integrated_circuit/IC in contents)
if(IC.power_draw_idle)
if(!draw_power(IC.power_draw_idle))
IC.power_fail()
/obj/item/device/electronic_assembly/implant/update_icon()
..()
implant.icon_state = icon_state
@@ -70,13 +97,18 @@
HTML += "<br><a href='?src=\ref[src]'>\[Refresh\]</a> | "
HTML += "<a href='?src=\ref[src];rename=1'>\[Rename\]</a><br>"
HTML += "[total_parts]/[max_components] ([round((total_parts / max_components) * 100, 0.1)]%) space taken up in the assembly.<br>"
HTML += "[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity."
HTML += "[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity.<br>"
if(battery)
HTML += "[round(battery.charge, 0.1)]/[battery.maxcharge] ([round(battery.percent(), 0.1)]%) cell charge. <a href='?src=\ref[src];remove_cell=1'>\[Remove\]</a>"
else
HTML += "<span class='danger'>No powercell detected!</span>"
HTML += "<br><br>"
HTML += "Components;<br>"
for(var/obj/item/integrated_circuit/circuit in contents)
HTML += "<a href=?src=\ref[circuit];examine=1>[circuit.name]</a> | "
HTML += "<a href=?src=\ref[circuit];rename=1>\[Rename\]</a> | "
HTML += "<a href=?src=\ref[circuit];remove=1>\[Remove\]</a>"
if(circuit.removable)
HTML += "<a href=?src=\ref[circuit];remove=1>\[Remove\]</a>"
HTML += "<br>"
HTML += "</body></html>"
@@ -89,6 +121,16 @@
if(href_list["rename"])
rename(usr)
if(href_list["remove_cell"])
if(!battery)
to_chat(usr, "<span class='warning'>There's no power cell to remove from \the [src].</span>")
else
var/turf/T = get_turf(src)
battery.forceMove(T)
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "<span class='notice'>You pull \the [battery] out of \the [src]'s power supplier.</span>")
battery = null
interact(usr) // To refresh the UI.
/obj/item/device/electronic_assembly/verb/rename()
@@ -117,39 +159,84 @@
else
icon_state = initial(icon_state)
/obj/item/device/electronic_assembly/GetAccess()
. = list()
for(var/obj/item/integrated_circuit/part in contents)
. |= part.GetAccess()
/obj/item/device/electronic_assembly/GetIdCard()
. = list()
for(var/obj/item/integrated_circuit/part in contents)
var/id_card = part.GetIdCard()
if(id_card)
return id_card
/obj/item/device/electronic_assembly/examine(mob/user)
. = ..(user, 1)
if(.)
for(var/obj/item/integrated_circuit/output/screen/S in contents)
if(S.stuff_to_display)
to_chat(user, "There's a little screen labeled '[S.name]', which displays '[S.stuff_to_display]'.")
for(var/obj/item/integrated_circuit/IC in contents)
IC.external_examine(user)
// for(var/obj/item/integrated_circuit/output/screen/S in contents)
// if(S.stuff_to_display)
// to_chat(user, "There's a little screen labeled '[S.name]', which displays '[S.stuff_to_display]'.")
if(opened)
interact(user)
/obj/item/device/electronic_assembly/proc/get_part_complexity()
. = 0
for(var/obj/item/integrated_circuit/part in contents)
. += part.complexity
/obj/item/device/electronic_assembly/proc/get_part_size()
. = 0
for(var/obj/item/integrated_circuit/part in contents)
. += part.w_class
// Returns true if the circuit made it inside.
/obj/item/device/electronic_assembly/proc/add_circuit(var/obj/item/integrated_circuit/IC, var/mob/user)
if(!opened)
to_chat(user, "<span class='warning'>\The [src] isn't opened, so you can't put anything inside. Try using a crowbar.</span>")
return FALSE
if(IC.w_class > src.w_class)
to_chat(user, "<span class='warning'>\The [IC] is way too big to fit into \the [src].</span>")
return FALSE
var/total_part_size = get_part_size()
var/total_complexity = get_part_complexity()
if((total_part_size + IC.w_class) > max_components)
to_chat(user, "<span class='warning'>You can't seem to add the '[IC.name]', as there's insufficient space.</span>")
return FALSE
if((total_complexity + IC.complexity) > max_complexity)
to_chat(user, "<span class='warning'>You can't seem to add the '[IC.name]', since this setup's too complicated for the case.</span>")
return FALSE
if(!IC.forceMove(src))
return FALSE
IC.assembly = src
return TRUE
/obj/item/device/electronic_assembly/afterattack(atom/target, mob/user, proximity)
if(proximity)
var/scanned = FALSE
for(var/obj/item/integrated_circuit/input/sensor/S in contents)
S.set_pin_data(IC_OUTPUT, 1, weakref(target))
S.check_then_do_work()
scanned = TRUE
if(scanned)
visible_message("<span class='notice'>\The [user] waves \the [src] around [target].</span>")
/obj/item/device/electronic_assembly/attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/integrated_circuit))
if(!opened)
to_chat(user, "<span class='warning'>\The [src] isn't opened, so you can't put anything inside. Try using a crowbar.</span>")
if(!user.unEquip(I))
return 0
var/obj/item/integrated_circuit/IC = I
var/total_parts = 0
var/total_complexity = 0
for(var/obj/item/integrated_circuit/part in contents)
total_parts++
total_complexity = total_complexity + part.complexity
if( (total_parts + 1) > max_components)
to_chat(user, "<span class='warning'>You can't seem to add this [IC.name], since there's no more room.</span>")
return 0
if( (total_complexity + IC.complexity) > max_complexity)
to_chat(user, "<span class='warning'>You can't seem to add this [IC.name], since this setup's too complicated for the case.</span>")
return 0
to_chat(user, "<span class='notice'>You slide \the [IC] inside \the [src].</span>")
user.drop_item()
IC.forceMove(src)
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
interact(user)
if(add_circuit(I, user))
to_chat(user, "<span class='notice'>You slide \the [I] inside \the [src].</span>")
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
interact(user)
else if(istype(I, /obj/item/weapon/crowbar))
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
opened = !opened
@@ -161,6 +248,21 @@
else
to_chat(user, "<span class='warning'>\The [src] isn't opened, so you can't fiddle with the internal components. \
Try using a crowbar.</span>")
else if(istype(I, /obj/item/weapon/cell/device))
if(!opened)
to_chat(user, "<span class='warning'>\The [src] isn't opened, so you can't put anything inside. Try using a crowbar.</span>")
return FALSE
if(battery)
to_chat(user, "<span class='warning'>\The [src] already has \a [battery] inside. Remove it first if you want to replace it.</span>")
return FALSE
var/obj/item/weapon/cell/device/cell = I
user.drop_item(cell)
cell.forceMove(src)
battery = cell
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "<span class='notice'>You slot \the [cell] inside \the [src]'s power supplier.</span>")
interact(user)
else
return ..()
@@ -179,4 +281,16 @@
/obj/item/device/electronic_assembly/emp_act(severity)
..()
for(var/atom/movable/AM in contents)
AM.emp_act(severity)
AM.emp_act(severity)
// Returns true if power was successfully drawn.
/obj/item/device/electronic_assembly/proc/draw_power(amount)
if(battery && battery.checked_use(amount * CELLRATE))
return TRUE
return FALSE
// Ditto for giving.
/obj/item/device/electronic_assembly/proc/give_power(amount)
if(battery && battery.give(amount * CELLRATE))
return TRUE
return FALSE

View File

@@ -0,0 +1,44 @@
/obj/item/integrated_circuit/proc/setup_io(var/list/io_list, var/io_type)
var/list/io_list_copy = io_list.Copy()
io_list.Cut()
for(var/io_entry in io_list_copy)
io_list.Add(new io_type(src, io_entry, io_list_copy[io_entry]))
/obj/item/integrated_circuit/proc/set_pin_data(var/pin_type, var/pin_number, var/new_data)
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
return pin.write_data_to_pin(new_data)
/obj/item/integrated_circuit/proc/get_pin_data(var/pin_type, var/pin_number)
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
return pin.get_data()
/obj/item/integrated_circuit/proc/get_pin_data_as_type(var/pin_type, var/pin_number, var/as_type)
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
return pin.data_as_type(as_type)
/obj/item/integrated_circuit/proc/activate_pin(var/pin_number)
var/datum/integrated_io/activate/A = activators[pin_number]
A.push_data()
/datum/integrated_io/proc/get_data()
if(isnull(data))
return
if(isweakref(data))
return data.resolve()
return data
/obj/item/integrated_circuit/proc/get_pin_ref(var/pin_type, var/pin_number)
switch(pin_type)
if(IC_INPUT)
if(pin_number > inputs.len)
return null
return inputs[pin_number]
if(IC_OUTPUT)
if(pin_number > outputs.len)
return null
return outputs[pin_number]
if(IC_ACTIVATOR)
if(pin_number > activators.len)
return null
return activators[pin_number]
return null

View File

@@ -0,0 +1,282 @@
/*
Integrated circuits are essentially modular machines. Each circuit has a specific function, and combining them inside Electronic Assemblies allows
a creative player the means to solve many problems. Circuits are held inside an electronic assembly, and are wired using special tools.
*/
/obj/item/integrated_circuit/examine(mob/user)
. = ..()
external_examine(user)
// This should be used when someone is examining while the case is opened.
/obj/item/integrated_circuit/proc/internal_examine(mob/user)
to_chat(user, "This board has [inputs.len] input pin\s, [outputs.len] output pin\s and [activators.len] activation pin\s.")
for(var/datum/integrated_io/input/I in inputs)
if(I.linked.len)
to_chat(user, "The '[I]' is connected to [I.get_linked_to_desc()].")
for(var/datum/integrated_io/output/O in outputs)
if(O.linked.len)
to_chat(user, "The '[O]' is connected to [O.get_linked_to_desc()].")
for(var/datum/integrated_io/activate/A in activators)
if(A.linked.len)
to_chat(user, "The '[A]' is connected to [A.get_linked_to_desc()].")
any_examine(user)
interact(user)
// This should be used when someone is examining from an 'outside' perspective, e.g. reading a screen or LED.
/obj/item/integrated_circuit/proc/external_examine(mob/user)
any_examine(user)
/obj/item/integrated_circuit/proc/any_examine(mob/user)
return
/obj/item/integrated_circuit/New()
setup_io(inputs, /datum/integrated_io/input)
setup_io(outputs, /datum/integrated_io/output)
setup_io(activators, /datum/integrated_io/activate)
..()
/obj/item/integrated_circuit/proc/on_data_written() //Override this for special behaviour when new data gets pushed to the circuit.
return
/obj/item/integrated_circuit/Destroy()
for(var/datum/integrated_io/I in inputs)
qdel(I)
for(var/datum/integrated_io/O in outputs)
qdel(O)
for(var/datum/integrated_io/A in activators)
qdel(A)
. = ..()
/obj/item/integrated_circuit/nano_host()
if(istype(src.loc, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/assembly = loc
return assembly.resolve_nano_host()
return ..()
/obj/item/integrated_circuit/emp_act(severity)
for(var/datum/integrated_io/io in inputs + outputs + activators)
io.scramble()
/obj/item/integrated_circuit/verb/rename_component()
set name = "Rename Circuit"
set category = "Object"
set desc = "Rename your circuit, useful to stay organized."
var/mob/M = usr
if(!CanInteract(M, physical_state))
return
var/input = sanitizeSafe(input("What do you want to name the circuit?", "Rename", src.name) as null|text, MAX_NAME_LEN)
if(src && input && CanInteract(M, physical_state))
to_chat(M, "<span class='notice'>The circuit '[src.name]' is now labeled '[input]'.</span>")
name = input
/obj/item/integrated_circuit/interact(mob/user)
if(!CanInteract(user, physical_state))
return
var/window_height = 350
var/window_width = 600
//var/table_edge_width = "[(window_width - window_width * 0.1) / 4]px"
//var/table_middle_width = "[(window_width - window_width * 0.1) - (table_edge_width * 2)]px"
var/table_edge_width = "30%"
var/table_middle_width = "40%"
var/HTML = list()
HTML += "<html><head><title>[src.name]</title></head><body>"
HTML += "<div align='center'>"
HTML += "<table border='1' style='undefined;table-layout: fixed; width: 424px'>"
HTML += "<br><a href='?src=\ref[src];'>\[Refresh\]</a> | "
HTML += "<a href='?src=\ref[src];rename=1'>\[Rename\]</a> | "
HTML += "<a href='?src=\ref[src];remove=1'>\[Remove\]</a><br>"
HTML += "<colgroup>"
//HTML += "<col style='width: 121px'>"
//HTML += "<col style='width: 181px'>"
//HTML += "<col style='width: 122px'>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "<col style='width: [table_middle_width]'>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "</colgroup>"
var/column_width = 3
var/row_height = max(inputs.len, outputs.len, 1)
for(var/i = 1 to row_height)
HTML += "<tr>"
for(var/j = 1 to column_width)
var/datum/integrated_io/io = null
var/words = list()
var/height = 1
switch(j)
if(1)
io = get_pin_ref(IC_INPUT, i)
if(io)
if(io.linked.len)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]><b>[io.name] [io.display_data()]</b></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder]</a><br>"
else
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>[io.name] [io.display_data()]</a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder]</a><br>"
if(outputs.len > inputs.len)
height = 1
if(2)
if(i == 1)
words += "[src.name]<br><br>[src.desc]"
height = row_height
else
continue
if(3)
io = get_pin_ref(IC_OUTPUT, i)
if(io)
if(io.linked.len)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]><b>[io.name] [io.display_data()]</b></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;user=\ref[user]>[linked.holder]</a><br>"
else
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>[io.name] [io.display_data()]</a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder]</a><br>"
if(inputs.len > outputs.len)
height = 1
HTML += "<td align='center' rowspan='[height]'>[jointext(words, null)]</td>"
HTML += "</tr>"
for(var/activator in activators)
var/datum/integrated_io/io = activator
var/words = list()
if(io.linked.len)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]><font color='FF0000'><b>[io.name]</b></font></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src[src];examine=1;user=\ref[user]>[linked.holder]</a><br>"
else
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]><font color='FF0000'>[io.name]</font></a><br>"
for(var/datum/integrated_io/linked in io.linked)
words += "<a href=?src=\ref[src];wire=1;pin=\ref[io]>\[[linked.name]\]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder]</a><br>"
HTML += "<tr>"
HTML += "<td colspan='3' align='center'>[jointext(words, null)]</td>"
HTML += "</tr>"
HTML += "</table>"
HTML += "</div>"
if(autopulse != -1)
HTML += "<br><font color='33CC33'>Meta Variables;</font>"
HTML += "<br><font color='33CC33'><a href='?src=\ref[src];autopulse=1'>\[Autopulse\]</a> = <b>[autopulse ? "ON" : "OFF"]</b></font>"
HTML += "<br>"
HTML += "<br><font color='0000AA'>Complexity: [complexity]</font>"
if(power_draw_idle)
HTML += "<br><font color='0000AA'>Power Draw: [power_draw_idle] W (Idle)</font>"
if(power_draw_per_use)
HTML += "<br><font color='0000AA'>Power Draw: [power_draw_per_use] W (Active)</font>" // Borgcode says that powercells' checked_use() takes joules as input.
HTML += "<br><font color='0000AA'>[extended_desc]</font>"
HTML += "</body></html>"
user << browse(jointext(HTML, null), "window=circuit-\ref[src];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
onclose(user, "circuit-\ref[src]")
/obj/item/integrated_circuit/Topic(href, href_list, state = physical_state)
if(..())
return 1
var/pin = locate(href_list["pin"]) in inputs + outputs + activators
var/obj/held_item = usr.get_active_hand()
if(href_list["wire"])
if(istype(held_item, /obj/item/device/integrated_electronics/wirer))
var/obj/item/device/integrated_electronics/wirer/wirer = held_item
if(pin)
wirer.wire(pin, usr)
else if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/debugger = held_item
if(pin)
debugger.write_data(pin, usr)
else
to_chat(usr, "<span class='warning'>You can't do a whole lot without the proper tools.</span>")
if(href_list["examine"])
examine(usr)
if(href_list["rename"])
rename_component(usr)
if(href_list["autopulse"])
if(autopulse != -1)
autopulse = !autopulse
if(href_list["remove"])
if(istype(held_item, /obj/item/weapon/screwdriver))
if(!removable)
to_chat(usr, "<span class='warning'>\The [src] seems to be permanently attached to the case.</span>")
return
disconnect_all()
var/turf/T = get_turf(src)
forceMove(T)
assembly = null
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "<span class='notice'>You pop \the [src] out of the case, and slide it out.</span>")
else
to_chat(usr, "<span class='warning'>You need a screwdriver to remove components.</span>")
var/obj/item/device/electronic_assembly/ea = loc
if(istype(ea))
ea.interact(usr)
return
interact(usr) // To refresh the UI.
/obj/item/integrated_circuit/proc/push_data()
for(var/datum/integrated_io/output/O in outputs)
O.push_data()
/obj/item/integrated_circuit/proc/pull_data()
for(var/datum/integrated_io/input/I in inputs)
I.push_data()
/obj/item/integrated_circuit/proc/draw_idle_power()
if(assembly)
return assembly.draw_power(power_draw_idle)
// Override this for special behaviour when there's no power left.
/obj/item/integrated_circuit/proc/power_fail()
return
// Returns true if there's enough power to work().
/obj/item/integrated_circuit/proc/check_power()
if(!assembly)
return FALSE // Not in an assembly, therefore no power.
if(assembly.draw_power(power_draw_per_use))
return TRUE // Battery has enough.
return FALSE // Not enough power.
/obj/item/integrated_circuit/proc/check_then_do_work()
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
return
if(power_draw_per_use)
if(!check_power())
power_fail()
return
next_use = world.time + cooldown_per_use
do_work()
/obj/item/integrated_circuit/proc/do_work()
return
/obj/item/integrated_circuit/proc/disconnect_all()
for(var/datum/integrated_io/input/I in inputs)
I.disconnect()
for(var/datum/integrated_io/output/O in outputs)
O.disconnect()
for(var/datum/integrated_io/activate/A in activators)
A.disconnect()

View File

@@ -0,0 +1,139 @@
/*
Pins both hold data for circuits, as well move data between them. Some also cause circuits to do their function. DATA_CHANNEL pins are the data holding/moving kind,
where as PULSE_CHANNEL causes circuits to work() when their pulse hits them.
A visualization of how pins work is below. Imagine the below image involves an addition circuit.
When the bottom pin, the activator, receives a pulse, all the numbers on the left (input) get added, and the answer goes on the right side (output).
Inputs Outputs
A [2]\ /[8] result
B [1]-\|++|/
C [4]-/|++|
D [1]/ ||
||
Activator
*/
/datum/integrated_io
var/name = "input/output"
var/obj/item/integrated_circuit/holder = null
var/weakref/data = null // This is a weakref, to reduce typecasts. Note that oftentimes numbers and text may also occupy this.
var/list/linked = list()
var/io_type = DATA_CHANNEL
/datum/integrated_io/New(var/newloc, var/name, var/data)
..()
src.name = name
src.data = data
holder = newloc
if(!istype(holder))
message_admins("ERROR: An integrated_io ([src.name]) spawned without a valid holder! This is a bug.")
/datum/integrated_io/Destroy()
disconnect()
data = null
holder = null
. = ..()
/datum/integrated_io/nano_host()
return holder.nano_host()
/datum/integrated_io/proc/data_as_type(var/as_type)
if(!isweakref(data))
return
var/weakref/w = data
var/output = w.resolve()
return istype(output, as_type) ? output : null
/datum/integrated_io/proc/display_data()
if(isnull(data))
return "(null)" // Empty data means nothing to show.
if(istext(data))
return "(\"[data]\")" // Wraps the 'string' in escaped quotes, so that people know it's a 'string'.
if(isweakref(data))
var/weakref/w = data
var/atom/A = w.resolve()
//return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed.
return A ? "(\ref[A] \[Ref\])" : "(null)"
return "([data])" // Nothing special needed for numbers or other stuff.
/datum/integrated_io/activate/display_data()
return "(\[pulse\])"
/datum/integrated_io/proc/display_pin_type()
return IC_FORMAT_ANY
/datum/integrated_io/activate/display_pin_type()
return IC_FORMAT_PULSE
/datum/integrated_io/proc/scramble()
if(isnull(data))
return
if(isnum(data))
write_data_to_pin(rand(-10000, 10000))
if(istext(data))
write_data_to_pin("ERROR")
push_data()
/datum/integrated_io/activate/scramble()
push_data()
/datum/integrated_io/proc/write_data_to_pin(var/new_data)
if(isnull(new_data) || isnum(new_data) || istext(new_data) || isweakref(new_data)) // Anything else is a type we don't want.
data = new_data
holder.on_data_written()
/datum/integrated_io/proc/push_data()
for(var/datum/integrated_io/io in linked)
io.write_data_to_pin(data)
/datum/integrated_io/activate/push_data()
for(var/datum/integrated_io/io in linked)
io.holder.check_then_do_work()
/datum/integrated_io/proc/pull_data()
for(var/datum/integrated_io/io in linked)
write_data_to_pin(io.data)
/datum/integrated_io/proc/get_linked_to_desc()
if(linked.len)
return "the [english_list(linked)]"
return "nothing"
/datum/integrated_io/proc/disconnect()
//First we iterate over everything we are linked to.
for(var/datum/integrated_io/their_io in linked)
//While doing that, we iterate them as well, and disconnect ourselves from them.
for(var/datum/integrated_io/their_linked_io in their_io.linked)
if(their_linked_io == src)
their_io.linked.Remove(src)
else
continue
//Now that we're removed from them, we gotta remove them from us.
src.linked.Remove(their_io)
/datum/integrated_io/input
name = "input pin"
/datum/integrated_io/output
name = "output pin"
/datum/integrated_io/activate
name = "activation pin"
io_type = PULSE_CHANNEL
/datum/integrated_io/list
name = "list pin"
/datum/integrated_io/list/write_data_to_pin(var/new_data)
if(islist(new_data))
data = new_data
holder.on_data_written()
/datum/integrated_io/list/display_pin_type()
return IC_FORMAT_LIST

View File

@@ -20,6 +20,9 @@
icon_state = "wirer-[mode]"
/obj/item/device/integrated_electronics/wirer/proc/wire(var/datum/integrated_io/io, mob/user)
if(!io.holder.assembly)
to_chat(user, "<span class='warning'>\The [io.holder] needs to be secured inside an assembly first.</span>")
return
if(mode == WIRE)
selected_io = io
to_chat(user, "<span class='notice'>You attach a data wire to \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
@@ -33,6 +36,9 @@
to_chat(user, "<span class='warning'>Those two types of channels are incompatable. The first is a [selected_io.io_type], \
while the second is a [io.io_type].</span>")
return
if(io.holder.assembly && io.holder.assembly != selected_io.holder.assembly)
to_chat(user, "<span class='warning'>Both \the [io.holder] and \the [selected_io.holder] need to be inside the same assembly.</span>")
return
selected_io.linked |= io
io.linked |= selected_io
@@ -191,6 +197,7 @@
new /obj/item/weapon/storage/bag/circuits/mini/reagents(src)
new /obj/item/weapon/storage/bag/circuits/mini/transfer(src)
new /obj/item/weapon/storage/bag/circuits/mini/converter(src)
new /obj/item/weapon/storage/bag/circuits/mini/power(src)
new /obj/item/device/electronic_assembly(src)
new /obj/item/device/integrated_electronics/wirer(src)
@@ -202,11 +209,24 @@
/obj/item/weapon/storage/bag/circuits/all/New()
..()
spawn(2 SECONDS) // So the list has time to initialize.
for(var/obj/item/integrated_circuit/IC in all_integrated_circuits)
for(var/i = 1 to 10)
new IC.type(src)
new /obj/item/weapon/storage/bag/circuits/mini/arithmetic/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/trig/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/input/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/output/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/memory/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/logic/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/smart/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/manipulation/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/time/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/reagents/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/transfer/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/converter/all(src)
new /obj/item/weapon/storage/bag/circuits/mini/power/all(src)
new /obj/item/device/electronic_assembly(src)
new /obj/item/device/electronic_assembly/medium(src)
new /obj/item/device/electronic_assembly/large(src)
new /obj/item/device/electronic_assembly/drone(src)
new /obj/item/device/integrated_electronics/wirer(src)
new /obj/item/device/integrated_electronics/debugger(src)
new /obj/item/weapon/crowbar(src)
@@ -219,16 +239,20 @@
w_class = 2
display_contents_with_number = 1
can_hold = list(/obj/item/integrated_circuit)
var/spawn_flags_to_use = IC_SPAWN_DEFAULT
/obj/item/weapon/storage/bag/circuits/mini/arithmetic
name = "arithmetic circuit box"
desc = "Warning: Contains math."
icon_state = "box_arithmetic"
/obj/item/weapon/storage/bag/circuits/mini/arithmetic/all // Don't believe this will ever be needed.
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/arithmetic/New()
..()
for(var/obj/item/integrated_circuit/arithmetic/IC in all_integrated_circuits)
if(IC.spawn_flags & IC_SPAWN_DEFAULT)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()
@@ -239,10 +263,13 @@
desc = "Danger: Contains more math."
icon_state = "box_trig"
/obj/item/weapon/storage/bag/circuits/mini/trig/all // Ditto
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/trig/New()
..()
for(var/obj/item/integrated_circuit/trig/IC in all_integrated_circuits)
if(IC.spawn_flags & IC_SPAWN_DEFAULT)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()
@@ -253,10 +280,13 @@
desc = "Tell these circuits everything you know."
icon_state = "box_input"
/obj/item/weapon/storage/bag/circuits/mini/input/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/input/New()
..()
for(var/obj/item/integrated_circuit/input/IC in all_integrated_circuits)
if(IC.spawn_flags & IC_SPAWN_DEFAULT)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()
@@ -267,10 +297,13 @@
desc = "Circuits to interface with the world beyond itself."
icon_state = "box_output"
/obj/item/weapon/storage/bag/circuits/mini/output/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/output/New()
..()
for(var/obj/item/integrated_circuit/output/IC in all_integrated_circuits)
if(IC.spawn_flags & IC_SPAWN_DEFAULT)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()
@@ -281,25 +314,30 @@
desc = "Machines can be quite forgetful without these."
icon_state = "box_memory"
/obj/item/weapon/storage/bag/circuits/mini/memory/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/memory/New()
..()
for(var/obj/item/integrated_circuit/memory/IC in all_integrated_circuits)
if(IC.spawn_flags & IC_SPAWN_DEFAULT)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()
/obj/item/weapon/storage/bag/circuits/mini/logic
name = "logic circuit box"
desc = "May or may not be Turing complete."
icon_state = "box_logic"
/obj/item/weapon/storage/bag/circuits/mini/logic/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/logic/New()
..()
for(var/obj/item/integrated_circuit/logic/IC in all_integrated_circuits)
if(IC.spawn_flags & IC_SPAWN_DEFAULT)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()
@@ -310,10 +348,13 @@
desc = "No time machine parts, sadly."
icon_state = "box_time"
/obj/item/weapon/storage/bag/circuits/mini/time/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/time/New()
..()
for(var/obj/item/integrated_circuit/time/IC in all_integrated_circuits)
if(IC.spawn_flags & IC_SPAWN_DEFAULT)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()
@@ -324,10 +365,13 @@
desc = "Unlike most electronics, these circuits are supposed to come in contact with liquids."
icon_state = "box_reagents"
/obj/item/weapon/storage/bag/circuits/mini/reagents/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/reagents/New()
..()
for(var/obj/item/integrated_circuit/reagent/IC in all_integrated_circuits)
if(IC.spawn_flags & IC_SPAWN_DEFAULT)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()
@@ -338,10 +382,13 @@
desc = "Useful for moving data representing something arbitrary to another arbitrary virtual place."
icon_state = "box_transfer"
/obj/item/weapon/storage/bag/circuits/mini/transfer/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/transfer/New()
..()
for(var/obj/item/integrated_circuit/transfer/IC in all_integrated_circuits)
if(IC.spawn_flags & IC_SPAWN_DEFAULT)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()
@@ -352,10 +399,66 @@
desc = "Transform one piece of data to another type of data with these."
icon_state = "box_converter"
/obj/item/weapon/storage/bag/circuits/mini/converter/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/converter/New()
..()
for(var/obj/item/integrated_circuit/converter/IC in all_integrated_circuits)
if(IC.spawn_flags & IC_SPAWN_DEFAULT)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()
/obj/item/weapon/storage/bag/circuits/mini/smart
name = "smart box"
desc = "Sentience not included."
icon_state = "box_ai"
/obj/item/weapon/storage/bag/circuits/mini/smart/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/smart/New()
..()
for(var/obj/item/integrated_circuit/smart/IC in all_integrated_circuits)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()
/obj/item/weapon/storage/bag/circuits/mini/manipulation
name = "manipulation box"
desc = "Make your machines actually useful with these."
icon_state = "box_manipulation"
/obj/item/weapon/storage/bag/circuits/mini/manipulation/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/manipulation/New()
..()
for(var/obj/item/integrated_circuit/manipulation/IC in all_integrated_circuits)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()
/obj/item/weapon/storage/bag/circuits/mini/power
name = "power circuit box"
desc = "Electronics generally require electricity."
icon_state = "box_power"
/obj/item/weapon/storage/bag/circuits/mini/power/all
spawn_flags_to_use = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/weapon/storage/bag/circuits/mini/power/New()
..()
for(var/obj/item/integrated_circuit/passive/power/IC in all_integrated_circuits)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
for(var/obj/item/integrated_circuit/power/IC in all_integrated_circuits)
if(IC.spawn_flags & spawn_flags_to_use)
for(var/i = 1 to 3)
new IC.type(src)
make_exact_fit()

View File

@@ -1,85 +0,0 @@
/obj/item/integrated_circuit/transfer
category_text = "Data Transfer"
autopulse = 1
/obj/item/integrated_circuit/transfer/on_data_written()
if(autopulse == 1)
check_then_do_work()
/obj/item/integrated_circuit/transfer/splitter
name = "splitter"
desc = "Splits incoming data into all of the output pins."
icon_state = "splitter"
complexity = 3
inputs = list("data to split")
outputs = list("A","B")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/transfer/splitter/medium
name = "four splitter"
icon_state = "splitter4"
complexity = 5
outputs = list("A","B","C","D")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/transfer/splitter/large
name = "eight splitter"
icon_state = "splitter8"
complexity = 9
outputs = list("A","B","C","D","E","F","G","H")
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/transfer/splitter/do_work()
var/datum/integrated_io/I = inputs[1]
for(var/datum/integrated_io/output/O in outputs)
O.data = I.data
/obj/item/integrated_circuit/transfer/activator_splitter
name = "activator splitter"
desc = "Splits incoming activation pulses into all of the output pins."
icon_state = "splitter"
complexity = 3
activators = list(
"incoming pulse",
"outgoing pulse A",
"outgoing pulse B"
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/transfer/activator_splitter/do_work()
for(var/datum/integrated_io/activate/A in outputs)
if(A == activators[1])
continue
if(A.linked.len)
for(var/datum/integrated_io/activate/target in A.linked)
target.holder.check_then_do_work()
/obj/item/integrated_circuit/transfer/activator_splitter/medium
name = "four activator splitter"
icon_state = "splitter4"
complexity = 5
activators = list(
"incoming pulse",
"outgoing pulse A",
"outgoing pulse B",
"outgoing pulse C",
"outgoing pulse D"
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/transfer/activator_splitter/large
name = "eight activator splitter"
icon_state = "splitter4"
complexity = 9
activators = list(
"incoming pulse",
"outgoing pulse A",
"outgoing pulse B",
"outgoing pulse C",
"outgoing pulse D",
"outgoing pulse E",
"outgoing pulse F",
"outgoing pulse G",
"outgoing pulse H"
)
spawn_flags = IC_SPAWN_RESEARCH

View File

@@ -0,0 +1,7 @@
// 'Passive' components do not have any pins, and instead contribute in some form to the assembly holding them.
/obj/item/integrated_circuit/passive
inputs = list()
outputs = list()
activators = list()
power_draw_idle = 0
power_draw_per_use = 0

View File

@@ -0,0 +1,109 @@
/obj/item/integrated_circuit/passive/power
name = "power thingy"
desc = "Does power stuff."
complexity = 5
origin_tech = list(TECH_POWER = 2, TECH_ENGINEERING = 2, TECH_DATA = 2)
category_text = "Power - Passive"
/obj/item/integrated_circuit/passive/power/proc/make_energy()
return
// For calculators.
/obj/item/integrated_circuit/passive/power/solar_cell
name = "tiny photovoltaic cell"
desc = "It's a very tiny solar cell, generally used in calculators."
extended_desc = "The cell generates 1W of energy per second in optimal lighting conditions. Less light will result in less power being generated."
icon_state = "solar_cell"
complexity = 8
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_DATA = 2)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/max_power = 1
/obj/item/integrated_circuit/passive/power/solar_cell/make_energy()
var/atom/movable/lighting_overlay/light = locate(/atom/movable/lighting_overlay) in get_turf(src)
var/light_amount = 1 // Unsimulated tiles are pretend-lit, so we need to be pretend too if that somehow happens.
if(light)
light_amount = (light.lum_r + light.lum_g + light.lum_b) / 3
var/adjusted_power = max(max_power * light_amount, 0)
adjusted_power = round(adjusted_power, 0.1)
if(adjusted_power)
if(assembly)
assembly.give_power(adjusted_power)
// For implants.
/obj/item/integrated_circuit/passive/power/metabolic_siphon
name = "metabolic siphon"
desc = "A complicated piece of technology which converts bodily nutriments of a host into electricity."
extended_desc = "The siphon generates 10W of energy, so long as the siphon exists inside a biological entity. The entity will feel an increased \
appetite and will need to eat more often due to this. This device will fail if used inside synthetic entities."
icon_state = "setup_implant"
complexity = 10
origin_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_BIO = 5)
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/passive/power/metabolic_siphon/proc/test_validity(var/mob/living/carbon/human/host)
if(!host || host.isSynthetic() || host.stat == DEAD || host.nutrition <= 10)
return FALSE // Robots and dead people don't have a metabolism.
return TRUE
/obj/item/integrated_circuit/passive/power/metabolic_siphon/make_energy()
var/mob/living/carbon/human/host = null
if(assembly && istype(assembly, /obj/item/device/electronic_assembly/implant))
var/obj/item/device/electronic_assembly/implant/implant_assembly = assembly
if(implant_assembly.implant.imp_in)
host = implant_assembly.implant.imp_in
if(host && test_validity(host))
assembly.give_power(10)
host.nutrition = max(host.nutrition - DEFAULT_HUNGER_FACTOR, 0)
/obj/item/integrated_circuit/passive/power/metabolic_siphon/synthetic
name = "internal energy siphon"
desc = "A small circuit designed to be connected to an internal power wire inside a synthetic entity."
extended_desc = "The siphon generates 10W of energy, so long as the siphon exists inside a synthetic entity. The entity need to recharge \
more often due to this. This device will fail if used inside organic entities."
icon_state = "setup_implant"
complexity = 10
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 4, TECH_DATA = 3)
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/passive/power/metabolic_siphon/synthetic/test_validity(var/mob/living/carbon/human/host)
if(!host || !host.isSynthetic() || host.stat == DEAD || host.nutrition <= 10)
return FALSE // This time we don't want a metabolism.
return TRUE
// For fat machines that need fat power, like drones.
/obj/item/integrated_circuit/passive/power/relay
name = "tesla power relay"
desc = "A seemingly enigmatic device which connects to nearby APCs wirelessly and draws power from them."
w_class = ITEMSIZE_NORMAL
extended_desc = "The siphon generates 250W of energy, so long as an APC is in the same room, with a cell that has energy. It will always drain \
from the 'equipment' power channel."
icon_state = "power_relay"
complexity = 7
origin_tech = list(TECH_POWER = 3, TECH_ENGINEERING = 3, TECH_DATA = 2)
spawn_flags = IC_SPAWN_RESEARCH
var/power_amount = 250
// For really fat machines.
/obj/item/integrated_circuit/passive/power/relay/large
name = "large tesla power relay"
desc = "A seemingly enigmatic device which connects to nearby APCs wirelessly and draws power from them, now in industiral size!"
w_class = ITEMSIZE_LARGE
extended_desc = "The siphon generates 2 kW of energy, so long as an APC is in the same room, with a cell that has energy. It will always drain \
from the 'equipment' power channel."
icon_state = "power_relay"
complexity = 15
origin_tech = list(TECH_POWER = 6, TECH_ENGINEERING = 5, TECH_DATA = 4)
spawn_flags = IC_SPAWN_RESEARCH
power_amount = 2000
/obj/item/integrated_circuit/passive/power/relay/make_energy()
if(!assembly)
return
var/area/A = get_area(src)
if(A)
if(A.powered(EQUIP))
A.use_power(power_amount, EQUIP)
assembly.give_power(power_amount) // give_power() handles CELLRATE on its own.

View File

@@ -6,6 +6,7 @@
activators = list("compute")
category_text = "Arithmetic"
autopulse = 1
power_draw_per_use = 5 // Math is pretty cheap.
/obj/item/integrated_circuit/arithmetic/on_data_written()
if(autopulse == 1)

View File

@@ -6,6 +6,7 @@
activators = list("convert")
category_text = "Converter"
autopulse = 1
power_draw_per_use = 10
/obj/item/integrated_circuit/converter/on_data_written()
if(autopulse == 1)

View File

@@ -0,0 +1,186 @@
/obj/item/integrated_circuit/transfer
category_text = "Data Transfer"
autopulse = 1
power_draw_per_use = 2
/obj/item/integrated_circuit/transfer/on_data_written()
if(autopulse == 1)
check_then_do_work()
/obj/item/integrated_circuit/transfer/splitter
name = "splitter"
desc = "Splits incoming data into all of the output pins."
icon_state = "splitter"
complexity = 3
inputs = list("data to split")
outputs = list("A","B")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/transfer/splitter/medium
name = "four splitter"
icon_state = "splitter4"
complexity = 5
outputs = list("A","B","C","D")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/transfer/splitter/large
name = "eight splitter"
icon_state = "splitter8"
w_class = ITEMSIZE_SMALL
complexity = 9
outputs = list("A","B","C","D","E","F","G","H")
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 8
/obj/item/integrated_circuit/transfer/splitter/do_work()
var/datum/integrated_io/I = inputs[1]
for(var/datum/integrated_io/output/O in outputs)
O.data = I.data
/obj/item/integrated_circuit/transfer/activator_splitter
name = "activator splitter"
desc = "Splits incoming activation pulses into all of the output pins."
icon_state = "splitter"
complexity = 3
activators = list(
"incoming pulse",
"outgoing pulse A",
"outgoing pulse B"
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 2
/obj/item/integrated_circuit/transfer/activator_splitter/do_work()
for(var/datum/integrated_io/activate/A in outputs)
if(A == activators[1])
continue
if(A.linked.len)
for(var/datum/integrated_io/activate/target in A.linked)
target.holder.check_then_do_work()
/obj/item/integrated_circuit/transfer/activator_splitter/medium
name = "four activator splitter"
icon_state = "splitter4"
complexity = 5
activators = list(
"incoming pulse",
"outgoing pulse A",
"outgoing pulse B",
"outgoing pulse C",
"outgoing pulse D"
)
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/transfer/activator_splitter/large
name = "eight activator splitter"
icon_state = "splitter4"
w_class = ITEMSIZE_SMALL
complexity = 9
activators = list(
"incoming pulse",
"outgoing pulse A",
"outgoing pulse B",
"outgoing pulse C",
"outgoing pulse D",
"outgoing pulse E",
"outgoing pulse F",
"outgoing pulse G",
"outgoing pulse H"
)
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 8
/obj/item/integrated_circuit/transfer/multiplexer
name = "two multiplexer"
desc = "This is what those in the business tend to refer to as a 'mux' or data selector. It moves data from one of the selected inputs to the output."
extended_desc = "The first input pin is used to select which of the other input pins which has its data moved to the output. If the input selection is outside the valid range then no output is given."
complexity = 2
icon_state = "mux2"
inputs = list("input selection")
outputs = list("output")
activators = list("select")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
var/number_of_inputs = 2
/obj/item/integrated_circuit/transfer/multiplexer/New()
for(var/i = 1 to number_of_inputs)
inputs += "input [i]"
complexity = number_of_inputs
..()
desc += " It has [number_of_inputs] input pins."
extended_desc += " This multiplexer has a range from 1 to [inputs.len - 1]."
/obj/item/integrated_circuit/transfer/multiplexer/do_work()
var/input_index = get_pin_data(IC_INPUT, 1)
var/output = null
if(isnum(input_index) && (input_index >= 1 && input_index < inputs.len))
output = get_pin_data(IC_INPUT, input_index + 1)
set_pin_data(IC_OUTPUT, 1, output)
/obj/item/integrated_circuit/transfer/multiplexer/medium
name = "four multiplexer"
number_of_inputs = 4
icon_state = "mux4"
/obj/item/integrated_circuit/transfer/multiplexer/large
name = "eight multiplexer"
number_of_inputs = 8
w_class = ITEMSIZE_SMALL
icon_state = "mux8"
/obj/item/integrated_circuit/transfer/multiplexer/huge
name = "sixteen multiplexer"
icon_state = "mux16"
w_class = ITEMSIZE_SMALL
number_of_inputs = 16
/obj/item/integrated_circuit/transfer/demultiplexer
name = "two demultiplexer"
desc = "This is what those in the business tend to refer to as a 'demux'. It moves data from the input to one of the selected outputs."
extended_desc = "The first input pin is used to select which of the output pins is given the data from the second input pin. If the output selection is outside the valid range then no output is given."
complexity = 2
icon_state = "dmux2"
inputs = list("output selection","input")
outputs = list()
activators = list("select")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
var/number_of_outputs = 2
/obj/item/integrated_circuit/transfer/demultiplexer/New()
for(var/i = 1 to number_of_outputs)
outputs += "output [i]"
complexity = number_of_outputs
..()
desc += " It has [number_of_outputs] output pins."
extended_desc += " This demultiplexer has a range from 1 to [outputs.len]."
/obj/item/integrated_circuit/transfer/demultiplexer/do_work()
var/output_index = get_pin_data(IC_INPUT, 1)
var/output = get_pin_data(IC_INPUT, 2)
for(var/i = 1 to outputs.len)
set_pin_data(IC_OUTPUT, i, i == output_index ? output : null)
/obj/item/integrated_circuit/transfer/demultiplexer/medium
name = "four demultiplexer"
icon_state = "dmux4"
number_of_outputs = 4
/obj/item/integrated_circuit/transfer/demultiplexer/large
name = "eight demultiplexer"
icon_state = "dmux8"
w_class = ITEMSIZE_SMALL
number_of_outputs = 8
/obj/item/integrated_circuit/transfer/demultiplexer/huge
name = "sixteen demultiplexer"
icon_state = "dmux16"
w_class = ITEMSIZE_SMALL
number_of_outputs = 16

View File

@@ -1,6 +1,7 @@
/obj/item/integrated_circuit/input
var/can_be_asked_input = 0
category_text = "Input"
power_draw_per_use = 5
/obj/item/integrated_circuit/input/proc/ask_for_input(mob/user)
return
@@ -23,6 +24,21 @@
target.holder.check_then_do_work()
to_chat(user, "<span class='notice'>You press the button labeled '[src.name]'.</span>")
/obj/item/integrated_circuit/input/toggle_button
name = "toggle button"
desc = "It toggles on, off, on, off..."
icon_state = "toggle_button"
complexity = 1
inputs = list()
outputs = list("on" = 0)
activators = list("on toggle")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/input/toggle_button/ask_for_input(mob/user) // Ditto.
set_pin_data(IC_OUTPUT, 1, !get_pin_data(IC_OUTPUT, 1))
activate_pin(1)
to_chat(user, "<span class='notice'>You toggle the button labeled '[src.name]' [get_pin_data(IC_OUTPUT, 1) ? "on" : "off"].</span>")
/obj/item/integrated_circuit/input/numberpad
name = "number pad"
desc = "This small number pad allows someone to input a number into the system."
@@ -33,6 +49,7 @@
outputs = list("number entered")
activators = list("on entered")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/input/numberpad/ask_for_input(mob/user)
var/new_input = input(user, "Enter a number, please.","Number pad") as null|num
@@ -53,6 +70,7 @@
outputs = list("string entered")
activators = list("on entered")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/input/textpad/ask_for_input(mob/user)
var/new_input = input(user, "Enter some words, please.","Number pad") as null|text
@@ -73,6 +91,7 @@
activators = list("scan")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
power_draw_per_use = 40
/obj/item/integrated_circuit/input/med_scanner/do_work()
var/datum/integrated_io/I = inputs[1]
@@ -111,6 +130,7 @@
activators = list("scan")
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 4)
power_draw_per_use = 80
/obj/item/integrated_circuit/input/adv_med_scanner/do_work()
var/datum/integrated_io/I = inputs[1]
@@ -148,12 +168,12 @@
outputs = list("located ref")
activators = list("locate")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 20
/obj/item/integrated_circuit/input/local_locator/do_work()
var/datum/integrated_io/O = outputs[1]
O.data = null
if(istype(src.loc, /obj/item/device/electronic_assembly)) // Check to make sure we're actually in a machine.
var/obj/item/device/electronic_assembly/assembly = src.loc
if(assembly)
if(istype(assembly.loc, /mob/living)) // Now check if someone's holding us.
O.data = weakref(assembly.loc)
@@ -170,6 +190,7 @@
outputs = list("located ref")
activators = list("locate")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 30
/obj/item/integrated_circuit/input/adjacent_locator/do_work()
var/datum/integrated_io/I = inputs[1]
@@ -205,7 +226,9 @@
outputs = list()
activators = list("send signal","on signal received")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNETS = 2)
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2)
power_draw_idle = 5
power_draw_per_use = 40
var/frequency = 1457
var/code = 30
@@ -287,7 +310,8 @@
outputs = list("address received", "data received", "secondary text received")
activators = list("send data", "on data received")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNETS = 2, TECH_BLUESPACE = 2)
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2)
power_draw_per_use = 50
var/datum/exonet_protocol/exonet = null
/obj/item/integrated_circuit/input/EPv2/New()
@@ -334,6 +358,7 @@
outputs = list("X (abs)", "Y (abs)")
activators = list("get coordinates")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 30
/obj/item/integrated_circuit/input/gps/do_work()
var/turf/T = get_turf(src)
@@ -361,6 +386,7 @@
outputs = list("speaker \<String\>", "message \<String\>")
activators = list("on message received")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 15
/obj/item/integrated_circuit/input/microphone/New()
..()
@@ -385,9 +411,27 @@
for(var/datum/integrated_io/output/out in outputs)
out.push_data()
A.push_data()
/obj/item/integrated_circuit/input/sensor
name = "sensor"
desc = "Scans and obtains a reference for any objects or persons near you. All you need to do is shove the machine in their face."
icon_state = "recorder"
complexity = 12
inputs = list()
outputs = list("scanned ref \<Ref\>")
activators = list("on scanned")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 120
/obj/item/integrated_circuit/input/sensor/do_work()
// Because this gets called by attack(), all this needs to do is pulse the activator.
for(var/datum/integrated_io/output/O in outputs)
O.push_data()
var/datum/integrated_io/activate/A = activators[1]
A.push_data()
/obj/item/integrated_circuit/output
@@ -401,8 +445,18 @@
outputs = list()
activators = list("load data")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 10
autopulse = 1
var/stuff_to_display = null
/obj/item/integrated_circuit/output/screen/disconnect_all()
..()
stuff_to_display = null
/obj/item/integrated_circuit/output/screen/any_examine(mob/user)
to_chat(user, "There is a little screen labeled '[name]', which displays [stuff_to_display ? "'[stuff_to_display]'" : "nothing"].")
/obj/item/integrated_circuit/output/screen/do_work()
var/datum/integrated_io/I = inputs[1]
if(isweakref(I.data))
@@ -416,22 +470,24 @@
name = "screen"
desc = "This screen allows for people holding the device to see a piece of data."
icon_state = "screen_medium"
power_draw_per_use = 20
/obj/item/integrated_circuit/output/screen/medium/do_work()
..()
var/list/nearby_things = range(0, get_turf(src))
for(var/mob/M in nearby_things)
var/obj/O = istype(loc, /obj/item/device/electronic_assembly) ? loc : src
visible_message("<span class='notice'>\icon[O] [stuff_to_display]</span>")
var/obj/O = assembly ? assembly : src
to_chat(M, "<span class='notice'>\icon[O] [stuff_to_display]</span>")
/obj/item/integrated_circuit/output/screen/large
name = "large screen"
desc = "This screen allows for people able to see the device to see a piece of data."
icon_state = "screen_large"
power_draw_per_use = 40
/obj/item/integrated_circuit/output/screen/large/do_work()
..()
var/obj/O = istype(loc, /obj/item/device/electronic_assembly) ? loc : src
var/obj/O = assembly ? loc : assembly
O.visible_message("<span class='notice'>\icon[O] [stuff_to_display]</span>")
/obj/item/integrated_circuit/output/light
@@ -446,6 +502,10 @@
var/light_toggled = 0
var/light_brightness = 3
var/light_rgb = "#FFFFFF"
power_draw_idle = 0 // Adjusted based on brightness.
/obj/item/integrated_circuit/output/light/Destroy()
..()
/obj/item/integrated_circuit/output/light/do_work()
light_toggled = !light_toggled
@@ -456,6 +516,7 @@
set_light(l_range = light_brightness, l_power = light_brightness, l_color = light_rgb)
else
set_light(0)
power_draw_idle = light_toggled ? light_brightness * 2 : 0
/obj/item/integrated_circuit/output/light/advanced/update_lighting()
var/datum/integrated_io/R = inputs[1]
@@ -473,6 +534,10 @@
..()
/obj/item/integrated_circuit/output/light/power_fail() // Turns off the flashlight if there's no power left.
light_toggled = FALSE
update_lighting()
/obj/item/integrated_circuit/output/light/advanced
name = "advanced light"
desc = "This light can turn on and off on command, in any color, and in various brightness levels."
@@ -504,6 +569,7 @@
)
outputs = list()
activators = list("play sound")
power_draw_per_use = 20
var/list/sounds = list()
/obj/item/integrated_circuit/output/text_to_speech
@@ -517,11 +583,12 @@
outputs = list()
activators = list("to speech")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 60
/obj/item/integrated_circuit/output/text_to_speech/do_work()
var/datum/integrated_io/text = inputs[1]
if(istext(text.data))
var/obj/O = istype(loc, /obj/item/device/electronic_assembly) ? loc : src
var/obj/O = assembly ? loc : assembly
audible_message("\icon[O] \The [O.name] states, \"[text.data]\"")
/obj/item/integrated_circuit/output/sound/New()
@@ -576,4 +643,118 @@
"secure day" = 'sound/voice/bsecureday.ogg',
)
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_ILLEGAL = 1)
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_ILLEGAL = 1)
/obj/item/integrated_circuit/output/video_camera
name = "video camera circuit"
desc = "This small camera allows a remote viewer to see what it sees."
extended_desc = "The camera is linked to the Research camera network."
icon_state = "video_camera"
w_class = ITEMSIZE_SMALL
complexity = 10
inputs = list("camera name" = "video camera circuit", "camera active" = 0)
outputs = list()
activators = list()
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_idle = 5 // Raises to 80 when on.
var/obj/machinery/camera/network/research/camera
/obj/item/integrated_circuit/output/video_camera/New()
..()
camera = new(src)
on_data_written()
/obj/item/integrated_circuit/output/video_camera/Destroy()
qdel(camera)
..()
/obj/item/integrated_circuit/output/video_camera/proc/set_camera_status(var/status)
if(camera)
camera.set_status(status)
power_draw_idle = camera.status ? 80 : 5
if(camera.status) // Ensure that there's actually power.
if(!draw_idle_power())
power_fail()
/obj/item/integrated_circuit/output/video_camera/on_data_written()
if(camera)
var/datum/integrated_io/cam_name = inputs[1]
var/datum/integrated_io/cam_active = inputs[2]
if(istext(cam_name.data))
camera.c_tag = cam_name.data
if(isnum(cam_active.data))
set_camera_status(cam_active.data)
/obj/item/integrated_circuit/output/video_camera/power_fail()
if(camera)
set_camera_status(0)
var/datum/integrated_io/cam_active = inputs[2]
cam_active.data = FALSE
/obj/item/integrated_circuit/output/led
name = "light-emitting diode"
desc = "This a LED that is lit whenever there is TRUE-equivalent data on its input."
extended_desc = "TRUE-equivalent values are: Non-empty strings, non-zero numbers, and valid refs."
complexity = 0.1
icon_state = "led"
inputs = list("lit")
outputs = list()
activators = list()
power_draw_idle = 0 // Raises to 1 when lit.
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/led_color
/obj/item/integrated_circuit/output/led/on_data_written()
power_draw_idle = get_pin_data(IC_INPUT, 1) ? 1 : 0
/obj/item/integrated_circuit/output/led/power_fail()
set_pin_data(IC_INPUT, 1, FALSE)
/obj/item/integrated_circuit/output/led/any_examine(mob/user)
var/text_output = list()
var/initial_name = initial(name)
// Doing all this work just to have a color-blind friendly output.
text_output += "There is "
if(name == initial_name)
text_output += "\an [name]"
else
text_output += "\an ["\improper[initial_name]"] labeled '[name]'"
text_output += " which is currently [get_pin_data(IC_INPUT, 1) ? "lit <font color=[led_color]>¤</font>" : "unlit."]"
to_chat(user,jointext(text_output,null))
/obj/item/integrated_circuit/output/led/red
name = "red LED"
led_color = COLOR_RED
/obj/item/integrated_circuit/output/led/orange
name = "orange LED"
led_color = COLOR_ORANGE
/obj/item/integrated_circuit/output/led/yellow
name = "yellow LED"
led_color = COLOR_YELLOW
/obj/item/integrated_circuit/output/led/green
name = "green LED"
led_color = COLOR_GREEN
/obj/item/integrated_circuit/output/led/blue
name = "blue LED"
led_color = COLOR_BLUE
/obj/item/integrated_circuit/output/led/purple
name = "purple LED"
led_color = COLOR_PURPLE
/obj/item/integrated_circuit/output/led/cyan
name = "cyan LED"
led_color = COLOR_CYAN
/obj/item/integrated_circuit/output/led/white
name = "white LED"
led_color = COLOR_WHITE
/obj/item/integrated_circuit/output/led/pink
name = "pink LED"
led_color = COLOR_PINK

View File

@@ -4,9 +4,10 @@
extended_desc = "Logic circuits will treat a null, 0, and a \"\" string value as FALSE and anything else as TRUE."
complexity = 3
outputs = list("result")
activators = list("compare", "on true result")
activators = list("compare", "on true result", "on false result")
category_text = "Logic"
autopulse = 1
power_draw_per_use = 1
/obj/item/integrated_circuit/logic/on_data_written()
if(autopulse == 1)
@@ -14,10 +15,13 @@
/obj/item/integrated_circuit/logic/do_work()
var/datum/integrated_io/O = outputs[1]
var/datum/integrated_io/P = activators[2]
var/datum/integrated_io/T = activators[2]
var/datum/integrated_io/F = activators[3]
O.push_data()
if(O.data)
P.push_data()
T.push_data()
else
F.push_data()
/obj/item/integrated_circuit/logic/binary
inputs = list("A","B")
@@ -53,6 +57,15 @@
/obj/item/integrated_circuit/logic/binary/equals/do_compare(var/datum/integrated_io/A, var/datum/integrated_io/B)
return A.data == B.data
/obj/item/integrated_circuit/logic/binary/not_equals
name = "not equal gate"
desc = "This gate compares two values, and outputs the number one if both are different."
icon_state = "not equal"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/binary/not_equals/do_compare(var/datum/integrated_io/A, var/datum/integrated_io/B)
return A.data != B.data
/obj/item/integrated_circuit/logic/binary/and
name = "and gate"
desc = "This gate will output 'one' if both inputs evaluate to true."
@@ -114,4 +127,4 @@
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/logic/unary/not/do_check(var/datum/integrated_io/A)
return !A.data
return !A.data

View File

@@ -9,6 +9,7 @@
The 'fire' activator will cause the mechanism to attempt to fire the weapon at the coordinates, if possible. Note that the \
normal limitations to firearms, such as ammunition requirements and firing delays, still hold true if fired by the mechanism."
complexity = 20
w_class = ITEMSIZE_NORMAL
inputs = list(
"target X rel",
"target Y rel"
@@ -20,6 +21,7 @@
var/obj/item/weapon/gun/installed_gun = null
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 4)
power_draw_per_use = 50 // The targeting mechanism uses this. The actual gun uses its own cell for firing if it's an energy weapon.
/obj/item/integrated_circuit/manipulation/weapon_firing/Destroy()
qdel(installed_gun)
@@ -106,20 +108,21 @@
<br>\
Pulsing the 'step towards dir' activator pin will cause the machine to move a meter in that direction, assuming it is not \
being held, or anchored in some way. It should be noted that the ability to move is dependant on the type of assembly that this circuit inhabits."
w_class = ITEMSIZE_NORMAL
complexity = 20
inputs = list("dir num")
outputs = list()
activators = list("step towards dir")
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 100
/obj/item/integrated_circuit/manipulation/locomotion/do_work()
..()
var/turf/T = get_turf(src)
if(T && istype(loc, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/machine = loc
if(machine.anchored || !machine.can_move())
if(T && assembly)
if(assembly.anchored || !assembly.can_move())
return
if(machine.loc == T) // Check if we're held by someone. If the loc is the floor, we're not held.
if(assembly.loc == T) // Check if we're held by someone. If the loc is the floor, we're not held.
var/datum/integrated_io/wanted_dir = inputs[1]
if(isnum(wanted_dir.data))
step(machine, wanted_dir.data)
step(assembly, wanted_dir.data)

View File

@@ -8,6 +8,7 @@
activators = list("set")
category_text = "Memory"
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 1
/obj/item/integrated_circuit/memory/examine(mob/user)
..()
@@ -33,15 +34,18 @@
name = "memory circuit"
desc = "This circuit can store four pieces of data."
icon_state = "memory4"
w_class = ITEMSIZE_SMALL
complexity = 4
inputs = list("input pin 1","input pin 2","input pin 3","input pin 4")
outputs = list("output pin 1","output pin 2","output pin 3","output pin 4")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 2
/obj/item/integrated_circuit/memory/large
name = "large memory circuit"
desc = "This big circuit can hold eight pieces of data."
icon_state = "memory8"
w_class = ITEMSIZE_SMALL
complexity = 8
inputs = list(
"input pin 1",
@@ -63,11 +67,13 @@
"output pin 8")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3)
power_draw_per_use = 4
/obj/item/integrated_circuit/memory/huge
name = "large memory stick"
desc = "This stick of memory can hold up up to sixteen pieces of data."
icon_state = "memory16"
w_class = ITEMSIZE_NORMAL
complexity = 16
inputs = list(
"input pin 1",
@@ -106,6 +112,7 @@
"output pin 16")
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4)
power_draw_per_use = 8
/obj/item/integrated_circuit/memory/constant
name = "constant chip"

View File

@@ -0,0 +1,80 @@
/obj/item/integrated_circuit/power/
category_text = "Power - Active"
/obj/item/integrated_circuit/power/transmitter
name = "power transmission circuit"
desc = "This can wirelessly transmit electricity from an assembly's battery towards a nearby machine."
icon_state = "power_transmitter"
extended_desc = "This circuit transmits 5 kJ of electricity every time the activator pin is pulsed. The input pin must be \
a reference to a machine to send electricity to. This can be a battery, or anything containing a battery. The machine can exist \
inside the assembly, or adjacent to it. The power is sourced from the assembly's power cell. If the target is outside of the assembly, \
some power is lost due to ineffiency."
w_class = ITEMSIZE_SMALL
complexity = 16
inputs = list("target ref")
outputs = list("target cell charge", "target cell max charge", "target cell percentage")
activators = list("transmit")
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 4, TECH_MAGNET = 3)
power_draw_per_use = 500 // Inefficency has to come from somewhere.
var/amount_to_move = 5000
/obj/item/integrated_circuit/power/transmitter/large
name = "large power transmission circuit"
desc = "This can wirelessly transmit a lot of electricity from an assembly's battery towards a nearby machine. Warning: Do not operate in flammable enviroments."
extended_desc = "This circuit transmits 20 kJ of electricity every time the activator pin is pulsed. The input pin must be \
a reference to a machine to send electricity to. This can be a battery, or anything containing a battery. The machine can exist \
inside the assembly, or adjacent to it. The power is sourced from the assembly's power cell. If the target is outside of the assembly, \
some power is lost due to ineffiency."
w_class = ITEMSIZE_LARGE
complexity = 32
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 6, TECH_MAGNET = 5)
power_draw_per_use = 2000
amount_to_move = 20000
/obj/item/integrated_circuit/power/transmitter/do_work()
set_pin_data(IC_OUTPUT, 1, null)
set_pin_data(IC_OUTPUT, 2, null)
set_pin_data(IC_OUTPUT, 3, null)
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
if(AM)
if(!assembly)
return FALSE // Pointless to do everything else if there's no battery to draw from.
var/obj/item/weapon/cell/cell = null
if(istype(AM, /obj/item/weapon/cell)) // Is this already a cell?
cell = AM
else // If not, maybe there's a cell inside it?
for(var/obj/item/weapon/cell/C in AM.contents)
if(C) // Find one cell to charge.
cell = C
break
if(cell)
var/transfer_amount = amount_to_move
var/turf/A = get_turf(src)
var/turf/B = get_turf(AM)
if(A.Adjacent(B))
if(AM.loc != assembly)
transfer_amount *= 0.8 // Losses due to distance.
if(cell.fully_charged())
return FALSE
if(transfer_amount && assembly.draw_power(amount_to_move)) // CELLRATE is already handled in draw_power()
cell.give(transfer_amount * CELLRATE)
AM.update_icon()
set_pin_data(IC_OUTPUT, 1, cell.charge)
set_pin_data(IC_OUTPUT, 2, cell.maxcharge)
set_pin_data(IC_OUTPUT, 3, cell.percent())
return TRUE
return FALSE
/obj/item/integrated_circuit/power/transmitter/large/do_work()
if(..()) // If the above code succeeds, do this below.
if(prob(2))
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
sparks.set_up(3, 0, get_turf(src))
sparks.start()
visible_message("<span class='warning'>\The [assembly] makes some sparks!</span>")
qdel(sparks)

View File

@@ -23,6 +23,7 @@
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 3)
volume = 100
power_draw_per_use = 20
/obj/item/integrated_circuit/reagent/smoke/do_work()
playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
@@ -47,6 +48,7 @@
activators = list("inject")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
volume = 30
power_draw_per_use = 15
/obj/item/integrated_circuit/reagent/injector/proc/inject_amount()
var/datum/integrated_io/amount = inputs[2]
@@ -92,6 +94,7 @@
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
var/transfer_amount = 10
power_draw_per_use = 10
/obj/item/integrated_circuit/reagent/pump/on_data_written()
var/datum/integrated_io/amount = inputs[3]

View File

@@ -0,0 +1,33 @@
/obj/item/integrated_circuit/smart
category_text = "Smart"
/obj/item/integrated_circuit/smart/basic_pathfinder
name = "basic pathfinder"
desc = "This complex circuit is able to determine what direction a given target is."
extended_desc = "This circuit uses a miniturized, integrated camera to determine where the target is. If the machine \
cannot see the target, it will not be able to calculate the correct direction."
icon_state = "numberpad"
complexity = 25
inputs = list("target ref")
outputs = list("dir")
activators = list("calculate dir")
spawn_flags = IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 5)
power_draw_per_use = 40
/obj/item/integrated_circuit/smart/basic_pathfinder/do_work()
var/datum/integrated_io/I = inputs[1]
var/datum/integrated_io/O = outputs[1]
O.data = null
if(!isweakref(I.data))
return
var/atom/A = I.data.resolve()
if(!A)
return
if(!(A in view(get_turf(src))))
return // Can't see the target.
var/desired_dir = get_dir(get_turf(src), A)
if(desired_dir)
O.data = desired_dir
O.push_data()

View File

@@ -14,6 +14,7 @@
var/delay = 2 SECONDS
activators = list("incoming pulse","outgoing pulse")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 2
/obj/item/integrated_circuit/time/delay/do_work()
set waitfor = 0 // Don't sleep in a proc that is called by a processor. It'll delay the entire thing
@@ -82,6 +83,7 @@
inputs = list("enable ticking")
activators = list("outgoing pulse")
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/time/ticker/Destroy()
if(is_running)
@@ -116,6 +118,7 @@
complexity = 12
ticks_to_pulse = 2
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 8
/obj/item/integrated_circuit/time/ticker/slow
name = "slow ticker"
@@ -124,6 +127,7 @@
complexity = 4
ticks_to_pulse = 6
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 2
/obj/item/integrated_circuit/time/clock
name = "integrated clock"
@@ -132,6 +136,7 @@
inputs = list()
outputs = list("time (string)", "hours (number)", "minutes (number)", "seconds (number)")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 4
/obj/item/integrated_circuit/time/clock/do_work()
var/datum/integrated_io/time = outputs[1]

View File

@@ -7,6 +7,7 @@
category_text = "Trig"
extended_desc = "Input and output are in degrees."
autopulse = 1
power_draw_per_use = 1 // Still cheap math.
/obj/item/integrated_circuit/trig/on_data_written()
if(autopulse == 1)
@@ -118,7 +119,7 @@
/obj/item/integrated_circuit/trig/cotangent
name = "cot circuit"
desc = "Outputs the cotangent of A. Has nothing to do with the security department."
desc = "Outputs the cotangent of A."
icon_state = "cotangent"
inputs = list("A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH

View File

@@ -1,6 +0,0 @@
#undef IC_INPUT
#undef IC_OUTPUT
#undef IC_ACTIVATOR
#undef DATA_CHANNEL
#undef PULSE_CHANNEL

View File

@@ -0,0 +1,16 @@
#undef IC_INPUT
#undef IC_OUTPUT
#undef IC_ACTIVATOR
#undef DATA_CHANNEL
#undef PULSE_CHANNEL
#undef IC_SPAWN_DEFAULT
//#undef IC_SPAWN_RESEARCH // Research designs depend on this unfortunately.
#undef IC_FORMAT_STRING
#undef IC_FORMAT_NUMBER
#undef IC_FORMAT_REF
#undef IC_FORMAT_LIST
#undef IC_FORMAT_ANY
#undef IC_FORMAT_PULSE

View File

@@ -252,8 +252,9 @@
for(var/iy = 0,iy < 5, iy++)
for(var/ix = 0, ix < 5, ix++)
mine_turf = locate(tx + ix, ty + iy, T.z)
if(mine_turf && mine_turf.has_resources)
resource_field += mine_turf
if(!istype(mine_turf, /turf/space/))
if(mine_turf && mine_turf.has_resources)
resource_field += mine_turf
if(!resource_field.len)
system_error("resources depleted")

View File

@@ -35,7 +35,7 @@ var/list/mining_overlay_cache = list()
var/ignore_mapgen
var/ore_types = list(
"iron" = /obj/item/weapon/ore/iron,
"hematite" = /obj/item/weapon/ore/iron,
"uranium" = /obj/item/weapon/ore/uranium,
"gold" = /obj/item/weapon/ore/gold,
"silver" = /obj/item/weapon/ore/silver,
@@ -44,7 +44,7 @@ var/list/mining_overlay_cache = list()
"osmium" = /obj/item/weapon/ore/osmium,
"hydrogen" = /obj/item/weapon/ore/hydrogen,
"silicates" = /obj/item/weapon/ore/glass,
"carbonaceous rock" = /obj/item/weapon/ore/coal
"carbon" = /obj/item/weapon/ore/coal
)
has_resources = 1
@@ -483,6 +483,11 @@ var/list/mining_overlay_cache = list()
if(prob(50))
M.Stun(5)
M.apply_effect(25, IRRADIATE)
if(prob(25))
excavate_find(prob(5), finds[1])
else if(rand(1,500) == 1)
visible_message("<span class='notice'>An old dusty crate was buried within!</span>")
new /obj/structure/closet/crate/secure/loot(src)
make_floor()
update_icon(1)
@@ -546,10 +551,10 @@ var/list/mining_overlay_cache = list()
var/mineral_name
if(rare_ore)
mineral_name = pickweight(list("uranium" = 10, "platinum" = 10, "iron" = 20, "coal" = 20, "diamond" = 2, "gold" = 10, "silver" = 10, "phoron" = 20))
mineral_name = pickweight(list("uranium" = 10, "platinum" = 10, "hematite" = 20, "carbon" = 20, "diamond" = 2, "gold" = 10, "silver" = 10, "phoron" = 20))
else
mineral_name = pickweight(list("uranium" = 5, "platinum" = 5, "iron" = 35, "coal" = 35, "diamond" = 1, "gold" = 5, "silver" = 5, "phoron" = 10))
mineral_name = pickweight(list("uranium" = 5, "platinum" = 5, "hematite" = 35, "carbon" = 35, "diamond" = 1, "gold" = 5, "silver" = 5, "phoron" = 10))
if(mineral_name && (mineral_name in ore_data))
mineral = ore_data[mineral_name]

View File

@@ -1,5 +1,5 @@
/datum/language/ling
name = "Changeling"
name = LANGUAGE_CHANGELING
desc = "Although they are normally wary and suspicious of each other, changelings can commune over a distance."
speech_verb = "says"
colour = "changeling"
@@ -38,7 +38,7 @@
..(speaker,message,speaker_mask)
/datum/language/vox
name = "Vox-pidgin"
name = LANGUAGE_VOX
desc = "The common tongue of the various Vox ships making up the Shoal. It sounds like chaotic shrieking to everyone else."
speech_verb = "shrieks"
ask_verb = "creels"
@@ -73,7 +73,7 @@
"d'rekkathnor", "khari'd", "gual'te", "nikka", "nikt'o", "barada", "kla'atu", "barhah", "hra" ,"zar'garis", "spiri", "malum")
/datum/language/cult
name = "Occult"
name = LANGUAGE_OCCULT
desc = "The initiated can share their thoughts by means defying all reason."
speech_verb = "intones"
ask_verb = "intones"

View File

@@ -437,7 +437,6 @@
stop_pulling()
src << "<span class='warning'>You slipped on [slipped_on]!</span>"
playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
Stun(stun_duration)
Weaken(Floor(stun_duration/2))
return 1

View File

@@ -24,3 +24,8 @@
var/pulse = PULSE_NORM //current pulse level
var/does_not_breathe = 0 //Used for specific mobs that can't take advantage of the species flags (changelings)
//these two help govern taste. The first is the last time a taste message was shown to the plaer.
//the second is the message in question.
var/last_taste_time = 0
var/last_taste_text = ""

View File

@@ -685,12 +685,20 @@
if(istype(src.head, /obj/item/clothing/head/helmet/space/emergency))
number -= 2
if(istype(src.glasses, /obj/item/clothing/glasses/thermal))
number -= 1
var/obj/item/clothing/glasses/thermal/T = src.glasses
if(T.active)
number -= 1
if(istype(src.glasses, /obj/item/clothing/glasses/night))
var/obj/item/clothing/glasses/night/N = src.glasses
if(N.active)
number -= 1
if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses))
if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses/sechud/aviator))
var/obj/item/clothing/glasses/sunglasses/sechud/aviator/S = src.glasses
if(!S.on)
if(!S.active)
number += 1
else if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses/medhud/aviator))
number += 0
else
number += 1
if(istype(src.glasses, /obj/item/clothing/glasses/welding))
@@ -1315,7 +1323,8 @@
/mob/living/carbon/human/slip(var/slipped_on, stun_duration=8)
if((species.flags & NO_SLIP) || (shoes && (shoes.item_flags & NOSLIP)))
return 0
..(slipped_on,stun_duration)
if(..(slipped_on,stun_duration))
return 1
/mob/living/carbon/human/proc/undislocate()
set category = "Object"

View File

@@ -90,54 +90,6 @@
return 0
/mob/living/carbon/human
var/next_sonar_ping = 0
/mob/living/carbon/human/proc/sonar_ping()
set name = "Listen In"
set desc = "Allows you to listen in to movement and noises around you."
set category = "Abilities"
if(incapacitated())
src << "<span class='warning'>You need to recover before you can use this ability.</span>"
return
if(world.time < next_sonar_ping)
src << "<span class='warning'>You need another moment to focus.</span>"
return
if(is_deaf() || is_below_sound_pressure(get_turf(src)))
src << "<span class='warning'>You are for all intents and purposes currently deaf!</span>"
return
next_sonar_ping += 10 SECONDS
var/heard_something = FALSE
src << "<span class='notice'>You take a moment to listen in to your environment...</span>"
for(var/mob/living/L in range(client.view, src))
var/turf/T = get_turf(L)
if(!T || L == src || L.stat == DEAD || is_below_sound_pressure(T))
continue
heard_something = TRUE
var/feedback = list()
feedback += "<span class='notice'>There are noises of movement "
var/direction = get_dir(src, L)
if(direction)
feedback += "towards the [dir2text(direction)], "
switch(get_dist(src, L) / client.view)
if(0 to 0.2)
feedback += "very close by."
if(0.2 to 0.4)
feedback += "close by."
if(0.4 to 0.6)
feedback += "some distance away."
if(0.6 to 0.8)
feedback += "further away."
else
feedback += "far away."
else // No need to check distance if they're standing right on-top of us
feedback += "right on top of you."
feedback += "</span>"
src << jointext(feedback,null)
if(!heard_something)
src << "<span class='notice'>You hear no movement but your own.</span>"
#undef HUMAN_EATING_NO_ISSUE
#undef HUMAN_EATING_NO_MOUTH
#undef HUMAN_EATING_BLOCKED_MOUTH

View File

@@ -175,3 +175,84 @@
output += "[IO.name] - <span style='color:green;'>OK</span>\n"
src << output
/mob/living/carbon/human
var/next_sonar_ping = 0
/mob/living/carbon/human/proc/sonar_ping()
set name = "Listen In"
set desc = "Allows you to listen in to movement and noises around you."
set category = "Abilities"
if(incapacitated())
src << "<span class='warning'>You need to recover before you can use this ability.</span>"
return
if(world.time < next_sonar_ping)
src << "<span class='warning'>You need another moment to focus.</span>"
return
if(is_deaf() || is_below_sound_pressure(get_turf(src)))
src << "<span class='warning'>You are for all intents and purposes currently deaf!</span>"
return
next_sonar_ping += 10 SECONDS
var/heard_something = FALSE
src << "<span class='notice'>You take a moment to listen in to your environment...</span>"
for(var/mob/living/L in range(client.view, src))
var/turf/T = get_turf(L)
if(!T || L == src || L.stat == DEAD || is_below_sound_pressure(T))
continue
heard_something = TRUE
var/feedback = list()
feedback += "<span class='notice'>There are noises of movement "
var/direction = get_dir(src, L)
if(direction)
feedback += "towards the [dir2text(direction)], "
switch(get_dist(src, L) / client.view)
if(0 to 0.2)
feedback += "very close by."
if(0.2 to 0.4)
feedback += "close by."
if(0.4 to 0.6)
feedback += "some distance away."
if(0.6 to 0.8)
feedback += "further away."
else
feedback += "far away."
else // No need to check distance if they're standing right on-top of us
feedback += "right on top of you."
feedback += "</span>"
src << jointext(feedback,null)
if(!heard_something)
src << "<span class='notice'>You hear no movement but your own.</span>"
/mob/living/carbon/human/proc/regenerate()
set name = "Regenerate"
set desc = "Allows you to regrow limbs and heal organs."
set category = "Abilities"
if(nutrition < 250)
to_chat(src, "<span class='warning'>You lack the biomass regrow anything!</span>")
return
nutrition -= 200
// Theoretically the only internal organ a slime will have
// is the slime core. but we might as well be thorough.
for(var/obj/item/organ/I in internal_organs)
if(I.damage > 0)
I.damage = 0
to_chat(src, "<span class='notice'>You feel a soothing sensation within your [I.name]...</span>")
// Replace completely missing limbs.
for(var/limb_type in src.species.has_limbs)
var/obj/item/organ/external/E = src.organs_by_name[limb_type]
if(E && (E.is_stump() || (E.status & (ORGAN_DESTROYED|ORGAN_DEAD|ORGAN_MUTATED))))
E.removed()
qdel(E)
E = null
if(!E)
var/list/organ_data = src.species.has_limbs[limb_type]
var/limb_path = organ_data["path"]
var/obj/item/organ/O = new limb_path(src)
organ_data["descriptor"] = O.name
to_chat(src, "<span class='notice'>You feel a slithering sensation as your [O.name] reform.</span>")
src.update_body()

View File

@@ -1337,6 +1337,9 @@
if(istype(G, /obj/item/clothing/glasses/sunglasses/sechud))
var/obj/item/clothing/glasses/sunglasses/sechud/S = G
O = S.hud
if(istype(G, /obj/item/clothing/glasses/sunglasses/medhud))
var/obj/item/clothing/glasses/sunglasses/medhud/M = G
O = M.hud
if(istype(O))
O.process_hud(src)
if(!druggy && !seer) see_invisible = SEE_INVISIBLE_LIVING

View File

@@ -3,8 +3,8 @@
name_plural = "Vox"
icobase = 'icons/mob/human_races/r_vox.dmi'
deform = 'icons/mob/human_races/r_def_vox.dmi'
default_language = "Vox-pidgin"
language = "Galactic Common"
default_language = LANGUAGE_VOX
language = LANGUAGE_GALCOM
num_alternate_languages = 1
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/strong)
rarity_value = 4
@@ -17,6 +17,8 @@
// taste_sensitivity = TASTE_DULL
slowdown = -0.5
speech_sounds = list('sound/voice/shriek1.ogg')
speech_chance = 20
@@ -37,7 +39,7 @@
spawn_flags = SPECIES_IS_WHITELISTED
appearance_flags = HAS_EYE_COLOR | HAS_HAIR_COLOR
blood_color = "#2299FC"
blood_color = "#9066BD"
flesh_color = "#808D11"
reagent_tag = IS_VOX
@@ -75,11 +77,11 @@
/datum/species/vox/equip_survival_gear(var/mob/living/carbon/human/H)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(H), slot_wear_mask)
if(H.backbag == 1)
H.equip_to_slot_or_del(new /obj/item/weapon/tank/phoron/vox(H), slot_back)
H.equip_to_slot_or_del(new /obj/item/weapon/tank/vox(H), slot_back)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/vox(H), slot_r_hand)
H.internal = H.back
else
H.equip_to_slot_or_del(new /obj/item/weapon/tank/phoron/vox(H), slot_r_hand)
H.equip_to_slot_or_del(new /obj/item/weapon/tank/vox(H), slot_r_hand)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/vox(H.back), slot_in_backpack)
H.internal = H.r_hand
H.internal = locate(/obj/item/weapon/tank) in H.contents

View File

@@ -36,6 +36,8 @@
var/blood_volume = 560 // Initial blood volume.
var/hunger_factor = 0.05 // Multiplier for hunger.
var/taste_sensitivity = TASTE_NORMAL // How sensitive the species is to minute tastes.
var/min_age = 17
var/max_age = 70

View File

@@ -28,9 +28,9 @@ var/datum/species/shapeshifter/promethean/prometheans
breath_type = null
poison_type = null
gluttonous = 2
gluttonous = 1
virus_immune = 1
blood_volume = 600
blood_volume = 560
min_age = 1
max_age = 5
brute_mod = 0.5
@@ -73,7 +73,8 @@ var/datum/species/shapeshifter/promethean/prometheans
/mob/living/carbon/human/proc/shapeshifter_select_shape,
/mob/living/carbon/human/proc/shapeshifter_select_colour,
/mob/living/carbon/human/proc/shapeshifter_select_hair,
/mob/living/carbon/human/proc/shapeshifter_select_gender
/mob/living/carbon/human/proc/shapeshifter_select_gender,
/mob/living/carbon/human/proc/regenerate
)
valid_transform_species = list("Human", "Unathi", "Tajara", "Skrell", "Diona", "Teshari", "Monkey")
@@ -130,42 +131,14 @@ var/datum/species/shapeshifter/promethean/prometheans
var/obj/effect/decal/cleanable/C = locate() in T
if(C)
qdel(C)
//TODO: gain nutriment
// Regenerate limbs and heal damage if we have any. Copied from Bay xenos code.
// Theoretically the only internal organ a slime will have
// is the slime core. but we might as well be thorough.
for(var/obj/item/organ/I in H.internal_organs)
if(I.damage > 0)
I.damage = max(I.damage - heal_rate, 0)
if (prob(5))
H << "<span class='notice'>You feel a soothing sensation within your [I.name]...</span>"
return 1
// Replace completely missing limbs.
for(var/limb_type in has_limbs)
var/obj/item/organ/external/E = H.organs_by_name[limb_type]
if(E && (E.is_stump() || (E.status & (ORGAN_DESTROYED|ORGAN_DEAD|ORGAN_MUTATED))))
E.removed()
qdel(E)
E = null
if(!E)
var/list/organ_data = has_limbs[limb_type]
var/limb_path = organ_data["path"]
var/obj/item/organ/O = new limb_path(H)
organ_data["descriptor"] = O.name
H << "<span class='notice'>You feel a slithering sensation as your [O.name] reforms.</span>"
H.update_body()
return 1
H.nutrition += rand(15, 45)
// Heal remaining damage.
if (H.getBruteLoss() || H.getFireLoss() || H.getOxyLoss() || H.getToxLoss())
if(H.getBruteLoss() || H.getFireLoss() || H.getOxyLoss() || H.getToxLoss())
H.adjustBruteLoss(-heal_rate)
H.adjustFireLoss(-heal_rate)
H.adjustOxyLoss(-heal_rate)
H.adjustToxLoss(-heal_rate)
return 1
/datum/species/shapeshifter/promethean/get_blood_colour(var/mob/living/carbon/human/H)
return (H ? rgb(H.r_skin, H.g_skin, H.b_skin) : ..())

View File

@@ -246,7 +246,8 @@
)
inherent_verbs = list(
/mob/living/carbon/human/proc/diona_split_nymph
/mob/living/carbon/human/proc/diona_split_nymph,
/mob/living/carbon/human/proc/regenerate
)
warning_low_pressure = 50

View File

@@ -0,0 +1,60 @@
/mob/living/carbon/proc/ingest(var/datum/reagents/from, var/datum/reagents/target, var/amount = 1, var/multiplier = 1, var/copy = 0) //we kind of 'sneak' a proc in here for ingesting stuff so we can play with it.
if(last_taste_time + 50 < world.time)
var/datum/reagents/temp = new(amount) //temporary holder used to analyse what gets transfered.
from.trans_to_holder(temp, amount, multiplier, 1)
var/text_output = temp.generate_taste_message(src)
if(text_output != last_taste_text || last_taste_time + 100 < world.time) //We dont want to spam the same message over and over again at the person. Give it a bit of a buffer.
to_chat(src, "<span class='notice'>You can taste [text_output].</span>")//no taste means there are too many tastes and not enough flavor.
last_taste_time = world.time
last_taste_text = text_output
return from.trans_to_holder(target,amount,multiplier,copy) //complete transfer
/* what this does:
catalogue the 'taste strength' of each one
calculate text size per text.
*/
/datum/reagents/proc/generate_taste_message(mob/living/carbon/taster = null)
var/minimum_percent = 15
if(ishuman(taster))
var/mob/living/carbon/human/H = taster
minimum_percent = round(15/ (H.isSynthetic() ? TASTE_DULL : H.species.taste_sensitivity))
var/list/out = list()
var/list/tastes = list() //descriptor = strength
if(minimum_percent <= 100)
for(var/datum/reagent/R in reagent_list)
if(!R.taste_mult)
continue
if(R.id == "nutriment") //this is ugly but apparently only nutriment (not subtypes) has taste data TODO figure out why
var/list/taste_data = R.get_data()
for(var/taste in taste_data)
if(taste in tastes)
tastes[taste] += taste_data[taste]
else
tastes[taste] = taste_data[taste]
else
var/taste_desc = R.taste_description
var/taste_amount = get_reagent_amount(R.id) * R.taste_mult
if(R.taste_description in tastes)
tastes[taste_desc] += taste_amount
else
tastes[taste_desc] = taste_amount
//deal with percentages
var/total_taste = 0
for(var/taste_desc in tastes)
total_taste += tastes[taste_desc]
for(var/taste_desc in tastes)
var/percent = tastes[taste_desc]/total_taste * 100
if(percent < minimum_percent)
continue
var/intensity_desc = "a hint of"
if(percent > minimum_percent * 2 || percent == 100)
intensity_desc = "the flavor of"
else if(percent > minimum_percent * 3)
intensity_desc = "the strong flavor of"
out += "[intensity_desc] [taste_desc]"
return english_list(out, "something indescribable")

View File

@@ -223,4 +223,25 @@
icon_state = "impact_lightning"
light_range = 2
light_power = 0.5
light_color = "#00C6FF"
light_color = "#00C6FF"
//----------------------------
// Dark matter
//----------------------------
/obj/effect/projectile/darkmatter/tracer
icon_state = "darkb"
light_range = 2
light_power = 0.5
light_color = "#8837A3"
/obj/effect/projectile/darkmatter/muzzle
icon_state = "muzzle_darkb"
light_range = 2
light_power = 0.5
light_color = "#8837A3"
/obj/effect/projectile/darkmatter/impact
icon_state = "impact_darkb"
light_range = 2
light_power = 0.5
light_color = "#8837A3"

View File

@@ -1,46 +0,0 @@
// Alien pinning weapon.
/obj/item/weapon/gun/launcher/spikethrower
name = "spike thrower"
desc = "A vicious alien projectile weapon. Parts of it quiver gelatinously, as though the thing is insectile and alive."
var/last_regen = 0
var/spike_gen_time = 150
var/max_spikes = 3
var/spikes = 3
release_force = 30
icon = 'icons/obj/gun.dmi'
icon_state = "spikethrower3"
item_state = "spikethrower"
fire_sound_text = "a strange noise"
fire_sound = 'sound/weapons/bladeslice.ogg'
/obj/item/weapon/gun/launcher/spikethrower/New()
..()
processing_objects.Add(src)
last_regen = world.time
/obj/item/weapon/gun/launcher/spikethrower/Destroy()
processing_objects.Remove(src)
..()
/obj/item/weapon/gun/launcher/spikethrower/process()
if(spikes < max_spikes && world.time > last_regen + spike_gen_time)
spikes++
last_regen = world.time
update_icon()
/obj/item/weapon/gun/launcher/spikethrower/examine(mob/user)
..(user)
user << "It has [spikes] spike\s remaining."
/obj/item/weapon/gun/launcher/spikethrower/update_icon()
icon_state = "spikethrower[spikes]"
/obj/item/weapon/gun/launcher/spikethrower/update_release_force()
return
/obj/item/weapon/gun/launcher/spikethrower/consume_next_projectile()
if(spikes < 1) return null
spikes--
return new /obj/item/weapon/spike(src)

View File

@@ -149,4 +149,4 @@ obj/item/weapon/gun/energy/staff/focus
charge_cost = 200
user << "<span class='warning'>The [src.name] will now strike only a single person.</span>"
projectile_type = "/obj/item/projectile/forcebolt"
*/
*/

View File

@@ -0,0 +1,139 @@
/*
* Vox Spike Thrower
* Alien pinning weapon.
*/
/obj/item/weapon/gun/launcher/spikethrower
name = "spike thrower"
desc = "A vicious alien projectile weapon. Parts of it quiver gelatinously, as though the thing is insectile and alive."
var/last_regen = 0
var/spike_gen_time = 150
var/max_spikes = 3
var/spikes = 3
release_force = 30
icon = 'icons/obj/gun.dmi'
icon_state = "spikethrower3"
item_state = "spikethrower"
fire_sound_text = "a strange noise"
fire_sound = 'sound/weapons/bladeslice.ogg'
/obj/item/weapon/gun/launcher/spikethrower/New()
..()
processing_objects.Add(src)
last_regen = world.time
/obj/item/weapon/gun/launcher/spikethrower/Destroy()
processing_objects.Remove(src)
..()
/obj/item/weapon/gun/launcher/spikethrower/process()
if(spikes < max_spikes && world.time > last_regen + spike_gen_time)
spikes++
last_regen = world.time
update_icon()
/obj/item/weapon/gun/launcher/spikethrower/examine(mob/user)
..(user)
user << "It has [spikes] spike\s remaining."
/obj/item/weapon/gun/launcher/spikethrower/update_icon()
icon_state = "spikethrower[spikes]"
/obj/item/weapon/gun/launcher/spikethrower/update_release_force()
return
/obj/item/weapon/gun/launcher/spikethrower/consume_next_projectile()
if(spikes < 1) return null
spikes--
return new /obj/item/weapon/spike(src)
/*
* Vox Darkmatter Cannon
*/
/obj/item/weapon/gun/energy/darkmatter
name = "dark matter gun"
desc = "A vicious alien beam weapon. Parts of it quiver gelatinously, as though the thing is insectile and alive."
icon_state = "darkcannon"
item_state = "darkcannon"
fire_sound = 'sound/weapons/eLuger.ogg'
charge_cost = 600
projectile_type = /obj/item/projectile/beam/darkmatter
self_recharge = 1
accuracy = 2
firemodes = list(
list(mode_name="focused", burst=1, fire_delay=null, move_delay=null, burst_accuracy=list(2), dispersion=null, projectile_type=/obj/item/projectile/beam/darkmatter, charge_cost = 600),
list(mode_name="scatter burst", burst=8, fire_delay=null, move_delay=4, burst_accuracy=list(0, 0, 0, 0, 0, 0, 0, 0), dispersion=list(3, 3, 3, 3, 3, 3, 3, 3, 3), projectile_type=/obj/item/projectile/energy/darkmatter, charge_cost = 300),
)
/obj/item/projectile/beam/darkmatter
name = "dark matter bolt"
icon_state = "darkb"
damage = 60
armor_penetration = 35
damage_type = BRUTE
check_armour = "energy"
light_color = "#8837A3"
embed_chance = 0
muzzle_type = /obj/effect/projectile/darkmatter/muzzle
tracer_type = /obj/effect/projectile/darkmatter/tracer
impact_type = /obj/effect/projectile/darkmatter/impact
/obj/item/projectile/energy/darkmatter
name = "dark matter pellet"
icon_state = "dark_pellet"
damage = 20
armor_penetration = 35
damage_type = BRUTE
check_armour = "energy"
light_color = "#8837A3"
embed_chance = 0
/*
* Vox Darkmatter Cannon
*/
/obj/item/weapon/gun/energy/sonic
name = "soundcannon"
desc = "A vicious alien sound weapon. Parts of it quiver gelatinously, as though the thing is insectile and alive."
icon_state = "noise"
item_state = "noise"
fire_sound = 'sound/effects/basscannon.ogg'
self_recharge = 1
charge_cost = 600
projectile_type=/obj/item/projectile/sonic/strong
firemodes = list(
list(mode_name="normal", projectile_type=/obj/item/projectile/sonic/strong, charge_cost = 600),
list(mode_name="suppressive", projectile_type=/obj/item/projectile/sonic/weak, charge_cost = 300),
)
/obj/item/projectile/sonic
name = "sonic pulse"
icon_state = "sound"
damage = 15
armor_penetration = 30
damage_type = BRUTE
check_armour = "melee"
embed_chance = 0
vacuum_traversal = 0
// var/amplitude = 10 //Roughly how loud it is, changes the way damage will work, and such
/obj/item/projectile/sonic/weak
agony = 30
/obj/item/projectile/sonic/strong
damage = 45
//Already have thoughts on how to improve this, will take a day or two after initial testing. - Anewbe
/obj/item/projectile/sonic/strong/on_hit(var/atom/movable/target, var/blocked = 0)
if(ismob(target))
var/throwdir = get_dir(firer,target)
target.throw_at(get_edge_target_turf(target, throwdir), rand(1,6), 10)
return 1

View File

@@ -8,6 +8,7 @@
eyeblur = 4
var/frequency = 1
hitscan = 1
embed_chance = 0
invisibility = 101 //beam projectiles are invisible as they are rendered by the effect engine
light_range = 2
light_power = 0.5

View File

@@ -140,7 +140,7 @@
armor_penetration = 10
kill_count = 4
damage = 5
agony = 70
agony = 55
damage_type = BURN
vacuum_traversal = 0 //Projectile disappears in empty space
@@ -151,12 +151,12 @@
var/ear_safety = 0
ear_safety = M.get_ear_protection()
if(ear_safety == 1)
M.Weaken(2)
M.confused += 150
else if (ear_safety > 1)
M.Weaken(1)
M.confused += 30
else if (!ear_safety)
M.Stun(10)
M.Weaken(3)
M.Weaken(2)
M.ear_damage += rand(1, 10)
M.ear_deaf = max(M.ear_deaf,15)
if (M.ear_damage >= 15)

View File

@@ -156,4 +156,3 @@
nodamage = 1
damage_type = HALLOSS
muzzle_type = /obj/effect/projectile/bullet/muzzle

View File

@@ -383,7 +383,7 @@
return trans_to_holder(R, amount, multiplier, copy)
if(type == CHEM_INGEST)
var/datum/reagents/R = C.ingested
return trans_to_holder(R, amount, multiplier, copy)
return C.ingest(src, R, amount, multiplier, copy)
if(type == CHEM_TOUCH)
var/datum/reagents/R = C.touching
return trans_to_holder(R, amount, multiplier, copy)

View File

@@ -14,6 +14,8 @@
var/name = "Reagent"
var/id = "reagent"
var/description = "A non-descript chemical."
var/taste_description = "bitterness"
var/taste_mult = 1 //how this taste compares to others. Higher values means it is more noticable
var/datum/reagents/holder = null
var/reagent_state = SOLID
var/list/data = null

View File

@@ -2,6 +2,8 @@
data = new/list("donor" = null, "viruses" = null, "species" = "Human", "blood_DNA" = null, "blood_type" = null, "blood_colour" = "#A10808", "resistances" = null, "trace_chem" = null, "antibodies" = list())
name = "Blood"
id = "blood"
taste_description = "iron"
taste_mult = 1.3
reagent_state = LIQUID
metabolism = REM * 5
mrate_static = TRUE
@@ -74,6 +76,7 @@
/datum/reagent/antibodies
data = list("antibodies"=list())
name = "Antibodies"
taste_description = "slime"
id = "antibodies"
reagent_state = LIQUID
color = "#0050F0"
@@ -88,6 +91,7 @@
/datum/reagent/water
name = "Water"
id = "water"
taste_description = "water"
description = "A ubiquitous chemical substance that is composed of hydrogen and oxygen."
reagent_state = LIQUID
color = "#0064C877"
@@ -150,6 +154,7 @@
name = "Welding fuel"
id = "fuel"
description = "Required for welders. Flamable."
taste_description = "gross metal"
reagent_state = LIQUID
color = "#660000"

View File

@@ -2,13 +2,17 @@
name = "Aluminum"
id = "aluminum"
description = "A silvery white and ductile member of the boron group of chemical elements."
taste_description = "metal"
taste_mult = 1.1
reagent_state = SOLID
color = "#A8A8A8"
/datum/reagent/carbon
name = "Carbon"
id = "carbon"
description = "A chemical element, the builing block of life."
description = "A chemical element, the building block of life."
taste_description = "sour chalk"
taste_mult = 1.5
reagent_state = SOLID
color = "#1C1300"
ingest_met = REM * 5
@@ -37,6 +41,7 @@
name = "Chlorine"
id = "chlorine"
description = "A chemical element with a characteristic odour."
taste_description = "pool water"
reagent_state = GAS
color = "#808080"
@@ -50,12 +55,14 @@
name = "Copper"
id = "copper"
description = "A highly ductile metal."
taste_description = "pennies"
color = "#6E3B08"
/datum/reagent/ethanol
name = "Ethanol" //Parent class for all alcoholic reagents.
id = "ethanol"
description = "A well-known alcohol with a variety of applications."
taste_description = "pure alcohol"
reagent_state = LIQUID
color = "#404030"
var/nutriment_factor = 0
@@ -142,6 +149,7 @@
name = "Fluorine"
id = "fluorine"
description = "A highly-reactive chemical element."
taste_description = "acid"
reagent_state = GAS
color = "#808080"
@@ -155,6 +163,7 @@
name = "Hydrogen"
id = "hydrogen"
description = "A colorless, odorless, nonmetallic, tasteless, highly combustible diatomic gas."
taste_mult = 0 //no taste
reagent_state = GAS
color = "#808080"
@@ -162,6 +171,7 @@
name = "Iron"
id = "iron"
description = "Pure iron is a metal."
taste_description = "metal"
reagent_state = SOLID
color = "#353535"
@@ -173,6 +183,7 @@
name = "Lithium"
id = "lithium"
description = "A chemical element, used as antidepressant."
taste_description = "metal"
reagent_state = SOLID
color = "#808080"
@@ -187,6 +198,7 @@
name = "Mercury"
id = "mercury"
description = "A chemical element."
taste_mult = 0 //mercury apparently is tasteless. IDK
reagent_state = LIQUID
color = "#484848"
@@ -202,6 +214,7 @@
name = "Nitrogen"
id = "nitrogen"
description = "A colorless, odorless, tasteless gas."
taste_mult = 0 //no taste
reagent_state = GAS
color = "#808080"
@@ -209,6 +222,7 @@
name = "Oxygen"
id = "oxygen"
description = "A colorless, odorless gas."
taste_mult = 0
reagent_state = GAS
color = "#808080"
@@ -220,6 +234,7 @@
name = "Phosphorus"
id = "phosphorus"
description = "A chemical element, the backbone of biological energy carriers."
taste_description = "vinegar"
reagent_state = SOLID
color = "#832828"
@@ -227,6 +242,7 @@
name = "Potassium"
id = "potassium"
description = "A soft, low-melting solid that can easily be cut with a knife. Reacts violently with water."
taste_description = "sweetness" //potassium is bitter in higher doses but sweet in lower ones.
reagent_state = SOLID
color = "#A0A0A0"
@@ -234,6 +250,7 @@
name = "Radium"
id = "radium"
description = "Radium is an alkaline earth metal. It is extremely radioactive."
taste_mult = 0 //Apparently radium is tasteless
reagent_state = SOLID
color = "#C7C7C7"
@@ -266,6 +283,7 @@
name = "Sulphuric acid"
id = "sacid"
description = "A very corrosive mineral acid with the molecular formula H2SO4."
taste_description = "acid"
reagent_state = LIQUID
color = "#DB5008"
metabolism = REM * 2
@@ -352,6 +370,7 @@
name = "Silicon"
id = "silicon"
description = "A tetravalent metalloid, silicon is less reactive than its chemical analog carbon."
taste_mult = 0
reagent_state = SOLID
color = "#A8A8A8"
@@ -359,6 +378,7 @@
name = "Sodium"
id = "sodium"
description = "A chemical element, readily reacts with water."
taste_description = "salty metal"
reagent_state = SOLID
color = "#808080"
@@ -366,6 +386,8 @@
name = "Sugar"
id = "sugar"
description = "The organic compound commonly known as table sugar and sometimes called saccharose. This white, odorless, crystalline powder has a pleasing, sweet taste."
taste_description = "sugar"
taste_mult = 1.8
reagent_state = SOLID
color = "#FFFFFF"
@@ -398,6 +420,7 @@
name = "Sulfur"
id = "sulfur"
description = "A chemical element with a pungent smell."
taste_description = "old eggs"
reagent_state = SOLID
color = "#BF8C00"
@@ -405,5 +428,7 @@
name = "Tungsten"
id = "tungsten"
description = "A chemical element, and a strong oxidising agent."
taste_description = "metal"
taste_mult = 0 //no taste
reagent_state = SOLID
color = "#DCDCDC"

View File

@@ -4,6 +4,7 @@
name = "Inaprovaline"
id = "inaprovaline"
description = "Inaprovaline is a synaptic stimulant and cardiostimulant. Commonly used to stabilize patients."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#00BFFF"
overdose = REAGENTS_OVERDOSE * 2
@@ -20,6 +21,8 @@
name = "Bicaridine"
id = "bicaridine"
description = "Bicaridine is an analgesic medication and can be used to treat blunt trauma."
taste_description = "bitterness"
taste_mult = 3
reagent_state = LIQUID
color = "#BF0000"
overdose = REAGENTS_OVERDOSE
@@ -33,6 +36,7 @@
name = "Kelotane"
id = "kelotane"
description = "Kelotane is a drug used to treat burns."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#FFA800"
overdose = REAGENTS_OVERDOSE
@@ -46,6 +50,8 @@
name = "Dermaline"
id = "dermaline"
description = "Dermaline is the next step in burn medication. Works twice as good as kelotane and enables the body to restore even the direst heat-damaged tissue."
taste_description = "bitterness"
taste_mult = 1.5
reagent_state = LIQUID
color = "#FF8000"
overdose = REAGENTS_OVERDOSE * 0.5
@@ -59,6 +65,7 @@
name = "Dylovene"
id = "anti_toxin"
description = "Dylovene is a broad-spectrum antitoxin."
taste_description = "a roll of gauze"
reagent_state = LIQUID
color = "#00A000"
scannable = 1
@@ -96,6 +103,7 @@
name = "Dexalin"
id = "dexalin"
description = "Dexalin is used in the treatment of oxygen deprivation."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#0080FF"
overdose = REAGENTS_OVERDOSE
@@ -113,6 +121,7 @@
name = "Dexalin Plus"
id = "dexalinp"
description = "Dexalin Plus is used in the treatment of oxygen deprivation. It is highly effective."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#0040FF"
mrate_static = TRUE //Until it's not crazy strong, at least
@@ -131,6 +140,7 @@
name = "Tricordrazine"
id = "tricordrazine"
description = "Tricordrazine is a highly potent stimulant, originally derived from cordrazine. Can be used to treat a wide range of injuries."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#8040FF"
scannable = 1
@@ -145,6 +155,7 @@
name = "Cryoxadone"
id = "cryoxadone"
description = "A chemical mixture with almost magical healing powers. Its main limitation is that the targets body temperature must be under 170K for it to metabolise correctly."
taste_description = "overripe bananas"
reagent_state = LIQUID
color = "#8080FF"
metabolism = REM * 0.5
@@ -162,6 +173,7 @@
name = "Clonexadone"
id = "clonexadone"
description = "A liquid compound similar to that used in the cloning process. Can be used to 'finish' the cloning process when used in conjunction with a cryo tube."
taste_description = "rotten bananas"
reagent_state = LIQUID
color = "#80BFFF"
metabolism = REM * 0.5
@@ -181,6 +193,7 @@
name = "Paracetamol"
id = "paracetamol"
description = "Most probably know this as Tylenol, but this chemical is a mild, simple painkiller."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#C8A5DC"
overdose = 60
@@ -199,6 +212,7 @@
name = "Tramadol"
id = "tramadol"
description = "A simple, yet effective painkiller."
taste_description = "sourness"
reagent_state = LIQUID
color = "#CB68FC"
overdose = 30
@@ -217,6 +231,7 @@
name = "Oxycodone"
id = "oxycodone"
description = "An effective and very addictive painkiller."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#800080"
overdose = 20
@@ -239,6 +254,7 @@
name = "Synaptizine"
id = "synaptizine"
description = "Synaptizine is used to treat various diseases."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#99CCFF"
metabolism = REM * 0.05
@@ -261,6 +277,7 @@
name = "Alkysine"
id = "alkysine"
description = "Alkysine is a drug used to lessen the damage to neurological tissue after a catastrophic injury. Can heal brain tissue."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#FFFF66"
metabolism = REM * 0.25
@@ -277,6 +294,7 @@
name = "Imidazoline"
id = "imidazoline"
description = "Heals eye damage"
taste_description = "dull toxin"
reagent_state = LIQUID
color = "#C8A5DC"
overdose = REAGENTS_OVERDOSE
@@ -300,6 +318,7 @@
name = "Peridaxon"
id = "peridaxon"
description = "Used to encourage recovery of internal organs and nervous systems. Medicate cautiously."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#561EC3"
overdose = 10
@@ -371,6 +390,7 @@
name = "Ryetalyn"
id = "ryetalyn"
description = "Ryetalyn can cure all genetic abnomalities via a catalytic process."
taste_description = "acid"
reagent_state = SOLID
color = "#004000"
overdose = REAGENTS_OVERDOSE
@@ -391,6 +411,7 @@
name = "Ethylredoxrazine"
id = "ethylredoxrazine"
description = "A powerful oxidizer that reacts with ethanol."
taste_description = "bitterness"
reagent_state = SOLID
color = "#605048"
overdose = REAGENTS_OVERDOSE
@@ -411,6 +432,7 @@
name = "Hyronalin"
id = "hyronalin"
description = "Hyronalin is a medicinal drug used to counter the effect of radiation poisoning."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#408000"
metabolism = REM * 0.25
@@ -426,6 +448,7 @@
name = "Arithrazine"
id = "arithrazine"
description = "Arithrazine is an unstable medication used for the most extreme cases of radiation poisoning."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#008000"
metabolism = REM * 0.25
@@ -444,6 +467,7 @@
name = "Spaceacillin"
id = "spaceacillin"
description = "An all-purpose antiviral agent."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#C1C1C1"
metabolism = REM * 0.05
@@ -455,6 +479,7 @@
name = "Sterilizine"
id = "sterilizine"
description = "Sterilizes wounds in preparation for surgery and thoroughly removes blood."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#C8A5DC"
touch_met = 5
@@ -480,6 +505,7 @@
name = "Leporazine"
id = "leporazine"
description = "Leporazine can be use to stabilize an individuals body temperature."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#C8A5DC"
overdose = REAGENTS_OVERDOSE
@@ -523,6 +549,7 @@
name = "Methylphenidate"
id = "methylphenidate"
description = "Improves the ability to concentrate."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#BF80BF"
metabolism = 0.01
@@ -544,6 +571,7 @@
name = "Citalopram"
id = "citalopram"
description = "Stabilizes the mind a little."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#FF80FF"
metabolism = 0.01
@@ -565,6 +593,7 @@
name = "Paroxetine"
id = "paroxetine"
description = "Stabilizes the mind greatly, but has a chance of adverse effects."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#FF80BF"
metabolism = 0.01
@@ -584,4 +613,25 @@
M << "<span class='notice'>Your mind feels much more stable.</span>"
else
M << "<span class='warning'>Your mind breaks apart...</span>"
M.hallucination += 200
M.hallucination += 200
/datum/reagent/rezadone
name = "Rezadone"
id = "rezadone"
description = "A powder with almost magical properties, this substance can effectively treat genetic damage in humanoids, though excessive consumption has side effects."
taste_description = "bitterness"
reagent_state = SOLID
color = "#669900"
overdose = REAGENTS_OVERDOSE
scannable = 1
/datum/reagent/rezadone/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
M.adjustCloneLoss(-20 * removed)
M.adjustOxyLoss(-2 * removed)
M.heal_organ_damage(20 * removed, 20 * removed)
M.adjustToxLoss(-20 * removed)
if(dose > 3)
M.status_flags &= ~DISFIGURED
if(dose > 10)
M.make_dizzy(5)
M.make_jittery(5)

View File

@@ -4,6 +4,7 @@
name = "Crayon dust"
id = "crayon_dust"
description = "Intensely coloured powder obtained by grinding crayons."
taste_description = "powdered wax"
reagent_state = LIQUID
color = "#888888"
overdose = 5
@@ -52,6 +53,7 @@
name = "Paint"
id = "paint"
description = "This paint will stick to almost any object."
taste_description = "chalk"
reagent_state = LIQUID
color = "#808080"
overdose = REAGENTS_OVERDOSE * 0.5
@@ -108,6 +110,7 @@
name = "Adminordrazine"
id = "adminordrazine"
description = "It's magic. We don't have to explain it."
taste_description = "bwoink"
reagent_state = LIQUID
color = "#C8A5DC"
affects_dead = 1 //This can even heal dead people.
@@ -146,6 +149,7 @@
name = "Gold"
id = "gold"
description = "Gold is a dense, soft, shiny metal and the most malleable and ductile metal known."
taste_description = "metal"
reagent_state = SOLID
color = "#F7C430"
@@ -153,6 +157,7 @@
name = "Silver"
id = "silver"
description = "A soft, white, lustrous transition metal, it has the highest electrical conductivity of any element and the highest thermal conductivity of any metal."
taste_description = "metal"
reagent_state = SOLID
color = "#D0D0D0"
@@ -160,6 +165,7 @@
name ="Uranium"
id = "uranium"
description = "A silvery-white metallic chemical element in the actinide series, weakly radioactive."
taste_description = "metal"
reagent_state = SOLID
color = "#B8B8C0"
@@ -181,6 +187,7 @@
name = "Adrenaline"
id = "adrenaline"
description = "Adrenaline is a hormone used as a drug to treat cardiac arrest and other cardiac dysrhythmias resulting in diminished or absent cardiac output."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#C8A5DC"
mrate_static = TRUE
@@ -196,6 +203,7 @@
name = "Holy Water"
id = "holywater"
description = "An ashen-obsidian-water mix, this solution will alter certain sections of the brain's rationality."
taste_description = "water"
color = "#E0E8EF"
mrate_static = TRUE
@@ -217,6 +225,8 @@
name = "Ammonia"
id = "ammonia"
description = "A caustic substance commonly used in fertilizer or household cleaners."
taste_description = "mordant"
taste_mult = 2
reagent_state = GAS
color = "#404030"
@@ -224,6 +234,7 @@
name = "Diethylamine"
id = "diethylamine"
description = "A secondary amine, mildly corrosive."
taste_description = "iron"
reagent_state = LIQUID
color = "#604030"
@@ -231,6 +242,7 @@
name = "Fluorosurfactant"
id = "fluorosurfactant"
description = "A perfluoronated sulfonic acid that forms a foam when mixed with water."
taste_description = "metal"
reagent_state = LIQUID
color = "#9E6B38"
@@ -238,6 +250,7 @@
name = "Foaming agent"
id = "foaming_agent"
description = "A agent that yields metallic foam when mixed with light metal and a strong acid."
taste_description = "metal"
reagent_state = SOLID
color = "#664B63"
@@ -245,6 +258,7 @@
name = "Thermite"
id = "thermite"
description = "Thermite produces an aluminothermic reaction known as a thermite reaction. Can be used to melt walls."
taste_description = "sweet tasting metal"
reagent_state = SOLID
color = "#673910"
touch_met = 50
@@ -269,6 +283,7 @@
name = "Space cleaner"
id = "cleaner"
description = "A compound used to clean things. Now with 50% more sodium hypochlorite!"
taste_description = "sourness"
reagent_state = LIQUID
color = "#A5F0EE"
touch_met = 50
@@ -317,6 +332,7 @@
name = "Space Lube"
id = "lube"
description = "Lubricant is a substance introduced between two moving surfaces to reduce the friction and wear between them. giggity."
taste_description = "slime"
reagent_state = LIQUID
color = "#009CA8"
@@ -330,6 +346,7 @@
name = "Silicate"
id = "silicate"
description = "A compound that can be used to reinforce glass."
taste_description = "plastic"
reagent_state = LIQUID
color = "#C7FFFF"
@@ -344,6 +361,7 @@
name = "Glycerol"
id = "glycerol"
description = "Glycerol is a simple polyol compound. Glycerol is sweet-tasting and of low toxicity."
taste_description = "sweetness"
reagent_state = LIQUID
color = "#808080"
@@ -351,6 +369,7 @@
name = "Nitroglycerin"
id = "nitroglycerin"
description = "Nitroglycerin is a heavy, colorless, oily, explosive liquid obtained by nitrating glycerol."
taste_description = "oil"
reagent_state = LIQUID
color = "#808080"
@@ -358,6 +377,8 @@
name = "Coolant"
id = "coolant"
description = "Industrial cooling substance."
taste_description = "sourness"
taste_mult = 1.1
reagent_state = LIQUID
color = "#C8A5DC"
@@ -365,12 +386,14 @@
name = "Ultra Glue"
id = "glue"
description = "An extremely powerful bonding agent."
taste_description = "a special education class"
color = "#FFFFCC"
/datum/reagent/woodpulp
name = "Wood Pulp"
id = "woodpulp"
description = "A mass of wood fibers."
taste_description = "wood"
reagent_state = LIQUID
color = "#B97A57"
@@ -378,6 +401,7 @@
name = "Luminol"
id = "luminol"
description = "A compound that interacts with blood on the molecular level."
taste_description = "metal"
reagent_state = LIQUID
color = "#F2F3F4"

View File

@@ -1,13 +1,14 @@
/* Toxins, poisons, venoms */
/datum/reagent/toxin
name = "Toxin"
name = "toxin"
id = "toxin"
description = "A toxic chemical."
taste_description = "bitterness"
taste_mult = 1.2
reagent_state = LIQUID
color = "#CF3600"
metabolism = REM * 0.25 // 0.05 by default. Hopefully enough to get some help, or die horribly, whatever floats your boat
mrate_static = TRUE
var/strength = 4 // How much damage it deals per unit
/datum/reagent/toxin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
@@ -19,6 +20,7 @@
name = "Plasticide"
id = "plasticide"
description = "Liquid plastic, do not eat."
taste_description = "plastic"
reagent_state = LIQUID
color = "#CF3600"
strength = 5
@@ -27,6 +29,7 @@
name = "Amatoxin"
id = "amatoxin"
description = "A powerful poison derived from certain species of mushroom."
taste_description = "mushroom"
reagent_state = LIQUID
color = "#792300"
strength = 10
@@ -35,6 +38,7 @@
name = "Carpotoxin"
id = "carpotoxin"
description = "A deadly neurotoxin produced by the dreaded space carp."
taste_description = "fish"
reagent_state = LIQUID
color = "#003333"
strength = 10
@@ -50,6 +54,7 @@
name = "Phoron"
id = "phoron"
description = "Phoron in its liquid form."
taste_mult = 1.5
reagent_state = LIQUID
color = "#9D14DB"
strength = 30
@@ -84,6 +89,8 @@
name = "Cyanide"
id = "cyanide"
description = "A highly toxic chemical."
taste_description = "almond"
taste_mult = 0.6
reagent_state = LIQUID
color = "#CF3600"
strength = 20
@@ -98,6 +105,7 @@
name = "Hyperzine"
id = "hyperzine"
description = "Hyperzine is a highly effective, long lasting, muscle stimulant."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#FF3300"
overdose = REAGENTS_OVERDOSE * 0.5
@@ -115,6 +123,8 @@
name = "Stimm"
id = "stimm"
description = "A homemade stimulant with some serious side-effects."
taste_description = "sweetness"
taste_mult = 1.8
color = "#d0583a"
metabolism = REM * 3
overdose = 10
@@ -135,6 +145,7 @@
name = "Potassium Chloride"
id = "potassium_chloride"
description = "A delicious salt that stops the heart when injected into cardiac muscle."
taste_description = "salt"
reagent_state = SOLID
color = "#FFFFFF"
strength = 0
@@ -154,6 +165,7 @@
name = "Potassium Chlorophoride"
id = "potassium_chlorophoride"
description = "A specific chemical based on Potassium Chloride to stop the heart for surgery. Not safe to eat!"
taste_description = "salt"
reagent_state = SOLID
color = "#FFFFFF"
strength = 10
@@ -173,6 +185,7 @@
name = "Zombie Powder"
id = "zombiepowder"
description = "A strong neurotoxin that puts the subject into a death-like state."
taste_description = "numbness"
reagent_state = SOLID
color = "#669900"
metabolism = REM
@@ -198,6 +211,8 @@
name = "fertilizer"
id = "fertilizer"
description = "A chemical mix good for growing plants with."
taste_description = "plant food"
taste_mult = 0.5
reagent_state = LIQUID
strength = 0.5 // It's not THAT poisonous.
color = "#664330"
@@ -218,6 +233,7 @@
name = "Plant-B-Gone"
id = "plantbgone"
description = "A harmful toxic mixture to kill plantlife. Do not ingest!"
taste_mult = 1
reagent_state = LIQUID
color = "#49002E"
strength = 4
@@ -246,6 +262,7 @@
name = "Polytrinic acid"
id = "pacid"
description = "Polytrinic acid is a an extremely corrosive chemical substance."
taste_description = "acid"
reagent_state = LIQUID
color = "#8E18A9"
power = 10
@@ -255,6 +272,7 @@
name = "Lexorin"
id = "lexorin"
description = "Lexorin temporarily stops respiration. Causes tissue damage."
taste_description = "acid"
reagent_state = LIQUID
color = "#C8A5DC"
overdose = REAGENTS_OVERDOSE
@@ -275,6 +293,8 @@
name = "Unstable mutagen"
id = "mutagen"
description = "Might cause unpredictable mutations. Keep away from children."
taste_description = "slime"
taste_mult = 0.9
reagent_state = LIQUID
color = "#13BC5E"
@@ -310,6 +330,8 @@
name = "Slime Jelly"
id = "slimejelly"
description = "A gooey semi-liquid produced from one of the deadliest lifeforms in existence. SO REAL."
taste_description = "slime"
taste_mult = 1.3
reagent_state = LIQUID
color = "#801E28"
@@ -326,6 +348,7 @@
name = "Soporific"
id = "stoxin"
description = "An effective hypnotic used to treat insomnia."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#009CA8"
metabolism = REM * 0.5
@@ -360,6 +383,7 @@
name = "Chloral Hydrate"
id = "chloralhydrate"
description = "A powerful sedative."
taste_description = "bitterness"
reagent_state = SOLID
color = "#000067"
metabolism = REM * 0.5
@@ -393,6 +417,7 @@
name = "Beer"
id = "beer2"
description = "An alcoholic beverage made from malted grains, hops, yeast, and water. The fermentation appears to be incomplete." //If the players manage to analyze this, they deserve to know something is wrong.
taste_description = "beer"
reagent_state = LIQUID
color = "#FFD300"
@@ -404,6 +429,8 @@
name = "Space drugs"
id = "space_drugs"
description = "An illegal chemical compound used as drug."
taste_description = "bitterness"
taste_mult = 0.4
reagent_state = LIQUID
color = "#60A584"
metabolism = REM * 0.5
@@ -427,6 +454,7 @@
name = "Serotrotium"
id = "serotrotium"
description = "A chemical compound that promotes concentrated production of the serotonin neurotransmitter in humans."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#202040"
metabolism = REM * 0.25
@@ -443,6 +471,7 @@
name = "Cryptobiolin"
id = "cryptobiolin"
description = "Cryptobiolin causes confusion and dizzyness."
taste_description = "sourness"
reagent_state = LIQUID
color = "#000055"
metabolism = REM * 0.5
@@ -461,6 +490,7 @@
name = "Impedrezene"
id = "impedrezene"
description = "Impedrezene is a narcotic that impedes one's ability by slowing down the higher brain cell functions."
taste_description = "numbness"
reagent_state = LIQUID
color = "#C8A5DC"
overdose = REAGENTS_OVERDOSE
@@ -480,6 +510,7 @@
name = "Mindbreaker Toxin"
id = "mindbreaker"
description = "A powerful hallucinogen, it can cause fatal effects in users."
taste_description = "sourness"
reagent_state = LIQUID
color = "#B31008"
metabolism = REM * 0.25
@@ -498,6 +529,7 @@
name = "Psilocybin"
id = "psilocybin"
description = "A strong psycotropic derived from certain species of mushroom."
taste_description = "mushroom"
color = "#E700E7"
overdose = REAGENTS_OVERDOSE
metabolism = REM * 0.5
@@ -538,6 +570,7 @@
name = "Nicotine"
id = "nicotine"
description = "A highly addictive stimulant extracted from the tobacco plant."
taste_description = "bitterness"
reagent_state = LIQUID
color = "#181818"
@@ -547,6 +580,7 @@
name = "Mutation Toxin"
id = "mutationtoxin"
description = "A corruptive toxin produced by slimes."
taste_description = "sludge"
reagent_state = LIQUID
color = "#13BC5E"
@@ -573,6 +607,7 @@
name = "Docility Toxin"
id = "docilitytoxin"
description = "A corruptive toxin produced by slimes."
taste_description = "sludge"
reagent_state = LIQUID
color = "#FF69B4"

View File

@@ -57,7 +57,7 @@
safe_thing = victim.glasses
if(safe_thing)
trans = reagents.trans_to_obj(safe_thing, amount_per_transfer_from_this)
trans = reagents.splash(safe_thing, amount_per_transfer_from_this, max_spill=30)
user.visible_message("<span class='warning'>[user] tries to squirt something into [target]'s eyes, but fails!</span>", "<span class='notice'>You transfer [trans] units of the solution.</span>")
return
@@ -67,14 +67,15 @@
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Used the [name] to squirt [M.name] ([M.key]). Reagents: [contained]</font>")
msg_admin_attack("[user.name] ([user.ckey]) squirted [M.name] ([M.key]) with [name]. Reagents: [contained] (INTENT: [uppertext(user.a_intent)]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
trans = reagents.trans_to_mob(target, reagents.total_volume, CHEM_INGEST)
trans += reagents.splash(target, reagents.total_volume/2, max_spill=30)
trans += reagents.trans_to_mob(target, reagents.total_volume/2, CHEM_BLOOD) //I guess it gets into the bloodstream through the eyes or something
user.visible_message("<span class='warning'>[user] squirts something into [target]'s eyes!</span>", "<span class='notice'>You transfer [trans] units of the solution.</span>")
return
else
trans = reagents.trans_to(target, amount_per_transfer_from_this) //sprinkling reagents on generic non-mobs
trans = reagents.splash(target, amount_per_transfer_from_this, max_spill=30) //sprinkling reagents on generic non-mobs
user << "<span class='notice'>You transfer [trans] units of the solution.</span>"
else // Taking from something

File diff suppressed because it is too large Load Diff

View File

@@ -23,6 +23,7 @@
var/image/filling //holds a reference to the current filling overlay
var/visible_name = "a syringe"
var/time = 30
var/drawing = 0
/obj/item/weapon/reagent_containers/syringe/on_reagent_change()
update_icon()
@@ -98,7 +99,12 @@
user << "<span class='warning'>You are unable to locate any blood.</span>"
return
if(drawing)
user << "<span class='warning'>You are already drawing blood from [T.name].</span>"
return
var/datum/reagent/B
drawing = 1
if(istype(T, /mob/living/carbon/human))
var/mob/living/carbon/human/H = T
if(H.species && !H.should_have_organ(O_HEART))
@@ -106,12 +112,16 @@
else
if(ismob(H) && H != user)
if(!do_mob(user, target, time))
drawing = 0
return
B = T.take_blood(src, amount)
drawing = 0
else
if(!do_mob(user, target, time))
drawing = 0
return
B = T.take_blood(src,amount)
drawing = 0
if (B)
reagents.reagent_list += B
@@ -200,7 +210,10 @@
admin_inject_log(user, target, src, contained, trans)
else
trans = reagents.trans_to(target, amount_per_transfer_from_this)
user << "<span class='notice'>You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units.</span>"
if(trans)
user << "<span class='notice'>You inject [trans] units of the solution. The syringe now contains [src.reagents.total_volume] units.</span>"
else
user << "<span class='notice'>The syringe is empty.</span>"
if (reagents.total_volume <= 0 && mode == SYRINGE_INJECT)
mode = SYRINGE_DRAW
update_icon()

View File

@@ -65,6 +65,32 @@
/datum/unit_test/integrated_circuits/not_equals_1
name = "Logic Circuits: Not Equals - String True"
circuit_type = /obj/item/integrated_circuit/logic/binary/not_equals
inputs_to_give = list("Test", "Nope")
expected_outputs = list(TRUE)
/datum/unit_test/integrated_circuits/not_equals_2
name = "Logic Circuits: Not Equals - String False"
circuit_type = /obj/item/integrated_circuit/logic/binary/not_equals
inputs_to_give = list("Test", "Test")
expected_outputs = list(FALSE)
/datum/unit_test/integrated_circuits/not_equals_3
name = "Logic Circuits: Not Equals - Number True"
circuit_type = /obj/item/integrated_circuit/logic/binary/not_equals
inputs_to_give = list(150, 20)
expected_outputs = list(TRUE)
/datum/unit_test/integrated_circuits/not_equals_4
name = "Logic Circuits: Not Equals - Number False"
circuit_type = /obj/item/integrated_circuit/logic/binary/not_equals
inputs_to_give = list(100, 100)
expected_outputs = list(FALSE)
/datum/unit_test/integrated_circuits/and_1
name = "Logic Circuits: And - True"
circuit_type = /obj/item/integrated_circuit/logic/binary/and