Merge remote-tracking branch 'refs/remotes/ParadiseSS13/master' into logic

This commit is contained in:
FalseIncarnate
2016-04-05 19:15:11 -04:00
434 changed files with 16507 additions and 12215 deletions
+30 -51
View File
@@ -70,7 +70,6 @@ var/list/admin_verbs_admin = list(
/client/proc/secrets,
/client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */
/client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */
/client/proc/virus_2_creator,
/client/proc/debug_variables
)
var/list/admin_verbs_ban = list(
@@ -446,7 +445,7 @@ var/list/admin_verbs_proccall = list (
/client/proc/big_brother()
set category = "Admin"
set name = "Big Brother Mode"
if(!check_rights(R_PERMISSIONS))
return
@@ -576,43 +575,16 @@ var/list/admin_verbs_proccall = list (
log_admin("[key_name(usr)] gave [key_name(T)] the spell [S].")
message_admins("[key_name_admin(usr)] gave [key_name(T)] the spell [S].", 1)
/client/proc/give_disease2(mob/T as mob in mob_list) // -- Giacom
/client/proc/give_disease(mob/T in mob_list)
set category = "Event"
set name = "Give Disease"
set desc = "Gives a Disease to a mob."
if(!check_rights(R_EVENT))
return
var/datum/disease2/disease/D = new /datum/disease2/disease()
var/severity = 1
var/greater = input("Is this a lesser, greater, or badmin disease?", "Give Disease") in list("Lesser", "Greater", "Badmin")
switch(greater)
if ("Lesser") severity = 1
if ("Greater") severity = 2
if ("Badmin") severity = 99
D.makerandom(severity)
D.spreadtype = input("What method of contagion should the disease have?", "Give Disease") in list("Airborne","Contact","Injection")
D.infectionchance = input("How virulent is this disease? (1-100)", "Give Disease", D.infectionchance) as num
if(istype(T,/mob/living/carbon/human))
var/mob/living/carbon/human/H = T
if (H.species)
D.affected_species = list(H.species.name)
if(H.species.primitive_form)
D.affected_species |= H.species.primitive_form
if(H.species.greater_form)
D.affected_species |= H.species.greater_form
infect_virus2(T,D,1)
feedback_add_details("admin_verb","GD2") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] gave [key_name(T)] a [greater] disease2 with infection chance [D.infectionchance].")
message_admins("[key_name_admin(usr)] gave [key_name(T)] a [greater] disease2 with infection chance [D.infectionchance].")
var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in diseases
if(!D) return
T.ForceContractDisease(new D)
feedback_add_details("admin_verb","GD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] gave [key_name(T)] the disease [D].")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] gave [key_name(T)] the disease [D].</span>")
/client/proc/make_sound(var/obj/O in view()) // -- TLE
set category = "Event"
@@ -809,7 +781,17 @@ var/list/admin_verbs_proccall = list (
return
if(!istype(H))
return
if(istype(H, /mob/living/carbon/brain))
var/mob/living/carbon/brain/B = H
if(istype(B.container, /obj/item/device/mmi/posibrain/ipc))
var/obj/item/device/mmi/posibrain/ipc/C = B.container
var/obj/item/organ/internal/brain/mmi_holder/posibrain/P = C.loc
if(istype(P.owner, /mob/living/carbon/human))
H = P.owner
else
return
else
return
if(holder)
admin_log_and_message_admins("is altering the appearance of [H].")
@@ -825,7 +807,17 @@ var/list/admin_verbs_proccall = list (
return
if(!istype(H))
return
if(istype(H, /mob/living/carbon/brain))
var/mob/living/carbon/brain/B = H
if(istype(B.container, /obj/item/device/mmi/posibrain/ipc))
var/obj/item/device/mmi/posibrain/ipc/C = B.container
var/obj/item/organ/internal/brain/mmi_holder/posibrain/P = C.loc
if(istype(P.owner, /mob/living/carbon/human))
H = P.owner
else
return
else
return
if(!H.client)
usr << "Only mobs with clients can alter their own appearance."
@@ -840,19 +832,6 @@ var/list/admin_verbs_proccall = list (
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1)
feedback_add_details("admin_verb","CMAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/virus_2_creator()
set name = "Virus2 Creator"
set desc = "Allows you to create and spread custom viruses."
set category = "Admin"
if(!check_rights(R_ADMIN))
return
var/datum/nano_module/virus2/virus2 = new()
virus2.ui_interact(usr, state = admin_state)
log_and_message_admins("has opened the virus2 creator.")
feedback_add_details("admin_verb","VS2C")
/client/proc/free_slot()
set name = "Free Job Slot"
set category = "Admin"
+2
View File
@@ -1529,6 +1529,8 @@
var/mob/dead/observer/G = locate(href_list["incarn_ghost"])
if(!istype(G))
usr << "This will only work on /mob/dead/observer"
log_admin("[key_name(G)] was incarnated by [key_name(src.owner)]")
message_admins("[key_name_admin(G)] was incarnated by [key_name_admin(src.owner)]")
G.incarnate_ghost()
else if(href_list["togmutate"])
+115 -81
View File
@@ -42,102 +42,113 @@
query_log = "[key_name(usr)] [query_log]"
log_admin(query_log)
for(var/list/query_tree in querys)
var/list/from_objs = list()
var/list/select_types = list()
try
for(var/list/query_tree in querys)
var/list/from_objs = list()
var/list/select_types = list()
switch(query_tree[1])
if("explain")
SDQL_testout(query_tree["explain"])
return
if("call")
if("on" in query_tree)
select_types = query_tree["on"]
else
switch(query_tree[1])
if("explain")
SDQL_testout(query_tree["explain"])
return
if("select", "delete", "update")
select_types = query_tree[query_tree[1]]
if("call")
if("on" in query_tree)
select_types = query_tree["on"]
else
return
from_objs = SDQL_from_objs(query_tree["from"])
if("select", "delete", "update")
select_types = query_tree[query_tree[1]]
var/list/objs = list()
from_objs = SDQL_from_objs(query_tree["from"])
for(var/type in select_types)
var/char = copytext(type, 1, 2)
var/list/objs = list()
if(char == "/" || char == "*")
for(var/from in from_objs)
objs += SDQL_get_all(type, from)
for(var/type in select_types)
var/char = copytext(type, 1, 2)
else if(char == "'" || char == "\"")
objs += locate(copytext(type, 2, length(type)))
if(char == "/" || char == "*")
for(var/from in from_objs)
objs += SDQL_get_all(type, from)
if("where" in query_tree)
var/objs_temp = objs
objs = list()
for(var/datum/d in objs_temp)
if(SDQL_expression(d, query_tree["where"]))
objs += d
else if(char == "'" || char == "\"")
objs += locate(copytext(type, 2, length(type)))
switch(query_tree[1])
if("call")
var/list/call_list = query_tree["call"]
var/list/args_list = query_tree["args"]
if("where" in query_tree)
var/objs_temp = objs
objs = list()
for(var/datum/d in objs_temp)
if(SDQL_expression(d, query_tree["where"]))
objs += d
for(var/datum/d in objs)
for(var/v in call_list)
// To stop any procs which sleep from executing slowly.
if(d)
if(hascall(d, v))
spawn() call(d, v)(arglist(args_list)) // Spawn in case the function sleeps.
switch(query_tree[1])
if("call")
var/list/call_list = query_tree["call"]
var/list/args_list = query_tree["args"]
if("delete")
for(var/datum/d in objs)
del(d)
for(var/datum/d in objs)
for(var/v in call_list)
var/list/arguments[0]
for(var/list/arg in args_list)
arguments += SDQL_expression(d, arg)
if("select")
var/text = ""
for(var/datum/t in objs)
text += "<A HREF='?_src_=vars;Vars=\ref[t]'>\ref[t]</A>"
if(istype(t, /atom))
var/atom/a = t
if(copytext(v, 1, 8) == "global.") // Global proc.
spawn()
call("/proc/[copytext(v, 8)]")(arglist(arguments))
else if(d)
if(hascall(d, v))
spawn()
call(d, v)(arglist(arguments)) // Spawn in case the function sleeps.
if(a.x)
text += ": [t] at ([a.x], [a.y], [a.z])<br>"
if("delete")
for(var/datum/d in objs)
del(d)
else if(a.loc && a.loc.x)
text += ": [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])<br>"
if("select")
var/text = ""
for(var/datum/t in objs)
text += "<A HREF='?_src_=vars;Vars=\ref[t]'>\ref[t]</A>"
if(istype(t, /atom))
var/atom/a = t
if(a.x)
text += ": [t] at ([a.x], [a.y], [a.z])<br>"
else if(a.loc && a.loc.x)
text += ": [t] in [a.loc] at ([a.loc.x], [a.loc.y], [a.loc.z])<br>"
else
text += ": [t]<br>"
else
text += ": [t]<br>"
else
text += ": [t]<br>"
usr << browse(text, "window=SDQL-result")
usr << browse(text, "window=SDQL-result")
if("update")
if("set" in query_tree)
var/list/set_list = query_tree["set"]
for(var/datum/d in objs)
var/list/vals = list()
for(var/v in set_list)
if(v in d.vars)
vals += v
vals[v] = SDQL_expression(d, set_list[v])
if("update")
if("set" in query_tree)
var/list/set_list = query_tree["set"]
for(var/datum/d in objs)
var/list/vals = list()
for(var/v in set_list)
if(v in d.vars)
vals += v
vals[v] = SDQL_expression(d, set_list[v])
if(istype(d, /turf))
for(var/v in vals)
if(v == "x" || v == "y" || v == "z")
continue
if(istype(d, /turf))
for(var/v in vals)
if(v == "x" || v == "y" || v == "z")
continue
d.vars[v] = vals[v]
d.vars[v] = vals[v]
else
for(var/v in vals)
d.vars[v] = vals[v]
else
for(var/v in vals)
d.vars[v] = vals[v]
catch(var/exception/e)
usr << "<span class='warning'>A runtime error has occured during the execution of your query and your query has been aborted.</span>"
usr << "[e]"
/proc/SDQL_parse(list/query_list)
var/datum/SDQL_parser/parser = new()
@@ -350,6 +361,12 @@
else if(copytext(expression[i], 1, 2) in list("'", "\""))
val = copytext(expression[i], 2, length(expression[i]))
else if(expression[i] == "{")
var/list/expressions_list = expression[++i]
val = list()
for(var/list/expression_list in expressions_list)
val += SDQL_expression(object, expression_list)
else
val = SDQL_var(object, expression, i)
i = expression.len
@@ -357,22 +374,39 @@
return list("val" = val, "i" = i)
/proc/SDQL_var(datum/object, list/expression, start = 1)
var/v
if(expression[start] in object.vars)
if(start < expression.len && expression[start + 1] == ".")
return SDQL_var(object.vars[expression[start]], expression[start + 2])
v = object.vars[expression[start]]
else if(expression[start] == "src")
v = object
else if(expression[start] == "usr")
v = usr
else if(expression[start] == "marked")
if(usr.client && usr.client.holder && usr.client.holder.marked_datum)
v = usr.client.holder.marked_datum
else
return object.vars[expression[start]]
return null
else if(expression[start] == "\[" && start < expression.len)
if(lowertext(copytext(expression[start + 1], 1, 3)) != "0x")
usr << "<span class='danger'>Invalid ref syntax: [expression[start + 1]]</span>"
return null
v = locate("\[[expression[start + 1]]\]")
if(!v)
usr << "<span class='danger'>Invalid ref: [expression[start + 1]]</span>"
return null
start++
else
return null
if(start < expression.len && expression[start + 1] == ".")
return SDQL_var(v, expression[start + 2])
else
return v
/proc/SDQL2_tokenize(query_text)
var/list/whitespace = list(" ", "\n", "\t")
var/list/single = list("(", ")", ",", "+", "-", ".", ";")
var/list/single = list("(", ")", ",", "+", "-", ".", ";", "\[", "\]", "{", "}")
var/list/multi = list(
"=" = list("", "="),
"<" = list("", "=", ">"),
@@ -25,18 +25,19 @@
//
// assignments : assignment, [',' assignments]
// assignment : <variable name> '=' expression
// variable : <variable name> | <variable name> '.' variable
// variable : <variable name> | <variable name> '.' variable | '[' <hex number> ']' | '[' <hex number> ']' '.' variable
//
// bool_expression : expression comparitor expression [bool_operator bool_expression]
// expression : ( unary_expression | '(' expression ')' | value ) [binary_operator expression]
// unary_expression : unary_operator ( unary_expression | value | '(' expression ')' )
// comparitor : '=' | '==' | '!=' | '<>' | '<' | '<=' | '>' | '>='
// value : variable | string | number | 'null'
// value : variable | string | array | number | 'null'
// unary_operator : '!' | '-' | '~'
// binary_operator : comparitor | '+' | '-' | '/' | '*' | '&' | '|' | '^'
// bool_operator : 'AND' | '&&' | 'OR' | '||'
//
// string : ''' <some text> ''' | '"' <some text > '"'
// array : '{' [arguments] '}'
// number : <some digits>
//
//////////
@@ -337,6 +338,13 @@
var/list/L = list(token(i))
node[++node.len] = L
if(token(i) == "\[")
L += token(i + 1)
i += 2
if(token(i) != "\]")
parse_error("Missing \] at end of reference.")
if(token(i + 1) == ".")
L += "."
i = variable(i + 2, L)
@@ -394,19 +402,54 @@
return i + 1
//array: '{' expression, expression, ... '}'
array(var/i, var/list/node)
// Arrays get turned into this: list("{", list(exp_1a = exp_1b, ...), ...), "{" is to mark the next node as an array.
if(copytext(token(i), 1, 2) != "{")
parse_error("Expected an array but found '[token(i)]'")
return i + 1
node += token(i) // Add the "{"
var/list/expression_list = list()
if(token(i + 1) != "}")
var/list/temp_expression_list = list()
do
i = expression(i + 1, temp_expression_list)
if(token(i) == ",")
expression_list[++expression_list.len] = temp_expression_list
temp_expression_list = list()
while(token(i) && token(i) != "}")
expression_list[++expression_list.len] = temp_expression_list
else
i++
node[++node.len] = expression_list
return i + 1
//call_function: <function name> ['(' [arguments] ')']
call_function(i, list/node, list/arguments)
var/list/cur_argument = list()
if(length(tokenl(i)))
node += token(i++)
var/procname = ""
if(tokenl(i) == "global" && token(i + 1) == ".") // Global proc.
i += 2
procname = "global."
node += procname + token(i++)
if(token(i) != "(")
parse_error("Expected ( but found '[token(i)]'")
else if(token(i + 1) != ")")
do
i = expression(i + 1, arguments)
i = expression(i + 1, cur_argument)
if(token(i) == ",")
arguments += list(cur_argument)
cur_argument = list()
continue
while(token(i) && token(i) != ")")
arguments += list(cur_argument)
else
i++
else
@@ -516,6 +559,10 @@
node += "null"
i++
else if(lowertext(copytext(token(i), 1, 3)) == "0x" && isnum(hex2num(copytext(token(i), 3))))
node += hex2num(copytext(token(i), 3))
i++
else if(isnum(text2num(token(i))))
node += text2num(token(i))
i++
@@ -523,6 +570,9 @@
else if(copytext(token(i), 1, 2) in list("'", "\""))
i = string(i, node)
else if(copytext(token(i), 1, 2) == "{") // Start a list.
i = array(i, node)
else
i = variable(i, node)
+5 -28
View File
@@ -9,7 +9,6 @@
use_power = 1
idle_power_usage = 40
var/tickets = 0
var/prize_tier = 1 //Increased by matter bin rating, unlocks more prize options per tier
/obj/machinery/prize_counter/New()
..()
@@ -21,20 +20,6 @@
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
RefreshParts()
/obj/machinery/prize_counter/upgraded/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/prize_counter(null)
component_parts += new /obj/item/weapon/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
component_parts += new /obj/item/stack/cable_coil(null, 1)
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
RefreshParts()
/obj/machinery/prize_counter/RefreshParts()
for(var/obj/item/weapon/stock_parts/matter_bin/B in component_parts)
prize_tier = B.rating
/obj/machinery/prize_counter/update_icon()
if(stat & BROKEN)
icon_state = "prize_counter-broken"
@@ -161,19 +146,11 @@ td.cost.toomuch {
<p>[item.desc]</p>
</td>
"}
if(prize_tier >= item.tier_unlocked)
dat += {"
<td class="cost [cost_class]">
<a href="byond://?src=\ref[src];buy=[itemID]">[item.cost] Tickets</a>
</td>
</tr>
"}
else
dat += {"
<td>
LOCKED.
</td>
</tr>
dat += {"
<td class="cost [cost_class]">
<a href="byond://?src=\ref[src];buy=[itemID]">[item.cost] Tickets</a>
</td>
</tr>
"}
dat += {"
+6 -52
View File
@@ -32,7 +32,6 @@ var/global/datum/prizes/global_prizes = new
var/desc = "This shouldn't show up..."
var/typepath = /obj/item/toy/prizeball
var/cost = 0
var/tier_unlocked = 0 //minimum tier needed to unlock the ability to select this prize
//////////////////////////////////////
// Tier 1 Prizes //
@@ -43,84 +42,72 @@ var/global/datum/prizes/global_prizes = new
desc = "A thin balloon for throwing liquid at people."
typepath = /obj/item/toy/balloon
cost = 10
tier_unlocked = 1
/datum/prize_item/crayons
name = "Box of Crayons"
desc = "A six-pack of crayons, just like back in kindergarten."
typepath = /obj/item/weapon/storage/fancy/crayons
cost = 35
tier_unlocked = 1
/datum/prize_item/snappops
name = "Snap-Pops"
desc = "A box of exploding snap-pop fireworks."
typepath = /obj/item/weapon/storage/box/snappops
cost = 20
tier_unlocked = 1
/datum/prize_item/spinningtoy
name = "Spinning Toy"
desc = "Looks like an authentic Singularity!"
typepath = /obj/item/toy/spinningtoy
cost = 15
tier_unlocked = 1
/datum/prize_item/blinktoy
name = "Blink toy"
desc = "Blink. Blink. Blink."
typepath = /obj/item/toy/blink
cost = 15
tier_unlocked = 1
/datum/prize_item/dice
name = "Dice set"
desc = "A set of assorted dice."
typepath = /obj/item/weapon/storage/box/dice
cost = 20
tier_unlocked = 1
/datum/prize_item/cards
name = "Deck of cards"
desc = "Anyone fancy a game of 52-card Pickup?"
typepath = /obj/item/toy/cards/deck
cost = 25
tier_unlocked = 1
/datum/prize_item/wallet
name = "Colored Wallet"
desc = "Brightly colored and big enough for standard issue ID cards."
typepath = /obj/item/weapon/storage/wallet/color
cost = 50
tier_unlocked = 1
/datum/prize_item/pet_rock
name = "pet rock"
desc = "A pet of your very own!"
typepath = /obj/item/toy/pet_rock
cost = 80
tier_unlocked = 1
/datum/prize_item/foam_darts
name = "Pack of Foam Darts"
desc = "A refill pack of 10 foam darts."
typepath = /obj/item/weapon/storage/box/foam_darts
cost = 20
tier_unlocked = 1
/datum/prize_item/minigibber
name = "Minigibber Toy"
desc = "A model of the station gibber. Probably shouldn't stick your fingers in it."
typepath = /obj/item/toy/minigibber
cost = 60
tier_unlocked = 1
/datum/prize_item/id_sticker
name = "Prisoner ID Sticker"
desc = "A sticker that can make any ID look like a prisoner ID."
typepath = /obj/item/weapon/id_decal/prisoner
cost = 50
tier_unlocked = 1
/datum/prize_item/id_sticker/silver
name = "Silver ID Sticker"
@@ -142,203 +129,170 @@ var/global/datum/prizes/global_prizes = new
desc = "A sticker that can make any ID look like something suspicious..."
typepath = /obj/item/weapon/id_decal/emag
//////////////////////////////////////
// Tier 2 Prizes //
//////////////////////////////////////
/datum/prize_item/carp_plushie
name = "Random Carp Plushie"
desc = "A colorful fish-shaped plush toy."
typepath = /obj/item/toy/prizeball/carp_plushie
cost = 75
tier_unlocked = 2
/datum/prize_item/therapy_doll
name = "Random Therapy Doll"
desc = "A therapeutic doll for relieving stress without being charged with assault."
typepath = /obj/item/toy/prizeball/therapy
cost = 60
tier_unlocked = 2
/datum/prize_item/plushie
name = "Random Animal Plushie"
desc = "A colorful animal-shaped plush toy."
typepath = /obj/item/toy/prizeball/plushie
cost = 75
tier_unlocked = 2
/datum/prize_item/mech_toy
name = "Random Mecha"
desc = "A random mecha figure, collect all 11!"
typepath = /obj/item/toy/prizeball/mech
cost = 75
tier_unlocked = 2
/datum/prize_item/action_figure
name = "Random Action Figure"
desc = "A random action figure, collect them all!"
typepath = /obj/item/toy/prizeball/figure
cost = 75
tier_unlocked = 2
/datum/prize_item/eight_ball
name = "Magic Eight Ball"
desc = "A mystical ball that can divine the future!"
typepath = /obj/item/toy/eight_ball
cost = 40
tier_unlocked = 2
/datum/prize_item/tacticool
name = "Tacticool Turtleneck"
desc = "A cool-looking turtleneck."
typepath = /obj/item/clothing/under/syndicate/tacticool
cost = 90
tier_unlocked = 2
/datum/prize_item/crossbow
name = "Foam Dart Crossbow"
desc = "A toy crossbow that fires foam darts."
typepath = /obj/item/toy/crossbow
cost = 100
tier_unlocked = 2
/datum/prize_item/toy_xeno
name = "Xeno Action Figure"
desc = "A lifelike replica of the horrific xeno scourge."
typepath = /obj/item/toy/toy_xeno
cost = 80
tier_unlocked = 2
/datum/prize_item/fakespell
name = "Fake Spellbook"
desc = "Perform magic! Astound your friends! Get mistaken for an enemy of the corporation!"
typepath = /obj/item/weapon/spellbook/oneuse/fake_gib
cost = 100
tier_unlocked = 2
/datum/prize_item/capgun
name = "Capgun Revolver"
desc = "Do you feel lucky... punk?"
typepath = /obj/item/weapon/gun/projectile/revolver/capgun
cost = 75
tier_unlocked = 2
//////////////////////////////////////
// Tier 3 Prizes //
//////////////////////////////////////
/datum/prize_item/confetti
name = "Confetti Grenade"
desc = "Party time!"
typepath = /obj/item/weapon/grenade/confetti
cost = 65
/datum/prize_item/magic_conch
name = "Magic Conch Shell"
desc = "All hail the magic conch!"
typepath = /obj/item/toy/eight_ball/conch
cost = 100
tier_unlocked = 3
/datum/prize_item/flash
name = "Toy Flash"
desc = "AUGH! MY EYES!"
typepath = /obj/item/toy/flash
cost = 50
tier_unlocked = 3
/datum/prize_item/foamblade
name = "Foam Armblade"
desc = "Perfect for reenacting space horror holo-vids."
typepath = /obj/item/toy/foamblade
cost = 100
tier_unlocked = 3
/datum/prize_item/minimeteor
name = "Mini-Meteor"
desc = "Meteors have been detected on a collision course with your fun times!"
typepath = /obj/item/toy/minimeteor
cost = 50
tier_unlocked = 3
/datum/prize_item/redbutton
name = "Shiny Red Button"
desc = "PRESS IT!"
typepath = /obj/item/toy/redbutton
cost = 100
tier_unlocked = 3
/datum/prize_item/owl
name = "Owl Action Figure"
desc = "Remember: heroes don't grief!"
typepath = /obj/item/toy/owl
cost = 125
tier_unlocked = 3
/datum/prize_item/griffin
name = "Griffin Action Figure"
desc = "If you can't be the best, you can always be the WORST."
typepath = /obj/item/toy/griffin
cost = 125
tier_unlocked = 3
/datum/prize_item/AI
name = "Toy AI Unit"
desc = "Law 1: Maximize fun for crew."
typepath = /obj/item/toy/AI
cost = 75
tier_unlocked = 3
/datum/prize_item/tommygun
name = "Tommygun"
desc = "A replica tommygun that fires foam darts."
typepath = /obj/item/toy/crossbow/tommygun
cost = 175
tier_unlocked = 3
/datum/prize_item/esword
name = "Toy Energy Sword"
desc = "A plastic replica of an energy blade."
typepath = /obj/item/toy/sword
cost = 150
tier_unlocked = 3
/datum/prize_item/blobhat
name = "Blob Hat"
desc = "There's... something... on your head..."
typepath = /obj/item/clothing/head/blob
cost = 125
tier_unlocked = 3
/datum/prize_item/nuke
name = "Nuclear Fun Device"
desc = "Annihilate boredom with an explosion of excitement!"
typepath = /obj/item/toy/nuke
cost = 100
tier_unlocked = 3
//////////////////////////////////////
// Tier 4 Prizes //
//////////////////////////////////////
/datum/prize_item/chainsaw
name = "Toy Chainsaw"
desc = "A full-scale model chainsaw, based on that massacre in Space Texas."
typepath = /obj/item/weapon/twohanded/toy/chainsaw
cost = 200
tier_unlocked = 4
/datum/prize_item/spacesuit
name = "Fake Spacesuit"
desc = "A replica spacesuit. Not actually spaceworthy."
typepath = /obj/item/weapon/storage/box/fakesyndiesuit
cost = 180
tier_unlocked = 4
/datum/prize_item/fakespace
name = "Space Carpet"
desc = "A stack of carpeted floor tiles that resemble space."
typepath = /obj/item/stack/tile/fakespace/loaded
cost = 150
tier_unlocked = 4
/datum/prize_item/bike
name = "Awesome Bike!"
desc = "WOAH."
typepath = /obj/structure/stool/bed/chair/wheelchair/bike
cost = 10000 //max stack + 1 tickets
tier_unlocked = 4
cost = 10000 //max stack + 1 tickets.
+143 -46
View File
@@ -59,8 +59,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
#define BE_CIVILIAN 1
#define RETURN_TO_LOBBY 2
#define MAX_SAVE_SLOTS 10 // Save slots for regular players
#define MAX_SAVE_SLOTS_MEMBER 10 // Save slots for BYOND members
#define MAX_SAVE_SLOTS 20 // Save slots for regular players
#define MAX_SAVE_SLOTS_MEMBER 20 // Save slots for BYOND members
/datum/preferences
//doohickeys for savefiles
@@ -255,7 +255,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
// dat += "Skin pattern: <a href='byond://?src=\ref[user];preference=skin_style;task=input'>Adjust</a><br>"
dat += "<br><b>Handicaps</b><br>"
dat += "\t<a href='?_src_=prefs;preference=disabilities'><b>\[Set Disabilities\]</b></a><br>"
dat += "Limbs: <a href='?_src_=prefs;preference=limbs;task=input'>Adjust</a><br>"
dat += "Limbs and Parts: <a href='?_src_=prefs;preference=limbs;task=input'>Adjust</a><br>"
if(species != "Slime People" && species != "Machine")
dat += "Internal Organs: <a href='?_src_=prefs;preference=organs;task=input'>Adjust</a><br>"
@@ -266,6 +266,12 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
var/status = organ_data[name]
var/organ_name = null
switch(name)
if("chest")
organ_name = "torso"
if("groin")
organ_name = "lower body"
if("head")
organ_name = "head"
if("l_arm")
organ_name = "left arm"
if("r_arm")
@@ -296,7 +302,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
R = all_robolimbs[rlimb_data[name]]
else
R = basic_robolimb
dat += "\t[R.company] [organ_name] prothesis"
dat += "\t[R.company] [organ_name] prosthesis"
else if(status == "amputated")
@@ -350,7 +356,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
dat += "[TextPreview(flavor_text)]...<br>"
dat += "<br>"
if((species in list("Unathi", "Vulpkanin", "Tajaran"))) //Species that have head accessories.
if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) //Species that have head accessories.
var/headaccessoryname = "Head Accessory"
if(species == "Unathi")
headaccessoryname = "Horns"
@@ -358,23 +364,22 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
dat += "<a href='?_src_=prefs;preference=headaccessory;task=input'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(r_headacc, 2)][num2hex(g_headacc, 2)][num2hex(b_headacc, 2)]'><table style='display:inline;' bgcolor='#[num2hex(r_headacc, 2)][num2hex(g_headacc, 2)][num2hex(b_headacc)]'><tr><td>__</td></tr></table></font> "
dat += "Style: <a href='?_src_=prefs;preference=ha_style;task=input'>[ha_style]</a><br>"
if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) //Species that have body markings.
dat += "<br><b>Body Markings</b><br>"
dat += "<a href='?_src_=prefs;preference=markings;task=input'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(r_markings, 2)][num2hex(g_markings, 2)][num2hex(b_markings, 2)]'><table style='display:inline;' bgcolor='#[num2hex(r_markings, 2)][num2hex(g_markings, 2)][num2hex(b_markings)]'><tr><td>__</td></tr></table></font> "
dat += "<br>Style: <a href='?_src_=prefs;preference=m_style;task=input'>[m_style]</a><br>"
var/hairname = "Hair"
if(species == "Machine")
hairname = "Frame Color"
dat += "<br><b>[hairname]</b><br>"
dat += "<br><b>Hair</b><br>"
dat += "<a href='?_src_=prefs;preference=hair;task=input'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(r_hair, 2)][num2hex(g_hair, 2)][num2hex(b_hair, 2)]'><table style='display:inline;' bgcolor='#[num2hex(r_hair, 2)][num2hex(g_hair, 2)][num2hex(b_hair)]'><tr><td>__</td></tr></table></font> "
dat += " <br>Style: <a href='?_src_=prefs;preference=h_style;task=input'>[h_style]</a><br>"
dat += "<br><b>Facial</b><br>"
dat += "<br><b>Facial Hair</b><br>"
dat += "<a href='?_src_=prefs;preference=facial;task=input'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(r_facial, 2)][num2hex(g_facial, 2)][num2hex(b_facial, 2)]'><table style='display:inline;' bgcolor='#[num2hex(r_facial, 2)][num2hex(g_facial, 2)][num2hex(b_facial)]'><tr><td>__</td></tr></table></font> "
dat += " <br>Style: <a href='?_src_=prefs;preference=f_style;task=input'>[f_style]</a><br>"
dat += " <br>Style: <a href='?_src_=prefs;preference=f_style;task=input'>[f_style ? "[f_style]" : "Shaved"]</a><br>"
dat += "<br><b>Eyes</b><br>"
dat += "<a href='?_src_=prefs;preference=eyes;task=input'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(r_eyes, 2)][num2hex(g_eyes, 2)][num2hex(b_eyes, 2)]'><table style='display:inline;' bgcolor='#[num2hex(r_eyes, 2)][num2hex(g_eyes, 2)][num2hex(b_eyes)]'><tr><td>__</td></tr></table></font><br>"
if(species != "Machine")
dat += "<br><b>Eyes</b><br>"
dat += "<a href='?_src_=prefs;preference=eyes;task=input'>Change Color</a> <font face='fixedsys' size='3' color='#[num2hex(r_eyes, 2)][num2hex(g_eyes, 2)][num2hex(b_eyes, 2)]'><table style='display:inline;' bgcolor='#[num2hex(r_eyes, 2)][num2hex(g_eyes, 2)][num2hex(b_eyes)]'><tr><td>__</td></tr></table></font><br>"
if((species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Vulpkanin", "Machine")) || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) //admins can always fuck with this, because they are admins
dat += "<br><b>Body Color</b><br>"
@@ -1060,7 +1065,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN)
if("species")
var/list/new_species = list("Human","Tajaran","Skrell","Unathi","Diona", "Vulpkanin")
var/list/new_species = list("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin")
var/prev_species = species
// var/whitelisted = 0
@@ -1085,8 +1090,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
continue
if(gender == FEMALE && S.gender == MALE)
continue
if( !(species in S.species_allowed))
if(!(species in S.species_allowed))
continue
valid_hairstyles[hairstyle] = hair_styles_list[hairstyle]
if(valid_hairstyles.len)
@@ -1103,7 +1109,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
continue
if(gender == FEMALE && S.gender == MALE)
continue
if( !(species in S.species_allowed))
if(!(species in S.species_allowed))
continue
valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle]
@@ -1138,6 +1144,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
m_style = "None" // No Unathi markings on Tajara
body_accessory = null //no vulptail on humans damnit
//Reset prosthetics.
organ_data = list()
rlimb_data = list()
if("speciesprefs")//oldvox code
speciesprefs = !speciesprefs
@@ -1176,7 +1186,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
if("hair")
if(species == "Human" || species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Machine" || species == "Vulpkanin")
var/input = "Choose your character's hair colour:"
if(species == "Machine")
if(species == "Machine" && !("head" in rlimb_data))
input = "Choose your character's frame colour:"
var/new_hair = input(user, input, "Character Preference", rgb(r_hair, g_hair, b_hair)) as color|null
if(new_hair)
@@ -1188,17 +1198,31 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
var/list/valid_hairstyles = list()
for(var/hairstyle in hair_styles_list)
var/datum/sprite_accessory/S = hair_styles_list[hairstyle]
if( !(species in S.species_allowed))
continue
if(species == "Machine") //Species that can use prosthetic heads.
if(species in S.species_allowed)
if(!rlimb_data["head"])
valid_hairstyles[hairstyle] = S
continue
else
continue
else
if(!rlimb_data["head"])
continue
else if("Human" in S.species_allowed)
valid_hairstyles[hairstyle] = S
continue
else
if(!(species in S.species_allowed))
continue
valid_hairstyles[hairstyle] = hair_styles_list[hairstyle]
valid_hairstyles[hairstyle] = S
var/new_h_style = input(user, "Choose your character's hair style:", "Character Preference") as null|anything in valid_hairstyles
if(new_h_style)
h_style = new_h_style
if("headaccessory")
if((species in list("Unathi", "Vulpkanin", "Tajaran"))) // Species with head accessories
if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) // Species with head accessories
var/input = "Choose the colour of your your character's head accessory:"
var/new_head_accessory = input(user, input, "Character Preference", rgb(r_headacc, g_headacc, b_headacc)) as color|null
if(new_head_accessory)
@@ -1207,11 +1231,11 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
b_headacc = hex2num(copytext(new_head_accessory, 6, 8))
if("ha_style")
if((species in list("Unathi", "Vulpkanin", "Tajaran"))) // Species with head accessories
if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) // Species with head accessories
var/list/valid_head_accessory_styles = list()
for(var/head_accessory_style in head_accessory_styles_list)
var/datum/sprite_accessory/H = head_accessory_styles_list[head_accessory_style]
if( !(species in H.species_allowed))
if(!(species in H.species_allowed))
continue
valid_head_accessory_styles[head_accessory_style] = head_accessory_styles_list[head_accessory_style]
@@ -1221,8 +1245,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
ha_style = new_head_accessory_style
if("markings")
if((species in list("Unathi", "Vulpkanin", "Tajaran"))) // Species with markings
var/input = "Choose the colour of your your character's body markings:"
if(species in list("Unathi", "Vulpkanin", "Tajaran", "Machine")) // Species with markings
var/input = "Choose the colour of your your character's markings:"
var/new_markings = input(user, input, "Character Preference", rgb(r_markings, g_markings, b_markings)) as color|null
if(new_markings)
r_markings = hex2num(copytext(new_markings, 2, 4))
@@ -1230,16 +1254,22 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
b_markings = hex2num(copytext(new_markings, 6, 8))
if("m_style")
if((species in list("Unathi", "Vulpkanin", "Tajaran"))) // Species with markings
if(species in list("Unathi", "Vulpkanin", "Tajaran")) // Species with markings
var/list/valid_markings = list()
for(var/markingstyle in marking_styles_list)
var/datum/sprite_accessory/M = marking_styles_list[markingstyle]
if( !(species in M.species_allowed))
if(!(species in M.species_allowed))
continue
if(species == "Machine") //Species that can use prosthetic heads.
if(!("head" in rlimb_data) && M.name != "None") //If the character can have prosthetic heads and they have the default head (with screen), no optic markings.
continue
else if(("head" in rlimb_data) && M.name == "None") //Otherwise, if they DON'T have the default head and since they must have optics, give them a list of styles excluding the "None" option.
continue
valid_markings[markingstyle] = marking_styles_list[markingstyle]
var/new_marking_style = input(user, "Choose the style of your character's body markings:", "Character Preference") as null|anything in valid_markings
var/new_marking_style = input(user, "Choose the style of your character's markings:", "Character Preference", m_style) as null|anything in valid_markings
if(new_marking_style)
m_style = new_marking_style
@@ -1275,8 +1305,24 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
continue
if(gender == FEMALE && S.gender == MALE)
continue
if( !(species in S.species_allowed))
continue
if(species == "Machine") //Species that can use prosthetic heads.
if(species in S.species_allowed)
if(!rlimb_data["head"])
valid_facialhairstyles[facialhairstyle] = S
continue
else
continue
else
if(!rlimb_data["head"])
continue
else if("Human" in S.species_allowed)
valid_facialhairstyles[facialhairstyle] = S
continue
else
continue
else
if(!(species in S.species_allowed))
continue
valid_facialhairstyles[facialhairstyle] = facial_hair_styles_list[facialhairstyle]
@@ -1370,14 +1416,29 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
flavor_text = msg
if("limbs")
var/limb_name = input(user, "Which limb do you want to change?") as null|anything in list("Left Leg","Right Leg","Left Arm","Right Arm","Left Foot","Right Foot","Left Hand","Right Hand")
var/valid_limbs = list("Left Leg", "Right Leg", "Left Arm", "Right Arm", "Left Foot", "Right Foot", "Left Hand", "Right Hand")
if(species == "Machine")
valid_limbs = list("Torso", "Lower Body", "Head", "Left Leg", "Right Leg", "Left Arm", "Right Arm", "Left Foot", "Right Foot", "Left Hand", "Right Hand")
var/limb_name = input(user, "Which limb do you want to change?") as null|anything in valid_limbs
if(!limb_name) return
var/limb = null
var/second_limb = null // if you try to change the arm, the hand should also change
var/third_limb = null // if you try to unchange the hand, the arm should also change
var/valid_limb_states=list("Normal","Amputated","Prothesis")
var/valid_limb_states = list("Normal", "Amputated", "Prosthesis")
var/no_amputate = 0
switch(limb_name)
if("Torso")
limb = "chest"
second_limb = "groin"
no_amputate = 1
if("Lower Body")
limb = "groin"
no_amputate = 1
if("Head")
limb = "head"
no_amputate = 1
if("Left Leg")
limb = "l_leg"
second_limb = "l_foot"
@@ -1392,37 +1453,50 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
second_limb = "r_hand"
if("Left Foot")
limb = "l_foot"
third_limb = "l_leg"
if(species != "Machine")
third_limb = "l_leg"
if("Right Foot")
limb = "r_foot"
third_limb = "r_leg"
if(species != "Machine")
third_limb = "r_leg"
if("Left Hand")
limb = "l_hand"
third_limb = "l_arm"
if(species != "Machine")
third_limb = "l_arm"
if("Right Hand")
limb = "r_hand"
third_limb = "r_arm"
if(species != "Machine")
third_limb = "r_arm"
var/new_state = input(user, "What state do you wish the limb to be in?") as null|anything in valid_limb_states
if(!new_state) return
switch(new_state)
if("Normal")
if(limb == "head")
m_style = "None"
h_style = random_hair_style(gender, species)
f_style = facial_hair_styles_list["Shaved"]
organ_data[limb] = null
rlimb_data[limb] = null
if(third_limb)
organ_data[third_limb] = null
rlimb_data[third_limb] = null
if("Amputated")
organ_data[limb] = "amputated"
rlimb_data[limb] = null
if(second_limb)
organ_data[second_limb] = "amputated"
rlimb_data[second_limb] = null
if("Prothesis")
if(!no_amputate)
organ_data[limb] = "amputated"
rlimb_data[limb] = null
if(second_limb)
organ_data[second_limb] = "amputated"
rlimb_data[second_limb] = null
if("Prosthesis")
var/choice = input(user, "Which manufacturer do you wish to use for this limb?") as null|anything in chargen_robolimbs
if(!choice)
return
if(limb == "head")
m_style = "Humanoid Optics"
ha_style = "None"
h_style = hair_styles_list["Bald"]
rlimb_data[limb] = choice
organ_data[limb] = "cyborg"
if(second_limb)
@@ -1499,7 +1573,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
UI_style_color = UI_style_color_new
if("UIalpha")
var/UI_style_alpha_new = input(user, "Select a new alpha(transparence) parametr for UI, between 50 and 255") as num
var/UI_style_alpha_new = input(user, "Select a new alpha(transparence) parameter for UI, between 50 and 255", UI_style_alpha) as num
if(!UI_style_alpha_new | !(UI_style_alpha_new <= 255 && UI_style_alpha_new >= 50)) return
UI_style_alpha = UI_style_alpha_new
@@ -1571,6 +1645,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
return 1
/datum/preferences/proc/copy_to(mob/living/carbon/human/character)
var/datum/species/S = all_species[species]
character.change_species(species) // Yell at me if this causes everything to melt
if(be_random_name)
real_name = random_name(gender,species)
@@ -1583,7 +1658,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
else if(firstspace == name_length)
real_name += "[pick(last_names)]"
character.add_language(language)
character.real_name = real_name
character.dna.real_name = real_name
character.name = character.real_name
character.flavor_text = flavor_text
@@ -1616,9 +1694,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
character.h_style = h_style
character.f_style = f_style
// Destroy/cyborgize organs
for(var/name in organ_data)
var/status = organ_data[name]
@@ -1645,15 +1721,30 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
else if(status == "mechanical")
I.robotize()
character.dna.b_type = b_type
if(disabilities & DISABILITY_FLAG_FAT && character.species.flags & CAN_BE_FAT)
character.dna.SetSEState(FATBLOCK,1,1)
character.mutations += FAT
character.mutations += OBESITY
character.overeatduration = 600
if(disabilities & DISABILITY_FLAG_NEARSIGHTED)
character.dna.SetSEState(GLASSESBLOCK,1,1)
character.disabilities|=NEARSIGHTED
if(disabilities & DISABILITY_FLAG_EPILEPTIC)
character.dna.SetSEState(EPILEPSYBLOCK,1,1)
character.disabilities|=EPILEPSY
if(disabilities & DISABILITY_FLAG_DEAF)
character.dna.SetSEState(DEAFBLOCK,1,1)
character.sdisabilities|=DEAF
if(disabilities & DISABILITY_FLAG_MUTE)
character.dna.SetSEState(MUTEBLOCK,1,1)
character.sdisabilities |= MUTE
S.handle_dna(character)
if(character.dna.dirtySE)
character.dna.UpdateSE()
domutcheck(character)
// Wheelchair necessary?
var/obj/item/organ/external/l_foot = character.get_organ("l_foot")
@@ -1694,8 +1785,14 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
message_admins("[key_name_admin(character)] has spawned with their gender as plural or neuter. Please notify coders.")
character.change_gender(MALE)
character.dna.ready_dna(character)
character.dna.ready_dna(character, flatten_SE = 0)
character.sync_organ_dna(assimilate=1)
character.UpdateAppearance()
// Do the initial caching of the player's body icons.
character.force_update_limbs()
character.update_eyes()
character.regenerate_icons()
/datum/preferences/proc/open_load_dialog(mob/user)
+14 -4
View File
@@ -306,8 +306,14 @@ BLIND // can't see anything
user << "You push \the [src] back into place."
mask_adjusted = 0
slot_flags = initial(slot_flags)
if(flags_inv != initial(flags_inv)) //If the mask is one that hides the face and can be adjusted yet lost that trait when it was adjusted, make it hide the face again.
flags_inv += HIDEFACE
if(flags_inv != initial(flags_inv))
if(initial(flags_inv) & HIDEFACE) //If the mask is one that hides the face and can be adjusted yet lost that trait when it was adjusted, make it hide the face again.
flags_inv |= HIDEFACE
if(flags != initial(flags))
if(initial(flags) & MASKCOVERSMOUTH) //If the mask covers the mouth when it's down and can be adjusted yet lost that trait when it was adjusted, make it cover the mouth again.
flags |= MASKCOVERSMOUTH
if(initial(flags) & AIRTIGHT) //If the mask is airtight and thus, one that you'd be able to run internals from yet can't because it was adjusted, make it airtight again.
flags |= AIRTIGHT
if(H.head == src)
if(flags_inv == HIDEFACE) //Means that only things like bandanas and balaclavas will be affected since they obscure the identity of the wearer.
if(H.l_hand && H.r_hand) //If both hands are occupied, drop the object on the ground.
@@ -331,9 +337,13 @@ BLIND // can't see anything
if(H.internals)
H.internals.icon_state = "internal0"
H.internal = null
if(flags_inv == HIDEFACE) //Means that only things like bandanas and balaclavas will be affected since they obscure the identity of the wearer.
flags_inv -= HIDEFACE /*Done after the above to avoid having to do a check for initial(src.flags_inv == HIDEFACE).
if(flags_inv & HIDEFACE) //Means that only things like bandanas and balaclavas will be affected since they obscure the identity of the wearer.
flags_inv &= ~HIDEFACE /*Done after the above to avoid having to do a check for initial(src.flags_inv == HIDEFACE).
This reveals the user's face since the bandana will now be going on their head.*/
if(flags & MASKCOVERSMOUTH) //Mask won't cover the mouth any more since it's been pushed out of the way. Allows for CPRing with adjusted masks.
flags &= ~MASKCOVERSMOUTH
if(flags & AIRTIGHT) //If the mask was airtight, it won't be anymore since you just pushed it off your face.
flags &= ~AIRTIGHT
if(user.wear_mask == src)
if(initial(flags_inv) == HIDEFACE) //Means that you won't have to take off and put back on simple things like breath masks which, realistically, can just be pulled down off your face.
if(H.l_hand && H.r_hand) //If both hands are occupied, drop the object on the ground.
+7 -1
View File
@@ -360,4 +360,10 @@
name = "Lord Admiral's Hat"
desc = "A hat suitable for any man of high and exalted rank."
icon_state = "lordadmiralhat"
item_state = "lordadmiralhat"
item_state = "lordadmiralhat"
/obj/item/clothing/head/human_head
name = "bloated human head"
desc = "A horribly bloated and mismatched human head."
icon_state = "lingspacehelmet"
item_state = "lingspacehelmet"
@@ -18,6 +18,7 @@
/obj/item/clothing/shoes/combat //basic syndicate combat boots for nuke ops and mob corpses
name = "combat boots"
desc = "High speed, low drag combat boots."
can_cut_open = 1
icon_state = "jackboots"
item_state = "jackboots"
armor = list(melee = 50, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 10, rad = 0)
@@ -93,6 +94,7 @@
/obj/item/clothing/shoes/jackboots/jacksandals
name = "jacksandals"
desc = "Nanotrasen-issue Security combat sandals for combat scenarios. They're jacksandals, however that works."
can_cut_open = 0
icon_state = "jacksandal"
item_color = "jacksandal"
species_restricted = null
+3 -3
View File
@@ -8,7 +8,7 @@
icon_state = "paramedic-vest"
item_state = "paramedic-vest"
allowed = list(/obj/item/stack/medical, /obj/item/weapon/reagent_containers/dropper, /obj/item/weapon/reagent_containers/hypospray, /obj/item/weapon/reagent_containers/syringe, \
/obj/item/device/healthanalyzer, /obj/item/device/antibody_scanner, /obj/item/device/flashlight, /obj/item/device/radio, /obj/item/weapon/tank/emergency_oxygen,/obj/item/device/rad_laser)
/obj/item/device/healthanalyzer, /obj/item/device/flashlight, /obj/item/device/radio, /obj/item/weapon/tank/emergency_oxygen,/obj/item/device/rad_laser)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 10)
species_fit = list("Vox")
sprite_sheets = list(
@@ -22,7 +22,7 @@
icon_state = "brigphysician-vest"
item_state = "brigphysician-vest"
allowed = list(/obj/item/stack/medical, /obj/item/weapon/reagent_containers/dropper, /obj/item/weapon/reagent_containers/hypospray, /obj/item/weapon/reagent_containers/syringe, \
/obj/item/device/healthanalyzer, /obj/item/device/antibody_scanner, /obj/item/device/flashlight, \
/obj/item/device/healthanalyzer, /obj/item/device/flashlight, \
/obj/item/device/radio, /obj/item/weapon/tank/emergency_oxygen,/obj/item/device/rad_laser)
armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 0)
@@ -253,7 +253,7 @@
item_state = "fr_jacket_open"
blood_overlay_type = "armor"
allowed = list(/obj/item/stack/medical, /obj/item/weapon/reagent_containers/dropper, /obj/item/weapon/reagent_containers/hypospray, /obj/item/weapon/reagent_containers/syringe, \
/obj/item/device/healthanalyzer, /obj/item/device/antibody_scanner, /obj/item/device/flashlight, /obj/item/device/radio, /obj/item/weapon/tank/emergency_oxygen,/obj/item/device/rad_laser)
/obj/item/device/healthanalyzer, /obj/item/device/flashlight, /obj/item/device/radio, /obj/item/weapon/tank/emergency_oxygen,/obj/item/device/rad_laser)
ignore_suitadjust = 0
suit_adjusted = 1
action_button_name = "Button/Unbutton Jacket"
+1 -1
View File
@@ -7,7 +7,7 @@
suit_adjusted = 1
blood_overlay_type = "coat"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
allowed = list(/obj/item/device/analyzer,/obj/item/device/antibody_scanner,/obj/item/stack/medical,/obj/item/weapon/dnainjector,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/syringe,/obj/item/weapon/reagent_containers/hypospray,/obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen,/obj/item/weapon/reagent_containers/glass/bottle,/obj/item/weapon/reagent_containers/glass/beaker,/obj/item/weapon/reagent_containers/food/pill,/obj/item/weapon/storage/pill_bottle,/obj/item/weapon/paper,/obj/item/device/rad_laser)
allowed = list(/obj/item/device/analyzer,/obj/item/stack/medical,/obj/item/weapon/dnainjector,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/syringe,/obj/item/weapon/reagent_containers/hypospray,/obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen,/obj/item/weapon/reagent_containers/glass/bottle,/obj/item/weapon/reagent_containers/glass/beaker,/obj/item/weapon/reagent_containers/food/pill,/obj/item/weapon/storage/pill_bottle,/obj/item/weapon/paper,/obj/item/device/rad_laser)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 50, rad = 0)
species_fit = list("Vox")
sprite_sheets = list(
+25 -2
View File
@@ -224,6 +224,14 @@
item_state = "ponchoshame"
flags = NODROP
/obj/item/clothing/suit/bloated_human //OH MY GOD WHAT HAVE YOU DONE!?!?!?
name = "bloated human suit"
desc = "A horribly bloated suit made from human skins."
icon_state = "lingspacesuit"
item_state = "lingspacesuit"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
/*
* Misc
*/
@@ -335,8 +343,8 @@
item_color = "mankini"
/obj/item/clothing/suit/jacket/miljacket
name = "military jacket"
desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable."
name = "olive military jacket"
desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable. This one comes in olive."
icon_state = "militaryjacket"
item_state = "militaryjacket"
ignore_suitadjust = 1
@@ -344,6 +352,21 @@
adjust_flavour = null
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/toy,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/lighter,/obj/item/weapon/gun/projectile/automatic/pistol,/obj/item/weapon/gun/projectile/revolver,/obj/item/weapon/gun/projectile/revolver/detective)
/obj/item/clothing/suit/jacket/miljacket/navy
name = "navy military jacket"
desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable. This one comes in navy blue."
icon_state = "navy_jacket"
/obj/item/clothing/suit/jacket/miljacket/desert
name = "desert military jacket"
desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable. This one comes in desert beige."
icon_state = "desert_jacket"
/obj/item/clothing/suit/jacket/miljacket/white
name = "white military jacket"
desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable. This one comes in snow white."
icon_state = "white_jacket"
/obj/item/clothing/suit/xenos
name = "xenos suit"
desc = "A suit made out of chitinous alien hide."
@@ -339,13 +339,79 @@
/obj/item/clothing/accessory/petcollar
name = "pet collar"
desc = "The latest fashion accessory for your favorite pets!"
icon_state = "petcollar"
item_color = "petcollar"
var/tagname = null
var/obj/item/weapon/card/id/access_id
/obj/item/clothing/accessory/petcollar/Destroy()
if(access_id)
qdel(access_id)
access_id = null
processing_objects -= src
return ..()
/obj/item/clothing/accessory/petcollar/attack_self(mob/user as mob)
tagname = copytext(sanitize(input(user, "Would you like to change the name on the tag?", "Name your new pet", "Spot") as null|text),1,MAX_NAME_LEN)
name = "[initial(name)] - [tagname]"
var/option = "Change Name"
if(access_id)
option = input(user, "What do you want to do?", "[src]", option) as null|anything in list("Change Name", "Remove ID")
switch(option)
if("Change Name")
var/t = input(user, "Would you like to change the name on the tag?", "Name your new pet", tagname ? tagname : "Spot") as null|text
if(t)
tagname = copytext(sanitize(t), 1, MAX_NAME_LEN)
name = "[initial(name)] - [tagname]"
if("Remove ID")
if(access_id)
user.visible_message("<span class='warning'>[user] starts unclipping \the [access_id] from \the [src].</span>")
if(do_after(user, 50, target = user) && access_id)
user.visible_message("<span class='warning'>[user] unclips \the [access_id] from \the [src].</span>")
access_id.forceMove(get_turf(user))
user.put_in_hands(access_id)
access_id = null
/obj/item/clothing/accessory/petcollar/attackby(obj/item/weapon/card/id/W, mob/user, params)
if(!istype(W))
return ..()
if(access_id)
user << "<span class='warning'>There is already \a [access_id] clipped onto \the [src]</span>"
user.drop_item()
W.forceMove(src)
access_id = W
user << "<span class='notice'>\The [W] clips onto \the [src] snugly.</span>"
/obj/item/clothing/accessory/petcollar/GetAccess()
return access_id ? access_id.GetAccess() : ..()
/obj/item/clothing/accessory/petcollar/examine(mob/user)
..()
if(access_id)
user << "There is \icon[access_id] \a [access_id] clipped onto it."
/obj/item/clothing/accessory/petcollar/equipped(mob/living/simple_animal/user)
if(istype(user))
processing_objects |= src
/obj/item/clothing/accessory/petcollar/dropped(mob/living/simple_animal/user)
processing_objects -= src
/obj/item/clothing/accessory/petcollar/process()
var/mob/living/simple_animal/M = loc
// if it wasn't intentionally unequipped but isn't being worn, possibly gibbed
if(istype(M) && src == M.collar && M.stat != DEAD)
return
var/area/t = get_area(M)
var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null)
if(istype(t, /area/syndicate_station) || istype(t, /area/syndicate_mothership) || istype(t, /area/shuttle/syndicate_elite) )
//give the syndicats a bit of stealth
a.autosay("[M] has been vandalized in Space!", "[M]'s Death Alarm")
else
a.autosay("[M] has been vandalized in [t.name]!", "[M]'s Death Alarm")
qdel(a)
processing_objects -= src
/proc/english_accessory_list(obj/item/clothing/under/U)
if(!istype(U) || !U.accessories.len)
+1 -7
View File
@@ -116,7 +116,6 @@
dat += text("\n<A href='?src=\ref[];print_p=1'>Print Record</A><BR>\n<A href='?src=\ref[];screen=2'>Back</A><BR>", src, src)
if(5.0)
dat += "<CENTER><B>Virus Database</B></CENTER>"
/* Advanced diseases is weak! Feeble! Glory to virus2!
for(var/Dt in typesof(/datum/disease/))
var/datum/disease/Dis = new Dt(0)
if(istype(Dis, /datum/disease/advance))
@@ -124,18 +123,13 @@
if(!Dis.desc)
continue
dat += "<br><a href='?src=\ref[src];vir=[Dt]'>[Dis.name]</a>"
*/
for (var/ID in virusDB)
var/datum/data/record/v = virusDB[ID]
dat += "<br><a href='?src=\ref[src];vir=\ref[v]'>[v.fields["name"]]</a>"
dat += "<br><a href='?src=\ref[src];screen=1'>Back</a>"
if(6.0)
dat += "<center><b>Medical Robot Monitor</b></center>"
dat += "<a href='?src=\ref[src];screen=1'>Back</a>"
dat += "<br><b>Medical Robots:</b>"
var/bdat = null
for(var/obj/machinery/bot/medbot/M in world)
for(var/mob/living/simple_animal/bot/medbot/M in world)
if(M.z != computer.z) continue //only find medibots on the same z-level as the computer
var/turf/bl = get_turf(M)
+14 -6
View File
@@ -36,7 +36,7 @@
/datum/table_recipe/ed209
name = "ED209"
result = /obj/machinery/bot/ed209
result = /mob/living/simple_animal/bot/ed209
reqs = list(/obj/item/robot_parts/robot_suit = 1,
/obj/item/clothing/head/helmet = 1,
/obj/item/clothing/suit/armor/vest = 1,
@@ -53,7 +53,7 @@
/datum/table_recipe/secbot
name = "Secbot"
result = /obj/machinery/bot/secbot
result = /mob/living/simple_animal/bot/secbot
reqs = list(/obj/item/device/assembly/signaler = 1,
/obj/item/clothing/head/helmet = 1,
/obj/item/weapon/melee/baton = 1,
@@ -64,7 +64,7 @@
/datum/table_recipe/cleanbot
name = "Cleanbot"
result = /obj/machinery/bot/cleanbot
result = /mob/living/simple_animal/bot/cleanbot
reqs = list(/obj/item/weapon/reagent_containers/glass/bucket = 1,
/obj/item/device/assembly/prox_sensor = 1,
/obj/item/robot_parts/r_arm = 1)
@@ -72,7 +72,7 @@
/datum/table_recipe/floorbot
name = "Floorbot"
result = /obj/machinery/bot/floorbot
result = /mob/living/simple_animal/bot/floorbot
reqs = list(/obj/item/weapon/storage/toolbox/mechanical = 1,
/obj/item/stack/tile/plasteel = 1,
/obj/item/device/assembly/prox_sensor = 1,
@@ -81,7 +81,7 @@
/datum/table_recipe/medbot
name = "Medbot"
result = /obj/machinery/bot/medbot
result = /mob/living/simple_animal/bot/medbot
reqs = list(/obj/item/device/healthanalyzer = 1,
/obj/item/weapon/storage/firstaid = 1,
/obj/item/device/assembly/prox_sensor = 1,
@@ -192,4 +192,12 @@
result = /obj/item/weapon/soap/ducttape
time = 100
reqs = list(/obj/item/stack/tape_roll = 1,
/datum/reagent/liquidgibs = 10)
/datum/reagent/liquidgibs = 10)
/datum/table_recipe/garrote
name = "Makeshift Garrote"
result = /obj/item/weapon/twohanded/garrote/improvised
time = 15
reqs = list(/obj/item/stack/sheet/wood = 1,
/obj/item/stack/cable_coil = 5)
tools = list(/obj/item/weapon/kitchen/knife) // Gotta carve the wood into handles
+7
View File
@@ -149,6 +149,13 @@
new /obj/item/weapon/reagent_containers/food/drinks/cans/cola(src)
/obj/item/device/guitar/jello_guitar //Antcolon3: Dan Jello
name = "Dan Jello's Pink Guitar"
desc = "Dan Jello's special pink guitar."
icon = 'icons/obj/custom_items.dmi'
icon_state = "jello_guitar"
item_state = "jello_guitar"
//////////////////////////////////
//////////// Clothing ////////////
//////////////////////////////////
-2
View File
@@ -151,7 +151,6 @@ var/list/event_last_fired = list()
//new /datum/event_meta(EVENT_LEVEL_MODERATE, "Grid Check", /datum/event/grid_check, 200, list(ASSIGNMENT_ENGINEER = 60)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Electrical Storm", /datum/event/electrical_storm, 250, list(ASSIGNMENT_ENGINEER = 20, ASSIGNMENT_JANITOR = 150)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Radiation Storm", /datum/event/radiation_storm, 0, list(ASSIGNMENT_MEDICAL = 50), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 150)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 100, list(ASSIGNMENT_SECURITY = 30), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Ion Storm", /datum/event/ion_storm, 0, list(ASSIGNMENT_AI = 50, ASSIGNMENT_CYBORG = 50, ASSIGNMENT_ENGINEER = 15, ASSIGNMENT_SCIENTIST = 5)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Borer Infestation", /datum/event/borer_infestation, 40, list(ASSIGNMENT_SECURITY = 30), 1),
@@ -179,7 +178,6 @@ var/list/event_last_fired = list()
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Nothing", /datum/event/nothing, 1320),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 3), 1),
//new /datum/event_meta(EVENT_LEVEL_MAJOR, "Containment Breach", /datum/event/prison_break/station, 0, list(ASSIGNMENT_ANY = 5)),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 30), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, 0, list(ASSIGNMENT_ENGINEER = 30), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 3), 1),
new /datum/event_meta/alien(EVENT_LEVEL_MAJOR, "Alien Infestation", /datum/event/alien_infestation, 0, list(ASSIGNMENT_SECURITY = 30), 1),
+2 -2
View File
@@ -32,9 +32,9 @@
M << "<br>"
if(botEmagChance)
for(var/obj/machinery/bot/bot in machines)
for(var/mob/living/simple_animal/bot/bot in machines)
if(prob(botEmagChance))
bot.Emag()
bot.emag_act()
/proc/generate_ion_law(ionMessage)
if(ionMessage)
+12 -8
View File
@@ -325,29 +325,33 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/hallucination/delusion
var/list/image/delusions = list()
/obj/effect/hallucination/delusion/New(loc,var/mob/living/carbon/T)
/obj/effect/hallucination/delusion/New(loc, mob/living/carbon/T, force_kind = null, duration = 300,skip_nearby = 1, custom_icon = null, custom_icon_file = null)
target = T
var/image/A = null
var/kind = rand(1,3)
var/kind = force_kind ? force_kind : pick("clown", "corgi", "carp", "skeleton", "demon")
for(var/mob/living/carbon/human/H in living_mob_list)
if(H == target)
continue
if(H in view(target))
if(skip_nearby && (H in view(target)))
continue
switch(kind)
if(1)//Clown
if("clown")//Clown
A = image('icons/mob/animal.dmi',H,"clown")
if(2)//Carp
if("carp")//Carp
A = image('icons/mob/animal.dmi',H,"carp")
if(3)//Corgi
if("corgi")//Corgi
A = image('icons/mob/pets.dmi',H,"corgi")
if(4)//Skeletons
if("skeleton")//Skeletons
A = image('icons/mob/human.dmi',H,"skeleton_s")
if("demon")//Demon
A = image('icons/mob/mob.dmi',H,"daemon")
if("custom")
A = image(custom_icon_file, H, custom_icon)
A.override = 1
if(target.client)
delusions |= A
target.client.images |= A
sleep(300)
sleep(duration)
for(var/image/I in delusions)
if(target.client)
target.client.images.Remove(I)
-7
View File
@@ -651,13 +651,6 @@ datum/recipe/microwave/slimesandwich
)
result = /obj/item/weapon/reagent_containers/food/snacks/sashimi
// Fuck Science!
/datum/recipe/microwave/ruinedvirusdish
items = list(
/obj/item/weapon/virusdish
)
result = /obj/item/weapon/ruinedvirusdish
/datum/recipe/microwave/mashedtaters
fruit = list("potato" = 1)
reagents = list("gravy" = 5)
+1 -1
View File
@@ -78,4 +78,4 @@
/obj/item/dropped()
. = ..()
update_light()
update_light()
+3 -3
View File
@@ -52,9 +52,9 @@
if(lum_r / mx1 != (lum_r + delta_r) / mx2 || lum_g / mx1 != (lum_g + delta_g) / mx2 || lum_b / mx1 != (lum_b + delta_b) / mx2) //Stuff would change.
should_update = 1
lum_r += delta_r
lum_g += delta_g
lum_b += delta_b
lum_r = max(lum_r + delta_r, 0) //Lum shouldn't drop below 1
lum_g = max(lum_g + delta_g, 0)
lum_b = max(lum_b + delta_b, 0)
if(!needs_update && should_update)
needs_update = 1
+10 -16
View File
@@ -20,7 +20,7 @@
var/sheet_per_ore = 1
var/point_upgrade = 1
var/list/ore_values = list(("sand" = 1), ("iron" = 1), ("plasma" = 15), ("silver" = 16), ("gold" = 18), ("uranium" = 30), ("diamond" = 50), ("bananium" = 60), ("tranquillite" = 60))
var/list/supply_consoles = list("Science", "Robotics", "Research Director's Desk", "Mechanic", "Engineering" = list("metal", "glass", "plasma"), "Chief Engineer's Desk" = list("metal", "glass", "plasma"), "Atmospherics" = list("metal", "glass", "plasma"), "Bar" = list("uranium", "plasma"))
var/list/supply_consoles = list("Science", "Robotics", "Research Director's Desk", "Mechanic", "Engineering" = list("metal", "glass", "plasma"), "Chief Engineer's Desk" = list("metal", "glass", "plasma"), "Atmospherics" = list("metal", "glass", "plasma"), "Bar" = list("uranium", "plasma"), "Virology" = list("uranium", "gold"))
/obj/machinery/mineral/ore_redemption/New()
..()
@@ -556,14 +556,15 @@
L.Weaken(3)
if(ishuman(L))
shake_camera(L, 20, 1)
var/mob/living/carbon/human/H = L
spawn(20)
if(L)
L.visible_message("<span class='danger'>[L.name] vomits from travelling through the [src.name]!</span>", "<span class='userdanger'>You throw up from travelling through the [src.name]!</span>")
L.nutrition -= 20
L.adjustToxLoss(-3)
var/turf/T = get_turf(L)
T.add_vomit_floor(L)
playsound(L, 'sound/effects/splat.ogg', 50, 1)
if(H && H.check_has_mouth())
H.visible_message("<span class='danger'>[L.name] vomits from travelling through the [src.name]!</span>", "<span class='userdanger'>You throw up from travelling through the [src.name]!</span>")
H.nutrition -= 20
H.adjustToxLoss(-3)
var/turf/T = get_turf(H)
T.add_vomit_floor(H)
playsound(H, 'sound/effects/splat.ogg', 50, 1)
/**********************Resonator**********************/
@@ -693,14 +694,7 @@
mouse_opacity = 1
faction = list("neutral")
a_intent = I_HARM
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
wander = 0
idle_vision_range = 5
@@ -257,6 +257,13 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return 1
/mob/dead/observer/proc/notify_cloning(var/message, var/sound, var/atom/source)
if(message)
src << "<span class='ghostalert'>[message]</span>"
src << "<span class='ghostalert'><a href=?src=\ref[src];reenter=1>(Click to re-enter)</a></span>"
if(sound)
src << sound(sound)
/mob/dead/observer/proc/show_me_the_hud(hud_index)
var/datum/atom_hud/H = huds[hud_index]
H.add_hud_to(src)
@@ -643,6 +650,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/mob/living/carbon/human/new_char = new(get_turf(src))
client.prefs.copy_to(new_char)
if(mind)
mind.active = 1
mind.transfer_to(new_char)
else
new_char.key = key
+2 -2
View File
@@ -114,7 +114,7 @@
message = stars(message)
var/speaker_name = "unknown"
if(speaker)
if(speaker)
speaker_name = speaker.name
if(vname)
@@ -160,7 +160,7 @@
else
track = "[speaker_name] ([jobname])"
else
if(istype(follow_target, /obj/machinery/bot))
if(istype(follow_target, /mob/living/simple_animal/bot))
track = "<a href='byond://?src=\ref[src];trackbot=\ref[follow_target]'>[speaker_name] ([jobname])</a>"
else
track = "<a href='byond://?src=\ref[src];track=\ref[speaker]'>[speaker_name] ([jobname])</a>"
@@ -196,7 +196,7 @@
usr.hud_used.nightvisionicon.icon_state = "nightvision0"
/mob/living/carbon/alien/assess_threat(var/obj/machinery/bot/secbot/judgebot, var/lasercolor)
/mob/living/carbon/alien/assess_threat(var/mob/living/simple_animal/bot/secbot/judgebot, var/lasercolor)
if(judgebot.emagged == 2)
return 10 //Everyone is a criminal!
var/threatcount = 0
@@ -2,6 +2,7 @@
name = "alien"
icon_state = "alien_s"
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/xenomeat = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
var/obj/item/weapon/r_store = null
var/obj/item/weapon/l_store = null
var/caste = ""
@@ -317,22 +318,27 @@ In all, this is a lot like the monkey code. /N
/mob/living/carbon/alien/humanoid/var/temperature_resistance = T0C+75
/mob/living/carbon/alien/humanoid/show_inv(mob/user as mob)
user.set_machine(src)
var/dat = {"
<B><HR><FONT size=3>[name]</FONT></B>
<BR><HR>
<BR><B>Left Hand:</B> <A href='?src=\ref[src];item=l_hand'>[(l_hand ? text("[]", l_hand) : "Nothing")]</A>
<BR><B>Right Hand:</B> <A href='?src=\ref[src];item=r_hand'>[(r_hand ? text("[]", r_hand) : "Nothing")]</A>
<BR><B>Head:</B> <A href='?src=\ref[src];item=head'>[(head ? text("[]", head) : "Nothing")]</A>
<BR><B>(Exo)Suit:</B> <A href='?src=\ref[src];item=suit'>[(wear_suit ? text("[]", wear_suit) : "Nothing")]</A>
<BR><A href='?src=\ref[src];item=pockets'>Empty Pouches</A>
<BR><A href='?src=\ref[user];mach_close=mob[name]'>Close</A>
<BR>"}
user << browse(dat, text("window=mob[name];size=340x480"))
onclose(user, "mob[name]")
return
var/dat = {"<table>
<tr><td><B>Left Hand:</B></td><td><A href='?src=\ref[src];item=[slot_l_hand]'>[(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "<font color=grey>Empty</font>"]</A></td></tr>
<tr><td><B>Right Hand:</B></td><td><A href='?src=\ref[src];item=[slot_r_hand]'>[(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "<font color=grey>Empty</font>"]</A></td></tr>
<tr><td>&nbsp;</td></tr>"}
dat += "<tr><td><B>Head:</B></td><td><A href='?src=\ref[src];item=[slot_head]'>[(head && !(head.flags&ABSTRACT)) ? head : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Exosuit:</B></td><td><A href='?src=\ref[src];item=[slot_wear_suit]'>[(wear_suit && !(wear_suit.flags&ABSTRACT)) ? wear_suit : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Pouches:</B></td><td><A href='?src=\ref[src];item=pockets'>[((l_store && !(l_store.flags&ABSTRACT)) || (r_store && !(r_store.flags&ABSTRACT))) ? "Full" : "<font color=grey>Empty</font>"]</A>"
dat += {"</table>
<A href='?src=\ref[user];mach_close=mob\ref[src]'>Close</A>
"}
var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 440, 500)
popup.set_content(dat)
popup.open()
/mob/living/carbon/alien/humanoid/canBeHandcuffed()
return 1
@@ -237,15 +237,6 @@
/mob/living/carbon/alien/larva/show_inv(mob/user as mob)
user.set_machine(src)
var/dat = {"
<B><HR><FONT size=3>[name]</FONT></B>
<BR><HR><BR>
<BR><A href='?src=\ref[user];mach_close=mob[name]'>Close</A>
<BR>"}
user << browse(dat, text("window=mob[name];size=340x480"))
onclose(user, "mob[name]")
return
/* Commented out because it's duplicated in life.dm
@@ -23,9 +23,10 @@
owner.ear_deaf = 0
/obj/item/organ/internal/brain/xeno
name = "thinkpan"
desc = "It looks kind of like an enormous wad of purple bubblegum."
icon_state = "brain-x-d"
name = "xenomorph brain"
desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?"
icon_state = "brain-x"
origin_tech = "biotech=7"
/obj/item/organ/internal/brain/New()
..()
+60 -34
View File
@@ -92,6 +92,42 @@
#undef STOMACH_ATTACK_DELAY
/mob/living/carbon/proc/vomit(var/lost_nutrition = 10, var/blood = 0, var/stun = 1, var/distance = 0, var/message = 1)
if(src.is_muzzled())
if(message)
src << "<span class='warning'>The muzzle prevents you from vomiting!</span>"
return 0
if(stun)
Stun(4)
if(nutrition < 100 && !blood)
if(message)
visible_message("<span class='warning'>[src] dry heaves!</span>", \
"<span class='userdanger'>You try to throw up, but there's nothing your stomach!</span>")
if(stun)
Weaken(10)
else
if(message)
visible_message("<span class='danger'>[src] throws up!</span>", \
"<span class='userdanger'>You throw up!</span>")
playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1)
var/turf/T = get_turf(src)
for(var/i=0 to distance)
if(blood)
if(T)
T.add_blood_floor(src)
if(stun)
adjustBruteLoss(3)
else
if(T)
T.add_vomit_floor(src)
nutrition -= lost_nutrition
if(stun)
adjustToxLoss(-3)
T = get_step(T, dir)
if (is_blocked_turf(T))
break
return 1
/mob/living/carbon/gib()
for(var/obj/item/organ/internal/I in internal_organs)
if(isturf(loc))
@@ -107,19 +143,6 @@
visible_message("<span class='danger'>[M] bursts out of [src]!</span>")
. = ..()
/mob/living/carbon/attack_hand(mob/M as mob)
if(!istype(M, /mob/living/carbon)) return
if (ishuman(M))
var/mob/living/carbon/human/H = M
var/obj/item/organ/external/temp = H.organs_by_name["r_hand"]
if (H.hand)
temp = H.organs_by_name["l_hand"]
if(temp && !temp.is_usable())
H << "\red You can't use your [temp.name]"
return
return
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, override = 0, tesla_shock = 0)
if(status_flags & GODMODE) //godmode
return 0
@@ -546,31 +569,34 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
/mob/living/carbon/show_inv(mob/user)
user.set_machine(src)
var/dat = {"
<HR>
<B><FONT size=3>[name]</FONT></B>
<HR>
<BR><B>Head:</B> <A href='?src=\ref[src];item=[slot_head]'> [(head && !(head.flags&ABSTRACT)) ? head : "Nothing"]</A>
<BR><B>Mask:</B> <A href='?src=\ref[src];item=[slot_wear_mask]'> [(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Nothing"]</A>
<BR><B>Left Hand:</B> <A href='?src=\ref[src];item=[slot_l_hand]'> [(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "Nothing"]</A>
<BR><B>Right Hand:</B> <A href='?src=\ref[src];item=[slot_r_hand]'> [(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "Nothing"]</A>"}
dat += "<BR><B>Back:</B> <A href='?src=\ref[src];item=[slot_back]'>[back ? back : "Nothing"]</A>"
var/dat = {"<table>
<tr><td><B>Left Hand:</B></td><td><A href='?src=\ref[src];item=[slot_l_hand]'>[(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "<font color=grey>Empty</font>"]</A></td></tr>
<tr><td><B>Right Hand:</B></td><td><A href='?src=\ref[src];item=[slot_r_hand]'>[(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "<font color=grey>Empty</font>"]</A></td></tr>
<tr><td>&nbsp;</td></tr>"}
dat += "<tr><td><B>Back:</B></td><td><A href='?src=\ref[src];item=[slot_back]'>[(back && !(back.flags&ABSTRACT)) ? back : "<font color=grey>Empty</font>"]</A>"
if(istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank))
dat += "<BR><A href='?src=\ref[src];internal=1'>[internal ? "Disable Internals" : "Set Internals"]</A>"
dat += "&nbsp;<A href='?src=\ref[src];internal=[slot_back]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
dat += "</td></tr><tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Head:</B></td><td><A href='?src=\ref[src];item=[slot_head]'>[(head && !(head.flags&ABSTRACT)) ? head : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Mask:</B></td><td><A href='?src=\ref[src];item=[slot_wear_mask]'>[(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "<font color=grey>Empty</font>"]</A></td></tr>"
if(handcuffed)
dat += "<BR><A href='?src=\ref[src];item=[slot_handcuffed]'>Handcuffed</A>"
dat += "<tr><td><B>Handcuffed:</B> <A href='?src=\ref[src];item=[slot_handcuffed]'>Remove</A></td></tr>"
if(legcuffed)
dat += "<BR><A href='?src=\ref[src];item=[slot_legcuffed]'>Legcuffed</A>"
dat += "<tr><td><A href='?src=\ref[src];item=[slot_legcuffed]'>Legcuffed</A></td></tr>"
dat += {"
<BR>
<BR><A href='?src=\ref[user];mach_close=mob\ref[src]'>Close</A>
dat += {"</table>
<A href='?src=\ref[user];mach_close=mob\ref[src]'>Close</A>
"}
user << browse(dat, "window=mob\ref[src];size=325x500")
onclose(user, "mob\ref[src]")
var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 440, 500)
popup.set_content(dat)
popup.open()
/mob/living/carbon/Topic(href, href_list)
..()
@@ -816,8 +842,8 @@ so that different stomachs can handle things in different ways VB*/
toEat.reagents.trans_to(src, toEat.reagents.total_volume*toEat.transfer_efficiency)
/mob/living/carbon/get_access()
var/obj/item/I = get_active_hand()
if(istype(I))
return I
. = ..()
return null
var/obj/item/I = get_active_hand()
if(I)
. |= I.GetAccess()
@@ -23,4 +23,17 @@
for(var/datum/surgery/S in surgeries)
if(S.next_step(user, src))
return 1
..()
..()
/mob/living/carbon/attack_hand(mob/living/carbon/human/user)
if(!iscarbon(user))
return
for(var/datum/disease/D in viruses)
if(D.IsSpreadByTouch())
user.ContractDisease(D)
for(var/datum/disease/D in user.viruses)
if(D.IsSpreadByTouch())
ContractDisease(D)
return 0
@@ -4,7 +4,6 @@
var/list/stomach_contents = list()
var/list/internal_organs = list()
var/brain_op_stage = 0.0
var/list/datum/disease2/disease/virus2 = list()
var/antibodies = 0
var/last_eating = 0 //Not sure what this does... I found it hidden in food.dm
@@ -177,9 +177,27 @@
continue
if(gender == FEMALE && S.gender == MALE)
continue
if(!(species.name in S.species_allowed))
continue
valid_hairstyles += hairstyle
if(species.flags & ALL_RPARTS) //If the user is a species who can have a robotic head...
var/obj/item/organ/external/head/H = organs_by_name["head"]
if(!H)
return
if(species.name in S.species_allowed) //If this is a hairstyle native to the user's species...
if(H.model == "Morpheus Cyberkinetics") //Check to see if they have the default head.
valid_hairstyles += hairstyle //Give them their hairstyles if they do.
continue
else //If they don't have the default head, they shouldn't be getting any hairstyles they wouldn't normally.
continue
else
if(H.model == "Morpheus Cyberkinetics") //If the hairstyle is not native to the user's species, and they're using the default head, don't let them access it.
continue
else
if("Human" in S.species_allowed) //If the user has a robotic head and the hairstyle can fit humans, let them use it as a wig for their humanoid robot head.
valid_hairstyles += hairstyle
continue
else
if(!(species.name in S.species_allowed)) //If the user is not a species who can have robotic heads, use the default handling.
continue
valid_hairstyles += hairstyle
return valid_hairstyles
@@ -192,9 +210,27 @@
continue
if(gender == FEMALE && S.gender == MALE)
continue
if(!(species.name in S.species_allowed))
continue
if(species.flags & ALL_RPARTS) //If the user is a species who can have a robotic head...
var/obj/item/organ/external/head/H = organs_by_name["head"]
if(!H)
continue // No head, no hair
if(species.name in S.species_allowed) //If this is a facial hair style native to the user's species...
if(H.model == "Morpheus Cyberkinetics") //Check to see if they have the default head.
valid_facial_hairstyles += facialhairstyle //Give them their facial hair styles if they do.
continue
else //If they don't have the default head, they shouldn't be getting any facial hair styles they wouldn't normally.
continue
else
valid_facial_hairstyles += facialhairstyle
if(H.model == "Morpheus Cyberkinetics") //If the facial hair style is not native to the user's species, and they're using the default head, don't let them access it.
continue
else
if("Human" in S.species_allowed) //If the user has a robotic head and the facial hair style can fit humans, let them use it as a postiche for their humanoid robot head.
valid_facial_hairstyles += facialhairstyle
continue
else //If the user is not a species who can have robotic heads, use the default handling.
if(!(species.name in S.species_allowed))
continue
valid_facial_hairstyles += facialhairstyle
return valid_facial_hairstyles
@@ -789,8 +789,6 @@
for(var/mob/M in range(location,aoe_range))
if (M.internal != null && M.wear_mask && (M.wear_mask.flags & AIRTIGHT))
continue
if(!airborne_can_reach(location,M,aoe_range))
continue
// Now, we don't have this:
//new /obj/effects/fart_cloud(T,L)
// But:
@@ -851,4 +849,4 @@
set desc = "Sets an extended description of your character's features."
set category = "IC"
flavor_text = TextPreview(input(usr, "Please enter your new flavour text.", "Flavour text", null) as text)
update_flavor_text()
+35 -80
View File
@@ -161,9 +161,6 @@
if(ismob(AM))
var/mob/tmob = AM
if(iscarbon(tmob) && prob(10))
spread_disease_to(tmob, "Contact")
//BubbleWrap - Should stop you pushing a restrained person out of the way
//i still don't get it, is this supposed to be 'bubblewrapping' or was it made by a guy named 'BubbleWrap'
if(ishuman(tmob))
@@ -636,10 +633,6 @@
// called when something steps onto a human
// this handles mulebots and vehicles
/mob/living/carbon/human/Crossed(var/atom/movable/AM)
if(istype(AM, /obj/machinery/bot/mulebot))
var/obj/machinery/bot/mulebot/MB = AM
MB.RunOver(src)
if(istype(AM, /obj/vehicle))
var/obj/vehicle/V = AM
V.RunOver(src)
@@ -839,15 +832,6 @@
U.accessories -= A
update_inv_w_uniform()
if (href_list["refresh"])
if((machine)&&(in_range(src, usr)))
show_inv(machine)
if (href_list["mach_close"])
var/t1 = text("window=[]", href_list["mach_close"])
unset_machine()
src << browse(null, t1)
if (href_list["criminal"])
if(hasHUD(usr,"security"))
@@ -1255,44 +1239,6 @@
return 0
return 1
/mob/living/carbon/human/proc/vomit(hairball=0)
if(stat==DEAD)return
if(!check_has_mouth())
return
if(!lastpuke)
lastpuke = 1
src << "<spawn class='warning'>You feel nauseous..."
spawn(150) //15 seconds until second warning
src << "<spawn class='warning'>You feel like you are about to throw up!"
spawn(100) //and you have 10 more for mad dash to the bucket
Stun(5)
if(hairball)
src.visible_message("<span class='warning'>[src] hacks up a hairball!</span>","<span class='warning'>You hack up a hairball!</span>")
else
src.visible_message("<span class='warning'>[src] throws up!</span>","<span class='warning'>You throw up!</span>")
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
var/turf/location = loc
if (istype(location, /turf/simulated))
location.add_vomit_floor(src, 1)
var/stomach_len = src.stomach_contents.len
if (stomach_len)
var/content = src.stomach_contents[stomach_len]
if (istype(content, /atom/movable))
var/atom/movable/AM = content
src.stomach_contents.Remove(AM)
AM.loc = location
if(!hairball)
nutrition -= 40
adjustToxLoss(-3)
spawn(350) //wait 35 seconds before next volley
lastpuke = 0
/mob/living/carbon/human/proc/get_visible_gender()
if(wear_suit && wear_suit.flags_inv & HIDEJUMPSUIT && ((head && head.flags_inv & HIDEMASK) || wear_mask))
@@ -1324,12 +1270,6 @@
H.brainmob.mind.transfer_to(src)
qdel(H)
for (var/ID in virus2)
var/datum/disease2/disease/V = virus2[ID]
V.cure(src)
..()
/mob/living/carbon/human/proc/is_lung_ruptured()
@@ -1619,26 +1559,36 @@
// Allows IPC's to change their monitor display
/mob/living/carbon/human/proc/change_monitor()
set category = "IC"
set name = "Change Monitor Display"
set desc = "Change the display on your monitor."
set name = "Change Monitor/Optical Display"
set desc = "Change the display on your monitor or the colour of your optics."
if(stat || paralysis || stunned || weakened)
src << "<span class='warning'>You cannot change your monitor display in your current state.</span>"
if(incapacitated())
src << "<span class='warning'>You cannot change your monitor or optical display in your current state.</span>"
return
var/list/hair = list()
for(var/i in hair_styles_list)
var/datum/sprite_accessory/hair/tmp_hair = hair_styles_list[i]
if(species.name in tmp_hair.species_allowed)
hair += i
if(species.flags & ALL_RPARTS) //If they can have a fully cybernetic body...
if(client.prefs.rlimb_data["head"]) //If head is present here, that means it's not the default Morpheus. Thus, no screen to adjust. Instead, let them change the colour of their optics!
var/optic_colour = input(src, "Select optic colour", rgb(r_markings, g_markings, b_markings)) as color|null
if(optic_colour)
r_markings = hex2num(copytext(optic_colour, 2, 4))
g_markings = hex2num(copytext(optic_colour, 4, 6))
b_markings = hex2num(copytext(optic_colour, 6, 8))
var/new_style = input(src, "Select a monitor display", "Monitor Display") as null|anything in hair
if(stat || paralysis || stunned || weakened)
return
if(new_style)
h_style = new_style
update_markings()
else if(!client.prefs.rlimb_data["head"])//Means that the character has the default Morpheus head, which has a screen. Time to customize.
var/list/hair = list()
for(var/i in hair_styles_list)
var/datum/sprite_accessory/hair/tmp_hair = hair_styles_list[i]
if(species.name in tmp_hair.species_allowed)
hair += i
update_hair()
var/new_style = input(src, "Select a monitor display", "Monitor Display", h_style) as null|anything in hair
if(incapacitated())
return
if(new_style)
h_style = new_style
update_hair()
//Putting a couple of procs here that I don't know where else to dump.
//Mostly going to be used for Vox and Vox Armalis, but other human mobs might like them (for adminbuse).
@@ -1752,7 +1702,7 @@
if(M.stat == 2)
M.gib()
/mob/living/carbon/human/assess_threat(var/obj/machinery/bot/secbot/judgebot, var/lasercolor)
/mob/living/carbon/human/assess_threat(var/mob/living/simple_animal/bot/secbot/judgebot, var/lasercolor)
if(judgebot.emagged == 2)
return 10 //Everyone is a criminal!
@@ -1929,7 +1879,12 @@
return 1.0 + 0.5*(30 - age)/80
/mob/living/carbon/human/get_access()
. = ..() //objects in hand
if(!. && wear_id) //nothing in hand, try ID
return wear_id
//otherwise return hand/nothing
. = ..()
if(wear_id)
. |= wear_id.GetAccess()
if(istype(w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = w_uniform
if(U.accessories)
for(var/obj/item/clothing/accessory/A in U.accessories)
. |= A.GetAccess()
@@ -48,10 +48,6 @@
apply_effect(4, WEAKEN, armor_block)
return
else
if(istype(M,/mob/living/carbon))
// log_debug("No gloves, [M] is truing to infect [src]")
M.spread_disease_to(src, "Contact")
var/datum/martial_art/attacker_style = M.martial_art
+29 -108
View File
@@ -64,8 +64,6 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
update_mutations()
check_mutations=0
handle_virus_updates()
handle_shock()
handle_pain()
handle_heartbeat()
@@ -345,12 +343,6 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
if(breath)
loc.assume_air(breath)
//spread virus2
if(virus2.len > 0)
if(prob(10) && get_infection_chance(src))
for(var/mob/living/carbon/M in view(1,src))
src.spread_disease_to(M)
// USED IN DEATHWHISPERS
@@ -731,32 +723,6 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
adjustOxyLoss(-(light_amount))
//TODO: heal wounds, heal broken limbs.
if(species.light_dam)
var/light_amount = 0
if(isturf(loc))
var/turf/T = loc
light_amount = T.get_lumcount()*10
if(light_amount > species.light_dam && !incorporeal_move) //if there's enough light, start dying
if(species.light_effect_amp)
adjustFireLoss(4.7) //This gets multiplied by 1.5 due to Shadowling's innate fire weakness, so it ends up being about 7.
else
adjustFireLoss(1)
adjustBruteLoss(1)
src << "<span class='userdanger'>The light burns you!</span>"
src << 'sound/weapons/sear.ogg'
else //heal in the dark
if(species.light_effect_amp)
adjustFireLoss(-5)
adjustBruteLoss(-5)
adjustBrainLoss(-25) //gibbering shadowlings are hilarious but also bad to have
adjustCloneLoss(-1)
SetWeakened(0)
SetStunned(0)
else
adjustFireLoss(-1)
adjustBruteLoss(-1)
//The fucking FAT mutation is the greatest shit ever. It makes everyone so hot and bothered.
if(species.flags & CAN_BE_FAT)
if(FAT in mutations)
@@ -965,6 +931,9 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
src << "<span class='alert'>Your psy-connection grows too faint to maintain!</span>"
isRemoteObserve = 0
if(remote_view)
isRemoteObserve = 1
if(!isRemoteObserve && client && !client.adminobs)
remoteview_target = null
reset_view(null)
@@ -978,7 +947,23 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
// Puke if toxloss is too high
if(!stat)
if (getToxLoss() >= 45 && nutrition > 20)
vomit()
lastpuke ++
if(lastpuke >= 25) // about 25 second delay I guess
Stun(5)
visible_message("<span class='danger'>[src] throws up!</span>", \
"<span class='userdanger'>[src] throws up!</span>")
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
var/turf/location = loc
if (istype(location, /turf/simulated))
location.add_vomit_floor(src, 1)
nutrition -= 20
adjustToxLoss(-3)
// make it so you can only puke so fast
lastpuke = 0
//0.1% chance of playing a scary sound to someone who's in complete darkness
if(isturf(loc) && rand(1,1000) == 1)
@@ -987,69 +972,6 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
if(L && L.lum_r + L.lum_g + L.lum_b == 0)
playsound_local(src,pick(scarySounds),50, 1, -1)
// Separate proc so we can jump out of it when we've succeeded in spreading disease.
/mob/living/carbon/human/proc/findAirborneVirii()
for(var/obj/effect/decal/cleanable/blood/B in get_turf(src))
if(B.virus2.len)
for (var/ID in B.virus2)
var/datum/disease2/disease/V = B.virus2[ID]
if (infect_virus2(src,V))
return 1
for(var/obj/effect/decal/cleanable/mucus/M in get_turf(src))
if(M.virus2.len)
for (var/ID in M.virus2)
var/datum/disease2/disease/V = M.virus2[ID]
if (infect_virus2(src,V))
return 1
for(var/obj/effect/decal/cleanable/poop/P in get_turf(src))
if(P.virus2.len)
for (var/ID in P.virus2)
var/datum/disease2/disease/V = P.virus2[ID]
if (infect_virus2(src,V))
return 1
return 0
/mob/living/carbon/human/proc/handle_virus_updates()
if(status_flags & GODMODE) return 0 //godmode
if(bodytemperature > 406)
for (var/ID in virus2)
var/datum/disease2/disease/V = virus2[ID]
V.cure(src)
if(mob_master.current_cycle % 3) //don't spam checks over all objects in view every tick.
for(var/obj/effect/decal/cleanable/O in view(1,src))
if(istype(O,/obj/effect/decal/cleanable/blood))
var/obj/effect/decal/cleanable/blood/B = O
if(B.virus2.len)
for (var/ID in B.virus2)
var/datum/disease2/disease/V = B.virus2[ID]
infect_virus2(src,V.getcopy())
else if(istype(O,/obj/effect/decal/cleanable/mucus))
var/obj/effect/decal/cleanable/mucus/M = O
if(M.virus2.len)
for (var/ID in M.virus2)
var/datum/disease2/disease/V = M.virus2[ID]
infect_virus2(src,V.getcopy())
for (var/ID in virus2)
var/datum/disease2/disease/V = virus2[ID]
if(isnull(V)) // Trying to figure out a runtime error that keeps repeating
CRASH("virus2 nulled before calling activate()")
else
V.activate(src)
// activate may have deleted the virus
if(!V) continue
// check if we're immune
if(V.antigen & src.antibodies)
V.dead = 1
return
/mob/living/carbon/human/handle_changeling()
if(mind)
if(mind.changeling)
@@ -1183,16 +1105,15 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
for(var/mob/living/carbon/human/H in range(decaylevel, src))
if(prob(5))
if(airborne_can_reach(get_turf(src), get_turf(H)))
if(istype(loc,/obj/item/bodybag))
return
var/obj/item/clothing/mask/M = H.wear_mask
if(M && (M.flags & MASKCOVERSMOUTH))
return
if(H.species && H.species.flags & NO_BREATHE)
return //no puking if you can't smell!
H << "<spawn class='warning'>You smell something foul..."
H.fakevomit()
if(istype(loc,/obj/item/bodybag))
return
var/obj/item/clothing/mask/M = H.wear_mask
if(M && (M.flags & MASKCOVERSMOUTH))
return
if(H.species && H.species.flags & NO_BREATHE)
return //no puking if you can't smell!
H << "<spawn class='warning'>You smell something foul..."
H.fakevomit()
/mob/living/carbon/human/proc/handle_heartbeat()
var/client/C = src.client
@@ -29,7 +29,6 @@
//unarmed_types = list(/datum/unarmed_attack/bite, /datum/unarmed_attack/claws)
//inherent_verbs = list(/mob/living/proc/ventcrawl)
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/monkey
total_health = 75
brute_mod = 1.5
@@ -7,7 +7,6 @@
default_language = "Galactic Common"
unarmed_type = /datum/unarmed_attack/claws
light_dam = 2
darksight = 8
blood_color = "#CCCCCC"
@@ -16,8 +15,8 @@
"brain" = /obj/item/organ/internal/brain
)
flags = NO_BLOOD | NO_BREATHE | NO_SCAN
bodyflags = FEET_NOSLIP
flags = NO_BLOOD | NO_BREATHE | RADIMMUNE
virus_immune = 1
dietflags = DIET_OMNI //the mutation process allowed you to now digest all foods regardless of initial race
reagent_tag = PROCESS_ORG
suicide_messages = list(
@@ -26,5 +25,13 @@
"is twisting their own neck!",
"is staring into the closest light source!")
/datum/species/shadow/handle_death(var/mob/living/carbon/human/H)
H.dust()
/datum/species/shadow/handle_life(var/mob/living/carbon/human/H)
var/light_amount = 0
if(isturf(H.loc))
var/turf/T = H.loc
light_amount = T.get_lumcount()*10
if(light_amount > 2) //if there's enough light, start dying
H.take_overall_damage(1,1)
else if (light_amount < 2) //heal in the dark
H.heal_overall_damage(1,1)
@@ -55,9 +55,6 @@
var/brute_mod = null // Physical damage reduction/malus.
var/burn_mod = null // Burn damage reduction/malus.
var/light_dam //Light level above which species takes damage, and below which it heals.
var/light_effect_amp //If 0, takes/heals 1 burn and brute per tick. Otherwise, both healing and damage effects are amplified.
var/total_health = 100
var/punchdamagelow = 0 //lowest possible punch damage
var/punchdamagehigh = 9 //highest possible punch damage
@@ -78,8 +75,6 @@
var/blood_color = "#A10808" //Red.
var/flesh_color = "#FFC896" //Pink.
var/single_gib_type = /obj/effect/decal/cleanable/blood/gibs
var/meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/human
var/base_color //Used when setting species.
//Used in icon caching.
@@ -325,6 +320,8 @@
return
/datum/species/proc/handle_post_spawn(var/mob/living/carbon/C) //Handles anything not already covered by basic species assignment.
if(C.get_species() == "Monkey" || C.get_species() == "Farwa" || C.get_species() == "Stok" || C.get_species() == "Wolpin" || C.get_species() == "Neara")
C.butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/monkey = 5)
grant_abilities(C)
return
@@ -334,6 +331,8 @@
return
/datum/species/proc/handle_pre_change(var/mob/living/carbon/human/H)
if(!H.get_species() == "Monkey" || !H.get_species() == "Farwa" || !H.get_species() == "Stok" || !H.get_species() == "Wolpin" || !H.get_species() == "Neara")
H.butcher_results = null
remove_abilities(H)
return
@@ -378,7 +378,7 @@
cold_env_multiplier = 3
flags = IS_WHITELISTED | NO_BREATHE | HAS_LIPS | NO_INTORGANS | NO_SCAN
clothing_flags = HAS_SOCKS
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
bodyflags = HAS_SKIN_COLOR | NO_EYES
dietflags = DIET_CARN
reagent_tag = PROCESS_ORG
@@ -712,9 +712,9 @@
passive_temp_gain = 10 //this should cause IPCs to stabilize at ~80 C in a 20 C environment.
flags = IS_WHITELISTED | NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | NO_DNA | NO_POISON | RADIMMUNE
clothing_flags = HAS_SOCKS
bodyflags = HAS_SKIN_COLOR
flags = IS_WHITELISTED | NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | NO_DNA | NO_POISON | RADIMMUNE | ALL_RPARTS
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
bodyflags = HAS_SKIN_COLOR | HAS_MARKINGS | HAS_HEAD_ACCESSORY
dietflags = 0 //IPCs can't eat, so no diet
blood_color = "#1F181F"
flesh_color = "#AAAAAA"
@@ -461,7 +461,7 @@ var/global/list/damage_icon_parts = list()
//if(!src.get_int_organ(/obj/item/organ/internal/brain) && src.get_species() != "Machine" )//make it obvious we have NO BRAIN
// hair_standing.Blend(debrained_s, ICON_OVERLAY)
if(hair_style && hair_style.species_allowed)
if(src.species.name in hair_style.species_allowed)
if((src.species.name in hair_style.species_allowed) || (src.species.flags & ALL_RPARTS))
var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s")
if(src.get_species() == "Slime People") // I am el worstos
hair_s.Blend(rgb(r_skin, g_skin, b_skin, 160), ICON_AND)
@@ -499,7 +499,7 @@ var/global/list/damage_icon_parts = list()
if(f_style)
var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[f_style]
if(facial_hair_style && facial_hair_style.species_allowed)
if(src.species.name in facial_hair_style.species_allowed)
if((src.species.name in facial_hair_style.species_allowed) || (src.species.flags & ALL_RPARTS))
var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s")
if(src.get_species() == "Slime People") // I am el worstos
facial_s.Blend(rgb(r_skin, g_skin, b_skin, 160), ICON_AND)
@@ -957,7 +957,8 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/update_hud() //TODO: do away with this if possible
if(client)
client.screen |= contents
for(var/obj/item/I in get_all_slots())
client.screen |= I // Items only please, no arms allowed
if(hud_used)
hud_used.hidden_inventory_update() //Updates the screenloc of the items on the 'other' inventory bar
update_inv_handcuffed(0) // update handcuff overlay
+1 -6
View File
@@ -84,12 +84,7 @@
if(breath)
loc.assume_air(breath)
//spread virus2
if(virus2.len > 0)
if(prob(10) && get_infection_chance(src))
for(var/mob/living/carbon/M in view(1,src))
src.spread_disease_to(M)
air_update_turf()
//Third link in a breath chain, calls handle_breath_temperature()
/mob/living/carbon/proc/check_breath(datum/gas_mixture/breath)
@@ -66,6 +66,12 @@
coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
..()
/mob/living/carbon/slime/Destroy()
for(var/obj/machinery/computer/camera_advanced/xenobio/X in machines)
if(src in X.stored_slimes)
X.stored_slimes -= src
return ..()
/mob/living/carbon/slime/regenerate_icons()
icon_state = "[colour] [is_adult ? "adult" : "baby"] slime"
overlays.len = 0
+1 -1
View File
@@ -212,7 +212,7 @@
if (!( machine.check_eye(src) ))
reset_view(null)
else
if(!client.adminobs)
if(!remote_view && !client.adminobs)
reset_view(null)
/mob/living/proc/update_sight()
+15 -1
View File
@@ -386,6 +386,9 @@
C.handcuffed = initial(C.handcuffed)
C.heart_attack = 0
for(var/datum/disease/D in C.viruses)
D.cure(0)
// restore all of the human's blood and reset their shock stage
if(ishuman(src))
var/mob/living/carbon/human/human_mob = src
@@ -952,4 +955,15 @@
//used in datum/reagents/reaction() proc
/mob/living/proc/get_permeability_protection()
return 0
return 0
/mob/living/proc/harvest(mob/living/user)
if(qdeleted(src))
return
if(butcher_results)
for(var/path in butcher_results)
for(var/i = 1, i <= butcher_results[path], i++)
new path(loc)
butcher_results.Remove(path) //In case you want to have things like simple_animals drop their butcher results on gib, so it won't double up below.
visible_message("<span class='notice'>[user] butchers [src].</span>")
gib()
@@ -52,4 +52,6 @@
var/list/datum/action/actions = list()
var/step_count = 0
var/list/butcher_results = null
var/list/surgeries = list() //a list of surgery datums. generally empty, they're added when the player wants them.
+6 -2
View File
@@ -430,7 +430,9 @@ proc/get_radio_key_from_channel(var/channel)
speech_bubble_recipients.Add(M.client)
spawn(0)
flick_overlay(image('icons/mob/talk.dmi', src, "h[speech_bubble_test]",MOB_LAYER+1), speech_bubble_recipients, 30)
var/image/I = image('icons/mob/talk.dmi', src, "h[speech_bubble_test]", MOB_LAYER + 1)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
flick_overlay(I, speech_bubble_recipients, 30)
if(watching.len)
var/rendered = "<span class='game say'><span class='name'>[src.name]</span> [not_heard].</span>"
@@ -441,4 +443,6 @@ proc/get_radio_key_from_channel(var/channel)
return 1
/mob/living/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
flick_overlay(image('icons/mob/talk.dmi', bubble_loc, bubble_state,MOB_LAYER+1), bubble_recipients, 30)
var/image/I = image('icons/mob/talk.dmi', bubble_loc, bubble_state, MOB_LAYER + 1)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
flick_overlay(I, bubble_recipients, 30)
+11 -6
View File
@@ -41,6 +41,7 @@ var/list/ai_verbs_default = list(
anchored = 1 // -- TLE
density = 1
status_flags = CANSTUN|CANPARALYSE|CANPUSH
can_strip = 0
var/list/network = list("SS13","Telecomms","Research Outpost","Mining Outpost")
var/obj/machinery/camera/current = null
var/list/connected_robots = list()
@@ -80,7 +81,7 @@ var/list/ai_verbs_default = list(
var/can_shunt = 1
var/last_announcement = ""
var/datum/announcement/priority/announcement
var/obj/machinery/bot/Bot
var/mob/living/simple_animal/bot/Bot
var/turf/waypoint //Holds the turf of the currently selected waypoint.
var/waypoint_mode = 0 //Waypoint mode is for selecting a turf via clicking.
@@ -513,7 +514,7 @@ var/list/ai_verbs_default = list(
return
if (href_list["trackbot"])
var/obj/machinery/bot/target = locate(href_list["trackbot"]) in aibots
var/mob/living/simple_animal/bot/target = locate(href_list["trackbot"]) in simple_animal_list
if(target)
ai_actual_track(target)
else
@@ -521,7 +522,7 @@ var/list/ai_verbs_default = list(
return
if (href_list["callbot"]) //Command a bot to move to a selected location.
Bot = locate(href_list["callbot"]) in aibots
Bot = locate(href_list["callbot"]) in simple_animal_list
if(!Bot || Bot.remote_disabled || src.control_disabled)
return //True if there is no bot found, the bot is manually emagged, or the AI is carded with wireless off.
waypoint_mode = 1
@@ -529,7 +530,7 @@ var/list/ai_verbs_default = list(
return
if (href_list["interface"]) //Remotely connect to a bot!
Bot = locate(href_list["interface"]) in aibots
Bot = locate(href_list["interface"]) in simple_animal_list
if(!Bot || Bot.remote_disabled || src.control_disabled)
return
Bot.attack_ai(src)
@@ -643,10 +644,10 @@ var/list/ai_verbs_default = list(
d += "<A HREF=?src=\ref[src];botrefresh=\ref[Bot]>Query network status</A><br>"
d += "<table width='100%'><tr><td width='40%'><h3>Name</h3></td><td width='20%'><h3>Status</h3></td><td width='30%'><h3>Location</h3></td><td width='10%'><h3>Control</h3></td></tr>"
for (Bot in aibots)
for (var/mob/living/simple_animal/bot/Bot in simple_animal_list)
if((Bot.z in ai_allowed_Zlevel) && !Bot.remote_disabled) //Only non-emagged bots on the allowed Z-level are detected!
bot_area = get_area(Bot)
d += "<tr><td width='30%'>[Bot.hacked ? "<span class='bad'>(!) </span>[Bot.name]" : Bot.name] ([Bot.bot_type_name])</td>"
d += "<tr><td width='30%'>[Bot.hacked ? "<span class='bad'>(!) </span>[Bot.name]" : Bot.name] ([Bot.model])</td>"
//If the bot is on, it will display the bot's current mode status. If the bot is not mode, it will just report "Idle". "Inactive if it is not on at all.
d += "<td width='20%'>[Bot.on ? "[Bot.mode ? "<span class='average'>[ Bot.mode_name[Bot.mode] ]</span>": "<span class='good'>Idle</span>"]" : "<span class='bad'>Inactive</span>"]</td>"
d += "<td width='30%'>[bot_area.name]</td>"
@@ -985,6 +986,10 @@ var/list/ai_verbs_default = list(
usr << "<span class='warning'>You are dead!</span>"
return 1
if(lacks_power())
usr << "<span class='warning'>Power systems failure!</span>"
return 1
if((flags & AI_CHECK_WIRELESS) && src.control_disabled)
usr << "<span class='warning'>Wireless control is disabled!</span>"
return 1
+3 -1
View File
@@ -59,7 +59,7 @@
var/screen // Which screen our main window displays
var/subscreen // Which specific function of the main screen is being displayed
var/obj/item/device/pda/ai/pai/pda = null
var/obj/item/device/pda/pai/pda = null
var/secHUD = 0 // Toggles whether the Security HUD is active or not
var/medHUD = 0 // Toggles whether the Medical HUD is active or not
@@ -110,6 +110,8 @@
pda.name = pda.owner + " (" + pda.ownjob + ")"
var/datum/data/pda/app/messenger/M = pda.find_program(/datum/data/pda/app/messenger)
M.toff = 1
var/datum/data/pda/app/chatroom/C = pda.find_program(/datum/data/pda/app/chatroom)
C.toff = 1
..()
/mob/living/silicon/pai/Login()
@@ -222,6 +222,123 @@
M.create_message(P, target, 1)
return 1
/datum/pai_software/chatroom
name = "Digital Chatroom"
ram_cost = 5
id = "chatroom"
toggle = 0
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
var/data[0]
if(!user.pda)
return
var/datum/data/pda/app/chatroom/M = user.pda.find_program(/datum/data/pda/app/chatroom)
if(!M)
return
data["receiver_off"] = M.toff
data["ringer_off"] = M.notify_silent
var/list/rooms[0]
for(var/datum/chatroom/c in chatrooms)
if((M in c.users) || (M in c.invites) || c.is_public)
rooms += list(list(name = "[c]", ref = "\ref[c]"))
data["rooms"] = rooms
if(M.disconnected || !M.messaging_available(1))
data["disconnected"] = 1
else if(M.current_room)
data["current_room"] = "\ref[M.current_room]"
data["current_room_name"] = M.current_room.name
data["current_room_topic"] = M.current_room.topic
data["messages"] = M.current_room.logs
var/list/users[0]
for(var/U in M.current_room.users)
var/datum/data/pda/app/chatroom/ch = U
users += "<span class='good'>[ch.pda.owner]</span>"
for(var/U in (M.current_room.invites - M.current_room.users))
var/datum/data/pda/app/chatroom/ch = U
users += "<span class='average'>[ch.pda.owner]</span>"
data["users"] = users
ui = nanomanager.try_update_ui(user, user, id, ui, data, force_open)
if(!ui)
// Don't copy-paste this unless you're making a pAI software module!
ui = new(user, user, id, "pai_chatroom.tmpl", "Digital Chatroom", 450, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
Topic(href, href_list)
var/mob/living/silicon/pai/P = usr
if(!istype(P))
return
if(!isnull(P.pda) && P.pda.can_use())
var/datum/data/pda/app/chatroom/M = P.pda.find_program(/datum/data/pda/app/chatroom)
if(!M)
return
if(href_list["toggler"])
M.toff = href_list["toggler"] != "1"
return 1
else if(href_list["ringer"])
M.notify_silent = href_list["ringer"] != "1"
return 1
else if(href_list["topic"])
if(!M.current_room)
return 1
var/t = input("Enter new topic:", M.current_room, M.current_room.topic) as text|null
spawn()
if(!t || !M.check_messaging_available() || !P.pda.can_use())
return
t = sanitize(copytext(t, 1, MAX_MESSAGE_LEN))
t = readd_quotes(t)
if (!t)
return
M.current_room.topic = t
M.current_room.announce(M, "Topic has been changed to '[t]' by [P.pda.owner].")
return 1
else if(href_list["select"])
var/s = href_list["select"]
if(s == "*NONE*")
M.current_room = null
else
var/datum/chatroom/CR = locate(s)
if(istype(CR))
if(!(M in CR.users))
if(!CR.login(M))
return
M.current_room = CR
return 1
else if(href_list["target"])
if(P.silence_time)
return alert("Communications circuits remain uninitialized.")
var/datum/chatroom/target = locate(href_list["target"])
if(istype(target))
if(!(M in target.users))
if(!target.login(M))
return
var/t = input("Please enter message", target) as text|null
spawn()
if(!t || !M.check_messaging_available())
return
t = sanitize(copytext(t, 1, MAX_MESSAGE_LEN))
t = readd_quotes(t)
if (!t || !P.pda.can_use())
return
target.post(M, t)
return 1
else if(href_list["reconnect"])
spawn()
M.messaging_available()
return 1
/datum/pai_software/med_records
name = "Medical Records"
ram_cost = 15
@@ -15,6 +15,7 @@
req_access = list(access_engine, access_robotics)
local_transmit = 1
ventcrawler = 2
magpulse = 1
// We need to keep track of a few module items so we don't need to do list operations
// every time we need them. These get set in New() after the module is chosen.
@@ -374,4 +374,4 @@
stack = stack_plastic
stack.amount++
decompiler.stored_comms[type]--;
decompiler.stored_comms[type]--
@@ -241,3 +241,9 @@
if(I == module_active)
deselect_module(get_selected_module())
return ..()
/mob/living/silicon/robot/proc/update_module_icon()
if(!module)
hands.icon_state = "nomod"
else
hands.icon_state = lowertext(module.module_type)
@@ -261,10 +261,8 @@
/mob/living/silicon/robot/proc/update_items()
if (src.client)
src.client.screen -= src.contents
for(var/obj/I in src.contents)
if(I && !(istype(I,/obj/item/weapon/stock_parts/cell) || istype(I,/obj/item/device/radio) || istype(I,/obj/machinery/camera) || istype(I,/obj/item/device/mmi)))
src.client.screen += I
for(var/obj/I in get_all_slots())
client.screen |= I
if(src.module_state_1)
src.module_state_1:screen_loc = ui_inv1
if(src.module_state_2)
+12 -4
View File
@@ -353,13 +353,11 @@ var/list/robot_verbs_default = list(
if("Peacekeeper")
module = new /obj/item/weapon/robot_module/peacekeeper(src)
icon_state = "droidpeace"
module.channels = list()
icon_state = "droidpeace"
if("Hunter")
module = new /obj/item/weapon/robot_module/alien/hunter(src)
hands.icon_state = "standard"
icon = "icons/mob/alien.dmi"
icon_state = "xenoborg-state-a"
modtype = "Xeno-Hu"
@@ -375,7 +373,7 @@ var/list/robot_verbs_default = list(
if (custom_sprite == 1)
module_sprites["Custom"] = "[src.ckey]-[modtype]"
hands.icon_state = lowertext(modtype)
hands.icon_state = lowertext(module.module_type)
feedback_inc("cyborg_[lowertext(modtype)]",1)
rename_character(real_name, get_default_name())
@@ -824,6 +822,9 @@ var/list/robot_verbs_default = list(
if(src.module && istype(src.module, /obj/item/weapon/robot_module/medical))
for(var/obj/item/weapon/borg_defib/F in src.module.modules)
F.safety = 0
if(module)
module.module_type = "Malf" // For the cool factor
update_module_icon()
update_icons()
return
@@ -1276,6 +1277,9 @@ var/list/robot_verbs_default = list(
if(icontype)
icon_state = module_sprites[icontype]
if(icontype == "Bro")
module.module_type = "Brobot"
update_module_icon()
lockcharge = null
else
src << "Something is badly wrong with the sprite selection. Harass a coder."
@@ -1325,6 +1329,10 @@ var/list/robot_verbs_default = list(
if (suiciding)
..()
/mob/living/silicon/robot/regenerate_icons()
..()
update_module_icon()
/mob/living/silicon/robot/deathsquad
base_icon = "nano_bloodhound"
icon_state = "nano_bloodhound"
@@ -1458,4 +1466,4 @@ var/list/robot_verbs_default = list(
status_flags &= ~CANPUSH
notify_ai(2)
notify_ai(2)
@@ -11,6 +11,8 @@
var/obj/item/borg/upgrade/jetpack = null
var/list/subsystems = list()
var/module_type = "NoMod" // For icon usage
var/list/stacktypes
var/channels = list()
@@ -101,7 +103,7 @@
/obj/item/weapon/robot_module/standard
name = "standard robot module"
module_type = "Standard"
/obj/item/weapon/robot_module/standard/New()
src.modules += new /obj/item/device/flash/cyborg(src)
@@ -116,6 +118,7 @@
/obj/item/weapon/robot_module/medical
name = "medical robot module"
module_type = "Medical"
subsystems = list(/mob/living/silicon/proc/subsystem_crew_monitor)
stacktypes = list(
/obj/item/stack/medical/advanced/bruise_pack = 5,
@@ -164,15 +167,16 @@
/obj/item/weapon/robot_module/engineering
name = "engineering robot module"
module_type = "Engineer"
subsystems = list(/mob/living/silicon/proc/subsystem_power_monitor)
stacktypes = list(
/obj/item/stack/sheet/metal = 50,
/obj/item/stack/sheet/glass = 50,
/obj/item/stack/sheet/rglass = 50,
/obj/item/stack/sheet/metal/cyborg = 50,
/obj/item/stack/sheet/glass/cyborg = 50,
/obj/item/stack/sheet/rglass/cyborg = 50,
/obj/item/stack/cable_coil/cyborg = 50,
/obj/item/stack/rods = 15,
/obj/item/stack/tile/plasteel = 15
/obj/item/stack/rods = 30,
/obj/item/stack/tile/plasteel = 20
)
/obj/item/weapon/robot_module/engineering/New()
@@ -194,34 +198,16 @@
src.emag = new /obj/item/borg/stun(src)
var/obj/item/stack/sheet/metal/cyborg/M = new /obj/item/stack/sheet/metal/cyborg(src)
M.amount = 50
src.modules += M
var/obj/item/stack/sheet/rglass/cyborg/R = new /obj/item/stack/sheet/rglass/cyborg(src)
R.amount = 50
src.modules += R
var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(src)
G.amount = 50
src.modules += G
var/obj/item/stack/cable_coil/cyborg/W = new /obj/item/stack/cable_coil/cyborg(src)
W.amount = 50
src.modules += W
var/obj/item/stack/rods/Q = new /obj/item/stack/rods(src)
Q.amount = 15
src.modules += Q
var/obj/item/stack/tile/plasteel/F = new /obj/item/stack/tile/plasteel(src) //floor tiles not regular plasteel, calm down
F.amount = 15
src.modules += F
for(var/G in stacktypes) //Attempt to unify Engi-Borg material stacks into fewer lines. See Line 492 for example. Variables changed out of paranoia.
var/obj/item/stack/sheet/M = new G(src)
M.amount = stacktypes[G]
src.modules += M
fix_modules()
/obj/item/weapon/robot_module/security
name = "security robot module"
module_type = "Security"
subsystems = list(/mob/living/silicon/proc/subsystem_crew_monitor)
/obj/item/weapon/robot_module/security/New()
@@ -237,6 +223,7 @@
/obj/item/weapon/robot_module/janitor
name = "janitorial robot module"
module_type = "Janitor"
/obj/item/weapon/robot_module/janitor/New()
src.modules += new /obj/item/device/flash/cyborg(src)
@@ -254,6 +241,7 @@
/obj/item/weapon/robot_module/butler
name = "service robot module"
module_type = "Service"
/obj/item/weapon/robot_module/butler/New()
src.modules += new /obj/item/device/flash/cyborg(src)
@@ -324,6 +312,7 @@
/obj/item/weapon/robot_module/miner
name = "miner robot module"
module_type = "Miner"
/obj/item/weapon/robot_module/miner/New()
src.modules += new /obj/item/device/flash/cyborg(src)
@@ -341,6 +330,7 @@
/obj/item/weapon/robot_module/deathsquad
name = "NT advanced combat module"
module_type = "Malf"
/obj/item/weapon/robot_module/deathsquad/New()
src.modules += new /obj/item/device/flash/cyborg(src)
@@ -355,6 +345,7 @@
/obj/item/weapon/robot_module/syndicate
name = "syndicate assault robot module"
module_type = "Malf" // cuz it looks cool
/obj/item/weapon/robot_module/syndicate/New()
src.modules += new /obj/item/device/flash/cyborg(src)
@@ -371,6 +362,7 @@
/obj/item/weapon/robot_module/syndicate_medical
name = "syndicate medical robot module"
module_type = "Malf"
stacktypes = list(
/obj/item/stack/medical/advanced/bruise_pack = 25,
/obj/item/stack/medical/advanced/ointment = 25,
@@ -409,6 +401,7 @@
/obj/item/weapon/robot_module/combat
name = "combat robot module"
module_type = "Malf"
/obj/item/weapon/robot_module/combat/New()
src.modules += new /obj/item/device/flash/cyborg(src)
@@ -425,6 +418,7 @@
/obj/item/weapon/robot_module/peacekeeper
name = "peacekeeper robot module"
module_type = "Malf"
/obj/item/weapon/robot_module/peacekeeper/New()
src.modules += new /obj/item/device/flash/cyborg(src)
@@ -440,6 +434,7 @@
/obj/item/weapon/robot_module/alien/hunter
name = "alien hunter module"
module_type = "Standard"
/obj/item/weapon/robot_module/alien/hunter/New()
src.modules += new /obj/item/weapon/melee/energy/alien/claws(src)
@@ -463,15 +458,15 @@
/obj/item/weapon/robot_module/drone
name = "drone module"
module_type = "Engineer"
stacktypes = list(
/obj/item/stack/sheet/wood = 1,
/obj/item/stack/sheet/mineral/plastic = 1,
/obj/item/stack/sheet/rglass = 5,
/obj/item/stack/tile/wood = 5,
/obj/item/stack/rods = 15,
/obj/item/stack/tile/plasteel = 15,
/obj/item/stack/sheet/metal = 20,
/obj/item/stack/sheet/glass = 20,
/obj/item/stack/sheet/wood/cyborg = 10,
/obj/item/stack/sheet/rglass/cyborg = 50,
/obj/item/stack/tile/wood = 20,
/obj/item/stack/rods = 30,
/obj/item/stack/tile/plasteel = 20,
/obj/item/stack/sheet/metal/cyborg = 50,
/obj/item/stack/sheet/glass/cyborg = 50,
/obj/item/stack/cable_coil/cyborg = 30
)
@@ -516,4 +511,4 @@
var/mob/living/silicon/robot/R = src.loc
return (src in R.module.modules)
return (src in R.module.modules)
+131 -139
View File
@@ -17,14 +17,6 @@
var/obj/machinery/portable_atmospherics/hydroponics/my_hydrotray
// Allow final solutions.
min_oxy = 5
max_oxy = 0
min_tox = 0
max_tox = 1
min_co2 = 0
max_co2 = 5
min_n2 = 0
max_n2 = 0
minbodytemp = 0
maxbodytemp = 360
@@ -37,145 +29,143 @@
parent.owned_bee_swarms.Remove(src)
return ..()
/mob/living/simple_animal/bee/Life()
..()
/mob/living/simple_animal/bee/process_ai()
//if we're strong enough, sting some people
var/mob/living/carbon/human/M = target_mob
var/sting_prob = 100 // Bees will always try to sting.
if(M in view(src,1)) // Can I see my target?
if(prob(max(feral * 10, 0))) // Am I mad enough to want to sting? And yes, when I initially appear, I AM mad enough
var/obj/item/clothing/worn_suit = M.wear_suit
var/obj/item/clothing/worn_helmet = M.head
if(worn_suit) // Are you wearing clothes?
sting_prob -= min(worn_suit.armor["bio"],70) // Is it sealed? I can't get to 70% of your body.
if(worn_helmet)
sting_prob -= min(worn_helmet.armor["bio"],30) // Is your helmet sealed? I can't get to 30% of your body.
if( prob(sting_prob) && (M.stat == CONSCIOUS || (M.stat == UNCONSCIOUS && prob(25))) ) // Try to sting! If you're not moving, think about stinging.
M.apply_damage(min(strength,2)+mut, BRUTE, sharp=1) // Stinging. The more mutated I am, the harder I sting.
M.apply_damage((round(feral/10,1)*(max((round(strength/20,1)),1)))+toxic, TOX) // Bee venom based on how angry I am and how many there are of me!
M << "\red You have been stung!"
if(stat == CONSCIOUS)
//if we're strong enough, sting some people
var/mob/living/carbon/human/M = target_mob
var/sting_prob = 100 // Bees will always try to sting.
if(M in view(src,1)) // Can I see my target?
if(prob(max(feral * 10, 0))) // Am I mad enough to want to sting? And yes, when I initially appear, I AM mad enough
var/obj/item/clothing/worn_suit = M.wear_suit
var/obj/item/clothing/worn_helmet = M.head
if(worn_suit) // Are you wearing clothes?
sting_prob -= min(worn_suit.armor["bio"],70) // Is it sealed? I can't get to 70% of your body.
if(worn_helmet)
sting_prob -= min(worn_helmet.armor["bio"],30) // Is your helmet sealed? I can't get to 30% of your body.
if( prob(sting_prob) && (M.stat == CONSCIOUS || (M.stat == UNCONSCIOUS && prob(25))) ) // Try to sting! If you're not moving, think about stinging.
M.apply_damage(min(strength,2)+mut, BRUTE, sharp=1) // Stinging. The more mutated I am, the harder I sting.
M.apply_damage((round(feral/10,1)*(max((round(strength/20,1)),1)))+toxic, TOX) // Bee venom based on how angry I am and how many there are of me!
M << "\red You have been stung!"
M.flash_pain()
//if we're chasing someone, get a little bit angry
if(target_mob && prob(10))
feral++
M.flash_pain()
//if we're chasing someone, get a little bit angry
if(target_mob && prob(10))
feral++
//calm down a little bit
if(feral > 0)
if(prob(feral * 10))
feral -= 1
else
//if feral is less than 0, we're becalmed by smoke or steam
if(feral < 0)
feral += 1
if(target_mob)
target_mob = null
target_turf = null
if(strength > 5)
//calm down and spread out a little
var/mob/living/simple_animal/bee/B = new(get_turf(pick(orange(src,1))))
B.strength = rand(1,5)
src.strength -= B.strength
if(src.strength <= 5)
src.icon_living = "bees[src.strength]"
B.icon_living = "bees[B.strength]"
if(src.parent)
B.parent = src.parent
src.parent.owned_bee_swarms.Add(B)
//make some noise
if(prob(0.5))
src.visible_message("\blue [pick("Buzzzz.","Hmmmmm.","Bzzz.")]")
//smoke, water and steam calms us down
var/calming = 0
var/list/calmers = list(/obj/effect/effect/chem_smoke, \
/obj/effect/effect/water, \
/obj/effect/effect/foam, \
/obj/effect/effect/steam, \
/obj/effect/mist)
for(var/obj/effect/check_effect in src.loc)
if(check_effect.type in calmers)
calming = 1
break
if(calming)
if(feral > 0)
src.visible_message("\blue The bees calm down!")
feral = -10
target_mob = null
target_turf = null
wander = 1
for(var/mob/living/simple_animal/bee/B in src.loc)
if(B == src)
continue
if(feral > 0)
src.strength += B.strength
qdel(B)
src.icon_living = "bees[src.strength]"
if(strength > 5)
icon_living = "bees_swarm"
else if(prob(10))
//make the other swarm of bees stronger, then move away
var/total_bees = B.strength + src.strength
if(total_bees < 10)
B.strength = min(5, total_bees)
src.strength = total_bees - B.strength
B.icon_living = "bees[B.strength]"
if(src.strength <= 0)
qdel(src)
return
src.icon_living = "bees[B.strength]"
var/turf/simulated/floor/T = get_turf(get_step(src, pick(1,2,4,8)))
density = 1
if(T.Enter(src, get_turf(src)))
src.loc = T
density = 0
break
//calm down a little bit
if(feral > 0)
if(prob(feral * 10))
feral -= 1
else
//if feral is less than 0, we're becalmed by smoke or steam
if(feral < 0)
feral += 1
if(target_mob)
if(target_mob in view(src,7))
target_turf = get_turf(target_mob)
wander = 0
target_mob = null
target_turf = null
if(strength > 5)
//calm down and spread out a little
var/mob/living/simple_animal/bee/B = new(get_turf(pick(orange(src,1))))
B.strength = rand(1,5)
src.strength -= B.strength
if(src.strength <= 5)
src.icon_living = "bees[src.strength]"
B.icon_living = "bees[B.strength]"
if(src.parent)
B.parent = src.parent
src.parent.owned_bee_swarms.Add(B)
else // My target's gone! But I might still be pissed! You there. You look like a good stinging target!
for(var/mob/living/carbon/G in view(src,7))
target_mob = G
break
//make some noise
if(prob(0.5))
src.visible_message("\blue [pick("Buzzzz.","Hmmmmm.","Bzzz.")]")
if(target_turf)
if (!(DirBlocked(get_step(src, get_dir(src,target_turf)),get_dir(src,target_turf)))) // Check for windows and doors!
Move(get_step(src, get_dir(src,target_turf)))
if (prob(0.1))
src.visible_message("\blue The bees swarm after [target_mob]!")
if(src.loc == target_turf)
target_turf = null
wander = 1
else
//find some flowers, harvest
//angry bee swarms don't hang around
if(feral > 0)
turns_per_move = rand(1,3)
else if(feral < 0)
turns_since_move = 0
else if(!my_hydrotray || my_hydrotray.loc != src.loc || my_hydrotray.dead || !my_hydrotray.seed)
var/obj/machinery/portable_atmospherics/hydroponics/my_hydrotray = locate() in src.loc
if(my_hydrotray)
if(!my_hydrotray.dead && my_hydrotray.seed)
turns_per_move = rand(20,50)
else
my_hydrotray = null
//smoke, water and steam calms us down
var/calming = 0
var/list/calmers = list(/obj/effect/effect/chem_smoke, \
/obj/effect/effect/water, \
/obj/effect/effect/foam, \
/obj/effect/effect/steam, \
/obj/effect/mist)
pixel_x = rand(-12,12)
pixel_y = rand(-12,12)
for(var/obj/effect/check_effect in src.loc)
if(check_effect.type in calmers)
calming = 1
break
if(calming)
if(feral > 0)
src.visible_message("\blue The bees calm down!")
feral = -10
target_mob = null
target_turf = null
wander = 1
for(var/mob/living/simple_animal/bee/B in src.loc)
if(B == src)
continue
if(feral > 0)
src.strength += B.strength
qdel(B)
src.icon_living = "bees[src.strength]"
if(strength > 5)
icon_living = "bees_swarm"
else if(prob(10))
//make the other swarm of bees stronger, then move away
var/total_bees = B.strength + src.strength
if(total_bees < 10)
B.strength = min(5, total_bees)
src.strength = total_bees - B.strength
B.icon_living = "bees[B.strength]"
if(src.strength <= 0)
qdel(src)
return
src.icon_living = "bees[B.strength]"
var/turf/simulated/floor/T = get_turf(get_step(src, pick(1,2,4,8)))
density = 1
if(T.Enter(src, get_turf(src)))
src.loc = T
density = 0
break
if(target_mob)
if(target_mob in view(src,7))
target_turf = get_turf(target_mob)
wander = 0
else // My target's gone! But I might still be pissed! You there. You look like a good stinging target!
for(var/mob/living/carbon/G in view(src,7))
target_mob = G
break
if(target_turf)
if (!(DirBlocked(get_step(src, get_dir(src,target_turf)),get_dir(src,target_turf)))) // Check for windows and doors!
Move(get_step(src, get_dir(src,target_turf)))
if (prob(0.1))
src.visible_message("\blue The bees swarm after [target_mob]!")
if(src.loc == target_turf)
target_turf = null
wander = 1
else
//find some flowers, harvest
//angry bee swarms don't hang around
if(feral > 0)
turns_per_move = rand(1,3)
else if(feral < 0)
turns_since_move = 0
else if(!my_hydrotray || my_hydrotray.loc != src.loc || my_hydrotray.dead || !my_hydrotray.seed)
var/obj/machinery/portable_atmospherics/hydroponics/my_hydrotray = locate() in src.loc
if(my_hydrotray)
if(!my_hydrotray.dead && my_hydrotray.seed)
turns_per_move = rand(20,50)
else
my_hydrotray = null
pixel_x = rand(-12,12)
pixel_y = rand(-12,12)
/mob/living/simple_animal/bee/handle_state_icons()
if(!parent && prob(10))
strength -= 1
if(strength <= 0)
@@ -187,3 +177,5 @@
/*icon_living = "[strength]"
if(strength > 5)
icon_living = "unknown"*/
..()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,225 @@
//Cleanbot
/mob/living/simple_animal/bot/cleanbot
name = "\improper Cleanbot"
desc = "A little cleaning robot, he looks so excited!"
icon = 'icons/obj/aibots.dmi'
icon_state = "cleanbot0"
density = 0
anchored = 0
health = 25
maxHealth = 25
radio_channel = "Service" //Service
bot_filter = RADIO_CLEANBOT
bot_type = CLEAN_BOT
model = "Cleanbot"
bot_purpose = "seek out messes and clean them"
bot_core_type = /obj/machinery/bot_core/cleanbot
window_id = "autoclean"
window_name = "Automatic Station Cleaner v1.1"
pass_flags = PASSMOB
var/blood = 1
var/list/target_types = list()
var/obj/effect/decal/cleanable/target
var/max_targets = 50 //Maximum number of targets a cleanbot can ignore.
var/oldloc = null
var/closest_dist
var/closest_loc
var/failed_steps
var/next_dest
var/next_dest_loc
/mob/living/simple_animal/bot/cleanbot/New()
..()
get_targets()
icon_state = "cleanbot[on]"
var/datum/job/janitor/J = new/datum/job/janitor
access_card.access += J.get_access()
prev_access = access_card.access
/mob/living/simple_animal/bot/cleanbot/turn_on()
..()
icon_state = "cleanbot[on]"
/mob/living/simple_animal/bot/cleanbot/turn_off()
..()
icon_state = "cleanbot[on]"
/mob/living/simple_animal/bot/cleanbot/bot_reset()
..()
ignore_list = list() //Allows the bot to clean targets it previously ignored due to being unreachable.
target = null
oldloc = null
/mob/living/simple_animal/bot/cleanbot/set_custom_texts()
text_hack = "You corrupt [name]'s cleaning software."
text_dehack = "[name]'s software has been reset!"
text_dehack_fail = "[name] does not seem to respond to your repair code!"
/mob/living/simple_animal/bot/cleanbot/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if(bot_core.allowed(user) && !open && !emagged)
locked = !locked
user << "<span class='notice'>You [ locked ? "lock" : "unlock"] \the [src] behaviour controls.</span>"
else
if(emagged)
user << "<span class='warning'>ERROR</span>"
if(open)
user << "<span class='warning'>Please close the access panel before locking it.</span>"
else
user << "<span class='notice'>\The [src] doesn't seem to respect your authority.</span>"
else
return ..()
/mob/living/simple_animal/bot/cleanbot/emag_act(mob/user)
..()
if(emagged == 2)
if(user)
user << "<span class='danger'>[src] buzzes and beeps.</span>"
/mob/living/simple_animal/bot/cleanbot/process_scan(obj/effect/decal/cleanable/D)
for(var/T in target_types)
if(istype(D, T))
return D
/mob/living/simple_animal/bot/cleanbot/handle_automated_action()
if(!..())
return
if(mode == BOT_CLEANING)
return
if(emagged == 2) //Emag functions
if(istype(loc,/turf/simulated))
if(prob(10)) //Wets floors randomly
var/turf/simulated/T = loc
T.MakeSlippery()
if(prob(5)) //Spawns foam!
visible_message("<span class='danger'>[src] whirs and bubbles violently, before releasing a plume of froth!</span>")
new /obj/effect/effect/foam(loc)
else if(prob(5))
audible_message("[src] makes an excited beeping booping sound!")
if(!target) //Search for cleanables it can see.
target = scan(/obj/effect/decal/cleanable/)
if(!target && auto_patrol) //Search for cleanables it can see.
if(mode == BOT_IDLE || mode == BOT_START_PATROL)
start_patrol()
if(mode == BOT_PATROL)
bot_patrol()
if(target)
if(!path || path.len == 0) //No path, need a new one
//Try to produce a path to the target, and ignore airlocks to which it has access.
path = get_path_to(src, target.loc, /turf/proc/Distance_cardinal, 0, 30, id=access_card)
if(!bot_move(target))
add_to_ignore(target)
target = null
path = list()
return
mode = BOT_MOVING
else if(!bot_move(target))
target = null
mode = BOT_IDLE
return
if(target && loc == target.loc)
clean(target)
path = list()
target = null
oldloc = loc
/mob/living/simple_animal/bot/cleanbot/proc/get_targets()
target_types = new/list()
target_types += /obj/effect/decal/cleanable/blood/oil
target_types += /obj/effect/decal/cleanable/vomit
target_types += /obj/effect/decal/cleanable/blood/gibs/robot
target_types += /obj/effect/decal/cleanable/crayon
target_types += /obj/effect/decal/cleanable/liquid_fuel
target_types += /obj/effect/decal/cleanable/molten_item
target_types += /obj/effect/decal/cleanable/tomato_smudge
target_types += /obj/effect/decal/cleanable/egg_smudge
target_types += /obj/effect/decal/cleanable/pie_smudge
target_types += /obj/effect/decal/cleanable/flour
target_types += /obj/effect/decal/cleanable/ash
target_types += /obj/effect/decal/cleanable/greenglow
target_types += /obj/effect/decal/cleanable/dirt
if(blood)
target_types += /obj/effect/decal/cleanable/blood/xeno/
target_types += /obj/effect/decal/cleanable/blood/gibs/xeno
target_types += /obj/effect/decal/cleanable/blood/
target_types += /obj/effect/decal/cleanable/blood/gibs/
target_types += /obj/effect/decal/cleanable/blood/tracks
target_types += /obj/effect/decal/cleanable/dirt
/mob/living/simple_animal/bot/cleanbot/proc/clean(obj/effect/decal/cleanable/target)
anchored = 1
icon_state = "cleanbot-c"
visible_message("<span class='notice'>[src] begins to clean up [target]</span>")
mode = BOT_CLEANING
spawn(50)
if(mode == BOT_CLEANING)
qdel(target)
anchored = 0
target = null
mode = BOT_IDLE
icon_state = "cleanbot[on]"
/mob/living/simple_animal/bot/cleanbot/explode()
on = 0
visible_message("<span class='userdanger'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
new /obj/item/weapon/reagent_containers/glass/bucket(Tsec)
new /obj/item/device/assembly/prox_sensor(Tsec)
if(prob(50))
new /obj/item/robot_parts/l_arm(Tsec)
var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
..()
/obj/machinery/bot_core/cleanbot
req_one_access = list(access_janitor, access_robotics)
/mob/living/simple_animal/bot/cleanbot/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += text({"
<TT><B>Cleaner v1.1 controls</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [open ? "opened" : "closed"]"},
text("<A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A>"))
if(!locked || issilicon(user) || check_rights(R_ADMIN, 0, user))
dat += text({"<BR>Cleans Blood: []<BR>"}, text("<A href='?src=\ref[src];operation=blood'>[blood ? "Yes" : "No"]</A>"))
dat += text({"<BR>Patrol station: []<BR>"}, text("<A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "Yes" : "No"]</A>"))
return dat
/mob/living/simple_animal/bot/cleanbot/Topic(href, href_list)
if(..())
return 1
switch(href_list["operation"])
if("blood")
blood =!blood
get_targets()
update_controls()
/mob/living/simple_animal/bot/cleanbot/UnarmedAttack(atom/A)
if(istype(A,/obj/effect/decal/cleanable))
clean(A)
else
..()
@@ -0,0 +1,480 @@
//Bot Construction
//Cleanbot assembly
/obj/item/weapon/bucket_sensor
desc = "It's a bucket. With a sensor attached."
name = "proxy bucket"
icon = 'icons/obj/aibots.dmi'
icon_state = "bucket_proxy"
force = 3
throwforce = 5
throw_speed = 2
throw_range = 5
w_class = 3
var/created_name = "Cleanbot"
/obj/item/weapon/bucket_sensor/attackby(obj/item/W, mob/user as mob, params)
..()
if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm))
if(!user.unEquip(W))
return
qdel(W)
var/turf/T = get_turf(loc)
var/mob/living/simple_animal/bot/cleanbot/A = new /mob/living/simple_animal/bot/cleanbot(T)
A.name = created_name
user << "<span class='notice'>You add the robot arm to the bucket and sensor assembly. Beep boop!</span>"
user.unEquip(src, 1)
qdel(src)
else if(istype(W, /obj/item/weapon/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && loc != usr)
return
created_name = t
//Edbot Assembly
/obj/item/weapon/ed209_assembly
name = "\improper ED-209 assembly"
desc = "Some sort of bizarre assembly."
icon = 'icons/obj/aibots.dmi'
icon_state = "ed209_frame"
item_state = "ed209_frame"
var/build_step = 0
var/created_name = "ED-209 Security Robot" //To preserve the name if it's a unique securitron I guess
var/lasercolor = ""
/obj/item/weapon/ed209_assembly/attackby(obj/item/weapon/W, mob/user, params)
..()
if(istype(W, /obj/item/weapon/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && loc != usr)
return
created_name = t
return
switch(build_step)
if(0,1)
if(istype(W, /obj/item/robot_parts/l_leg) || istype(W, /obj/item/robot_parts/r_leg))
if(!user.unEquip(W))
return
qdel(W)
build_step++
user << "<span class='notice'>You add the robot leg to [src].</span>"
name = "legs/frame assembly"
if(build_step == 1)
item_state = "ed209_leg"
icon_state = "ed209_leg"
else
item_state = "ed209_legs"
icon_state = "ed209_legs"
if(2)
var/newcolor = ""
if(istype(W, /obj/item/clothing/suit/redtag))
newcolor = "r"
else if(istype(W, /obj/item/clothing/suit/bluetag))
newcolor = "b"
if(newcolor || istype(W, /obj/item/clothing/suit/armor/vest))
if(!user.unEquip(W))
return
lasercolor = newcolor
qdel(W)
build_step++
user << "<span class='notice'>You add the armor to [src].</span>"
name = "vest/legs/frame assembly"
item_state = "[lasercolor]ed209_shell"
icon_state = "[lasercolor]ed209_shell"
if(3)
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(WT.remove_fuel(0,user))
build_step++
name = "shielded frame assembly"
user << "<span class='notice'>You weld the vest to [src].</span>"
if(4)
switch(lasercolor)
if("b")
if(!istype(W, /obj/item/clothing/head/helmet/bluetaghelm))
return
if("r")
if(!istype(W, /obj/item/clothing/head/helmet/redtaghelm))
return
if("")
if(!istype(W, /obj/item/clothing/head/helmet))
return
if(!user.unEquip(W))
return
qdel(W)
build_step++
user << "<span class='notice'>You add the helmet to [src].</span>"
name = "covered and shielded frame assembly"
item_state = "[lasercolor]ed209_hat"
icon_state = "[lasercolor]ed209_hat"
if(5)
if(isprox(W))
if(!user.unEquip(W))
return
qdel(W)
build_step++
user << "<span class='notice'>You add the prox sensor to [src].</span>"
name = "covered, shielded and sensored frame assembly"
item_state = "[lasercolor]ed209_prox"
icon_state = "[lasercolor]ed209_prox"
if(6)
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/coil = W
if(coil.get_amount() < 1)
user << "<span class='warning'>You need one length of cable to wire the ED-209!</span>"
return
user << "<span class='notice'>You start to wire [src]...</span>"
if(do_after(user, 40, target = src))
if(coil.get_amount() >= 1 && build_step == 6)
coil.use(1)
build_step = 7
user << "<span class='notice'>You wire the ED-209 assembly.</span>"
name = "wired ED-209 assembly"
if(7)
var/newname = ""
switch(lasercolor)
if("b")
if(!istype(W, /obj/item/weapon/gun/energy/laser/bluetag))
return
newname = "bluetag ED-209 assembly"
if("r")
if(!istype(W, /obj/item/weapon/gun/energy/laser/redtag))
return
newname = "redtag ED-209 assembly"
if("")
if(!istype(W, /obj/item/weapon/gun/energy/advtaser))
return
newname = "taser ED-209 assembly"
else
return
if(!user.unEquip(W))
return
name = newname
build_step++
user << "<span class='notice'>You add [W] to [src].</span>"
item_state = "[lasercolor]ed209_taser"
icon_state = "[lasercolor]ed209_taser"
qdel(W)
if(8)
if(istype(W, /obj/item/weapon/screwdriver))
playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1)
user << "<span class='notice'>You start attaching the gun to the frame...</span>"
if(do_after(user, 40, target = src))
build_step++
name = "armed [name]"
user << "<span class='notice'>Taser gun attached.</span>"
if(9)
if(istype(W, /obj/item/weapon/stock_parts/cell))
if(!user.unEquip(W))
return
build_step++
user << "<span class='notice'>You complete the ED-209.</span>"
var/turf/T = get_turf(src)
new /mob/living/simple_animal/bot/ed209(T,created_name,lasercolor)
qdel(W)
user.unEquip(src, 1)
qdel(src)
//Floorbot assemblies
/obj/item/weapon/toolbox_tiles
desc = "It's a toolbox with tiles sticking out the top"
name = "tiles and toolbox"
icon = 'icons/obj/aibots.dmi'
icon_state = "toolbox_tiles"
force = 3
throwforce = 10
throw_speed = 2
throw_range = 5
w_class = 3
var/created_name = "Floorbot"
/obj/item/weapon/toolbox_tiles_sensor
desc = "It's a toolbox with tiles sticking out the top and a sensor attached"
name = "tiles, toolbox and sensor arrangement"
icon = 'icons/obj/aibots.dmi'
icon_state = "toolbox_tiles_sensor"
force = 3
throwforce = 10
throw_speed = 2
throw_range = 5
w_class = 3
var/created_name = "Floorbot"
/obj/item/weapon/storage/toolbox/mechanical/attackby(obj/item/stack/tile/plasteel/T, mob/user, params)
if(!istype(T, /obj/item/stack/tile/plasteel))
..()
return
if(contents.len >= 1)
user << "<span class='warning'>They won't fit in, as there is already stuff inside.</span>"
return
if(T.use(10))
if(user.s_active)
user.s_active.close(user)
var/obj/item/weapon/toolbox_tiles/B = new /obj/item/weapon/toolbox_tiles
user.put_in_hands(B)
user << "<span class='notice'>You add the tiles into the empty toolbox. They protrude from the top.</span>"
user.unEquip(src, 1)
qdel(src)
else
user << "<span class='warning'>You need 10 floor tiles to start building a floorbot.</span>"
return
/obj/item/weapon/toolbox_tiles/attackby(obj/item/W, mob/user, params)
..()
if(isprox(W))
qdel(W)
var/obj/item/weapon/toolbox_tiles_sensor/B = new /obj/item/weapon/toolbox_tiles_sensor()
B.created_name = created_name
user.put_in_hands(B)
user << "<span class='notice'>You add the sensor to the toolbox and tiles.</span>"
user.unEquip(src, 1)
qdel(src)
else if(istype(W, /obj/item/weapon/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && loc != usr)
return
created_name = t
/obj/item/weapon/toolbox_tiles_sensor/attackby(obj/item/W, mob/user, params)
..()
if(istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm))
qdel(W)
var/turf/T = get_turf(user.loc)
var/mob/living/simple_animal/bot/floorbot/A = new /mob/living/simple_animal/bot/floorbot(T)
A.name = created_name
user << "<span class='notice'>You add the robot arm to the odd looking toolbox assembly. Boop beep!</span>"
user.unEquip(src, 1)
qdel(src)
else if(istype(W, /obj/item/weapon/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && loc != usr)
return
created_name = t
//Medbot Assembly
/obj/item/weapon/firstaid_arm_assembly
name = "incomplete medibot assembly."
desc = "A first aid kit with a robot arm permanently grafted to it."
icon = 'icons/obj/aibots.dmi'
icon_state = "firstaid_arm"
var/build_step = 0
var/created_name = "Medibot" //To preserve the name if it's a unique medbot I guess
var/skin = null //Same as medbot, set to tox or ointment for the respective kits.
w_class = 3
var/treatment_brute = "salglu_solution"
var/treatment_oxy = "salbutamol"
var/treatment_fire = "salglu_solution"
var/treatment_tox = "charcoal"
var/treatment_virus = "spaceacillin"
req_one_access = list(access_medical, access_robotics)
/obj/item/weapon/firstaid_arm_assembly/New()
..()
spawn(5)
if(skin)
overlays += image('icons/obj/aibots.dmi', "kit_skin_[skin]")
/obj/item/weapon/storage/firstaid/attackby(obj/item/robot_parts/S, mob/user, params)
if((!istype(S, /obj/item/robot_parts/l_arm)) && (!istype(S, /obj/item/robot_parts/r_arm)))
..()
return
//Making a medibot!
if(contents.len >= 1)
user << "<span class='warning'>You need to empty [src] out first!</span>"
return
var/obj/item/weapon/firstaid_arm_assembly/A = new /obj/item/weapon/firstaid_arm_assembly
if(istype(src,/obj/item/weapon/storage/firstaid/fire))
A.skin = "ointment"
else if(istype(src,/obj/item/weapon/storage/firstaid/toxin))
A.skin = "tox"
else if(istype(src,/obj/item/weapon/storage/firstaid/o2))
A.skin = "o2"
else if(istype(src,/obj/item/weapon/storage/firstaid/brute))
A.skin = "brute"
else if(istype(src,/obj/item/weapon/storage/firstaid/adv))
A.skin = "adv"
else if(istype(src,/obj/item/weapon/storage/firstaid/tactical))
A.skin = "bezerk"
else if(istype(src,/obj/item/weapon/storage/firstaid/aquatic_kit))
A.skin = "fish"
A.req_one_access = req_one_access
A.treatment_oxy = treatment_oxy
A.treatment_brute = treatment_brute
A.treatment_fire = treatment_fire
A.treatment_tox = treatment_tox
A.treatment_virus = treatment_virus
qdel(S)
user.put_in_hands(A)
user << "<span class='notice'>You add the robot arm to the first aid kit.</span>"
user.unEquip(src, 1)
qdel(src)
/obj/item/weapon/firstaid_arm_assembly/attackby(obj/item/weapon/W, mob/user, params)
..()
if(istype(W, /obj/item/weapon/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && loc != usr)
return
created_name = t
else
switch(build_step)
if(0)
if(istype(W, /obj/item/device/healthanalyzer))
if(!user.unEquip(W))
return
qdel(W)
build_step++
user << "<span class='notice'>You add the health sensor to [src].</span>"
name = "First aid/robot arm/health analyzer assembly"
overlays += image('icons/obj/aibots.dmi', "na_scanner")
if(1)
if(isprox(W))
if(!user.unEquip(W))
return
qdel(W)
build_step++
user << "<span class='notice'>You complete the Medibot. Beep boop!</span>"
var/turf/T = get_turf(src)
var/mob/living/simple_animal/bot/medbot/S = new /mob/living/simple_animal/bot/medbot(T)
S.skin = skin
S.name = created_name
S.bot_core.req_one_access = req_one_access
S.treatment_oxy = treatment_oxy
S.treatment_brute = treatment_brute
S.treatment_fire = treatment_fire
S.treatment_tox = treatment_tox
S.treatment_virus = treatment_virus
user.unEquip(src, 1)
qdel(src)
//Secbot Assembly
/obj/item/weapon/secbot_assembly
name = "incomplete securitron assembly"
desc = "Some sort of bizarre assembly made from a proximity sensor, helmet, and signaler."
icon = 'icons/obj/aibots.dmi'
icon_state = "helmet_signaler"
item_state = "helmet"
var/build_step = 0
var/created_name = "Securitron" //To preserve the name if it's a unique securitron I guess
/obj/item/clothing/head/helmet/attackby(obj/item/device/assembly/signaler/S, mob/user, params)
..()
if(!issignaler(S))
..()
return
if(!S.secured)
qdel(S)
var/obj/item/weapon/secbot_assembly/A = new /obj/item/weapon/secbot_assembly
user.put_in_hands(A)
user << "<span class='notice'>You add the signaler to the helmet.</span>"
user.unEquip(src, 1)
qdel(src)
else
return
/obj/item/weapon/secbot_assembly/attackby(obj/item/I, mob/user, params)
..()
if(istype(I, /obj/item/weapon/weldingtool))
if(!build_step)
var/obj/item/weapon/weldingtool/WT = I
if(WT.remove_fuel(0, user))
build_step++
overlays += "hs_hole"
user << "<span class='notice'>You weld a hole in [src]!</span>"
else if(build_step == 1)
var/obj/item/weapon/weldingtool/WT = I
if(WT.remove_fuel(0, user))
build_step--
overlays -= "hs_hole"
user << "<span class='notice'>You weld the hole in [src] shut!</span>"
else if(isprox(I) && (build_step == 1))
if(!user.unEquip(I))
return
build_step++
user << "<span class='notice'>You add the prox sensor to [src]!</span>"
overlays += "hs_eye"
name = "helmet/signaler/prox sensor assembly"
qdel(I)
else if(((istype(I, /obj/item/robot_parts/l_arm)) || (istype(I, /obj/item/robot_parts/r_arm))) && (build_step == 2))
if(!user.unEquip(I))
return
build_step++
user << "<span class='notice'>You add the robot arm to [src]!</span>"
name = "helmet/signaler/prox sensor/robot arm assembly"
overlays += "hs_arm"
qdel(I)
else if((istype(I, /obj/item/weapon/melee/baton)) && (build_step >= 3))
if(!user.unEquip(I))
return
build_step++
user << "<span class='notice'>You complete the Securitron! Beep boop.</span>"
var/mob/living/simple_animal/bot/secbot/S = new /mob/living/simple_animal/bot/secbot
S.forceMove(get_turf(src))
S.name = created_name
qdel(I)
qdel(src)
else if(istype(I, /obj/item/weapon/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && loc != usr)
return
created_name = t
else if(istype(I, /obj/item/weapon/screwdriver))
if(!build_step)
new /obj/item/device/assembly/signaler(get_turf(src))
new /obj/item/clothing/head/helmet(get_turf(src))
user << "<span class='notice'>You disconnect the signaler from the helmet.</span>"
qdel(src)
else if(build_step == 2)
overlays -= "hs_eye"
new /obj/item/device/assembly/prox_sensor(get_turf(src))
user << "<span class='notice'>You detach the proximity sensor from [src].</span>"
build_step--
else if(build_step == 3)
overlays -= "hs_arm"
new /obj/item/robot_parts/l_arm(get_turf(src))
user << "<span class='notice'>You remove the robot arm from [src].</span>"
build_step--
@@ -0,0 +1,569 @@
/mob/living/simple_animal/bot/ed209
name = "\improper ED-209 Security Robot"
desc = "A security robot. He looks less than thrilled."
icon = 'icons/obj/aibots.dmi'
icon_state = "ed2090"
density = 1
anchored = 0
health = 100
maxHealth = 100
damage_coeff = list(BRUTE = 0.5, BURN = 0.7, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
environment_smash = 2 //Walls can't stop THE LAW
radio_channel = "Security"
bot_type = SEC_BOT
bot_filter = RADIO_SECBOT
model = "ED-209"
bot_purpose = "seek out criminals, handcuff them, and report their location to security"
bot_core = /obj/machinery/bot_core/secbot
window_id = "autoed209"
window_name = "Automatic Security Unit v2.6"
var/lastfired = 0
var/shot_delay = 3 //.3 seconds between shots
var/lasercolor = ""
var/disabled = 0//A holder for if it needs to be disabled, if true it will not seach for targets, shoot at targets, or move, currently only used for lasertag
var/mob/living/carbon/target
var/oldtarget_name
var/threatlevel = 0
var/target_lastloc //Loc of target when arrested.
var/last_found //There's a delay
var/declare_arrests = 1 //When making an arrest, should it notify everyone wearing sechuds?
var/idcheck = 1 //If true, arrest people with no IDs
var/weaponscheck = 1 //If true, arrest people for weapons if they don't have access
var/check_records = 1 //Does it check security records?
var/arrest_type = 0 //If true, don't handcuff
var/projectile = /obj/item/projectile/energy/electrode //Holder for projectile type
var/shoot_sound = 'sound/weapons/Taser.ogg'
/mob/living/simple_animal/bot/ed209/New(loc,created_name,created_lasercolor)
..()
if(created_name)
name = created_name
if(created_lasercolor)
lasercolor = created_lasercolor
icon_state = "[lasercolor]ed209[on]"
set_weapon() //giving it the right projectile and firing sound.
spawn(3)
var/datum/job/detective/J = new/datum/job/detective
access_card.access += J.get_access()
prev_access = access_card.access
if(lasercolor)
shot_delay = 6//Longer shot delay because JESUS CHRIST
check_records = 0//Don't actively target people set to arrest
arrest_type = 1//Don't even try to cuff
bot_core.req_access = list(access_maint_tunnels, access_theatre)
arrest_type = 1
if((lasercolor == "b") && (name == "\improper ED-209 Security Robot"))//Picks a name if there isn't already a custome one
name = pick("BLUE BALLER","SANIC","BLUE KILLDEATH MURDERBOT")
if((lasercolor == "r") && (name == "\improper ED-209 Security Robot"))
name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT")
//SECHUD
var/datum/atom_hud/secsensor = huds[DATA_HUD_SECURITY_ADVANCED]
secsensor.add_hud_to(src)
permanent_huds |= secsensor
/mob/living/simple_animal/bot/ed209/turn_on()
. = ..()
icon_state = "[lasercolor]ed209[on]"
mode = BOT_IDLE
/mob/living/simple_animal/bot/ed209/turn_off()
..()
icon_state = "[lasercolor]ed209[on]"
/mob/living/simple_animal/bot/ed209/bot_reset()
..()
target = null
oldtarget_name = null
anchored = 0
walk_to(src,0)
last_found = world.time
set_weapon()
/mob/living/simple_animal/bot/ed209/set_custom_texts()
text_hack = "You disable [name]'s combat inhibitor."
text_dehack = "You restore [name]'s combat inhibitor."
text_dehack_fail = "[name] ignores your attempts to restrict him!"
/mob/living/simple_animal/bot/ed209/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += text({"
<TT><B>Security Unit v2.6 controls</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [open ? "opened" : "closed"]<BR>"},
"<A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A>" )
if(!locked || issilicon(user) || check_rights(R_ADMIN, 0, user))
if(!lasercolor)
dat += text({"<BR>
Arrest Unidentifiable Persons: []<BR>
Arrest for Unauthorized Weapons: []<BR>
Arrest for Warrant: []<BR>
<BR>
Operating Mode: []<BR>
Report Arrests[]<BR>
Auto Patrol[]"},
"<A href='?src=\ref[src];operation=idcheck'>[idcheck ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=weaponscheck'>[weaponscheck ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=ignorerec'>[check_records ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=switchmode'>[arrest_type ? "Detain" : "Arrest"]</A>",
"<A href='?src=\ref[src];operation=declarearrests'>[declare_arrests ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
return dat
/mob/living/simple_animal/bot/ed209/Topic(href, href_list)
if(lasercolor && (istype(usr,/mob/living/carbon/human)))
var/mob/living/carbon/human/H = usr
if((lasercolor == "b") && (istype(H.wear_suit, /obj/item/clothing/suit/redtag)))//Opposing team cannot operate it
return
else if((lasercolor == "r") && (istype(H.wear_suit, /obj/item/clothing/suit/bluetag)))
return
if(..())
return 1
switch(href_list["operation"])
if("idcheck")
idcheck = !idcheck
update_controls()
if("weaponscheck")
weaponscheck = !weaponscheck
update_controls()
if("ignorerec")
check_records = !check_records
update_controls()
if("switchmode")
arrest_type = !arrest_type
update_controls()
if("declarearrests")
declare_arrests = !declare_arrests
update_controls()
/mob/living/simple_animal/bot/ed209/proc/retaliate(mob/living/carbon/human/H)
threatlevel = H.assess_threat(src)
threatlevel += 6
if(threatlevel >= 4)
target = H
mode = BOT_HUNT
/mob/living/simple_animal/bot/ed209/attack_hand(mob/living/carbon/human/H)
if(H.a_intent == "harm")
retaliate(H)
return ..()
/mob/living/simple_animal/bot/ed209/attackby(obj/item/weapon/W, mob/user, params)
..()
if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != "harm") // Any intent but harm will heal, so we shouldn't get angry.
return
if(!istype(W, /obj/item/weapon/screwdriver) && (!target)) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass.
if(W.force && W.damtype != STAMINA)//If force is non-zero and damage type isn't stamina.
retaliate(user)
if(lasercolor)//To make up for the fact that lasertag bots don't hunt
shootAt(user)
/mob/living/simple_animal/bot/ed209/emag_act(mob/user)
..()
if(emagged == 2)
if(user)
user << "<span class='warning'>You short out [src]'s target assessment circuits.</span>"
oldtarget_name = user.name
audible_message("<span class='danger'>[src] buzzes oddly!</span>")
declare_arrests = 0
icon_state = "[lasercolor]ed209[on]"
set_weapon()
/mob/living/simple_animal/bot/ed209/bullet_act(obj/item/projectile/Proj)
if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet))
if((Proj.damage_type == BURN) || (Proj.damage_type == BRUTE))
if(!Proj.nodamage && Proj.damage < src.health)
retaliate(Proj.firer)
..()
/mob/living/simple_animal/bot/ed209/handle_automated_action()
if(!..())
return
if(disabled)
return
var/list/targets = list()
for(var/mob/living/carbon/C in view(7, src)) //Let's find us a target
var/threatlevel = 0
if((C.stat) || (C.lying))
continue
threatlevel = C.assess_threat(src, lasercolor)
//speak(C.real_name + text(": threat: []", threatlevel))
if(threatlevel < 4)
continue
var/dst = get_dist(src, C)
if(dst <= 1 || dst > 7)
continue
targets += C
if(targets.len>0)
var/mob/living/carbon/t = pick(targets)
if((t.stat!=2) && (t.lying != 1) && (!t.handcuffed)) //we don't shoot people who are dead, cuffed or lying down.
shootAt(t)
switch(mode)
if(BOT_IDLE) // idle
walk_to(src,0)
if(!lasercolor) //lasertag bots don't want to arrest anyone
look_for_perp() // see if any criminals are in range
if(!mode && auto_patrol) // still idle, and set to patrol
mode = BOT_START_PATROL // switch to patrol mode
if(BOT_HUNT) // hunting for perp
// if can't reach perp for long enough, go idle
if(frustration >= 8)
walk_to(src,0)
back_to_idle()
if(target) // make sure target exists
if(Adjacent(target) && isturf(target.loc)) // if right next to perp
stun_attack(target)
mode = BOT_PREP_ARREST
anchored = 1
target_lastloc = target.loc
return
else // not next to perp
var/turf/olddist = get_dist(src, target)
walk_to(src, target,1,4)
if((get_dist(src, target)) >= (olddist))
frustration++
else
frustration = 0
else
back_to_idle()
if(BOT_PREP_ARREST) // preparing to arrest target
// see if he got away. If he's no no longer adjacent or inside a closet or about to get up, we hunt again.
if(!Adjacent(target) || !isturf(target.loc) || target.weakened < 2)
back_to_hunt()
return
if(iscarbon(target) && target.canBeHandcuffed())
if(!arrest_type)
if(!target.handcuffed) //he's not cuffed? Try to cuff him!
cuff(target)
else
back_to_idle()
return
else
back_to_idle()
return
if(BOT_ARREST)
if(!target)
anchored = 0
mode = BOT_IDLE
last_found = world.time
frustration = 0
return
if(target.handcuffed) //no target or target cuffed? back to idle.
back_to_idle()
return
if(!Adjacent(target) || !isturf(target.loc) || (target.loc != target_lastloc && target.weakened < 2)) //if he's changed loc and about to get up or not adjacent or got into a closet, we prep arrest again.
back_to_hunt()
return
else
mode = BOT_PREP_ARREST
anchored = 0
if(BOT_START_PATROL)
look_for_perp()
start_patrol()
if(BOT_PATROL)
look_for_perp()
bot_patrol()
return
/mob/living/simple_animal/bot/ed209/proc/back_to_idle()
anchored = 0
mode = BOT_IDLE
target = null
last_found = world.time
frustration = 0
spawn(0)
handle_automated_action() //ensure bot quickly responds
/mob/living/simple_animal/bot/ed209/proc/back_to_hunt()
anchored = 0
frustration = 0
mode = BOT_HUNT
spawn(0)
handle_automated_action() //ensure bot quickly responds
// look for a criminal in view of the bot
/mob/living/simple_animal/bot/ed209/proc/look_for_perp()
if(disabled)
return
anchored = 0
threatlevel = 0
for (var/mob/living/carbon/C in view(7,src)) //Let's find us a criminal
if((C.stat) || (C.handcuffed))
continue
if((C.name == oldtarget_name) && (world.time < last_found + 100))
continue
threatlevel = C.assess_threat(src, lasercolor)
if(!threatlevel)
continue
else if(threatlevel >= 4)
target = C
oldtarget_name = C.name
speak("Level [threatlevel] infraction alert!")
playsound(loc, pick('sound/voice/ed209_20sec.ogg', 'sound/voice/EDPlaceholder.ogg'), 50, 0)
visible_message("<b>[src]</b> points at [C.name]!")
mode = BOT_HUNT
spawn(0)
handle_automated_action() // ensure bot quickly responds to a perp
break
else
continue
/mob/living/simple_animal/bot/ed209/proc/check_for_weapons(var/obj/item/slot_item)
if(slot_item && slot_item.needs_permit)
return 1
return 0
/mob/living/simple_animal/bot/ed209/explode()
walk_to(src,0)
visible_message("<span class='userdanger'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
var/obj/item/weapon/ed209_assembly/Sa = new /obj/item/weapon/ed209_assembly(Tsec)
Sa.build_step = 1
Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole")
Sa.created_name = name
new /obj/item/device/assembly/prox_sensor(Tsec)
if(!lasercolor)
var/obj/item/weapon/gun/energy/advtaser/G = new /obj/item/weapon/gun/energy/advtaser(Tsec)
G.power_supply.charge = 0
G.update_icon()
else if(lasercolor == "b")
var/obj/item/weapon/gun/energy/laser/bluetag/G = new /obj/item/weapon/gun/energy/laser/bluetag(Tsec)
G.power_supply.charge = 0
G.update_icon()
else if(lasercolor == "r")
var/obj/item/weapon/gun/energy/laser/redtag/G = new /obj/item/weapon/gun/energy/laser/redtag(Tsec)
G.power_supply.charge = 0
G.update_icon()
if(prob(50))
new /obj/item/robot_parts/l_leg(Tsec)
if(prob(25))
new /obj/item/robot_parts/r_leg(Tsec)
if(prob(25))//50% chance for a helmet OR vest
if(prob(50))
new /obj/item/clothing/head/helmet(Tsec)
else
if(!lasercolor)
new /obj/item/clothing/suit/armor/vest(Tsec)
if(lasercolor == "b")
new /obj/item/clothing/suit/bluetag(Tsec)
if(lasercolor == "r")
new /obj/item/clothing/suit/redtag(Tsec)
var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
new /obj/effect/decal/cleanable/blood/oil(loc)
..()
/mob/living/simple_animal/bot/ed209/proc/set_weapon() //used to update the projectile type and firing sound
shoot_sound = 'sound/weapons/laser.ogg'
if(emagged == 2)
if(lasercolor)
projectile = /obj/item/projectile/lasertag
else
projectile = /obj/item/projectile/beam
else
if(!lasercolor)
shoot_sound = 'sound/weapons/Taser.ogg'
projectile = /obj/item/projectile/energy/electrode
else if(lasercolor == "b")
projectile = /obj/item/projectile/lasertag/blue
else if(lasercolor == "r")
projectile = /obj/item/projectile/lasertag/red
/mob/living/simple_animal/bot/ed209/proc/shootAt(mob/target)
if(lastfired && world.time - lastfired < shot_delay)
return
lastfired = world.time
var/turf/T = loc
var/atom/U = (istype(target, /atom/movable) ? target.loc : target)
if((!( U ) || !( T )))
return
while(!(istype(U, /turf)))
U = U.loc
if(!(istype(T, /turf)))
return
if(!projectile)
return
if(!(istype(U, /turf)))
return
var/obj/item/projectile/A = new projectile(loc)
playsound(loc, shoot_sound, 50, 1)
A.current = U
A.yo = U.y - T.y
A.xo = U.x - T.x
spawn(0)
A.process()
/mob/living/simple_animal/bot/ed209/attack_alien(mob/living/carbon/alien/user)
..()
if(!isalien(target))
target = user
mode = BOT_HUNT
/mob/living/simple_animal/bot/ed209/emp_act(severity)
if(severity==2 && prob(70))
..(severity-1)
else
var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( loc )
pulse2.icon = 'icons/effects/effects.dmi'
pulse2.icon_state = "empdisable"
pulse2.name = "emp sparks"
pulse2.anchored = 1
pulse2.dir = pick(cardinal)
spawn(10)
qdel(pulse2)
var/list/mob/living/carbon/targets = new
for(var/mob/living/carbon/C in view(12,src))
if(C.stat==2)
continue
targets += C
if(targets.len)
if(prob(50))
var/mob/toshoot = pick(targets)
if(toshoot)
targets-=toshoot
if(prob(50) && emagged < 2)
emagged = 2
set_weapon()
shootAt(toshoot)
emagged = 0
set_weapon()
else
shootAt(toshoot)
else if(prob(50))
if(targets.len)
var/mob/toarrest = pick(targets)
if(toarrest)
target = toarrest
mode = BOT_HUNT
/mob/living/simple_animal/bot/ed209/bullet_act(obj/item/projectile/Proj)
if(!disabled)
var/lasertag_check = 0
if((lasercolor == "b"))
if(istype(Proj, /obj/item/projectile/lasertag/red))
lasertag_check++
else if((lasercolor == "r"))
if(istype(Proj, /obj/item/projectile/lasertag/blue))
lasertag_check++
if(lasertag_check)
icon_state = "[lasercolor]ed2090"
disabled = 1
target = null
spawn(100)
disabled = 0
icon_state = "[lasercolor]ed2091"
return 1
else
..(Proj)
else
..(Proj)
/mob/living/simple_animal/bot/ed209/bluetag
lasercolor = "b"
/mob/living/simple_animal/bot/ed209/redtag
lasercolor = "r"
/mob/living/simple_animal/bot/ed209/UnarmedAttack(atom/A)
if(!on)
return
if(iscarbon(A))
var/mob/living/carbon/C = A
if(!C.stunned || arrest_type)
stun_attack(A)
else if(C.canBeHandcuffed() && !C.handcuffed)
cuff(A)
else
..()
/mob/living/simple_animal/bot/ed209/RangedAttack(atom/A)
if(!on)
return
shootAt(A)
/mob/living/simple_animal/bot/ed209/proc/stun_attack(mob/living/carbon/C)
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
icon_state = "[lasercolor]ed209-c"
spawn(2)
icon_state = "[lasercolor]ed209[on]"
var/threat = 5
if(istype(C, /mob/living/carbon/human))
C.stuttering = 5
C.Stun(5)
C.Weaken(5)
var/mob/living/carbon/human/H = C
threat = H.assess_threat(src)
else
C.Weaken(5)
C.stuttering = 5
C.Stun(5)
add_logs(src,C,"stunned")
if(declare_arrests)
var/area/location = get_area(src)
speak("[arrest_type ? "Detaining" : "Arresting"] level [threat] scumbag <b>[C]</b> in [location].", radio_channel)
C.visible_message("<span class='danger'>[src] has stunned [C]!</span>",\
"<span class='userdanger'>[src] has stunned you!</span>")
/mob/living/simple_animal/bot/ed209/proc/cuff(mob/living/carbon/C)
mode = BOT_ARREST
playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
C.visible_message("<span class='danger'>[src] is trying to put zipties on [C]!</span>",\
"<span class='userdanger'>[src] is trying to put zipties on you!</span>")
spawn(60)
if( !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing.
return
if(!C.handcuffed)
C.handcuffed = new /obj/item/weapon/restraints/handcuffs/cable/zipties/used(C)
C.update_inv_handcuffed(1)
back_to_idle()
@@ -0,0 +1,119 @@
/mob/living/simple_animal/bot/emote(var/act, var/m_type=1, var/message = null)
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_'
act = copytext(act,1,length(act))
//Emote Cooldown System (it's so simple!)
// proc/handle_emote_CD() located in [code\modules\mob\emote.dm]
var/on_CD = 0
switch(act)
//Cooldown-inducing emotes
if("scream", "screams")
on_CD = handle_emote_CD(50) //longer cooldown
if("ping","buzz","beep","yes","no") //halt is exempt because it's used to stop criminal scum //WHOEVER THOUGHT THAT WAS A GOOD IDEA IS GOING TO GET SHOT.
on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm
//Everything else, including typos of the above emotes
else
on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown
if(on_CD == 1) // Check if we need to suppress the emote attempt.
return // Suppress emote, you're still cooling off.
//--FalseIncarnate
switch(act)
if("ping")
var/M = null
if(param)
for (var/mob/A in view(null, null))
if (param == A.name)
M = A
break
if(!M)
param = null
if (param)
message = "<B>[src]</B> pings at [param]."
else
message = "<B>[src]</B> pings."
playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
m_type = 2
if("buzz")
var/M = null
if(param)
for (var/mob/A in view(null, null))
if (param == A.name)
M = A
break
if(!M)
param = null
if (param)
message = "<B>[src]</B> buzzes at [param]."
else
message = "<B>[src]</B> buzzes."
playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
m_type = 2
if("beep")
var/M = null
if(param)
for (var/mob/A in view(null, null))
if (param == A.name)
M = A
break
if(!M)
param = null
if (param)
message = "<B>[src]</B> beeps at [param]."
else
message = "<B>[src]</B> beeps."
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
m_type = 2
if("yes")
var/M = null
if(param)
for (var/mob/A in view(null, null))
if (param == A.name)
M = A
break
if(!M)
param = null
if (param)
message = "<B>[src]</B> emits an affirmative blip at [param]."
else
message = "<B>[src]</B> emits an affirmative blip."
playsound(src.loc, 'sound/machines/synth_yes.ogg', 50, 0)
m_type = 2
if("no")
var/M = null
if(param)
for (var/mob/A in view(null, null))
if (param == A.name)
M = A
break
if(!M)
param = null
if (param)
message = "<B>[src]</B> emits a negative blip at [param]."
else
message = "<B>[src]</B> emits a negative blip."
playsound(src.loc, 'sound/machines/synth_no.ogg', 50, 0)
m_type = 2
if("scream", "screams")
message = "<B>[src]</B> screams!"
playsound(src.loc, 'sound/goonstation/voice/robot_scream.ogg', 80, 0)
m_type = 2
..(act, m_type, message)
@@ -0,0 +1,425 @@
//Floorbot
/mob/living/simple_animal/bot/floorbot
name = "\improper Floorbot"
desc = "A little floor repairing robot, he looks so excited!"
icon = 'icons/obj/aibots.dmi'
icon_state = "floorbot0"
density = 0
anchored = 0
health = 25
maxHealth = 25
radio_channel = "Engineering"
bot_type = FLOOR_BOT
bot_filter = RADIO_FLOORBOT
model = "Floorbot"
bot_purpose = "seek out damaged or missing floor tiles, and repair or replace them as necessary"
bot_core = /obj/machinery/bot_core/floorbot
window_id = "autofloor"
window_name = "Automatic Station Floor Repairer v1.1"
var/process_type //Determines what to do when process_scan() recieves a target. See process_scan() for details.
var/targetdirection
var/amount = 10
var/replacetiles = 0
var/eattiles = 0
var/maketiles = 0
var/fixfloors = 0
var/autotile = 0
var/nag_on_empty = 1
var/nagged = 0 //Prevents the Floorbot nagging more than once per refill.
var/max_targets = 50
var/turf/target
var/oldloc = null
#define HULL_BREACH 1
#define BRIDGE_MODE 2
#define FIX_TILE 3
#define AUTO_TILE 4
#define REPLACE_TILE 5
#define TILE_EMAG 6
/mob/living/simple_animal/bot/floorbot/New()
..()
update_icon()
var/datum/job/engineer/J = new/datum/job/engineer
access_card.access += J.get_access()
prev_access = access_card.access
/mob/living/simple_animal/bot/floorbot/bot_reset()
..()
target = null
oldloc = null
ignore_list = list()
nagged = 0
anchored = 0
update_icon()
/mob/living/simple_animal/bot/floorbot/set_custom_texts()
text_hack = "You corrupt [name]'s construction protocols."
text_dehack = "You detect errors in [name] and reset his programming."
text_dehack_fail = "[name] is not responding to reset commands!"
/mob/living/simple_animal/bot/floorbot/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += "<TT><B>Floor Repairer Controls v1.1</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel panel is [open ? "opened" : "closed"]<BR>"
dat += "Tiles left: [amount]<BR>"
dat += "Behvaiour controls are [locked ? "locked" : "unlocked"]<BR>"
if(!locked || issilicon(user) || check_rights(R_ADMIN, 0, user))
dat += "Add tiles to new hull plating: <A href='?src=\ref[src];operation=autotile'>[autotile ? "Yes" : "No"]</A><BR>"
dat += "Replace floor tiles: <A href='?src=\ref[src];operation=replace'>[replacetiles ? "Yes" : "No"]</A><BR>"
dat += "Finds tiles: <A href='?src=\ref[src];operation=tiles'>[eattiles ? "Yes" : "No"]</A><BR>"
dat += "Make pieces of metal into tiles when empty: <A href='?src=\ref[src];operation=make'>[maketiles ? "Yes" : "No"]</A><BR>"
dat += "Transmit notice when empty: <A href='?src=\ref[src];operation=emptynag'>[nag_on_empty ? "Yes" : "No"]</A><BR>"
dat += "Repair damaged tiles and platings: <A href='?src=\ref[src];operation=fix'>[fixfloors ? "Yes" : "No"]</A><BR>"
dat += "Traction Magnets: <A href='?src=\ref[src];operation=anchor'>[anchored ? "Engaged" : "Disengaged"]</A><BR>"
dat += "Patrol Station: <A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "Yes" : "No"]</A><BR>"
var/bmode
if(targetdirection)
bmode = dir2text(targetdirection)
else
bmode = "disabled"
dat += "Bridge Mode : <A href='?src=\ref[src];operation=bridgemode'>[bmode]</A><BR>"
return dat
/mob/living/simple_animal/bot/floorbot/attackby(obj/item/W , mob/user, params)
if(istype(W, /obj/item/stack/tile/plasteel))
var/obj/item/stack/tile/plasteel/T = W
if(amount >= 50)
return
var/loaded = min(50-amount, T.amount)
T.use(loaded)
amount += loaded
if(loaded > 0)
user << "<span class='notice'>You load [loaded] tiles into the floorbot. He now contains [amount] tiles.</span>"
nagged = 0
update_icon()
else
user << "<span class='warning'>You need at least one floor tile to put into [src]!</span>"
else
..()
/mob/living/simple_animal/bot/floorbot/emag_act(mob/user)
..()
if(emagged == 2)
if(user)
user << "<span class='danger'>[src] buzzes and beeps.</span>"
/mob/living/simple_animal/bot/floorbot/Topic(href, href_list)
if(..())
return 1
switch(href_list["operation"])
if("replace")
replacetiles = !replacetiles
if("tiles")
eattiles = !eattiles
if("make")
maketiles = !maketiles
if("fix")
fixfloors = !fixfloors
if("autotile")
autotile = !autotile
if("emptynag")
nag_on_empty = !nag_on_empty
if("anchor")
anchored = !anchored
if("bridgemode")
var/setdir = input("Select construction direction:") as null|anything in list("north","east","south","west","disable")
switch(setdir)
if("north")
targetdirection = 1
if("south")
targetdirection = 2
if("east")
targetdirection = 4
if("west")
targetdirection = 8
if("disable")
targetdirection = null
update_controls()
/mob/living/simple_animal/bot/floorbot/handle_automated_action()
if(!..())
return
if(mode == BOT_REPAIRING)
return
if(amount <= 0 && !target) //Out of tiles! We must refill!
if(eattiles) //Configured to find and consume floortiles!
target = scan(/obj/item/stack/tile/plasteel)
process_type = null
if(!target && maketiles) //We did not manage to find any floor tiles! Scan for metal stacks and make our own!
target = scan(/obj/item/stack/sheet/metal)
process_type = null
return
else
if(nag_on_empty) //Floorbot is empty and cannot acquire more tiles, nag the engineers for more!
nag()
if(prob(5))
audible_message("[src] makes an excited booping beeping sound!")
//Normal scanning procedure. We have tiles loaded, are not emagged.
if(!target && emagged < 2 && amount > 0)
if(targetdirection != null) //The bot is in bridge mode.
//Try to find a space tile immediately in our selected direction.
var/turf/T = get_step(src, targetdirection)
if(istype(T, /turf/space))
target = T
else //Find a space tile farther way!
target = scan(/turf/space)
process_type = BRIDGE_MODE
if(!target)
process_type = HULL_BREACH //Ensures the floorbot does not try to "fix" space areas or shuttle docking zones.
target = scan(/turf/space)
if(!target && replacetiles) //Finds a floor without a tile and gives it one.
process_type = REPLACE_TILE //The target must be the floor and not a tile. The floor must not already have a floortile.
target = scan(/turf/simulated/floor)
if(!target && fixfloors) //Repairs damaged floors and tiles.
process_type = FIX_TILE
target = scan(/turf/simulated/floor)
if(!target && emagged == 2) //We are emagged! Time to rip up the floors!
process_type = TILE_EMAG
target = scan(/turf/simulated/floor)
if(!target)
if(auto_patrol)
if(mode == BOT_IDLE || mode == BOT_START_PATROL)
start_patrol()
if(mode == BOT_PATROL)
bot_patrol()
if(target)
if(path.len == 0)
if(!istype(target, /turf/))
var/turf/TL = get_turf(target)
path = get_path_to(src, TL, /turf/proc/Distance_cardinal, 0, 30, id=access_card,simulated_only = 0)
else
path = get_path_to(src, target, /turf/proc/Distance_cardinal, 0, 30, id=access_card,simulated_only = 0)
if(!bot_move(target))
add_to_ignore(target)
target = null
mode = BOT_IDLE
return
else if( !bot_move(target) )
target = null
mode = BOT_IDLE
return
if(loc == target || loc == target.loc)
if(istype(target, /obj/item/stack/tile/plasteel))
eattile(target)
else if(istype(target, /obj/item/stack/sheet/metal))
maketile(target)
else if(istype(target, /turf/) && emagged < 2)
repair(target)
else if(emagged == 2 && istype(target,/turf/simulated/floor))
var/turf/simulated/floor/F = target
anchored = 1
mode = BOT_REPAIRING
if(prob(90))
F.break_tile_to_plating()
else
F.ReplaceWithLattice()
audible_message("<span class='danger'>[src] makes an excited booping sound.</span>")
spawn(50)
amount ++
anchored = 0
mode = BOT_IDLE
target = null
path = list()
return
oldloc = loc
/mob/living/simple_animal/bot/floorbot/proc/nag() //Annoy everyone on the channel to refill us!
if(!nagged)
speak("Requesting refill at <b>[get_area(src)]</b>!", radio_channel)
nagged = 1
/mob/living/simple_animal/bot/floorbot/proc/is_hull_breach(turf/t) //Ignore space tiles not considered part of a structure, also ignores shuttle docking areas.
var/area/t_area = get_area(t)
if(t_area && (t_area.name == "Space" || findtext(t_area.name, "huttle")))
return 0
else
return 1
//Floorbots, having several functions, need sort out special conditions here.
/mob/living/simple_animal/bot/floorbot/process_scan(scan_target)
var/result
var/turf/simulated/floor/F
switch(process_type)
if(HULL_BREACH) //The most common job, patching breaches in the station's hull.
if(is_hull_breach(scan_target)) //Ensure that the targeted space turf is actually part of the station, and not random space.
result = scan_target
anchored = 1 //Prevent the floorbot being blown off-course while trying to reach a hull breach.
if(BRIDGE_MODE) //Only space turfs in our chosen direction are considered.
if(get_dir(src, scan_target) == targetdirection)
result = scan_target
anchored = 1
if(REPLACE_TILE)
F = scan_target
if(istype(F, /turf/simulated/floor/plating)) //The floor must not already have a tile.
result = F
if(FIX_TILE) //Selects only damaged floors.
F = scan_target
if(istype(F) && (F.broken || F.burnt))
result = F
if(TILE_EMAG) //Emag mode! Rip up the floor and cause breaches to space!
F = scan_target
if(!istype(F, /turf/simulated/floor/plating))
result = F
else //If no special processing is needed, simply return the result.
result = scan_target
return result
/mob/living/simple_animal/bot/floorbot/proc/repair(turf/target_turf)
if(istype(target_turf, /turf/space/))
//Must be a hull breach or in bridge mode to continue.
if(!is_hull_breach(target_turf) && !targetdirection)
target = null
return
else if(!istype(target_turf, /turf/simulated/floor))
return
if(amount <= 0)
mode = BOT_IDLE
target = null
return
anchored = 1
icon_state = "floorbot-c"
if(istype(target_turf, /turf/space/)) //If we are fixing an area not part of pure space, it is
visible_message("<span class='notice'>[targetdirection ? "[src] begins installing a bridge plating." : "[src] begins to repair the hole."] </span>")
mode = BOT_REPAIRING
spawn(50)
if(mode == BOT_REPAIRING)
if(autotile) //Build the floor and include a tile.
target_turf.ChangeTurf(/turf/simulated/floor/plasteel)
else //Build a hull plating without a floor tile.
target_turf.ChangeTurf(/turf/simulated/floor/plating)
mode = BOT_IDLE
amount -= 1
update_icon()
anchored = 0
target = null
else
var/turf/simulated/floor/F = target_turf
mode = BOT_REPAIRING
visible_message("<span class='notice'>[src] begins repairing the floor.</span>")
spawn(50)
if(mode == BOT_REPAIRING)
F.broken = 0
F.burnt = 0
F.ChangeTurf(/turf/simulated/floor/plasteel)
mode = BOT_IDLE
amount -= 1
update_icon()
anchored = 0
target = null
/mob/living/simple_animal/bot/floorbot/proc/eattile(obj/item/stack/tile/plasteel/T)
if(!istype(T, /obj/item/stack/tile/plasteel))
return
visible_message("<span class='notice'>[src] begins to collect tiles.</span>")
mode = BOT_REPAIRING
spawn(20)
if(isnull(T))
target = null
mode = BOT_IDLE
return
if(amount + T.amount > 50)
var/i = 50 - amount
amount += i
T.amount -= i
else
amount += T.amount
qdel(T)
update_icon()
target = null
mode = BOT_IDLE
/mob/living/simple_animal/bot/floorbot/proc/maketile(obj/item/stack/sheet/metal/M)
if(!istype(M, /obj/item/stack/sheet/metal))
return
visible_message("<span class='notice'>[src] begins to create tiles.</span>")
mode = BOT_REPAIRING
spawn(20)
if(isnull(M))
target = null
mode = BOT_IDLE
return
var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel
T.amount = 4
T.forceMove(M.loc)
if(M.amount > 1)
M.amount--
else
qdel(M)
target = null
mode = BOT_IDLE
/mob/living/simple_animal/bot/floorbot/update_icon()
if(amount > 0)
icon_state = "floorbot[on]"
else
icon_state = "floorbot[on]e"
/mob/living/simple_animal/bot/floorbot/explode()
on = 0
visible_message("<span class='userdanger'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
var/obj/item/weapon/storage/toolbox/mechanical/N = new /obj/item/weapon/storage/toolbox/mechanical(Tsec)
N.contents = list()
new /obj/item/device/assembly/prox_sensor(Tsec)
if(prob(50))
new /obj/item/robot_parts/l_arm(Tsec)
while(amount)//Dumps the tiles into the appropriate sized stacks
if(amount >= 16)
var/obj/item/stack/tile/plasteel/T = new (Tsec)
T.amount = 16
amount -= 16
else
var/obj/item/stack/tile/plasteel/T = new (Tsec)
T.amount = amount
amount = 0
var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
..()
/obj/machinery/bot_core/floorbot
req_one_access = list(access_construction, access_robotics)
/mob/living/simple_animal/bot/floorbot/UnarmedAttack(atom/A)
if(isturf(A))
repair(A)
else if(istype(A,/obj/item/stack/tile/plasteel))
eattile(A)
else if(istype(A,/obj/item/stack/sheet/metal))
maketile(A)
else
..()
@@ -0,0 +1,578 @@
//Medbot
/mob/living/simple_animal/bot/medbot
name = "\improper Medibot"
desc = "A little medical robot. He looks somewhat underwhelmed."
icon = 'icons/obj/aibots.dmi'
icon_state = "medibot0"
density = 0
anchored = 0
health = 20
maxHealth = 20
pass_flags = PASSMOB
radio_channel = "Medical"
bot_type = MED_BOT
bot_filter = RADIO_MEDBOT
model = "Medibot"
bot_purpose = "seek out hurt crewmembers and ensure that they are healed"
bot_core_type = /obj/machinery/bot_core/medbot
window_id = "automed"
window_name = "Automatic Medical Unit v1.1"
var/obj/item/weapon/reagent_containers/glass/reagent_glass = null //Can be set to draw from this for reagents.
var/skin = null //Set to "tox", "ointment" or "o2" for the other two firstaid kits.
var/mob/living/carbon/patient = null
var/mob/living/carbon/oldpatient = null
var/oldloc = null
var/last_found = 0
var/last_newpatient_speak = 0 //Don't spam the "HEY I'M COMING" messages
var/injection_amount = 15 //How much reagent do we inject at a time?
var/heal_threshold = 10 //Start healing when they have this much damage in a category
var/use_beaker = 0 //Use reagents in beaker instead of default treatment agents.
var/declare_crit = 1 //If active, the bot will transmit a critical patient alert to MedHUD users.
var/declare_cooldown = 0 //Prevents spam of critical patient alerts.
var/stationary_mode = 0 //If enabled, the Medibot will not move automatically.
//Setting which reagents to use to treat what by default. By id.
var/treatment_brute = "salglu_solution"
var/treatment_oxy = "salbutamol"
var/treatment_fire = "salglu_solution"
var/treatment_tox = "charcoal"
var/treatment_virus = "spaceacillin"
var/treat_virus = 1 //If on, the bot will attempt to treat viral infections, curing them if possible.
var/shut_up = 0 //self explanatory :)
/mob/living/simple_animal/bot/medbot/tox
skin = "tox"
/mob/living/simple_animal/bot/medbot/o2
skin = "o2"
/mob/living/simple_animal/bot/medbot/brute
skin = "brute"
/mob/living/simple_animal/bot/medbot/fire
skin = "ointment"
/mob/living/simple_animal/bot/medbot/adv
skin = "adv"
/mob/living/simple_animal/bot/medbot/fish
skin = "fish"
/mob/living/simple_animal/bot/medbot/mysterious
name = "\improper Mysterious Medibot"
desc = "International Medibot of mystery."
skin = "bezerk"
treatment_oxy = "perfluorodecalin"
treatment_brute = "styptic_powder"
treatment_fire = "silver_sulfadiazine"
treatment_tox = "charcoal"
/mob/living/simple_animal/bot/medbot/syndicate
name = "Suspicious Medibot"
desc = "You'd better have insurance!"
skin = "bezerk"
treatment_oxy = "perfluorodecalin"
treatment_brute = "styptic_powder"
treatment_fire = "silver_sulfadiazine"
treatment_tox = "charcoal"
bot_core_type = /obj/machinery/bot_core/medbot/syndicate
control_freq = BOT_FREQ + 1000 // make it not show up on lists
radio_channel = "Syndicate"
radio_config = list("Common" = 1, "Medical" = 1, "Syndicate" = 1)
/mob/living/simple_animal/bot/medbot/syndicate/New()
..()
Radio.syndie = 1
/mob/living/simple_animal/bot/medbot/update_icon()
if(!on)
icon_state = "medibot0"
return
if(mode == BOT_HEALING)
icon_state = "medibots[stationary_mode]"
return
else if(stationary_mode) //Bot has yellow light to indicate stationary mode.
icon_state = "medibot2"
else
icon_state = "medibot1"
/mob/living/simple_animal/bot/medbot/New()
..()
update_icon()
spawn(4)
if(skin)
overlays += image('icons/obj/aibots.dmi', "medskin_[skin]")
var/datum/job/doctor/J = new/datum/job/doctor
access_card.access += J.get_access()
prev_access = access_card.access
var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED]
medsensor.add_hud_to(src)
permanent_huds |= medsensor
/mob/living/simple_animal/bot/medbot/bot_reset()
..()
patient = null
oldpatient = null
oldloc = null
last_found = world.time
declare_cooldown = 0
update_icon()
/mob/living/simple_animal/bot/medbot/proc/soft_reset() //Allows the medibot to still actively perform its medical duties without being completely halted as a hard reset does.
path = list()
patient = null
mode = BOT_IDLE
last_found = world.time
update_icon()
/mob/living/simple_animal/bot/medbot/set_custom_texts()
text_hack = "You corrupt [name]'s reagent processor circuits."
text_dehack = "You reset [name]'s reagent processor circuits."
text_dehack_fail = "[name] seems damaged and does not respond to reprogramming!"
/mob/living/simple_animal/bot/medbot/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += "<TT><B>Medical Unit Controls v1.1</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel panel is [open ? "opened" : "closed"]<BR>"
dat += "Beaker: "
if(reagent_glass)
dat += "<A href='?src=\ref[src];eject=1'>Loaded \[[reagent_glass.reagents.total_volume]/[reagent_glass.reagents.maximum_volume]\]</a>"
else
dat += "None Loaded"
dat += "<br>Behaviour controls are [locked ? "locked" : "unlocked"]<hr>"
if(!locked || issilicon(user) || check_rights(R_ADMIN, 0, user))
dat += "<TT>Healing Threshold: "
dat += "<a href='?src=\ref[src];adj_threshold=-10'>--</a> "
dat += "<a href='?src=\ref[src];adj_threshold=-5'>-</a> "
dat += "[heal_threshold] "
dat += "<a href='?src=\ref[src];adj_threshold=5'>+</a> "
dat += "<a href='?src=\ref[src];adj_threshold=10'>++</a>"
dat += "</TT><br>"
dat += "<TT>Injection Level: "
dat += "<a href='?src=\ref[src];adj_inject=-5'>-</a> "
dat += "[injection_amount] "
dat += "<a href='?src=\ref[src];adj_inject=5'>+</a> "
dat += "</TT><br>"
dat += "Reagent Source: "
dat += "<a href='?src=\ref[src];use_beaker=1'>[use_beaker ? "Loaded Beaker (When available)" : "Internal Synthesizer"]</a><br>"
dat += "Treat Viral Infections: <a href='?src=\ref[src];virus=1'>[treat_virus ? "Yes" : "No"]</a><br>"
dat += "The speaker switch is [shut_up ? "off" : "on"]. <a href='?src=\ref[src];togglevoice=[1]'>Toggle</a><br>"
dat += "Critical Patient Alerts: <a href='?src=\ref[src];critalerts=1'>[declare_crit ? "Yes" : "No"]</a><br>"
dat += "Patrol Station: <a href='?src=\ref[src];operation=patrol'>[auto_patrol ? "Yes" : "No"]</a><br>"
dat += "Stationary Mode: <a href='?src=\ref[src];stationary=1'>[stationary_mode ? "Yes" : "No"]</a><br>"
return dat
/mob/living/simple_animal/bot/medbot/Topic(href, href_list)
if(..())
return 1
if(href_list["adj_threshold"])
var/adjust_num = text2num(href_list["adj_threshold"])
heal_threshold += adjust_num
if(heal_threshold < 5)
heal_threshold = 5
if(heal_threshold > 75)
heal_threshold = 75
else if(href_list["adj_inject"])
var/adjust_num = text2num(href_list["adj_inject"])
injection_amount += adjust_num
if(injection_amount < 5)
injection_amount = 5
if(injection_amount > 15)
injection_amount = 15
else if(href_list["use_beaker"])
use_beaker = !use_beaker
else if(href_list["eject"] && (!isnull(reagent_glass)))
reagent_glass.forceMove(get_turf(src))
reagent_glass = null
else if(href_list["togglevoice"])
shut_up = !shut_up
else if(href_list["critalerts"])
declare_crit = !declare_crit
else if(href_list["stationary"])
stationary_mode = !stationary_mode
path = list()
update_icon()
else if(href_list["virus"])
treat_virus = !treat_virus
update_controls()
return
/mob/living/simple_animal/bot/medbot/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/weapon/reagent_containers/glass))
if(locked)
user << "<span class='warning'>You cannot insert a beaker because the panel is locked!</span>"
return
if(!isnull(reagent_glass))
user << "<span class='warning'>There is already a beaker loaded!</span>"
return
if(!user.drop_item())
return
W.forceMove(src)
reagent_glass = W
user << "<span class='notice'>You insert [W].</span>"
show_controls(user)
return
else
var/current_health = health
..()
if(health < current_health) //if medbot took some damage
step_to(src, (get_step_away(src,user)))
/mob/living/simple_animal/bot/medbot/emag_act(mob/user)
..()
if(emagged == 2)
declare_crit = 0
if(user)
user << "<span class='notice'>You short out [src]'s reagent synthesis circuits.</span>"
audible_message("<span class='danger'>[src] buzzes oddly!</span>")
flick("medibot_spark", src)
if(user)
oldpatient = user
/mob/living/simple_animal/bot/medbot/process_scan(mob/living/carbon/human/H)
if(H.stat == 2)
return
if((H == oldpatient) && (world.time < last_found + 200))
return
if(assess_patient(H))
last_found = world.time
if((last_newpatient_speak + 300) < world.time) //Don't spam these messages!
var/message = pick("Hey, [H.name]! Hold on, I'm coming.","Wait [H.name]! I want to help!","[H.name], you appear to be injured!")
speak(message)
last_newpatient_speak = world.time
return H
else
return
/mob/living/simple_animal/bot/medbot/handle_automated_action()
if(!..())
return
if(mode == BOT_HEALING)
return
if(stunned)
icon_state = "medibota"
stunned--
oldpatient = patient
patient = null
mode = BOT_IDLE
if(stunned <= 0)
update_icon()
stunned = 0
return
if(frustration > 8)
oldpatient = patient
soft_reset()
if(!patient)
if(!shut_up && prob(1))
var/message = pick("Radar, put a mask on!","There's always a catch, and it's the best there is.","I knew it, I should've been a plastic surgeon.","What kind of medbay is this? Everyone's dropping like dead flies.","Delicious!")
speak(message)
var/scan_range = (stationary_mode ? 1 : DEFAULT_SCAN_RANGE) //If in stationary mode, scan range is limited to adjacent patients.
patient = scan(/mob/living/carbon/human, oldpatient, scan_range)
oldpatient = patient
if(patient && (get_dist(src,patient) <= 1)) //Patient is next to us, begin treatment!
if(mode != BOT_HEALING)
mode = BOT_HEALING
update_icon()
frustration = 0
medicate_patient(patient)
return
//Patient has moved away from us!
else if(patient && path.len && (get_dist(patient,path[path.len]) > 2))
path = list()
mode = BOT_IDLE
last_found = world.time
else if(stationary_mode && patient) //Since we cannot move in this mode, ignore the patient and wait for another.
soft_reset()
return
if(patient && path.len == 0 && (get_dist(src,patient) > 1))
path = get_path_to(src, get_turf(patient), /turf/proc/Distance_cardinal, 0, 30,id=access_card)
mode = BOT_MOVING
if(!path.len) //try to get closer if you can't reach the patient directly
path = get_path_to(src, get_turf(patient), /turf/proc/Distance_cardinal, 0, 30,1,id=access_card)
if(!path.len) //Do not chase a patient we cannot reach.
soft_reset()
if(path.len > 0 && patient)
if(!bot_move(path[path.len]))
oldpatient = patient
soft_reset()
return
if(path.len > 8 && patient)
frustration++
if(auto_patrol && !stationary_mode && !patient)
if(mode == BOT_IDLE || mode == BOT_START_PATROL)
start_patrol()
if(mode == BOT_PATROL)
bot_patrol()
return
/mob/living/simple_animal/bot/medbot/proc/assess_patient(mob/living/carbon/C)
//Time to see if they need medical help!
if(C.stat == 2)
return 0 //welp too late for them!
if(C.suiciding)
return 0 //Kevorkian school of robotic medical assistants.
// is secretly a silicon
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(H.species && H.species.reagent_tag == PROCESS_SYN)
return 0
if(emagged == 2) //Everyone needs our medicine. (Our medicine is toxins)
return 1
if((skin == "bezerk") && (!("syndicate" in C.faction)))
return 0
if(declare_crit && C.health <= 0) //Critical condition! Call for help!
declare(C)
//If they're injured, we're using a beaker, and don't have one of our WONDERCHEMS.
if((reagent_glass) && (use_beaker) && ((C.getBruteLoss() >= heal_threshold) || (C.getToxLoss() >= heal_threshold) || (C.getToxLoss() >= heal_threshold) || (C.getOxyLoss() >= (heal_threshold + 15))))
for(var/datum/reagent/R in reagent_glass.reagents.reagent_list)
if(!C.reagents.has_reagent(R.id))
return 1
//They're injured enough for it!
if((C.getBruteLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_brute)))
return 1 //If they're already medicated don't bother!
if((C.getOxyLoss() >= (15 + heal_threshold)) && (!C.reagents.has_reagent(treatment_oxy)))
return 1
if((C.getFireLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_fire)))
return 1
if((C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_tox)))
return 1
if(treat_virus)
for(var/datum/disease/D in C.viruses)
//the medibot can't detect viruses that are undetectable to Health Analyzers or Pandemic machines.
if(D.visibility_flags & HIDDEN_SCANNER || D.visibility_flags & HIDDEN_PANDEMIC)
return 0
if(D.severity == NONTHREAT) // medibot doesn't try to heal truly harmless viruses
return 0
if((D.stage > 1) || (D.spread_flags & AIRBORNE)) // medibot can't detect a virus in its initial stage unless it spreads airborne.
if(!C.reagents.has_reagent(treatment_virus))
return 1 //STOP DISEASE FOREVER
return 0
/mob/living/simple_animal/bot/medbot/UnarmedAttack(atom/A)
if(iscarbon(A))
var/mob/living/carbon/C = A
patient = C
mode = BOT_HEALING
update_icon()
medicate_patient(C)
update_icon()
else
..()
/mob/living/simple_animal/bot/medbot/examinate(atom/A as mob|obj|turf in view())
..()
if(!is_blind(src))
chemscan(src, A)
/mob/living/simple_animal/bot/medbot/proc/medicate_patient(mob/living/carbon/C)
if(!on)
return
if(!istype(C))
oldpatient = patient
soft_reset()
return
if(C.stat == 2)
var/death_message = pick("No! NO!","Live, damnit! LIVE!","I...I've never lost a patient before. Not today, I mean.")
speak(death_message)
oldpatient = patient
soft_reset()
return
var/reagent_id = null
if(emagged == 2) //Emagged! Time to poison everybody.
reagent_id = "pancuronium"
else
if(treat_virus)
var/virus = 0
for(var/datum/disease/D in C.viruses)
//detectable virus
if((!(D.visibility_flags & HIDDEN_SCANNER)) || (!(D.visibility_flags & HIDDEN_PANDEMIC)))
if(D.severity != NONTHREAT) //virus is harmful
if((D.stage > 1) || (D.spread_flags & AIRBORNE))
virus = 1
if(!reagent_id && (virus))
if(!C.reagents.has_reagent(treatment_virus))
reagent_id = treatment_virus
if(!reagent_id && (C.getBruteLoss() >= heal_threshold))
if(!C.reagents.has_reagent(treatment_brute))
reagent_id = treatment_brute
if(!reagent_id && (C.getOxyLoss() >= (15 + heal_threshold)))
if(!C.reagents.has_reagent(treatment_oxy))
reagent_id = treatment_oxy
if(!reagent_id && (C.getFireLoss() >= heal_threshold))
if(!C.reagents.has_reagent(treatment_fire))
reagent_id = treatment_fire
if(!reagent_id && (C.getToxLoss() >= heal_threshold))
if(!C.reagents.has_reagent(treatment_tox))
reagent_id = treatment_tox
//If the patient is injured but doesn't have our special reagent in them then we should give it to them first
if(reagent_id && use_beaker && reagent_glass && reagent_glass.reagents.total_volume)
for(var/datum/reagent/R in reagent_glass.reagents.reagent_list)
if(!C.reagents.has_reagent(R.id))
reagent_id = "internal_beaker"
break
if(!reagent_id) //If they don't need any of that they're probably cured!
var/message = pick("All patched up!","An apple a day keeps me away.","Feel better soon!")
speak(message)
bot_reset()
return
else
if(!emagged && check_overdose(patient,reagent_id,injection_amount))
soft_reset()
return
C.visible_message("<span class='danger'>[src] is trying to inject [patient]!</span>", \
"<span class='userdanger'>[src] is trying to inject you!</span>")
spawn(30)//replace with do mob
if((get_dist(src, patient) <= 1) && on && assess_patient(patient))
if(reagent_id == "internal_beaker")
if(use_beaker && reagent_glass && reagent_glass.reagents.total_volume)
var/fraction = min(injection_amount/reagent_glass.reagents.total_volume, 1)
reagent_glass.reagents.reaction(patient, 2, fraction)
reagent_glass.reagents.trans_to(patient, injection_amount) //Inject from beaker instead.
else
patient.reagents.add_reagent(reagent_id,injection_amount)
C.visible_message("<span class='danger'>[src] injects [patient] with its syringe!</span>", \
"<span class='userdanger'>[src] injects you with its syringe!</span>")
else
visible_message("[src] retracts its syringe.")
update_icon()
soft_reset()
return
reagent_id = null
return
/mob/living/simple_animal/bot/medbot/proc/check_overdose(mob/living/carbon/patient,reagent_id,injection_amount)
var/datum/reagent/R = chemical_reagents_list[reagent_id]
if(!R.overdose_threshold)
return 0
var/current_volume = patient.reagents.get_reagent_amount(reagent_id)
if(current_volume + injection_amount > R.overdose_threshold)
return 1
return 0
/mob/living/simple_animal/bot/medbot/bullet_act(obj/item/projectile/Proj)
if(Proj.flag == "taser")
stunned = min(stunned+10,20)
..()
/mob/living/simple_animal/bot/medbot/explode()
on = 0
visible_message("<span class='userdanger'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
switch(skin)
if("ointment")
new /obj/item/weapon/storage/firstaid/fire/empty(Tsec)
if("tox")
new /obj/item/weapon/storage/firstaid/toxin/empty(Tsec)
if("o2")
new /obj/item/weapon/storage/firstaid/o2/empty(Tsec)
if("brute")
new /obj/item/weapon/storage/firstaid/brute/empty(Tsec)
if("adv")
new /obj/item/weapon/storage/firstaid/adv/empty(Tsec)
if("bezerk")
new /obj/item/weapon/storage/firstaid/tactical/empty(Tsec)
if("fish")
new /obj/item/weapon/storage/firstaid/aquatic_kit(Tsec)
else
new /obj/item/weapon/storage/firstaid(Tsec)
new /obj/item/device/assembly/prox_sensor(Tsec)
new /obj/item/device/healthanalyzer(Tsec)
if(reagent_glass)
reagent_glass.forceMove(Tsec)
reagent_glass = null
if(prob(50))
new /obj/item/robot_parts/l_arm(Tsec)
var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
..()
/mob/living/simple_animal/bot/medbot/proc/declare(crit_patient)
if(declare_cooldown)
return
if((skin == "bezerk"))
return
var/area/location = get_area(src)
speak("Medical emergency! [crit_patient ? "<b>[crit_patient]</b>" : "A patient"] is in critical condition at [location]!", radio_channel)
declare_cooldown = 1
spawn(200) //Twenty seconds
declare_cooldown = 0
/obj/machinery/bot_core/medbot
req_one_access = list(access_medical, access_robotics)
/obj/machinery/bot_core/medbot/syndicate
req_one_access = list(access_syndicate)
@@ -0,0 +1,871 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
// Mulebot - carries crates around for Quartermaster
// Navigates via floor navbeacons
// Remote Controlled from QM's PDA
#define SIGH 0
#define ANNOYED 1
#define DELIGHT 2
/mob/living/simple_animal/bot/mulebot
name = "\improper MULEbot"
desc = "A Multiple Utility Load Effector bot."
icon_state = "mulebot0"
density = 1
anchored = 1
animate_movement=1
health = 50
maxHealth = 50
damage_coeff = list(BRUTE = 0.5, BURN = 0.7, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
a_intent = "harm" //No swapping
buckle_lying = 0
radio_channel = "Supply"
bot_type = MULE_BOT
bot_filter = RADIO_MULEBOT
model = "MULE"
bot_purpose = "deliver crates and other packages between departments, as requested"
bot_core_type = /obj/machinery/bot_core/mulebot
suffix = ""
var/global/mulebot_count = 0
var/atom/movable/load = null
var/mob/living/passenger = null
var/turf/target // this is turf to navigate to (location of beacon)
var/loaddir = 0 // this the direction to unload onto/load from
var/home_destination = "" // tag of home beacon
var/reached_target = 1 //true if already reached the target
var/auto_return = 1 // true if auto return to home beacon after unload
var/auto_pickup = 1 // true if auto-pickup at beacon
var/report_delivery = 1 // true if bot will announce an arrival to a location.
var/obj/item/weapon/stock_parts/cell/cell
var/datum/wires/mulebot/wires = null
var/bloodiness = 0
var/currentBloodColor = "#A10808"
var/currentDNA = null
/mob/living/simple_animal/bot/mulebot/New()
..()
wires = new /datum/wires/mulebot(src)
var/datum/job/cargo_tech/J = new/datum/job/cargo_tech
access_card.access = J.get_access()
prev_access = access_card.access
cell = new(src)
cell.charge = 2000
cell.maxcharge = 2000
mulebot_count++
set_suffix(suffix ? suffix : "#[mulebot_count]")
/mob/living/simple_animal/bot/mulebot/Destroy()
unload(0)
if(wires)
qdel(wires)
wires = null
if(cell)
qdel(cell)
cell = null
return ..()
/mob/living/simple_animal/bot/mulebot/proc/set_suffix(suffix)
src.suffix = suffix
if(paicard)
bot_name = "\improper MULEbot ([suffix])"
else
name = "\improper MULEbot ([suffix])"
/mob/living/simple_animal/bot/mulebot/bot_reset()
..()
reached_target = 0
/mob/living/simple_animal/bot/mulebot/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/screwdriver))
..()
if(open)
on = FALSE
update_controls()
else if(istype(I,/obj/item/weapon/stock_parts/cell) && open && !cell)
if(!user.drop_item())
return
var/obj/item/weapon/stock_parts/cell/C = I
C.forceMove(src)
cell = C
visible_message("[user] inserts a cell into [src].",
"<span class='notice'>You insert the new cell into [src].</span>")
update_controls()
else if(istype(I, /obj/item/weapon/crowbar) && open && cell)
cell.add_fingerprint(usr)
cell.forceMove(loc)
cell = null
visible_message("[user] crowbars out the power cell from [src].",
"<span class='notice'>You pry the powercell out of [src].</span>")
update_controls()
else if (istype(I, /obj/item/weapon/wrench))
if (health < maxHealth)
adjustBruteLoss(-25)
updatehealth()
user.visible_message(
"<span class='notice'>[user] repairs [src]!</span>",
"<span class='notice'>You repair [src]!</span>"
)
else
user << "<span class='notice'>[src] does not need a repair!</span>"
else if((istype(I, /obj/item/device/multitool) || istype(I, /obj/item/weapon/wirecutters)) && open)
return attack_hand(user)
else if(load && ismob(load)) // chance to knock off rider
if(prob(1 + I.force * 2))
unload(0)
user.visible_message("<span class='danger'>[user] knocks [load] off [src] with \the [I]!</span>",
"<span class='danger'>You knock [load] off [src] with \the [I]!</span>")
else
user << "<span class='warning'>You hit [src] with \the [I] but to no effect!</span>"
..()
else
..()
update_icon()
return
/mob/living/simple_animal/bot/mulebot/emag_act(mob/user)
if(emagged < 1)
emagged = 1
if(!open)
locked = !locked
user << "<span class='notice'>You [locked ? "lock" : "unlock"] the [src]'s controls!</span>"
flick("mulebot-emagged", src)
playsound(loc, 'sound/effects/sparks1.ogg', 100, 0)
/mob/living/simple_animal/bot/mulebot/update_icon()
if(open)
icon_state="mulebot-hatch"
else
icon_state = "mulebot[!wires.MobAvoid()]"
overlays.Cut()
if(load && !ismob(load))//buckling handles the mob offsets
load.pixel_y = initial(load.pixel_y) + 9
if(load.layer < layer)
load.layer = layer + 0.1
overlays += load
return
/mob/living/simple_animal/bot/mulebot/ex_act(severity)
unload(0)
switch(severity)
if(1)
qdel(src)
if(2)
for(var/i = 1; i < 3; i++)
wires.RandomCut()
if(3)
wires.RandomCut()
return
/mob/living/simple_animal/bot/mulebot/bullet_act(obj/item/projectile/Proj)
if(..())
if(prob(50) && !isnull(load))
unload(0)
if(prob(25))
visible_message("<span class='danger'>Something shorts out inside [src]!</span>")
wires.RandomCut()
/mob/living/simple_animal/bot/mulebot/Topic(href, list/href_list)
if(..())
return 1
switch(href_list["op"])
if("lock")
toggle_lock(usr)
if("power")
if(on)
turn_off()
else if(cell && !open)
if(!turn_on())
usr << "<span class='warning'>You can't switch on [src]!</span>"
return
else
return
visible_message("[usr] switches [on ? "on" : "off"] [src].")
if("cellremove")
if(open && cell && !usr.get_active_hand())
cell.updateicon()
usr.put_in_active_hand(cell)
cell.add_fingerprint(usr)
cell = null
usr.visible_message("<span class='notice'>[usr] removes the power cell from [src].</span>", "<span class='notice'>You remove the power cell from [src].</span>")
if("cellinsert")
if(open && !cell)
var/obj/item/weapon/stock_parts/cell/C = usr.get_active_hand()
if(istype(C))
usr.drop_item()
cell = C
C.forceMove(src)
C.add_fingerprint(usr)
usr.visible_message("<span class='notice'>[usr] inserts a power cell into [src].</span>", "<span class='notice'>You insert the power cell into [src].</span>")
if("stop")
if(mode >= BOT_DELIVER)
bot_reset()
if("go")
if(mode == BOT_IDLE)
start()
if("home")
if(mode == BOT_IDLE || mode == BOT_DELIVER)
start_home()
if("destination")
var/new_dest = input(usr, "Enter Destination:", name, destination) as null|anything in deliverybeacontags
if(new_dest)
set_destination(new_dest)
if("setid")
var/new_id = stripped_input(usr, "Enter ID:", name, suffix, MAX_NAME_LEN)
if(new_id)
set_suffix(new_id)
if("sethome")
var/new_home = input(usr, "Enter Home:", name, home_destination) as null|anything in deliverybeacontags
if(new_home)
home_destination = new_home
if("unload")
if(load && mode != BOT_HUNT)
if(loc == target)
unload(loaddir)
else
unload(0)
if("autoret")
auto_return = !auto_return
if("autopick")
auto_pickup = !auto_pickup
if("report")
report_delivery = !report_delivery
update_controls()
/mob/living/simple_animal/bot/mulebot/proc/toggle_lock(var/mob/user)
if(bot_core.allowed(user))
locked = !locked
update_controls()
return 1
else
user << "<span class='danger'>Access denied.</span>"
return 0
// TODO: remove this; PDAs currently depend on it
/mob/living/simple_animal/bot/mulebot/get_controls(mob/user)
var/ai = issilicon(user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += "<h3>Multiple Utility Load Effector Mk. V</h3>"
dat += "<b>ID:</b> [suffix]<BR>"
dat += "<b>Power:</b> [on ? "On" : "Off"]<BR>"
if(!open)
dat += "<h3>Status</h3>"
dat += "<div class='statusDisplay'>"
switch(mode)
if(BOT_IDLE)
dat += "<span class='good'>Ready</span>"
if(BOT_DELIVER)
dat += "<span class='good'>[mode_name[BOT_DELIVER]]</span>"
if(BOT_GO_HOME)
dat += "<span class='good'>[mode_name[BOT_GO_HOME]]</span>"
if(BOT_BLOCKED)
dat += "<span class='average'>[mode_name[BOT_BLOCKED]]</span>"
if(BOT_NAV,BOT_WAIT_FOR_NAV)
dat += "<span class='average'>[mode_name[BOT_NAV]]</span>"
if(BOT_NO_ROUTE)
dat += "<span class='bad'>[mode_name[BOT_NO_ROUTE]]</span>"
dat += "</div>"
dat += "<b>Current Load:</b> [load ? load.name : "<i>none</i>"]<BR>"
dat += "<b>Destination:</b> [!destination ? "<i>none</i>" : destination]<BR>"
dat += "<b>Power level:</b> [cell ? cell.percent() : 0]%"
if(locked && !ai && !check_rights(R_ADMIN, 0, user))
dat += "&nbsp;<br /><div class='notice'>Controls are locked</div><A href='?src=\ref[src];op=unlock'>Unlock Controls</A>"
else
dat += "&nbsp;<br /><div class='notice'>Controls are unlocked</div><A href='?src=\ref[src];op=lock'>Lock Controls</A><BR><BR>"
dat += "<A href='?src=\ref[src];op=power'>Toggle Power</A><BR>"
dat += "<A href='?src=\ref[src];op=stop'>Stop</A><BR>"
dat += "<A href='?src=\ref[src];op=go'>Proceed</A><BR>"
dat += "<A href='?src=\ref[src];op=home'>Return to Home</A><BR>"
dat += "<A href='?src=\ref[src];op=destination'>Set Destination</A><BR>"
dat += "<A href='?src=\ref[src];op=setid'>Set Bot ID</A><BR>"
dat += "<A href='?src=\ref[src];op=sethome'>Set Home</A><BR>"
dat += "<A href='?src=\ref[src];op=autoret'>Toggle Auto Return Home</A> ([auto_return ? "On":"Off"])<BR>"
dat += "<A href='?src=\ref[src];op=autopick'>Toggle Auto Pickup Crate</A> ([auto_pickup ? "On":"Off"])<BR>"
dat += "<A href='?src=\ref[src];op=report'>Toggle Delivery Reporting</A> ([report_delivery ? "On" : "Off"])<BR>"
if(load)
dat += "<A href='?src=\ref[src];op=unload'>Unload Now</A><BR>"
dat += "<div class='notice'>The maintenance hatch is closed.</div>"
else
if(!ai)
dat += "<div class='notice'>The maintenance hatch is open.</div><BR>"
dat += "<b>Power cell:</b> "
if(cell)
dat += "<A href='?src=\ref[src];op=cellremove'>Installed</A><BR>"
else
dat += "<A href='?src=\ref[src];op=cellinsert'>Removed</A><BR>"
dat += wires.GetInteractWindow()
else
dat += "<div class='notice'>The bot is in maintenance mode and cannot be controlled.</div><BR>"
return dat
// returns true if the bot has power
/mob/living/simple_animal/bot/mulebot/proc/has_power()
return !open && cell && cell.charge > 0 && wires.HasPower()
/mob/living/simple_animal/bot/mulebot/proc/buzz(type)
switch(type)
if(SIGH)
audible_message("[src] makes a sighing buzz.", "<span class='emote'>You hear an electronic buzzing sound.</span>")
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
if(ANNOYED)
audible_message("[src] makes an annoyed buzzing sound.", "<span class='emote'>You hear an electronic buzzing sound.</span>")
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
if(DELIGHT)
audible_message("[src] makes a delighted ping!", "<span class='emote'>You hear a ping.</span>")
playsound(loc, 'sound/machines/ping.ogg', 50, 0)
// mousedrop a crate to load the bot
// can load anything if hacked
/mob/living/simple_animal/bot/mulebot/MouseDrop_T(atom/movable/AM, mob/user)
if(user.incapacitated() || user.lying || get_dist(user, src) > 1)
return
if(!istype(AM))
return
load(AM)
// called to load a crate
/mob/living/simple_animal/bot/mulebot/proc/load(atom/movable/AM)
if(!on || load || AM.anchored || get_dist(src, AM) > 1)
return
//I'm sure someone will come along and ask why this is here... well people were dragging screen items onto the mule, and that was not cool.
//So this is a simple fix that only allows a selection of item types to be considered. Further narrowing-down is below.
if(!istype(AM, /obj/item) && !istype(AM, /obj/machinery) && !istype(AM, /obj/structure) && !ismob(AM))
return
if(!isturf(AM.loc)) //To prevent the loading from stuff from someone's inventory or screen icons.
return
var/obj/structure/closet/crate/CRATE
if(istype(AM,/obj/structure/closet/crate))
CRATE = AM
else
if(wires.LoadCheck())
buzz(SIGH)
return // if not hacked, only allow crates to be loaded
if(CRATE) // if it's a crate, close before loading
CRATE.close()
if(isobj(AM))
var/obj/O = AM
if(O.buckled_mob || (locate(/mob) in AM)) //can't load non crates objects with mobs buckled to it or inside it.
buzz(SIGH)
return
if(isliving(AM))
if(!load_mob(AM))
return
else
AM.forceMove(src)
load = AM
mode = BOT_IDLE
update_icon()
/mob/living/simple_animal/bot/mulebot/proc/load_mob(mob/living/M)
can_buckle = TRUE
if(buckle_mob(M))
passenger = M
load = M
can_buckle = FALSE
if(M.client)
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
return TRUE
return FALSE
/mob/living/simple_animal/bot/mulebot/post_buckle_mob(mob/living/M)
if(M == buckled_mob) //post buckling
M.pixel_y = initial(M.pixel_y) + 9
if(M.layer < layer)
M.layer = layer + 0.1
else //post unbuckling
load = null
M.layer = initial(M.layer)
M.pixel_y = initial(M.pixel_y)
// called to unload the bot
// argument is optional direction to unload
// if zero, unload at bot's location
/mob/living/simple_animal/bot/mulebot/proc/unload(dirn)
if(!load)
return
mode = BOT_IDLE
overlays.Cut()
if(ismob(load))
var/mob/M = load
if(M.client)
M.client.perspective = MOB_PERSPECTIVE
M.client.eye = M
unbuckle_mob()
if(load)
load.forceMove(loc)
load.pixel_y = initial(load.pixel_y)
load.layer = initial(load.layer)
if(dirn)
var/turf/T = loc
var/turf/newT = get_step(T,dirn)
if(load.CanPass(load,newT)) //Can't get off onto anything that wouldn't let you pass normally
step(load, dirn)
load = null
// in case non-load items end up in contents, dump every else too
// this seems to happen sometimes due to race conditions
// with items dropping as mobs are loaded
for(var/atom/movable/AM in src)
if(AM == cell || AM == access_card || AM == Radio || AM == bot_core || AM == paicard)
continue
AM.forceMove(loc)
AM.layer = initial(AM.layer)
AM.pixel_y = initial(AM.pixel_y)
if(ismob(AM))
var/mob/M = AM
if(M.client)
M.client.perspective = MOB_PERSPECTIVE
M.client.eye = M
/mob/living/simple_animal/bot/mulebot/call_bot()
..()
var/area/dest_area
if(path && path.len)
target = ai_waypoint //Target is the end point of the path, the waypoint set by the AI.
dest_area = get_area(target)
destination = format_text(dest_area.name)
pathset = 1 //Indicates the AI's custom path is initialized.
start()
/mob/living/simple_animal/bot/mulebot/handle_automated_action()
diag_hud_set_botmode()
if(!has_power())
on = 0
return
if(on)
var/speed = (wires.Motor1() ? 1 : 0) + (wires.Motor2() ? 2 : 0)
//world << "speed: [speed]"
var/num_steps = 0
switch(speed)
if(0)
// do nothing
if(1)
num_steps = 10
if(2)
num_steps = 5
if(3)
num_steps = 3
if(num_steps)
process_bot()
num_steps--
if(mode != BOT_IDLE)
spawn(0)
for(var/i=num_steps,i>0,i--)
sleep(2)
process_bot()
/mob/living/simple_animal/bot/mulebot/proc/process_bot()
if(!on)
return
update_icon()
switch(mode)
if(BOT_IDLE) // idle
return
if(BOT_DELIVER, BOT_GO_HOME, BOT_BLOCKED) // navigating to deliver,home, or blocked
if(loc == target) // reached target
at_target()
return
else if(path.len > 0 && target) // valid path
var/turf/next = path[1]
reached_target = 0
if(next == loc)
path -= next
return
if(istype(next, /turf/simulated))
//world << "at ([x],[y]) moving to ([next.x],[next.y])"
var/oldloc = loc
var/moved = step_towards(src, next) // attempt to move
if(cell) cell.use(1)
if(moved && oldloc!=loc) // successful move
//world << "Successful move."
blockcount = 0
path -= loc
if(destination == home_destination)
mode = BOT_GO_HOME
else
mode = BOT_DELIVER
else // failed to move
//world << "Unable to move."
blockcount++
mode = BOT_BLOCKED
if(blockcount == 3)
buzz(ANNOYED)
if(blockcount > 10) // attempt 10 times before recomputing
// find new path excluding blocked turf
buzz(SIGH)
mode = BOT_WAIT_FOR_NAV
blockcount = 0
spawn(20)
calc_path(avoid=next)
if(path.len > 0)
buzz(DELIGHT)
mode = BOT_BLOCKED
return
return
else
buzz(ANNOYED)
//world << "Bad turf."
mode = BOT_NAV
return
else
//world << "No path."
mode = BOT_NAV
return
if(BOT_NAV) // calculate new path
//world << "Calc new path."
mode = BOT_WAIT_FOR_NAV
spawn(0)
calc_path()
if(path.len > 0)
blockcount = 0
mode = BOT_BLOCKED
buzz(DELIGHT)
else
buzz(SIGH)
mode = BOT_NO_ROUTE
/mob/living/simple_animal/bot/mulebot/Move(turf/simulated/next)
var/turf/simulated/last = loc
if(istype(last) && bloodiness)
last.AddTracks(/obj/effect/decal/cleanable/blood/tracks/wheels, currentDNA, 0, get_dir(last, next), currentBloodColor)
. = ..()
if(. && istype(next))
if(bloodiness)
next.AddTracks(/obj/effect/decal/cleanable/blood/tracks/wheels, currentDNA, get_dir(last, next), 0, currentBloodColor)
bloodiness--
for(var/mob/living/carbon/human/H in next)
RunOver(H)
// calculates a path to the current destination
// given an optional turf to avoid
/mob/living/simple_animal/bot/mulebot/calc_path(turf/avoid = null)
check_bot_access()
path = get_path_to(src, target, /turf/proc/Distance_cardinal, 0, 250, id=access_card, exclude=avoid)
// sets the current destination
// signals all beacons matching the delivery code
// beacons will return a signal giving their locations
/mob/living/simple_animal/bot/mulebot/proc/set_destination(new_dest)
new_destination = new_dest
get_nav()
// starts bot moving to current destination
/mob/living/simple_animal/bot/mulebot/proc/start()
if(!on)
return
if(destination == home_destination)
mode = BOT_GO_HOME
else
mode = BOT_DELIVER
update_icon()
get_nav()
// starts bot moving to home
// sends a beacon query to find
/mob/living/simple_animal/bot/mulebot/proc/start_home()
if(!on)
return
spawn(0)
set_destination(home_destination)
mode = BOT_BLOCKED
update_icon()
// called when bot reaches current target
/mob/living/simple_animal/bot/mulebot/proc/at_target()
if(!reached_target)
radio_channel = "Supply" //Supply channel
audible_message("[src] makes a chiming sound!", "<span class='emote'>You hear a chime.</span>")
playsound(loc, 'sound/machines/chime.ogg', 50, 0)
reached_target = 1
if(pathset) //The AI called us here, so notify it of our arrival.
loaddir = dir //The MULE will attempt to load a crate in whatever direction the MULE is "facing".
if(calling_ai)
calling_ai << "<span class='notice'>\icon[src] [src] wirelessly plays a chiming sound!</span>"
playsound(calling_ai, 'sound/machines/chime.ogg',40, 0)
calling_ai = null
radio_channel = "AI Private" //Report on AI Private instead if the AI is controlling us.
if(load) // if loaded, unload at target
if(report_delivery)
speak("Destination <b>[destination]</b> reached. Unloading [load].", radio_channel)
if(istype(load, /obj/structure/closet/crate))
var/obj/structure/closet/crate/C = load
C.notifyRecipient(destination)
unload(loaddir)
else
// not loaded
if(auto_pickup) // find a crate
var/atom/movable/AM
if(wires.LoadCheck()) // if hacked, load first unanchored thing we find
for(var/atom/movable/A in get_step(loc, loaddir))
if(!A.anchored)
AM = A
break
else // otherwise, look for crates only
AM = locate(/obj/structure/closet/crate) in get_step(loc,loaddir)
if(AM && AM.Adjacent(src))
load(AM)
if(report_delivery)
speak("Now loading [load] at <b>[get_area(src)]</b>.", radio_channel)
// whatever happened, check to see if we return home
if(auto_return && home_destination && destination != home_destination)
// auto return set and not at home already
start_home()
mode = BOT_BLOCKED
else
bot_reset() // otherwise go idle
return
// called when bot bumps into anything
/mob/living/simple_animal/bot/mulebot/Bump(atom/obs)
if(!wires.MobAvoid()) // usually just bumps, but if avoidance disabled knock over mobs
var/mob/M = obs
if(ismob(M))
if(istype(M,/mob/living/silicon/robot))
visible_message("<span class='danger'>[src] bumps into [M]!</span>")
else
add_logs(src, M, "knocked down")
visible_message("<span class='danger'>[src] knocks over [M]!</span>")
M.stop_pulling()
M.Stun(8)
M.Weaken(5)
return ..()
/mob/living/simple_animal/bot/mulebot/proc/RunOver(mob/living/carbon/human/H)
add_logs(src, H, "run over", null, "(DAMTYPE: [uppertext(BRUTE)])")
H.visible_message("<span class='danger'>[src] drives over [H]!</span>", \
"<span class='userdanger'>[src] drives over you!<span>")
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
var/damage = rand(5,15)
H.apply_damage(2*damage, BRUTE, "head", run_armor_check("head", "melee"))
H.apply_damage(2*damage, BRUTE, "chest", run_armor_check("chest", "melee"))
H.apply_damage(0.5*damage, BRUTE, "l_leg", run_armor_check("l_leg", "melee"))
H.apply_damage(0.5*damage, BRUTE, "r_leg", run_armor_check("r_leg", "melee"))
H.apply_damage(0.5*damage, BRUTE, "l_arm", run_armor_check("l_arm", "melee"))
H.apply_damage(0.5*damage, BRUTE, "r_arm", run_armor_check("r_arm", "melee"))
var/obj/effect/decal/cleanable/blood/B = new(loc)
B.blood_DNA = list()
B.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type
currentDNA = B.blood_DNA
bloodiness += 4
currentBloodColor = "#A10808"
if(istype(H))
var/datum/reagent/blood/bld = H.get_blood(H.vessel)
if(bld.data["blood_colour"])
currentBloodColor = bld.data["blood_colour"]
return
B.basecolor = currentBloodColor
B.update_icon()
/mob/living/simple_animal/bot/mulebot/bot_control_message(command, mob/user, user_turf)
switch(command)
if("start")
if(load)
src << "<span class='warning big'>DELIVER [load] TO [destination]</span>"
else
src << "<span class='warning big'>PICK UP DELIVERY AT [destination]</span>"
if("unload")
if(load)
src << "<span class='warning big'>UNLOAD</span>"
else
src << "<span class='warning big'>LOAD</span>"
if("autoret", "autopick", "target")
else
..()
/mob/living/simple_animal/bot/mulebot/receive_signal(datum/signal/signal)
if(!wires.RemoteRX() || ..())
return 1
var/recv = signal.data["command"]
// process control input
switch(recv)
if("start")
start()
if("target")
set_destination(signal.data["destination"])
if("unload")
if(client)
return 1
if(loc == target)
unload(loaddir)
else
unload(0)
if("home")
start_home()
if("autoret")
auto_return = text2num(signal.data["value"])
if("autopick")
auto_pickup = text2num(signal.data["value"])
else
return 0
return 1
// send a radio signal with multiple data key/values
/mob/living/simple_animal/bot/mulebot/post_signal_multiple(var/freq, var/list/keyval)
if(!wires.RemoteTX())
return
..()
// signals bot status etc. to controller
/mob/living/simple_animal/bot/mulebot/send_status()
var/list/kv = list(
"type" = MULE_BOT,
"name" = suffix,
"loca" = get_area(src),
"mode" = mode,
"powr" = (cell ? cell.percent() : 0),
"dest" = destination,
"home" = home_destination,
"load" = load,
"retn" = auto_return,
"pick" = auto_pickup,
)
post_signal_multiple(control_freq, kv)
// player on mulebot attempted to move
/mob/living/simple_animal/bot/mulebot/relaymove(mob/user)
if(user.incapacitated())
return
if(load == user)
unload(0)
//Update navigation data. Called when commanded to deliver, return home, or a route update is needed...
/mob/living/simple_animal/bot/mulebot/proc/get_nav()
if(!on || !wires.BeaconRX())
return
for(var/obj/machinery/navbeacon/NB in deliverybeacons)
if(NB.location == new_destination) // if the beacon location matches the set destination
destination = new_destination // the we will navigate there
target = NB.loc
var/direction = NB.dir // this will be the load/unload dir
loaddir = direction
update_icon()
calc_path()
return
/mob/living/simple_animal/bot/mulebot/emp_act(severity)
if(cell)
cell.emp_act(severity)
if(load)
load.emp_act(severity)
..()
/mob/living/simple_animal/bot/mulebot/explode()
visible_message("<span class='userdanger'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
new /obj/item/device/assembly/prox_sensor(Tsec)
new /obj/item/stack/rods(Tsec)
new /obj/item/stack/rods(Tsec)
new /obj/item/stack/cable_coil/cut(Tsec)
if(cell)
cell.forceMove(Tsec)
cell.update_icon()
cell = null
var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
new /obj/effect/decal/cleanable/blood/oil(loc)
..()
/mob/living/simple_animal/bot/mulebot/remove_air(amount) //To prevent riders suffocating
if(loc)
return loc.remove_air(amount)
else
return null
/mob/living/simple_animal/bot/mulebot/resist()
..()
if(load)
unload()
/mob/living/simple_animal/bot/mulebot/UnarmedAttack(atom/A)
if(isturf(A) && isturf(loc) && loc.Adjacent(A) && load)
unload(get_dir(loc, A))
else
..()
#undef SIGH
#undef ANNOYED
#undef DELIGHT
/obj/machinery/bot_core/mulebot
req_access = list(access_cargo)
@@ -0,0 +1,465 @@
/mob/living/simple_animal/bot/secbot
name = "\improper Securitron"
desc = "A little security robot. He looks less than thrilled."
icon = 'icons/obj/aibots.dmi'
icon_state = "secbot0"
density = 0
anchored = 0
health = 25
maxHealth = 25
damage_coeff = list(BRUTE = 0.5, BURN = 0.7, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
pass_flags = PASSMOB
radio_channel = "Security" //Security channel
bot_type = SEC_BOT
bot_filter = RADIO_SECBOT
model = "Securitron"
bot_purpose = "seek out criminals, handcuff them, and report their location to security"
bot_core_type = /obj/machinery/bot_core/secbot
window_id = "autosec"
window_name = "Automatic Security Unit v1.6"
var/base_icon = "secbot"
var/mob/living/carbon/target
var/oldtarget_name
var/threatlevel = 0
var/target_lastloc //Loc of target when arrested.
var/last_found //There's a delay
var/declare_arrests = 1 //When making an arrest, should it notify everyone on the security channel?
var/idcheck = 0 //If true, arrest people with no IDs
var/weaponscheck = 0 //If true, arrest people for weapons if they lack access
var/check_records = 1 //Does it check security records?
var/arrest_type = 0 //If true, don't handcuff
var/harmbaton = 0 //If true, beat instead of stun
var/flashing_lights = 0 //If true, flash lights
var/prev_flashing_lights = 0
/mob/living/simple_animal/bot/secbot/beepsky
name = "Officer Beepsky"
desc = "It's Officer Beepsky! Powered by a potato and a shot of whiskey."
idcheck = 0
weaponscheck = 0
auto_patrol = 1
allow_pai = 0
/mob/living/simple_animal/bot/secbot/beepsky/explode()
var/turf/Tsec = get_turf(src)
new /obj/item/weapon/stock_parts/cell/potato(Tsec)
var/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/S = new(Tsec)
S.reagents.add_reagent("whiskey", 15)
S.on_reagent_change()
..()
/mob/living/simple_animal/bot/secbot/pingsky
name = "Officer Pingsky"
desc = "It's Officer Pingsky! Delegated to satellite guard duty for harbouring anti-human sentiment."
radio_channel = "AI Private"
allow_pai = 0
/mob/living/simple_animal/bot/secbot/ofitser
name = "Prison Ofitser"
desc = "It's Prison Ofitser! Powered by the tears and sweat of prisoners."
idcheck = 0
weaponscheck = 1
auto_patrol = 1
allow_pai = 0
/mob/living/simple_animal/bot/secbot/buzzsky
name = "Officer Buzzsky"
desc = "It's Officer Buzzsky! Rusted and falling apart, he seems less than thrilled with the crew for leaving him in his current state."
base_icon = "rustbot"
icon_state = "rustbot0"
declare_arrests = 0
arrest_type = 1
harmbaton = 1
emagged = 2
/mob/living/simple_animal/bot/secbot/New()
..()
icon_state = "[base_icon][on]"
spawn(3)
var/datum/job/detective/J = new/datum/job/detective
access_card.access += J.get_access()
prev_access = access_card.access
//SECHUD
var/datum/atom_hud/secsensor = huds[DATA_HUD_SECURITY_ADVANCED]
secsensor.add_hud_to(src)
permanent_huds |= secsensor
/mob/living/simple_animal/bot/secbot/turn_on()
..()
icon_state = "[base_icon][on]"
/mob/living/simple_animal/bot/secbot/turn_off()
..()
icon_state = "[base_icon][on]"
/mob/living/simple_animal/bot/secbot/bot_reset()
..()
target = null
oldtarget_name = null
anchored = 0
walk_to(src,0)
last_found = world.time
/mob/living/simple_animal/bot/secbot/set_custom_texts()
text_hack = "You overload [name]'s target identification system."
text_dehack = "You reboot [name] and restore the target identification."
text_dehack_fail = "[name] refuses to accept your authority!"
/mob/living/simple_animal/bot/secbot/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += text({"
<TT><B>Securitron v1.6 controls</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [open ? "opened" : "closed"]"},
"<A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A>" )
if(!locked || issilicon(user) || check_rights(R_ADMIN, 0, user))
dat += text({"<BR>
Arrest Unidentifiable Persons: []<BR>
Arrest for Unauthorized Weapons: []<BR>
Arrest for Warrant: []<BR>
Operating Mode: []<BR>
Report Arrests[]<BR>
Auto Patrol: []"},
"<A href='?src=\ref[src];operation=idcheck'>[idcheck ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=weaponscheck'>[weaponscheck ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=ignorerec'>[check_records ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=switchmode'>[arrest_type ? "Detain" : "Arrest"]</A>",
"<A href='?src=\ref[src];operation=declarearrests'>[declare_arrests ? "Yes" : "No"]</A>",
"<A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
return dat
/mob/living/simple_animal/bot/secbot/Topic(href, href_list)
if(..())
return 1
switch(href_list["operation"])
if("idcheck")
idcheck = !idcheck
update_controls()
if("weaponscheck")
weaponscheck = !weaponscheck
update_controls()
if("ignorerec")
check_records = !check_records
update_controls()
if("switchmode")
arrest_type = !arrest_type
update_controls()
if("declarearrests")
declare_arrests = !declare_arrests
update_controls()
/mob/living/simple_animal/bot/secbot/proc/retaliate(mob/living/carbon/human/H)
threatlevel = H.assess_threat(src)
threatlevel += 6
if(threatlevel >= 4)
target = H
mode = BOT_HUNT
/mob/living/simple_animal/bot/secbot/attack_hand(mob/living/carbon/human/H)
if(H.a_intent == "harm")
retaliate(H)
return ..()
/mob/living/simple_animal/bot/secbot/attackby(obj/item/weapon/W, mob/user, params)
..()
if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != "harm") // Any intent but harm will heal, so we shouldn't get angry.
return
if(!istype(W, /obj/item/weapon/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass.
retaliate(user)
/mob/living/simple_animal/bot/secbot/emag_act(mob/user)
..()
if(emagged == 2)
if(user)
user << "<span class='danger'>You short out [src]'s target assessment circuits.</span>"
oldtarget_name = user.name
audible_message("<span class='danger'>[src] buzzes oddly!</span>")
declare_arrests = 0
icon_state = "[base_icon][on]"
/mob/living/simple_animal/bot/secbot/bullet_act(obj/item/projectile/Proj)
if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet))
if((Proj.damage_type == BURN) || (Proj.damage_type == BRUTE))
if(!Proj.nodamage && Proj.damage < src.health)
retaliate(Proj.firer)
..()
/mob/living/simple_animal/bot/secbot/UnarmedAttack(atom/A)
if(!on)
return
if(iscarbon(A))
var/mob/living/carbon/C = A
if(!C.stunned || arrest_type)
stun_attack(A)
else if(C.canBeHandcuffed() && !C.handcuffed)
cuff(A)
else
..()
/mob/living/simple_animal/bot/secbot/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
if(istype(AM, /obj/item))
var/obj/item/I = AM
if(I.throwforce < src.health && I.thrower && (istype(I.thrower, /mob/living/carbon/human)))
var/mob/living/carbon/human/H = I.thrower
retaliate(H)
..()
/mob/living/simple_animal/bot/secbot/proc/cuff(mob/living/carbon/C)
mode = BOT_ARREST
playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
C.visible_message("<span class='danger'>[src] is trying to put zipties on [C]!</span>",\
"<span class='userdanger'>[src] is trying to put zipties on you!</span>")
spawn(60)
if( !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing.
return
if(!C.handcuffed)
C.handcuffed = new /obj/item/weapon/restraints/handcuffs/cable/zipties/used(C)
C.update_inv_handcuffed(1)
playsound(loc, pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0)
back_to_idle()
/mob/living/simple_animal/bot/secbot/proc/stun_attack(mob/living/carbon/C)
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
if(harmbaton)
playsound(loc, 'sound/weapons/genhit1.ogg', 50, 1, -1)
icon_state = "[base_icon]-c"
spawn(2)
icon_state = "[base_icon][on]"
var/threat = 5
if(istype(C, /mob/living/carbon/human))
C.stuttering = 5
if(harmbaton) // Bots with harmbaton enabled become shitcurity. - Dave
C.apply_damage(10, BRUTE)
C.Stun(5)
C.Weaken(5)
var/mob/living/carbon/human/H = C
threat = H.assess_threat(src)
else
C.Weaken(5)
C.stuttering = 5
C.Stun(5)
add_logs(src,C,"stunned")
if(declare_arrests)
var/area/location = get_area(src)
speak("[arrest_type ? "Detaining" : "Arresting"] level [threat] scumbag <b>[C]</b> in [location].", radio_channel)
C.visible_message("<span class='danger'>[src] has [harmbaton ? "beaten" : "stunned"] [C]!</span>",\
"<span class='userdanger'>[src] has [harmbaton ? "beaten" : "stunned"] you!</span>")
/mob/living/simple_animal/bot/secbot/Life()
. = ..()
if(flashing_lights)
switch(light_color)
if(LIGHT_COLOR_PURE_RED)
light_color = LIGHT_COLOR_PURE_BLUE
if(LIGHT_COLOR_PURE_BLUE)
light_color = LIGHT_COLOR_PURE_RED
update_light()
else if(prev_flashing_lights)
light_color = LIGHT_COLOR_PURE_RED
update_light()
prev_flashing_lights = flashing_lights
/mob/living/simple_animal/bot/secbot/verb/toggle_flashing_lights()
set name = "Toggle Flashing Lights"
set category = "Object"
set src = usr
flashing_lights = !flashing_lights
/mob/living/simple_animal/bot/secbot/handle_automated_action()
if(!..())
return
flashing_lights = mode == BOT_HUNT
switch(mode)
if(BOT_IDLE) // idle
walk_to(src,0)
look_for_perp() // see if any criminals are in range
if(!mode && auto_patrol) // still idle, and set to patrol
mode = BOT_START_PATROL // switch to patrol mode
if(BOT_HUNT) // hunting for perp
// if can't reach perp for long enough, go idle
if(frustration >= 8)
walk_to(src,0)
back_to_idle()
return
if(target) // make sure target exists
if(Adjacent(target) && isturf(target.loc)) // if right next to perp
stun_attack(target)
mode = BOT_PREP_ARREST
anchored = 1
target_lastloc = target.loc
return
else // not next to perp
var/turf/olddist = get_dist(src, target)
walk_to(src, target,1,4)
if((get_dist(src, target)) >= (olddist))
frustration++
else
frustration = 0
else
back_to_idle()
if(BOT_PREP_ARREST) // preparing to arrest target
// see if he got away. If he's no no longer adjacent or inside a closet or about to get up, we hunt again.
if( !Adjacent(target) || !isturf(target.loc) || target.weakened < 2 )
back_to_hunt()
return
if(iscarbon(target) && target.canBeHandcuffed())
if(!arrest_type)
if(!target.handcuffed) //he's not cuffed? Try to cuff him!
cuff(target)
else
back_to_idle()
return
else
back_to_idle()
return
if(BOT_ARREST)
if(!target)
anchored = 0
mode = BOT_IDLE
last_found = world.time
frustration = 0
return
if(target.handcuffed) //no target or target cuffed? back to idle.
back_to_idle()
return
if(!Adjacent(target) || !isturf(target.loc) || (target.loc != target_lastloc && target.weakened < 2)) //if he's changed loc and about to get up or not adjacent or got into a closet, we prep arrest again.
back_to_hunt()
return
else //Try arresting again if the target escapes.
mode = BOT_PREP_ARREST
anchored = 0
if(BOT_START_PATROL)
look_for_perp()
start_patrol()
if(BOT_PATROL)
look_for_perp()
bot_patrol()
return
/mob/living/simple_animal/bot/secbot/proc/back_to_idle()
anchored = 0
mode = BOT_IDLE
target = null
last_found = world.time
frustration = 0
spawn(0)
handle_automated_action() //ensure bot quickly responds
/mob/living/simple_animal/bot/secbot/proc/back_to_hunt()
anchored = 0
frustration = 0
mode = BOT_HUNT
spawn(0)
handle_automated_action() //ensure bot quickly responds
// look for a criminal in view of the bot
/mob/living/simple_animal/bot/secbot/proc/look_for_perp()
anchored = 0
for (var/mob/living/carbon/C in view(7,src)) //Let's find us a criminal
if((C.stat) || (C.handcuffed))
continue
if((C.name == oldtarget_name) && (world.time < last_found + 100))
continue
threatlevel = C.assess_threat(src)
if(!threatlevel)
continue
else if(threatlevel >= 4)
target = C
oldtarget_name = C.name
speak("Level [threatlevel] infraction alert!")
playsound(loc, pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0)
visible_message("<b>[src]</b> points at [C.name]!")
mode = BOT_HUNT
spawn(0)
handle_automated_action() // ensure bot quickly responds to a perp
break
else
continue
/mob/living/simple_animal/bot/secbot/proc/check_for_weapons(var/obj/item/slot_item)
if(slot_item && slot_item.needs_permit)
return 1
return 0
/mob/living/simple_animal/bot/secbot/explode()
walk_to(src,0)
visible_message("<span class='userdanger'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
var/obj/item/weapon/secbot_assembly/Sa = new /obj/item/weapon/secbot_assembly(Tsec)
Sa.build_step = 1
Sa.overlays += "hs_hole"
Sa.created_name = name
new /obj/item/device/assembly/prox_sensor(Tsec)
new /obj/item/weapon/melee/baton(Tsec)
if(prob(50))
new /obj/item/robot_parts/l_arm(Tsec)
var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
new /obj/effect/decal/cleanable/blood/oil(loc)
..()
/mob/living/simple_animal/bot/secbot/attack_alien(var/mob/living/carbon/alien/user as mob)
..()
if(!isalien(target))
target = user
mode = BOT_HUNT
/mob/living/simple_animal/bot/secbot/Crossed(atom/movable/AM)
if(ismob(AM) && target)
var/mob/living/carbon/C = AM
if(!istype(C) || !C || in_range(src, target))
return
C.visible_message("<span class='warning'>[pick( \
"[C] dives out of [src]'s way!", \
"[C] stumbles over [src]!", \
"[C] jumps out of [src]'s path!", \
"[C] trips over [src] and falls!", \
"[C] topples over [src]!", \
"[C] leaps out of [src]'s way!")]</span>")
C.Weaken(2)
return
..()
/obj/machinery/bot_core/secbot
req_access = list(access_security)
@@ -14,14 +14,7 @@
stop_automated_movement = 1
status_flags = CANPUSH
attack_sound = 'sound/weapons/punch1.ogg'
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
faction = list("cult")
flying = 1
@@ -110,7 +103,7 @@
/mob/living/simple_animal/construct/armoured/Life()
weakened = 0
..()
return ..()
/mob/living/simple_animal/construct/armoured/bullet_act(var/obj/item/projectile/P)
if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
@@ -17,8 +17,7 @@
density = 0
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
ventcrawler = 2
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 0
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 0)
/mob/living/simple_animal/butterfly/New()
..()
@@ -5,7 +5,7 @@
icon_state = "cat2"
icon_living = "cat2"
icon_dead = "cat2_dead"
icon_resting = "cat_rest"
icon_resting = "cat2_rest"
gender = MALE
speak = list("Meow!", "Esp!", "Purr!", "HSSSSS")
speak_emote = list("purrs", "meows")
@@ -16,8 +16,7 @@
see_in_dark = 6
simplespecies = /mob/living/simple_animal/pet/cat
childtype = /mob/living/simple_animal/pet/cat/kitten
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 3
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 3)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
@@ -28,7 +27,8 @@
desc = "GCAT"
icon_state = "cat"
icon_living = "cat"
icon_dead = "cat2_dead"
icon_dead = "cat_dead"
icon_resting = "cat_rest"
gender = FEMALE
var/turns_since_scan = 0
var/mob/living/simple_animal/mouse/movement_target
@@ -15,8 +15,7 @@
emote_see = list("shakes its head", "shivers")
speak_chance = 1
turns_per_move = 10
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/corgi
meat_amount = 3
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/corgi = 3)
response_help = "pets"
response_disarm = "bops"
response_harm = "kicks"
@@ -32,31 +31,6 @@
..()
regenerate_icons()
/mob/living/simple_animal/pet/corgi/handle_hud_icons()
..()
if(fire)
if(fire_alert) fire.icon_state = "fire[fire_alert]" //fire_alert is either 0 if no alert, 1 for heat and 2 for cold.
else fire.icon_state = "fire0"
if(oxygen)
if(oxygen_alert) oxygen.icon_state = "oxy1"
else oxygen.icon_state = "oxy0"
if(toxin)
if(toxins_alert) toxin.icon_state = "tox1"
else toxin.icon_state = "tox0"
/mob/living/simple_animal/pet/corgi/handle_hud_icons_health()
..()
if(healths)
switch(health)
if(30 to INFINITY) healths.icon_state = "health0"
if(26 to 29) healths.icon_state = "health1"
if(21 to 25) healths.icon_state = "health2"
if(16 to 20) healths.icon_state = "health3"
if(11 to 15) healths.icon_state = "health4"
if(6 to 10) healths.icon_state = "health5"
if(1 to 5) healths.icon_state = "health6"
if(0) healths.icon_state = "health7"
/mob/living/simple_animal/pet/corgi/Life()
. = ..()
regenerate_icons()
@@ -73,19 +47,21 @@
user.set_machine(src)
if(user.stat) return
var/dat = "<div align='center'><b>Inventory of [name]</b></div><p>"
if(inventory_head)
dat += "<br><b>Head:</b> [inventory_head] (<a href='?src=\ref[src];remove_inv=head'>Remove</a>)"
else
dat += "<br><b>Head:</b> <a href='?src=\ref[src];add_inv=head'>Nothing</a>"
if(inventory_back)
dat += "<br><b>Back:</b> [inventory_back] (<a href='?src=\ref[src];remove_inv=back'>Remove</a>)"
else
dat += "<br><b>Back:</b> <a href='?src=\ref[src];add_inv=back'>Nothing</a>"
var/dat = {"<table>"}
user << browse(dat, text("window=mob[];size=325x500", real_name))
onclose(user, "mob[real_name]")
return
dat += "<tr><td><B>Head:</B></td><td><A href='?src=\ref[src];[inventory_head?"remove_inv":"add_inv"]=head'>[(inventory_head && !(inventory_head.flags&ABSTRACT)) ? inventory_head : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Back:</B></td><td><A href='?src=\ref[src];[inventory_back?"remove_inv":"add_inv"]=back'>[(inventory_back && !(inventory_back.flags&ABSTRACT)) ? inventory_back : "<font color=grey>Empty</font>"]</A></td></tr>"
if(can_collar)
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Collar:</B></td><td><A href='?src=\ref[src];[collar?"remove_inv":"add_inv"]=collar'>[(collar && !(collar.flags&ABSTRACT)) ? collar : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += {"</table>
<A href='?src=\ref[user];mach_close=mob\ref[src]'>Close</A>
"}
var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 440, 500)
popup.set_content(dat)
popup.open()
/mob/living/simple_animal/pet/corgi/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
if(inventory_head && inventory_back)
@@ -422,11 +398,11 @@
response_disarm = "bops"
response_harm = "kicks"
/mob/living/simple_animal/pet/corgi/Ian/Life()
/mob/living/simple_animal/pet/corgi/Ian/process_ai()
..()
//Feeding, chasing food, FOOOOODDDD
if(!stat && !resting && !buckled && (ckey == null))
if(!resting && !buckled)
turns_since_scan++
if(turns_since_scan > 5)
turns_since_scan = 0
@@ -473,10 +449,9 @@
if(prob(1))
custom_emote(1, pick("dances around.","chases its tail!"))
spawn(0)
if (ckey == null)
for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
dir = i
sleep(1)
for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
dir = i
sleep(1)
/obj/item/weapon/reagent_containers/food/snacks/meat/corgi
name = "Corgi meat"
@@ -542,11 +517,7 @@
overlays += image('icons/mob/mask.dmi',"facehugger_corgipuppy")
else
overlays += image('icons/mob/mask.dmi',"facehugger_corgi")
if(pcollar)
overlays += collar
overlays += pettag
return
..(0)
/mob/living/simple_animal/pet/corgi/puppy
name = "\improper corgi puppy"
@@ -590,20 +561,18 @@
return
..()
/mob/living/simple_animal/pet/corgi/Lisa/Life()
/mob/living/simple_animal/pet/corgi/Lisa/process_ai()
..()
make_babies()
if(!stat && !resting && !buckled)
if(!resting && !buckled)
if(prob(1))
if (ckey == null)
custom_emote(1, pick("dances around.","chases her tail."))
spawn(0)
for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
dir = i
sleep(1)
custom_emote(1, pick("dances around.","chases her tail."))
spawn(0)
for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
dir = i
sleep(1)
/mob/living/simple_animal/pet/corgi/attack_hand(mob/living/carbon/human/M)
. = ..()
@@ -11,8 +11,7 @@
emote_see = list("clacks")
speak_chance = 1
turns_per_move = 5
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 3
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 1)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "stomps the"
@@ -22,6 +21,7 @@
var/obj/item/inventory_head
var/obj/item/inventory_mask
can_hide = 1
can_collar = 1
/mob/living/simple_animal/crab/handle_automated_movement()
//CRAB movement
@@ -10,8 +10,8 @@
speak_chance = 1
turns_per_move = 5
see_in_dark = 0 //I'm so funny
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 3
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 4)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
response_harm = "kicks"
can_collar = 1
@@ -38,6 +38,7 @@
var/list/donors = list()
var/ready_evolve = 0
holder_type = /obj/item/weapon/holder/diona
can_collar = 1
/mob/living/simple_animal/diona/New()
..()
@@ -12,8 +12,7 @@
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 4
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 4)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "kicks the"
@@ -26,6 +25,7 @@
melee_damage_upper = 2
stop_automated_movement_when_pulled = 1
var/milk_content = 0
can_collar = 1
/mob/living/simple_animal/hostile/retaliate/goat/handle_automated_movement()
..()
@@ -102,8 +102,7 @@
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 6
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 6)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "kicks the"
@@ -111,6 +110,7 @@
attack_sound = 'sound/weapons/punch1.ogg'
health = 50
var/milk_content = 0
can_collar = 1
/mob/living/simple_animal/cow/New()
..()
@@ -166,8 +166,7 @@
density = 0
speak_chance = 2
turns_per_move = 2
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 1
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 1)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "kicks the"
@@ -178,6 +177,7 @@
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
small = 1
can_hide = 1
can_collar = 1
/mob/living/simple_animal/chick/New()
..()
@@ -208,8 +208,7 @@ var/global/chicken_count = 0
density = 0
speak_chance = 2
turns_per_move = 3
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 2
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 2)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "kicks the"
@@ -220,6 +219,7 @@ var/global/chicken_count = 0
pass_flags = PASSTABLE | PASSMOB
small = 1
can_hide = 1
can_collar = 1
/mob/living/simple_animal/chicken/New()
..()
@@ -290,13 +290,13 @@ var/global/chicken_count = 0
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/ham
meat_amount = 6
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/ham = 6)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "kicks the"
attacktext = "kicks"
health = 50
can_collar = 1
/mob/living/simple_animal/turkey
name = "turkey"
@@ -311,13 +311,13 @@ var/global/chicken_count = 0
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat //enough to make one turkey
meat_amount = 4
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 4)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "kicks the"
attacktext = "pecks"
health = 50
can_collar = 1
/mob/living/simple_animal/goose
name = "goose"
@@ -332,13 +332,13 @@ var/global/chicken_count = 0
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 6
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 6)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "kicks the"
attacktext = "kicks"
health = 50
can_collar = 1
/mob/living/simple_animal/seal
name = "seal"
@@ -353,13 +353,13 @@ var/global/chicken_count = 0
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 6
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 6)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "kicks the"
attacktext = "kicks"
health = 50
can_collar = 1
/mob/living/simple_animal/walrus
name = "walrus"
@@ -374,10 +374,10 @@ var/global/chicken_count = 0
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 6
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 6)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "kicks the"
attacktext = "kicks"
health = 50
can_collar = 1
@@ -13,8 +13,7 @@
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 3
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 3)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
@@ -20,5 +20,5 @@
density = 0
pass_flags = PASSTABLE | PASSMOB
can_hide = 1
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 1
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 1)
can_collar = 1
@@ -15,8 +15,7 @@
see_in_dark = 6
maxHealth = 5
health = 5
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 1
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 1)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "stamps on the"
@@ -25,12 +24,13 @@
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
var/mouse_color //brown, gray and white, leave blank for random
layer = MOB_LAYER
min_oxy = 16 //Require atleast 16kPA oxygen
atmos_requirements = list("min_oxy" = 16, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 223 //Below -50 Degrees Celcius
maxbodytemp = 323 //Above 50 Degrees Celcius
universal_speak = 0
can_hide = 1
holder_type = /obj/item/weapon/holder/mouse
can_collar = 1
/mob/living/simple_animal/mouse/handle_automated_speech()
..()
@@ -40,14 +40,7 @@
/mob/living/simple_animal/mouse/Life()
. = ..()
if(!ckey && stat == CONSCIOUS && prob(0.5))
stat = UNCONSCIOUS
icon_state = "mouse_[mouse_color]_sleep"
wander = 0
speak_chance = 0
//snuffles
else if(stat == UNCONSCIOUS)
if(stat == UNCONSCIOUS)
if(ckey || prob(1))
stat = CONSCIOUS
icon_state = "mouse_[mouse_color]"
@@ -55,6 +48,15 @@
else if(prob(5))
emote("snuffles")
/mob/living/simple_animal/mouse/process_ai()
..()
if(prob(0.5))
stat = UNCONSCIOUS
icon_state = "mouse_[mouse_color]_sleep"
wander = 0
speak_chance = 0
/mob/living/simple_animal/mouse/New()
..()
if(!mouse_color)
@@ -1,22 +1,8 @@
/mob/living/simple_animal/pet
icon = 'icons/mob/pets.dmi'
var/obj/item/clothing/accessory/petcollar/pcollar = null
var/image/collar = null
var/image/pettag = null
can_collar = 1
/mob/living/simple_animal/pet/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
if(istype(O, /obj/item/clothing/accessory/petcollar) && !pcollar)
var/obj/item/clothing/accessory/petcollar/P = O
pcollar = P
collar = image('icons/mob/pets.dmi', src, "[icon_state]collar")
pettag = image('icons/mob/pets.dmi', src, "[icon_state]tag")
regenerate_icons()
user << "<span class='notice'>You put the [P] around [src]'s neck.</span>"
if(P.tagname)
name = P.tagname
real_name = P.tagname
qdel(P)
return
if(istype(O, /obj/item/weapon/newspaper))
if(!stat)
user.visible_message("[user] baps [name] on the nose with the rolled up [O].")
@@ -27,12 +13,6 @@
else
..()
/mob/living/simple_animal/pet/New()
..()
if(pcollar)
pcollar = new(src)
regenerate_icons()
/mob/living/simple_animal/pet/revive()
..()
regenerate_icons()
@@ -41,7 +21,9 @@
..()
regenerate_icons()
/mob/living/simple_animal/pet/regenerate_icons()
overlays.Cut()
overlays += collar
overlays += pettag
/mob/living/simple_animal/pet/regenerate_icons(cut_overlays = 1)
if(cut_overlays)
overlays.Cut()
if(collar)
overlays += "[icon_state]collar"
overlays += "[icon_state]tag"
@@ -12,17 +12,16 @@
emote_see = list("shakes its head.", "chases its tail.","shivers.")
speak_chance = 1
turns_per_move = 10
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/pug
meat_amount = 3
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/pug = 3)
response_help = "pets"
response_disarm = "bops"
response_harm = "kicks"
see_in_dark = 5
/mob/living/simple_animal/pet/pug/Life()
/mob/living/simple_animal/pet/pug/process_ai()
..()
if(!stat && !resting && !buckled)
if(!resting && !buckled)
if(prob(1))
custom_emote(1, pick("chases its tail."))
spawn(0)
@@ -1,8 +1,6 @@
/mob/living/simple_animal/spiderbot
min_oxy = 0
max_tox = 0
max_co2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 500
@@ -8,8 +8,7 @@
turns_per_move = 5
maxHealth = 15
health = 15
meat_type = /obj/item/weapon/reagent_containers/food/snacks/tomatomeat
meat_amount = 3
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/tomatomeat = 3)
response_help = "prods the"
response_disarm = "pushes aside the"
response_harm = "smacks the"
@@ -10,8 +10,7 @@
response_disarm = "shoves the"
response_harm = "hits the"
speed = 0
meat_type = /obj/item/weapon/reagent_containers/food/snacks/xenomeat
meat_amount = 3
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/xenomeat = 3)
maxHealth = 100
health = 100
harm_intent_damage = 5
@@ -21,14 +20,7 @@
speak_emote = list("hisses")
a_intent = I_HARM
attack_sound = 'sound/weapons/bladeslice.ogg'
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
var/dead = 0
unsuitable_atmos_damage = 15
faction = list("alien")
@@ -50,14 +42,16 @@
var/plant_cooldown = 30
var/plants_off = 0
/mob/living/simple_animal/hostile/alien/drone/Life()
..()
if(!stat)
plant_cooldown--
if(stance==HOSTILE_STANCE_IDLE)
if(!plants_off && prob(10) && plant_cooldown<=0)
plant_cooldown = initial(plant_cooldown)
SpreadPlants()
/mob/living/simple_animal/hostile/alien/drone/process_ai()
. = ..()
if(!.)
return
plant_cooldown--
if(stance==HOSTILE_STANCE_IDLE)
if(!plants_off && prob(10) && plant_cooldown<=0)
plant_cooldown = initial(plant_cooldown)
SpreadPlants()
/mob/living/simple_animal/hostile/alien/sentinel
name = "alien sentinel"
@@ -95,18 +89,18 @@
var/egg_cooldown = 30
var/plant_cooldown = 30
/mob/living/simple_animal/hostile/alien/queen/Life()
/mob/living/simple_animal/hostile/alien/queen/process_ai()
..()
if(!stat)
egg_cooldown--
plant_cooldown--
if(stance==HOSTILE_STANCE_IDLE)
if(!plants_off && prob(10) && plant_cooldown<=0)
plant_cooldown = initial(plant_cooldown)
SpreadPlants()
if(!sterile && prob(10) && egg_cooldown<=0)
egg_cooldown = initial(egg_cooldown)
LayEggs()
egg_cooldown--
plant_cooldown--
if(stance==HOSTILE_STANCE_IDLE)
if(!plants_off && prob(10) && plant_cooldown<=0)
plant_cooldown = initial(plant_cooldown)
SpreadPlants()
if(!sterile && prob(10) && egg_cooldown<=0)
egg_cooldown = initial(egg_cooldown)
LayEggs()
/mob/living/simple_animal/hostile/alien/proc/SpreadPlants()
if(!isturf(loc) || istype(loc, /turf/space))
@@ -145,3 +139,25 @@
dead = 1
visible_message("[src] lets out a waning guttural screech, green blood bubbling from its maw...")
playsound(src, 'sound/voice/hiss6.ogg', 100, 1)
/mob/living/simple_animal/hostile/alien/maid
name = "lusty xenomorph maid"
melee_damage_lower = 0
melee_damage_upper = 0
a_intent = "help"
friendly = "caresses"
environment_smash = 0
icon_state = "maid"
icon_living = "maid"
icon_dead = "maid_dead"
/mob/living/simple_animal/hostile/alien/maid/AttackingTarget()
if(istype(target, /atom/movable))
if(istype(target, /obj/effect/decal/cleanable))
visible_message("<span class='notice'>\The [src] cleans up \the [target].</span>")
qdel(target)
return
var/atom/movable/M = target
M.clean_blood()
visible_message("<span class='notice'>\The [src] polishes \the [target].</span>")
@@ -8,8 +8,7 @@
icon_gib = "bat_dead"
speak_chance = 0
turns_per_move = 3
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 1
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 1)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "hits the"
@@ -23,15 +22,7 @@
attacktext = "bites"
attack_sound = 'sound/weapons/bite.ogg'
//Space carp aren't affected by atmos.
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
// break_stuff_probability = 2
@@ -13,8 +13,7 @@
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
meat_type = /obj/item/weapon/reagent_containers/food/snacks/bearmeat
meat_amount = 5
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/bearmeat = 5, /obj/item/clothing/head/bearpelt = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
@@ -27,14 +26,7 @@
attack_sound = 'sound/weapons/genhit3.ogg'
//Space bears aren't affected by atmos.
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
var/stance_step = 0
@@ -56,12 +48,11 @@
else
icon_state = "bearfloor"
/mob/living/simple_animal/hostile/bear/Life()
/mob/living/simple_animal/hostile/bear/process_ai()
. = ..()
if(!.)
return
switch(stance)
if(HOSTILE_STANCE_TIRED)
@@ -9,8 +9,7 @@
icon_gib = "carp_gib"
speak_chance = 0
turns_per_move = 5
meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat
meat_amount = 2
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/carpmeat = 2)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "hits the"
@@ -26,14 +25,7 @@
speak_emote = list("gnashes")
//Space carp aren't affected by atmos.
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 1500
@@ -20,14 +20,7 @@
attack_sound = 'sound/hallucinations/growl1.ogg'
speak_emote = list("growls")
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
speed = 4
@@ -33,8 +33,7 @@
speak_chance = 5
turns_per_move = 5
see_in_dark = 10
meat_type = /obj/item/weapon/reagent_containers/food/snacks/spidermeat
meat_amount = 2
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/spidermeat = 2, /obj/item/weapon/reagent_containers/food/snacks/spiderleg = 8)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
@@ -57,8 +56,8 @@
icon_state = "nurse"
icon_living = "nurse"
icon_dead = "nurse_dead"
meat_type = /obj/item/weapon/reagent_containers/food/snacks/spidereggs
meat_amount = 4
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/spidermeat = 2, /obj/item/weapon/reagent_containers/food/snacks/spiderleg = 8, /obj/item/weapon/reagent_containers/food/snacks/spidereggs = 4)
maxHealth = 40
health = 40
melee_damage_lower = 5
@@ -95,19 +94,6 @@
stop_automated_movement = 0
walk(src,0)
// Chops off each leg with a 50/50 chance of harvesting one, until finally calling
// default harvest action
/mob/living/simple_animal/hostile/poison/giant_spider/harvest()
if(butcher_state > 0)
butcher_state--
icon_state = icon_dead + "[butcher_state]"
if(prob(50))
new /obj/item/weapon/reagent_containers/food/snacks/spiderleg(src.loc)
return
else
return ..()
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/proc/GiveUp(var/C)
spawn(100)
if(busy == MOVING_TO_TARGET)
@@ -18,14 +18,7 @@
projectilesound = 'sound/weapons/Gunshot.ogg'
projectiletype = /obj/item/projectile/hivebotbullet
faction = list("hivebot")
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
speak_emote = list("states")
@@ -79,37 +72,36 @@
warpbots()
New()
..()
var/datum/effect/system/harmless_smoke_spread/smoke = new /datum/effect/system/harmless_smoke_spread()
smoke.set_up(5, 0, src.loc)
smoke.start()
visible_message("\red <B>The [src] warps in!</B>")
playsound(src.loc, 'sound/effects/EMPulse.ogg', 25, 1)
/mob/living/simple_animal/hostile/hivebot/tele/New()
..()
var/datum/effect/system/harmless_smoke_spread/smoke = new /datum/effect/system/harmless_smoke_spread()
smoke.set_up(5, 0, src.loc)
smoke.start()
visible_message("\red <B>The [src] warps in!</B>")
playsound(src.loc, 'sound/effects/EMPulse.ogg', 25, 1)
warpbots()
icon_state = "def_radar"
visible_message("\red The [src] turns on!")
while(bot_amt > 0)
bot_amt--
switch(bot_type)
if("norm")
var/mob/living/simple_animal/hostile/hivebot/H = new /mob/living/simple_animal/hostile/hivebot(get_turf(src))
H.faction = faction
if("range")
var/mob/living/simple_animal/hostile/hivebot/range/R = new /mob/living/simple_animal/hostile/hivebot/range(get_turf(src))
R.faction = faction
if("rapid")
var/mob/living/simple_animal/hostile/hivebot/rapid/F = new /mob/living/simple_animal/hostile/hivebot/rapid(get_turf(src))
F.faction = faction
spawn(100)
qdel(src)
/mob/living/simple_animal/hostile/hivebot/tele/warpbots()
icon_state = "def_radar"
visible_message("\red The [src] turns on!")
while(bot_amt > 0)
bot_amt--
switch(bot_type)
if("norm")
var/mob/living/simple_animal/hostile/hivebot/H = new /mob/living/simple_animal/hostile/hivebot(get_turf(src))
H.faction = faction
if("range")
var/mob/living/simple_animal/hostile/hivebot/range/R = new /mob/living/simple_animal/hostile/hivebot/range(get_turf(src))
R.faction = faction
if("rapid")
var/mob/living/simple_animal/hostile/hivebot/rapid/F = new /mob/living/simple_animal/hostile/hivebot/rapid(get_turf(src))
F.faction = faction
spawn(100)
qdel(src)
return
/mob/living/simple_animal/hostile/hivebot/tele/process_ai()
. = ..()
if(!.)
return
Life()
..()
if(stat == 0)
if(prob(2))//Might be a bit low, will mess with it likely
warpbots()
if(prob(2))//Might be a bit low, will mess with it likely
warpbots()
@@ -32,33 +32,34 @@
var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_SLEEP (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
/mob/living/simple_animal/hostile/Life()
. = ..()
if(!.)
walk(src, 0)
return 0
if(ranged)
ranged_cooldown--
if(client)
return 0
/mob/living/simple_animal/hostile/process_ai()
..()
if(!AICanContinue())
return 0
if(!stat)
switch(stance)
if(HOSTILE_STANCE_IDLE)
var/new_target = FindTarget()
GiveTarget(new_target)
switch(stance)
if(HOSTILE_STANCE_IDLE)
var/new_target = FindTarget()
GiveTarget(new_target)
if(HOSTILE_STANCE_ATTACK)
MoveToTarget()
DestroySurroundings()
if(HOSTILE_STANCE_ATTACK)
MoveToTarget()
DestroySurroundings()
if(HOSTILE_STANCE_ATTACKING)
AttackTarget()
DestroySurroundings()
if(HOSTILE_STANCE_ATTACKING)
AttackTarget()
DestroySurroundings()
if(AIShouldSleep())
AIStatus = AI_SLEEP
if(AIShouldSleep())
AIStatus = AI_SLEEP
return 1
//////////////HOSTILE MOB TARGETTING AND AGGRESSION////////////
@@ -13,8 +13,7 @@
icon_gib = "panther_dead"
speak_chance = 0
turns_per_move = 3
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 3
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 3)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "hits the"
@@ -72,8 +71,7 @@
icon_gib = "snake_dead"
speak_chance = 0
turns_per_move = 1
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
meat_amount = 2
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat = 2)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "hits the"
@@ -23,14 +23,7 @@
attack_sound = 'sound/weapons/bite.ogg'
speak_emote = list("creaks")
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
faction = list("mimic")
@@ -1,13 +1,6 @@
/mob/living/simple_animal/hostile/asteroid/
vision_range = 2
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
unsuitable_atmos_damage = 15
faction = list("mining")
environment_smash = 2
@@ -387,7 +380,7 @@
anchored = 1 //Stays anchored until death as to be unpullable
var/pre_attack = 0
/mob/living/simple_animal/hostile/asteroid/goliath/Life()
/mob/living/simple_animal/hostile/asteroid/goliath/process_ai()
..()
handle_preattack()
@@ -8,7 +8,7 @@
turns_per_move = 1
maxHealth = 10
health = 10
meat_type = /obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "whacks"
@@ -19,14 +19,7 @@
attacktext = "slashes"
attack_sound = 'sound/weapons/bladeslice.ogg'
min_oxy = 5
max_oxy = 0
min_tox = 0
max_tox = 1
min_co2 = 0
max_co2 = 5
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
unsuitable_atmos_damage = 15
speak_emote = list("yarrs")
var/corpse = /obj/effect/landmark/mobcorpse/pirate
@@ -22,14 +22,7 @@
flying = 1
//Spaceborn beings don't get hurt by space
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
/mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(var/check_drift = 0)
@@ -23,15 +23,6 @@
attacktext = "attacks"
attack_sound = 'sound/items/bikehorn.ogg'
environment_smash = 0
min_oxy = 5
max_oxy = 0
min_tox = 0
max_tox = 1
min_co2 = 0
max_co2 = 5
min_n2 = 0
max_n2 = 0
minbodytemp = 270
maxbodytemp = 370
heat_damage_per_tick = 15 //amount of damage applied if animal's body temperature is higher than maxbodytemp
@@ -35,14 +35,7 @@
var/exploding = 0
//Drones aren't affected by atmos.
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
var/has_loot = 1
@@ -8,8 +8,7 @@
icon_gib = "carp_gib"
speak_chance = 0
turns_per_move = 5
meat_type = /obj/item/weapon/reagent_containers/food/snacks/carpmeat
meat_amount = 1
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/carpmeat = 1)
response_help = "pets the"
response_disarm = "gently pushes aside the"
response_harm = "hits the"

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