Telecomms Refactor & CodeMirror

This commit does the following:
 - A lot of shit I am really too tired to fucking write about
 - Absolute pathed telecomms scripting
 - Browser Datum traffic control
  - Absolutely lovely replacement for the fucking skin TCS window, using
    codemirror
 - CodeMirror integration for nanoUI
  - Sorta, I didn't work on this as much as I wanted to, because IT TOOK
    11 FUCKING HOURS TO GET THE BROWSER DATUM TO WORK
This commit is contained in:
Tigercat2000
2015-10-28 17:19:18 -07:00
parent f76109ca5c
commit c244a0fe15
38 changed files with 13973 additions and 2155 deletions
@@ -4,253 +4,312 @@
/* --- Traffic Control Scripting Language --- */
// Nanotrasen TCS Language - Made by Doohl
/n_Interpreter/TCS_Interpreter
/datum/n_Interpreter/TCS_Interpreter
var/datum/TCS_Compiler/Compiler
HandleError(runtimeError/e)
Compiler.Holder.add_entry(e.ToString(), "Execution Error")
/datum/n_Interpreter/TCS_Interpreter/HandleError(datum/runtimeError/e)
Compiler.Holder.add_entry(e.ToString(), "Execution Error")
/datum/n_Interpreter/TCS_Interpreter/GC()
..()
Compiler = null
/datum/TCS_Compiler
var/n_Interpreter/TCS_Interpreter/interpreter
var/datum/n_Interpreter/TCS_Interpreter/interpreter
var/obj/machinery/telecomms/server/Holder // the server that is running the code
var/ready = 1 // 1 if ready to run code
/* -- Set ourselves to Garbage Collect -- */
/datum/TCS_Compiler/proc/GC()
Holder = null
if(interpreter)
interpreter.GC()
/* -- Compile a raw block of text -- */
proc/Compile(code as message)
var/n_scriptOptions/nS_Options/options = new()
var/n_Scanner/nS_Scanner/scanner = new(code, options)
var/list/tokens = scanner.Scan()
var/n_Parser/nS_Parser/parser = new(tokens, options)
var/node/BlockDefinition/GlobalBlock/program = parser.Parse()
/datum/TCS_Compiler/proc/Compile(code as message)
var/datum/n_scriptOptions/nS_Options/options = new()
var/datum/n_Scanner/nS_Scanner/scanner = new(code, options)
var/list/tokens = scanner.Scan()
var/datum/n_Parser/nS_Parser/parser = new(tokens, options)
var/datum/node/BlockDefinition/GlobalBlock/program = parser.Parse()
var/list/returnerrors = list()
var/list/returnerrors = list()
returnerrors += scanner.errors
returnerrors += parser.errors
if(returnerrors.len)
return returnerrors
interpreter = new(program)
interpreter.persist = 1
interpreter.Compiler= src
returnerrors += scanner.errors
returnerrors += parser.errors
if(returnerrors.len)
return returnerrors
/* -- Execute the compiled code -- */
interpreter = new(program)
interpreter.persist = 1
interpreter.Compiler= src
proc/Run(var/datum/signal/signal)
return returnerrors
if(!ready)
return
/* -- Execute the compiled code -- */
if(!interpreter)
return
/datum/TCS_Compiler/proc/Run(var/datum/signal/signal)
if(!ready)
return
interpreter.container = src
if(!interpreter)
return
interpreter.SetVar("PI" , 3.141592653) // value of pi
interpreter.SetVar("E" , 2.718281828) // value of e
interpreter.SetVar("SQURT2" , 1.414213562) // value of the square root of 2
interpreter.SetVar("FALSE" , 0) // boolean shortcut to 0
interpreter.SetVar("TRUE" , 1) // boolean shortcut to 1
interpreter.container = src
interpreter.SetVar("NORTH" , NORTH) // NORTH (1)
interpreter.SetVar("SOUTH" , SOUTH) // SOUTH (2)
interpreter.SetVar("EAST" , EAST) // EAST (4)
interpreter.SetVar("WEST" , WEST) // WEST (8)
interpreter.SetVar("PI", 3.141592653) // value of pi
interpreter.SetVar("E", 2.718281828) // value of e
interpreter.SetVar("SQURT2", 1.414213562) // value of the square root of 2
interpreter.SetVar("FALSE", 0) // boolean shortcut to 0
interpreter.SetVar("false", 0) // boolean shortcut to 0
interpreter.SetVar("TRUE", 1) // boolean shortcut to 1
interpreter.SetVar("true", 1) // boolean shortcut to 1
// Channel macros
interpreter.SetVar("$common", PUB_FREQ)
interpreter.SetVar("$science", SCI_FREQ)
interpreter.SetVar("$command", COMM_FREQ)
interpreter.SetVar("$medical", MED_FREQ)
interpreter.SetVar("$engineering", ENG_FREQ)
interpreter.SetVar("$security", SEC_FREQ)
interpreter.SetVar("$supply", SUP_FREQ)
interpreter.SetVar("$service", SRV_FREQ)
// Signal data
interpreter.SetVar("NORTH", NORTH) // NORTH (1)
interpreter.SetVar("SOUTH", SOUTH) // SOUTH (2)
interpreter.SetVar("EAST", EAST) // EAST (4)
interpreter.SetVar("WEST", WEST) // WEST (8)
interpreter.SetVar("$content", signal.data["message"])
interpreter.SetVar("$freq" , signal.frequency)
interpreter.SetVar("$source" , signal.data["name"])
interpreter.SetVar("$job" , signal.data["job"])
interpreter.SetVar("$sign" , signal)
interpreter.SetVar("$pass" , !(signal.data["reject"])) // if the signal isn't rejected, pass = 1; if the signal IS rejected, pass = 0
var/datum/language/speaking = signal.data["language"]
if(speaking)
interpreter.SetVar("$language", speaking.name)
else
interpreter.SetVar("$language", "Unknown")
// Channel macros
interpreter.SetVar("$common", PUB_FREQ)
interpreter.SetVar("$science", SCI_FREQ)
interpreter.SetVar("$command", COMM_FREQ)
interpreter.SetVar("$medical", MED_FREQ)
interpreter.SetVar("$engineering", ENG_FREQ)
interpreter.SetVar("$security", SEC_FREQ)
interpreter.SetVar("$supply", SUP_FREQ)
interpreter.SetVar("$service", SRV_FREQ)
// Set up the script procs
// Signal data
/*
-> Send another signal to a server
@format: broadcast(content, frequency, source, job)
interpreter.SetVar("$content", signal.data["message"])
interpreter.SetVar("$freq", signal.frequency)
interpreter.SetVar("$source", signal.data["name"])
interpreter.SetVar("$job", signal.data["job"])
interpreter.SetVar("$sign", signal)
interpreter.SetVar("$pass", !(signal.data["reject"])) // if the signal isn't rejected, pass = 1; if the signal IS rejected, pass = 0
@param content: Message to broadcast
@param frequency: Frequency to broadcast to
@param source: The name of the source you wish to imitate. Must be stored in stored_names list.
@param job: The name of the job.
*/
interpreter.SetProc("broadcast", "tcombroadcast", signal, list("message", "freq", "source", "job"))
var/datum/language/speaking = signal.data["language"]
if(speaking)
interpreter.SetVar("$language", speaking.name)
else
interpreter.SetVar("$language", "Unknown")
/*
-> Store a value permanently to the server machine (not the actual game hosting machine, the ingame machine)
@format: mem(address, value)
// Set up the script procs
@param address: The memory address (string index) to store a value to
@param value: The value to store to the memory address
*/
interpreter.SetProc("mem", "mem", signal, list("address", "value"))
/*
-> Send another signal to a server
@format: broadcast(content, frequency, source, job)
/* -- Clone functions, carried from default BYOND procs --- */
// Vector
interpreter.SetProc("vector", /proc/n_list)
interpreter.SetProc("at", /proc/n_listpos)
interpreter.SetProc("copy", /proc/n_listcopy)
interpreter.SetProc("push_back", /proc/n_listadd)
interpreter.SetProc("remove", /proc/n_listremove)
interpreter.SetProc("cut", /proc/n_listcut)
interpreter.SetProc("swap", /proc/n_listswap)
interpreter.SetProc("insert", /proc/n_listinsert)
interpreter.SetProc("pick", /proc/n_pick)
interpreter.SetProc("prob", /proc/n_prob)
interpreter.SetProc("substr", /proc/n_substr)
interpreter.SetProc("find", /proc/n_smartfind)
interpreter.SetProc("length", /proc/n_smartlength)
@param content: Message to broadcast
@param frequency: Frequency to broadcast to
@param source: The name of the source you wish to imitate. Must be stored in stored_names list.
@param job: The name of the job.
*/
interpreter.SetProc("broadcast", "tcombroadcast", signal, list("message", "freq", "source", "job"))
// Strings
interpreter.SetProc("lower", /proc/n_lower)
interpreter.SetProc("upper", /proc/n_upper)
interpreter.SetProc("explode", /proc/n_explode)
interpreter.SetProc("implode", /proc/n_implode)
interpreter.SetProc("repeat", /proc/n_repeat)
interpreter.SetProc("reverse", /proc/n_reverse)
interpreter.SetProc("tonum", /proc/n_str2num)
interpreter.SetProc("replace", /proc/n_replace)
interpreter.SetProc("proper", /proc/n_proper)
/*
-> Store a value permanently to the server machine (not the actual game hosting machine, the ingame machine)
@format: mem(address, value)
// Numbers
interpreter.SetProc("tostring", /proc/n_num2str)
interpreter.SetProc("sqrt", /proc/n_sqrt)
interpreter.SetProc("abs", /proc/n_abs)
interpreter.SetProc("floor", /proc/n_floor)
interpreter.SetProc("ceil", /proc/n_ceil)
interpreter.SetProc("round", /proc/n_round)
interpreter.SetProc("clamp", /proc/n_clamp)
interpreter.SetProc("inrange", /proc/n_inrange)
interpreter.SetProc("rand", /proc/n_rand)
interpreter.SetProc("randseed", /proc/n_randseed)
interpreter.SetProc("min", /proc/n_min)
interpreter.SetProc("max", /proc/n_max)
interpreter.SetProc("sin", /proc/n_sin)
interpreter.SetProc("cos", /proc/n_cos)
interpreter.SetProc("asin", /proc/n_asin)
interpreter.SetProc("acos", /proc/n_acos)
interpreter.SetProc("log", /proc/n_log)
@param address: The memory address (string index) to store a value to
@param value: The value to store to the memory address
*/
interpreter.SetProc("mem", "mem", signal, list("address", "value"))
// Time
interpreter.SetProc("time", /proc/n_time)
interpreter.SetProc("sleep", /proc/n_delay)
interpreter.SetProc("timestamp", /proc/gameTimestamp)
/*
-> Delay code for a given amount of deciseconds
@format: sleep(time)
// Run the compiled code
interpreter.Run()
@param time: time to sleep in deciseconds (1/10th second)
*/
interpreter.SetProc("sleep", /proc/delay)
// Backwards-apply variables onto signal data
/* sanitize EVERYTHING. fucking players can't be trusted with SHIT */
/*
-> Replaces a string with another string
@format: replace(string, substring, replacestring)
signal.data["message"] = interpreter.GetVar("$content")
signal.frequency = interpreter.GetVar("$freq")
@param string: the string to search for substrings (best used with $content$ constant)
@param substring: the substring to search for
@param replacestring: the string to replace the substring with
var/setname = ""
var/obj/machinery/telecomms/server/S = signal.data["server"]
if(interpreter.GetVar("$source") in S.stored_names)
setname = interpreter.GetVar("$source")
else
setname = "<i>[interpreter.GetVar("$source")]</i>"
*/
interpreter.SetProc("replace", /proc/replacetext)
if(signal.data["name"] != setname)
signal.data["realname"] = setname
signal.data["name"] = setname
signal.data["job"] = interpreter.GetVar("$job")
signal.data["reject"] = !(interpreter.GetVar("$pass")) // set reject to the opposite of $pass
/*
-> Locates an element/substring inside of a list or string
@format: find(haystack, needle, start = 1, end = 0)
// If the message is invalid, just don't broadcast it!
if(signal.data["message"] == "" || !signal.data["message"])
signal.data["reject"] = 1
@param haystack: the container to search
@param needle: the element to search for
@param start: the position to start in
@param end: the position to end in
*/
interpreter.SetProc("find", /proc/smartfind)
/*
-> Finds the length of a string or list
@format: length(container)
@param container: the list or container to measure
*/
interpreter.SetProc("length", /proc/smartlength)
/* -- Clone functions, carried from default BYOND procs --- */
// vector namespace
interpreter.SetProc("vector", /proc/n_list)
interpreter.SetProc("at", /proc/n_listpos)
interpreter.SetProc("copy", /proc/n_listcopy)
interpreter.SetProc("push_back", /proc/n_listadd)
interpreter.SetProc("remove", /proc/n_listremove)
interpreter.SetProc("cut", /proc/n_listcut)
interpreter.SetProc("swap", /proc/n_listswap)
interpreter.SetProc("insert", /proc/n_listinsert)
interpreter.SetProc("pick", /proc/n_pick)
interpreter.SetProc("prob", /proc/prob_chance)
interpreter.SetProc("substr", /proc/docopytext)
interpreter.SetProc("shuffle", /proc/shuffle)
interpreter.SetProc("uniquevector", /proc/uniquelist)
interpreter.SetProc("text2vector", /proc/text2list)
interpreter.SetProc("text2vectorEx",/proc/text2listEx)
interpreter.SetProc("vector2text", /proc/list2text)
// Donkie~
// Strings
interpreter.SetProc("lower", /proc/n_lower)
interpreter.SetProc("upper", /proc/n_upper)
interpreter.SetProc("explode", /proc/string_explode)
interpreter.SetProc("implode", /proc/list2text)
interpreter.SetProc("repeat", /proc/n_repeat)
interpreter.SetProc("reverse", /proc/reverse_text)
interpreter.SetProc("tonum", /proc/n_str2num)
interpreter.SetProc("capitalize", /proc/capitalize)
interpreter.SetProc("replacetextEx",/proc/replacetextEx)
// Numbers
interpreter.SetProc("tostring", /proc/n_num2str)
interpreter.SetProc("sqrt", /proc/n_sqrt)
interpreter.SetProc("abs", /proc/n_abs)
interpreter.SetProc("floor", /proc/Floor)
interpreter.SetProc("ceil", /proc/Ceiling)
interpreter.SetProc("round", /proc/n_round)
interpreter.SetProc("clamp", /proc/n_clamp)
interpreter.SetProc("inrange", /proc/IsInRange)
interpreter.SetProc("rand", /proc/rand_chance)
interpreter.SetProc("arctan", /proc/Atan2)
interpreter.SetProc("lcm", /proc/Lcm)
interpreter.SetProc("gcd", /proc/Gcd)
interpreter.SetProc("mean", /proc/Mean)
interpreter.SetProc("root", /proc/Root)
interpreter.SetProc("sin", /proc/n_sin)
interpreter.SetProc("cos", /proc/n_cos)
interpreter.SetProc("arcsin", /proc/n_asin)
interpreter.SetProc("arccos", /proc/n_acos)
interpreter.SetProc("tan", /proc/Tan)
interpreter.SetProc("csc", /proc/Csc)
interpreter.SetProc("cot", /proc/Cot)
interpreter.SetProc("sec", /proc/Sec)
interpreter.SetProc("todegrees", /proc/ToDegrees)
interpreter.SetProc("toradians", /proc/ToRadians)
interpreter.SetProc("lerp", /proc/Lerp)
interpreter.SetProc("max", /proc/n_max)
interpreter.SetProc("min", /proc/n_min)
// End of Donkie~
// Time
interpreter.SetProc("time", /proc/time)
interpreter.SetProc("timestamp", /proc/timestamp)
// Run the compiled code
interpreter.Run()
// Backwards-apply variables onto signal data
/* sanitize EVERYTHING. fucking players can't be trusted with SHIT */
/* Okay, so, the original 'sanitizing' code... did fucking nothing. Then PJB fixed it, which means no HTML.
But I like HTML, so back to no sanitizing.*/
signal.data["message"] = interpreter.GetVar("$content", signal.data["message"])
signal.frequency = interpreter.GetCleanVar("$freq", signal.frequency)
var/setname = interpreter.GetVar("$source", signal.data["name"])
if(signal.data["name"] != setname)
signal.data["realname"] = setname
signal.data["name"] = setname
signal.data["job"] = interpreter.GetVar("$job", signal.data["job"])
signal.data["reject"] = !(interpreter.GetCleanVar("$pass")) // set reject to the opposite of $pass
// If the message is invalid, just don't broadcast it!
if(signal.data["message"] == "" || !signal.data["message"])
signal.data["reject"] = 1
/* -- Actual language proc code -- */
datum/signal
proc/mem(var/address, var/value)
if(istext(address))
var/obj/machinery/telecomms/server/S = data["server"]
if(!value && value != 0)
return S.memory[address]
else
S.memory[address] = value
proc/tcombroadcast(var/message, var/freq, var/source, var/job)
var/datum/signal/newsign = new
/datum/signal/proc/mem(var/address, var/value)
if(istext(address))
var/obj/machinery/telecomms/server/S = data["server"]
var/obj/item/device/radio/hradio = S.server_radio
if(!hradio)
error("[src] has no radio.")
return
if(!value && value != 0)
return S.memory[address]
if((!message || message == "") && message != 0)
message = "*beep*"
if(!source)
source = "[html_encode(uppertext(S.id))]"
hradio = new // sets the hradio as a radio intercom
if(!freq)
freq = 1459
if(findtext(num2text(freq), ".")) // if the frequency has been set as a decimal
freq *= 10 // shift the decimal one place
if(!job)
job = "?"
newsign.data["mob"] = null
newsign.data["mobtype"] = /mob/living/carbon/human
if(source in S.stored_names)
newsign.data["name"] = source
else
newsign.data["name"] = "<i>[html_encode(uppertext(source))]<i>"
newsign.data["realname"] = newsign.data["name"]
newsign.data["job"] = job
newsign.data["compression"] = 0
newsign.data["message"] = message
newsign.data["type"] = 2 // artificial broadcast
if(!isnum(freq))
freq = text2num(freq)
newsign.frequency = freq
S.memory[address] = value
var/datum/radio_frequency/connection = radio_controller.return_frequency(freq)
newsign.data["connection"] = connection
/datum/signal/proc/tcombroadcast(var/message, var/freq, var/source, var/job)
var/datum/signal/newsign = new
var/obj/machinery/telecomms/server/S = data["server"]
var/obj/item/device/radio/hradio = S.server_radio
if(!hradio)
error("[src] has no radio.")
return
if((!message || message == "") && message != 0)
message = "*beep*"
if(!source)
source = "[html_encode(uppertext(S.id))]"
hradio = new // sets the hradio as a radio intercom
if(!freq || (!isnum(freq) && text2num(freq) == null))
freq = 1459
if(findtext(num2text(freq), ".")) // if the frequency has been set as a decimal
freq *= 10 // shift the decimal one place
if(!job)
job = "?"
newsign.data["mob"] = null
newsign.data["mobtype"] = /mob/living/carbon/human
newsign.data["name"] = source
newsign.data["realname"] = newsign.data["name"]
newsign.data["job"] = "[job]"
newsign.data["compression"] = 0
newsign.data["message"] = message
newsign.data["type"] = 2 // artificial broadcast
if(!isnum(freq))
freq = text2num(freq)
newsign.frequency = freq
var/datum/radio_frequency/connection = radio_controller.return_frequency(freq)
newsign.data["connection"] = connection
newsign.data["radio"] = hradio
newsign.data["vmessage"] = message
newsign.data["vname"] = source
newsign.data["vmask"] = 0
newsign.data["level"] = list()
var/pass = S.relay_information(newsign, "/obj/machinery/telecomms/hub")
if(!pass)
S.relay_information(newsign, "/obj/machinery/telecomms/broadcaster") // send this simple message to broadcasters
newsign.data["radio"] = hradio
newsign.data["vmessage"] = message
newsign.data["vname"] = source
newsign.data["vmask"] = 0
newsign.data["level"] = data["level"]
var/pass = S.relay_information(newsign, "/obj/machinery/telecomms/hub")
if(!pass)
S.relay_information(newsign, "/obj/machinery/telecomms/broadcaster") // send this simple message to broadcasters
+101 -154
View File
@@ -1,17 +1,18 @@
// Script -> BYOND code procs
#define SCRIPT_MAX_REPLACEMENTS_ALLOWED 200
// --- List operations (lists known as vectors in n_script) ---
// Creates a list out of all the arguments
// Clone of list()
/proc/n_list()
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/n_list() called tick#: [world.time]")
var/list/returnlist = list()
for(var/e in args)
returnlist.Add(e)
return returnlist
// Picks one random item from the list
// Clone of pick()
/proc/n_pick()
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/n_pick() called tick#: [world.time]")
var/list/finalpick = list()
for(var/e in args)
if(isobject(e))
@@ -24,15 +25,16 @@
return pick(finalpick)
// Gets/Sets a value at a key in the list
// Clone of list[]
/proc/n_listpos(var/list/L, var/pos, var/value)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/n_listpos() called tick#: [world.time]")
if(!istype(L, /list)) return
if(isnum(pos))
if(!value)
if(L.len >= pos)
if(L.len >= pos && !(pos > L.len))
return L[pos]
else
if(L.len >= pos)
if(L.len >= pos && !(pos > L.len))
L[pos] = value
else if(istext(pos))
if(!value)
@@ -40,13 +42,15 @@
else
L[pos] = value
// Copies the list into a new one
// Clone of list.Copy()
/proc/n_listcopy(var/list/L, var/start, var/end)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/n_listcopy() called tick#: [world.time]")
if(!istype(L, /list)) return
return L.Copy(start, end)
// Adds arg 2,3,4,5... to the end of list at arg 1
// Clone of list.Add()
/proc/n_listadd()
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/n_listadd() called tick#: [world.time]")
var/list/chosenlist
var/i = 1
for(var/e in args)
@@ -59,8 +63,9 @@
if(chosenlist)
chosenlist.Add(e)
// Removes arg 2,3,4,5... from list at arg 1
// Clone of list.Remove()
/proc/n_listremove()
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/n_listremove() called tick#: [world.time]")
var/list/chosenlist
var/i = 1
for(var/e in args)
@@ -73,26 +78,45 @@
if(chosenlist)
chosenlist.Remove(e)
// Cuts out a copy of a list
// Clone of list.len = 0
/proc/n_listcut(var/list/L, var/start, var/end)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/n_listcut() called tick#: [world.time]")
if(!istype(L, /list)) return
return L.Cut(start, end)
// Swaps two values in the list
// Clone of list.Swap()
/proc/n_listswap(var/list/L, var/firstindex, var/secondindex)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/n_listswap() called tick#: [world.time]")
if(!istype(L, /list)) return
if(L.len >= secondindex && L.len >= firstindex)
return L.Swap(firstindex, secondindex)
// Inserts a value into the list
// Clone of list.Insert()
/proc/n_listinsert(var/list/L, var/index, var/element)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/n_listinsert() called tick#: [world.time]")
if(!istype(L, /list)) return
return L.Insert(index, element)
// --- String methods ---
// --- Miscellaneous functions ---
//If list, finds a value in it, if text, finds a substring in it
/proc/n_smartfind(var/haystack, var/needle, var/start = 1, var/end = 0)
// Clone of sleep()
/proc/delay(var/time)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/delay() called tick#: [world.time]")
sleep(time)
// Clone of rand()
/proc/rand_chance(var/low = 0, var/high)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/rand_chance() called tick#: [world.time]")
return rand(low, high)
// Clone of prob()
/proc/prob_chance(var/chance)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/prob_chance() called tick#: [world.time]")
return prob(chance)
// Merge of list.Find() and findtext()
/proc/smartfind(var/haystack, var/needle, var/start = 1, var/end = 0)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/smartfind() called tick#: [world.time]")
if(haystack && needle)
if(isobject(haystack))
if(istype(haystack, /list))
@@ -104,41 +128,54 @@
if(istext(haystack))
if(length(haystack) >= end && start > 0)
return findtext(haystack, needle, start, end)
//Returns a substring of the string
/proc/n_substr(var/string, var/start = 1, var/end = 0)
// Clone of copytext()
/proc/docopytext(var/string, var/start = 1, var/end = 0)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/docopytext() called tick#: [world.time]")
if(istext(string) && isnum(start) && isnum(end))
if(start > 0)
return copytext(string, start, end)
//Returns the length of the string or list
/proc/n_smartlength(var/container)
// Clone of length()
/proc/smartlength(var/container)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/smartlength() called tick#: [world.time]")
if(container)
if(istype(container, /list) || istext(container))
return length(container)
return 0
//Lowercase all characters
// BY DONKIE~
// String stuff
/proc/n_lower(var/string)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/n_lower() called tick#: [world.time]")
if(istext(string))
return lowertext(string)
//Uppercase all characters
/proc/n_upper(var/string)
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/n_upper() called tick#: [world.time]")
if(istext(string))
return uppertext(string)
//Converts a string to a list
/proc/n_explode(var/string, var/separator = "")
/proc/time()
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/time() called tick#: [world.time]")
return world.time + (12 HOURS)
/proc/timestamp(var/format = "hh:mm:ss") // Get the game time in text
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/timestamp() called tick#: [world.time]")
return time2text(world.time + (10 HOURS), format) // Yes, 10, not 12 hours, for some reason time2text() is being moronic (T-thanks BYOND), and it's adding 2 hours to this, I don't even know either.
proc/string_explode(var/string, var/separator = "")
//writepanic("[__FILE__].[__LINE__] \\/proc/string_explode() called tick#: [world.time]")
if(istext(string) && (istext(separator) || isnull(separator)))
return text2list(string, separator)
//Converts a list to a string
/proc/n_implode(var/list/li, var/separator)
/proc/list_implode(var/list/li, var/separator)
if(istype(li) && (istext(separator) || isnull(separator)))
return list2text(li, separator)
//Repeats the string x times
/proc/n_repeat(var/string, var/amount)
proc/n_repeat(var/string, var/amount)
//writepanic("[__FILE__].[__LINE__] \\/proc/n_repeat() called tick#: [world.time]")
if(istext(string) && isnum(amount))
var/i
var/newstring = ""
@@ -151,166 +188,76 @@
return newstring
//Reverses the order of the string. "Clown" becomes "nwolC"
/proc/n_reverse(var/string)
if(istext(string))
var/newstring = ""
var/i
for(i=lentext(string), i>0, i--)
if(i>=1000)
break
newstring = newstring + copytext(string, i, i+1)
return newstring
// String -> Number
/proc/n_str2num(var/string)
// I don't know if it's neccesary to make my own proc, but I think I have to to be able to check for istext.
proc/n_str2num(var/string)
//writepanic("[__FILE__].[__LINE__] \\/proc/n_str2num() called tick#: [world.time]")
if(istext(string))
return text2num(string)
/proc/n_proper(var/string)
if(!istext(string))
return ""
// Clamps N between min and max
/proc/n_clamp(var/num, var/min = 0, var/max = 1)
if(isnum(num) && isnum(min) && isnum(max))
return Clamp(num, min, max)
return text("[][]", uppertext(copytext(string, 1, 2)), lowertext(copytext(string, 2)))
// --- Number methods ---
//Returns the highest value of the arguments
//Need custom functions here cause byond's min and max runtimes if you give them a string or list.
/proc/n_max()
if(args.len == 0)
return 0
var/max = args[1]
for(var/e in args)
if(isnum(e) && e > max)
max = e
return max
//Returns the lowest value of the arguments
/proc/n_min()
if(args.len == 0)
return 0
var/min = args[1]
for(var/e in args)
if(isnum(e) && e < min)
min = e
return min
/proc/n_prob(var/chance)
return prob(chance)
/proc/n_randseed(var/seed)
rand_seed(seed)
return 0
/proc/n_rand(var/low, var/high)
if(isnull(low) && isnull(high))
return rand()
return rand(low, high)
// Number shit
/proc/n_num2str(var/num)
proc/n_num2str(var/num)
//writepanic("[__FILE__].[__LINE__] \\/proc/n_num2str() called tick#: [world.time]")
if(isnum(num))
return num2text(num)
// Squareroot
/proc/n_sqrt(var/num)
proc/n_sqrt(var/num)
//writepanic("[__FILE__].[__LINE__] \\/proc/n_sqrt() called tick#: [world.time]")
if(isnum(num))
return sqrt(num)
// Magnitude of num
/proc/n_abs(var/num)
proc/n_abs(var/num)
//writepanic("[__FILE__].[__LINE__] \\/proc/n_abs() called tick#: [world.time]")
if(isnum(num))
return abs(num)
// Round down
/proc/n_floor(var/num)
proc/n_floor(var/num)
//writepanic("[__FILE__].[__LINE__] \\/proc/n_floor() called tick#: [world.time]")
if(isnum(num))
return round(num)
// Round up
/proc/n_ceil(var/num)
proc/n_ceil(var/num)
//writepanic("[__FILE__].[__LINE__] \\/proc/n_ceil() called tick#: [world.time]")
if(isnum(num))
return round(num)+1
// Round to nearest integer
/proc/n_round(var/num)
proc/n_round(var/num)
//writepanic("[__FILE__].[__LINE__] \\/proc/n_round() called tick#: [world.time]")
if(isnum(num))
if(num-round(num)<0.5)
return round(num)
return n_ceil(num)
return n_ceil(num)\
// Clamps N between min and max
/proc/n_clamp(var/num, var/min=-1, var/max=1)
if(isnum(num)&&isnum(min)&&isnum(max))
if(num<=min)
return min
if(num>=max)
return max
return num
// END OF BY DONKIE :(
// Returns 1 if N is inbetween Min and Max
/proc/n_inrange(var/num, var/min=-1, var/max=1)
if(isnum(num)&&isnum(min)&&isnum(max))
return ((min <= num) && (num <= max))
/proc/n_sin(var/const/x)
return sin(x)
// Returns the sine of num
/proc/n_sin(var/num)
if(isnum(num))
return sin(num)
/proc/n_cos(var/const/x)
return cos(x)
// Returns the cosine of num
/proc/n_cos(var/num)
if(isnum(num))
return cos(num)
/proc/n_asin(var/const/x)
return arcsin(x)
// Returns the arcsine of num
/proc/n_asin(var/num)
if(isnum(num)&&-1<=num&&num<=1)
return arcsin(num)
/proc/n_acos(var/const/x)
return arccos(x)
// Returns the arccosine of num
/proc/n_acos(var/num)
if(isnum(num)&&-1<=num&&num<=1)
return arccos(num)
// Returns the natural log of num
/proc/n_max(...)
return max(arglist(args))
/proc/n_min(...)
return min(arglist(args))
/proc/n_log(var/num)
if(isnum(num)&&0<num)
return log(num)
// Replace text
/proc/n_replace(text, find, replacement)
if(istext(text) && istext(find) && istext(replacement))
var/find_len = length(find)
if(find_len < 1) return text
. = ""
var/last_found = 1
var/count = 0
while(1)
count += 1
if(count > SCRIPT_MAX_REPLACEMENTS_ALLOWED)
break
var/found = findtext(text, find, last_found, 0)
. += copytext(text, last_found, found)
if(found)
. += replacement
last_found = found + find_len
continue
return
// --- Miscellaneous functions ---
/proc/n_time()
return world.timeofday
// Clone of sleep()
/proc/n_delay(var/time)
sleep(time)
if(isnum(num) && 0 < num)
return log(num)