mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
TG: More work done on Telecomms:
▫ Signals can now be rejected by Subspace broadcasters through a specific data[] parameter. ▫ Improved the log browser. ▫ Log browsers and telecommunication monitors no longer require access to use. You do need access to delete logs, however. ▫ Intercoms need power to work. They don't drain power, they just need a constant flow of equipment power. As such, that offline intercom sprite's now finally being put to use. Scripting language: ▫ Sorry about all the files; they're all necessary! It's important to notice that the basic structure of the scripting language code is not mine; I cannibalized the base structure from some obscure BYOND project. It's pretty well documented, and I'd say easier to browse through than atmos. Here's the basic deal: A compiler datum manages the relationships between the three main subsystems of a scripting language: the Scanner, the Parser, and the Interpreter. The Scanner splits raw text into token datums that the Parser can read. The Parser transforms the otherwise random bits and strings into ordered AST Trees and nodes for the Interpreter to read. The interpreter actually executes the code and handles scope/functions/code blocks. Revision: r3193 Author: vageyenaman
This commit is contained in:
@@ -14,7 +14,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
|||||||
last_transmission
|
last_transmission
|
||||||
frequency = 1459 //common chat
|
frequency = 1459 //common chat
|
||||||
traitor_frequency = 0 //tune to frequency to unlock traitor supplies
|
traitor_frequency = 0 //tune to frequency to unlock traitor supplies
|
||||||
canhear_range = 3
|
canhear_range = 3 // the range which mobs can hear this radio from
|
||||||
obj/item/device/radio/patch_link = null
|
obj/item/device/radio/patch_link = null
|
||||||
obj/item/device/uplink/radio/traitorradio = null
|
obj/item/device/uplink/radio/traitorradio = null
|
||||||
wires = WIRE_SIGNAL | WIRE_RECEIVE | WIRE_TRANSMIT
|
wires = WIRE_SIGNAL | WIRE_RECEIVE | WIRE_TRANSMIT
|
||||||
@@ -63,6 +63,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
|||||||
checkpower()
|
checkpower()
|
||||||
|
|
||||||
/obj/item/device/radio/initialize()
|
/obj/item/device/radio/initialize()
|
||||||
|
|
||||||
if(freerange)
|
if(freerange)
|
||||||
if(frequency < 1200 || frequency > 1600)
|
if(frequency < 1200 || frequency > 1600)
|
||||||
frequency = sanitize_frequency(frequency)
|
frequency = sanitize_frequency(frequency)
|
||||||
@@ -145,6 +146,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
|||||||
//..()
|
//..()
|
||||||
if (usr.stat || !on)
|
if (usr.stat || !on)
|
||||||
return
|
return
|
||||||
|
|
||||||
if (!(issilicon(usr) || (usr.contents.Find(src) || ( in_range(src, usr) && istype(loc, /turf) ))))
|
if (!(issilicon(usr) || (usr.contents.Find(src) || ( in_range(src, usr) && istype(loc, /turf) ))))
|
||||||
usr << browse(null, "window=radio")
|
usr << browse(null, "window=radio")
|
||||||
return
|
return
|
||||||
@@ -155,6 +157,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
|||||||
if(A && target)
|
if(A && target)
|
||||||
A.ai_actual_track(target)
|
A.ai_actual_track(target)
|
||||||
return
|
return
|
||||||
|
|
||||||
else if (href_list["faketrack"])
|
else if (href_list["faketrack"])
|
||||||
var/mob/target = locate(href_list["track"])
|
var/mob/target = locate(href_list["track"])
|
||||||
var/mob/living/silicon/ai/A = locate(href_list["track2"])
|
var/mob/living/silicon/ai/A = locate(href_list["track2"])
|
||||||
@@ -169,7 +172,9 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
|||||||
usr << "Target is not on or near any active cameras on the station. We'll check again in 5 seconds (unless you use the cancel-camera verb)."
|
usr << "Target is not on or near any active cameras on the station. We'll check again in 5 seconds (unless you use the cancel-camera verb)."
|
||||||
sleep(40)
|
sleep(40)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
else if (href_list["freq"])
|
else if (href_list["freq"])
|
||||||
var/new_frequency = (frequency + text2num(href_list["freq"]))
|
var/new_frequency = (frequency + text2num(href_list["freq"]))
|
||||||
if (!freerange || (frequency < 1200 || frequency > 1600))
|
if (!freerange || (frequency < 1200 || frequency > 1600))
|
||||||
@@ -248,6 +253,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
|||||||
return
|
return
|
||||||
|
|
||||||
/obj/item/device/radio/talk_into(mob/M as mob, message, channel)
|
/obj/item/device/radio/talk_into(mob/M as mob, message, channel)
|
||||||
|
|
||||||
if(!on) return // the device has to be on
|
if(!on) return // the device has to be on
|
||||||
|
|
||||||
if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl
|
if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl
|
||||||
@@ -424,7 +430,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
|||||||
sleep(rand(10,25)) // wait a little...
|
sleep(rand(10,25)) // wait a little...
|
||||||
|
|
||||||
if(signal.data["done"])
|
if(signal.data["done"])
|
||||||
//we're done here.
|
// we're done here.
|
||||||
return
|
return
|
||||||
|
|
||||||
// Oh my god; the comms are down or something because the signal hasn't been broadcasted yet.
|
// Oh my god; the comms are down or something because the signal hasn't been broadcasted yet.
|
||||||
@@ -615,6 +621,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
|||||||
R.show_message(rendered, 2)
|
R.show_message(rendered, 2)
|
||||||
|
|
||||||
/obj/item/device/radio/hear_talk(mob/M as mob, msg)
|
/obj/item/device/radio/hear_talk(mob/M as mob, msg)
|
||||||
|
|
||||||
if (broadcasting)
|
if (broadcasting)
|
||||||
talk_into(M, msg)
|
talk_into(M, msg)
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -250,6 +250,7 @@
|
|||||||
for(var/obj/effect/speech_bubble/S in range(1, mob))
|
for(var/obj/effect/speech_bubble/S in range(1, mob))
|
||||||
if(S.parent == mob)
|
if(S.parent == mob)
|
||||||
S.loc = mob.loc
|
S.loc = mob.loc
|
||||||
|
|
||||||
moving = 0
|
moving = 0
|
||||||
|
|
||||||
return .
|
return .
|
||||||
@@ -364,6 +365,8 @@
|
|||||||
if((istype(turf,/turf/simulated/floor)) && (src.lastarea.has_gravity == 0)) // No one else gets a chance.
|
if((istype(turf,/turf/simulated/floor)) && (src.lastarea.has_gravity == 0)) // No one else gets a chance.
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if(istype(turf,/turf/simulated/floor) && (src.flags & NOGRAV))
|
if(istype(turf,/turf/simulated/floor) && (src.flags & NOGRAV))
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -52,6 +52,10 @@
|
|||||||
message+="[id]'. "
|
message+="[id]'. "
|
||||||
if(T)message+="Found '[T.value]'."
|
if(T)message+="Found '[T.value]'."
|
||||||
|
|
||||||
|
|
||||||
|
UnterminatedComment
|
||||||
|
message="Unterminated multi-line comment statement: expected */"
|
||||||
|
|
||||||
DuplicateFunction
|
DuplicateFunction
|
||||||
New(name, token/t)
|
New(name, token/t)
|
||||||
message="Function '[name]' defined twice."
|
message="Function '[name]' defined twice."
|
||||||
@@ -121,4 +125,8 @@
|
|||||||
|
|
||||||
DivisionByZero
|
DivisionByZero
|
||||||
name="DivideByZeroError"
|
name="DivideByZeroError"
|
||||||
message="Division by zero attempted."
|
message="Division by zero attempted."
|
||||||
|
|
||||||
|
MaxCPU
|
||||||
|
name="MaxComputationalUse"
|
||||||
|
message="Maximum amount of computational cycles reached (>= 1000)."
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
client/verb/tcssave()
|
client/verb/tcssave()
|
||||||
set hidden = 1
|
set hidden = 1
|
||||||
if(mob.machine)
|
if(mob.machine || issilicon(mob))
|
||||||
if(istype(mob.machine, /obj/machinery/computer/telecomms/traffic) && mob.machine in view(1, mob))
|
if((istype(mob.machine, /obj/machinery/computer/telecomms/traffic) && mob.machine in view(1, mob)) || issilicon(mob))
|
||||||
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
|
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
|
||||||
if(Machine.editingcode != mob)
|
if(Machine.editingcode != mob)
|
||||||
return
|
return
|
||||||
@@ -23,8 +23,8 @@ client/verb/tcssave()
|
|||||||
|
|
||||||
client/verb/tcscompile()
|
client/verb/tcscompile()
|
||||||
set hidden = 1
|
set hidden = 1
|
||||||
if(mob.machine)
|
if(mob.machine || issilicon(mob))
|
||||||
if(istype(mob.machine, /obj/machinery/computer/telecomms/traffic) && mob.machine in view(1, mob))
|
if((istype(mob.machine, /obj/machinery/computer/telecomms/traffic) && mob.machine in view(1, mob)) || (issilicon(mob) && istype(mob.machine, /obj/machinery/computer/telecomms/traffic) ))
|
||||||
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
|
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
|
||||||
if(Machine.editingcode != mob)
|
if(Machine.editingcode != mob)
|
||||||
return
|
return
|
||||||
@@ -74,8 +74,8 @@ client/verb/tcscompile()
|
|||||||
|
|
||||||
client/verb/tcsrun()
|
client/verb/tcsrun()
|
||||||
set hidden = 1
|
set hidden = 1
|
||||||
if(mob.machine)
|
if(mob.machine || issilicon(mob))
|
||||||
if(istype(mob.machine, /obj/machinery/computer/telecomms/traffic) && mob.machine in view(1, mob))
|
if((istype(mob.machine, /obj/machinery/computer/telecomms/traffic) && mob.machine in view(1, mob)) || (issilicon(mob) && istype(mob.machine, /obj/machinery/computer/telecomms/traffic) ))
|
||||||
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
|
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
|
||||||
if(Machine.editingcode != mob)
|
if(Machine.editingcode != mob)
|
||||||
return
|
return
|
||||||
@@ -140,8 +140,8 @@ client/verb/tcsrun()
|
|||||||
|
|
||||||
client/verb/exittcs()
|
client/verb/exittcs()
|
||||||
set hidden = 1
|
set hidden = 1
|
||||||
if(mob.machine)
|
if(mob.machine || issilicon(mob))
|
||||||
if(istype(mob.machine, /obj/machinery/computer/telecomms/traffic))
|
if((istype(mob.machine, /obj/machinery/computer/telecomms/traffic) && mob.machine in view(1, mob)) || (issilicon(mob) && istype(mob.machine, /obj/machinery/computer/telecomms/traffic) ))
|
||||||
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
|
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
|
||||||
if(Machine.editingcode == mob)
|
if(Machine.editingcode == mob)
|
||||||
Machine.storedcode = "[winget(mob, "tcscode", "text")]"
|
Machine.storedcode = "[winget(mob, "tcscode", "text")]"
|
||||||
@@ -152,8 +152,8 @@ client/verb/exittcs()
|
|||||||
|
|
||||||
client/verb/tcsrevert()
|
client/verb/tcsrevert()
|
||||||
set hidden = 1
|
set hidden = 1
|
||||||
if(mob.machine)
|
if(mob.machine || issilicon(mob))
|
||||||
if(istype(mob.machine, /obj/machinery/computer/telecomms/traffic) && mob.machine in view(1, mob))
|
if((istype(mob.machine, /obj/machinery/computer/telecomms/traffic) && mob.machine in view(1, mob)) || (issilicon(mob) && istype(mob.machine, /obj/machinery/computer/telecomms/traffic) ))
|
||||||
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
|
var/obj/machinery/computer/telecomms/traffic/Machine = mob.machine
|
||||||
if(Machine.editingcode != mob)
|
if(Machine.editingcode != mob)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -47,6 +47,8 @@
|
|||||||
if(!interpreter)
|
if(!interpreter)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
interpreter.container = src
|
||||||
|
|
||||||
interpreter.SetVar("PI" , 3.141592653) // value of pi
|
interpreter.SetVar("PI" , 3.141592653) // value of pi
|
||||||
interpreter.SetVar("E" , 2.718281828) // value of e
|
interpreter.SetVar("E" , 2.718281828) // value of e
|
||||||
interpreter.SetVar("SQURT2" , 1.414213562) // value of the square root of 2
|
interpreter.SetVar("SQURT2" , 1.414213562) // value of the square root of 2
|
||||||
@@ -155,6 +157,25 @@
|
|||||||
interpreter.SetProc("prob", /proc/prob_chance)
|
interpreter.SetProc("prob", /proc/prob_chance)
|
||||||
interpreter.SetProc("substr", /proc/docopytext)
|
interpreter.SetProc("substr", /proc/docopytext)
|
||||||
|
|
||||||
|
// Donkie~
|
||||||
|
// Strings
|
||||||
|
interpreter.SetProc("lower", /proc/n_lower)
|
||||||
|
interpreter.SetProc("upper", /proc/n_upper)
|
||||||
|
interpreter.SetProc("explode", /proc/string_explode)
|
||||||
|
interpreter.SetProc("repeat", /proc/n_repeat)
|
||||||
|
interpreter.SetProc("reverse", /proc/n_reverse)
|
||||||
|
interpreter.SetProc("tonum", /proc/n_str2num)
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
// End of Donkie~
|
||||||
|
|
||||||
|
|
||||||
// Run the compiled code
|
// Run the compiled code
|
||||||
@@ -163,7 +184,7 @@
|
|||||||
// Backwards-apply variables onto signal data
|
// Backwards-apply variables onto signal data
|
||||||
/* sanitize EVERYTHING. fucking players can't be trusted with SHIT */
|
/* sanitize EVERYTHING. fucking players can't be trusted with SHIT */
|
||||||
|
|
||||||
signal.data["message"] = trim(copytext(sanitize(interpreter.GetVar("$content")), 1, MAX_MESSAGE_LEN))
|
signal.data["message"] = interpreter.GetVar("$content")
|
||||||
signal.frequency = interpreter.GetVar("$freq")
|
signal.frequency = interpreter.GetVar("$freq")
|
||||||
|
|
||||||
var/setname = ""
|
var/setname = ""
|
||||||
@@ -171,14 +192,18 @@
|
|||||||
if(interpreter.GetVar("$source") in S.stored_names)
|
if(interpreter.GetVar("$source") in S.stored_names)
|
||||||
setname = interpreter.GetVar("$source")
|
setname = interpreter.GetVar("$source")
|
||||||
else
|
else
|
||||||
setname = "<i>[trim(copytext(sanitize(interpreter.GetVar("$source")), 1, MAX_MESSAGE_LEN))]</i>"
|
setname = "<i>[interpreter.GetVar("$source")]</i>"
|
||||||
|
|
||||||
if(signal.data["name"] != setname)
|
if(signal.data["name"] != setname)
|
||||||
signal.data["realname"] = setname
|
signal.data["realname"] = setname
|
||||||
signal.data["name"] = setname
|
signal.data["name"] = setname
|
||||||
signal.data["job"] = trim(copytext(sanitize(interpreter.GetVar("$job")), 1, MAX_MESSAGE_LEN))
|
signal.data["job"] = interpreter.GetVar("$job")
|
||||||
signal.data["reject"] = !(interpreter.GetVar("$pass")) // set reject to the opposite of $pass
|
signal.data["reject"] = !(interpreter.GetVar("$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 -- */
|
/* -- Actual language proc code -- */
|
||||||
|
|
||||||
datum/signal
|
datum/signal
|
||||||
@@ -188,7 +213,7 @@ datum/signal
|
|||||||
if(istext(address))
|
if(istext(address))
|
||||||
var/obj/machinery/telecomms/server/S = data["server"]
|
var/obj/machinery/telecomms/server/S = data["server"]
|
||||||
|
|
||||||
if(!value)
|
if(!value && value != 0)
|
||||||
return S.memory[address]
|
return S.memory[address]
|
||||||
|
|
||||||
else
|
else
|
||||||
@@ -202,7 +227,7 @@ datum/signal
|
|||||||
var/obj/machinery/telecomms/server/S = data["server"]
|
var/obj/machinery/telecomms/server/S = data["server"]
|
||||||
var/obj/item/device/radio/hradio
|
var/obj/item/device/radio/hradio
|
||||||
|
|
||||||
if(!message)
|
if((!message || message == "") && message != 0)
|
||||||
message = "*beep*"
|
message = "*beep*"
|
||||||
if(!source)
|
if(!source)
|
||||||
source = "[html_encode(uppertext(S.id))]"
|
source = "[html_encode(uppertext(S.id))]"
|
||||||
@@ -213,7 +238,7 @@ datum/signal
|
|||||||
freq *= 10 // shift the decimal one place
|
freq *= 10 // shift the decimal one place
|
||||||
|
|
||||||
if(!job)
|
if(!job)
|
||||||
job = "None"
|
job = "?"
|
||||||
|
|
||||||
newsign.data["mob"] = H
|
newsign.data["mob"] = H
|
||||||
newsign.data["mobtype"] = H.type
|
newsign.data["mobtype"] = H.type
|
||||||
@@ -222,9 +247,9 @@ datum/signal
|
|||||||
else
|
else
|
||||||
newsign.data["name"] = "<i>[html_encode(uppertext(source))]<i>"
|
newsign.data["name"] = "<i>[html_encode(uppertext(source))]<i>"
|
||||||
newsign.data["realname"] = newsign.data["name"]
|
newsign.data["realname"] = newsign.data["name"]
|
||||||
newsign.data["job"] = html_encode(job)
|
newsign.data["job"] = job
|
||||||
newsign.data["compression"] = 0
|
newsign.data["compression"] = 0
|
||||||
newsign.data["message"] = html_encode(message)
|
newsign.data["message"] = message
|
||||||
newsign.data["type"] = 2 // artificial broadcast
|
newsign.data["type"] = 2 // artificial broadcast
|
||||||
if(!isnum(freq))
|
if(!isnum(freq))
|
||||||
freq = text2num(freq)
|
freq = text2num(freq)
|
||||||
@@ -242,4 +267,4 @@ datum/signal
|
|||||||
newsign.data["vmessage"] = H.voice_message
|
newsign.data["vmessage"] = H.voice_message
|
||||||
newsign.data["vname"] = H.voice_name
|
newsign.data["vname"] = H.voice_name
|
||||||
newsign.data["vmask"] = 0
|
newsign.data["vmask"] = 0
|
||||||
S.relay_information(newsign, "/obj/machinery/telecomms/broadcaster") // send this simple message to broadcasters
|
S.relay_information(newsign, "/obj/machinery/telecomms/broadcaster") // send this simple message to broadcasters
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
if(isobject(e))
|
if(isobject(e))
|
||||||
if(istype(e, /list))
|
if(istype(e, /list))
|
||||||
chosenlist = e
|
chosenlist = e
|
||||||
|
i = 2
|
||||||
else
|
else
|
||||||
if(chosenlist)
|
if(chosenlist)
|
||||||
chosenlist.Add(e)
|
chosenlist.Add(e)
|
||||||
@@ -66,6 +67,7 @@
|
|||||||
if(isobject(e))
|
if(isobject(e))
|
||||||
if(istype(e, /list))
|
if(istype(e, /list))
|
||||||
chosenlist = e
|
chosenlist = e
|
||||||
|
i = 2
|
||||||
else
|
else
|
||||||
if(chosenlist)
|
if(chosenlist)
|
||||||
chosenlist.Remove(e)
|
chosenlist.Remove(e)
|
||||||
@@ -101,23 +103,142 @@
|
|||||||
if(haystack && needle)
|
if(haystack && needle)
|
||||||
if(isobject(haystack))
|
if(isobject(haystack))
|
||||||
if(istype(haystack, /list))
|
if(istype(haystack, /list))
|
||||||
if(length(haystack) + 1 >= end && start > 0)
|
if(length(haystack) >= end && start > 0)
|
||||||
var/list/listhaystack = haystack
|
var/list/listhaystack = haystack
|
||||||
return listhaystack.Find(needle, start, end)
|
return listhaystack.Find(needle, start, end)
|
||||||
|
|
||||||
else
|
else
|
||||||
if(istext(haystack))
|
if(istext(haystack))
|
||||||
if(length(haystack) + 1 >= end && start > 0)
|
if(length(haystack) >= end && start > 0)
|
||||||
return findtext(haystack, needle, start, end)
|
return findtext(haystack, needle, start, end)
|
||||||
|
|
||||||
// Clone of copytext()
|
// Clone of copytext()
|
||||||
/proc/docopytext(var/string, var/start = 1, var/end = 0)
|
/proc/docopytext(var/string, var/start = 1, var/end = 0)
|
||||||
if(istext(string) && isnum(start) && isnum(end))
|
if(istext(string) && isnum(start) && isnum(end))
|
||||||
if(length(string) >= end && start > 0)
|
if(start > 0)
|
||||||
return copytext(string, start, end)
|
return copytext(string, start, end)
|
||||||
|
|
||||||
// Clone of length()
|
// Clone of length()
|
||||||
/proc/smartlength(var/container)
|
/proc/smartlength(var/container)
|
||||||
if(container)
|
if(container)
|
||||||
if(istype(container, /list) || istext(container))
|
if(istype(container, /list) || istext(container))
|
||||||
return length(container)
|
return length(container)
|
||||||
|
|
||||||
|
// BY DONKIE~
|
||||||
|
// String stuff
|
||||||
|
/proc/n_lower(var/string)
|
||||||
|
if(istext(string))
|
||||||
|
return lowertext(string)
|
||||||
|
|
||||||
|
/proc/n_upper(var/string)
|
||||||
|
if(istext(string))
|
||||||
|
return uppertext(string)
|
||||||
|
|
||||||
|
/*
|
||||||
|
//Makes a list where all indicies in a string is a seperate index in the list
|
||||||
|
// JUST A HELPER DON'T ADD TO NTSCRIPT
|
||||||
|
proc/string_tolist(var/string)
|
||||||
|
var/list/L = new/list()
|
||||||
|
|
||||||
|
var/i
|
||||||
|
for(i=1, i<=lentext(string), i++)
|
||||||
|
L.Add(copytext(string, i, i))
|
||||||
|
|
||||||
|
return L
|
||||||
|
|
||||||
|
proc/string_explode(var/string, var/separator)
|
||||||
|
if(istext(string))
|
||||||
|
if(istext(separator) && separator == "")
|
||||||
|
return string_tolist(string)
|
||||||
|
var/i
|
||||||
|
var/lasti = 1
|
||||||
|
var/list/L = new/list()
|
||||||
|
|
||||||
|
for(i=1, i<=lentext(string)+1, i++)
|
||||||
|
if(copytext(string, i, i+1) == separator) // We found a separator
|
||||||
|
L.Add(copytext(string, lasti, i))
|
||||||
|
lasti = i+1
|
||||||
|
|
||||||
|
L.Add(copytext(string, lasti, lentext(string)+1)) // Adds the last segment
|
||||||
|
|
||||||
|
return L
|
||||||
|
|
||||||
|
Just found out there was already a string explode function, did some benchmarking, and that function were a bit faster, sticking to that.
|
||||||
|
*/
|
||||||
|
proc/string_explode(var/string, var/separator)
|
||||||
|
if(istext(string) && istext(separator))
|
||||||
|
return dd_text2list(string, separator)
|
||||||
|
|
||||||
|
proc/n_repeat(var/string, var/amount)
|
||||||
|
if(istext(string) && isnum(amount))
|
||||||
|
var/i
|
||||||
|
var/newstring = ""
|
||||||
|
for(i=0, i<=amount, i++)
|
||||||
|
if(i>=1000)
|
||||||
|
break
|
||||||
|
newstring = newstring + string
|
||||||
|
|
||||||
|
return newstring
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
if(istext(string))
|
||||||
|
return text2num(string)
|
||||||
|
|
||||||
|
// Number shit
|
||||||
|
proc/n_num2str(var/num)
|
||||||
|
if(isnum(num))
|
||||||
|
return num2text(num)
|
||||||
|
|
||||||
|
// Squareroot
|
||||||
|
proc/n_sqrt(var/num)
|
||||||
|
if(isnum(num))
|
||||||
|
return sqrt(num)
|
||||||
|
|
||||||
|
// Magnitude of num
|
||||||
|
proc/n_abs(var/num)
|
||||||
|
if(isnum(num))
|
||||||
|
return abs(num)
|
||||||
|
|
||||||
|
// Round down
|
||||||
|
proc/n_floor(var/num)
|
||||||
|
if(isnum(num))
|
||||||
|
return round(num)
|
||||||
|
|
||||||
|
// Round up
|
||||||
|
proc/n_ceil(var/num)
|
||||||
|
if(isnum(num))
|
||||||
|
return round(num)+1
|
||||||
|
|
||||||
|
// Round to nearest integer
|
||||||
|
proc/n_round(var/num)
|
||||||
|
if(isnum(num))
|
||||||
|
if(num-round(num)<0.5)
|
||||||
|
return round(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
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
// END OF BY DONKIE :(
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
*/
|
*/
|
||||||
Run()
|
Run()
|
||||||
cur_recursion = 0 // reset recursion
|
cur_recursion = 0 // reset recursion
|
||||||
|
cur_statements = 0 // reset CPU tracking
|
||||||
|
alertadmins = 0
|
||||||
|
|
||||||
ASSERT(src.program)
|
ASSERT(src.program)
|
||||||
RunBlock(src.program)
|
RunBlock(src.program)
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
stack
|
stack
|
||||||
scopes = new()
|
scopes = new()
|
||||||
functions = new()
|
functions = new()
|
||||||
|
|
||||||
|
datum/container // associated container for interpeter
|
||||||
/*
|
/*
|
||||||
Var: status
|
Var: status
|
||||||
A variable indicating that the rest of the current block should be skipped. This may be set to any combination of <Status Macros>.
|
A variable indicating that the rest of the current block should be skipped. This may be set to any combination of <Status Macros>.
|
||||||
@@ -31,10 +33,12 @@
|
|||||||
status=0
|
status=0
|
||||||
returnVal
|
returnVal
|
||||||
|
|
||||||
max_iterations=100 // max iterations without any kind of delay
|
max_statements=1000 // maximum amount of statements that can be called in one execution. this is to prevent massive crashes and exploitation
|
||||||
cur_iterations=0 // current iteration
|
cur_statements=0 // current amount of statements called
|
||||||
max_recursion=50 // max recursions without returning anything (or completing the code block)
|
alertadmins=0 // set to 1 if the admins shouldn't be notified of anymore issues
|
||||||
cur_recursion=0 // current amount of recursion
|
max_iterations=100 // max number of uninterrupted loops possible
|
||||||
|
max_recursion=50 // max recursions without returning anything (or completing the code block)
|
||||||
|
cur_recursion=0 // current amount of recursion
|
||||||
/*
|
/*
|
||||||
Var: persist
|
Var: persist
|
||||||
If 0, global variables will be reset after Run() finishes.
|
If 0, global variables will be reset after Run() finishes.
|
||||||
@@ -88,56 +92,74 @@
|
|||||||
CreateGlobalScope()
|
CreateGlobalScope()
|
||||||
curScope = globalScope
|
curScope = globalScope
|
||||||
|
|
||||||
for(var/node/statement/S in Block.statements)
|
if(cur_statements < max_statements)
|
||||||
while(paused) sleep(10)
|
|
||||||
if(istype(S, /node/statement/VariableAssignment))
|
for(var/node/statement/S in Block.statements)
|
||||||
var/node/statement/VariableAssignment/stmt = S
|
while(paused) sleep(10)
|
||||||
var/name = stmt.var_name.id_name
|
|
||||||
if(!stmt.object)
|
cur_statements++
|
||||||
// Below we assign the variable first to null if it doesn't already exist.
|
if(cur_statements >= max_statements)
|
||||||
// This is necessary for assignments like +=, and when the variable is used in a function
|
RaiseError(new/runtimeError/MaxCPU())
|
||||||
// If the variable already exists in a different block, then AssignVariable will automatically use that one.
|
|
||||||
if(!IsVariableAccessible(name))
|
if(container && !alertadmins)
|
||||||
AssignVariable(name, null)
|
if(istype(container, /datum/TCS_Compiler))
|
||||||
AssignVariable(name, Eval(stmt.value))
|
var/datum/TCS_Compiler/Compiler = container
|
||||||
|
var/obj/machinery/telecomms/server/Holder = Compiler.Holder
|
||||||
|
var/message = "Potential crash-inducing NTSL script detected at telecommunications server [Compiler.Holder] ([Holder.x], [Holder.y], [Holder.z])."
|
||||||
|
|
||||||
|
alertadmins = 1
|
||||||
|
message_admins(message, 1)
|
||||||
|
break
|
||||||
|
|
||||||
|
if(istype(S, /node/statement/VariableAssignment))
|
||||||
|
var/node/statement/VariableAssignment/stmt = S
|
||||||
|
var/name = stmt.var_name.id_name
|
||||||
|
if(!stmt.object)
|
||||||
|
// Below we assign the variable first to null if it doesn't already exist.
|
||||||
|
// This is necessary for assignments like +=, and when the variable is used in a function
|
||||||
|
// If the variable already exists in a different block, then AssignVariable will automatically use that one.
|
||||||
|
if(!IsVariableAccessible(name))
|
||||||
|
AssignVariable(name, null)
|
||||||
|
AssignVariable(name, Eval(stmt.value))
|
||||||
|
else
|
||||||
|
var/datum/D = Eval(GetVariable(stmt.object.id_name))
|
||||||
|
if(!D) return
|
||||||
|
D.vars[stmt.var_name.id_name] = Eval(stmt.value)
|
||||||
|
else if(istype(S, /node/statement/VariableDeclaration))
|
||||||
|
//VariableDeclaration nodes are used to forcibly declare a local variable so that one in a higher scope isn't used by default.
|
||||||
|
var/node/statement/VariableDeclaration/dec=S
|
||||||
|
if(!dec.object)
|
||||||
|
AssignVariable(dec.var_name.id_name, null, curScope)
|
||||||
|
else
|
||||||
|
var/datum/D = Eval(GetVariable(dec.object.id_name))
|
||||||
|
if(!D) return
|
||||||
|
D.vars[dec.var_name.id_name] = null
|
||||||
|
else if(istype(S, /node/statement/FunctionCall))
|
||||||
|
RunFunction(S)
|
||||||
|
else if(istype(S, /node/statement/FunctionDefinition))
|
||||||
|
//do nothing
|
||||||
|
else if(istype(S, /node/statement/WhileLoop))
|
||||||
|
RunWhile(S)
|
||||||
|
else if(istype(S, /node/statement/IfStatement))
|
||||||
|
RunIf(S)
|
||||||
|
else if(istype(S, /node/statement/ReturnStatement))
|
||||||
|
if(!curFunction)
|
||||||
|
RaiseError(new/runtimeError/UnexpectedReturn())
|
||||||
|
continue
|
||||||
|
status |= RETURNING
|
||||||
|
returnVal=Eval(S:value)
|
||||||
|
break
|
||||||
|
else if(istype(S, /node/statement/BreakStatement))
|
||||||
|
status |= BREAKING
|
||||||
|
break
|
||||||
|
else if(istype(S, /node/statement/ContinueStatement))
|
||||||
|
status |= CONTINUING
|
||||||
|
break
|
||||||
else
|
else
|
||||||
var/datum/D = Eval(GetVariable(stmt.object.id_name))
|
RaiseError(new/runtimeError/UnknownInstruction())
|
||||||
if(!D) return
|
if(status)
|
||||||
D.vars[stmt.var_name.id_name] = Eval(stmt.value)
|
break
|
||||||
else if(istype(S, /node/statement/VariableDeclaration))
|
|
||||||
//VariableDeclaration nodes are used to forcibly declare a local variable so that one in a higher scope isn't used by default.
|
|
||||||
var/node/statement/VariableDeclaration/dec=S
|
|
||||||
if(!dec.object)
|
|
||||||
AssignVariable(dec.var_name.id_name, null, curScope)
|
|
||||||
else
|
|
||||||
var/datum/D = Eval(GetVariable(dec.object.id_name))
|
|
||||||
if(!D) return
|
|
||||||
D.vars[dec.var_name.id_name] = null
|
|
||||||
else if(istype(S, /node/statement/FunctionCall))
|
|
||||||
RunFunction(S)
|
|
||||||
else if(istype(S, /node/statement/FunctionDefinition))
|
|
||||||
//do nothing
|
|
||||||
else if(istype(S, /node/statement/WhileLoop))
|
|
||||||
RunWhile(S)
|
|
||||||
else if(istype(S, /node/statement/IfStatement))
|
|
||||||
RunIf(S)
|
|
||||||
else if(istype(S, /node/statement/ReturnStatement))
|
|
||||||
if(!curFunction)
|
|
||||||
RaiseError(new/runtimeError/UnexpectedReturn())
|
|
||||||
continue
|
|
||||||
status |= RETURNING
|
|
||||||
returnVal=Eval(S:value)
|
|
||||||
break
|
|
||||||
else if(istype(S, /node/statement/BreakStatement))
|
|
||||||
status |= BREAKING
|
|
||||||
break
|
|
||||||
else if(istype(S, /node/statement/ContinueStatement))
|
|
||||||
status |= CONTINUING
|
|
||||||
break
|
|
||||||
else
|
|
||||||
RaiseError(new/runtimeError/UnknownInstruction())
|
|
||||||
if(status)
|
|
||||||
break
|
|
||||||
curScope = scopes.Pop()
|
curScope = scopes.Pop()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -212,14 +234,9 @@
|
|||||||
*/
|
*/
|
||||||
RunWhile(node/statement/WhileLoop/stmt)
|
RunWhile(node/statement/WhileLoop/stmt)
|
||||||
var/i=1
|
var/i=1
|
||||||
if(!cur_iterations)
|
|
||||||
cur_iterations = 1
|
|
||||||
while(Eval(stmt.cond) && Iterate(stmt.block, i++))
|
while(Eval(stmt.cond) && Iterate(stmt.block, i++))
|
||||||
cur_iterations++
|
|
||||||
continue
|
continue
|
||||||
status &= ~BREAKING
|
status &= ~BREAKING
|
||||||
cur_iterations -= i
|
|
||||||
if(cur_iterations <= 0) cur_iterations = 0
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Proc:Iterate
|
Proc:Iterate
|
||||||
@@ -227,7 +244,7 @@
|
|||||||
*/
|
*/
|
||||||
Iterate(node/BlockDefinition/block, count)
|
Iterate(node/BlockDefinition/block, count)
|
||||||
RunBlock(block)
|
RunBlock(block)
|
||||||
if(max_iterations > 0 && (count >= max_iterations || cur_iterations + 1 >= max_iterations))
|
if(max_iterations > 0 && count >= max_iterations)
|
||||||
RaiseError(new/runtimeError/IterationLimitReached())
|
RaiseError(new/runtimeError/IterationLimitReached())
|
||||||
return 0
|
return 0
|
||||||
if(status & (BREAKING|RETURNING))
|
if(status & (BREAKING|RETURNING))
|
||||||
@@ -294,3 +311,4 @@
|
|||||||
else if(!istype(value) && isobject(value)) value = new/node/expression/value/reference(value)
|
else if(!istype(value) && isobject(value)) value = new/node/expression/value/reference(value)
|
||||||
//TODO: check for invalid name
|
//TODO: check for invalid name
|
||||||
S.variables["[name]"] = value
|
S.variables["[name]"] = value
|
||||||
|
|
||||||
|
|||||||
@@ -276,7 +276,13 @@
|
|||||||
exp.func_name=curToken.value
|
exp.func_name=curToken.value
|
||||||
NextToken() //skip function name
|
NextToken() //skip function name
|
||||||
NextToken() //skip open parenthesis, already found
|
NextToken() //skip open parenthesis, already found
|
||||||
|
var/loops = 0
|
||||||
|
|
||||||
for()
|
for()
|
||||||
|
loops++
|
||||||
|
if(loops>=1000)
|
||||||
|
CRASH("Something TERRIBLE has gone wrong in ParseFunctionExpression ;__;")
|
||||||
|
|
||||||
if(istype(curToken, /token/symbol) && curToken.value==")")
|
if(istype(curToken, /token/symbol) && curToken.value==")")
|
||||||
return exp
|
return exp
|
||||||
exp.parameters+=ParseParamExpression()
|
exp.parameters+=ParseParamExpression()
|
||||||
|
|||||||
@@ -171,7 +171,12 @@
|
|||||||
NextToken() //skip function name
|
NextToken() //skip function name
|
||||||
if(!CheckToken("(", /token/symbol)) //Check for and skip open parenthesis
|
if(!CheckToken("(", /token/symbol)) //Check for and skip open parenthesis
|
||||||
return
|
return
|
||||||
|
var/loops = 0
|
||||||
for()
|
for()
|
||||||
|
loops++
|
||||||
|
if(loops>=6000)
|
||||||
|
CRASH("Something TERRIBLE has gone wrong in ParseFunctionStatement ;__;")
|
||||||
|
|
||||||
if(!curToken)
|
if(!curToken)
|
||||||
errors+=new/scriptError/EndOfFile()
|
errors+=new/scriptError/EndOfFile()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -59,6 +59,10 @@
|
|||||||
line = 1
|
line = 1
|
||||||
linepos = 0 //column=codepos-linepos
|
linepos = 0 //column=codepos-linepos
|
||||||
n_scriptOptions/nS_Options/options
|
n_scriptOptions/nS_Options/options
|
||||||
|
|
||||||
|
commenting = 0
|
||||||
|
// 1: single-line
|
||||||
|
// 2: multi-line
|
||||||
list
|
list
|
||||||
/*
|
/*
|
||||||
Variable: ignore
|
Variable: ignore
|
||||||
@@ -112,12 +116,16 @@
|
|||||||
Scan() //Creates a list of tokens from source code
|
Scan() //Creates a list of tokens from source code
|
||||||
var/list/tokens=new
|
var/list/tokens=new
|
||||||
for(, src.codepos<=lentext(code), src.codepos++)
|
for(, src.codepos<=lentext(code), src.codepos++)
|
||||||
|
|
||||||
var/char=copytext(code, codepos, codepos+1)
|
var/char=copytext(code, codepos, codepos+1)
|
||||||
if(char=="\n")
|
if(char=="\n")
|
||||||
line++
|
line++
|
||||||
linepos=codepos
|
linepos=codepos
|
||||||
|
|
||||||
if(ignore.Find(char))
|
if(ignore.Find(char))
|
||||||
continue
|
continue
|
||||||
|
else if(char == "/")
|
||||||
|
ReadComment()
|
||||||
else if(end_stmt.Find(char))
|
else if(end_stmt.Find(char))
|
||||||
tokens+=new /token/end(char, line, COL)
|
tokens+=new /token/end(char, line, COL)
|
||||||
else if(string_delim.Find(char))
|
else if(string_delim.Find(char))
|
||||||
@@ -129,6 +137,8 @@
|
|||||||
tokens+=ReadNumber()
|
tokens+=ReadNumber()
|
||||||
else if(options.symbols.Find(char))
|
else if(options.symbols.Find(char))
|
||||||
tokens+=ReadSymbol()
|
tokens+=ReadSymbol()
|
||||||
|
|
||||||
|
|
||||||
codepos=initial(codepos)
|
codepos=initial(codepos)
|
||||||
line=initial(line)
|
line=initial(line)
|
||||||
linepos=initial(linepos)
|
linepos=initial(linepos)
|
||||||
@@ -228,4 +238,50 @@
|
|||||||
errors+=new/scriptError("Bad number: ", T)
|
errors+=new/scriptError("Bad number: ", T)
|
||||||
T.value=0
|
T.value=0
|
||||||
codepos-- //allow main Scan() proc to read the next character
|
codepos-- //allow main Scan() proc to read the next character
|
||||||
return T
|
return T
|
||||||
|
|
||||||
|
/*
|
||||||
|
Proc: ReadComment
|
||||||
|
Reads a comment and outputs the type of comment
|
||||||
|
*/
|
||||||
|
|
||||||
|
ReadComment()
|
||||||
|
var
|
||||||
|
char=copytext(code, codepos, codepos+1)
|
||||||
|
nextchar=copytext(code, codepos+1, codepos+2)
|
||||||
|
charstring = char+nextchar
|
||||||
|
comm = 1
|
||||||
|
// 1: single-line comment
|
||||||
|
// 2: multi-line comment
|
||||||
|
expectedend = 0
|
||||||
|
|
||||||
|
if(charstring == "//" || charstring == "/*")
|
||||||
|
if(charstring == "/*")
|
||||||
|
comm = 2 // starts a multi-line comment
|
||||||
|
|
||||||
|
while(comm)
|
||||||
|
if(++codepos>lentext(code)) break
|
||||||
|
|
||||||
|
if(expectedend) // ending statement expected...
|
||||||
|
char = copytext(code, codepos, codepos+1)
|
||||||
|
if(char == "/") // ending statement found - beak the comment
|
||||||
|
comm = 0
|
||||||
|
break
|
||||||
|
|
||||||
|
if(comm == 2)
|
||||||
|
// multi-line comments are broken by ending statements
|
||||||
|
char = copytext(code, codepos, codepos+1)
|
||||||
|
if(char == "*")
|
||||||
|
expectedend = 1
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
char = copytext(code, codepos, codepos+1)
|
||||||
|
if(char == "\n")
|
||||||
|
comm = 0
|
||||||
|
break
|
||||||
|
|
||||||
|
if(expectedend) expectedend = 0
|
||||||
|
|
||||||
|
if(comm == 2)
|
||||||
|
errors+=new/scriptError/UnterminatedComment()
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 96 KiB |
@@ -331,7 +331,7 @@ menu "menu"
|
|||||||
window "Telecomms IDE"
|
window "Telecomms IDE"
|
||||||
elem "Telecomms IDE"
|
elem "Telecomms IDE"
|
||||||
type = MAIN
|
type = MAIN
|
||||||
pos = 281,0
|
pos = 303,13
|
||||||
size = 652x582
|
size = 652x582
|
||||||
anchor1 = none
|
anchor1 = none
|
||||||
anchor2 = none
|
anchor2 = none
|
||||||
@@ -372,8 +372,8 @@ window "Telecomms IDE"
|
|||||||
type = BUTTON
|
type = BUTTON
|
||||||
pos = 180,464
|
pos = 180,464
|
||||||
size = 60x20
|
size = 60x20
|
||||||
anchor1 = none
|
anchor1 = 28,80
|
||||||
anchor2 = none
|
anchor2 = 37,83
|
||||||
font-family = ""
|
font-family = ""
|
||||||
font-size = 0
|
font-size = 0
|
||||||
font-style = ""
|
font-style = ""
|
||||||
@@ -400,8 +400,8 @@ window "Telecomms IDE"
|
|||||||
type = BUTTON
|
type = BUTTON
|
||||||
pos = 120,464
|
pos = 120,464
|
||||||
size = 60x20
|
size = 60x20
|
||||||
anchor1 = none
|
anchor1 = 18,80
|
||||||
anchor2 = none
|
anchor2 = 28,83
|
||||||
font-family = ""
|
font-family = ""
|
||||||
font-size = 0
|
font-size = 0
|
||||||
font-style = ""
|
font-style = ""
|
||||||
@@ -428,8 +428,8 @@ window "Telecomms IDE"
|
|||||||
type = OUTPUT
|
type = OUTPUT
|
||||||
pos = 0,488
|
pos = 0,488
|
||||||
size = 648x94
|
size = 648x94
|
||||||
anchor1 = none
|
anchor1 = 0,84
|
||||||
anchor2 = none
|
anchor2 = 99,100
|
||||||
font-family = "sans-serif"
|
font-family = "sans-serif"
|
||||||
font-size = 9
|
font-size = 9
|
||||||
font-style = ""
|
font-style = ""
|
||||||
@@ -454,8 +454,8 @@ window "Telecomms IDE"
|
|||||||
type = BUTTON
|
type = BUTTON
|
||||||
pos = 60,464
|
pos = 60,464
|
||||||
size = 60x20
|
size = 60x20
|
||||||
anchor1 = none
|
anchor1 = 9,80
|
||||||
anchor2 = none
|
anchor2 = 18,83
|
||||||
font-family = ""
|
font-family = ""
|
||||||
font-size = 0
|
font-size = 0
|
||||||
font-style = ""
|
font-style = ""
|
||||||
@@ -482,8 +482,8 @@ window "Telecomms IDE"
|
|||||||
type = BUTTON
|
type = BUTTON
|
||||||
pos = 0,464
|
pos = 0,464
|
||||||
size = 60x20
|
size = 60x20
|
||||||
anchor1 = none
|
anchor1 = 0,80
|
||||||
anchor2 = none
|
anchor2 = 9,83
|
||||||
font-family = ""
|
font-family = ""
|
||||||
font-size = 0
|
font-size = 0
|
||||||
font-style = ""
|
font-style = ""
|
||||||
@@ -510,8 +510,8 @@ window "Telecomms IDE"
|
|||||||
type = INPUT
|
type = INPUT
|
||||||
pos = 0,0
|
pos = 0,0
|
||||||
size = 652x464
|
size = 652x464
|
||||||
anchor1 = none
|
anchor1 = 0,0
|
||||||
anchor2 = none
|
anchor2 = 100,80
|
||||||
font-family = "Courier"
|
font-family = "Courier"
|
||||||
font-size = 10
|
font-size = 10
|
||||||
font-style = ""
|
font-style = ""
|
||||||
|
|||||||
Reference in New Issue
Block a user