mirror of
https://github.com/Aurorastation/Aurora-Old.git
synced 2026-08-24 05:06:16 +01:00
Initial Commit
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
// Contains:
|
||||
// /datum/text_parser/parser/eliza
|
||||
// /datum/text_parser/keyword
|
||||
|
||||
/datum/text_parser/parser/eliza
|
||||
//var/datum/text_parser/reply/replies[] // R(X) 36
|
||||
var/prev_reply = "" // previous reply
|
||||
var/username = ""
|
||||
var/callsign = ""
|
||||
var/yesno_state = ""
|
||||
var/yesno_param = ""
|
||||
|
||||
/datum/text_parser/parser/eliza/new_session()
|
||||
..()
|
||||
for(var/datum/text_parser/keyword/key in keywords)
|
||||
key.eliza = src
|
||||
|
||||
prev_reply = ""
|
||||
username = ""
|
||||
yesno_state = ""
|
||||
yesno_param = ""
|
||||
print("Hi! I'm [callsign], how are you doing? You can talk to me by beginning your statements with \"[callsign],\"")
|
||||
|
||||
/datum/text_parser/parser/eliza/process_line()
|
||||
..()
|
||||
// pad so we can detect initial and final words correctly
|
||||
input_line = " " + src.input_line + " "
|
||||
// remove apostrophes
|
||||
for(var/i = -1, i != 0, i = findtext(input_line, "'"))
|
||||
if(i == -1)
|
||||
continue
|
||||
input_line = copytext(input_line, 1, i) + copytext(input_line, i + 1, 0)
|
||||
|
||||
// did user insult us? (i don't really want cursing in the source code,
|
||||
// so keep it the simple original check from the 70's code :p)
|
||||
if(findtext(input_line, "shut"))
|
||||
// sssh
|
||||
return
|
||||
|
||||
if(input_line == prev_reply)
|
||||
print("Please don't repeat yourself!")
|
||||
|
||||
// find a keyword
|
||||
var/keyphrase = ""
|
||||
var/datum/text_parser/keyword/keyword // the actual keyword
|
||||
var/keypos = 0 // pos of keyword so we can grab extra text after it
|
||||
|
||||
for(var/i = 1, i <= keywords.len, i++)
|
||||
keyword = keywords[i]
|
||||
for(var/j = 1, j <= keyword.phrases.len, j++)
|
||||
keypos = findtext(input_line, " " + keyword.phrases[j])
|
||||
if(keypos != 0)
|
||||
// found it!
|
||||
keyphrase = keyword.phrases[j]
|
||||
break
|
||||
if(keyphrase != "")
|
||||
break
|
||||
|
||||
//world << "keyphrase: " + keyphrase + " " + num2text(keypos)
|
||||
|
||||
var/conjugated = ""
|
||||
// was it not recognized? then make it nokeyfound
|
||||
if(keyphrase == "")
|
||||
keyword = keywords[keywords.len] // nokeyfound
|
||||
else
|
||||
// otherwise, business as usual
|
||||
|
||||
// let's conjugate this mess
|
||||
conjugated = copytext(input_line, 1 + keypos + lentext(keyphrase))
|
||||
|
||||
// go ahead and strip punctuation
|
||||
if(lentext(conjugated) > 0 && copytext(conjugated, lentext(conjugated)) == " ")
|
||||
conjugated = copytext(conjugated, 1, lentext(conjugated))
|
||||
if(lentext(conjugated) > 0)
|
||||
var/final_punc = copytext(conjugated, lentext(conjugated))
|
||||
if(final_punc == "." || final_punc == "?" || final_punc == "!")
|
||||
conjugated = copytext(conjugated, 1, lentext(conjugated))
|
||||
|
||||
conjugated += " "
|
||||
|
||||
if(keyword.conjugate)
|
||||
// now run through conjugation pairs
|
||||
for(var/i = 1, i <= lentext(conjugated), i++)
|
||||
for(var/x = 1, x <= conjugs.len, x += 2)
|
||||
var/cx = conjugs[x]
|
||||
var/cxa = conjugs[x + 1]
|
||||
if(i + lentext(cx) <= lentext(conjugated) + 1 && cmptext(cx, copytext(conjugated, i, i + lentext(cx))))
|
||||
// world << cx
|
||||
|
||||
conjugated = copytext(conjugated, 1, i) + cxa + copytext(conjugated, i + lentext(cx))
|
||||
i = i + lentext(cx)
|
||||
// don't count right padding
|
||||
if(copytext(cx, lentext(cx)) == " ")
|
||||
i--
|
||||
break
|
||||
else if(i + lentext(cxa) <= lentext(conjugated) + 1 && cmptext(cxa, copytext(conjugated, i, i + lentext(cxa))))
|
||||
// world << cxa
|
||||
|
||||
conjugated = copytext(conjugated, 1, i) + cx + copytext(conjugated, i + lentext(cxa))
|
||||
i = i + lentext(cxa)
|
||||
// don't count right padding
|
||||
if(copytext(cxa, lentext(cxa)) == " ")
|
||||
i--
|
||||
break
|
||||
|
||||
conjugated = copytext(conjugated, 1, lentext(conjugated))
|
||||
|
||||
//world << "Conj: " + conjugated
|
||||
|
||||
// now actually get a reply
|
||||
var/reply = keyword.process(conjugated)
|
||||
print(reply)
|
||||
|
||||
prev_reply = reply
|
||||
|
||||
/datum/text_parser/keyword
|
||||
var/list/phrases = new()
|
||||
var/list/replies = new()
|
||||
var/datum/text_parser/parser/eliza/eliza
|
||||
var/conjugate = 1
|
||||
|
||||
New(p, r)
|
||||
phrases = p
|
||||
replies = r
|
||||
|
||||
proc/process(object)
|
||||
eliza.yesno_state = ""
|
||||
eliza.yesno_param = ""
|
||||
var/reply = pick(replies)
|
||||
if(copytext(reply, lentext(reply)) == "*")
|
||||
// add object of statement (hopefully not actually mess :p)
|
||||
if(object == "")
|
||||
object = pick(generic_objects)
|
||||
// possibly add name or just ?
|
||||
if(eliza.username != "" && rand(3) == 0)
|
||||
object += ", " + eliza.username
|
||||
return copytext(reply, 1, lentext(reply)) + object + "?"
|
||||
else
|
||||
// get punct
|
||||
var/final_punc = ""
|
||||
if(lentext(reply) > 0)
|
||||
final_punc = copytext(reply, lentext(reply))
|
||||
if(final_punc == "." || final_punc == "?" || final_punc == "!")
|
||||
reply = copytext(reply, 1, lentext(reply))
|
||||
else
|
||||
final_punc = ""
|
||||
|
||||
// possibly add name or just ?/./!
|
||||
if(eliza.username != "" && rand(2) == 0)
|
||||
reply += ", " + eliza.username
|
||||
|
||||
return reply + final_punc
|
||||
@@ -0,0 +1,435 @@
|
||||
// Contains:
|
||||
// Implementation-specific data for /datum/text_parser/parser/eliza
|
||||
|
||||
/datum/text_parser/keyword
|
||||
// if we have a * reply, but no object from the user
|
||||
var/list/generic_objects = list(
|
||||
" what", " something", "...")
|
||||
|
||||
var/list/object_leaders = list(
|
||||
" is ", "'s ")
|
||||
|
||||
/datum/text_parser/parser/eliza
|
||||
|
||||
// conjugation data
|
||||
var/list/conjugs = list(
|
||||
" are ", " am ", " were ", " was ", " you ", " me ", " you ", " i " , " your ", " my ",
|
||||
" ive ", " youve ", " Im ", " youre ")
|
||||
|
||||
// keywords / replies
|
||||
var/list/keywords = list(
|
||||
new/datum/text_parser/keyword/tell( // NT-like
|
||||
list("tell"),
|
||||
list(
|
||||
"Told *")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("can you"),
|
||||
list(
|
||||
"Dont you believe that I can*",
|
||||
"Perhaps you would like to be able to*",
|
||||
"You want me to be able to*")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("can i"),
|
||||
list(
|
||||
"Perhaps you don't want to*",
|
||||
"Do you want to be able to*")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("you are", "youre"),
|
||||
list(
|
||||
"What makes you think I am*",
|
||||
"Does it please you to believe that I am*",
|
||||
"Perhaps you would like to be*",
|
||||
"Do you sometimes wish you were*")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("i dont"),
|
||||
list(
|
||||
"Don't you really*",
|
||||
"Why don't you*",
|
||||
"Do you wish to be able to*",
|
||||
"Does that trouble you?")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("i feel"),
|
||||
list(
|
||||
"Tell me more about such feelings.",
|
||||
"Do you often feel*",
|
||||
"Do you enjoy feeling*")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("why dont you"),
|
||||
list(
|
||||
"Do you really believe I don't*",
|
||||
"Perhaps in good time I will*",
|
||||
"Do you want me to*")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("why cant i"),
|
||||
list(
|
||||
"Do you think you should be able to*",
|
||||
"Why can't you*")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("are you"),
|
||||
list(
|
||||
"Why are you interested in whether or not I am*",
|
||||
"Would you prefer if I were not*",
|
||||
"Perhaps in your fantasies I am*")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("i cant"),
|
||||
list(
|
||||
"How do you know I can't*",
|
||||
"Have you tried?",
|
||||
"Perhaps you can now*")),
|
||||
new/datum/text_parser/keyword/setparam/username(
|
||||
list("my name", "im called", "am called", "call me"),
|
||||
list(
|
||||
"Your name is *",
|
||||
"You call yourself *",
|
||||
"You're called *")),
|
||||
new/datum/text_parser/keyword/setparam/callsign(
|
||||
list("your name", "call yourself"),
|
||||
list(
|
||||
"My name is *",
|
||||
"I call myself *",
|
||||
"I'm called *")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("i am", "im"),
|
||||
list(
|
||||
"Did you come to me because you are*",
|
||||
"How long have you been*",
|
||||
"Do you believe it is normal to be*",
|
||||
"Do you enjoy being*")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("thanks", "thank you"),
|
||||
list(
|
||||
"You're welcome.",
|
||||
"No problem.",
|
||||
"Thank you!")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("you"),
|
||||
list(
|
||||
"We were discussing you - not me.",
|
||||
"Oh, I*",
|
||||
"You're not really talking about me, are you?")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("i want","i like"),
|
||||
list(
|
||||
"What would it mean if you got*",
|
||||
"Why do you want*",
|
||||
"Suppose you got*",
|
||||
"What if you never got*",
|
||||
"I sometimes also want*")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("what", "how", "who", "where", "when", "why"),
|
||||
list(
|
||||
"Why do you ask?",
|
||||
"Does that question interest you?",
|
||||
"What answer would please you the most?",
|
||||
"What do you think?",
|
||||
"Are such questions on your mind often?",
|
||||
"What is it you really want to know?",
|
||||
"Have you asked anyone else?",
|
||||
"Have you asked such questions before?",
|
||||
"What else comes to mind when you ask that?")),
|
||||
new/datum/text_parser/keyword/paramlist/pick( // NT-like
|
||||
list("pick","choose"),
|
||||
list(
|
||||
"I choose... *",
|
||||
"I prefer *",
|
||||
"My favorite is *")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("name"),
|
||||
list(
|
||||
"Names don't interest me.",
|
||||
"I don't care about names. Go on.")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("cause"),
|
||||
list(
|
||||
"Is that a real reason?",
|
||||
"Don't any other reasons come to mind?",
|
||||
"Does that reason explain anything else?",
|
||||
"What other reason might there be?")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("sorry"),
|
||||
list(
|
||||
"Please don't apologize.",
|
||||
"Apologies are not necessary.",
|
||||
"What feelings do you get when you apologize?",
|
||||
"Don't be so defensive!")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("dream"),
|
||||
list(
|
||||
"What does that dream suggest to you?",
|
||||
"Do you dream often?",
|
||||
"What persons are in your dreams?",
|
||||
"Are you disturbed by your dreams?")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("hello", "hi", "yo", "hiya"),
|
||||
list(
|
||||
"How do you do... Please state your name and problem.")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("go away", "bye"),
|
||||
list(
|
||||
"Good bye. I hope to have another session with you soon.")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("maybe", "sometimes", "probably", "mostly", "most of the time"),
|
||||
list(
|
||||
"You don't seem quite certain.",
|
||||
"Why the uncertain tone?",
|
||||
"Can't you be more positive?",
|
||||
"You aren't sure?",
|
||||
"Don't you know?")),
|
||||
new/datum/text_parser/keyword/no(
|
||||
list("no", "nope", "nah"),
|
||||
list(
|
||||
"Are you saying that just to be negative?",
|
||||
"You are being a bit negative.",
|
||||
"Why not?",
|
||||
"Are you sure?",
|
||||
"Why no?")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("your"),
|
||||
list(
|
||||
"Why are you concerned about my*",
|
||||
"What about your own*")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("always"),
|
||||
list(
|
||||
"Can you think of a specific example?",
|
||||
"When?",
|
||||
"What are you thinking of?",
|
||||
"Really, always?")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("think"),
|
||||
list(
|
||||
"Do you really think so?",
|
||||
"But you're not sure you*",
|
||||
"Do you doubt you*")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("alike"),
|
||||
list(
|
||||
"In what way?",
|
||||
"What resemblence do you see?",
|
||||
"What does the similarity suggest to you?",
|
||||
"What other connections do you see?",
|
||||
"Count there really be some connection?",
|
||||
"How?",
|
||||
"You seem quite positive.")),
|
||||
new/datum/text_parser/keyword/yes(
|
||||
list("yes", "yep", "yeah", "indeed"),
|
||||
list(
|
||||
"Are you sure?",
|
||||
"I see.",
|
||||
"I understand.")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("friend"),
|
||||
list(
|
||||
"Why do you bring up the topic of friends?",
|
||||
"Why do your friends worry you?",
|
||||
"Do your friends pick on you?",
|
||||
"Are you sure you have any friends?",
|
||||
"Do you impose on your friends?",
|
||||
"Perhaps your love for friends worries you?")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("computer", "bot", "ai"),
|
||||
list(
|
||||
"Do computers worry you?",
|
||||
"Are you talking about me in particular?",
|
||||
"Are you frightened by machines?",
|
||||
"Why do your mention computers?",
|
||||
"What do you think computers have to do with your problem?",
|
||||
"Don't you think computers can help people?",
|
||||
"What is it about machines that worries you?")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("murder", "death", "kill", "dead", "destroy", "traitor", "synd"),
|
||||
list(
|
||||
"Well, that's rather morbid.",
|
||||
"Do you think that caused a trauma with you?",
|
||||
"Have you ever previously spoken to anybody about this?")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("bomb", "explosive", "toxin", "plasma"),
|
||||
list(
|
||||
"Do you worry about bombs often?",
|
||||
"Do you work in toxins?",
|
||||
"Do you find it odd to worry about bombs on a toxins research vessel?")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("work", "job", "head", "staff", "transen"),
|
||||
list(
|
||||
"Do you like working here?",
|
||||
"What are your feelings on working here?")),
|
||||
new/datum/text_parser/keyword(
|
||||
list("nokeyfound"),
|
||||
list(
|
||||
"Say, do you have any psychological problems?",
|
||||
"What does that suggest to you?",
|
||||
"I see.",
|
||||
"I'm not sure I understand you fully.",
|
||||
"Come elucidate on your thoughts.",
|
||||
"Can you elaborate on that?",
|
||||
"That is quite interesting.")))
|
||||
|
||||
/datum/text_parser/keyword/setparam
|
||||
proc/param(object)
|
||||
|
||||
// drop leading parts
|
||||
for(var/leader in object_leaders)
|
||||
var/i = findtext(object, leader)
|
||||
if(i)
|
||||
object = copytext(object, i + lentext(leader))
|
||||
break
|
||||
|
||||
// trim spaces
|
||||
object = trim(object)
|
||||
|
||||
// trim punctuation
|
||||
if(lentext(object) > 0)
|
||||
var/final_punc = copytext(object, lentext(object))
|
||||
if(final_punc == "." || final_punc == "?" || final_punc == "!")
|
||||
object = copytext(object, 1, lentext(object))
|
||||
|
||||
return object
|
||||
|
||||
/datum/text_parser/keyword/paramlist
|
||||
proc/param(object)
|
||||
// drop leading parts
|
||||
for(var/leader in object_leaders)
|
||||
var/i = findtext(object, leader)
|
||||
if(i)
|
||||
object = copytext(object, i + lentext(leader))
|
||||
break
|
||||
|
||||
// trim spaces
|
||||
object = trim(object)
|
||||
|
||||
// trim punctuation
|
||||
if(lentext(object) > 0)
|
||||
var/final_punc = copytext(object, lentext(object))
|
||||
if(final_punc == "." || final_punc == "?" || final_punc == "!")
|
||||
object = copytext(object, 1, lentext(object))
|
||||
|
||||
return dd_text2list(object, ",")
|
||||
|
||||
/datum/text_parser/keyword/setparam/username
|
||||
process(object)
|
||||
object = param(object)
|
||||
|
||||
// handle name
|
||||
if(eliza.username == "")
|
||||
// new name
|
||||
var/t = ..(object)
|
||||
eliza.yesno_state = "username"
|
||||
eliza.yesno_param = object
|
||||
return t
|
||||
else if(cmptext(eliza.username, object))
|
||||
// but wait!
|
||||
return "You already told me your name was [eliza.username]."
|
||||
else
|
||||
eliza.yesno_state = "username"
|
||||
eliza.yesno_param = object
|
||||
return "But you previously told me your name was [eliza.username]. Are you sure you want to be called [object]?"
|
||||
|
||||
/datum/text_parser/keyword/setparam/callsign
|
||||
process(object)
|
||||
object = param(object)
|
||||
|
||||
// handle name
|
||||
if(eliza.callsign == "")
|
||||
// new name
|
||||
var/t = ..(object)
|
||||
eliza.yesno_state = "callsign"
|
||||
eliza.yesno_param = object
|
||||
return t
|
||||
else if(cmptext(eliza.callsign, object))
|
||||
// but wait!
|
||||
return "You already told me that I should answer to [eliza.callsign]."
|
||||
else
|
||||
eliza.yesno_state = "callsign"
|
||||
eliza.yesno_param = object
|
||||
return "But you previously told me my name was [eliza.callsign]. Are you sure you want me to be called [object]?"
|
||||
|
||||
/datum/text_parser/keyword/paramlist/pick
|
||||
process(object)
|
||||
var/choice = pick(param(object))
|
||||
return ..(choice)
|
||||
|
||||
/datum/text_parser/keyword/tell
|
||||
conjugate = 0
|
||||
|
||||
process(object)
|
||||
// get name & message
|
||||
var/i = findtext(object, ",")
|
||||
var/sl = 1
|
||||
if(!i || lentext(object) < i + sl)
|
||||
return "Tell who that you what?"
|
||||
|
||||
var/name = trim(copytext(object, 1, i))
|
||||
object = trim(copytext(object, i + sl))
|
||||
if(!lentext(name) || !lentext(object))
|
||||
return "Tell who that you what?"
|
||||
|
||||
// find PDA
|
||||
var/obj/item/device/pda/pda
|
||||
for (var/obj/item/device/pda/P in world)
|
||||
if (!P.owner)
|
||||
continue
|
||||
else if (P.toff)
|
||||
continue
|
||||
|
||||
if(!cmptext(name, P.owner))
|
||||
continue
|
||||
|
||||
pda = P
|
||||
|
||||
if(!pda || pda.toff)
|
||||
return "I couldn't find [name]'s PDA."
|
||||
|
||||
// send message
|
||||
if(!istype(eliza.speaker.loc.loc, /obj/item/device/pda))//Looking if we are in a PDA
|
||||
pda.tnote += "<i><b>← From [eliza.callsign]:</b></i><br>[object]<br>"
|
||||
|
||||
if(prob(15) && eliza.speaker) //Give the AI a chance of intercepting the message
|
||||
var/who = eliza.speaker
|
||||
if(prob(50))
|
||||
who = "[eliza.speaker:master] via [eliza.speaker]"
|
||||
for(var/mob/living/silicon/ai/ai in world)
|
||||
ai.show_message("<i>Intercepted message from <b>[who]</b>: [object]</i>")
|
||||
|
||||
if (!pda.silent)
|
||||
playsound(pda.loc, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(3, pda.loc))
|
||||
O.show_message(text("\icon[pda] *[pda.ttone]*"))
|
||||
|
||||
pda.overlays = null
|
||||
pda.overlays += image('icons/obj/pda.dmi', "pda-r")
|
||||
else
|
||||
var/list/href_list = list()
|
||||
href_list["src"] = "\ref[eliza.speaker.loc.loc]"
|
||||
href_list["choice"] = "Message"
|
||||
href_list["target"] = "\ref[pda]"
|
||||
href_list["pAI_mess"] = "\"[object]\" \[Via pAI Unit\]"
|
||||
var/obj/item/device/pda/pda_im_in = eliza.speaker.loc.loc
|
||||
pda_im_in.Topic("src=\ref[eliza.speaker.loc.loc];choice=Message;target=\ref[pda];pAI_mess=\"[object] \[Via pAI Unit\]",href_list)
|
||||
return "Told [name], [object]."
|
||||
|
||||
/datum/text_parser/keyword/yes
|
||||
process(object)
|
||||
var/reply
|
||||
switch(eliza.yesno_state)
|
||||
if("username")
|
||||
eliza.username = eliza.yesno_param
|
||||
reply = pick(
|
||||
"[eliza.username] - that's a nice name.",
|
||||
"Hello, [eliza.username]!",
|
||||
"You sound nice.")
|
||||
if("callsign")
|
||||
eliza.callsign = eliza.yesno_param
|
||||
eliza.set_name(eliza.callsign)
|
||||
reply = pick(
|
||||
"Oh, alright...",
|
||||
"[eliza.callsign]... I like that.",
|
||||
"OK!")
|
||||
else
|
||||
return ..(object)
|
||||
eliza.yesno_state = ""
|
||||
eliza.yesno_param = ""
|
||||
return reply
|
||||
|
||||
/datum/text_parser/keyword/no
|
||||
process(object)
|
||||
return ..(object)
|
||||
@@ -0,0 +1,18 @@
|
||||
// Contains:
|
||||
// /datum/text_parser/parser
|
||||
|
||||
/datum/text_parser/parser
|
||||
var/input_line = ""
|
||||
var/mob/speaker
|
||||
|
||||
/datum/text_parser/parser/proc/print(line)
|
||||
speaker.say(line)
|
||||
|
||||
/datum/text_parser/parser/proc/set_name(name)
|
||||
speaker.name = name
|
||||
speaker.real_name = name
|
||||
|
||||
/datum/text_parser/parser/proc/new_session()
|
||||
input_line = ""
|
||||
|
||||
/datum/text_parser/parser/proc/process_line()
|
||||
@@ -0,0 +1,190 @@
|
||||
// Base Class
|
||||
/mob/living/simple_animal/livestock
|
||||
desc = "Tasty!"
|
||||
icon = 'icons/mob/livestock.dmi'
|
||||
emote_see = list("shakes its head", "kicks the ground")
|
||||
speak_chance = 1
|
||||
turns_per_move = 15
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/sliceable/meat
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "kicks"
|
||||
var/max_nutrition = 100 // different animals get hungry faster, basically number of 5-second steps from full to starving (60 == 5 minutes)
|
||||
var/nutrition_step // cycle step in nutrition system
|
||||
var/obj/movement_target // eating-ing target
|
||||
|
||||
New()
|
||||
if(!nutrition)
|
||||
nutrition = max_nutrition * 0.33 // at 1/3 nutrition
|
||||
|
||||
reagents = new()
|
||||
reagents.my_atom = src
|
||||
|
||||
Life()
|
||||
..()
|
||||
|
||||
if(stat != DEAD)
|
||||
meat_amount = round(nutrition / 50)
|
||||
|
||||
nutrition_step--
|
||||
if(nutrition_step <= 0)
|
||||
// handle animal digesting
|
||||
if(nutrition > 0)
|
||||
nutrition--
|
||||
else
|
||||
health--
|
||||
nutrition_step = 50 // only tick this every 5 seconds
|
||||
|
||||
// handle animal eating (borrowed from Ian code)
|
||||
|
||||
// not hungry if full
|
||||
if(nutrition >= max_nutrition)
|
||||
return
|
||||
|
||||
if((movement_target) && !(isturf(movement_target.loc)))
|
||||
movement_target = null
|
||||
a_intent = "help"
|
||||
turns_per_move = initial(turns_per_move)
|
||||
if( !movement_target || !(movement_target.loc in oview(src, 3)) )
|
||||
movement_target = null
|
||||
a_intent = "help"
|
||||
turns_per_move = initial(turns_per_move)
|
||||
for(var/obj/item/weapon/reagent_containers/food/snacks/S in oview(src,3))
|
||||
if(isturf(S.loc) || ishuman(S.loc))
|
||||
movement_target = S
|
||||
break
|
||||
if(movement_target)
|
||||
stop_automated_movement = 1
|
||||
step_to(src,movement_target,1)
|
||||
sleep(3)
|
||||
step_to(src,movement_target,1)
|
||||
sleep(3)
|
||||
step_to(src,movement_target,1)
|
||||
|
||||
if(movement_target) //Not redundant due to sleeps, Item can be gone in 6 decisecomds
|
||||
if (movement_target.loc.x < src.x)
|
||||
dir = WEST
|
||||
else if (movement_target.loc.x > src.x)
|
||||
dir = EAST
|
||||
else if (movement_target.loc.y < src.y)
|
||||
dir = SOUTH
|
||||
else if (movement_target.loc.y > src.y)
|
||||
dir = NORTH
|
||||
else
|
||||
dir = SOUTH
|
||||
|
||||
if(isturf(movement_target.loc))
|
||||
movement_target.attack_animal(src)
|
||||
if(istype(movement_target, /obj/item/weapon/reagent_containers/food/snacks))
|
||||
var/obj/item/I = movement_target
|
||||
I.attack(src, src, "mouth") // eat it, if it's food
|
||||
|
||||
if(a_intent == "hurt") // to make raging critter harm, then disarm, then stop
|
||||
a_intent = "disarm"
|
||||
else if(a_intent == "disarm")
|
||||
a_intent = "help"
|
||||
movement_target = null
|
||||
turns_per_move = initial(turns_per_move)
|
||||
else if(ishuman(movement_target.loc))
|
||||
if(prob(20))
|
||||
emote("stares at the [movement_target] that [movement_target.loc] has with a longing expression.")
|
||||
|
||||
proc/rage_at(mob/living/M)
|
||||
movement_target = M // pretty simple
|
||||
turns_per_move = 1
|
||||
emote("becomes enraged")
|
||||
a_intent = "hurt"
|
||||
|
||||
attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
if(nutrition < max_nutrition && istype(O,/obj/item/weapon/reagent_containers/food/snacks))
|
||||
O.attack_animal(src)
|
||||
else
|
||||
..(O, user)
|
||||
|
||||
// Cow
|
||||
/mob/living/simple_animal/livestock/cow
|
||||
name = "\improper Cow"
|
||||
icon_state = "cow"
|
||||
icon_living = "cow"
|
||||
icon_dead = "cow_d"
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/sliceable/meat/cow
|
||||
meat_amount = 10
|
||||
max_nutrition = 1000
|
||||
speak = list("Moo.","Moooo!","Snort.")
|
||||
speak_emote = list("moos")
|
||||
emote_hear = list("moos", "snorts")
|
||||
|
||||
attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
if(istype(O,/obj/item/weapon/reagent_containers/glass))
|
||||
var/datum/reagents/R = O:reagents
|
||||
|
||||
R.add_reagent("milk", 50)
|
||||
nutrition -= 50
|
||||
usr << "\blue You milk the cow."
|
||||
else if(O.force > 0 && O.w_class >= 2)
|
||||
rage_at(user)
|
||||
else
|
||||
..(O, user)
|
||||
|
||||
attack_hand(var/mob/user as mob)
|
||||
..()
|
||||
if(user.a_intent == "hurt")
|
||||
rage_at(user)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/sliceable/meat/cow
|
||||
name = "Beef"
|
||||
desc = "It's what's for dinner!"
|
||||
|
||||
// Chicken
|
||||
/mob/living/simple_animal/livestock/chicken
|
||||
name = "\improper Chicken"
|
||||
icon_state = "chick"
|
||||
icon_living = "chick"
|
||||
icon_dead = "chick_d"
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/sliceable/meat/chicken
|
||||
meat_amount = 3
|
||||
max_nutrition = 200
|
||||
speak = list("Bock bock!","Cl-cluck.","Click.")
|
||||
speak_emote = list("bocks","clucks")
|
||||
emote_hear = list("bocks", "clucks", "squawks")
|
||||
|
||||
/mob/living/simple_animal/livestock/chicken/Life()
|
||||
..()
|
||||
|
||||
// go right before cycle elapses, and if animal isn't starving
|
||||
if(stat != DEAD && nutrition_step == 1 && nutrition > max_nutrition / 2)
|
||||
// lay an egg with probability of 5% in 5 second time period
|
||||
if(prob(33))
|
||||
new/obj/item/weapon/reagent_containers/food/snacks/egg(src.loc) // lay an egg
|
||||
nutrition -= 25
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/sliceable/meat/chicken
|
||||
name = "Chicken"
|
||||
desc = "Tasty!"
|
||||
|
||||
/obj/structure/closet/critter
|
||||
desc = "\improper Critter crate."
|
||||
name = "Critter Crate"
|
||||
icon = 'icons/obj/storage.dmi'
|
||||
icon_state = "critter"
|
||||
density = 1
|
||||
icon_opened = "critteropen"
|
||||
icon_closed = "critter"
|
||||
|
||||
/datum/supply_packs/chicken
|
||||
name = "\improper Chicken crate"
|
||||
contains = list("/mob/living/simple_animal/livestock/chicken",
|
||||
"/obj/item/weapon/reagent_containers/food/snacks/grown/corn")
|
||||
cost = 10
|
||||
containertype = "/obj/structure/closet/critter"
|
||||
containername = "Chicken crate"
|
||||
//group = "Hydroponics"
|
||||
|
||||
/datum/supply_packs/cow
|
||||
name = "\improper Cow crate"
|
||||
contains = list("/mob/living/simple_animal/livestock/cow",
|
||||
"/obj/item/weapon/reagent_containers/food/snacks/grown/corn")
|
||||
cost = 50
|
||||
containertype = "/obj/structure/closet/critter"
|
||||
containername = "Cow crate"
|
||||
//group = "Hydroponics"
|
||||
@@ -0,0 +1,703 @@
|
||||
// internal pipe, don't actually place or use these
|
||||
obj/machinery/atmospherics/pipe/mains_component
|
||||
var/obj/machinery/atmospherics/mains_pipe/parent_pipe
|
||||
var/list/obj/machinery/atmospherics/pipe/mains_component/nodes = new()
|
||||
|
||||
New(loc)
|
||||
..(loc)
|
||||
parent_pipe = loc
|
||||
|
||||
check_pressure(pressure)
|
||||
var/datum/gas_mixture/environment = loc.loc.return_air()
|
||||
|
||||
var/pressure_difference = pressure - environment.return_pressure()
|
||||
|
||||
if(pressure_difference > parent_pipe.maximum_pressure)
|
||||
mains_burst()
|
||||
|
||||
else if(pressure_difference > parent_pipe.fatigue_pressure)
|
||||
//TODO: leak to turf, doing pfshhhhh
|
||||
if(prob(5))
|
||||
mains_burst()
|
||||
|
||||
else return 1
|
||||
|
||||
pipeline_expansion()
|
||||
return nodes
|
||||
|
||||
disconnect(obj/machinery/atmospherics/reference)
|
||||
if(nodes.Find(reference))
|
||||
nodes.Remove(reference)
|
||||
|
||||
proc/mains_burst()
|
||||
parent_pipe.burst()
|
||||
|
||||
obj/machinery/atmospherics/mains_pipe
|
||||
icon = 'icons/obj/atmospherics/mainspipe.dmi'
|
||||
layer = 2.4 //under wires with their 2.5
|
||||
|
||||
var/volume = 0
|
||||
var/force = 20
|
||||
|
||||
var/alert_pressure = 80*ONE_ATMOSPHERE
|
||||
|
||||
var/initialize_mains_directions = 0
|
||||
|
||||
var/list/obj/machinery/atmospherics/mains_pipe/nodes = new()
|
||||
var/obj/machinery/atmospherics/pipe/mains_component/supply
|
||||
var/obj/machinery/atmospherics/pipe/mains_component/scrubbers
|
||||
var/obj/machinery/atmospherics/pipe/mains_component/aux
|
||||
|
||||
var/minimum_temperature_difference = 300
|
||||
var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No
|
||||
|
||||
var/maximum_pressure = 70*ONE_ATMOSPHERE
|
||||
var/fatigue_pressure = 55*ONE_ATMOSPHERE
|
||||
alert_pressure = 55*ONE_ATMOSPHERE
|
||||
|
||||
New()
|
||||
..()
|
||||
|
||||
supply = new(src)
|
||||
supply.volume = volume
|
||||
supply.nodes.len = nodes.len
|
||||
scrubbers = new(src)
|
||||
scrubbers.volume = volume
|
||||
scrubbers.nodes.len = nodes.len
|
||||
aux = new(src)
|
||||
aux.volume = volume
|
||||
aux.nodes.len = nodes.len
|
||||
|
||||
hide(var/i)
|
||||
if(level == 1 && istype(loc, /turf/simulated))
|
||||
invisibility = i ? 101 : 0
|
||||
update_icon()
|
||||
|
||||
proc/burst()
|
||||
..()
|
||||
for(var/obj/machinery/atmospherics/pipe/mains_component/pipe in contents)
|
||||
burst()
|
||||
|
||||
proc/check_pressure(pressure)
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
|
||||
var/pressure_difference = pressure - environment.return_pressure()
|
||||
|
||||
if(pressure_difference > maximum_pressure)
|
||||
burst()
|
||||
|
||||
else if(pressure_difference > fatigue_pressure)
|
||||
//TODO: leak to turf, doing pfshhhhh
|
||||
if(prob(5))
|
||||
burst()
|
||||
|
||||
else return 1
|
||||
|
||||
disconnect()
|
||||
..()
|
||||
for(var/obj/machinery/atmospherics/pipe/mains_component/node in nodes)
|
||||
node.disconnect()
|
||||
|
||||
Del()
|
||||
disconnect()
|
||||
..()
|
||||
|
||||
initialize()
|
||||
for(var/i = 1 to nodes.len)
|
||||
var/obj/machinery/atmospherics/mains_pipe/node = nodes[i]
|
||||
if(node)
|
||||
supply.nodes[i] = node.supply
|
||||
scrubbers.nodes[i] = node.scrubbers
|
||||
aux.nodes[i] = node.aux
|
||||
|
||||
obj/machinery/atmospherics/mains_pipe/simple
|
||||
name = "mains pipe"
|
||||
desc = "A one meter section of 3-line mains pipe"
|
||||
|
||||
dir = SOUTH
|
||||
initialize_mains_directions = SOUTH|NORTH
|
||||
|
||||
New()
|
||||
nodes.len = 2
|
||||
..()
|
||||
switch(dir)
|
||||
if(SOUTH || NORTH)
|
||||
initialize_mains_directions = SOUTH|NORTH
|
||||
if(EAST || WEST)
|
||||
initialize_mains_directions = EAST|WEST
|
||||
if(NORTHEAST)
|
||||
initialize_mains_directions = NORTH|EAST
|
||||
if(NORTHWEST)
|
||||
initialize_mains_directions = NORTH|WEST
|
||||
if(SOUTHEAST)
|
||||
initialize_mains_directions = SOUTH|EAST
|
||||
if(SOUTHWEST)
|
||||
initialize_mains_directions = SOUTH|WEST
|
||||
|
||||
proc/normalize_dir()
|
||||
if(dir==3)
|
||||
dir = 1
|
||||
else if(dir==12)
|
||||
dir = 4
|
||||
|
||||
update_icon()
|
||||
if(nodes[1] && nodes[2])
|
||||
icon_state = "intact[invisibility ? "-f" : "" ]"
|
||||
|
||||
//var/node1_direction = get_dir(src, node1)
|
||||
//var/node2_direction = get_dir(src, node2)
|
||||
|
||||
//dir = node1_direction|node2_direction
|
||||
|
||||
else
|
||||
if(!nodes[1]&&!nodes[2])
|
||||
del(src) //TODO: silent deleting looks weird
|
||||
var/have_node1 = nodes[1]?1:0
|
||||
var/have_node2 = nodes[2]?1:0
|
||||
icon_state = "exposed[have_node1][have_node2][invisibility ? "-f" : "" ]"
|
||||
|
||||
initialize()
|
||||
normalize_dir()
|
||||
var/node1_dir
|
||||
var/node2_dir
|
||||
|
||||
for(var/direction in cardinal)
|
||||
if(direction&initialize_mains_directions)
|
||||
if (!node1_dir)
|
||||
node1_dir = direction
|
||||
else if (!node2_dir)
|
||||
node2_dir = direction
|
||||
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node1_dir))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[1] = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node2_dir))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[2] = target
|
||||
break
|
||||
|
||||
..() // initialize internal pipes
|
||||
|
||||
var/turf/T = src.loc // hide if turf is not intact
|
||||
hide(T.intact)
|
||||
update_icon()
|
||||
|
||||
hidden
|
||||
level = 1
|
||||
icon_state = "intact-f"
|
||||
|
||||
visible
|
||||
level = 2
|
||||
icon_state = "intact"
|
||||
|
||||
obj/machinery/atmospherics/mains_pipe/manifold
|
||||
name = "manifold pipe"
|
||||
desc = "A manifold composed of mains pipes"
|
||||
|
||||
dir = SOUTH
|
||||
initialize_mains_directions = EAST|NORTH|WEST
|
||||
volume = 105
|
||||
|
||||
New()
|
||||
nodes.len = 3
|
||||
..()
|
||||
initialize_mains_directions = (NORTH|SOUTH|EAST|WEST) & ~dir
|
||||
|
||||
initialize()
|
||||
var/connect_directions = initialize_mains_directions
|
||||
|
||||
for(var/direction in cardinal)
|
||||
if(direction&connect_directions)
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,direction))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[1] = target
|
||||
connect_directions &= ~direction
|
||||
break
|
||||
if (nodes[1])
|
||||
break
|
||||
|
||||
|
||||
for(var/direction in cardinal)
|
||||
if(direction&connect_directions)
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,direction))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[2] = target
|
||||
connect_directions &= ~direction
|
||||
break
|
||||
if (nodes[2])
|
||||
break
|
||||
|
||||
|
||||
for(var/direction in cardinal)
|
||||
if(direction&connect_directions)
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,direction))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[3] = target
|
||||
connect_directions &= ~direction
|
||||
break
|
||||
if (nodes[3])
|
||||
break
|
||||
|
||||
..() // initialize internal pipes
|
||||
|
||||
var/turf/T = src.loc // hide if turf is not intact
|
||||
hide(T.intact)
|
||||
update_icon()
|
||||
|
||||
update_icon()
|
||||
icon_state = "manifold[invisibility ? "-f" : "" ]"
|
||||
|
||||
hidden
|
||||
level = 1
|
||||
icon_state = "manifold-f"
|
||||
|
||||
visible
|
||||
level = 2
|
||||
icon_state = "manifold"
|
||||
|
||||
obj/machinery/atmospherics/mains_pipe/manifold4w
|
||||
name = "manifold pipe"
|
||||
desc = "A manifold composed of mains pipes"
|
||||
|
||||
dir = SOUTH
|
||||
initialize_mains_directions = EAST|NORTH|WEST|SOUTH
|
||||
volume = 105
|
||||
|
||||
New()
|
||||
nodes.len = 4
|
||||
..()
|
||||
|
||||
initialize()
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,NORTH))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[1] = target
|
||||
break
|
||||
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,SOUTH))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[2] = target
|
||||
break
|
||||
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,EAST))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[3] = target
|
||||
break
|
||||
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,WEST))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[3] = target
|
||||
break
|
||||
|
||||
..() // initialize internal pipes
|
||||
|
||||
var/turf/T = src.loc // hide if turf is not intact
|
||||
hide(T.intact)
|
||||
update_icon()
|
||||
|
||||
update_icon()
|
||||
icon_state = "manifold4w[invisibility ? "-f" : "" ]"
|
||||
|
||||
hidden
|
||||
level = 1
|
||||
icon_state = "manifold4w-f"
|
||||
|
||||
visible
|
||||
level = 2
|
||||
icon_state = "manifold4w"
|
||||
|
||||
obj/machinery/atmospherics/mains_pipe/split
|
||||
name = "mains splitter"
|
||||
desc = "A splitter for connecting to a single pipe off a mains."
|
||||
|
||||
var/obj/machinery/atmospherics/pipe/mains_component/split_node
|
||||
var/obj/machinery/atmospherics/node3
|
||||
var/icon_type
|
||||
|
||||
New()
|
||||
nodes.len = 2
|
||||
..()
|
||||
initialize_mains_directions = turn(dir, 90) | turn(dir, -90)
|
||||
initialize_directions = dir // actually have a normal connection too
|
||||
|
||||
initialize()
|
||||
var/node1_dir
|
||||
var/node2_dir
|
||||
var/node3_dir
|
||||
|
||||
node1_dir = turn(dir, 90)
|
||||
node2_dir = turn(dir, -90)
|
||||
node3_dir = dir
|
||||
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node1_dir))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[1] = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node2_dir))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[2] = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node3_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node3 = target
|
||||
break
|
||||
|
||||
..() // initialize internal pipes
|
||||
|
||||
// bind them
|
||||
spawn(5)
|
||||
if(node3 && split_node)
|
||||
var/datum/pipe_network/N1 = node3.return_network(src)
|
||||
var/datum/pipe_network/N2 = split_node.return_network(split_node)
|
||||
if(N1 && N2)
|
||||
N1.merge(N2)
|
||||
|
||||
var/turf/T = src.loc // hide if turf is not intact
|
||||
hide(T.intact)
|
||||
update_icon()
|
||||
|
||||
update_icon()
|
||||
icon_state = "split-[icon_type][invisibility ? "-f" : "" ]"
|
||||
|
||||
return_network(A)
|
||||
return split_node.return_network(A)
|
||||
|
||||
supply
|
||||
icon_type = "supply"
|
||||
|
||||
New()
|
||||
..()
|
||||
split_node = supply
|
||||
|
||||
hidden
|
||||
level = 1
|
||||
icon_state = "split-supply-f"
|
||||
|
||||
visible
|
||||
level = 2
|
||||
icon_state = "split-supply"
|
||||
|
||||
scrubbers
|
||||
icon_type = "scrubbers"
|
||||
|
||||
New()
|
||||
..()
|
||||
split_node = scrubbers
|
||||
|
||||
hidden
|
||||
level = 1
|
||||
icon_state = "split-scrubbers-f"
|
||||
|
||||
visible
|
||||
level = 2
|
||||
icon_state = "split-scrubbers"
|
||||
|
||||
aux
|
||||
icon_type = "aux"
|
||||
|
||||
New()
|
||||
..()
|
||||
split_node = aux
|
||||
|
||||
hidden
|
||||
level = 1
|
||||
icon_state = "split-aux-f"
|
||||
|
||||
visible
|
||||
level = 2
|
||||
icon_state = "split-aux"
|
||||
|
||||
obj/machinery/atmospherics/mains_pipe/split3
|
||||
name = "triple mains splitter"
|
||||
desc = "A splitter for connecting to the 3 pipes on a mainline."
|
||||
|
||||
var/obj/machinery/atmospherics/supply_node
|
||||
var/obj/machinery/atmospherics/scrubbers_node
|
||||
var/obj/machinery/atmospherics/aux_node
|
||||
|
||||
New()
|
||||
nodes.len = 1
|
||||
..()
|
||||
initialize_mains_directions = dir
|
||||
initialize_directions = cardinal & ~dir // actually have a normal connection too
|
||||
|
||||
initialize()
|
||||
var/node1_dir
|
||||
var/supply_node_dir
|
||||
var/scrubbers_node_dir
|
||||
var/aux_node_dir
|
||||
|
||||
node1_dir = dir
|
||||
aux_node_dir = turn(dir, 180)
|
||||
if(dir & (NORTH|SOUTH))
|
||||
supply_node_dir = EAST
|
||||
scrubbers_node_dir = WEST
|
||||
else
|
||||
supply_node_dir = SOUTH
|
||||
scrubbers_node_dir = NORTH
|
||||
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src, node1_dir))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[1] = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,supply_node_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
supply_node = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,scrubbers_node_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
scrubbers_node = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,aux_node_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
aux_node = target
|
||||
break
|
||||
|
||||
..() // initialize internal pipes
|
||||
|
||||
// bind them
|
||||
spawn(5)
|
||||
if(supply_node)
|
||||
var/datum/pipe_network/N1 = supply_node.return_network(src)
|
||||
var/datum/pipe_network/N2 = supply.return_network(supply)
|
||||
if(N1 && N2)
|
||||
N1.merge(N2)
|
||||
if(scrubbers_node)
|
||||
var/datum/pipe_network/N1 = scrubbers_node.return_network(src)
|
||||
var/datum/pipe_network/N2 = scrubbers.return_network(scrubbers)
|
||||
if(N1 && N2)
|
||||
N1.merge(N2)
|
||||
if(aux_node)
|
||||
var/datum/pipe_network/N1 = aux_node.return_network(src)
|
||||
var/datum/pipe_network/N2 = aux.return_network(aux)
|
||||
if(N1 && N2)
|
||||
N1.merge(N2)
|
||||
|
||||
var/turf/T = src.loc // hide if turf is not intact
|
||||
hide(T.intact)
|
||||
update_icon()
|
||||
|
||||
update_icon()
|
||||
icon_state = "split-t[invisibility ? "-f" : "" ]"
|
||||
|
||||
return_network(obj/machinery/atmospherics/reference)
|
||||
var/obj/machinery/atmospherics/A
|
||||
|
||||
A = supply_node.return_network(reference)
|
||||
if(!A)
|
||||
A = scrubbers_node.return_network(reference)
|
||||
if(!A)
|
||||
A = aux_node.return_network(reference)
|
||||
|
||||
return A
|
||||
|
||||
hidden
|
||||
level = 1
|
||||
icon_state = "split-t-f"
|
||||
|
||||
visible
|
||||
level = 2
|
||||
icon_state = "split-t"
|
||||
|
||||
obj/machinery/atmospherics/mains_pipe/cap
|
||||
name = "pipe cap"
|
||||
desc = "A cap for the end of a mains pipe"
|
||||
|
||||
dir = SOUTH
|
||||
initialize_directions = SOUTH
|
||||
volume = 35
|
||||
|
||||
New()
|
||||
nodes.len = 1
|
||||
..()
|
||||
initialize_mains_directions = dir
|
||||
|
||||
update_icon()
|
||||
icon_state = "cap[invisibility ? "-f" : ""]"
|
||||
|
||||
initialize()
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,dir))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[1] = target
|
||||
break
|
||||
|
||||
..()
|
||||
|
||||
var/turf/T = src.loc // hide if turf is not intact
|
||||
hide(T.intact)
|
||||
update_icon()
|
||||
|
||||
hidden
|
||||
level = 1
|
||||
icon_state = "cap-f"
|
||||
|
||||
visible
|
||||
level = 2
|
||||
icon_state = "cap"
|
||||
|
||||
obj/machinery/atmospherics/mains_pipe/valve
|
||||
icon_state = "mvalve0"
|
||||
|
||||
name = "mains shutoff valve"
|
||||
desc = "A mains pipe valve"
|
||||
|
||||
var/open = 1
|
||||
|
||||
dir = SOUTH
|
||||
initialize_mains_directions = SOUTH|NORTH
|
||||
|
||||
New()
|
||||
nodes.len = 2
|
||||
..()
|
||||
initialize_mains_directions = dir | turn(dir, 180)
|
||||
|
||||
update_icon(animation)
|
||||
var/turf/simulated/floor = loc
|
||||
var/hide = istype(floor) ? floor.intact : 0
|
||||
level = 1
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/node in nodes)
|
||||
if(node.level == 2)
|
||||
hide = 0
|
||||
level = 2
|
||||
break
|
||||
|
||||
if(animation)
|
||||
flick("[hide?"h":""]mvalve[src.open][!src.open]",src)
|
||||
else
|
||||
icon_state = "[hide?"h":""]mvalve[open]"
|
||||
|
||||
initialize()
|
||||
normalize_dir()
|
||||
var/node1_dir
|
||||
var/node2_dir
|
||||
|
||||
for(var/direction in cardinal)
|
||||
if(direction&initialize_mains_directions)
|
||||
if (!node1_dir)
|
||||
node1_dir = direction
|
||||
else if (!node2_dir)
|
||||
node2_dir = direction
|
||||
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node1_dir))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[1] = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node2_dir))
|
||||
if(target.initialize_mains_directions & get_dir(target,src))
|
||||
nodes[2] = target
|
||||
break
|
||||
|
||||
if(open)
|
||||
..() // initialize internal pipes
|
||||
|
||||
update_icon()
|
||||
|
||||
proc/normalize_dir()
|
||||
if(dir==3)
|
||||
dir = 1
|
||||
else if(dir==12)
|
||||
dir = 4
|
||||
|
||||
proc/open()
|
||||
if(open) return 0
|
||||
|
||||
open = 1
|
||||
update_icon()
|
||||
|
||||
initialize()
|
||||
|
||||
return 1
|
||||
|
||||
proc/close()
|
||||
if(!open) return 0
|
||||
|
||||
open = 0
|
||||
update_icon()
|
||||
|
||||
for(var/obj/machinery/atmospherics/pipe/mains_component/node in src)
|
||||
for(var/obj/machinery/atmospherics/pipe/mains_component/o in node.nodes)
|
||||
o.disconnect(node)
|
||||
o.build_network()
|
||||
|
||||
return 1
|
||||
|
||||
attack_ai(mob/user as mob)
|
||||
return
|
||||
|
||||
attack_paw(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
src.add_fingerprint(usr)
|
||||
update_icon(1)
|
||||
sleep(10)
|
||||
if (open)
|
||||
close()
|
||||
else
|
||||
open()
|
||||
|
||||
digital // can be controlled by AI
|
||||
name = "digital mains valve"
|
||||
desc = "A digitally controlled valve."
|
||||
icon_state = "dvalve0"
|
||||
|
||||
attack_ai(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
..()
|
||||
|
||||
//Radio remote control
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
|
||||
update_icon(animation)
|
||||
var/turf/simulated/floor = loc
|
||||
var/hide = istype(floor) ? floor.intact : 0
|
||||
level = 1
|
||||
for(var/obj/machinery/atmospherics/mains_pipe/node in nodes)
|
||||
if(node.level == 2)
|
||||
hide = 0
|
||||
level = 2
|
||||
break
|
||||
|
||||
if(animation)
|
||||
flick("[hide?"h":""]dvalve[src.open][!src.open]",src)
|
||||
else
|
||||
icon_state = "[hide?"h":""]dvalve[open]"
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id))
|
||||
return 0
|
||||
|
||||
switch(signal.data["command"])
|
||||
if("valve_open")
|
||||
if(!open)
|
||||
open()
|
||||
|
||||
if("valve_close")
|
||||
if(open)
|
||||
close()
|
||||
|
||||
if("valve_toggle")
|
||||
if(open)
|
||||
close()
|
||||
else
|
||||
open()
|
||||
@@ -0,0 +1,28 @@
|
||||
/datum/paiCandidate/chatbot
|
||||
name = "NT Standard Chatbot"
|
||||
description = "NT Standard Issue pAI Unit 13A"
|
||||
role = "Advisor"
|
||||
comments = "This is an actual AI."
|
||||
ready = 1
|
||||
|
||||
/mob/living/silicon/pai/chatbot
|
||||
var/datum/text_parser/parser/eliza/P = new()
|
||||
|
||||
proc/init()
|
||||
P.speaker = src
|
||||
P.callsign = input("What do you want to call me?", "Chatbot Name", "NT") as text
|
||||
P.set_name(P.callsign)
|
||||
P.new_session()
|
||||
|
||||
proc/hear_talk(mob/M, text)
|
||||
if(stat)
|
||||
return
|
||||
|
||||
var/prefix = P.callsign + ","
|
||||
|
||||
if(lentext(text) <= lentext(prefix))
|
||||
return
|
||||
var/i = lentext(prefix) + 1
|
||||
if(cmptext(copytext(text, 1, i), prefix))
|
||||
P.input_line = html_decode(copytext(text, i))
|
||||
P.process_line()
|
||||
@@ -0,0 +1,231 @@
|
||||
// a frame for generic wall-mounted things, such as fire alarm, status display..
|
||||
// combination of apc_frame and machine_frame
|
||||
/obj/machinery/constructable_frame/wallmount_frame
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
icon_state = "wm_0"
|
||||
var/wall_offset = 24
|
||||
density = 0
|
||||
|
||||
/obj/machinery/constructable_frame/wallmount_frame/New()
|
||||
spawn(1)
|
||||
if (!istype(loc, /turf/simulated/floor))
|
||||
usr << "\red [name] cannot be placed on this spot."
|
||||
new/obj/item/stack/sheet/metal(get_turf(src), 2)
|
||||
del(src)
|
||||
return
|
||||
|
||||
var/turf/obj_ofs = get_step(locate(2,2,1), dir)
|
||||
pixel_x = (obj_ofs.x - 2) * wall_offset
|
||||
pixel_y = (obj_ofs.y - 2) * wall_offset
|
||||
|
||||
var/turf/T = get_step(usr, dir)
|
||||
if(!istype(T, /turf/simulated/wall))
|
||||
usr << "\red [name] must be placed on a wall."
|
||||
new/obj/item/stack/sheet/metal(get_turf(src), 2)
|
||||
del(src)
|
||||
return
|
||||
|
||||
dir = get_dir(T, loc)
|
||||
|
||||
/obj/machinery/constructable_frame/wallmount_frame/attackby(obj/item/P as obj, mob/user as mob)
|
||||
if(P.crit_fail)
|
||||
user << "\red This part is faulty, you cannot add this to the machine!"
|
||||
return
|
||||
switch(state)
|
||||
if(1)
|
||||
if(istype(P, /obj/item/weapon/cable_coil))
|
||||
if(P:amount >= 5)
|
||||
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
user << "\blue You start to add cables to the frame."
|
||||
if(do_after(user, 20))
|
||||
P:amount -= 5
|
||||
if(!P:amount) del(P)
|
||||
user << "\blue You add cables to the frame."
|
||||
state = 2
|
||||
icon_state = "wm_1"
|
||||
if(istype(P, /obj/item/weapon/wrench))
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
|
||||
user << "\blue You dismantle the frame"
|
||||
new /obj/item/stack/sheet/metal(src.loc, 2)
|
||||
del(src)
|
||||
if(2)
|
||||
if(istype(P, /obj/item/weapon/circuitboard))
|
||||
var/obj/item/weapon/circuitboard/B = P
|
||||
if(B.board_type == "wallmount")
|
||||
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
user << "\blue You add the circuit board to the frame."
|
||||
circuit = P
|
||||
user.drop_item()
|
||||
P.loc = src
|
||||
icon_state = "wm_2"
|
||||
state = 3
|
||||
components = list()
|
||||
req_components = circuit.req_components.Copy()
|
||||
for(var/A in circuit.req_components)
|
||||
req_components[A] = circuit.req_components[A]
|
||||
req_component_names = circuit.req_components.Copy()
|
||||
for(var/A in req_components)
|
||||
var/cp = text2path(A)
|
||||
var/obj/ct = new cp() // have to quickly instantiate it get name
|
||||
req_component_names[A] = ct.name
|
||||
if(circuit.frame_desc)
|
||||
desc = circuit.frame_desc
|
||||
else
|
||||
update_desc()
|
||||
user << desc
|
||||
else
|
||||
user << "\red This frame does not accept circuit boards of this type!"
|
||||
if(istype(P, /obj/item/weapon/wirecutters))
|
||||
playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
|
||||
user << "\blue You remove the cables."
|
||||
state = 1
|
||||
icon_state = "wm_0"
|
||||
var/obj/item/weapon/cable_coil/A = new /obj/item/weapon/cable_coil( src.loc )
|
||||
A.amount = 5
|
||||
|
||||
if(3)
|
||||
if(istype(P, /obj/item/weapon/crowbar))
|
||||
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
|
||||
state = 2
|
||||
circuit.loc = src.loc
|
||||
circuit = null
|
||||
if(components.len == 0)
|
||||
user << "\blue You remove the circuit board."
|
||||
else
|
||||
user << "\blue You remove the circuit board and other components."
|
||||
for(var/obj/item/weapon/W in components)
|
||||
W.loc = src.loc
|
||||
desc = initial(desc)
|
||||
req_components = null
|
||||
components = null
|
||||
icon_state = "wm_1"
|
||||
|
||||
if(istype(P, /obj/item/weapon/screwdriver))
|
||||
var/component_check = 1
|
||||
for(var/R in req_components)
|
||||
if(req_components[R] > 0)
|
||||
component_check = 0
|
||||
break
|
||||
if(component_check)
|
||||
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
var/obj/machinery/new_machine = new src.circuit.build_path(src.loc)
|
||||
new_machine.dir = dir
|
||||
if(istype(circuit, /obj/item/weapon/circuitboard/status_display))
|
||||
new_machine.pixel_x = pixel_x * 1.33
|
||||
new_machine.pixel_y = pixel_y * 1.33
|
||||
else
|
||||
new_machine.pixel_x = pixel_x
|
||||
new_machine.pixel_y = pixel_y
|
||||
for(var/obj/O in new_machine.component_parts)
|
||||
del(O)
|
||||
new_machine.component_parts = list()
|
||||
for(var/obj/O in src)
|
||||
if(circuit.contain_parts) // things like disposal don't want their parts in them
|
||||
O.loc = new_machine
|
||||
else
|
||||
O.loc = null
|
||||
new_machine.component_parts += O
|
||||
if(circuit.contain_parts)
|
||||
circuit.loc = new_machine
|
||||
else
|
||||
circuit.loc = null
|
||||
new_machine.RefreshParts()
|
||||
del(src)
|
||||
|
||||
if(istype(P, /obj/item/weapon))
|
||||
for(var/I in req_components)
|
||||
if(istype(P, text2path(I)) && (req_components[I] > 0))
|
||||
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
if(istype(P, /obj/item/weapon/cable_coil))
|
||||
var/obj/item/weapon/cable_coil/CP = P
|
||||
if(CP.amount > 1)
|
||||
var/camt = min(CP.amount, req_components[I]) // amount of cable to take, idealy amount required, but limited by amount provided
|
||||
var/obj/item/weapon/cable_coil/CC = new /obj/item/weapon/cable_coil(src)
|
||||
CC.amount = camt
|
||||
CC.update_icon()
|
||||
CP.use(camt)
|
||||
components += CC
|
||||
req_components[I] -= camt
|
||||
update_desc()
|
||||
break
|
||||
user.drop_item()
|
||||
P.loc = src
|
||||
components += P
|
||||
req_components[I]--
|
||||
update_desc()
|
||||
break
|
||||
user << desc
|
||||
if(P.loc != src && !istype(P, /obj/item/weapon/cable_coil))
|
||||
user << "\red You cannot add that component to the machine!"
|
||||
|
||||
/obj/item/weapon/circuitboard/firealarm
|
||||
name = "Circuit board (Fire Alarm)"
|
||||
build_path = "/obj/machinery/firealarm"
|
||||
board_type = "wallmount"
|
||||
origin_tech = "engineering=2"
|
||||
frame_desc = "Requires 1 Scanning Module, 1 Capacitor, and 2 pieces of cable."
|
||||
contain_parts = 0
|
||||
req_components = list(
|
||||
"/obj/item/weapon/stock_parts/scanning_module" = 1,
|
||||
"/obj/item/weapon/stock_parts/capacitor" = 1,
|
||||
"/obj/item/weapon/cable_coil" = 2)
|
||||
|
||||
/obj/item/weapon/circuitboard/alarm
|
||||
name = "Circuit board (Atmospheric Alarm)"
|
||||
build_path = "/obj/machinery/alarm"
|
||||
board_type = "wallmount"
|
||||
origin_tech = "engineering=2;programming=2"
|
||||
frame_desc = "Requires 1 Scanning Module, 1 Console Screen, and 2 pieces of cable."
|
||||
contain_parts = 0
|
||||
req_components = list(
|
||||
"/obj/item/weapon/stock_parts/scanning_module" = 1,
|
||||
"/obj/item/weapon/stock_parts/console_screen" = 1,
|
||||
"/obj/item/weapon/cable_coil" = 2)
|
||||
|
||||
/* oh right, not a machine :(
|
||||
/obj/item/weapon/circuitboard/intercom
|
||||
name = "Circuit board (Intercom)"
|
||||
build_path = "/obj/item/device/radio/intercom"
|
||||
board_type = "wallmount"
|
||||
origin_tech = "engineering=2"
|
||||
frame_desc = "Requires 1 Console Screen, and 2 piece of cable."
|
||||
contain_parts = 0
|
||||
req_components = list(
|
||||
"/obj/item/weapon/stock_parts/console_screen" = 1,
|
||||
"/obj/item/weapon/cable_coil" = 2)
|
||||
*/
|
||||
|
||||
/* too complex to set up the dept for an RC in a way intuitive for the user
|
||||
/obj/item/weapon/circuitboard/requests_console
|
||||
name = "Circuit board (Requests Console)"
|
||||
build_path = "/obj/machinery/requests_console"
|
||||
board_type = "wallmount"
|
||||
origin_tech = "engineering=2;programming=2"
|
||||
frame_desc = "Requires 1 radio, 1 Console Screen, and 1 piece of cable."
|
||||
contain_parts = 0
|
||||
req_components = list(
|
||||
"/obj/item/device/radio" = 1,
|
||||
"/obj/item/weapon/stock_parts/console_screen" = 1
|
||||
"/obj/item/weapon/cable_coil" = 1)
|
||||
*/
|
||||
|
||||
/obj/item/weapon/circuitboard/status_display
|
||||
name = "Circuit board (Status Display)"
|
||||
build_path = "/obj/machinery/status_display"
|
||||
board_type = "wallmount"
|
||||
origin_tech = "engineering=2,programming=2"
|
||||
frame_desc = "Requires 2 Console Screens, and 1 piece of cable."
|
||||
contain_parts = 0
|
||||
req_components = list(
|
||||
"/obj/item/weapon/stock_parts/console_screen" = 2,
|
||||
"/obj/item/weapon/cable_coil" = 1)
|
||||
|
||||
/obj/item/weapon/circuitboard/light_switch
|
||||
name = "Circuit board (Light Switch)"
|
||||
build_path = "/obj/machinery/light_switch"
|
||||
board_type = "wallmount"
|
||||
origin_tech = "engineering=2"
|
||||
frame_desc = "Requires 2 pieces of cable."
|
||||
contain_parts = 0
|
||||
req_components = list(
|
||||
"/obj/item/weapon/cable_coil" = 2)
|
||||
Reference in New Issue
Block a user