Merge branch 'master' of https://github.com/PolarisSS13/Polaris into dice_thing

This commit is contained in:
Anewbe
2017-05-02 11:13:53 -05:00
310 changed files with 3332 additions and 1457 deletions
+5 -1
View File
@@ -249,7 +249,11 @@
"Anything Legal Considered",
"New Toy",
"Me, I'm Always Counting",
"Just Five More Minutes"
"Just Five More Minutes",
"Are You Feeling It",
"Great White Snark",
"No Shirt No Shoes",
"Callsign"
)
+1
View File
@@ -408,6 +408,7 @@
projectile_type = /obj/item/projectile/chameleon
charge_meter = 0
charge_cost = 48 //uses next to no power, since it's just holograms
battery_lock = 1
var/obj/item/projectile/copy_projectile
var/global/list/gun_choices
+3 -1
View File
@@ -347,7 +347,9 @@
body_parts_covered = FACE|EYES
sprite_sheets = list(
"Teshari" = 'icons/mob/species/seromi/masks.dmi',
"Vox" = 'icons/mob/species/vox/masks.dmi'
"Vox" = 'icons/mob/species/vox/masks.dmi',
"Tajara" = 'icons/mob/species/tajaran/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi'
)
var/voicechange = 0
+4 -3
View File
@@ -132,7 +132,7 @@ BLIND // can't see anything
eye = !eye
if(eye)
icon_state = "[icon_state]_r"
icon_state = "[icon_state]_1"
else
icon_state = initial(icon_state)
update_clothing_icon()
@@ -395,14 +395,15 @@ BLIND // can't see anything
toggleable = 1
action_button_name = "Toggle Goggles"
vision_flags = SEE_MOBS
see_invisible = INVISIBILITY_LEVEL_TWO
see_invisible = SEE_INVISIBLE_NOLIGHTING
emp_act(severity)
if(istype(src.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/M = src.loc
M << "\red The Optical Thermal Scanner overloads and blinds you!"
if(M.glasses == src)
M.eye_blind = 3
M.Blind(3)
M.eye_blurry = 5
// Don't cure being nearsighted
if(!(M.disabilities & NEARSIGHTED))
-8
View File
@@ -6,10 +6,6 @@
flags_inv = HIDEFACE|BLOCKHAIR
body_parts_covered = FACE|HEAD
w_class = ITEMSIZE_SMALL
sprite_sheets = list(
"Tajara" = 'icons/mob/species/tajaran/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
)
/obj/item/clothing/mask/balaclava/tactical
name = "green balaclava"
@@ -18,10 +14,6 @@
item_state_slots = list(slot_r_hand_str = "bandgreen", slot_l_hand_str = "bandgreen")
flags_inv = HIDEFACE|BLOCKHAIR
w_class = ITEMSIZE_SMALL
sprite_sheets = list(
"Tajara" = 'icons/mob/species/tajaran/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
)
/obj/item/clothing/mask/luchador
name = "Luchador Mask"
+1 -1
View File
@@ -34,7 +34,7 @@
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)
phoronproof = 1
slowdown = 2
slowdown = 0.5
armor = list(melee = 60, bullet = 50, laser = 40,energy = 15, bomb = 30, bio = 100, rad = 50)
siemens_coefficient = 0.2
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
+3
View File
@@ -80,6 +80,9 @@
if(istype(damage_source, /obj/item/projectile/energy) || istype(damage_source, /obj/item/projectile/beam))
var/obj/item/projectile/P = damage_source
if(P.reflected) // Can't reflect twice
return ..()
var/reflectchance = 40 - round(damage/3)
if(!(def_zone in list(BP_TORSO, BP_GROIN)))
reflectchance /= 2
@@ -76,10 +76,12 @@
/obj/item/clothing/accessory/holster/on_attached(obj/item/clothing/under/S, mob/user as mob)
..()
has_suit.verbs += /obj/item/clothing/accessory/holster/verb/holster_verb
if(has_suit)
has_suit.verbs += /obj/item/clothing/accessory/holster/verb/holster_verb
/obj/item/clothing/accessory/holster/on_removed(mob/user as mob)
has_suit.verbs -= /obj/item/clothing/accessory/holster/verb/holster_verb
if(has_suit)
has_suit.verbs -= /obj/item/clothing/accessory/holster/verb/holster_verb
..()
//For the holster hotkey
@@ -105,7 +107,7 @@
if(!H.holstered)
var/obj/item/W = usr.get_active_hand()
if(!istype(W, /obj/item))
usr << "<span class='warning'>You need your gun equiped to holster it.</span>"
usr << "<span class='warning'>You need your gun equipped to holster it.</span>"
return
H.holster(W, usr)
else
+8 -6
View File
@@ -41,9 +41,11 @@
i++
/datum/event/carp_migration/end()
for(var/mob/living/simple_animal/hostile/carp/C in spawned_carp)
if(!C.stat)
var/turf/T = get_turf(C)
if(istype(T, /turf/space))
if(!prob(25))
qdel(C)
spawn(0)
for(var/mob/living/simple_animal/hostile/C in spawned_carp)
if(!C.stat)
var/turf/T = get_turf(C)
if(istype(T, /turf/space))
if(prob(75))
qdel(C)
sleep(1)
+1 -1
View File
@@ -72,7 +72,7 @@
finish(mob/living/carbon/human/H)
if(!H.reagents.has_reagent("anti_toxin"))
H.confused += 100
H.Confuse(100)
proc/trigger_side_effect(mob/living/carbon/human/H)
spawn
+73 -27
View File
@@ -18,23 +18,57 @@
var/mob/last_to_emag = null
var/last_change = 0
var/last_gravity_change = 0
var/list/supported_programs = list( \
"Empty Court" = "emptycourt", \
"Basketball Court" = "basketball", \
"Thunderdome Court" = "thunderdomecourt", \
"Boxing Ring"="boxingcourt", \
"Beach" = "beach", \
"Desert" = "desert", \
"Space" = "space", \
"Picnic Area" = "picnicarea", \
"Snow Field" = "snowfield", \
"Theatre" = "theatre", \
"Meeting Hall" = "meetinghall", \
"Courtroom" = "courtroom", \
"Turn Off" = "turnoff" \
var/area/projection_area = /area/holodeck/alphadeck
var/current_program
var/powerdown_program = "Turn Off"
var/default_program = "Empty Court"
var/list/supported_programs = list(
"Empty Court" = new/datum/holodeck_program(/area/holodeck/source_emptycourt, list('sound/music/THUNDERDOME.ogg')),
"Boxing Ring" = new/datum/holodeck_program(/area/holodeck/source_boxingcourt, list('sound/music/THUNDERDOME.ogg')),
"Basketball" = new/datum/holodeck_program(/area/holodeck/source_basketball, list('sound/music/THUNDERDOME.ogg')),
"Thunderdome" = new/datum/holodeck_program(/area/holodeck/source_thunderdomecourt, list('sound/music/THUNDERDOME.ogg')),
"Beach" = new/datum/holodeck_program(/area/holodeck/source_beach),
"Desert" = new/datum/holodeck_program(/area/holodeck/source_desert,
list(
'sound/effects/wind/wind_2_1.ogg',
'sound/effects/wind/wind_2_2.ogg',
'sound/effects/wind/wind_3_1.ogg',
'sound/effects/wind/wind_4_1.ogg',
'sound/effects/wind/wind_4_2.ogg',
'sound/effects/wind/wind_5_1.ogg'
)
),
"Snowfield" = new/datum/holodeck_program(/area/holodeck/source_snowfield,
list(
'sound/effects/wind/wind_2_1.ogg',
'sound/effects/wind/wind_2_2.ogg',
'sound/effects/wind/wind_3_1.ogg',
'sound/effects/wind/wind_4_1.ogg',
'sound/effects/wind/wind_4_2.ogg',
'sound/effects/wind/wind_5_1.ogg'
)
),
"Space" = new/datum/holodeck_program(/area/holodeck/source_space,
list(
'sound/ambience/ambispace.ogg',
'sound/music/main.ogg',
'sound/music/space.ogg',
'sound/music/traitor.ogg',
)
),
"Picnic Area" = new/datum/holodeck_program(/area/holodeck/source_picnicarea, list('sound/music/title2.ogg')),
"Theatre" = new/datum/holodeck_program(/area/holodeck/source_theatre),
"Meetinghall" = new/datum/holodeck_program(/area/holodeck/source_meetinghall),
"Courtroom" = new/datum/holodeck_program(/area/holodeck/source_courtroom, list('sound/music/traitor.ogg')),
"Turn Off" = new/datum/holodeck_program(/area/holodeck/source_plating, list())
)
var/list/restricted_programs = list(
"Burnoff Test Simulation" = new/datum/holodeck_program(/area/holodeck/source_burntest, list()),
"Wildlife Simulation" = new/datum/holodeck_program(/area/holodeck/source_wildlife, list())
)
var/list/restricted_programs = list("Atmospheric Burn Simulation" = "burntest", "Wildlife Simulation" = "wildlifecarp")
var/current_program = "turnoff"
/obj/machinery/computer/HolodeckControl/attack_ai(var/mob/user as mob)
return src.attack_hand(user)
@@ -59,10 +93,10 @@
var/restricted_program_list[0]
for(var/P in supported_programs)
program_list[++program_list.len] = list("name" = P, "program" = supported_programs[P])
program_list[++program_list.len] = P
for(var/P in restricted_programs)
restricted_program_list[++restricted_program_list.len] = list("name" = P, "program" = restricted_programs[P])
restricted_program_list[++restricted_program_list.len] = P
data["supportedPrograms"] = program_list
data["restrictedPrograms"] = restricted_program_list
@@ -93,9 +127,9 @@
if(href_list["program"])
var/prog = href_list["program"]
if(prog in holodeck_programs)
loadProgram(holodeck_programs[prog])
current_program = href_list["program"]
if(prog in (supported_programs + restricted_programs))
loadProgram(prog)
current_program = prog
else if(href_list["AIoverride"])
if(!issilicon(usr))
@@ -150,7 +184,10 @@
/obj/machinery/computer/HolodeckControl/New()
..()
linkedholodeck = locate(/area/holodeck/alphadeck)
current_program = powerdown_program
linkedholodeck = locate(projection_area)
if(!linkedholodeck)
world << "<span class='danger'>Holodeck computer at [x],[y],[z] failed to locate projection area.</span>"
//This could all be done better, but it works for now.
/obj/machinery/computer/HolodeckControl/Destroy()
@@ -185,7 +222,7 @@
if(!checkInteg(linkedholodeck))
damaged = 1
loadProgram(holodeck_programs["turnoff"], 0)
loadProgram(powerdown_program, 0)
active = 0
use_power = 1
for(var/mob/M in range(10,src))
@@ -227,9 +264,9 @@
//Why is it called toggle if it doesn't toggle?
/obj/machinery/computer/HolodeckControl/proc/togglePower(var/toggleOn = 0)
if(toggleOn)
loadProgram(holodeck_programs["emptycourt"], 0)
loadProgram(default_program, 0)
else
loadProgram(holodeck_programs["turnoff"], 0)
loadProgram(powerdown_program, 0)
if(!linkedholodeck.has_gravity)
linkedholodeck.gravitychange(1,linkedholodeck)
@@ -238,9 +275,18 @@
use_power = 1
/obj/machinery/computer/HolodeckControl/proc/loadProgram(var/datum/holodeck_program/HP, var/check_delay = 1)
/obj/machinery/computer/HolodeckControl/proc/loadProgram(var/prog, var/check_delay = 1)
if(!prog)
return
var/datum/holodeck_program/HP
if(prog in supported_programs)
HP = supported_programs[prog]
else if(prog in restricted_programs)
HP = restricted_programs[prog]
if(!HP)
return
var/area/A = locate(HP.target)
if(!A)
return
@@ -324,7 +370,7 @@
/obj/machinery/computer/HolodeckControl/proc/emergencyShutdown()
//Turn it back to the regular non-holographic room
loadProgram(holodeck_programs["turnoff"], 0)
loadProgram(powerdown_program, 0)
if(!linkedholodeck.has_gravity)
linkedholodeck.gravitychange(1,linkedholodeck)
-43
View File
@@ -1,46 +1,3 @@
var/global/list/holodeck_programs = list(
"emptycourt" = new/datum/holodeck_program(/area/holodeck/source_emptycourt, list('sound/music/THUNDERDOME.ogg')),
"boxingcourt" = new/datum/holodeck_program(/area/holodeck/source_boxingcourt, list('sound/music/THUNDERDOME.ogg')),
"basketball" = new/datum/holodeck_program(/area/holodeck/source_basketball, list('sound/music/THUNDERDOME.ogg')),
"thunderdomecourt" = new/datum/holodeck_program(/area/holodeck/source_thunderdomecourt, list('sound/music/THUNDERDOME.ogg')),
"beach" = new/datum/holodeck_program(/area/holodeck/source_beach),
"desert" = new/datum/holodeck_program(/area/holodeck/source_desert,
list(
'sound/effects/wind/wind_2_1.ogg',
'sound/effects/wind/wind_2_2.ogg',
'sound/effects/wind/wind_3_1.ogg',
'sound/effects/wind/wind_4_1.ogg',
'sound/effects/wind/wind_4_2.ogg',
'sound/effects/wind/wind_5_1.ogg'
)
),
"snowfield" = new/datum/holodeck_program(/area/holodeck/source_snowfield,
list(
'sound/effects/wind/wind_2_1.ogg',
'sound/effects/wind/wind_2_2.ogg',
'sound/effects/wind/wind_3_1.ogg',
'sound/effects/wind/wind_4_1.ogg',
'sound/effects/wind/wind_4_2.ogg',
'sound/effects/wind/wind_5_1.ogg'
)
),
"space" = new/datum/holodeck_program(/area/holodeck/source_space,
list(
'sound/ambience/ambispace.ogg',
'sound/music/main.ogg',
'sound/music/space.ogg',
'sound/music/traitor.ogg',
)
),
"picnicarea" = new/datum/holodeck_program(/area/holodeck/source_picnicarea, list('sound/music/title2.ogg')),
"theatre" = new/datum/holodeck_program(/area/holodeck/source_theatre),
"meetinghall" = new/datum/holodeck_program(/area/holodeck/source_meetinghall),
"courtroom" = new/datum/holodeck_program(/area/holodeck/source_courtroom, list('sound/music/traitor.ogg')),
"burntest" = new/datum/holodeck_program(/area/holodeck/source_burntest, list()),
"wildlifecarp" = new/datum/holodeck_program(/area/holodeck/source_wildlife, list()),
"turnoff" = new/datum/holodeck_program(/area/holodeck/source_plating, list())
)
/datum/holodeck_program
var/target
var/list/ambience = null
@@ -8,7 +8,7 @@
#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_STRING "\<TEXT\>"
#define IC_FORMAT_NUMBER "\<NUM\>"
#define IC_FORMAT_REF "\<REF\>"
#define IC_FORMAT_LIST "\<LIST\>"
@@ -107,6 +107,7 @@
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];scan=1>\[Scan with Debugger\]</a> | "
if(circuit.removable)
HTML += "<a href=?src=\ref[circuit];remove=1>\[Remove\]</a>"
HTML += "<br>"
@@ -223,9 +224,10 @@
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
// S.set_pin_data(IC_OUTPUT, 1, weakref(target))
// S.check_then_do_work()
if(S.scan(target))
scanned = TRUE
if(scanned)
visible_message("<span class='notice'>\The [user] waves \the [src] around [target].</span>")
@@ -6,6 +6,7 @@ a creative player the means to solve many problems. Circuits are held inside an
/obj/item/integrated_circuit/examine(mob/user)
. = ..()
external_examine(user)
interact(user)
// This should be used when someone is examining while the case is opened.
/obj/item/integrated_circuit/proc/internal_examine(mob/user)
@@ -86,16 +87,14 @@ a creative player the means to solve many problems. Circuits are held inside an
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 += "<table border='1' style='undefined;table-layout: fixed; width: 80%'>"
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];scan=1'>\[Scan with Debugger\]</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]'>"
@@ -212,6 +211,16 @@ a creative player the means to solve many problems. Circuits are held inside an
if(href_list["rename"])
rename_component(usr)
if(href_list["scan"])
if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/D = held_item
if(D.accepting_refs)
D.afterattack(src, usr, TRUE)
else
to_chat(usr, "<span class='warning'>The Debugger's 'ref scanner' needs to be on.</span>")
else
to_chat(usr, "<span class='warning'>You need a Debugger set to 'ref' mode to do that.</span>")
if(href_list["autopulse"])
if(autopulse != -1)
autopulse = !autopulse
@@ -260,10 +269,10 @@ a creative player the means to solve many problems. Circuits are held inside an
return TRUE // Battery has enough.
return FALSE // Not enough power.
/obj/item/integrated_circuit/proc/check_then_do_work()
/obj/item/integrated_circuit/proc/check_then_do_work(var/ignore_power = FALSE)
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
return
if(power_draw_per_use)
if(power_draw_per_use && !ignore_power)
if(!check_power())
power_fail()
return
@@ -160,7 +160,7 @@
data_to_show = A.name
to_chat(user, "<span class='notice'>You write '[data_to_write ? data_to_show : "NULL"]' to the '[io]' pin of \the [io.holder].</span>")
else if(io.io_type == PULSE_CHANNEL)
io.holder.check_then_do_work()
io.holder.check_then_do_work(ignore_power = TRUE)
to_chat(user, "<span class='notice'>You pulse \the [io.holder]'s [io].</span>")
io.holder.interact(user) // This is to update the UI.
@@ -1,9 +1,18 @@
//These circuits do simple math.
/obj/item/integrated_circuit/arithmetic
complexity = 1
inputs = list("A","B","C","D","E","F","G","H")
outputs = list("result")
activators = list("compute")
inputs = list(
"\<NUM\> A",
"\<NUM\> B",
"\<NUM\> C",
"\<NUM\> D",
"\<NUM\> E",
"\<NUM\> F",
"\<NUM\> G",
"\<NUM\> H"
)
outputs = list("\<NUM\> result")
activators = list("\<PULSE IN\> compute", "\<PULSE OUT\> on computed")
category_text = "Arithmetic"
autopulse = 1
power_draw_per_use = 5 // Math is pretty cheap.
@@ -30,9 +39,9 @@
if(isnum(I.data))
result = result + I.data
for(var/datum/integrated_io/output/O in outputs)
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// -Subtracting- //
@@ -58,9 +67,9 @@
if(isnum(I.data))
result = result - I.data
for(var/datum/integrated_io/output/O in outputs)
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// *Multiply* //
@@ -86,9 +95,9 @@
if(isnum(I.data))
result = result * I.data
for(var/datum/integrated_io/output/O in outputs)
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// /Division/ //
@@ -114,9 +123,9 @@
if(isnum(I.data) && I.data != 0) //No runtimes here.
result = result / I.data
for(var/datum/integrated_io/output/O in outputs)
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
//^ Exponent ^//
@@ -134,9 +143,9 @@
if(isnum(A.data) && isnum(B.data))
result = A.data ** B.data
for(var/datum/integrated_io/output/O in outputs)
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// +-Sign-+ //
@@ -159,9 +168,9 @@
else
result = 0
for(var/datum/integrated_io/output/O in outputs)
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Round //
@@ -183,9 +192,9 @@
else
result = round(A.data)
for(var/datum/integrated_io/output/O in outputs)
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Absolute //
@@ -204,9 +213,9 @@
if(isnum(I.data))
result = abs(I.data)
for(var/datum/integrated_io/output/O in outputs)
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Averaging //
@@ -229,9 +238,9 @@
if(inputs_used)
result = result / inputs_used
for(var/datum/integrated_io/output/O in outputs)
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Pi, because why the hell not? //
/obj/item/integrated_circuit/arithmetic/pi
@@ -242,9 +251,9 @@
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/pi/do_work()
var/datum/integrated_io/output/O = outputs[1]
O.data = 3.14159
O.push_data()
set_pin_data(IC_OUTPUT, 1, 3.14159)
push_data()
activate_pin(2)
// Random //
/obj/item/integrated_circuit/arithmetic/random
@@ -253,20 +262,20 @@
extended_desc = "'Inclusive' means that the upper bound is included in the range of numbers, e.g. L = 1 and H = 3 will allow \
for outputs of 1, 2, or 3. H being the higher number is not <i>strictly</i> required."
icon_state = "random"
inputs = list("L","H")
inputs = list("\<NUM\> L","\<NUM\> H")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/random/do_work()
var/result = 0
var/datum/integrated_io/L = inputs[1]
var/datum/integrated_io/H = inputs[2]
var/L = get_pin_data(IC_INPUT, 1)
var/H = get_pin_data(IC_INPUT, 2)
if(isnum(L.data) && isnum(H.data))
result = rand(L.data, H.data)
if(isnum(L) && isnum(H))
result = rand(L, H)
for(var/datum/integrated_io/output/O in outputs)
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Square Root //
@@ -274,7 +283,7 @@
name = "square root circuit"
desc = "This outputs the square root of a number you put in."
icon_state = "square_root"
inputs = list("A")
inputs = list("\<NUM\> A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/square_root/do_work()
@@ -284,9 +293,9 @@
if(isnum(I.data))
result = sqrt(I.data)
for(var/datum/integrated_io/output/O in outputs)
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// % Modulo % //
@@ -294,17 +303,17 @@
name = "modulo circuit"
desc = "Gets the remainder of A / B."
icon_state = "modulo"
inputs = list("A", "B")
inputs = list("\<NUM\> A", "\<NUM\> B")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/arithmetic/modulo/do_work()
var/result = 0
var/datum/integrated_io/input/A = inputs[1]
var/datum/integrated_io/input/B = inputs[2]
if(isnum(A.data) && isnum(B.data) && B.data != 0)
result = A.data % B.data
var/A = get_pin_data(IC_INPUT, 1)
var/B = get_pin_data(IC_INPUT, 2)
if(isnum(A) && isnum(B) && B != 0)
result = A % B
for(var/datum/integrated_io/output/O in outputs)
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
@@ -3,7 +3,7 @@
complexity = 2
inputs = list("input")
outputs = list("output")
activators = list("convert")
activators = list("\<PULSE IN\> convert", "\<PULSE OUT\> on convert")
category_text = "Converter"
autopulse = 1
power_draw_per_use = 10
@@ -16,89 +16,113 @@
name = "number to string"
desc = "This circuit can convert a number variable into a string."
icon_state = "num-string"
inputs = list("\<NUM\> input")
outputs = list("\<TEXT\> output")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/num2text/do_work()
var/result = null
var/datum/integrated_io/incoming = inputs[1]
var/datum/integrated_io/outgoing = outputs[1]
if(incoming.data && isnum(incoming.data))
result = num2text(incoming.data)
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(incoming && isnum(incoming))
result = num2text(incoming)
outgoing.data = result
outgoing.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/text2num
name = "string to number"
desc = "This circuit can convert a string variable into a number."
icon_state = "string-num"
inputs = list("\<TEXT\> input")
outputs = list("\<NUM\> output")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/text2num/do_work()
var/result = null
var/datum/integrated_io/incoming = inputs[1]
var/datum/integrated_io/outgoing = outputs[1]
if(incoming.data && istext(incoming.data))
result = text2num(incoming.data)
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(incoming && istext(incoming))
result = text2num(incoming)
outgoing.data = result
outgoing.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/ref2text
name = "reference to string"
desc = "This circuit can convert a reference to something else to a string, specifically the name of that reference."
icon_state = "ref-string"
inputs = list("\<REF\> input")
outputs = list("\<TEXT\> output")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/ref2text/do_work()
var/result = null
var/datum/integrated_io/incoming = inputs[1]
var/datum/integrated_io/outgoing = outputs[1]
var/atom/A = incoming.data_as_type(/atom)
result = A && A.name
pull_data()
var/atom/A = get_pin_data(IC_INPUT, 1)
if(A && istype(A))
result = A.name
outgoing.data = result
outgoing.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/lowercase
name = "lowercase string converter"
desc = "this will cause a string to come out in all lowercase."
icon_state = "lowercase"
inputs = list("\<TEXT\> input")
outputs = list("\<TEXT\> output")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/lowercase/do_work()
var/result = null
var/datum/integrated_io/incoming = inputs[1]
var/datum/integrated_io/outgoing = outputs[1]
if(incoming.data && istext(incoming.data))
result = lowertext(incoming.data)
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(incoming && istext(incoming))
result = lowertext(incoming)
outgoing.data = result
outgoing.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/uppercase
name = "uppercase string converter"
desc = "THIS WILL CAUSE A STRING TO COME OUT IN ALL UPPERCASE."
icon_state = "uppercase"
inputs = list("\<TEXT\> input")
outputs = list("\<TEXT\> output")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/uppercase/do_work()
var/result = null
var/datum/integrated_io/incoming = inputs[1]
var/datum/integrated_io/outgoing = outputs[1]
if(incoming.data && istext(incoming.data))
result = uppertext(incoming.data)
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(incoming && istext(incoming))
result = uppertext(incoming)
outgoing.data = result
outgoing.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/concatenatior
name = "concatenatior"
desc = "This joins many strings together to get one big string."
desc = "This joins many strings or numbers together to get one big string."
complexity = 4
inputs = list("A","B","C","D","E","F","G","H")
outputs = list("result")
activators = list("concatenate")
inputs = list(
"\<TEXT/NUM\> A",
"\<TEXT/NUM\> B",
"\<TEXT/NUM\> C",
"\<TEXT/NUM\> D",
"\<TEXT/NUM\> E",
"\<TEXT/NUM\> F",
"\<TEXT/NUM\> G",
"\<TEXT/NUM\> H"
)
outputs = list("\<TEXT\> result")
activators = list("\<PULSE IN\> concatenate", "\<PULSE OUT\> on concatenated")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/concatenatior/do_work()
@@ -107,70 +131,70 @@
I.pull_data()
if(istext(I.data))
result = result + I.data
else if(!isnull(I.data) && num2text(I.data))
result = result + num2text(I.data)
var/datum/integrated_io/outgoing = outputs[1]
outgoing.data = result
outgoing.push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/radians2degrees
name = "radians to degrees converter"
desc = "Converts radians to degrees."
inputs = list("radian")
outputs = list("degrees")
inputs = list("\<NUM\> radian")
outputs = list("\<NUM\> degrees")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/radians2degrees/do_work()
var/result = null
var/datum/integrated_io/incoming = inputs[1]
var/datum/integrated_io/outgoing = outputs[1]
incoming.pull_data()
if(incoming.data && isnum(incoming.data))
result = ToDegrees(incoming.data)
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(incoming && isnum(incoming))
result = ToDegrees(incoming)
outgoing.data = result
outgoing.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/degrees2radians
name = "degrees to radians converter"
desc = "Converts degrees to radians."
inputs = list("degrees")
outputs = list("radians")
inputs = list("\<NUM\> degrees")
outputs = list("\<NUM\> radians")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/degrees2radians/do_work()
var/result = null
var/datum/integrated_io/incoming = inputs[1]
var/datum/integrated_io/outgoing = outputs[1]
incoming.pull_data()
if(incoming.data && isnum(incoming.data))
result = ToRadians(incoming.data)
pull_data()
var/incoming = get_pin_data(IC_INPUT, 1)
if(incoming && isnum(incoming))
result = ToRadians(incoming)
outgoing.data = result
outgoing.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
/obj/item/integrated_circuit/converter/abs_to_rel_coords
name = "abs to rel coordinate converter"
desc = "Easily convert absolute coordinates to relative coordinates with this."
complexity = 4
inputs = list("X1 (abs)", "Y1 (abs)", "X2 (abs)", "Y2 (abs)")
outputs = list("X (rel)", "Y (rel)")
activators = list("compute rel coordinates")
inputs = list("\<NUM\> X1", "\<NUM\> Y1", "\<NUM\> X2", "\<NUM\> Y2")
outputs = list("\<NUM\> X", "\<NUM\> Y")
activators = list("\<PULSE IN\> compute rel coordinates", "\<PULSE OUT\> on convert")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work()
var/datum/integrated_io/x1 = inputs[1]
var/datum/integrated_io/y1 = inputs[2]
var/x1 = get_pin_data(IC_INPUT, 1)
var/y1 = get_pin_data(IC_INPUT, 2)
var/datum/integrated_io/x2 = inputs[3]
var/datum/integrated_io/y2 = inputs[4]
var/x2 = get_pin_data(IC_INPUT, 3)
var/y2 = get_pin_data(IC_INPUT, 4)
var/datum/integrated_io/result_x = outputs[1]
var/datum/integrated_io/result_y = outputs[2]
if(x1 && y1 && x2 && y2)
set_pin_data(IC_OUTPUT, 1, x1 - x2)
set_pin_data(IC_OUTPUT, 2, y1 - y2)
if(x1.data && y1.data && x2.data && y2.data)
result_x.data = x1.data - x2.data
result_y.data = y1.data - y2.data
for(var/datum/integrated_io/output/O in outputs)
O.push_data()
push_data()
activate_pin(2)
@@ -14,28 +14,27 @@
can_be_asked_input = 1
inputs = list()
outputs = list()
activators = list("on pressed")
activators = list("\<PULSE OUT\> on pressed")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/input/button/ask_for_input(mob/user) //Bit misleading name for this specific use.
var/datum/integrated_io/A = activators[1]
if(A.linked.len)
for(var/datum/integrated_io/activate/target in A.linked)
target.holder.check_then_do_work()
to_chat(user, "<span class='notice'>You press the button labeled '[src.name]'.</span>")
activate_pin(1)
/obj/item/integrated_circuit/input/toggle_button
name = "toggle button"
desc = "It toggles on, off, on, off..."
icon_state = "toggle_button"
complexity = 1
can_be_asked_input = 1
inputs = list()
outputs = list("on" = 0)
activators = list("on toggle")
outputs = list("\<NUM\> on" = 0)
activators = list("\<PULSE OUT\> 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))
push_data()
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>")
@@ -46,19 +45,17 @@
complexity = 2
can_be_asked_input = 1
inputs = list()
outputs = list("number entered")
activators = list("on entered")
outputs = list("\<NUM\> number entered")
activators = list("\<PULSE OUT\> 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
if(isnum(new_input) && CanInteract(user, physical_state))
var/datum/integrated_io/O = outputs[1]
O.data = new_input
O.push_data()
var/datum/integrated_io/A = activators[1]
A.push_data()
set_pin_data(IC_OUTPUT, 1, new_input)
push_data()
activate_pin(1)
/obj/item/integrated_circuit/input/textpad
name = "text pad"
@@ -67,49 +64,43 @@
complexity = 2
can_be_asked_input = 1
inputs = list()
outputs = list("string entered")
activators = list("on entered")
outputs = list("\<TEXT\> string entered")
activators = list("\<PULSE OUT\> 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
if(istext(new_input) && CanInteract(user, physical_state))
var/datum/integrated_io/O = outputs[1]
O.data = new_input
O.push_data()
var/datum/integrated_io/A = activators[1]
A.push_data()
set_pin_data(IC_OUTPUT, 1, new_input)
push_data()
activate_pin(1)
/obj/item/integrated_circuit/input/med_scanner
name = "integrated medical analyser"
desc = "A very small version of the common medical analyser. This allows the machine to know how healthy someone is."
icon_state = "medscan"
complexity = 4
inputs = list("target ref")
outputs = list("total health %", "total missing health")
activators = list("scan")
inputs = list("\<REF\> target")
outputs = list("\<NUM\> total health %", "\<NUM\> total missing health")
activators = list("\<PULSE IN\> scan", "\<PULSE OUT\> on scanned")
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]
var/mob/living/carbon/human/H = I.data_as_type(/mob/living/carbon/human)
var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human)
if(!istype(H)) //Invalid input
return
if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range.
var/total_health = round(H.health/H.maxHealth, 0.1)*100
var/missing_health = H.maxHealth - H.health
var/total_health = round(H.health/H.getMaxHealth(), 0.1)*100
var/missing_health = H.getMaxHealth() - H.health
var/datum/integrated_io/total = outputs[1]
var/datum/integrated_io/missing = outputs[2]
set_pin_data(IC_OUTPUT, 1, total_health)
set_pin_data(IC_OUTPUT, 2, missing_health)
total.data = total_health
missing.data = missing_health
for(var/datum/integrated_io/output/O in outputs)
O.push_data()
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/adv_med_scanner
name = "integrated advanced medical analyser"
@@ -117,48 +108,39 @@
This type is much more precise, allowing the machine to know much more about the target than a normal analyzer."
icon_state = "medscan_adv"
complexity = 12
inputs = list("target ref")
inputs = list("\<REF\> target")
outputs = list(
"total health %",
"total missing health",
"brute damage",
"burn damage",
"tox damage",
"oxy damage",
"clone damage"
"\<NUM\> total health %",
"\<NUM\> total missing health",
"\<NUM\> brute damage",
"\<NUM\> burn damage",
"\<NUM\> tox damage",
"\<NUM\> oxy damage",
"\<NUM\> clone damage"
)
activators = list("scan")
activators = list("\<PULSE IN\> scan", "\<PULSE OUT\> on scanned")
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]
var/mob/living/carbon/human/H = I.data_as_type(/mob/living/carbon/human)
var/mob/living/carbon/human/H = get_pin_data_as_type(IC_INPUT, 1, /mob/living/carbon/human)
if(!istype(H)) //Invalid input
return
if(H.Adjacent(get_turf(src))) // Like normal analysers, it can't be used at range.
var/total_health = round(H.health/H.maxHealth, 0.1)*100
var/missing_health = H.maxHealth - H.health
var/total_health = round(H.health/H.getMaxHealth(), 0.1)*100
var/missing_health = H.getMaxHealth() - H.health
var/datum/integrated_io/total = outputs[1]
var/datum/integrated_io/missing = outputs[2]
var/datum/integrated_io/brute = outputs[3]
var/datum/integrated_io/burn = outputs[4]
var/datum/integrated_io/tox = outputs[5]
var/datum/integrated_io/oxy = outputs[6]
var/datum/integrated_io/clone = outputs[7]
set_pin_data(IC_OUTPUT, 1, total_health)
set_pin_data(IC_OUTPUT, 2, missing_health)
set_pin_data(IC_OUTPUT, 3, H.getBruteLoss())
set_pin_data(IC_OUTPUT, 4, H.getFireLoss())
set_pin_data(IC_OUTPUT, 5, H.getToxLoss())
set_pin_data(IC_OUTPUT, 6, H.getOxyLoss())
set_pin_data(IC_OUTPUT, 7, H.getCloneLoss())
total.data = total_health
missing.data = missing_health
brute.data = H.getBruteLoss()
burn.data = H.getFireLoss()
tox.data = H.getToxLoss()
oxy.data = H.getOxyLoss()
clone.data = H.getCloneLoss()
for(var/datum/integrated_io/output/O in outputs)
O.push_data()
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/local_locator
name = "local locator"
@@ -222,9 +204,9 @@
Meaning the default frequency is expressed as 1457, not 145.7. To send a signal, pulse the 'send signal' activator pin."
icon_state = "signal"
complexity = 4
inputs = list("frequency","code")
inputs = list("\<NUM\> frequency","\<NUM\> code")
outputs = list()
activators = list("send signal","on signal received")
activators = list("\<PULSE IN\> send signal","\<PULSE OUT\> on signal sent", "\<PULSE OUT\> on signal received")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2)
power_draw_idle = 5
@@ -237,11 +219,9 @@
/obj/item/integrated_circuit/input/signaler/initialize()
..()
set_frequency(frequency)
var/datum/integrated_io/new_freq = inputs[1]
var/datum/integrated_io/new_code = inputs[2]
// Set the pins so when someone sees them, they won't show as null
new_freq.data = frequency
new_code.data = code
set_pin_data(IC_INPUT, 1, frequency)
set_pin_data(IC_INPUT, 2, code)
/obj/item/integrated_circuit/input/signaler/Destroy()
if(radio_controller)
@@ -250,12 +230,12 @@
. = ..()
/obj/item/integrated_circuit/input/signaler/on_data_written()
var/datum/integrated_io/new_freq = inputs[1]
var/datum/integrated_io/new_code = inputs[2]
if(isnum(new_freq.data) && new_freq.data > 0)
set_frequency(new_freq.data)
if(isnum(new_code.data))
code = new_code.data
var/new_freq = get_pin_data(IC_INPUT, 1)
var/new_code = get_pin_data(IC_INPUT, 2)
if(isnum(new_freq) && new_freq > 0)
set_frequency(new_freq)
if(isnum(new_code))
code = new_code
/obj/item/integrated_circuit/input/signaler/do_work() // Sends a signal.
@@ -267,6 +247,7 @@
signal.encryption = code
signal.data["message"] = "ACTIVATE"
radio_connection.post_signal(src, signal)
activate_pin(2)
/obj/item/integrated_circuit/input/signaler/proc/set_frequency(new_frequency)
if(!frequency)
@@ -280,11 +261,11 @@
radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT)
/obj/item/integrated_circuit/input/signaler/receive_signal(datum/signal/signal)
var/datum/integrated_io/new_code = inputs[2]
var/new_code = get_pin_data(IC_INPUT, 2)
var/code = 0
if(isnum(new_code.data))
code = new_code.data
if(isnum(new_code))
code = new_code
if(!signal)
return 0
if(signal.encryption != code)
@@ -292,8 +273,7 @@
if(signal.source == src) // Don't trigger ourselves.
return 0
var/datum/integrated_io/A = activators[2]
A.push_data()
activate_pin(3)
for(var/mob/O in hearers(1, get_turf(src)))
O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2)
@@ -306,9 +286,9 @@
will pulse whatever's connected to it. Pulsing the first activation pin will send a message."
icon_state = "signal"
complexity = 4
inputs = list("target EPv2 address", "data to send", "secondary text")
outputs = list("address received", "data received", "secondary text received")
activators = list("send data", "on data received")
inputs = list("\<TEXT\> target EPv2 address", "\<TEXT\> data to send", "\<TEXT\> secondary text")
outputs = list("\<TEXT\> address received", "\<TEXT\> data received", "\<TEXT\> secondary text received")
activators = list("\<PULSE IN\> send data", "\<PULSE OUT\> on data received")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2)
power_draw_per_use = 50
@@ -318,7 +298,7 @@
..()
exonet = new(src)
exonet.make_address("EPv2_circuit-\ref[src]")
desc += "<br>This circuit's EPv2 address is: [exonet.address]."
desc += "<br>This circuit's EPv2 address is: [exonet.address]"
/obj/item/integrated_circuit/input/EPv2/Destroy()
if(exonet)
@@ -327,64 +307,60 @@
..()
/obj/item/integrated_circuit/input/EPv2/do_work()
var/datum/integrated_io/target_address = inputs[1]
var/datum/integrated_io/message = inputs[2]
var/datum/integrated_io/text = inputs[3]
if(istext(target_address.data))
exonet.send_message(target_address.data, message.data, text.data)
var/target_address = get_pin_data(IC_INPUT, 1)
var/message = get_pin_data(IC_INPUT, 2)
var/text = get_pin_data(IC_INPUT, 3)
if(target_address && istext(target_address))
exonet.send_message(target_address, message, text)
/obj/item/integrated_circuit/input/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message, var/text)
var/datum/integrated_io/message_received = outputs[1]
var/datum/integrated_io/data_received = outputs[2]
var/datum/integrated_io/text_received = outputs[3]
set_pin_data(IC_OUTPUT, 1, origin_address)
set_pin_data(IC_OUTPUT, 2, message)
set_pin_data(IC_OUTPUT, 3, text)
var/datum/integrated_io/A = activators[2]
A.push_data()
message_received.write_data_to_pin(origin_address)
data_received.write_data_to_pin(message)
text_received.write_data_to_pin(text)
for(var/datum/integrated_io/output/O in outputs)
O.push_data()
push_data()
activate_pin(2)
//This circuit gives information on where the machine is.
/obj/item/integrated_circuit/input/gps
name = "global positioning system"
desc = "This allows you to easily know the position of a machine containing this device."
extended_desc = "The GPS's coordinates it gives is absolute, not relative."
icon_state = "gps"
complexity = 4
inputs = list()
outputs = list("X (abs)", "Y (abs)")
activators = list("get coordinates")
outputs = list("\<NUM\> X", "\<NUM\> Y")
activators = list("\<PULSE IN\> get coordinates", "\<PULSE OUT\> on 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)
var/datum/integrated_io/result_x = outputs[1]
var/datum/integrated_io/result_y = outputs[2]
result_x.data = null
result_y.data = null
set_pin_data(IC_OUTPUT, 1, null)
set_pin_data(IC_OUTPUT, 2, null)
if(!T)
return
result_x.data = T.x
result_y.data = T.y
set_pin_data(IC_OUTPUT, 1, T.x)
set_pin_data(IC_OUTPUT, 2, T.y)
for(var/datum/integrated_io/output/O in outputs)
O.push_data()
push_data()
activate_pin(2)
/obj/item/integrated_circuit/input/microphone
name = "microphone"
desc = "Useful for spying on people or for voice activated machines."
extended_desc = "This will automatically translate most languages it hears to Galactic Common. \
The first activation pin is always pulsed when the circuit hears someone talk, while the second one \
is only triggered if it hears someone speaking a language other than Galactic Common."
icon_state = "recorder"
complexity = 8
inputs = list()
outputs = list("speaker \<String\>", "message \<String\>")
activators = list("on message received")
outputs = list("\<TEXT\> speaker", "\<TEXT\> message")
activators = list("\<PULSE OUT\> on message received", "\<PULSE OUT\> on translation")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 15
@@ -397,42 +373,45 @@
..()
/obj/item/integrated_circuit/input/microphone/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null)
var/datum/integrated_io/V = outputs[1]
var/datum/integrated_io/O = outputs[2]
var/datum/integrated_io/A = activators[1]
var/translated = FALSE
if(M && msg)
if(speaking)
if(!speaking.machine_understands)
msg = speaking.scramble(msg)
V.data = M.GetVoice()
O.data = msg
A.push_data()
if(!istype(speaking, /datum/language/common))
translated = TRUE
set_pin_data(IC_OUTPUT, 1, M.GetVoice())
set_pin_data(IC_OUTPUT, 2, msg)
for(var/datum/integrated_io/output/out in outputs)
out.push_data()
A.push_data()
push_data()
activate_pin(1)
if(translated)
activate_pin(2)
/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."
extended_desc = "If 'ignore storage' pin is set to 1, the sensor will disregard scanning various storage containers such as backpacks."
icon_state = "recorder"
complexity = 12
inputs = list()
outputs = list("scanned ref \<Ref\>")
activators = list("on scanned")
inputs = list("\<NUM\> ignore storage" = 1)
outputs = list("\<REF\> scanned")
activators = list("\<PULSE OUT\> 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/input/sensor/proc/scan(var/atom/A)
var/ignore_bags = get_pin_data(IC_INPUT, 1)
if(ignore_bags)
if(istype(A, /obj/item/weapon/storage))
return FALSE
set_pin_data(IC_OUTPUT, 1, weakref(A))
push_data()
activate_pin(1)
return TRUE
/obj/item/integrated_circuit/output
category_text = "Output"
@@ -441,9 +420,9 @@
name = "small screen"
desc = "This small screen can display a single piece of data, when the machine is examined closely."
icon_state = "screen"
inputs = list("displayed data")
inputs = list("\<TEXT/NUM\> displayed data")
outputs = list()
activators = list("load data")
activators = list("\<PULSE IN\> load data")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
power_draw_per_use = 10
autopulse = 1
@@ -497,7 +476,7 @@
complexity = 4
inputs = list()
outputs = list()
activators = list("toggle light")
activators = list("\<PULSE IN\> toggle light")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
var/light_toggled = 0
var/light_brightness = 3
@@ -519,18 +498,18 @@
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]
var/datum/integrated_io/G = inputs[2]
var/datum/integrated_io/B = inputs[3]
var/datum/integrated_io/brightness = inputs[4]
var/R = get_pin_data(IC_INPUT, 1)
var/G = get_pin_data(IC_INPUT, 2)
var/B = get_pin_data(IC_INPUT, 3)
var/brightness = get_pin_data(IC_INPUT, 4)
if(isnum(R.data) && isnum(G.data) && isnum(B.data) && isnum(brightness.data))
R.data = Clamp(R.data, 0, 255)
G.data = Clamp(G.data, 0, 255)
B.data = Clamp(B.data, 0, 255)
brightness.data = Clamp(brightness.data, 0, 6)
light_rgb = rgb(R.data, G.data, B.data)
light_brightness = brightness.data
if(isnum(R) && isnum(G) && isnum(B) && isnum(brightness))
R = Clamp(R, 0, 255)
G = Clamp(G, 0, 255)
B = Clamp(B, 0, 255)
brightness = Clamp(brightness, 0, 6)
light_rgb = rgb(R, G, B)
light_brightness = brightness
..()
@@ -544,10 +523,10 @@
icon_state = "light_adv"
complexity = 8
inputs = list(
"R",
"G",
"B",
"Brightness"
"\<NUM\> R",
"\<NUM\> G",
"\<NUM\> B",
"\<NUM\> Brightness"
)
outputs = list()
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
@@ -563,9 +542,9 @@
complexity = 8
cooldown_per_use = 4 SECONDS
inputs = list(
"sound ID",
"volume",
"frequency"
"\<TEXT\> sound ID",
"\<NUM\> volume",
"\<NUM\> frequency"
)
outputs = list()
activators = list("play sound")
@@ -4,7 +4,7 @@
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", "on false result")
activators = list("\<PULSE IN\> compare", "\<PULSE OUT\> on true result", "\<PULSE OUT\> on false result")
category_text = "Logic"
autopulse = 1
power_draw_per_use = 1
@@ -14,19 +14,17 @@
check_then_do_work()
/obj/item/integrated_circuit/logic/do_work()
var/datum/integrated_io/O = outputs[1]
var/datum/integrated_io/T = activators[2]
var/datum/integrated_io/F = activators[3]
O.push_data()
if(O.data)
T.push_data()
push_data()
if(get_pin_data(IC_INPUT, 1))
activate_pin(1)
else
F.push_data()
activate_pin(2)
/obj/item/integrated_circuit/logic/binary
inputs = list("A","B")
inputs = list("\<ANY\> A","\<ANY\> B")
/obj/item/integrated_circuit/logic/binary/do_work()
pull_data()
var/datum/integrated_io/A = inputs[1]
var/datum/integrated_io/B = inputs[2]
var/datum/integrated_io/O = outputs[1]
@@ -37,9 +35,10 @@
return FALSE
/obj/item/integrated_circuit/logic/unary
inputs = list("A")
inputs = list("\<ANY\> A")
/obj/item/integrated_circuit/logic/unary/do_work()
pull_data()
var/datum/integrated_io/A = inputs[1]
var/datum/integrated_io/O = outputs[1]
O.data = do_check(A) ? TRUE : FALSE
@@ -11,12 +11,12 @@
complexity = 20
w_class = ITEMSIZE_NORMAL
inputs = list(
"target X rel",
"target Y rel"
"\<NUM\> target X rel",
"\<NUM\> target Y rel"
)
outputs = list()
activators = list(
"fire"
"\<PULSE IN\> fire"
)
var/obj/item/weapon/gun/installed_gun = null
spawn_flags = IC_SPAWN_RESEARCH
@@ -11,9 +11,9 @@
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")
inputs = list("\<REF\> target")
outputs = list("\<NUM\> target cell charge", "\<NUM\> target cell max charge", "\<NUM\> target cell percentage")
activators = list("\<PULSE IN\> 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.
@@ -43,39 +43,39 @@
flags = OPENCONTAINER
complexity = 20
cooldown_per_use = 6 SECONDS
inputs = list("target ref", "injection amount" = 5)
inputs = list("\<REF\> target", "\<NUM\> injection amount" = 5)
outputs = list()
activators = list("inject")
activators = list("\<PULSE IN\> 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]
if(isnum(amount.data))
return Clamp(amount.data, 0, 30)
var/amount = get_pin_data(IC_INPUT, 2)
if(isnum(amount))
return Clamp(amount, 0, 30)
/obj/item/integrated_circuit/reagent/injector/do_work()
set waitfor = 0 // Don't sleep in a proc that is called by a processor without this set, otherwise it'll delay the entire thing
var/datum/integrated_io/target = inputs[1]
var/atom/movable/AM = target.data_as_type(/atom/movable)
var/atom/movable/AM = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
if(!istype(AM)) //Invalid input
return
if(!reagents.total_volume) // Empty
return
if(AM.can_be_injected_by(src))
if(isliving(AM))
var/mob/living/L = AM
var/turf/T = get_turf(AM)
T.visible_message("<span class='warning'>[src] is trying to inject [AM]!</span>")
T.visible_message("<span class='warning'>[src] is trying to inject [L]!</span>")
sleep(3 SECONDS)
if(!AM.can_be_injected_by(src))
if(!L.can_be_injected_by(src))
return
var/contained = reagents.get_reagents()
var/trans = reagents.trans_to_mob(target, inject_amount(), CHEM_BLOOD)
message_admins("[src] injected \the [AM] with [trans]u of [contained].")
var/trans = reagents.trans_to_mob(L, inject_amount(), CHEM_BLOOD)
message_admins("[src] injected \the [L] with [trans]u of [contained].")
to_chat(AM, "<span class='notice'>You feel a tiny prick!</span>")
visible_message("<span class='warning'>[src] injects [AM]!</span>")
visible_message("<span class='warning'>[src] injects [L]!</span>")
else
reagents.trans_to(AM, inject_amount())
@@ -88,9 +88,9 @@
outside the machine if it is next to the machine. Note that this cannot be used on entities."
flags = OPENCONTAINER
complexity = 8
inputs = list("source ref", "target ref", "injection amount" = 10)
inputs = list("\<REF\> source", "\<REF\> target", "\<NUM\> injection amount" = 10)
outputs = list()
activators = list("transfer reagents")
activators = list("\<PULSE IN\> transfer reagents", "\<PULSE OUT\> on transfer")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2)
var/transfer_amount = 10
@@ -103,10 +103,9 @@
transfer_amount = amount.data
/obj/item/integrated_circuit/reagent/pump/do_work()
var/datum/integrated_io/A = inputs[1]
var/datum/integrated_io/B = inputs[2]
var/atom/movable/source = A.data_as_type(/atom/movable)
var/atom/movable/target = B.data_as_type(/atom/movable)
var/atom/movable/source = get_pin_data_as_type(IC_INPUT, 1, /atom/movable)
var/atom/movable/target = get_pin_data_as_type(IC_INPUT, 2, /atom/movable)
if(!istype(source) || !istype(target)) //Invalid input
return
var/turf/T = get_turf(src)
@@ -117,10 +116,11 @@
return
if(!source.is_open_container() || !target.is_open_container())
return
if(!source.reagents.get_free_space() || !target.reagents.get_free_space())
if(!target.reagents.get_free_space())
return
source.reagents.trans_to(target, transfer_amount)
activate_pin(2)
/obj/item/integrated_circuit/reagent/storage
name = "reagent storage"
@@ -8,17 +8,16 @@
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")
inputs = list("\<REF\> target")
outputs = list("\<NUM\> dir")
activators = list("\<PULSE IN\> calculate dir", "\<PULSE OUT\> on calculated")
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
set_pin_data(IC_OUTPUT, 1, null)
if(!isweakref(I.data))
return
@@ -28,6 +27,6 @@
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()
set_pin_data(IC_OUTPUT, 1, desired_dir)
push_data()
@@ -12,16 +12,15 @@
This circuit is set to send a pulse after a delay of two seconds."
icon_state = "delay-20"
var/delay = 2 SECONDS
activators = list("incoming pulse","outgoing pulse")
activators = list("\<PULSE IN\> incoming","\<PULSE OUT\> outgoing")
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
var/datum/integrated_io/out_pulse = activators[2]
sleep(delay)
out_pulse.push_data()
activate_pin(2)
/obj/item/integrated_circuit/time/delay/five_sec
name = "five-sec delay circuit"
@@ -60,14 +59,13 @@
desc = "This sends a pulse signal out after a delay, critical for ensuring proper control flow in a complex machine. \
This circuit's delay can be customized, between 1/10th of a second to one hour. The delay is updated upon receiving a pulse."
icon_state = "delay"
inputs = list("delay time")
inputs = list("\<NUM\> delay time")
spawn_flags = IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/time/delay/custom/do_work()
var/datum/integrated_io/delay_input = inputs[1]
if(delay_input.data && isnum(delay_input.data) )
var/new_delay = min(delay_input.data, 1)
new_delay = max(new_delay, 36000) //An hour.
var/delay_input = get_pin_data(IC_INPUT, 1)
if(delay_input && isnum(delay_input) )
var/new_delay = between(1, delay_input, 36000) //An hour.
delay = new_delay
..()
@@ -80,8 +78,8 @@
var/ticks_to_pulse = 4
var/ticks_completed = 0
var/is_running = FALSE
inputs = list("enable ticking")
activators = list("outgoing pulse")
inputs = list("\<NUM\> enable ticking" = 0)
activators = list("\<PULSE OUT\> outgoing pulse")
spawn_flags = IC_SPAWN_RESEARCH
power_draw_per_use = 4
@@ -91,8 +89,8 @@
. = ..()
/obj/item/integrated_circuit/time/ticker/on_data_written()
var/datum/integrated_io/do_tick = inputs[1]
if(do_tick.data && !is_running)
var/do_tick = get_pin_data(IC_INPUT, 1)
if(do_tick && !is_running)
is_running = TRUE
processing_objects |= src
else if(is_running)
@@ -108,8 +106,7 @@
ticks_completed -= ticks_to_pulse
else
ticks_completed = 0
var/datum/integrated_io/pulser = activators[1]
pulser.push_data()
activate_pin(1)
/obj/item/integrated_circuit/time/ticker/fast
name = "fast ticker"
@@ -134,20 +131,16 @@
desc = "Tells you what the local time is, specific to your station or planet."
icon_state = "clock"
inputs = list()
outputs = list("time (string)", "hours (number)", "minutes (number)", "seconds (number)")
outputs = list("\<TEXT\> time", "\<NUM\> hours", "\<NUM\> minutes", "\<NUM\> seconds")
activators = list("\<PULSE IN\> get time","\<PULSE OUT\> on time got")
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]
var/datum/integrated_io/hour = outputs[2]
var/datum/integrated_io/min = outputs[3]
var/datum/integrated_io/sec = outputs[4]
set_pin_data(IC_OUTPUT, 1, time2text(station_time_in_ticks, "hh:mm:ss") )
set_pin_data(IC_OUTPUT, 2, text2num(time2text(station_time_in_ticks, "hh") ) )
set_pin_data(IC_OUTPUT, 3, text2num(time2text(station_time_in_ticks, "mm") ) )
set_pin_data(IC_OUTPUT, 4, text2num(time2text(station_time_in_ticks, "ss") ) )
time.data = time2text(station_time_in_ticks, "hh:mm:ss")
hour.data = text2num(time2text(station_time_in_ticks, "hh"))
min.data = text2num(time2text(station_time_in_ticks, "mm"))
sec.data = text2num(time2text(station_time_in_ticks, "ss"))
for(var/datum/integrated_io/output/O in outputs)
O.push_data()
push_data()
activate_pin(2)
@@ -1,9 +1,18 @@
//These circuits do not-so-simple math.
/obj/item/integrated_circuit/trig
complexity = 1
inputs = list("A","B","C","D","E","F","G","H")
outputs = list("result")
activators = list("compute")
inputs = list(
"\<NUM\> A",
"\<NUM\> B",
"\<NUM\> C",
"\<NUM\> D",
"\<NUM\> E",
"\<NUM\> F",
"\<NUM\> G",
"\<NUM\> H"
)
outputs = list("\<NUM\> result")
activators = list("\<PULSE IN\> compute", "\<PULSE OUT\> on computed")
category_text = "Trig"
extended_desc = "Input and output are in degrees."
autopulse = 1
@@ -19,19 +28,19 @@
name = "sin circuit"
desc = "Has nothing to do with evil, unless you consider trigonometry to be evil. Outputs the sine of A."
icon_state = "sine"
inputs = list("A")
inputs = list("\<NUM\> A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/sine/do_work()
pull_data()
var/result = null
var/datum/integrated_io/input/A = inputs[1]
A.pull_data()
if(isnum(A.data))
result = sin(A.data)
var/A = get_pin_data(IC_INPUT, 1)
if(isnum(A))
result = sin(A)
var/datum/integrated_io/output/O = outputs[1]
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Cosine //
@@ -39,19 +48,19 @@
name = "cos circuit"
desc = "Outputs the cosine of A."
icon_state = "cosine"
inputs = list("A")
inputs = list("\<NUM\> A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/cosine/do_work()
pull_data()
var/result = null
var/datum/integrated_io/input/A = inputs[1]
A.pull_data()
if(isnum(A.data))
result = cos(A.data)
var/A = get_pin_data(IC_INPUT, 1)
if(isnum(A))
result = cos(A)
var/datum/integrated_io/output/O = outputs[1]
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Tangent //
@@ -59,19 +68,19 @@
name = "tan circuit"
desc = "Outputs the tangent of A. Guaranteed to not go on a tangent about its existance."
icon_state = "tangent"
inputs = list("A")
inputs = list("\<NUM\> A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/tangent/do_work()
pull_data()
var/result = null
var/datum/integrated_io/input/A = inputs[1]
A.pull_data()
if(isnum(A.data))
result = Tan(A.data)
var/A = get_pin_data(IC_INPUT, 1)
if(isnum(A))
result = Tan(A)
var/datum/integrated_io/output/O = outputs[1]
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Cosecant //
@@ -79,19 +88,19 @@
name = "csc circuit"
desc = "Outputs the cosecant of A."
icon_state = "cosecant"
inputs = list("A")
inputs = list("\<NUM\> A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/cosecant/do_work()
pull_data()
var/result = null
var/datum/integrated_io/input/A = inputs[1]
A.pull_data()
if(isnum(A.data))
result = Csc(A.data)
var/A = get_pin_data(IC_INPUT, 1)
if(isnum(A))
result = Csc(A)
var/datum/integrated_io/output/O = outputs[1]
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Secant //
@@ -100,19 +109,19 @@
name = "sec circuit"
desc = "Outputs the secant of A. Has nothing to do with the security department."
icon_state = "secant"
inputs = list("A")
inputs = list("\<NUM\> A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/secant/do_work()
pull_data()
var/result = null
var/datum/integrated_io/input/A = inputs[1]
A.pull_data()
if(isnum(A.data))
result = Sec(A.data)
var/A = get_pin_data(IC_INPUT, 1)
if(isnum(A))
result = Sec(A)
var/datum/integrated_io/output/O = outputs[1]
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
// Cotangent //
@@ -121,16 +130,16 @@
name = "cot circuit"
desc = "Outputs the cotangent of A."
icon_state = "cotangent"
inputs = list("A")
inputs = list("\<NUM\> A")
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
/obj/item/integrated_circuit/trig/cotangent/do_work()
pull_data()
var/result = null
var/datum/integrated_io/input/A = inputs[1]
A.pull_data()
if(isnum(A.data))
result = Cot(A.data)
var/A = get_pin_data(IC_INPUT, 1)
if(isnum(A))
result = Cot(A)
var/datum/integrated_io/output/O = outputs[1]
O.data = result
O.push_data()
set_pin_data(IC_OUTPUT, 1, result)
push_data()
activate_pin(2)
+5 -10
View File
@@ -38,16 +38,11 @@
/datum/lore/codex/page/unathi
name = "Unathi"
data = "The author wishes to apologize to the reader, as they currently lack enough knowledge of the Unathi to write about them, as they are \
rather rare inside Vir." // Replace this when Anewbe finishes the lizard rewrite.
/*
data = "Raging in from Moghes, the Unathi are a race of tall, reptilian humanoids that possess both crocodile-like and serpent-like features. \
They are a proud, warlike species that favors honor and strength, their home, Moghes, is a desert planet but was once believed to be full of life. \
Of all the currently known sentient species, the Unathi are the most unequal in gender with females tending to be property of the males. Most Unathi \
outside of Moghes tend to be exiles however, and with influence of other species the gender difference is not nearly as pronounced. Unathi were \
humanity's second contact, and despite their aggressive nature, seem to get along well enough with humanity, though are often considered to be \
'second-class' citizens and are rarely seen in jobs other than where muscle is needed." // This probably needs to be updated.
*/
data = "The Unathi are a race of tall, reptilian humanoids that possess a blend of serpentine features reminiscent of crocodiles. \
They are a proud, religious species that favors honor and strength, and originate from the desert planet of Moghes. \
The Unathi follow a religious code known as the Unity, and they carry this with them on their travels. \
Unathi once fought a serious war against SolGov, and as a result are often considered to be second-class citizens, \
rarely seen in jobs that don't require a little muscle."
/datum/lore/codex/page/tajaran
name = "Tajaran"
@@ -10,6 +10,7 @@
recipes += new/datum/stack_recipe("[display_name] baseball bat", /obj/item/weapon/material/twohanded/baseballbat, 10, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]")
recipes += new/datum/stack_recipe("[display_name] ashtray", /obj/item/weapon/material/ashtray, 2, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
recipes += new/datum/stack_recipe("[display_name] spoon", /obj/item/weapon/material/kitchen/utensil/spoon/plastic, 1, on_floor = 1, supplied_material = "[name]")
recipes += new/datum/stack_recipe("[display_name] armor plate", /obj/item/weapon/material/armor_plating, 1, time = 20, on_floor = 1, supplied_material = "[name]")
if(integrity>=50)
recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]")
+42 -4
View File
@@ -90,10 +90,12 @@ var/list/name_to_material
var/ignition_point // K, point at which the material catches on fire.
var/melting_point = 1800 // K, walls will take damage if they're next to a fire hotter than this
var/integrity = 150 // General-use HP value for products.
var/protectiveness = 10 // How well this material works as armor. Higher numbers are better, diminishing returns applies.
var/opacity = 1 // Is the material transparent? 0.5< makes transparent walls/doors.
var/reflectivity = 0 // How reflective to light is the material? Currently used for laser defense.
var/reflectivity = 0 // How reflective to light is the material? Currently used for laser reflection and defense.
var/explosion_resistance = 5 // Only used by walls currently.
var/conductive = 1 // Objects with this var add CONDUCTS to flags on spawn.
var/conductivity = null // How conductive the material is. Iron acts as the baseline, at 10.
var/list/composite_material // If set, object matter var will be a list containing these values.
// Placeholder vars for the time being, todo properly integrate windows/light tiles/rods.
@@ -103,7 +105,7 @@ var/list/name_to_material
var/list/window_options = list()
// Damage values.
var/hardness = 60 // Prob of wall destruction by hulk, used for edge damage in weapons.
var/hardness = 60 // Prob of wall destruction by hulk, used for edge damage in weapons. Also used for bullet protection in armor.
var/weight = 20 // Determines blunt damage/throwforce for weapons.
// Noise when someone is faceplanted onto a table made of this material.
@@ -236,6 +238,7 @@ var/list/name_to_material
icon_colour = "#00FFE1"
opacity = 0.4
reflectivity = 0.6
conductivity = 1
shard_type = SHARD_SHARD
tableslam_noise = 'sound/effects/Glasshit.ogg'
hardness = 100
@@ -247,6 +250,7 @@ var/list/name_to_material
icon_colour = "#EDD12F"
weight = 24
hardness = 40
conductivity = 41
stack_origin_tech = list(TECH_MATERIAL = 4)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
@@ -261,6 +265,7 @@ var/list/name_to_material
icon_colour = "#D1E6E3"
weight = 22
hardness = 50
conductivity = 63
stack_origin_tech = list(TECH_MATERIAL = 3)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
@@ -304,6 +309,8 @@ var/list/name_to_material
shard_type = SHARD_STONE_PIECE
weight = 22
hardness = 55
protectiveness = 5 // 20%
conductivity = 5
door_icon_base = "stone"
sheet_singular_name = "brick"
sheet_plural_name = "bricks"
@@ -320,6 +327,8 @@ var/list/name_to_material
name = DEFAULT_WALL_MATERIAL
stack_type = /obj/item/stack/material/steel
integrity = 150
conductivity = 11 // Assuming this is carbon steel, it would actually be slightly less conductive than iron, but lets ignore that.
protectiveness = 10 // 33%
icon_base = "solid"
icon_reinf = "reinf_over"
icon_colour = "#666666"
@@ -355,6 +364,8 @@ var/list/name_to_material
explosion_resistance = 25
hardness = 80
weight = 23
protectiveness = 20 // 50%
conductivity = 13 // For the purposes of balance.
stack_origin_tech = list(TECH_MATERIAL = 2)
composite_material = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT, "platinum" = SHEET_MATERIAL_AMOUNT) //todo
@@ -370,6 +381,7 @@ var/list/name_to_material
explosion_resistance = 75
hardness = 100
weight = 28
protectiveness = 60 // 75%
reflectivity = 0.7 // Not a perfect mirror, but close.
stack_origin_tech = list(TECH_MATERIAL = 8)
composite_material = list("plasteel" = SHEET_MATERIAL_AMOUNT, "diamond" = SHEET_MATERIAL_AMOUNT) //shrug
@@ -377,6 +389,7 @@ var/list/name_to_material
/material/plasteel/titanium
name = "titanium"
stack_type = null
conductivity = 2.38
icon_base = "metal"
door_icon_base = "metal"
icon_colour = "#D1E6E3"
@@ -393,6 +406,8 @@ var/list/name_to_material
tableslam_noise = 'sound/effects/Glasshit.ogg'
hardness = 30
weight = 15
protectiveness = 0 // 0%
conductivity = 1 // Glass shards don't conduct.
door_icon_base = "stone"
destruction_desc = "shatters"
window_options = list("One Direction" = 1, "Full Window" = 4, "Windoor" = 2)
@@ -483,7 +498,7 @@ var/list/name_to_material
tableslam_noise = 'sound/effects/Glasshit.ogg'
hardness = 40
weight = 30
stack_origin_tech = "materials=2"
stack_origin_tech = list(TECH_MATERIAL = 2)
composite_material = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT / 2, "glass" = SHEET_MATERIAL_AMOUNT)
window_options = list("One Direction" = 1, "Full Window" = 4, "Windoor" = 2)
created_window = /obj/structure/window/reinforced
@@ -526,6 +541,8 @@ var/list/name_to_material
icon_colour = "#CCCCCC"
hardness = 10
weight = 12
protectiveness = 5 // 20%
conductivity = 2 // For the sake of material armor diversity, we're gonna pretend this plastic is a good insulator.
melting_point = T0C+371 //assuming heat resistant plastic
stack_origin_tech = list(TECH_MATERIAL = 3)
@@ -556,12 +573,14 @@ var/list/name_to_material
stack_type = /obj/item/stack/material/mhydrogen
icon_colour = "#E6C5DE"
stack_origin_tech = list(TECH_MATERIAL = 6, TECH_POWER = 6, TECH_MAGNET = 5)
conductivity = 100
/material/platinum
name = "platinum"
stack_type = /obj/item/stack/material/platinum
icon_colour = "#9999FF"
weight = 27
conductivity = 9.43
stack_origin_tech = list(TECH_MATERIAL = 2)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
@@ -571,6 +590,7 @@ var/list/name_to_material
stack_type = /obj/item/stack/material/iron
icon_colour = "#5C5454"
weight = 22
conductivity = 10
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
@@ -585,6 +605,7 @@ var/list/name_to_material
explosion_resistance = 200 // Hull plating.
hardness = 500
weight = 500
protectiveness = 80 // 80%
// Likewise.
/material/alienalloy/elevatorium
@@ -603,6 +624,8 @@ var/list/name_to_material
shard_can_repair = 0 // you can't weld splinters back into planks
hardness = 15
weight = 18
protectiveness = 8 // 28%
conductivity = 1
melting_point = T0C+300 //okay, not melting in this case, but hot enough to destroy wood
ignition_point = T0C+288
stack_origin_tech = list(TECH_MATERIAL = 1, TECH_BIO = 1)
@@ -634,6 +657,7 @@ var/list/name_to_material
icon_colour = "#AAAAAA"
hardness = 1
weight = 1
protectiveness = 0 // 0%
ignition_point = T0C+232 //"the temperature at which book-paper catches fire, and burns." close enough
melting_point = T0C+232 //temperature at which cardboard walls would be destroyed
stack_origin_tech = list(TECH_MATERIAL = 1)
@@ -650,6 +674,7 @@ var/list/name_to_material
integrity = 1
hardness = 1
weight = 1
protectiveness = 0 // 0%
stack_origin_tech = list(TECH_MATERIAL = 1)
melting_point = T0C+1
destruction_desc = "crumples"
@@ -662,6 +687,7 @@ var/list/name_to_material
door_icon_base = "wood"
ignition_point = T0C+232
melting_point = T0C+300
protectiveness = 1 // 4%
flags = MATERIAL_PADDING
/material/cult
@@ -695,6 +721,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+300
melting_point = T0C+300
protectiveness = 3 // 13%
/material/carpet
name = "carpet"
@@ -706,6 +733,7 @@ var/list/name_to_material
melting_point = T0C+300
sheet_singular_name = "tile"
sheet_plural_name = "tiles"
protectiveness = 1 // 4%
/material/cotton
name = "cotton"
@@ -714,7 +742,9 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
protectiveness = 1 // 4%
// This all needs to be OOP'd and use inheritence if its ever used in the future.
/material/cloth_teal
name = "teal"
display_name ="teal"
@@ -723,6 +753,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
protectiveness = 1 // 4%
/material/cloth_black
name = "black"
@@ -732,6 +763,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
protectiveness = 1 // 4%
/material/cloth_green
name = "green"
@@ -741,6 +773,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
protectiveness = 1 // 4%
/material/cloth_puple
name = "purple"
@@ -750,6 +783,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
protectiveness = 1 // 4%
/material/cloth_blue
name = "blue"
@@ -759,6 +793,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
protectiveness = 1 // 4%
/material/cloth_beige
name = "beige"
@@ -768,6 +803,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
protectiveness = 1 // 4%
/material/cloth_lime
name = "lime"
@@ -777,6 +813,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
protectiveness = 1 // 4%
/material/toy_foam
name = "foam"
@@ -787,4 +824,5 @@ var/list/name_to_material
melting_point = T0C+300
icon_colour = "#ff9900"
hardness = 1
weight = 1
weight = 1
protectiveness = 0 // 0%
+1 -1
View File
@@ -37,7 +37,7 @@
var/mob/living/carbon/human/H = hit_atom
if(istype(H) && H.has_eyes() && prob(85))
H << "<span class='danger'>Some of \the [src] gets in your eyes!</span>"
H.eye_blind += 5
H.Blind(5)
H.eye_blurry += 10
spawn(1)
if(istype(loc, /turf/)) qdel(src)
+2 -2
View File
@@ -212,7 +212,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set name = "Ghost"
set desc = "Relinquish your life and enter the land of the dead."
if(stat == DEAD)
if(stat == DEAD && !forbid_seeing_deadchat)
announce_ghost_joinleave(ghostize(1))
else
var/response
@@ -223,7 +223,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return
src.client.admin_ghost()
else
response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost, you won't be able to play this round for another 30 minutes! You can't change your mind so choose wisely!)", "Are you sure you want to ghost?", "Ghost", "Stay in body")
response = alert(src, "Are you -sure- you want to ghost?\n(You are alive, or otherwise have the potential to become alive. If you ghost, you won't be able to play this round until you respawn as a new character! You can't change your mind so choose wisely!)", "Are you sure you want to ghost?", "Ghost", "Stay in body")
if(response != "Ghost")
return
resting = 1
+1 -1
View File
@@ -101,7 +101,7 @@
/mob/living/silicon/ai/special_mentions()
return list("AI") // AI door!
// Converts specific characters, like *, |, and _ to formatted output.
// Converts specific characters, like +, |, and _ to formatted output.
/mob/proc/say_emphasis(var/message)
message = encode_html_emphasis(message, "|", "i")
message = encode_html_emphasis(message, "+", "b")
+2 -2
View File
@@ -24,7 +24,7 @@
/datum/language/unathi
name = LANGUAGE_UNATHI
desc = "The common language of Moghes, composed of sibilant hisses and rattles. Spoken natively by Unathi."
desc = "The common language of the Moghes Hegemony, composed of sibilant hisses and rattles. Spoken natively by Unathi."
speech_verb = "hisses"
ask_verb = "hisses"
exclaim_verb = "roars"
@@ -60,7 +60,7 @@
flags = WHITELISTED
syllables = list("mrr","rr","tajr","kir","raj","kii","mir","kra","ahk","nal","vah","khaz","jri","ran","darr",
"mi","jri","dynh","manq","rhe","zar","rrhaz","kal","chur","eech","thaa","dra","jurl","mah","sanu","dra","ii'r",
"ka","aasi","far","wa","baq","ara","qara","zir","sam","mak","hrar","nja","rir","khan","jun","dar","rik","kah",
"ka","aasi","far","wa","baq","ara","qara","zir","saam","mak","hrar","nja","rir","khan","jun","dar","rik","kah",
"hal","ket","jurl","mah","tul","cresh","azu","ragh","mro","mra","mrro","mrra")
/datum/language/tajaran/get_random_name(var/gender)
+5 -5
View File
@@ -70,10 +70,10 @@
/mob/living/bot/updatehealth()
if(status_flags & GODMODE)
health = maxHealth
health = getMaxHealth()
stat = CONSCIOUS
else
health = maxHealth - getFireLoss() - getBruteLoss()
health = getMaxHealth() - getFireLoss() - getBruteLoss()
oxyloss = 0
toxloss = 0
cloneloss = 0
@@ -104,9 +104,9 @@
user << "<span class='notice'>You need to unlock the controls first.</span>"
return
else if(istype(O, /obj/item/weapon/weldingtool))
if(health < maxHealth)
if(health < getMaxHealth())
if(open)
health = min(maxHealth, health + 10)
health = min(getMaxHealth(), health + 10)
user.visible_message("<span class='notice'>[user] repairs [src].</span>","<span class='notice'>You repair [src].</span>")
else
user << "<span class='notice'>Unable to repair with the maintenance panel closed.</span>"
@@ -224,7 +224,7 @@
/mob/living/bot/proc/getPatrolTurf()
var/minDist = INFINITY
var/obj/machinery/navbeacon/targ = locate() in get_turf(src)
if(!targ)
for(var/obj/machinery/navbeacon/N in navbeacons)
if(!N.codes["patrol"])
+2 -2
View File
@@ -73,11 +73,11 @@
// Eyes and blindness.
if(!has_eyes())
eye_blind = 1
SetBlinded(1)
blinded = 1
eye_blurry = 1
else if(eye_blind)
eye_blind = max(eye_blind-1,0)
AdjustBlinded(-1)
blinded = 1
else if(eye_blurry)
eye_blurry = max(eye_blurry-1, 0)
+3 -3
View File
@@ -76,7 +76,7 @@
if(ingested) ingested.metabolize()
if(bloodstr) bloodstr.metabolize()
confused = max(0, confused - 1)
AdjustConfused(-1)
// decrement dizziness counter, clamped to 0
if(resting)
dizziness = max(0, dizziness - 5)
@@ -110,7 +110,7 @@
if(31 to INFINITY)
emp_damage = 30//Let's not overdo it
if(21 to 30)//High level of EMP damage, unable to see, hear, or speak
eye_blind = 1
SetBlinded(1)
blinded = 1
ear_deaf = 1
silent = 1
@@ -123,7 +123,7 @@
if(20)
alert = 0
blinded = 0
eye_blind = 0
SetBlinded(0)
ear_deaf = 0
silent = 0
emp_damage -= 1
+3 -3
View File
@@ -1,11 +1,11 @@
/mob/living/carbon/human/verb/give(var/mob/living/target in view(1)-usr)
/mob/living/carbon/human/verb/give(var/mob/living/carbon/target in view(1)-usr)
set category = "IC"
set name = "Give"
// TODO : Change to incapacitated() on merge.
if(src.stat || src.lying || src.resting || src.buckled)
if(src.stat || src.lying || src.resting || src.handcuffed)
return
if(!istype(target) || target.stat || target.lying || target.resting || target.buckled || target.client == null)
if(!istype(target) || target.stat || target.lying || target.resting || target.handcuffed || target.client == null)
return
var/obj/item/I = src.get_active_hand()
@@ -41,6 +41,13 @@
species.handle_death(src)
animate_tail_stop()
//Handle snowflake ling stuff.
if(mind && mind.changeling)
// If the ling is capable of revival, don't allow them to see deadchat.
if(mind.changeling.chem_charges >= CHANGELING_STASIS_COST)
if(mind.changeling.max_geneticpoints >= 0) // Absorbed lings don't count, as they can't revive.
forbid_seeing_deadchat = TRUE
//Handle brain slugs.
var/obj/item/organ/external/Hd = get_organ(BP_HEAD)
var/mob/living/simple_animal/borer/B
@@ -88,6 +88,7 @@
if(mind.changeling)
stat("Chemical Storage", mind.changeling.chem_charges)
stat("Genetic Damage Time", mind.changeling.geneticdamage)
stat("Re-Adaptations", "[mind.changeling.readapts]/[mind.changeling.max_readapts]")
/mob/living/carbon/human/ex_act(severity)
if(!blinded)
@@ -1496,3 +1497,11 @@
/mob/living/carbon/human/is_muzzled()
return (wear_mask && (istype(wear_mask, /obj/item/clothing/mask/muzzle) || istype(src.wear_mask, /obj/item/weapon/grenade)))
// Called by job_controller. Makes drones start with a permit, might be useful for other people later too.
/mob/living/carbon/human/equip_post_job()
var/braintype = get_FBP_type()
if(braintype == FBP_DRONE)
var/turf/T = get_turf(src)
var/obj/item/weapon/permit/drone/permit = new(T)
permit.set_name(real_name)
equip_to_appropriate_slot(permit) // If for some reason it can't find room, it'll still be on the floor.
@@ -2,7 +2,7 @@
/mob/living/carbon/human/updatehealth()
if(status_flags & GODMODE)
health = maxHealth
health = getMaxHealth()
stat = CONSCIOUS
return
@@ -14,10 +14,10 @@
total_brute += O.brute_dam
total_burn += O.burn_dam
health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
health = getMaxHealth() - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
//TODO: fix husking
if( ((maxHealth - total_burn) < config.health_threshold_dead) && stat == DEAD)
if( ((getMaxHealth() - total_burn) < config.health_threshold_dead) && stat == DEAD)
ChangeToHusk()
return
@@ -42,7 +42,7 @@
if(should_have_organ("brain"))
var/obj/item/organ/internal/brain/sponge = internal_organs_by_name["brain"]
if(sponge)
sponge.damage = min(max(amount, 0),(maxHealth*2))
sponge.damage = min(max(amount, 0),(getMaxHealth()*2))
brainloss = sponge.damage
else
brainloss = 200
@@ -56,7 +56,7 @@
if(should_have_organ("brain"))
var/obj/item/organ/internal/brain/sponge = internal_organs_by_name["brain"]
if(sponge)
brainloss = min(sponge.damage,maxHealth*2)
brainloss = min(sponge.damage,getMaxHealth()*2)
else
brainloss = 200
else
@@ -99,16 +99,32 @@
/mob/living/carbon/human/adjustBruteLoss(var/amount)
amount = amount*species.brute_mod
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
amount *= M.incoming_damage_percent
if(!isnull(M.incoming_brute_damage_percent))
amount *= M.incoming_brute_damage_percent
take_overall_damage(amount, 0)
else
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
amount *= M.incoming_healing_percent
heal_overall_damage(-amount, 0)
BITSET(hud_updateflag, HEALTH_HUD)
/mob/living/carbon/human/adjustFireLoss(var/amount)
amount = amount*species.burn_mod
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
amount *= M.incoming_damage_percent
if(!isnull(M.incoming_fire_damage_percent))
amount *= M.incoming_fire_damage_percent
take_overall_damage(0, amount)
else
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
amount *= M.incoming_healing_percent
heal_overall_damage(0, -amount)
BITSET(hud_updateflag, HEALTH_HUD)
@@ -118,8 +134,16 @@
var/obj/item/organ/external/O = get_organ(organ_name)
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
amount *= M.incoming_damage_percent
if(!isnull(M.incoming_brute_damage_percent))
amount *= M.incoming_brute_damage_percent
O.take_damage(amount, 0, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source)
else
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
amount *= M.incoming_healing_percent
//if you don't want to heal robot organs, they you will have to check that yourself before using this proc.
O.heal_damage(-amount, 0, internal=0, robo_repair=(O.robotic >= ORGAN_ROBOT))
@@ -131,8 +155,16 @@
var/obj/item/organ/external/O = get_organ(organ_name)
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
amount *= M.incoming_damage_percent
if(!isnull(M.incoming_fire_damage_percent))
amount *= M.incoming_fire_damage_percent
O.take_damage(0, amount, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source)
else
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
amount *= M.incoming_healing_percent
//if you don't want to heal robot organs, they you will have to check that yourself before using this proc.
O.heal_damage(0, -amount, internal=0, robo_repair=(O.robotic >= ORGAN_ROBOT))
@@ -153,6 +185,26 @@
wearing_rig.notify_ai("<span class='danger'>Warning: user consciousness failure. Mobility control passed to integrated intelligence system.</span>")
..()
/mob/living/carbon/human/proc/Stasis(amount)
if((species.flags & NO_SCAN) || isSynthetic())
in_stasis = 0
else
in_stasis = amount
/mob/living/carbon/human/proc/getStasis()
if((species.flags & NO_SCAN) || isSynthetic())
return 0
return in_stasis
//This determines if, RIGHT NOW, the life() tick is being skipped due to stasis
/mob/living/carbon/human/proc/inStasisNow()
var/stasisValue = getStasis()
if(stasisValue && (life_tick % stasisValue))
return 1
return 0
/mob/living/carbon/human/getCloneLoss()
if((species.flags & NO_SCAN) || isSynthetic())
cloneloss = 0
@@ -400,11 +452,25 @@ This function restores all organs.
if(BRUTE)
damageoverlaytemp = 20
damage = damage*species.brute_mod
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
damage *= M.incoming_damage_percent
if(!isnull(M.incoming_brute_damage_percent))
damage *= M.incoming_brute_damage_percent
if(organ.take_damage(damage, 0, sharp, edge, used_weapon))
UpdateDamageIcon()
if(BURN)
damageoverlaytemp = 20
damage = damage*species.burn_mod
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
damage *= M.incoming_damage_percent
if(!isnull(M.incoming_brute_damage_percent))
damage *= M.incoming_fire_damage_percent
if(organ.take_damage(0, damage, sharp, edge, used_weapon))
UpdateDamageIcon()
@@ -27,6 +27,11 @@ emp_act
if(!P.nodamage)
organ.add_autopsy_data("[P.name]", P.damage)
// Tell clothing we're wearing that it got hit by a bullet/laser/etc
var/list/clothing = get_clothing_list_organ(organ)
for(var/obj/item/clothing/C in clothing)
C.clothing_impact(P, P.damage)
//Shrapnel
if(P.can_embed())
var/armor = getarmor_organ(organ, "bullet")
@@ -130,6 +135,15 @@ emp_act
return siemens_coefficient
// Returns a list of clothing that is currently covering def_zone.
/mob/living/carbon/human/proc/get_clothing_list_organ(var/obj/item/organ/external/def_zone, var/type)
var/list/results = list()
var/list/clothing_items = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes)
for(var/obj/item/clothing/C in clothing_items)
if(istype(C) && (C.body_parts_covered & def_zone.body_part))
results.Add(C)
return results
//this proc returns the armour value for a particular external organ.
/mob/living/carbon/human/proc/getarmor_organ(var/obj/item/organ/external/def_zone, var/type)
if(!type || !def_zone) return 0
@@ -231,10 +245,6 @@ emp_act
var/soaked = get_armor_soak(hit_zone, "melee", I.armor_penetration)
if(soaked >= effective_force)
src << "Your armor absorbs the force of [I.name]!"
return
var/blocked = run_armor_check(hit_zone, "melee", I.armor_penetration, "Your armor has protected your [affecting.name].", "Your armor has softened the blow to your [affecting.name].")
standard_weapon_hit_effects(I, user, effective_force, blocked, soaked, hit_zone)
@@ -246,9 +256,14 @@ emp_act
if(!affecting)
return 0
if(soaked >= effective_force)
return 0
// Allow clothing to respond to being hit.
// This is done up here so that clothing damage occurs even if fully blocked.
var/list/clothing = get_clothing_list_organ(affecting)
for(var/obj/item/clothing/C in clothing)
C.clothing_impact(I, effective_force)
if(soaked >= round(effective_force*0.8))
effective_force -= round(effective_force*0.8)
// Handle striking to cripple.
if(user.a_intent == I_DISARM)
effective_force *= 0.5 //reduced effective force...
@@ -309,12 +324,15 @@ emp_act
return 1
/mob/living/carbon/human/proc/attack_joint(var/obj/item/organ/external/organ, var/obj/item/W, var/effective_force, var/dislocate_mult, var/blocked, var/soaked)
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 100 || soaked > effective_force)
if(!organ || (organ.dislocated == 2) || (organ.dislocated == -1) || blocked >= 100)
return 0
if(W.damtype != BRUTE)
return 0
if(soaked >= round(effective_force*0.8))
effective_force -= round(effective_force*0.8)
//want the dislocation chance to be such that the limb is expected to dislocate after dealing a fraction of the damage needed to break the limb
var/dislocate_chance = effective_force/(dislocate_mult * organ.min_broken_damage * config.organ_health_multiplier)*100
if(prob(dislocate_chance * (100 - blocked)/100))
@@ -93,3 +93,5 @@
mob_swap_flags = ~HEAVY
var/identifying_gender // In case the human identifies as another gender than it's biological
var/step_count = 0 // Track how many footsteps have been taken to know when to play footstep sounds
@@ -90,6 +90,24 @@
return 0
// Returns a string based on what kind of brain the FBP has.
/mob/living/carbon/human/proc/get_FBP_type()
if(!isSynthetic())
return FBP_NONE
var/obj/item/organ/internal/brain/B
B = internal_organs_by_name[O_BRAIN]
if(B) // Incase we lost our brain for some reason, like if we got decapped.
if(istype(B, /obj/item/organ/internal/mmi_holder))
var/obj/item/organ/internal/mmi_holder/mmi_holder = B
if(istype(mmi_holder.stored_mmi, /obj/item/device/mmi/digital/posibrain))
return FBP_POSI
else if(istype(mmi_holder.stored_mmi, /obj/item/device/mmi/digital/robot))
return FBP_DRONE
else if(istype(mmi_holder.stored_mmi, /obj/item/device/mmi)) // This needs to come last because inheritence.
return FBP_CYBORG
return FBP_NONE
#undef HUMAN_EATING_NO_ISSUE
#undef HUMAN_EATING_NO_MOUTH
#undef HUMAN_EATING_BLOCKED_MOUTH
@@ -13,9 +13,15 @@
handle_embedded_objects() //Moving with objects stuck in you can cause bad times.
if(force_max_speed)
return -3 // Returning -1 will actually result in a slowdown for Teshari.
return -3
var/health_deficiency = (maxHealth - health)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.haste) && M.haste == TRUE)
return -3 // Returning -1 will actually result in a slowdown for Teshari.
if(!isnull(M.slowdown))
tally += M.slowdown
var/health_deficiency = (getMaxHealth() - health)
if(health_deficiency >= 40) tally += (health_deficiency / 25)
if(can_feel_pain())
@@ -80,9 +86,7 @@
if(T && T.movement_cost)
tally += T.movement_cost
if(species.item_slowdown_halved)
if(item_tally > 0)
item_tally *= 0.5
item_tally *= species.item_slowdown_mod
tally += item_tally
@@ -140,3 +144,36 @@
prob_slip = round(prob_slip)
return(prob_slip)
// Handle footstep sounds
/mob/living/carbon/human/handle_footstep(var/turf/T)
if(!config.footstep_volume || !T.footstep_sounds || !T.footstep_sounds.len)
return
// Future Upgrades - Multi species support
var/list/footstep_sounds = T.footstep_sounds["human"]
if(!footstep_sounds)
return
var/S = pick(footstep_sounds)
if(!S) return
// Only play every other step while running
if(m_intent == "run" && step_count++ % 2 == 0)
return
var/volume = config.footstep_volume
// Reduce volume while walking or barefoot
if(!shoes || m_intent != "run")
volume *= 0.5
if(!has_organ(BP_L_FOOT) && !has_organ(BP_R_FOOT))
return // no feet = no footsteps
if(buckled || lying || throwing)
return // people flying, lying down or sitting do not step
if(!has_gravity(src) && prob(75))
return // Far less likely to make noise in no gravity
playsound(T, S, volume, FALSE)
return
+13 -10
View File
@@ -62,8 +62,12 @@
voice = GetVoice()
var/stasis = inStasisNow()
if(getStasis() > 2)
Sleeping(20)
//No need to update all of these procs if the guy is dead.
if(stat != DEAD && !in_stasis)
if(stat != DEAD && !stasis)
//Updates the number of stored chemicals for powers
handle_changeling()
@@ -82,7 +86,6 @@
if(!client)
species.handle_npc(src)
if(!handle_some_updates())
return //We go ahead and process them 5 times for HUD images and other stuff though.
@@ -97,7 +100,7 @@
return 1
/mob/living/carbon/human/breathe()
if(!in_stasis)
if(!inStasisNow())
..()
// Calculate how vulnerable the human is to under- and overpressure.
@@ -207,7 +210,7 @@
/mob/living/carbon/human/handle_mutations_and_radiation()
if(in_stasis)
if(inStasisNow())
return
if(getFireLoss())
@@ -789,7 +792,7 @@
/mob/living/carbon/human/handle_chemicals_in_body()
if(in_stasis)
if(inStasisNow())
return
if(reagents)
@@ -971,18 +974,18 @@
vision = internal_organs_by_name[species.vision_organ]
if(!species.vision_organ) // Presumably if a species has no vision organs, they see via some other means.
eye_blind = 0
SetBlinded(0)
blinded = 0
eye_blurry = 0
else if(!vision || vision.is_broken()) // Vision organs cut out or broken? Permablind.
eye_blind = 1
SetBlinded(1)
blinded = 1
eye_blurry = 1
else //You have the requisite organs
if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own
blinded = 1
else if(eye_blind) // Blindness, heals slowly over time
eye_blind = max(eye_blind-1,0)
AdjustBlinded(-1)
blinded = 1
else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster
eye_blurry = max(eye_blurry-3, 0)
@@ -1339,7 +1342,7 @@
if(!druggy && !seer) see_invisible = SEE_INVISIBLE_LIVING
/mob/living/carbon/human/handle_random_events()
if(in_stasis)
if(inStasisNow())
return
// Puke if toxloss is too high
@@ -1536,7 +1539,7 @@
if(stat == DEAD)
holder.icon_state = "-100" // X_X
else
holder.icon_state = RoundHealth((health-config.health_threshold_crit)/(maxHealth-config.health_threshold_crit)*100)
holder.icon_state = RoundHealth((health-config.health_threshold_crit)/(getMaxHealth()-config.health_threshold_crit)*100)
hud_list[HEALTH_HUD] = holder
if (BITTEST(hud_updateflag, LIFE_HUD))
@@ -133,7 +133,7 @@
var/appearance_flags = 0 // Appearance/display related features.
var/spawn_flags = 0 // Flags that specify who can spawn as this species
var/slowdown = 0 // Passive movement speed malus (or boost, if negative)
var/item_slowdown_halved = 0 // If this is on, they're not as affected by item weights for slowdown
var/item_slowdown_mod = 1 // How affected by item slowdown the species is.
var/primitive_form // Lesser form, if any (ie. monkey for humans)
var/greater_form // Greater form, if any, ie. human for monkeys.
var/holder_type
@@ -34,19 +34,21 @@
ambiguous_genders = TRUE
gluttonous = 1
slowdown = 0.5
brute_mod = 0.9
burn_mod = 0.9
brute_mod = 0.85
burn_mod = 0.85
metabolic_rate = 0.85
item_slowdown_mod = 0.5
num_alternate_languages = 3
secondary_langs = list(LANGUAGE_UNATHI)
name_language = LANGUAGE_UNATHI
health_hud_intensity = 2.5
min_age = 18
max_age = 60
min_age = 32
max_age = 260
blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \
Uuosa-Eso system, which roughly translates to 'burning mother'.<br/><br/>Coming from a harsh, radioactive \
desert planet, they mostly hold ideals of honesty, virtue, martial combat and bravery above all \
Uuosa-Eso system, which roughly translates to 'burning mother'.<br/><br/>Coming from a harsh, inhospitable \
planet, they mostly hold ideals of honesty, virtue, proficiency and bravery above all \
else, frequently even their own lives. They prefer warmer temperatures than most species and \
their native tongue is a heavy hissing laungage called Sinta'Unathi."
@@ -62,9 +64,34 @@
appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR
flesh_color = "#34AF10"
blood_color = "#b3cbc3"
base_color = "#066000"
reagent_tag = IS_UNATHI
base_color = "#066000"
has_limbs = list(
BP_TORSO = list("path" = /obj/item/organ/external/chest/unathi),
BP_GROIN = list("path" = /obj/item/organ/external/groin/unathi),
BP_HEAD = list("path" = /obj/item/organ/external/head/unathi),
BP_L_ARM = list("path" = /obj/item/organ/external/arm),
BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
BP_L_LEG = list("path" = /obj/item/organ/external/leg),
BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
BP_L_HAND = list("path" = /obj/item/organ/external/hand),
BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right)
)
//No kidneys or appendix
has_organ = list(
O_HEART = /obj/item/organ/internal/heart/unathi,
O_LUNGS = /obj/item/organ/internal/lungs/unathi,
O_LIVER = /obj/item/organ/internal/liver/unathi,
O_BRAIN = /obj/item/organ/internal/brain/unathi,
O_EYES = /obj/item/organ/internal/eyes,
)
heat_discomfort_level = 295
heat_discomfort_strings = list(
@@ -229,6 +256,7 @@
secondary_langs = list(LANGUAGE_ROOTGLOBAL)
name_language = LANGUAGE_ROOTLOCAL
health_hud_intensity = 2.5
item_slowdown_mod = 0.25
min_age = 1
max_age = 300
@@ -131,10 +131,11 @@ Please contact me on #coderbus IRC. ~Carn x
#define LEGCUFF_LAYER 23
#define L_HAND_LAYER 24
#define R_HAND_LAYER 25
#define FIRE_LAYER 26 //If you're on fire
#define WATER_LAYER 27 //If you're submerged in water.
#define TARGETED_LAYER 28 //BS12: Layer for the target overlay from weapon targeting system
#define TOTAL_LAYERS 29
#define MODIFIER_EFFECTS_LAYER 26
#define FIRE_LAYER 27 //If you're on fire
#define WATER_LAYER 28 //If you're submerged in water.
#define TARGETED_LAYER 29 //BS12: Layer for the target overlay from weapon targeting system
#define TOTAL_LAYERS 30
//////////////////////////////////
/mob/living/carbon/human
@@ -1118,6 +1119,18 @@ var/global/list/damage_icon_parts = list()
if(update_icons) update_icons()
/mob/living/carbon/human/update_modifier_visuals(var/update_icons=1)
overlays_standing[MODIFIER_EFFECTS_LAYER] = null
var/image/effects = new()
for(var/datum/modifier/M in modifiers)
if(M.mob_overlay_state)
var/image/I = image("icon" = 'icons/mob/modifier_effects.dmi', "icon_state" = M.mob_overlay_state)
effects.overlays += I
overlays_standing[MODIFIER_EFFECTS_LAYER] = effects
if(update_icons)
update_icons()
/mob/living/carbon/human/update_fire(var/update_icons=1)
overlays_standing[FIRE_LAYER] = null
@@ -80,7 +80,7 @@
src.blinded = null
health = maxHealth - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
health = getMaxHealth() - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
if(health < 0 && stat != DEAD)
death()
@@ -118,7 +118,7 @@
if (src.stuttering) src.stuttering = 0
if (src.eye_blind)
src.eye_blind = 0
SetBlinded(0)
src.blinded = 1
if (src.ear_deaf > 0) src.ear_deaf = 0
@@ -81,7 +81,7 @@
var/tally = 0
var/health_deficiency = (maxHealth - health)
var/health_deficiency = (getMaxHealth() - health)
if(health_deficiency >= 30) tally += (health_deficiency / 25)
if (bodytemperature < 183.222)
@@ -146,7 +146,7 @@
..()
statpanel("Status")
stat(null, "Health: [round((health / maxHealth) * 100)]%")
stat(null, "Health: [round((health / getMaxHealth()) * 100)]%")
stat(null, "Intent: [a_intent]")
if (client.statpanel == "Status")
@@ -21,7 +21,7 @@
return "I cannot feed on other slimes..."
if (!Adjacent(M))
return "This subject is too far away..."
if (istype(M, /mob/living/carbon) && M.getCloneLoss() >= M.maxHealth * 1.5 || istype(M, /mob/living/simple_animal) && M.stat == DEAD)
if (istype(M, /mob/living/carbon) && M.getCloneLoss() >= M.getMaxHealth() * 1.5 || istype(M, /mob/living/simple_animal) && M.stat == DEAD)
return "This subject does not have an edible life energy..."
for(var/mob/living/carbon/slime/met in view())
if(met.Victim == M && met != src)
+5 -2
View File
@@ -11,10 +11,13 @@
/mob/living/proc/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/soaked = 0, var/used_weapon = null, var/sharp = 0, var/edge = 0)
if(Debug2)
world.log << "## DEBUG: apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked]."
if(!damage || (blocked >= 100) || soaked >= damage)
if(!damage || (blocked >= 100))
return 0
if(soaked)
damage -= soaked
if(soaked >= round(damage*0.8))
damage -= round(damage*0.8)
else
damage -= soaked
blocked = (100-blocked)/100
switch(damagetype)
if(BRUTE)
+4 -2
View File
@@ -10,6 +10,8 @@
return
var/datum/gas_mixture/environment = loc.return_air()
handle_modifiers() // Do this early since it might affect other things later.
if(stat != DEAD)
//Breathing, if applicable
handle_breathing()
@@ -148,9 +150,9 @@
/mob/living/proc/handle_disabilities()
//Eyes
if(sdisabilities & BLIND || stat) //blindness from disability or unconsciousness doesn't get better on its own
eye_blind = max(eye_blind, 1)
SetBlinded(1)
else if(eye_blind) //blindness, heals slowly over time
eye_blind = max(eye_blind-1,0)
AdjustBlinded(-1)
else if(eye_blurry) //blurry eyes heal slowly
eye_blurry = max(eye_blurry-1, 0)
+183 -13
View File
@@ -150,9 +150,9 @@ default behaviour is:
/mob/living/verb/succumb()
set hidden = 1
if ((src.health < 0 && src.health > (5-src.maxHealth))) // Health below Zero but above 5-away-from-death, as before, but variable
src.adjustOxyLoss(src.health + src.maxHealth * 2) // Deal 2x health in OxyLoss damage, as before but variable.
src.health = src.maxHealth - src.getOxyLoss() - src.getToxLoss() - src.getFireLoss() - src.getBruteLoss()
if ((src.health < 0 && src.health > (5-src.getMaxHealth()))) // Health below Zero but above 5-away-from-death, as before, but variable
src.adjustOxyLoss(src.health + src.getMaxHealth() * 2) // Deal 2x health in OxyLoss damage, as before but variable.
src.health = src.getMaxHealth() - src.getOxyLoss() - src.getToxLoss() - src.getFireLoss() - src.getBruteLoss()
src << "\blue You have given up life and succumbed to death."
@@ -161,7 +161,7 @@ default behaviour is:
health = 100
stat = CONSCIOUS
else
health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() - halloss
health = getMaxHealth() - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() - halloss
//This proc is used for mobs which are affected by pressure to calculate the amount of pressure that actually
@@ -223,14 +223,38 @@ default behaviour is:
/mob/living/proc/adjustBruteLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
bruteloss = min(max(bruteloss + amount, 0),(maxHealth*2))
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
amount *= M.incoming_damage_percent
if(!isnull(M.incoming_brute_damage_percent))
amount *= M.incoming_brute_damage_percent
else if(amount < 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
amount *= M.incoming_healing_percent
bruteloss = min(max(bruteloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/getOxyLoss()
return oxyloss
/mob/living/proc/adjustOxyLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
oxyloss = min(max(oxyloss + amount, 0),(maxHealth*2))
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
amount *= M.incoming_damage_percent
if(!isnull(M.incoming_oxy_damage_percent))
amount *= M.incoming_oxy_damage_percent
else if(amount < 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
amount *= M.incoming_healing_percent
oxyloss = min(max(oxyloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/setOxyLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
@@ -241,7 +265,19 @@ default behaviour is:
/mob/living/proc/adjustToxLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
toxloss = min(max(toxloss + amount, 0),(maxHealth*2))
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
amount *= M.incoming_damage_percent
if(!isnull(M.incoming_tox_damage_percent))
amount *= M.incoming_tox_damage_percent
else if(amount < 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
amount *= M.incoming_healing_percent
toxloss = min(max(toxloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/setToxLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
@@ -255,14 +291,37 @@ default behaviour is:
/mob/living/proc/adjustFireLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
fireloss = min(max(fireloss + amount, 0),(maxHealth*2))
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
amount *= M.incoming_damage_percent
if(!isnull(M.incoming_fire_damage_percent))
amount *= M.incoming_fire_damage_percent
else if(amount < 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
amount *= M.incoming_healing_percent
fireloss = min(max(fireloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/getCloneLoss()
return cloneloss
/mob/living/proc/adjustCloneLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
cloneloss = min(max(cloneloss + amount, 0),(maxHealth*2))
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
amount *= M.incoming_damage_percent
if(!isnull(M.incoming_clone_damage_percent))
amount *= M.incoming_clone_damage_percent
else if(amount < 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
amount *= M.incoming_healing_percent
cloneloss = min(max(cloneloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/setCloneLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
@@ -273,7 +332,7 @@ default behaviour is:
/mob/living/proc/adjustBrainLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
brainloss = min(max(brainloss + amount, 0),(maxHealth*2))
brainloss = min(max(brainloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/setBrainLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
@@ -284,18 +343,117 @@ default behaviour is:
/mob/living/proc/adjustHalLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
halloss = min(max(halloss + amount, 0),(maxHealth*2))
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_damage_percent))
amount *= M.incoming_damage_percent
if(!isnull(M.incoming_hal_damage_percent))
amount *= M.incoming_hal_damage_percent
if(!isnull(M.disable_duration_percent))
amount *= M.incoming_hal_damage_percent
else if(amount < 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.incoming_healing_percent))
amount *= M.incoming_healing_percent
halloss = min(max(halloss + amount, 0),(getMaxHealth()*2))
/mob/living/proc/setHalLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
halloss = amount
// Use this to get a mob's max health whenever possible. Reading maxHealth directly will give inaccurate results if any modifiers exist.
/mob/living/proc/getMaxHealth()
return maxHealth
var/result = maxHealth
for(var/datum/modifier/M in modifiers)
if(!isnull(M.max_health_flat))
result += M.max_health_flat
// Second loop is so we can get all the flat adjustments first before multiplying, otherwise the result will be different.
for(var/datum/modifier/M in modifiers)
if(!isnull(M.max_health_percent))
result *= M.max_health_percent
return result
/mob/living/proc/setMaxHealth(var/newMaxHealth)
maxHealth = newMaxHealth
/mob/living/Stun(amount)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
/mob/living/AdjustStunned(amount)
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
/mob/living/Weaken(amount)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
/mob/living/AdjustWeakened(amount)
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
/mob/living/Paralyse(amount)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
/mob/living/AdjustParalysis(amount)
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
/mob/living/Sleeping(amount)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
/mob/living/AdjustSleeping(amount)
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
/mob/living/Confuse(amount)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
/mob/living/AdjustConfused(amount)
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
/mob/living/Blind(amount)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
/mob/living/AdjustBlinded(amount)
if(amount > 0)
for(var/datum/modifier/M in modifiers)
if(!isnull(M.disable_duration_percent))
amount = round(amount * M.disable_duration_percent)
..(amount)
// ++++ROCKDTBEN++++ MOB PROCS //END
/mob/proc/get_contents()
@@ -433,7 +591,7 @@ default behaviour is:
// fix blindness and deafness
blinded = 0
eye_blind = 0
SetBlinded(0)
eye_blurry = 0
ear_deaf = 0
ear_damage = 0
@@ -570,6 +728,9 @@ default behaviour is:
for(var/mob/living/carbon/slime/M in view(1,src))
M.UpdateFeed(src)
/mob/living/proc/handle_footstep(turf/T)
return FALSE
/mob/living/verb/resist()
set name = "Resist"
set category = "IC"
@@ -797,6 +958,11 @@ default behaviour is:
update_icons()
return canmove
// Adds overlays for specific modifiers.
// You'll have to add your own implementation for non-humans currently, just override this proc.
/mob/living/proc/update_modifier_visuals()
return
/mob/living/proc/update_water() // Involves overlays for humans. Maybe we'll get submerged sprites for borgs in the future?
return
@@ -804,3 +970,7 @@ default behaviour is:
if(isSynthetic())
return FALSE
return TRUE
// Called by job_controller.
/mob/living/proc/equip_post_job()
return
+23 -11
View File
@@ -107,6 +107,11 @@
var/absorb = run_armor_check(def_zone, P.check_armour, P.armor_penetration)
var/proj_sharp = is_sharp(P)
var/proj_edge = has_edge(P)
if ((proj_sharp || proj_edge) && (soaked >= round(P.damage*0.8)))
proj_sharp = 0
proj_edge = 0
if ((proj_sharp || proj_edge) && prob(getarmor(def_zone, P.check_armour)))
proj_sharp = 0
proj_edge = 0
@@ -167,13 +172,11 @@
var/soaked = get_armor_soak(hit_zone, "melee")
var/blocked = run_armor_check(hit_zone, "melee")
//If the armor absorbs all of the damage, skip the damage calculation and the blood
if(!(soaked > effective_force))
standard_weapon_hit_effects(I, user, effective_force, blocked, soaked, hit_zone)
standard_weapon_hit_effects(I, user, effective_force, blocked, soaked, hit_zone)
if(I.damtype == BRUTE && prob(33)) // Added blood for whacking non-humans too
var/turf/simulated/location = get_turf(src)
if(istype(location)) location.add_blood_floor(src)
if(I.damtype == BRUTE && prob(33)) // Added blood for whacking non-humans too
var/turf/simulated/location = get_turf(src)
if(istype(location)) location.add_blood_floor(src)
return blocked
@@ -186,13 +189,14 @@
if(HULK in user.mutations)
effective_force *= 2
//Armor soak
if(soaked >= effective_force)
return 0
//Apply weapon damage
var/weapon_sharp = is_sharp(I)
var/weapon_edge = has_edge(I)
if(getsoak(hit_zone, "melee",) - (I.armor_penetration/5) > round(effective_force*0.8)) //soaking a hit turns sharp attacks into blunt ones
weapon_sharp = 0
weapon_edge = 0
if(prob(max(getarmor(hit_zone, "melee") - I.armor_penetration, 0))) //melee armour provides a chance to turn sharp/edge weapon attacks into blunt ones
weapon_sharp = 0
weapon_edge = 0
@@ -251,7 +255,7 @@
if(!O || !src) return
if(O.sharp) //Projectile is suitable for pinning.
if(soaked >= throw_damage) //Don't embed if it didn't actually damage
if(soaked >= round(throw_damage*0.8))
return
//Handles embedding for non-humans and simple_animals.
@@ -435,3 +439,11 @@
hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1)
//hud_used.SetButtonCoords(hud_used.hide_actions_toggle,button_number+1)
client.screen += hud_used.hide_actions_toggle
// Returns a number to determine if something is harder or easier to hit than normal.
/mob/living/proc/get_evasion()
var/result = evasion // First we get the 'base' evasion. Generally this is zero.
for(var/datum/modifier/M in modifiers)
if(!isnull(M.evasion))
result += M.evasion
return result
+1 -1
View File
@@ -2,7 +2,7 @@
see_invisible = SEE_INVISIBLE_LIVING
//Health and life related vars
var/maxHealth = 100 //Maximum health that should be possible.
var/maxHealth = 100 //Maximum health that should be possible. Avoid adjusting this if you can, and instead use modifiers datums.
var/health = 100 //A mob's health
var/hud_updateflag = 0
+2 -2
View File
@@ -141,7 +141,7 @@ proc/get_radio_key_from_channel(var/channel)
//Redirect to say_dead if talker is dead
if(stat)
if(stat == DEAD)
if(stat == DEAD && !forbid_seeing_deadchat)
return say_dead(message)
return
@@ -308,7 +308,7 @@ proc/get_radio_key_from_channel(var/channel)
if(M && src) //If we still exist, when the spawn processes
var/dst = get_dist(get_turf(M),get_turf(src))
if(dst <= message_range || M.stat == DEAD) //Inside normal message range, or dead with ears (handled in the view proc)
if(dst <= message_range || (M.stat == DEAD && !forbid_seeing_deadchat)) //Inside normal message range, or dead with ears (handled in the view proc)
M << speech_bubble
M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol)
@@ -1,7 +1,6 @@
/obj/machinery/computer/drone_control
name = "Maintenance Drone Control"
desc = "Used to monitor the station's drone population and the assembler that services them."
icon = 'icons/obj/computer.dmi'
icon_keyboard = "power_key"
icon_screen = "power"
req_access = list(access_engine_equip)
@@ -98,7 +98,7 @@
else //Not stunned.
src.stat = 0
confused = max(0, confused - 1)
AdjustConfused(-1)
else //Dead.
src.blinded = 1
@@ -107,7 +107,7 @@
if (src.stuttering) src.stuttering--
if (src.eye_blind)
src.eye_blind--
src.AdjustBlinded(-1)
src.blinded = 1
if (src.ear_deaf > 0) src.ear_deaf--
@@ -1,9 +1,9 @@
/mob/living/silicon/robot/updatehealth()
if(status_flags & GODMODE)
health = maxHealth
health = getMaxHealth()
stat = CONSCIOUS
return
health = maxHealth - (getBruteLoss() + getFireLoss())
health = getMaxHealth() - (getBruteLoss() + getFireLoss())
return
/mob/living/silicon/robot/getBruteLoss()
+5 -5
View File
@@ -63,16 +63,16 @@
switch(severity)
if(1)
src.take_organ_damage(0,20,emp=1)
confused = (min(confused + 5, 30))
Confuse(5)
if(2)
src.take_organ_damage(0,15,emp=1)
confused = (min(confused + 4, 30))
Confuse(4)
if(3)
src.take_organ_damage(0,10,emp=1)
confused = (min(confused + 3, 30))
Confuse(3)
if(4)
src.take_organ_damage(0,5,emp=1)
confused = (min(confused + 2, 30))
Confuse(2)
flash_eyes(affect_silicon = 1)
src << "<span class='danger'><B>*BZZZT*</B></span>"
src << "<span class='danger'>Warning: Electromagnetic pulse detected.</span>"
@@ -148,7 +148,7 @@
// this function shows the health of the AI in the Status panel
/mob/living/silicon/proc/show_system_integrity()
if(!src.stat)
stat(null, text("System integrity: [round((health/maxHealth)*100)]%"))
stat(null, text("System integrity: [round((health/getMaxHealth())*100)]%"))
else
stat(null, text("Systems nonfunctional"))
@@ -17,7 +17,7 @@
response_help = "pokes"
response_disarm = "gently pushes aside"
response_harm = "hits"
a_intent = I_HURT
ranged = 1
rapid = 1
@@ -99,16 +99,16 @@
src.visible_message("\red \icon[src] [src] suddenly lights up, and additional targetting vanes slide into place.")
hostile = 1
if(health / maxHealth > 0.9)
if(health / getMaxHealth() > 0.9)
icon_state = "drone3"
explode_chance = 0
else if(health / maxHealth > 0.7)
else if(health / getMaxHealth() > 0.7)
icon_state = "drone2"
explode_chance = 0
else if(health / maxHealth > 0.5)
else if(health / getMaxHealth() > 0.5)
icon_state = "drone1"
explode_chance = 0.5
else if(health / maxHealth > 0.3)
else if(health / getMaxHealth() > 0.3)
icon_state = "drone0"
explode_chance = 5
else if(health > 0)
@@ -95,10 +95,10 @@
if (istype(O, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = O
if (WT.remove_fuel(0))
if(health < maxHealth)
if(health < getMaxHealth())
health += pick(1,1,1,2,2,3)
if(health > maxHealth)
health = maxHealth
if(health > getMaxHealth())
health = getMaxHealth()
add_fingerprint(user)
src.visible_message("<span class='notice'>\The [user] has spot-welded some of the damage to \the [src]!</span>")
else
@@ -57,7 +57,7 @@
/mob/living/simple_animal/construct/attack_generic(var/mob/user)
if(istype(user, /mob/living/simple_animal/construct/builder))
if(health < maxHealth)
if(health < getMaxHealth())
adjustBruteLoss(-5)
user.visible_message("<span class='notice'>\The [user] mends some of \the [src]'s wounds.</span>")
else
@@ -68,9 +68,9 @@
/mob/living/simple_animal/construct/examine(mob/user)
..(user)
var/msg = "<span cass='info'>*---------*\nThis is \icon[src] \a <EM>[src]</EM>!\n"
if (src.health < src.maxHealth)
if (src.health < src.getMaxHealth())
msg += "<span class='warning'>"
if (src.health >= src.maxHealth/2)
if (src.health >= src.getMaxHealth()/2)
msg += "It looks slightly dented.\n"
else
msg += "<B>It looks severely dented!</B>\n"
@@ -170,7 +170,7 @@
T.forceMove(src) //put shade in stone
T.status_flags |= GODMODE
T.canmove = 0
T.health = T.maxHealth
T.health = T.getMaxHealth()
src.icon_state = "soulstone2"
T << "Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form"
@@ -75,7 +75,7 @@
/mob/living/simple_animal/hostile/mecha/Life()
. = ..()
if(!.) return
if((health < maxHealth*0.3) && prob(10))
if((health < getMaxHealth()*0.3) && prob(10))
sparks.start()
/mob/living/simple_animal/hostile/mecha/bullet_act()
@@ -234,8 +234,8 @@
density = 1
//Overhealth
else if(health > maxHealth)
health = maxHealth
else if(health > getMaxHealth())
health = getMaxHealth()
/mob/living/simple_animal/update_icon()
..()
@@ -534,7 +534,7 @@
if(istype(O, /obj/item/stack/medical))
if(stat != DEAD)
var/obj/item/stack/medical/MED = O
if(health < maxHealth)
if(health < getMaxHealth())
if(MED.amount >= 1)
adjustBruteLoss(-MED.heal_brute)
MED.amount -= 1
@@ -602,7 +602,7 @@
..()
if(statpanel("Status") && show_stat_health)
stat(null, "Health: [round((health / maxHealth) * 100)]%")
stat(null, "Health: [round((health / getMaxHealth()) * 100)]%")
/mob/living/simple_animal/lay_down()
..()
@@ -645,10 +645,10 @@
adjustBruteLoss(30)
/mob/living/simple_animal/adjustBruteLoss(damage)
health = Clamp(health - damage, 0, maxHealth)
health = Clamp(health - damage, 0, getMaxHealth())
/mob/living/simple_animal/adjustFireLoss(damage)
health = Clamp(health - damage, 0, maxHealth)
health = Clamp(health - damage, 0, getMaxHealth())
// Check target_mob if worthy of attack (i.e. check if they are dead or empty mecha)
/mob/living/simple_animal/proc/SA_attackable(target_mob)
+24
View File
@@ -804,6 +804,30 @@
sleeping = max(sleeping + amount,0)
return
/mob/proc/Confuse(amount)
confused = max(max(confused,amount),0)
return
/mob/proc/SetConfused(amount)
confused = max(amount,0)
return
/mob/proc/AdjustConfused(amount)
confused = max(confused + amount,0)
return
/mob/proc/Blind(amount)
eye_blind = max(max(eye_blind,amount),0)
return
/mob/proc/SetBlinded(amount)
eye_blind = max(amount,0)
return
/mob/proc/AdjustBlinded(amount)
eye_blind = max(eye_blind + amount,0)
return
/mob/proc/Resting(amount)
facing_dir = null
resting = max(max(resting,amount),0)
+1
View File
@@ -207,3 +207,4 @@
var/list/active_genes=list()
var/mob_size = MOB_MEDIUM
var/forbid_seeing_deadchat = FALSE // Used for lings to not see deadchat, and to have ghosting behave as if they were not really dead.
+1 -1
View File
@@ -170,7 +170,7 @@
if(announce)
assailant.visible_message("<span class='warning'>[assailant] covers [affecting]'s eyes!</span>")
if(affecting.eye_blind < 3)
affecting.eye_blind = 3
affecting.Blind(3)
/obj/item/weapon/grab/attack_self()
return s_click(hud)
+6
View File
@@ -390,10 +390,16 @@ proc/is_blind(A)
else
name = realname
if(subject && subject.forbid_seeing_deadchat && !subject.client.holder)
return // Can't talk in deadchat if you can't see it.
for(var/mob/M in player_list)
if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && !is_mentor(M.client))) && M.is_preference_enabled(/datum/client_preference/show_dsay))
var/follow
var/lname
if(M.forbid_seeing_deadchat && !M.client.holder)
continue
if(subject)
if(M.is_key_ignored(subject.client.key)) // If we're ignored, do nothing.
continue
+1 -1
View File
@@ -199,7 +199,7 @@
if(S.victim == mob)
return
if(mob.stat==DEAD && isliving(mob))
if(mob.stat==DEAD && isliving(mob) && !mob.forbid_seeing_deadchat)
mob.ghostize()
return
+131
View File
@@ -0,0 +1,131 @@
// This is a datum that tells the mob that something is affecting them.
// The advantage of using this datum verses just setting a variable on the mob directly, is that there is no risk of two different procs overwriting
// each other, or other weirdness. An excellent example is adjusting max health.
/datum/modifier
var/name = null // Mostly used to organize, might show up on the UI in the Future(tm)
var/desc = null // Ditto.
var/icon_state = null // See above.
var/mob/living/holder = null // The mob that this datum is affecting.
var/expire_at = null // world.time when holder's Life() will remove the datum. If null, it lasts forever or until it gets deleted by something else.
var/on_created_text = null // Text to show to holder upon being created.
var/on_expired_text = null // Text to show to holder when it expires.
var/hidden = FALSE // If true, it will not show up on the HUD in the Future(tm)
var/stacks = MODIFIER_STACK_FORBID // If true, attempts to add a second instance of this type will refresh expire_at instead.
var/flags = 0 // Flags for the modifier, see mobs.dm defines for more details.
var/light_color = null // If set, the mob possessing the modifier will glow in this color. Not implemented yet.
var/light_range = null // How far the light for the above var goes. Not implemented yet.
var/light_intensity = null // Ditto. Not implemented yet.
var/mob_overlay_state = null // Icon_state for an overlay to apply to a (human) mob while this exists. This is actually implemented.
// Now for all the different effects.
// Percentage modifiers are expressed as a multipler. (e.g. +25% damage should be written as 1.25)
var/max_health_flat // Adjusts max health by a flat (e.g. +20) amount. Note this is added to base health.
var/max_health_percent // Adjusts max health by a percentage (e.g. -30%).
var/disable_duration_percent // Adjusts duration of 'disables' (stun, weaken, paralyze, confusion, sleep, halloss, etc) Setting to 0 will grant immunity.
var/incoming_damage_percent // Adjusts all incoming damage.
var/incoming_brute_damage_percent // Only affects bruteloss.
var/incoming_fire_damage_percent // Only affects fireloss.
var/incoming_tox_damage_percent // Only affects toxloss.
var/incoming_oxy_damage_percent // Only affects oxyloss.
var/incoming_clone_damage_percent // Only affects cloneloss.
var/incoming_hal_damage_percent // Only affects halloss.
var/incoming_healing_percent // Adjusts amount of healing received.
var/outgoing_melee_damage_percent // Adjusts melee damage inflicted by holder by a percentage. Affects attacks by melee weapons and hand-to-hand.
var/slowdown // Negative numbers speed up, positive numbers slow down movement.
var/haste // If set to 1, the mob will be 'hasted', which makes it ignore slowdown and go really fast.
var/evasion // Positive numbers reduce the odds of being hit by 15% each. Negative numbers increase the odds.
/datum/modifier/New(var/new_holder)
holder = new_holder
..()
// Checks to see if this datum should continue existing.
/datum/modifier/proc/check_if_valid()
if(expire_at && expire_at < world.time) // Is our time up?
src.expire()
/datum/modifier/proc/expire(var/silent = FALSE)
if(on_expired_text && !silent)
to_chat(holder, on_expired_text)
on_expire()
holder.modifiers.Remove(src)
if(mob_overlay_state) // We do this after removing ourselves from the list so that the overlay won't remain.
holder.update_modifier_visuals()
qdel(src)
// Override this for special effects when it gets removed.
/datum/modifier/proc/on_expire()
return
// Called every Life() tick. Override for special behaviour.
/datum/modifier/proc/tick()
return
/mob/living
var/list/modifiers = list() // A list of modifier datums, which can adjust certain mob numbers.
/mob/living/Destroy()
remove_all_modifiers(TRUE)
..()
// Called by Life().
/mob/living/proc/handle_modifiers()
if(!modifiers.len) // No work to do.
return
// Get rid of anything we shouldn't have.
for(var/datum/modifier/M in modifiers)
M.check_if_valid()
// Remaining modifiers will now receive a tick(). This is in a second loop for safety in order to not tick() an expired modifier.
for(var/datum/modifier/M in modifiers)
M.tick()
// Call this to add a modifier to a mob. First argument is the modifier type you want, second is how long it should last, in ticks.
// The SECONDS/MINUTES macro is very helpful for this. E.g. M.add_modifier(/datum/modifier/example, 5 MINUTES)
/mob/living/proc/add_modifier(var/modifier_type, var/expire_at = null)
// First, check if the mob already has this modifier.
for(var/datum/modifier/M in modifiers)
if(istype(modifier_type, M))
switch(M.stacks)
if(MODIFIER_STACK_FORBID)
return // Stop here.
if(MODIFIER_STACK_ALLOWED)
break // No point checking anymore.
if(MODIFIER_STACK_EXTEND)
// Not allow to add a second instance, but we can try to prolong the first instance.
if(expire_at && world.time + expire_at > M.expire_at)
M.expire_at = world.time + expire_at
return
// If we're at this point, the mob doesn't already have it, or it does but stacking is allowed.
var/datum/modifier/mod = new modifier_type(src)
if(expire_at)
mod.expire_at = world.time + expire_at
if(mod.on_created_text)
to_chat(src, mod.on_created_text)
modifiers.Add(mod)
if(mod.mob_overlay_state)
update_modifier_visuals()
// Removes a specific instance of modifier
/mob/living/proc/remove_specific_modifier(var/datum/modifier/M, var/silent = FALSE)
M.expire(silent)
// Removes all modifiers of a type
/mob/living/proc/remove_modifiers_of_type(var/modifier_type, var/silent = FALSE)
for(var/datum/modifier/M in modifiers)
if(istype(M, modifier_type))
M.expire(silent)
// Removes all modifiers, useful if the mob's being deleted
/mob/living/proc/remove_all_modifiers(var/silent = FALSE)
for(var/datum/modifier/M in modifiers)
M.expire(silent)
// Checks if the mob has a modifier type.
/mob/living/proc/has_modifier_of_type(var/modifier_type)
for(var/datum/modifier/M in modifiers)
if(istype(M, modifier_type))
return TRUE
return FALSE
+22 -4
View File
@@ -11,25 +11,43 @@ var/z_levels = 0 // Each bit represents a connection between adjacent levels. S
qdel(src)
// The storage of connections between adjacent levels means some bitwise magic is needed.
proc/HasAbove(var/z)
/proc/HasAbove(var/z)
if(z >= world.maxz || z > 16 || z < 1)
return 0
return z_levels & (1 << (z - 1))
proc/HasBelow(var/z)
/proc/HasBelow(var/z)
if(z > world.maxz || z > 17 || z < 2)
return 0
return z_levels & (1 << (z - 2))
// Thankfully, no bitwise magic is needed here.
proc/GetAbove(var/atom/atom)
/proc/GetAbove(var/atom/atom)
var/turf/turf = get_turf(atom)
if(!turf)
return null
return HasAbove(turf.z) ? get_step(turf, UP) : null
proc/GetBelow(var/atom/atom)
/proc/GetBelow(var/atom/atom)
var/turf/turf = get_turf(atom)
if(!turf)
return null
return HasBelow(turf.z) ? get_step(turf, DOWN) : null
/proc/GetConnectedZlevels(z)
. = list(z)
for(var/level = z, HasBelow(level), level--)
. |= level-1
for(var/level = z, HasAbove(level), level++)
. |= level+1
proc/AreConnectedZLevels(var/zA, var/zB)
return zA == zB || (zB in GetConnectedZlevels(zA))
/proc/get_zstep(ref, dir)
if(dir == UP)
. = GetAbove(ref)
else if (dir == DOWN)
. = GetBelow(ref)
else
. = get_step(ref, dir)
+18 -14
View File
@@ -3,34 +3,38 @@
set category = "IC"
if(zMove(UP))
to_chat(usr, "<span class='notice'>You move upwards.</span>")
to_chat(src, "<span class='notice'>You move upwards.</span>")
/mob/verb/down()
set name = "Move Down"
set category = "IC"
if(zMove(DOWN))
to_chat(usr, "<span class='notice'>You move down.</span>")
to_chat(src, "<span class='notice'>You move down.</span>")
/mob/proc/zMove(direction)
if(eyeobj)
return eyeobj.zMove(direction)
if(!can_ztravel())
to_chat(usr, "<span class='warning'>You lack means of travel in that direction.</span>")
to_chat(src, "<span class='warning'>You lack means of travel in that direction.</span>")
return
var/turf/start = loc
if(!istype(start))
to_chat(src, "<span class='notice'>You are unable to move from here.</span>")
return 0
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
if(!destination)
to_chat(usr, "<span class='notice'>There is nothing of interest in this direction.</span>")
to_chat(src, "<span class='notice'>There is nothing of interest in this direction.</span>")
return 0
if(!start.CanZPass(src, direction))
to_chat(src, "<span class='warning'>\The [start] is in the way.</span>")
return 0
var/turf/start = get_turf(src)
if(!start.CanZPass(src, direction))
to_chat(usr, "<span class='warning'>\The [start] is in the way.</span>")
return 0
if(!destination.CanZPass(src, direction))
to_chat(usr, "<span class='warning'>\The [destination] blocks your way.</span>")
to_chat(src, "<span class='warning'>\The [destination] blocks your way.</span>")
return 0
var/area/area = get_area(src)
@@ -46,12 +50,12 @@
to_chat(src, "<span class='warning'>You gave up on pulling yourself up.</span>")
return 0
else
to_chat(usr, "<span class='warning'>Gravity stops you from moving upward.</span>")
to_chat(src, "<span class='warning'>Gravity stops you from moving upward.</span>")
return 0
for(var/atom/A in destination)
if(!A.CanPass(src, start, 1.5, 0))
to_chat(usr, "<span class='warning'>\The [A] blocks you.</span>")
to_chat(src, "<span class='warning'>\The [A] blocks you.</span>")
return 0
Move(destination)
return 1
@@ -61,14 +65,14 @@
if(destination)
forceMove(destination)
else
to_chat(usr, "<span class='notice'>There is nothing of interest in this direction.</span>")
to_chat(src, "<span class='notice'>There is nothing of interest in this direction.</span>")
/mob/observer/eye/zMove(direction)
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
if(destination)
setLoc(destination)
else
to_chat(usr, "<span class='notice'>There is nothing of interest in this direction.</span>")
to_chat(src, "<span class='notice'>There is nothing of interest in this direction.</span>")
/mob/proc/can_ztravel()
return 0
+9 -5
View File
@@ -13,6 +13,9 @@ obj/machinery/atmospherics/pipe/zpipe
dir = SOUTH
initialize_directions = SOUTH
// node1 is the connection on the same Z
// node2 is the connection on the other Z
var/minimum_temperature_difference = 300
var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No
@@ -48,7 +51,7 @@ obj/machinery/atmospherics/pipe/zpipe/New()
invisibility = i ? 101 : 0
update_icon()
obj/machinery/atmospherics/pipe/up/process()
obj/machinery/atmospherics/pipe/zpipe/process()
if(!parent) //This should cut back on the overhead calling build_network thousands of times per cycle
..()
else
@@ -78,10 +81,10 @@ obj/machinery/atmospherics/pipe/zpipe/proc/burst()
qdel(src) // NOT qdel.
obj/machinery/atmospherics/pipe/zpipe/proc/normalize_dir()
if(dir==3)
set_dir(1)
else if(dir==12)
set_dir(4)
if(dir == (NORTH|SOUTH))
set_dir(NORTH)
else if(dir == (EAST|WEST))
set_dir(EAST)
obj/machinery/atmospherics/pipe/zpipe/Destroy()
if(node1)
@@ -94,6 +97,7 @@ obj/machinery/atmospherics/pipe/zpipe/pipeline_expansion()
return list(node1, node2)
obj/machinery/atmospherics/pipe/zpipe/update_icon()
color = pipe_color
return
obj/machinery/atmospherics/pipe/zpipe/disconnect(obj/machinery/atmospherics/reference)
-4
View File
@@ -122,10 +122,6 @@
allowed_directions = UP|DOWN
icon_state = "ladder11"
/obj/structure/stairs
name = "Stairs"
desc = "Stairs leading to another deck. Not too useful if the gravity goes out."
+7 -2
View File
@@ -36,6 +36,11 @@
..()
mover.fall()
// Called when thrown object lands on this turf.
/turf/simulated/open/hitby(var/atom/movable/AM, var/speed)
. = ..()
AM.fall()
/turf/simulated/open/proc/update()
below = GetBelow(src)
turf_changed_event.register(below, src, /turf/simulated/open/update_icon)
@@ -82,7 +87,7 @@
return
var/obj/item/stack/rods/R = C
if (R.use(1))
user << "<span class='notice'>Constructing support lattice ...</span>"
to_chat(user, "<span class='notice'>Constructing support lattice ...</span>")
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
ReplaceWithLattice()
return
@@ -99,7 +104,7 @@
ChangeTurf(/turf/simulated/floor/airless)
return
else
user << "<span class='warning'>The plating is going to need some support.</span>"
to_chat(user, "<span class='warning'>The plating is going to need some support.</span>")
//To lay cable.
if(istype(C, /obj/item/stack/cable_coil))
+1 -1
View File
@@ -37,7 +37,7 @@ var/const/CE_STABLE_THRESHOLD = 0.5
// Takes care blood loss and regeneration
/mob/living/carbon/human/handle_blood()
if(in_stasis)
if(inStasisNow())
return
if(!should_have_organ(O_HEART))
+1 -1
View File
@@ -35,7 +35,7 @@
if (. >= 2)
if(prob(1))
owner.custom_pain("Your feel very dizzy for a moment!",0)
owner.confused = max(owner.confused, 2)
owner.Confuse(2)
/obj/item/organ/internal/brain/proc/replace_self_with(replace_path)
var/mob/living/carbon/human/tmp_owner = owner
+1 -1
View File
@@ -72,7 +72,7 @@
if(is_bruised())
owner.eye_blurry = 20
if(is_broken())
owner.eye_blind = 20
owner.Blind(20)
/obj/item/organ/internal/eyes/handle_germ_effects()
. = ..() //Up should return an infection level as an integer
+1 -1
View File
@@ -53,6 +53,6 @@
if(prob(1))
owner.custom_pain("There's a sharp pain in your upper-right abdomen!",1)
if (. >= 2)
if(prob(1) && owner.getToxLoss() < owner.maxHealth*0.3)
if(prob(1) && owner.getToxLoss() < owner.getMaxHealth()*0.3)
//owner << "" //Toxins provide their own messages for pain
owner.adjustToxLoss(5) //Not realistic to PA but there are basically no 'real' liver infections
+5 -5
View File
@@ -492,7 +492,7 @@ This function completely restores a damaged organ to perfect condition.
//Burn damage can cause fluid loss due to blistering and cook-off
if((damage > 5 || damage + burn_dam >= 15) && type == BURN && (robotic < ORGAN_ROBOT))
var/fluid_loss = 0.75 * (damage/(owner.maxHealth - config.health_threshold_dead)) * owner.species.blood_volume*(1 - BLOOD_VOLUME_SURVIVE/100)
var/fluid_loss = 0.75 * (damage/(owner.getMaxHealth() - config.health_threshold_dead)) * owner.species.blood_volume*(1 - BLOOD_VOLUME_SURVIVE/100)
owner.remove_blood(fluid_loss)
// first check whether we can widen an existing wound
@@ -882,7 +882,7 @@ Note that amputating the affected organ does in fact remove the infection from t
if(!clean)
// Throw limb around.
if(src && istype(loc,/turf))
throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30)
throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
dir = 2
if(DROPLIMB_BURN)
new /obj/effect/decal/cleanable/ash(get_turf(victim))
@@ -901,19 +901,19 @@ Note that amputating the affected organ does in fact remove the infection from t
gore.basecolor = use_blood_colour
gore.update_icon()
gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30)
gore.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
for(var/obj/item/organ/I in internal_organs)
I.removed()
if(istype(loc,/turf))
I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30)
I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
for(var/obj/item/I in src)
if(I.w_class <= ITEMSIZE_SMALL)
qdel(I)
continue
I.loc = get_turf(src)
I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30)
I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5)
qdel(src)
+1 -1
View File
@@ -165,7 +165,7 @@
if(is_bruised())
owner.eye_blurry = 20
if(is_broken())
owner.eye_blind = 20
owner.Blind(20)
/obj/item/organ/internal/liver
name = "liver"
+8
View File
@@ -44,6 +44,14 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\
var/parts = BP_ALL //Defines what parts said brand can replace on a body.
var/health_hud_intensity = 1 // Intensity modifier for the health GUI indicator.
/datum/robolimb/unbranded_monitor
company = "Unbranded Monitor"
desc = "A generic unbranded interpretation of a popular prosthetic head model. It looks rudimentary and cheaply constructed."
icon = 'icons/mob/human_races/cyberlimbs/unbranded/unbranded_monitor.dmi'
parts = list(BP_HEAD)
monitor_styles = standard_monitor_styles
unavailable_to_build = 1
/datum/robolimb/nanotrasen
company = "NanoTrasen"
desc = "A simple but efficient robotic limb, created by NanoTrasen."
+50
View File
@@ -0,0 +1,50 @@
/obj/item/organ/external/chest/unathi
max_damage = 100
min_broken_damage = 40
encased = "upper ribplates"
/obj/item/organ/external/groin/unathi
max_damage = 100
min_broken_damage = 40
encased = "lower ribplates"
/obj/item/organ/external/head/unathi
max_damage = 75
min_broken_damage = 35
eye_icon = "eyes_s"
force = 5
throwforce = 10
/obj/item/organ/internal/heart/unathi
icon_state = "unathi_heart-on"
dead_icon = "unath_heart-off"
/obj/item/organ/internal/lungs/unathi
color = "#b3cbc3"
/obj/item/organ/internal/liver/unathi
name = "filtration organ"
icon_state = "unathi_liver"
//Unathi liver acts as kidneys, too.
/obj/item/organ/internal/liver/unathi/process()
..()
if(!owner) return
var/datum/reagent/coffee = locate(/datum/reagent/drink/coffee) in owner.reagents.reagent_list
if(coffee)
if(is_bruised())
owner.adjustToxLoss(0.1 * PROCESS_ACCURACY)
else if(is_broken())
owner.adjustToxLoss(0.3 * PROCESS_ACCURACY)
var/datum/reagent/sugar = locate(/datum/reagent/sugar) in owner.reagents.reagent_list
if(sugar)
if(is_bruised())
owner.adjustToxLoss(0.1 * PROCESS_ACCURACY)
else if(is_broken())
owner.adjustToxLoss(0.3 * PROCESS_ACCURACY)
/obj/item/organ/internal/brain/unathi
color = "#b3cbc3"
+14 -9
View File
@@ -12,8 +12,17 @@
var/datum/weather_holder/weather_holder
var/sun_position = 0 // 0 means midnight, 1 means noon.
var/list/sun = list("range","brightness","color")
var/expected_z_levels = list()
var/turf/unsimulated/wall/planetary/planetary_wall_type = /turf/unsimulated/wall/planetary
var/turf/simulated/floor/planet_floors = list()
var/turf/unsimulated/wall/planetary/planet_walls = list()
var/needs_work = 0 // Bitflags to signal to the planet controller these need (properly deferrable) work. Flags defined in controller.
/datum/planet/New()
..()
weather_holder = new(src)
@@ -31,17 +40,13 @@
/datum/planet/proc/update_sun()
sun_last_process = world.time
/datum/planet/proc/update_weather()
if(weather_holder)
weather_holder.process()
/datum/planet/proc/update_sun_deferred(var/new_range, var/new_brightness, var/new_color)
set background = 1
set waitfor = 0
var/i = 0
for(var/turf/simulated/floor/T in outdoor_turfs)
T.set_light(new_range, new_brightness, new_color)
i++
if(i % 30 == 0)
sleep(1)
sun["range"] = new_range
sun["brightness"] = new_brightness
sun["color"] = new_color
needs_work |= PLANET_PROCESS_SUN
+195
View File
@@ -10,6 +10,7 @@ var/datum/planet/sif/planet_sif = null
Its center of government is the equatorial city and site of first settlement, New Reykjavik." // Ripped straight from the wiki.
current_time = new /datum/time/sif() // 32 hour clocks are nice.
expected_z_levels = list(1) // To be changed when real map is finished.
planetary_wall_type = /turf/unsimulated/wall/planetary/sif
/datum/planet/sif/New()
..()
@@ -104,3 +105,197 @@ var/datum/planet/sif/planet_sif = null
/proc/get_sif_time()
if(planet_sif)
return planet_sif.current_time
//Weather definitions
/datum/weather_holder/sif
temperature = T0C
allowed_weather_types = list(
WEATHER_CLEAR = new /datum/weather/sif/clear(),
WEATHER_OVERCAST = new /datum/weather/sif/overcast(),
WEATHER_LIGHT_SNOW = new /datum/weather/sif/light_snow(),
WEATHER_SNOW = new /datum/weather/sif/snow(),
WEATHER_BLIZZARD = new /datum/weather/sif/blizzard(),
WEATHER_RAIN = new /datum/weather/sif/rain(),
WEATHER_STORM = new /datum/weather/sif/storm(),
WEATHER_HAIL = new /datum/weather/sif/hail(),
WEATHER_BLOOD_MOON = new /datum/weather/sif/blood_moon()
)
roundstart_weather_chances = list(
WEATHER_CLEAR = 30,
WEATHER_OVERCAST = 30,
WEATHER_LIGHT_SNOW = 20,
WEATHER_SNOW = 5,
WEATHER_BLIZZARD = 5,
WEATHER_RAIN = 5,
WEATHER_STORM = 2.5,
WEATHER_HAIL = 2.5
)
datum/weather/sif
name = "sif base"
temp_high = 243.15 // -20c
temp_low = 233.15 // -30c
/datum/weather/sif/clear
name = "clear"
transition_chances = list(
WEATHER_CLEAR = 60,
WEATHER_OVERCAST = 40
)
/datum/weather/sif/overcast
name = "overcast"
light_modifier = 0.8
transition_chances = list(
WEATHER_CLEAR = 25,
WEATHER_OVERCAST = 50,
WEATHER_LIGHT_SNOW = 10,
WEATHER_SNOW = 5,
WEATHER_RAIN = 5,
WEATHER_HAIL = 5
)
/datum/weather/sif/light_snow
name = "light snow"
icon_state = "snowfall_light"
temp_high = 238.15 // -25c
temp_low = 228.15 // -35c
light_modifier = 0.7
transition_chances = list(
WEATHER_OVERCAST = 20,
WEATHER_LIGHT_SNOW = 50,
WEATHER_SNOW = 25,
WEATHER_HAIL = 5
)
/datum/weather/sif/snow
name = "moderate snow"
icon_state = "snowfall_med"
temp_high = 233.15 // -30c
temp_low = 223.15 // -40c
light_modifier = 0.5
transition_chances = list(
WEATHER_LIGHT_SNOW = 20,
WEATHER_SNOW = 50,
WEATHER_BLIZZARD = 20,
WEATHER_HAIL = 5,
WEATHER_OVERCAST = 5
)
/datum/weather/sif/snow/process_effects()
for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs)
if(S.z in holder.our_planet.expected_z_levels)
for(var/dir_checked in cardinal)
var/turf/simulated/floor/T = get_step(S, dir_checked)
if(istype(T))
if(istype(T, /turf/simulated/floor/outdoors) && prob(33))
T.chill()
/datum/weather/sif/blizzard
name = "blizzard"
icon_state = "snowfall_heavy"
temp_high = 223.15 // -40c
temp_low = 203.15 // -60c
light_modifier = 0.3
transition_chances = list(
WEATHER_SNOW = 45,
WEATHER_BLIZZARD = 40,
WEATHER_HAIL = 10,
WEATHER_OVERCAST = 5
)
/datum/weather/sif/blizzard/process_effects()
for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs)
if(S.z in holder.our_planet.expected_z_levels)
for(var/dir_checked in cardinal)
var/turf/simulated/floor/T = get_step(S, dir_checked)
if(istype(T))
if(istype(T, /turf/simulated/floor/outdoors) && prob(50))
T.chill()
/datum/weather/sif/rain
name = "rain"
icon_state = "rain"
light_modifier = 0.5
transition_chances = list(
WEATHER_OVERCAST = 25,
WEATHER_LIGHT_SNOW = 10,
WEATHER_RAIN = 50,
WEATHER_STORM = 10,
WEATHER_HAIL = 5
)
/datum/weather/sif/rain/process_effects()
for(var/mob/living/L in living_mob_list)
if(L.z in holder.our_planet.expected_z_levels)
var/turf/T = get_turf(L)
if(!T.outdoors)
return // They're indoors, so no need to rain on them.
L.adjust_fire_stacks(-5)
to_chat(L, "<span class='warning'>Rain falls on you.</span>")
/datum/weather/sif/storm
name = "storm"
icon_state = "storm"
temp_high = 233.15 // -30c
temp_low = 213.15 // -50c
light_modifier = 0.3
transition_chances = list(
WEATHER_RAIN = 45,
WEATHER_STORM = 40,
WEATHER_HAIL = 10,
WEATHER_OVERCAST = 5
)
/datum/weather/sif/rain/process_effects()
for(var/mob/living/L in living_mob_list)
if(L.z in holder.our_planet.expected_z_levels)
var/turf/T = get_turf(L)
if(!T.outdoors)
return // They're indoors, so no need to rain on them.
L.adjust_fire_stacks(-10)
to_chat(L, "<span class='warning'>Rain falls on you, drenching you in water.</span>")
/datum/weather/sif/hail
name = "hail"
icon_state = "hail"
temp_high = 233.15 // -30c
temp_low = 213.15 // -50c
light_modifier = 0.3
transition_chances = list(
WEATHER_RAIN = 45,
WEATHER_STORM = 10,
WEATHER_HAIL = 40,
WEATHER_OVERCAST = 5
)
/datum/weather/sif/hail/process_effects()
for(var/mob/living/L in living_mob_list)
if(L.z in holder.our_planet.expected_z_levels)
var/turf/T = get_turf(L)
if(!T.outdoors)
return // They're indoors, so no need to pelt them with ice.
var/target_zone = pick(BP_ALL)
var/amount_blocked = L.run_armor_check(target_zone, "melee")
var/amount_soaked = L.get_armor_soak(target_zone, "melee")
if(amount_blocked >= 100)
return // No need to apply damage.
if(amount_soaked >= 10)
return // No need to apply damage.
L.apply_damage(rand(5, 10), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail")
to_chat(L, "<span class='warning'>The hail raining down on you [L.can_feel_pain() ? "hurts" : "damages you"]!</span>")
/datum/weather/sif/blood_moon
name = "blood moon"
light_modifier = 0.5
light_color = "#FF0000"
transition_chances = list(
WEATHER_BLOODMOON = 100
)
+2 -221
View File
@@ -1,15 +1,3 @@
#define WEATHER_CLEAR "clear"
#define WEATHER_OVERCAST "overcast"
#define WEATHER_LIGHT_SNOW "light snow"
#define WEATHER_SNOW "snow"
#define WEATHER_BLIZZARD "blizzard"
#define WEATHER_RAIN "rain"
#define WEATHER_STORM "storm"
#define WEATHER_HAIL "hail"
#define WEATHER_WINDY "windy"
#define WEATHER_HOT "hot"
#define WEATHER_BLOOD_MOON "blood moon" // For admin fun or cult later on.
/datum/weather_holder
var/datum/planet/our_planet = null
var/datum/weather/current_weather = null
@@ -19,7 +7,6 @@
var/list/allowed_weather_types = list()
var/list/roundstart_weather_chances = list()
var/next_weather_shift = null
var/planetary_wall_type = null // Which walls to look for when updating temperature.
/datum/weather_holder/New(var/source)
..()
@@ -54,55 +41,15 @@
current_weather.process_effects()
/datum/weather_holder/proc/update_icon_effects()
set background = 1
set waitfor = 0
if(current_weather)
for(var/turf/simulated/floor/T in outdoor_turfs)
if(T.z in our_planet.expected_z_levels)
T.overlays -= T.weather_overlay
T.weather_overlay = image(icon = current_weather.icon, icon_state = current_weather.icon_state, layer = LIGHTING_LAYER - 1)
T.overlays += T.weather_overlay
our_planet.needs_work |= PLANET_PROCESS_WEATHER
/datum/weather_holder/proc/update_temperature()
temperature = Interpolate(current_weather.temp_low, current_weather.temp_high, weight = our_planet.sun_position)
for(var/turf/unsimulated/wall/planetary/wall in planetary_walls)
if(ispath(wall.type, planetary_wall_type))
wall.temperature = temperature
for(var/dir in cardinal)
var/turf/simulated/T = get_step(wall, dir)
if(istype(T))
if(T.zone)
T.zone.rebuild()
our_planet.needs_work |= PLANET_PROCESS_TEMP
/datum/weather_holder/proc/get_weather_datum(desired_type)
return allowed_weather_types[desired_type]
/datum/weather_holder/sif
temperature = T0C
allowed_weather_types = list(
WEATHER_CLEAR = new /datum/weather/sif/clear(),
WEATHER_OVERCAST = new /datum/weather/sif/overcast(),
WEATHER_LIGHT_SNOW = new /datum/weather/sif/light_snow(),
WEATHER_SNOW = new /datum/weather/sif/snow(),
WEATHER_BLIZZARD = new /datum/weather/sif/blizzard(),
WEATHER_RAIN = new /datum/weather/sif/rain(),
WEATHER_STORM = new /datum/weather/sif/storm(),
WEATHER_HAIL = new /datum/weather/sif/hail(),
WEATHER_BLOOD_MOON = new /datum/weather/sif/blood_moon()
)
planetary_wall_type = /turf/unsimulated/wall/planetary/sif
roundstart_weather_chances = list(
WEATHER_CLEAR = 30,
WEATHER_OVERCAST = 30,
WEATHER_LIGHT_SNOW = 20,
WEATHER_SNOW = 5,
WEATHER_BLIZZARD = 5,
WEATHER_RAIN = 5,
WEATHER_STORM = 2.5,
WEATHER_HAIL = 2.5
)
/datum/weather
var/name = "weather base"
@@ -117,169 +64,3 @@
/datum/weather/proc/process_effects()
return
/datum/weather/sif
name = "sif base"
temp_high = 243.15 // -20c
temp_low = 233.15 // -30c
/datum/weather/sif/clear
name = "clear"
transition_chances = list(
WEATHER_CLEAR = 60,
WEATHER_OVERCAST = 40
)
/datum/weather/sif/overcast
name = "overcast"
light_modifier = 0.8
transition_chances = list(
WEATHER_CLEAR = 25,
WEATHER_OVERCAST = 50,
WEATHER_LIGHT_SNOW = 10,
WEATHER_SNOW = 5,
WEATHER_RAIN = 5,
WEATHER_HAIL = 5
)
/datum/weather/sif/light_snow
name = "light snow"
icon_state = "snowfall_light"
temp_high = 238.15 // -25c
temp_low = 228.15 // -35c
light_modifier = 0.7
transition_chances = list(
WEATHER_OVERCAST = 20,
WEATHER_LIGHT_SNOW = 50,
WEATHER_SNOW = 25,
WEATHER_HAIL = 5
)
/datum/weather/sif/snow
name = "moderate snow"
icon_state = "snowfall_med"
temp_high = 233.15 // -30c
temp_low = 223.15 // -40c
light_modifier = 0.5
transition_chances = list(
WEATHER_LIGHT_SNOW = 20,
WEATHER_SNOW = 50,
WEATHER_BLIZZARD = 20,
WEATHER_HAIL = 5,
WEATHER_OVERCAST = 5
)
/datum/weather/sif/snow/process_effects()
for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs)
for(var/dir_checked in cardinal)
var/turf/simulated/floor/T = get_step(S, dir_checked)
if(istype(T))
if(istype(T, /turf/simulated/floor/outdoors) && prob(33))
T.chill()
/datum/weather/sif/blizzard
name = "blizzard"
icon_state = "snowfall_heavy"
temp_high = 223.15 // -40c
temp_low = 203.15 // -60c
light_modifier = 0.3
transition_chances = list(
WEATHER_SNOW = 45,
WEATHER_BLIZZARD = 40,
WEATHER_HAIL = 10,
WEATHER_OVERCAST = 5
)
/datum/weather/sif/blizzard/process_effects()
for(var/turf/simulated/floor/outdoors/snow/S in outdoor_turfs)
for(var/dir_checked in cardinal)
var/turf/simulated/floor/T = get_step(S, dir_checked)
if(istype(T))
if(istype(T, /turf/simulated/floor/outdoors) && prob(50))
T.chill()
/datum/weather/sif/rain
name = "rain"
icon_state = "rain"
light_modifier = 0.5
transition_chances = list(
WEATHER_OVERCAST = 25,
WEATHER_LIGHT_SNOW = 10,
WEATHER_RAIN = 50,
WEATHER_STORM = 10,
WEATHER_HAIL = 5
)
/datum/weather/sif/rain/process_effects()
for(var/mob/living/L in living_mob_list)
if(L.z in holder.our_planet.expected_z_levels)
var/turf/T = get_turf(L)
if(!T.outdoors)
return // They're indoors, so no need to rain on them.
L.adjust_fire_stacks(-5)
to_chat(L, "<span class='warning'>Rain falls on you.</span>")
/datum/weather/sif/storm
name = "storm"
icon_state = "storm"
temp_high = 233.15 // -30c
temp_low = 213.15 // -50c
light_modifier = 0.3
transition_chances = list(
WEATHER_RAIN = 45,
WEATHER_STORM = 40,
WEATHER_HAIL = 10,
WEATHER_OVERCAST = 5
)
/datum/weather/sif/rain/process_effects()
for(var/mob/living/L in living_mob_list)
if(L.z in holder.our_planet.expected_z_levels)
var/turf/T = get_turf(L)
if(!T.outdoors)
return // They're indoors, so no need to rain on them.
L.adjust_fire_stacks(-10)
to_chat(L, "<span class='warning'>Rain falls on you, drenching you in water.</span>")
/datum/weather/sif/hail
name = "hail"
icon_state = "hail"
temp_high = 233.15 // -30c
temp_low = 213.15 // -50c
light_modifier = 0.3
transition_chances = list(
WEATHER_RAIN = 45,
WEATHER_STORM = 10,
WEATHER_HAIL = 40,
WEATHER_OVERCAST = 5
)
/datum/weather/sif/hail/process_effects()
for(var/mob/living/L in living_mob_list)
if(L.z in holder.our_planet.expected_z_levels)
var/turf/T = get_turf(L)
if(!T.outdoors)
return // They're indoors, so no need to pelt them with ice.
var/target_zone = pick(BP_ALL)
var/amount_blocked = L.run_armor_check(target_zone, "melee")
var/amount_soaked = L.get_armor_soak(target_zone, "melee")
if(amount_blocked >= 100)
return // No need to apply damage.
if(amount_soaked >= 10)
return // No need to apply damage.
L.apply_damage(rand(5, 10), BRUTE, target_zone, amount_blocked, amount_soaked, used_weapon = "hail")
to_chat(L, "<span class='warning'>The hail raining down on you [L.can_feel_pain() ? "hurts" : "damages you"]!</span>")
/datum/weather/sif/blood_moon
name = "blood moon"
light_modifier = 0.5
light_color = "#FF0000"
transition_chances = list(
WEATHER_BLOODMOON = 100
)
+24 -34
View File
@@ -48,7 +48,7 @@ var/list/possible_cable_coil_colours = list(
anchored =1
var/datum/powernet/powernet
name = "power cable"
desc = "A flexible superconducting cable for heavy-duty power transfer"
desc = "A flexible superconducting cable for heavy-duty power transfer."
icon = 'icons/obj/power_cond_white.dmi'
icon_state = "0-1"
var/d1 = 0
@@ -116,9 +116,9 @@ var/list/possible_cable_coil_colours = list(
user.examinate(src)
// following code taken from attackby (multitool)
if(powernet && (powernet.avail > 0))
user << "<span class='warning'>[powernet.avail]W in power network.</span>"
to_chat(user, "<span class='warning'>[powernet.avail]W in power network.</span>")
else
user << "<span class='warning'>The cable is not powered.</span>"
to_chat(user, "<span class='warning'>The cable is not powered.</span>")
return
///////////////////////////////////
@@ -159,12 +159,12 @@ var/list/possible_cable_coil_colours = list(
return
if(istype(W, /obj/item/weapon/wirecutters))
if(d1 == 12 || d2 == 12)
user << "<span class='warning'>You must cut this cable from above.</span>"
if(d1 == UP || d2 == UP)
to_chat(user, "<span class='warning'>You must cut this cable from above.</span>")
return
if(breaker_box)
user << "\red This cable is connected to nearby breaker box. Use breaker box to interact with it."
to_chat(user, "<span class='warning'>This cable is connected to nearby breaker box. Use breaker box to interact with it.</span>")
return
if (shock(user, 50))
@@ -178,11 +178,11 @@ var/list/possible_cable_coil_colours = list(
for(var/mob/O in viewers(src, null))
O.show_message("<span class='warning'>[user] cuts the cable.</span>", 1)
if(d1 == 11 || d2 == 11)
if(d1 == DOWN || d2 == DOWN)
var/turf/turf = GetBelow(src)
if(turf)
for(var/obj/structure/cable/c in turf)
if(c.d1 == 12 || c.d2 == 12)
if(c.d1 == UP || c.d2 == UP)
qdel(c)
investigate_log("was cut by [key_name(usr, usr.client)] in [user.loc.loc]","wires")
@@ -194,17 +194,17 @@ var/list/possible_cable_coil_colours = list(
else if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = W
if (coil.get_amount() < 1)
user << "Not enough cable"
to_chat(user, "Not enough cable")
return
coil.cable_join(src, user)
else if(istype(W, /obj/item/device/multitool))
if(powernet && (powernet.avail > 0)) // is it powered?
user << "<span class='warning'>[powernet.avail]W in power network.</span>"
to_chat(user, "<span class='warning'>[powernet.avail]W in power network.</span>")
else
user << "<span class='warning'>The cable is not powered.</span>"
to_chat(user, "<span class='warning'>The cable is not powered.</span>")
shock(user, 5, 0.2)
@@ -300,12 +300,12 @@ obj/structure/cable/proc/cableColor(var/colorC)
// merge with the powernets of power objects in the given direction
/obj/structure/cable/proc/mergeConnectedNetworks(var/direction)
var/fdir = (!direction)? 0 : turn(direction, 180) //flip the direction, to match with the source position on its turf
var/fdir = direction ? reverse_dir[direction] : 0 //flip the direction, to match with the source position on its turf
if(!(d1 == direction || d2 == direction)) //if the cable is not pointed in this direction, do nothing
return
var/turf/TB = get_step(src, direction)
var/turf/TB = get_zstep(src, direction)
for(var/obj/structure/cable/C in TB)
@@ -376,25 +376,15 @@ obj/structure/cable/proc/cableColor(var/colorC)
. = list() // this will be a list of all connected power objects
var/turf/T
// Handle up/down cables
if(d1 == 11 || d2 == 11)
T = GetBelow(src)
if(T)
. += power_list(T, src, 12, 1)
if(d1 == 12 || d1 == 12)
T = GetAbove(src)
if(T)
. += power_list(T, src, 11, 1)
// Handle standard cables in adjacent turfs
for(var/cable_dir in list(d1, d2))
if(cable_dir == 11 || cable_dir == 12 || cable_dir == 0)
if(cable_dir == 0)
continue
var/reverse = reverse_dir[cable_dir]
T = get_step(src, cable_dir)
T = get_zstep(src, cable_dir)
if(T)
for(var/obj/structure/cable/C in T)
if((C.d1 && C.d1 == reverse) || (C.d2 && C.d2 == reverse))
if(C.d1 == reverse || C.d2 == reverse)
. += C
if(cable_dir & (cable_dir - 1)) // Diagonal, check for /\/\/\ style cables along cardinal directions
for(var/pair in list(NORTH|SOUTH, EAST|WEST))
@@ -402,7 +392,7 @@ obj/structure/cable/proc/cableColor(var/colorC)
if(T)
var/req_dir = cable_dir ^ pair
for(var/obj/structure/cable/C in T)
if((C.d1 && C.d1 == req_dir) || (C.d2 && C.d2 == req_dir))
if(C.d1 == req_dir || C.d2 == req_dir)
. += C
// Handle cables on the same turf as us
@@ -566,7 +556,7 @@ obj/structure/cable/proc/cableColor(var/colorC)
final_color = possible_cable_coil_colours["Red"]
selected_color = "red"
color = final_color
user << "<span class='notice'>You change \the [src]'s color to [lowertext(selected_color)].</span>"
to_chat(user, "<span class='notice'>You change \the [src]'s color to [lowertext(selected_color)].</span>")
/obj/item/stack/cable_coil/proc/update_wclass()
if(amount == 1)
@@ -579,11 +569,11 @@ obj/structure/cable/proc/cableColor(var/colorC)
return
if(get_amount() == 1)
user << "A short piece of power cable."
to_chat(user, "A short piece of power cable.")
else if(get_amount() == 2)
user << "A piece of power cable."
to_chat(user, "A piece of power cable.")
else
user << "A coil of power cable. There are [get_amount()] lengths of cable in the coil."
to_chat(user, "A coil of power cable. There are [get_amount()] lengths of cable in the coil.")
/obj/item/stack/cable_coil/verb/make_restraint()
@@ -594,14 +584,14 @@ obj/structure/cable/proc/cableColor(var/colorC)
if(ishuman(M) && !M.restrained() && !M.stat && !M.paralysis && ! M.stunned)
if(!istype(usr.loc,/turf)) return
if(src.amount <= 14)
usr << "\red You need at least 15 lengths to make restraints!"
to_chat(usr, "<span class='warning'>You need at least 15 lengths to make restraints!</span>")
return
var/obj/item/weapon/handcuffs/cable/B = new /obj/item/weapon/handcuffs/cable(usr.loc)
B.color = color
usr << "<span class='notice'>You wind some cable together to make some restraints.</span>"
to_chat(usr, "<span class='notice'>You wind some cable together to make some restraints.</span>")
src.use(15)
else
usr << "\blue You cannot do that."
to_chat(usr, "<span class='notice'>You cannot do that.</span>")
..()
/obj/item/stack/cable_coil/cyborg/verb/set_colour()
-1
View File
@@ -3,7 +3,6 @@
/obj/machinery/computer/gravity_control_computer
name = "Gravity Generator Control"
desc = "A computer to control a local gravity generator. Qualified personnel only."
icon = 'icons/obj/computer.dmi'
icon_state = "airtunnel0e"
anchored = 1
density = 1
+3 -15
View File
@@ -209,16 +209,8 @@
// if unmarked==1, only return those with no powernet
/proc/power_list(var/turf/T, var/source, var/d, var/unmarked=0, var/cable_only = 0)
. = list()
var/fdir = (!d)? 0 : turn(d, 180) // the opposite direction to d (or 0 if d==0)
///// Z-Level Stuff
var/Zdir
if(d==11)
Zdir = 11
else if (d==12)
Zdir = 12
else
Zdir = 999
///// Z-Level Stuff
var/reverse = d ? reverse_dir[d] : 0
for(var/AM in T)
if(AM == source) continue //we don't want to return source
@@ -234,11 +226,7 @@
var/obj/structure/cable/C = AM
if(!unmarked || !C.powernet)
///// Z-Level Stuff
if(C.d1 == fdir || C.d2 == fdir || C.d1 == Zdir || C.d2 == Zdir)
///// Z-Level Stuff
. += C
else if(C.d1 == d || C.d2 == d)
if(C.d1 == d || C.d2 == d || C.d1 == reverse || C.d2 == reverse )
. += C
return .
@@ -6,7 +6,6 @@
/obj/machinery/computer/power_monitor
name = "Power Monitoring Console"
desc = "Computer designed to remotely monitor power levels around the station"
icon = 'icons/obj/computer.dmi'
icon_keyboard = "power_key"
icon_screen = "power:0"
light_color = "#ffcc33"
-1
View File
@@ -28,7 +28,6 @@
/obj/machinery/computer/turbine_computer
name = "Gas turbine control computer"
desc = "A computer to remotely control a gas turbine"
icon = 'icons/obj/computer.dmi'
icon_keyboard = "tech_key"
icon_screen = "turbinecomp"
circuit = /obj/item/weapon/circuitboard/turbine_control
+25 -17
View File
@@ -182,7 +182,11 @@
if (A == user && user.zone_sel.selecting == O_MOUTH && !mouthshoot)
handle_suicide(user)
else if(user.a_intent == I_HURT) //point blank shooting
Fire(A, user, pointblank=1)
if(user && user.client && user.aiming && user.aiming.active && user.aiming.aiming_at != A && A != user)
PreFire(A,user) //They're using the new gun system, locate what they're aiming at.
return
else
Fire(A, user, pointblank=1)
else
return ..() //Pistolwhippin'
@@ -326,6 +330,8 @@
user.setMoveCooldown(move_delay)
next_fire_time = world.time + fire_delay
accuracy = initial(accuracy) //Reset the gun's accuracy
if(muzzle_flash)
set_light(0)
@@ -396,6 +402,8 @@
//update timing
next_fire_time = world.time + fire_delay
accuracy = initial(accuracy) //Reset the gun's accuracy
if(muzzle_flash)
set_light(0)
@@ -425,21 +433,21 @@
/obj/item/weapon/gun/proc/handle_post_fire(mob/user, atom/target, var/pointblank=0, var/reflex=0)
if(silenced)
playsound(user, fire_sound, 10, 1)
to_chat(user, "<span class='warning'>You fire \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]</span>")
for(var/mob/living/L in oview(2,user))
if(L.stat)
continue
if(L.blinded)
to_chat(L, "You hear a [fire_sound_text]!")
continue
to_chat(L, "<span class='warning'>[user] fires \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]</span>")
else
playsound(user, fire_sound, 50, 1)
if(reflex)
user.visible_message(
"<span class='reflex_shoot'><b>\The [user] fires \the [src][pointblank ? " point blank at \the [target]":""] by reflex!</b></span>",
"<span class='reflex_shoot'>You fire \the [src] by reflex!</span>",
"You hear a [fire_sound_text]!"
)
else
user.visible_message(
"<span class='danger'>\The [user] fires \the [src][pointblank ? " point blank at \the [target]":""]!</span>",
"<span class='warning'>You fire \the [src]!</span>",
"You hear a [fire_sound_text]!"
)
user.visible_message(
"<span class='warning'>[user] fires \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]</span>",
"<span class='warning'>You fire \the [src][pointblank ? " point blank at \the [target]":""][reflex ? " by reflex!":""]</span>",
"You hear a [fire_sound_text]!"
)
if(muzzle_flash)
set_light(muzzle_flash)
@@ -482,11 +490,11 @@
// Certain statuses make it harder to aim, blindness especially. Same chances as melee, however guns accuracy uses multiples of 15.
if(user.eye_blind)
accuracy -= 5
P.accuracy -= 5
if(user.eye_blurry)
accuracy -= 2
P.accuracy -= 2
if(user.confused)
accuracy -= 3
P.accuracy -= 3
//accuracy bonus from aiming
if (aim_targets && (target in aim_targets))
@@ -28,6 +28,7 @@
name = "practice laser carbine"
desc = "A modified version of the HI G40E, this one fires less concentrated energy bolts designed for target practice."
projectile_type = /obj/item/projectile/beam/practice
charge_cost = 48
cell_type = /obj/item/weapon/cell/device
@@ -21,7 +21,7 @@
item_state = null
w_class = ITEMSIZE_NORMAL
force = 5
slot_flags = SLOT_BELT
slot_flags = SLOT_BELT|SLOT_HOLSTER
charge_cost = 480
projectile_type = /obj/item/projectile/ion
@@ -49,4 +49,19 @@
desc = "The firepower of a Mosin, now the size of a pistol, with an effective combat range of about three feet. Uses 7.62mm rounds."
user << "<span class='warning'>You shorten the barrel and stock of \the [src]!</span>"
else
..()
..()
//Lever actions are the same thing, but bigger.
/obj/item/weapon/gun/projectile/shotgun/pump/rifle/lever
name = "lever-action rifle"
desc = "A reproduction of an almost ancient weapon design from the 19th century. This one uses a lever-action to move new rounds into the chamber. Uses 5.56mm rounds."
item_state = "leveraction"
icon_state = "leveraction"
fire_sound = 'sound/weapons/rifleshot.ogg'
max_shells = 5
caliber = "a556"
origin_tech = list(TECH_COMBAT = 1)// Old as shit rifle doesn't have very good tech.
ammo_type = /obj/item/ammo_casing/a556
load_method = SINGLE_CASING|SPEEDLOADER
action_sound = 'sound/weapons/riflebolt.ogg'
+1 -1
View File
@@ -173,7 +173,7 @@
return
//roll to-hit
miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier + round(15*target_mob.evasion), 0)
miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier + round(15*target_mob.get_evasion()), 0)
var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, miss_modifier, ranged_attack=(distance > 1 || original != target_mob)) //if the projectile hits a target we weren't originally aiming at then retain the chance to miss
var/result = PROJECTILE_FORCE_MISS
@@ -29,8 +29,8 @@
flash_strength *= H.species.flash_mod
if(flash_strength > 0)
H.confused = max(H.confused, flash_strength + 5)
H.eye_blind = max(H.eye_blind, flash_strength)
H.Confuse(flash_strength + 5)
H.Blind(flash_strength)
H.eye_blurry = max(H.eye_blurry, flash_strength + 5)
H.adjustHalLoss(22 * (flash_strength / 5)) // Five flashes to stun. Bit weaker than melee flashes due to being ranged.
@@ -146,9 +146,9 @@
var/ear_safety = 0
ear_safety = M.get_ear_protection()
if(ear_safety == 1)
M.confused += 150
M.Confuse(150)
else if (ear_safety > 1)
M.confused += 30
M.Confuse(30)
else if (!ear_safety)
M.Stun(10)
M.Weaken(2)

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