mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-22 12:29:46 +01:00
Major UT Overhaul (#16544)
* Removes old UT definition files (drone/travis) * Adds concurrency definitions to the workflows * Changes our workflows to be more in line with what /tg does * Adds a workflow to build/commit TGUI * Adds a workflow to build/commit changelogs Add python version to dependencies.sh Fix dme errors Removes a bunch of not included files Cache Opendream and add directory to check_grep.py Co-authored-by: Werner <Arrow768@users.noreply.github.com>
This commit is contained in:
@@ -104,3 +104,7 @@
|
||||
/datum/alarm_handler/proc/notify_listeners(var/alarm, var/was_raised)
|
||||
for(var/listener in listeners)
|
||||
call(listener, listeners[listener])(src, alarm, was_raised)
|
||||
|
||||
|
||||
#undef ALARM_RAISED
|
||||
#undef ALARM_CLEARED
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
//citizenship defines
|
||||
#define CITIZENSHIP_BIESEL "Republic of Biesel"
|
||||
#define CITIZENSHIP_SOL "Sol Alliance"
|
||||
#define CITIZENSHIP_COALITION "Coalition of Colonies"
|
||||
#define CITIZENSHIP_ELYRA "Republic of Elyra"
|
||||
#define CITIZENSHIP_ERIDANI "Eridani Federation"
|
||||
#define CITIZENSHIP_DOMINIA "Empire of Dominia"
|
||||
|
||||
#define CITIZENSHIP_IZWESKI "Izweski Hegemony"
|
||||
|
||||
#define CITIZENSHIP_NRALAKK "Nralakk Federation"
|
||||
#define CITIZENSHIP_EUM "Co-Operative Territories of EUM"
|
||||
|
||||
#define CITIZENSHIP_PRA "People's Republic of Adhomai"
|
||||
#define CITIZENSHIP_DPRA "Democratic People's Republic of Adhomai"
|
||||
#define CITIZENSHIP_NKA "New Kingdom of Adhomai"
|
||||
#define CITIZENSHIP_FREE_COUNCIL "Free Tajaran Council"
|
||||
|
||||
#define CITIZENSHIP_ZORA "Zo'ra Hive"
|
||||
#define CITIZENSHIP_KLAX "K'lax Hive"
|
||||
#define CITIZENSHIP_CTHUR "C'thur Hive"
|
||||
|
||||
#define CITIZENSHIP_NONE "None"
|
||||
#define CITIZENSHIP_GOLDEN "Golden Deep"
|
||||
|
||||
//religion defines
|
||||
#define RELIGION_NONE "None"
|
||||
#define RELIGION_OTHER "Other"
|
||||
#define RELIGION_CHRISTIANITY "Christianity"
|
||||
#define RELIGION_ISLAM "Islam"
|
||||
#define RELIGION_JUDAISM "Judaism"
|
||||
#define RELIGION_HINDU "Hinduism"
|
||||
#define RELIGION_BUDDHISM "Buddhism"
|
||||
#define RELIGION_SHINTO "Shinto"
|
||||
#define RELIGION_MOROZ "Moroz Holy Tribunal"
|
||||
#define RELIGION_TRINARY "Trinary Perfection"
|
||||
#define RELIGION_SCARAB "Scarab Folk Beliefs"
|
||||
#define RELIGION_TAOISM "Taoism"
|
||||
#define RELIGION_LUCEISM "Luceism"
|
||||
#define RELIGION_SIKHISM "Sikhism"
|
||||
#define RELIGION_STOLITISM "Vysokan Stolitism"
|
||||
|
||||
#define RELIGION_THAKH "Th'akh"
|
||||
#define RELIGION_SKAKH "Sk'akh"
|
||||
#define RELIGION_AUTAKH "Aut'akh"
|
||||
#define RELIGION_SIAKH "Si'akh"
|
||||
|
||||
#define RELIGION_QEBLAK "Qeblak"
|
||||
#define RELIGION_WEISHII "Weishii"
|
||||
#define RELIGION_SUURKA "Suur'ka"
|
||||
#define RELIGION_KIRGUL "Kir'gul"
|
||||
|
||||
#define RELIGION_TWINSUNS "S'rendarr and Messa"
|
||||
#define RELIGION_MATAKE "Ma'ta'ke"
|
||||
#define RELIGION_RASKARA "Raskariim"
|
||||
|
||||
#define RELIGION_HIVEPANTHEON "Hive Pantheon"
|
||||
#define RELIGION_PREIMMINENNCE "Preimminennce"
|
||||
#define RELIGION_PILOTDREAM "Pilot Dream"
|
||||
|
||||
#define RELIGION_ETERNAL "The Eternal"
|
||||
#define RELIGION_KSSHR "Ksshr"
|
||||
#define RELIGION_SHRKH "Shrkh"
|
||||
#define RELIGION_MADA "Maraka"
|
||||
#define RELIGION_GLEANERS "Lights Accord"
|
||||
|
||||
//accent defines
|
||||
|
||||
#define ACCENT_CETI "Biesellite"
|
||||
#define ACCENT_COC "Frontiersfolk"
|
||||
#define ACCENT_ELYRA "Elyran"
|
||||
#define ACCENT_ERIDANI "Eridanian"
|
||||
#define ACCENT_ERIDANIREINSTATED "Reinstated Dreg"
|
||||
#define ACCENT_ERIDANIDREG "Eridanian Dreg"
|
||||
#define ACCENT_SOL "Solarian"
|
||||
#define ACCENT_SCARAB "Scarab Fleets"
|
||||
#define ACCENT_SILVERSUN_ORIGINAL "Silversun Original"
|
||||
#define ACCENT_SILVERSUN_EXPATRIATE "Silversun Expatriate"
|
||||
#define ACCENT_PHONG "New Hai Phongese"
|
||||
#define ACCENT_MARTIAN "Martian"
|
||||
#define ACCENT_KONYAN "Konyanger"
|
||||
#define ACCENT_LUNA "Lunan"
|
||||
#define ACCENT_GIBSON_OVAN "New Gibson Ovanstad"
|
||||
#define ACCENT_GIBSON_UNDIR "New Gibson Undirstad"
|
||||
#define ACCENT_HIMEO "Himean"
|
||||
#define ACCENT_VYSOKA "Vysokan"
|
||||
#define ACCENT_VENUS "Venusian Cytherean"
|
||||
#define ACCENT_VENUSJIN "Venusian Jintarian"
|
||||
#define ACCENT_DOMINIA_HIGH "High Morozi"
|
||||
#define ACCENT_DOMINIA_VULGAR "Vulgar Morozi"
|
||||
#define ACCENT_DOMINIA_FRONTIER "Imperial Frontier"
|
||||
#define ACCENT_DOMINIA_NOVIJADRAN "Novi Jadranic"
|
||||
#define ACCENT_DOMINIA_LYODII "Lyodii"
|
||||
#define ACCENT_JUPITER "Jovian"
|
||||
#define ACCENT_CALLISTO "Callistean"
|
||||
#define ACCENT_EUROPA "Europan"
|
||||
#define ACCENT_EARTH "Earther"
|
||||
#define ACCENT_NCF "Non-Coalition Frontier"
|
||||
#define ACCENT_FISANDUH "Fisanduhian"
|
||||
#define ACCENT_GADPATHUR "Gadpathurian"
|
||||
#define ACCENT_PLUTO "Plutonian"
|
||||
#define ACCENT_ASSUNZIONE "Assunzionii"
|
||||
#define ACCENT_VISEGRAD "Visegradi"
|
||||
#define ACCENT_VALKYRIE "Valkyrian"
|
||||
#define ACCENT_MICTLAN "Mictlanian"
|
||||
#define ACCENT_PERSEPOLIS "Persepolis"
|
||||
#define ACCENT_MEDINA "Medina"
|
||||
#define ACCENT_AEMAQ "Aemaq"
|
||||
#define ACCENT_NEWSUEZ "New Suez"
|
||||
#define ACCENT_DAMASCUS "Damascus II"
|
||||
#define ACCENT_ANTILLIA "Port Antillia"
|
||||
#define ACCENT_XANU "Xanu"
|
||||
#define ACCENT_SANCOLETTE "San Colette"
|
||||
#define ACCENT_BURZSIA "Burzsia"
|
||||
|
||||
#define ACCENT_REPUBICLANSIIK "Republican Siik'maas"
|
||||
#define ACCENT_NAZIRASIIK "Nazira Siik'maas"
|
||||
#define ACCENT_CREVAN "Crevan Creole"
|
||||
#define ACCENT_DASNRRASIIK "Das'nrra Siik'maas"
|
||||
#define ACCENT_HIGHHARRSIIK "High-Harr'masir Siik'maas"
|
||||
#define ACCENT_LOWHARRSIIK "Lower-Harr'masir Siik'maas"
|
||||
#define ACCENT_AMOHDASIIK "Amohdan Siik'maas"
|
||||
#define ACCENT_RURALDELVAHHI "Rural Delvahhi"
|
||||
#define ACCENT_NOMADDELVAHHI "Nomadic Delvahhi"
|
||||
#define ACCENT_OLDYASSA "Old Ya'ssa"
|
||||
#define ACCENT_NEWYASSA "New Ya'ssa"
|
||||
#define ACCENT_NORTHRASNRR "Northern Ras'nrr Siik'maas"
|
||||
#define ACCENT_DINAKK "Din'akk Mountains Siik'maas"
|
||||
#define ACCENT_HARRNRRI "Harr'nrri Siik'mas"
|
||||
#define ACCENT_ZARRJIRI "Zarr'jiri Siik'mas"
|
||||
|
||||
#define ACCENT_HEGEMON_NOBLE "Noble Hegemonic"
|
||||
#define ACCENT_HEGEMON_PEASANT "Peasant Hegemonic"
|
||||
#define ACCENT_TRAD_NOBLE "Noble Traditional"
|
||||
#define ACCENT_TRAD_PEASANT "Peasant Traditional"
|
||||
#define ACCENT_WASTELAND "Deep Wastelander"
|
||||
#define ACCENT_AUTAKH "Aut'akh Dialect"
|
||||
#define ACCENT_QUEENDOM "Queendom Dialect"
|
||||
#define ACCENT_TZA_PEASANT "Tza Prairie Peasant"
|
||||
#define ACCENT_TZA_NOBLE "Tza Prairie Noble"
|
||||
#define ACCENT_SOUTHLANDS_PEASANT "Southlands Peasant"
|
||||
#define ACCENT_SOUTHLANDS_NOBLE "Southlands Noble"
|
||||
#define ACCENT_BROKEN_PEASANT "Broken Coalition Peasant"
|
||||
#define ACCENT_BROKEN_NOBLE "Broken Coalition Noble"
|
||||
#define ACCENT_UNATHI_SPACER "Spacer"
|
||||
#define ACCENT_HAZANA "Hazana"
|
||||
#define ACCENT_TORN "Torn Cities"
|
||||
|
||||
#define ACCENT_SKRELL "Standard Nral'Malic"
|
||||
#define ACCENT_HOMEWORLD "Qerrbalak"
|
||||
#define ACCENT_QERRMALIC "Qerr'Malic"
|
||||
#define ACCENT_ALIOSE "Aliose"
|
||||
#define ACCENT_AWEIJI "Aweiji"
|
||||
#define ACCENT_TRAVERSE "Traverse"
|
||||
#define ACCENT_GENNER "Generational Ship"
|
||||
#define ACCENT_SKRELLSOL "Solarian Skrell Standard"
|
||||
#define ACCENT_SKRELLCOC "Coalition Skrell Standard"
|
||||
#define ACCENT_SKRELLCETI "Biesellite Skrell Standard"
|
||||
#define ACCENT_SKRELLEUM "Nral'Daaq"
|
||||
#define ACCENT_SROM "Inner Voice"
|
||||
#define ACCENT_TATTUQIG "Tattuqig"
|
||||
|
||||
#define ACCENT_ROOTSONG "Rootsong"
|
||||
#define ACCENT_VOIDSONG "Voidsong"
|
||||
#define ACCENT_ANCIENTSONG "Ancientsong"
|
||||
#define ACCENT_CRIMSONSONG "Crimsonsong"
|
||||
#define ACCENT_IRONSONG "Ironsong"
|
||||
#define ACCENT_SANDSONG "Sandsong"
|
||||
#define ACCENT_WASTESONG "Wastesong"
|
||||
#define ACCENT_WAVESONG "Wavesong"
|
||||
#define ACCENT_SUNKENSONG "Sunkensong"
|
||||
#define ACCENT_STARSONG "Starsong"
|
||||
|
||||
|
||||
#define ACCENT_TTS "Text-to-Speech"
|
||||
|
||||
#define ACCENT_BLUESPACE "Bluespace"
|
||||
|
||||
#define ACCENT_ZORA "Zo'rane"
|
||||
#define ACCENT_KLAX "K'laxane"
|
||||
#define ACCENT_CTHUR "C'thuric"
|
||||
#define ACCENT_LIIDRA "Lii'draic"
|
||||
|
||||
#define ACCENTS_ALL_IPC_SOL list(ACCENT_SOL, ACCENT_EARTH, ACCENT_SILVERSUN_ORIGINAL, ACCENT_SILVERSUN_EXPATRIATE, ACCENT_VENUS, ACCENT_VENUSJIN, ACCENT_MARTIAN, ACCENT_JUPITER, ACCENT_CALLISTO, ACCENT_EUROPA, ACCENT_PHONG, ACCENT_ERIDANI, ACCENT_PLUTO, ACCENT_VISEGRAD, ACCENT_MICTLAN, ACCENT_KONYAN, ACCENT_LUNA, ACCENT_SANCOLETTE, ACCENT_TTS)
|
||||
#define ACCENTS_ALL_IPC list(ACCENT_CETI, ACCENT_TTS, ACCENT_XANU, ACCENT_COC, ACCENT_ELYRA, ACCENT_ERIDANI, ACCENT_ERIDANIDREG, ACCENT_ERIDANIREINSTATED, ACCENT_SOL, ACCENT_SILVERSUN_EXPATRIATE, ACCENT_SILVERSUN_ORIGINAL, ACCENT_PHONG, ACCENT_MARTIAN, ACCENT_KONYAN, ACCENT_LUNA, ACCENT_GIBSON_OVAN, ACCENT_GIBSON_UNDIR, ACCENT_HIMEO, ACCENT_VYSOKA, ACCENT_VENUS, ACCENT_VENUSJIN, ACCENT_JUPITER, ACCENT_CALLISTO, ACCENT_EUROPA, ACCENT_EARTH, ACCENT_NCF, ACCENT_PLUTO, ACCENT_ASSUNZIONE, ACCENT_VISEGRAD, ACCENT_SANCOLETTE, ACCENT_VALKYRIE, ACCENT_MICTLAN, ACCENT_PERSEPOLIS, ACCENT_MEDINA, ACCENT_NEWSUEZ, ACCENT_AEMAQ, ACCENT_DAMASCUS)
|
||||
#define RELIGIONS_ALL_IPC list(RELIGION_NONE, RELIGION_CHRISTIANITY, RELIGION_ISLAM, RELIGION_BUDDHISM, RELIGION_HINDU, RELIGION_TAOISM, RELIGION_JUDAISM, RELIGION_OTHER, RELIGION_TRINARY, RELIGION_SCARAB, RELIGION_LUCEISM, RELIGION_SHINTO)
|
||||
@@ -1,7 +1,3 @@
|
||||
#define RELIGIONS_BIESEL list(RELIGION_NONE, RELIGION_CHRISTIANITY, RELIGION_ISLAM, RELIGION_BUDDHISM, RELIGION_SHINTO, RELIGION_HINDU, RELIGION_TAOISM, RELIGION_JUDAISM, RELIGION_SIKHISM, RELIGION_OTHER, RELIGION_TRINARY)
|
||||
#define CITIZENSHIPS_BIESEL list(CITIZENSHIP_BIESEL, CITIZENSHIP_ERIDANI, CITIZENSHIP_COALITION)
|
||||
|
||||
|
||||
/singleton/origin_item/culture/biesellite
|
||||
name = "Biesellite"
|
||||
desc = "Relatively new compared to other cultures across the Orion Spur, the Biesellite culture was forged from the fire borne by its independence. Since its inception, it has continued to evolve, especially with the recent expansion of the Republic of Biesel into the Solarian Alliance's Outer Ring after its abandonment during the collapse. Despite its recent acquisition, the Corporate Reconstruction Zone as it is now known has begun adjusting and blending their own cultures into the Biesellite way of life, those not bending the knee and aligning are often bastions of insurgency and unrest."
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
#define RELIGIONS_COALITION list(RELIGION_NONE, RELIGION_CHRISTIANITY, RELIGION_ISLAM, RELIGION_BUDDHISM, RELIGION_SHINTO, RELIGION_HINDU, RELIGION_TAOISM, RELIGION_JUDAISM, RELIGION_SIKHISM, RELIGION_OTHER, RELIGION_TRINARY)
|
||||
#define RELIGIONS_COALITION_ALL list(RELIGION_NONE, RELIGION_CHRISTIANITY, RELIGION_ISLAM, RELIGION_BUDDHISM, RELIGION_SHINTO, RELIGION_HINDU, RELIGION_TAOISM, RELIGION_JUDAISM, RELIGION_SIKHISM, RELIGION_OTHER, RELIGION_TRINARY, RELIGION_SCARAB, RELIGION_MOROZ)
|
||||
#define CITIZENSHIPS_COALITION list(CITIZENSHIP_COALITION, CITIZENSHIP_BIESEL)
|
||||
|
||||
/singleton/origin_item/culture/coalition
|
||||
name = "Coalition of Colonies"
|
||||
desc = "The Coalition of Colonies was born out of the fires of the Interstellar War, the bloodiest war humanity has seen since its dawn as a species. The majority of its citizens prize their freedom above all else, which has led to problems with governance for the Coalition: to this day, it remains a very decentralized and fragmented entity that can only be brought together as a unified front in moments of extreme crisis. But with the recent growth of the Republic of Biesel, retreat of the Solarian Alliance, and an increasingly militaristic Empire of Dominia, perhaps this matter shall change in the years to come."
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#define CITIZENSHIPS_DOMINIA list(CITIZENSHIP_DOMINIA, CITIZENSHIP_COALITION, CITIZENSHIP_BIESEL)
|
||||
|
||||
/singleton/origin_item/culture/dominia
|
||||
name = "Empire of Dominia"
|
||||
desc = "The Empire of Dominia (often simply referred to as \"the Empire\") is an autocratic monarchy that is heavily influenced by its state religion, the Moroz Holy Tribunal, which is often regarded as an offshoot of old Earth faiths. Imperial society is sharply divided between Morozians, which are themselves divided between noble Primaries and commoner Secondaries, and Ma'zals, which make up the population of its conquered worlds. Militaristic and expansionist, the Empire has been increasingly brought into conflict with its neighbors: the Serene Republic of Elyra and Coalition of Colonies. Dominians are often stereotyped as militant, religious, and egotistical."
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#define RELIGIONS_ELYRA list(RELIGION_NONE, RELIGION_CHRISTIANITY, RELIGION_ISLAM, RELIGION_SHINTO, RELIGION_BUDDHISM, RELIGION_HINDU, RELIGION_TAOISM, RELIGION_JUDAISM, RELIGION_SIKHISM, RELIGION_OTHER)
|
||||
|
||||
/singleton/origin_item/culture/elyran
|
||||
name = "Serene Republic of Elyra"
|
||||
desc = "A rich and prosperous nation, the Serene Republic of Elyra is one of the few locations in the Orion Spur where phoron can be found. This phoron has made the Republic extremely wealthy and has given them a technological edge over much of the Spur. Highly-controlled customs and harsh immigration requirements have kept much of Elyra isolated from the broader Spur, and have led to the growth of a large population of \"Non-Citizen Persons,\" that reside in the Republic. Recent attacks by the Lii'dra Hive of the vaurca have led to the Republic becoming increasingly militarized."
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#define RELIGIONS_SOLARIAN list(RELIGION_NONE, RELIGION_CHRISTIANITY, RELIGION_ISLAM, RELIGION_SHINTO, RELIGION_BUDDHISM, RELIGION_HINDU, RELIGION_TAOISM, RELIGION_JUDAISM, RELIGION_SIKHISM, RELIGION_OTHER, RELIGION_TRINARY)
|
||||
#define CITIZENSHIPS_SOLARIAN list(CITIZENSHIP_SOL, CITIZENSHIP_BIESEL, CITIZENSHIP_ERIDANI, CITIZENSHIP_COALITION)
|
||||
|
||||
/singleton/origin_item/culture/solarian
|
||||
name = "Solarian"
|
||||
desc = "Despite the loss of much of its territory during the Solarian Collapse of 2463, most of those that fall under the general umbrella of Solarian culture are citizens or belong to statelets affiliated with the Alliance of Sovereign Solarian Nations (ASSN). By and large, Solarians are generally perceived as xenophobic, nationalistic, and militarist. Non-humans, aside from Skrell, are generally rare on Solarian worlds, and many that do reside on them are treated as second-class citizens at best."
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
/singleton/origin_item/culture/ipc_tau_ceti
|
||||
name = "Tau Ceti"
|
||||
desc = "Tau Ceti serves as a hotbed for IPC and synthetics in general, with their treatment and status being a contentious issue within the Republic. On average, IPC within the system are programmed or exposed to influences that place value on their status as individuals and encourage them to seek freedom and citizenship in life. This focus on freedom is however carefully tailored by megacorporate influence, with many synthetics being directly owned or in indentured servitude."
|
||||
@@ -12,4 +10,4 @@
|
||||
desc = "IPC have had a strong presence on Biesel, a place viewed by many as a beacon of hope and freedom for all species. IPC have been granted rights to self ownership and even citizenship, complete with property and a bid in the corporate job market. However, a great number remain in impoverished conditions in the slums of District 14 of Mendell City, while the majority of synthetics are still owned under conditions similar to those of the Alliance. New Gibson similarly hosts a number of IPC as a point of entry into the wider Tau Ceti system and the Republic at large. While the cold weather may provide for a comfortable stay, the negative attitude of the human population towards synthetics has forced many to adopt a more closed and stoic outlook, tending to keep to themselves."
|
||||
possible_accents = ACCENTS_ALL_IPC
|
||||
possible_citizenships = list(CITIZENSHIP_BIESEL, CITIZENSHIP_COALITION, CITIZENSHIP_NONE)
|
||||
possible_religions = RELIGIONS_ALL_IPC
|
||||
possible_religions = RELIGIONS_ALL_IPC
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#define CITIZENSHIPS_NRALAKK list(CITIZENSHIP_NRALAKK, CITIZENSHIP_EUM)
|
||||
#define RELIGIONS_NRALAKK list(RELIGION_QEBLAK, RELIGION_WEISHII, RELIGION_SUURKA, RELIGION_KIRGUL, RELIGION_OTHER, RELIGION_NONE)
|
||||
|
||||
/singleton/origin_item/culture/federation
|
||||
name = "Federation Skrell"
|
||||
desc = "The Nralakk Federation was first formed in 900 CE to unite the Skrell diaspora on Qerrbalak and its initial colonies, and formed again in 2245 CE with the disappearance of Glorsh-Omega. The Federation throughout the centuries has always had the main goal of uplifting the Skrell species as a whole, resulting in a culture that places importance on family, success, and working as a collective for the betterment of Skrellkind."
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#define RELIGIONS_ADHOMAI list(RELIGION_TWINSUNS, RELIGION_MATAKE, RELIGION_RASKARA, RELIGION_NONE, RELIGION_OTHER)
|
||||
#define CITIZENSHIPS_ADHOMAI list(CITIZENSHIP_PRA, CITIZENSHIP_DPRA, CITIZENSHIP_NKA)
|
||||
|
||||
/singleton/origin_item/culture/adhomian
|
||||
name = "Adhomian"
|
||||
desc = "Adhomai is the most important planet culturally for the Tajara species. Due to its relatively recent discovery, all Tajara have some kind of connection to the homeworld. Adhomai is currently divided between three competing nations. Besides the national divide, regional and ethnic divisions still exist."
|
||||
@@ -174,4 +171,4 @@
|
||||
desc = "Despite all efforts by the revolutionaries to destroy the Njarir'Akhran nobility during the First Revolution, some of its members survived. These remnants still cling, to varying degrees, to the Pre-Contact traditions; a culture once infamous for its opulence and stratification. The Pre-Contact Nobility is faded to oblivion as its member succumbs to old age and the New Kingdom diverges to its own path. However, its influence is still felt in the Royalist project."
|
||||
possible_accents = list(ACCENT_OLDYASSA)
|
||||
possible_citizenships = CITIZENSHIPS_ADHOMAI
|
||||
possible_religions = RELIGIONS_ADHOMAI
|
||||
possible_religions = RELIGIONS_ADHOMAI
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/datum/bounty/item/mech/New()
|
||||
..()
|
||||
description = "Upper management has requested one [name] mech be sent as soon as possible. Ship it to receive a large payment."
|
||||
|
||||
/datum/bounty/item/mech/ship(obj/O)
|
||||
if(!applies_to(O))
|
||||
return
|
||||
if(istype(O, /obj/mecha))
|
||||
var/obj/mecha/M = O
|
||||
M.wreckage = null // So the mech doesn't explode.
|
||||
..()
|
||||
|
||||
/datum/bounty/item/mech/mark_high_priority(scale_reward)
|
||||
return ..(max(scale_reward * 0.7, 1.2))
|
||||
|
||||
/datum/bounty/item/mech/ripley
|
||||
name = "APLU \"Ripley\""
|
||||
reward = 13000
|
||||
wanted_types = list(/obj/mecha/working/ripley)
|
||||
|
||||
/datum/bounty/item/mech/odysseus
|
||||
name = "Odysseus"
|
||||
reward = 11000
|
||||
wanted_types = list(/obj/mecha/medical/odysseus)
|
||||
|
||||
/datum/bounty/item/mech/gygax
|
||||
name = "Gygax"
|
||||
reward = 28000
|
||||
wanted_types = list(/obj/mecha/combat/gygax)
|
||||
|
||||
/datum/bounty/item/mech/durand
|
||||
name = "Durand"
|
||||
reward = 20000
|
||||
wanted_types = list(/obj/mecha/combat/durand)
|
||||
|
||||
/*
|
||||
/datum/bounty/item/mech/phazon
|
||||
name = "Phazon"
|
||||
reward = 50000
|
||||
wanted_types = list(/obj/mecha/combat/phazon)
|
||||
*/
|
||||
@@ -225,3 +225,11 @@
|
||||
if(B.claimed)
|
||||
++count
|
||||
return count
|
||||
|
||||
|
||||
#undef BOUNTY_MIN
|
||||
#undef BOUNTY_MAX
|
||||
|
||||
#undef BOUNTY_NUM_LOW
|
||||
#undef BOUNTY_NUM_MED
|
||||
#undef BOUNTY_NUM_HIGH
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
// Approved manifest.
|
||||
// +200 credits flat.
|
||||
/datum/export/manifest_correct
|
||||
cost = 200
|
||||
k_elasticity = 0
|
||||
unit_name = "approved manifest"
|
||||
export_types = list(/obj/item/paper/fluff/jobs/cargo/manifest)
|
||||
|
||||
/datum/export/manifest_correct/applies_to(obj/O)
|
||||
if(!..())
|
||||
return FALSE
|
||||
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/M = O
|
||||
if(M.is_approved() && !M.errors)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
// Correctly denied manifest.
|
||||
// Refunds the package cost minus the cost of crate.
|
||||
/datum/export/manifest_error_denied
|
||||
cost = -500
|
||||
k_elasticity = 0
|
||||
unit_name = "correctly denied manifest"
|
||||
export_types = list(/obj/item/paper/fluff/jobs/cargo/manifest)
|
||||
|
||||
/datum/export/manifest_error_denied/applies_to(obj/O)
|
||||
if(!..())
|
||||
return FALSE
|
||||
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/M = O
|
||||
if(M.is_denied() && M.errors)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/export/manifest_error_denied/get_cost(obj/O)
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/M = O
|
||||
return ..() + M.order_cost
|
||||
|
||||
|
||||
// Erroneously approved manifest.
|
||||
// Substracts the package cost.
|
||||
/datum/export/manifest_error
|
||||
unit_name = "erroneously approved manifest"
|
||||
export_types = list(/obj/item/paper/fluff/jobs/cargo/manifest)
|
||||
|
||||
/datum/export/manifest_error/applies_to(obj/O)
|
||||
if(!..())
|
||||
return FALSE
|
||||
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/M = O
|
||||
if(M.is_approved() && M.errors)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/export/manifest_error/get_cost(obj/O)
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/M = O
|
||||
return -M.order_cost
|
||||
|
||||
|
||||
// Erroneously denied manifest.
|
||||
// Substracts the package cost minus the cost of crate.
|
||||
/datum/export/manifest_correct_denied
|
||||
cost = 500
|
||||
unit_name = "erroneously denied manifest"
|
||||
export_types = list(/obj/item/paper/fluff/jobs/cargo/manifest)
|
||||
|
||||
/datum/export/manifest_correct_denied/applies_to(obj/O)
|
||||
if(!..())
|
||||
return FALSE
|
||||
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/M = O
|
||||
if(M.is_denied() && !M.errors)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/export/manifest_correct_denied/get_cost(obj/O)
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/M = O
|
||||
return ..() - M.order_cost
|
||||
@@ -1,8 +1,3 @@
|
||||
#define EVIDENCE_TYPE_BLOOD "Blood"
|
||||
#define EVIDENCE_TYPE_GSR "Gunshot Residue"
|
||||
#define EVIDENCE_TYPE_SALIVA "Saliva"
|
||||
#define EVIDENCE_TYPE_ADDITIONAL "Additional"
|
||||
|
||||
/obj/item/forensics/swab
|
||||
name = "swab kit"
|
||||
desc = "A sterilized cotton swab and vial used to take forensic samples."
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
|
||||
#define RIOTS 1
|
||||
#define WILD_ANIMAL_ATTACK 2
|
||||
#define INDUSTRIAL_ACCIDENT 3
|
||||
#define BIOHAZARD_OUTBREAK 4
|
||||
#define WARSHIPS_ARRIVE 5
|
||||
#define PIRATES 6
|
||||
#define CORPORATE_ATTACK 7
|
||||
#define ALIEN_RAIDERS 8
|
||||
#define AI_LIBERATION 9
|
||||
#define MOURNING 10
|
||||
#define CULT_CELL_REVEALED 11
|
||||
#define SECURITY_BREACH 12
|
||||
#define ANIMAL_RIGHTS_RAID 13
|
||||
#define FESTIVAL 14
|
||||
|
||||
#define RESEARCH_BREAKTHROUGH 15
|
||||
#define BARGAINS 16
|
||||
#define SONG_DEBUT 17
|
||||
#define MOVIE_RELEASE 18
|
||||
#define BIG_GAME_HUNTERS 19
|
||||
#define ELECTION 20
|
||||
#define GOSSIP 21
|
||||
#define TOURISM 22
|
||||
#define CELEBRITY_DEATH 23
|
||||
#define RESIGNATION 24
|
||||
|
||||
#define DEFAULT 1
|
||||
|
||||
#define ADMINISTRATIVE 2
|
||||
#define CLOTHING 3
|
||||
#define SECURITY 4
|
||||
#define SPECIAL_SECURITY 5
|
||||
|
||||
#define FOOD 6
|
||||
#define ANIMALS 7
|
||||
|
||||
#define MINERALS 8
|
||||
|
||||
#define EMERGENCY 9
|
||||
#define GAS_EVENT 10
|
||||
#define MAINTENANCE 11
|
||||
#define ELECTRICAL 12
|
||||
#define ROBOTICS 13
|
||||
#define BIOMEDICAL 14
|
||||
|
||||
#define GEAR_EVA 15
|
||||
|
||||
//---- Descriptions of destination types
|
||||
//Space stations can be purpose built for a number of different things, but generally require regular shipments of essential supplies.
|
||||
//Corvettes are small, fast warships generally assigned to border patrol or chasing down smugglers.
|
||||
//Battleships are large, heavy cruisers designed for slugging it out with other heavies or razing planets.
|
||||
//Yachts are fast civilian craft, often used for pleasure or smuggling.
|
||||
//Destroyers are medium sized vessels, often used for escorting larger ships but able to go toe-to-toe with them if need be.
|
||||
//Frigates are medium sized vessels, often used for escorting larger ships. They will rapidly find themselves outclassed if forced to face heavy warships head on.
|
||||
@@ -1,44 +0,0 @@
|
||||
/datum/event/disease_outbreak
|
||||
announceWhen = 15
|
||||
ic_name = "a viral biohazard"
|
||||
|
||||
/datum/event/disease_outbreak/announce()
|
||||
command_announcement.Announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/level_7_biohazard.ogg')
|
||||
|
||||
/datum/event/disease_outbreak/setup()
|
||||
announceWhen = rand(15, 30)
|
||||
|
||||
/datum/event/disease_outbreak/start()
|
||||
var/virus_type = pick(/datum/disease/dnaspread, /datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis)
|
||||
|
||||
for(var/mob/living/carbon/human/H in shuffle(living_mob_list))
|
||||
var/foundAlready = 0 // don't infect someone that already has the virus
|
||||
var/turf/T = get_turf(H)
|
||||
if(!T)
|
||||
continue
|
||||
if(isNotStationLevel(T.z))
|
||||
continue
|
||||
for(var/datum/disease/D in H.viruses)
|
||||
foundAlready = 1
|
||||
if(H.stat == 2 || foundAlready)
|
||||
continue
|
||||
|
||||
if(virus_type == /datum/disease/dnaspread) //Dnaspread needs strain_data set to work.
|
||||
if((!H.dna) || (H.sdisabilities & BLIND)) //A blindness disease would be the worst.
|
||||
continue
|
||||
var/datum/disease/dnaspread/D = new
|
||||
D.strain_data["name"] = H.real_name
|
||||
D.strain_data["UI"] = H.dna.UI.Copy()
|
||||
D.strain_data["SE"] = H.dna.SE.Copy()
|
||||
D.carrier = 1
|
||||
D.holder = H
|
||||
D.affected_mob = H
|
||||
H.viruses += D
|
||||
break
|
||||
else
|
||||
var/datum/disease/D = new virus_type
|
||||
D.carrier = 1
|
||||
D.holder = H
|
||||
D.affected_mob = H
|
||||
H.viruses += D
|
||||
break
|
||||
@@ -128,3 +128,11 @@
|
||||
|
||||
/datum/event/infestation/announce()
|
||||
command_announcement.Announce("[chosen_scan_type] indicate that [chosen_mob] [chosen_verb] [chosen_area]. Clear them out before this starts to affect productivity.", event_name, new_sound = 'sound/AI/vermin.ogg', zlevels = affecting_z)
|
||||
|
||||
|
||||
#undef INFESTATION_RATS
|
||||
#undef INFESTATION_LIZARDS
|
||||
#undef INFESTATION_SPACE_BATS
|
||||
#undef INFESTATION_SPIDERLINGS
|
||||
#undef INFESTATION_HIVEBOTS
|
||||
#undef INFESTATION_SLIMES
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
#define NO_THOUGHT 1 //Hallucinated thoughts will not occur on this hallucination's end()
|
||||
#define NO_EMOTE 2 //User will not emote to others when this hallucination ends
|
||||
#define HEARING_DEPENDENT 4 //deaf characters will not experience this hallucination
|
||||
|
||||
//Power Defines
|
||||
#define HAL_POWER_LOW 30
|
||||
#define HAL_POWER_MED 50
|
||||
#define HAL_POWER_HIGH 70
|
||||
|
||||
/datum/hallucination
|
||||
var/mob/living/carbon/holder //Who is hallucinating?
|
||||
var/allow_duplicates = TRUE //This is set to false for hallucinations with long durations or ones we do not want repeated for a time
|
||||
@@ -62,4 +53,4 @@
|
||||
|
||||
//For adding accent tags when you imagine people talking to you. This will be a forced accent. If there is no accent (simplemobs), give them a random one from a list
|
||||
/datum/hallucination/proc/get_hallucinated_accent(var/mob/living/talker)
|
||||
return talker.accent ? talker.accent : pick(ACCENTS_ALL_IPC)
|
||||
return talker.accent ? talker.accent : pick(ACCENTS_ALL_IPC)
|
||||
|
||||
@@ -293,3 +293,7 @@
|
||||
|
||||
/obj/effect/plant/proc/is_mature()
|
||||
return (health >= (max_health/3) && world.time > mature_time)
|
||||
|
||||
|
||||
#undef DEFAULT_SEED
|
||||
#undef VINE_GROWTH_STAGES
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#define IC_COMPONENTS_BASE 25
|
||||
#define IC_COMPLEXITY_BASE 75
|
||||
|
||||
/obj/item/device/electronic_assembly
|
||||
name = "electronic assembly"
|
||||
desc = "It's a case, for building small electronics with."
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#define MINIMUM_USEFUL_LIGHT_RANGE 1.4
|
||||
|
||||
/atom
|
||||
var/light_power = 1 // Intensity of the light.
|
||||
var/light_range = 0 // Range in tiles of the light.
|
||||
|
||||
@@ -79,3 +79,6 @@
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You fail to pick open \the [holder].</span>")
|
||||
return 0
|
||||
|
||||
#undef LOCK_LOCKED
|
||||
#undef LOCK_BROKEN
|
||||
|
||||
@@ -1,235 +0,0 @@
|
||||
/*
|
||||
DMP to swapmap converter
|
||||
version 1.0
|
||||
|
||||
by Lummox JR
|
||||
*/
|
||||
|
||||
mob/verb/Convert(filename as file)
|
||||
dmp2swapmap(filename)
|
||||
|
||||
/proc/d2sm_prepmap(filename)
|
||||
var/txt = file2text(filename)
|
||||
if(!txt) return
|
||||
var/i,j
|
||||
i=findText(txt,ascii2text(13)) // eliminate carriage returns
|
||||
while(i)
|
||||
txt=copytext(txt,1,i)+copytext(txt,i+1)
|
||||
i=findText(txt,ascii2text(13),i)
|
||||
i=findText(txt,"\\\n")
|
||||
while(i)
|
||||
for(j=i+2,j<=length(txt),++j) if(text2ascii(txt,j)>32) break
|
||||
txt=copytext(txt,1,i)+copytext(txt,j)
|
||||
i=findText(txt,"\\\n",i)
|
||||
return txt
|
||||
|
||||
/proc/dmp2swapmap(filename)
|
||||
//var/txt = file2text(filename)
|
||||
//if(!txt) return
|
||||
var/txt = d2sm_prepmap(filename)
|
||||
var/mapname="[filename]"
|
||||
var/i,j,k
|
||||
i=findtext(mapname,".dmp")
|
||||
while(i && i+4<length(mapname)) i=findtext(mapname,".dmp",i+1)
|
||||
mapname=copytext(mapname,1,i)
|
||||
/* i=findText(txt,ascii2text(13))
|
||||
while(i)
|
||||
txt=copytext(txt,1,i)+copytext(txt,i+1)
|
||||
i=findText(txt,ascii2text(13),i)
|
||||
i=findText(txt,"\\\n")
|
||||
while(i)
|
||||
for(j=i+2,j<=length(txt),++j) if(text2ascii(txt,j)>32) break
|
||||
txt=copytext(txt,1,i)+copytext(txt,j)
|
||||
i=findText(txt,"\\\n",i) */
|
||||
var/list/codes=new
|
||||
var/codelen=1
|
||||
var/list/areas
|
||||
var/mode=34
|
||||
var/z=0
|
||||
var/X=0,Y=0,Z=0
|
||||
while(txt)
|
||||
if(text2ascii(txt)==34)
|
||||
if(mode!=34)
|
||||
to_world("Corrupt map file [filename]: Unexpected code found after z-level [z]")
|
||||
return
|
||||
// standard line:
|
||||
// "a" = (/obj, /obj, /turf, /area)
|
||||
i=findtext(txt,"\"",2)
|
||||
var/code=copytext(txt,2,i)
|
||||
codelen=length(code)
|
||||
i=findtext(txt,"(",i)
|
||||
if(!i)
|
||||
to_world("Corrupt map file [filename]: No type list follows \"[code]\"")
|
||||
return
|
||||
k=findtext(txt,"\n",++i)
|
||||
j=(k || length(txt+1))
|
||||
while(--j>=i && text2ascii(txt,j)!=41)
|
||||
if(j<i)
|
||||
to_world("Corrupt map file [filename]: Type list following \"[code]\" is incomplete")
|
||||
return
|
||||
var/list/L = d2sm_ParseCommaList(copytext(txt,i,j))
|
||||
if(istext(L))
|
||||
to_world("Corrupt map file [filename]: [L]")
|
||||
return
|
||||
if(L.len<2)
|
||||
to_world("Corrupt map file [filename]: Type list following \"[code]\" has only 1 item")
|
||||
return
|
||||
txt=k?copytext(txt,k+1):null
|
||||
if(L[L.len] == "[world.area]") L[L.len]=0
|
||||
else
|
||||
if(!areas) areas=list()
|
||||
i=areas.Find(L[L.len])
|
||||
if(i) L[L.len]=i
|
||||
else
|
||||
areas+=L[L.len]
|
||||
L[L.len]=areas.len
|
||||
var/codetrans=d2sm_ConvertType(L[L.len-1],"\t\t\t\t")
|
||||
if(L[L.len]) codetrans+="\t\t\t\tAREA = [L[L.len]]\n"
|
||||
if(L.len>2) codetrans+=d2sm_Contents(L,L.len-2,"\t\t\t\t")
|
||||
codes[code]=copytext(codetrans,1,length(codetrans))
|
||||
else if(text2ascii(txt)==40)
|
||||
mode=40
|
||||
// standard line (top-down, left-right symbol order):
|
||||
// (1,1,1) = {"
|
||||
// abcde
|
||||
// bcdef
|
||||
// "}
|
||||
i=d2sm_MatchBrace(txt,1,40)
|
||||
if(!i)
|
||||
to_world("Corrupt map file [filename]: No matching ) for coordinates: [copytext(txt,1,findtext(txt,"\n"))]")
|
||||
return
|
||||
var/list/coords=d2sm_ParseCommaList(copytext(txt,2,i))
|
||||
if(istext(coords) || coords.len!=3)
|
||||
to_world("Corrupt map file [filename]: [istext(coords)?(coords):"[copytext(txt,1,i+1)] is not a valid (x,y,z) coordinate"]")
|
||||
return
|
||||
j=findtext(txt,"{",i+1)
|
||||
if(!j)
|
||||
to_world("Corrupt map file [filename]: No braces {} following [copytext(txt,1,i+1)]")
|
||||
return
|
||||
k=d2sm_MatchBrace(txt,j,123)
|
||||
if(!k)
|
||||
to_world("Corrupt map file [filename]: No closing brace } following [copytext(txt,1,i+1)]")
|
||||
return
|
||||
var/mtxt=copytext(txt,j+1,k)
|
||||
if(findText(mtxt,"\"\n")!=1 || !findText(mtxt,"\n\"",length(mtxt)-1))
|
||||
to_world(findText(mtxt,"\"\n"))
|
||||
to_world(findText(mtxt,"\n\"",length(mtxt)-1))
|
||||
to_world("Corrupt map file [filename]: No quotes in braces following [copytext(txt,1,i+1)]")
|
||||
return
|
||||
mtxt=copytext(mtxt,2,length(mtxt))
|
||||
var/_x=0,_y=0
|
||||
for(i=1,,++_y)
|
||||
j=findText(mtxt,"\n",i+1)
|
||||
if(!j) break
|
||||
_x=max(_x,(j-i-1)/codelen)
|
||||
i=j
|
||||
X=max(X,_x)
|
||||
Y=max(Y,_y)
|
||||
z=text2num(coords[3])
|
||||
Z=max(Z,z)
|
||||
txt=copytext(txt,k+1)
|
||||
else
|
||||
i=findtext(txt,"\n")
|
||||
txt=i?copytext(txt,i+1):null
|
||||
to_world("Map size: [X],[Y],[Z]")
|
||||
fdel("map_[mapname].txt")
|
||||
var/F = file("map_[mapname].txt")
|
||||
to_chat(F, ". = object(\".0\")\n.0\n\ttype = /swapmap\n\tid = \"[mapname]\"\n\tz = [Z]\n\ty = [Y]\n\tx = [X]")
|
||||
if(areas)
|
||||
txt=""
|
||||
for(i=0,i<areas.len,++i)
|
||||
txt+="[i?", ":""]object(\".[i]\")"
|
||||
to_chat(F, "\tareas = list([txt])")
|
||||
for(i=0,i<areas.len,++i)
|
||||
to_chat(F, "\t\t.[i]")
|
||||
txt=d2sm_ConvertType(areas[i+1],"\t\t\t")
|
||||
to_chat(F, copytext(txt,1,length(txt)))
|
||||
|
||||
// 2nd pass
|
||||
txt=d2sm_prepmap(filename)
|
||||
while(txt)
|
||||
// skip all non-data sections
|
||||
if(text2ascii(txt)!=40)
|
||||
i=findText(txt,"\n")
|
||||
if(i) txt=copytext(txt,i+1)
|
||||
else txt=null
|
||||
continue
|
||||
i=d2sm_MatchBrace(txt,1,40)
|
||||
var/list/coords=d2sm_ParseCommaList(copytext(txt,2,i))
|
||||
j=findtext(txt,"{",i+1)
|
||||
k=d2sm_MatchBrace(txt,j,123)
|
||||
var/mtxt=copytext(txt,j+2,k-1)
|
||||
var/_x=0,_y=0
|
||||
for(i=1,,++_y)
|
||||
j=findText(mtxt,"\n",i+1)
|
||||
if(!j) break
|
||||
_x=max(_x,(j-i-1)/codelen)
|
||||
i=j
|
||||
// print out this z-level now
|
||||
to_chat(F, "\t[coords[3]]")
|
||||
i=1
|
||||
for(var/y=_y,y>0,--y) // map is top-down
|
||||
++i
|
||||
to_chat(F, "\t\t[y]")
|
||||
for(var/x in 1 to _x)
|
||||
to_chat(F, "\t\t\t[x]")
|
||||
j=i+codelen
|
||||
to_chat(F, codes[copytext(mtxt,i,j)])
|
||||
i=j
|
||||
txt=copytext(txt,k+1)
|
||||
/* for(z in 1 to Z)
|
||||
to_chat(F, "\t[z]")
|
||||
for(var/y in 1 to Y)
|
||||
to_chat(F, "\t\t[y]")
|
||||
for(var/x in 1 to X)
|
||||
to_chat(F, "\t\t\t[x]")
|
||||
to_chat(F, codes[pick(codes)] */
|
||||
|
||||
/proc/d2sm_ParseCommaList(txt)
|
||||
var/list/L=new
|
||||
var/i,ch
|
||||
for(i=1,i<=length(txt),++i)
|
||||
if(text2ascii(txt,i)>32) break
|
||||
for(,i<=length(txt),++i)
|
||||
ch=text2ascii(txt,i)
|
||||
if(ch==44)
|
||||
L+=copytext(txt,1,i)
|
||||
for(++i,i<=length(txt),++i) if(text2ascii(txt,i)>32) break
|
||||
txt=copytext(txt,i)
|
||||
i=0;continue
|
||||
if(ch==40 || ch==91 || ch==123)
|
||||
i=d2sm_MatchBrace(txt,i,ch)
|
||||
if(!i) return "No matching brace found for [ascii2text(ch)]"
|
||||
if(i>1) L+=copytext(txt,1,i)
|
||||
return L
|
||||
|
||||
/proc/d2sm_MatchBrace(txt, i, which)
|
||||
if(which==40) ++which
|
||||
else which+=2
|
||||
var/j,ch
|
||||
for(j=i+1,j<=length(txt),++j)
|
||||
ch=text2ascii(txt,j)
|
||||
if(ch==which) return j
|
||||
if(ch==40 || ch==91 || ch==123)
|
||||
j=d2sm_MatchBrace(txt,j,ch)
|
||||
if(!j) return 0
|
||||
|
||||
/proc/d2sm_ConvertType(tt,tabs="")
|
||||
var/i=findText(tt,"{")
|
||||
if(!i) return "[tabs]type = [tt]\n"
|
||||
.="[tabs]type = [copytext(tt,1,i)]\n"
|
||||
var/list/L=d2sm_ParseCommaList(copytext(tt,i+1,d2sm_MatchBrace(tt,i,123)))
|
||||
if(istext(L)) return
|
||||
for(var/pair in L)
|
||||
.="[.][tabs][pair]\n"
|
||||
|
||||
/proc/d2sm_Contents(list/conts,n,tabs="")
|
||||
.="[tabs]contents = list("
|
||||
var/i
|
||||
for(i=0,i<n,++i)
|
||||
.+="[i?", ":""]object(\".[i]\")"
|
||||
.+=")\n"
|
||||
tabs+="\t"
|
||||
for(i=0,i<n,++i)
|
||||
.+="[tabs].[i]\n"
|
||||
.+=d2sm_ConvertType(conts[i+1],tabs+"\t")
|
||||
@@ -584,3 +584,7 @@
|
||||
connected.supports -= src
|
||||
connected.check_supports()
|
||||
connected = null
|
||||
|
||||
#undef DRILL_LIGHT_IDLE
|
||||
#undef DRILL_LIGHT_WARNING
|
||||
#undef DRILL_LIGHT_ACTIVE
|
||||
|
||||
@@ -385,3 +385,10 @@
|
||||
|
||||
/obj/item/farmbot_arm_assembly/attack_hand(mob/user)
|
||||
return //it's a converted watertank, no you cannot pick it up and put it in your backpack
|
||||
|
||||
|
||||
#undef FARMBOT_COLLECT
|
||||
#undef FARMBOT_WATER
|
||||
#undef FARMBOT_UPROOT
|
||||
#undef FARMBOT_NUTRIMENT
|
||||
#undef FARMBOT_PESTKILL
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
// MEDICAL SIDE EFFECT BASE
|
||||
// ========================
|
||||
/datum/medical_effect
|
||||
var/name = "None"
|
||||
var/strength = 0
|
||||
var/start = 0
|
||||
var/list/triggers
|
||||
var/list/cures
|
||||
var/cure_message
|
||||
|
||||
/datum/medical_effect/proc/manifest(mob/living/carbon/human/H)
|
||||
for(var/R in cures)
|
||||
if(H.reagents.has_reagent(R))
|
||||
return 0
|
||||
for(var/R in triggers)
|
||||
if(REAGENT_VOLUME(H.reagents, R) >= triggers[R])
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/medical_effect/proc/on_life(mob/living/carbon/human/H, strength)
|
||||
return
|
||||
|
||||
/datum/medical_effect/proc/cure(mob/living/carbon/human/H)
|
||||
for(var/R in cures)
|
||||
if(H.reagents.has_reagent(R))
|
||||
if (cure_message)
|
||||
to_chat(H, "<span class='notice'>[cure_message]</span>")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
// MOB HELPERS
|
||||
// ===========
|
||||
/mob/living/carbon/human/var/list/datum/medical_effect/side_effects = list()
|
||||
/mob/proc/add_side_effect(name, strength = 0)
|
||||
/mob/living/carbon/human/add_side_effect(name, strength = 0)
|
||||
for(var/datum/medical_effect/M in src.side_effects)
|
||||
if(M.name == name)
|
||||
M.strength = max(M.strength, 10)
|
||||
M.start = life_tick
|
||||
return
|
||||
|
||||
|
||||
var/T = side_effects[name]
|
||||
if (!T)
|
||||
return
|
||||
|
||||
var/datum/medical_effect/M = new T
|
||||
if(M.name == name)
|
||||
M.strength = strength
|
||||
M.start = life_tick
|
||||
side_effects += M
|
||||
|
||||
/mob/living/carbon/human/proc/handle_medical_side_effects()
|
||||
//Going to handle those things only every few ticks.
|
||||
if(life_tick % 15 != 0)
|
||||
return 0
|
||||
|
||||
var/list/L = typesof(/datum/medical_effect)-/datum/medical_effect
|
||||
for(var/T in L)
|
||||
var/datum/medical_effect/M = new T
|
||||
if (M.manifest(src))
|
||||
src.add_side_effect(M.name)
|
||||
|
||||
// One full cycle(in terms of strength) every 10 minutes
|
||||
for (var/datum/medical_effect/M in side_effects)
|
||||
if (!M) continue
|
||||
var/strength_percent = sin((life_tick - M.start) / 2)
|
||||
|
||||
// Only do anything if the effect is currently strong enough
|
||||
if(strength_percent >= 0.4)
|
||||
if (M.cure(src) || M.strength > 50)
|
||||
side_effects -= M
|
||||
M = null
|
||||
else
|
||||
if(life_tick % 45 == 0)
|
||||
M.on_life(src, strength_percent*M.strength)
|
||||
// Effect slowly growing stronger
|
||||
M.strength+=0.08
|
||||
|
||||
// HEADACHE
|
||||
// ========
|
||||
/datum/medical_effect/headache
|
||||
name = "Headache"
|
||||
triggers = list(/singleton/reagent/cryoxadone = 10, /singleton/reagent/bicaridine = 15, /singleton/reagent/tricordrazine = 15)
|
||||
cures = list(/singleton/reagent/alkysine, /singleton/reagent/mortaphenyl, /singleton/reagent/perconol, /singleton/reagent/oxycomorphine)
|
||||
cure_message = "Your head stops throbbing..."
|
||||
|
||||
/datum/medical_effect/headache/on_life(mob/living/carbon/human/H, strength)
|
||||
switch(strength)
|
||||
if(1 to 10)
|
||||
H.custom_pain("You feel a light pain in your head.",0)
|
||||
if(11 to 30)
|
||||
H.custom_pain("You feel a throbbing pain in your head!",1)
|
||||
if(31 to INFINITY)
|
||||
H.custom_pain("You feel an excrutiating pain in your head!",1)
|
||||
|
||||
// BAD STOMACH
|
||||
// ===========
|
||||
/datum/medical_effect/bad_stomach
|
||||
name = "Bad Stomach"
|
||||
triggers = list(/singleton/reagent/kelotane = 30, /singleton/reagent/dermaline = 15)
|
||||
cures = list(/singleton/reagent/dylovene)
|
||||
cure_message = "Your stomach feels a little better now..."
|
||||
|
||||
/datum/medical_effect/bad_stomach/on_life(mob/living/carbon/human/H, strength)
|
||||
switch(strength)
|
||||
if(1 to 10)
|
||||
H.custom_pain("You feel a bit light around the stomach.",0)
|
||||
if(11 to 30)
|
||||
H.custom_pain("Your stomach hurts.",0)
|
||||
if(31 to INFINITY)
|
||||
H.custom_pain("You feel sick.",1)
|
||||
|
||||
// CRAMPS
|
||||
// ======
|
||||
/datum/medical_effect/cramps
|
||||
name = "Cramps"
|
||||
triggers = list(/singleton/reagent/dylovene = 30, /singleton/reagent/mortaphenyl = 15)
|
||||
cures = list(/singleton/reagent/inaprovaline)
|
||||
cure_message = "The cramps let up..."
|
||||
|
||||
/datum/medical_effect/cramps/on_life(mob/living/carbon/human/H, strength)
|
||||
switch(strength)
|
||||
if(1 to 10)
|
||||
H.custom_pain("The muscles in your body hurt a little.",0)
|
||||
if(11 to 30)
|
||||
H.custom_pain("The muscles in your body cramp up painfully.",0)
|
||||
if(31 to INFINITY)
|
||||
H.visible_message("<b>[H]</b> flinches!")
|
||||
H.custom_pain("There's pain all over your body!",1)
|
||||
|
||||
// ITCH
|
||||
// ====
|
||||
/datum/medical_effect/itch
|
||||
name = "Itch"
|
||||
triggers = list(/singleton/reagent/space_drugs = 10)
|
||||
cures = list(/singleton/reagent/inaprovaline)
|
||||
cure_message = "The itching stops..."
|
||||
|
||||
/datum/medical_effect/itch/on_life(mob/living/carbon/human/H, strength)
|
||||
switch(strength)
|
||||
if(1 to 10)
|
||||
H.custom_pain("You feel a slight itch.",0)
|
||||
if(11 to 30)
|
||||
H.custom_pain("You want to scratch your itch badly.",0)
|
||||
if(31 to INFINITY)
|
||||
H.visible_message("<b>[H]</b> shivers slightly.")
|
||||
H.custom_pain("This itch makes it really hard to concentrate.",1)
|
||||
@@ -1,6 +1,3 @@
|
||||
#define SEC_HUDTYPE "security"
|
||||
#define MED_HUDTYPE "medical"
|
||||
|
||||
/mob/living/carbon/human/proc/get_covered_body_parts(var/thick)
|
||||
var/skipbody = 0
|
||||
for(var/obj/item/clothing/C in list(wear_suit, head, wear_mask, w_uniform, gloves, shoes))
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#define DEFAULT_LAW_CHANNEL "Main Frequency"
|
||||
|
||||
/mob/living/silicon/proc/laws_sanity_check()
|
||||
if(!src.laws)
|
||||
laws = new base_law_type
|
||||
@@ -106,4 +104,4 @@
|
||||
|
||||
/mob/living/silicon/proc/log_law(var/law_message)
|
||||
log_and_message_admins(law_message)
|
||||
lawchanges += "[worldtime2text()] - [usr ? "[key_name(usr)]" : "EVENT"] [law_message]"
|
||||
lawchanges += "[worldtime2text()] - [usr ? "[key_name(usr)]" : "EVENT"] [law_message]"
|
||||
|
||||
@@ -1294,3 +1294,5 @@
|
||||
|
||||
/mob/living/silicon/robot/GetIdCard()
|
||||
return id_card
|
||||
|
||||
#undef CYBORG_POWER_USAGE_MULTIPLIER
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
#define NO_HUD 0
|
||||
#define SEC_HUD 1
|
||||
#define MED_HUD 2
|
||||
|
||||
/mob/living/silicon
|
||||
// Speaking
|
||||
gender = NEUTER
|
||||
|
||||
@@ -283,3 +283,12 @@
|
||||
if(rats.len >= RAT_KING_LEVEL)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
#undef RAT_MAYOR_LEVEL
|
||||
#undef RAT_BARON_LEVEL
|
||||
#undef RAT_DUKE_LEVEL
|
||||
#undef RAT_KING_LEVEL
|
||||
#undef RAT_EMPEROR_LEVEL
|
||||
#undef RAT_SAVIOR_LEVEL
|
||||
#undef RAT_GOD_LEVEL
|
||||
|
||||
@@ -320,3 +320,10 @@
|
||||
new /obj/effect/gibspawner/generic(T)
|
||||
explosion(T, -1, 0, 2)
|
||||
qdel(src)
|
||||
|
||||
#undef EGG_SCHLORRGO
|
||||
#undef BABY_SCHLORRGO
|
||||
#undef NORMAL_SCHLORRGO
|
||||
#undef FAT_SCHLORRGO
|
||||
#undef WIDE_SCHLORRGO
|
||||
#undef COLOSSAL_SCHLORRGO
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
#define UPGRADE_COOLDOWN 40
|
||||
#define UPGRADE_KILL_TIMER 100
|
||||
|
||||
|
||||
//This is called from human_attackhand.dm before grabbing happens.
|
||||
//IT is called when grabber tries to grab this mob
|
||||
//Override this for special grab behaviour.
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#define LISTENER_MODULAR_COMPUTER "modular_computers"
|
||||
|
||||
/obj/item/modular_computer/process()
|
||||
if(!enabled) // The computer is turned off
|
||||
last_power_usage = 0
|
||||
@@ -95,7 +93,7 @@
|
||||
if(looping_sound)
|
||||
soundloop = new(src, enabled)
|
||||
initial_name = name
|
||||
listener = new(LISTENER_MODULAR_COMPUTER, src)
|
||||
listener = new("modular_computers", src)
|
||||
|
||||
/obj/item/modular_computer/Destroy()
|
||||
kill_program(TRUE)
|
||||
|
||||
+1
-1
@@ -247,7 +247,7 @@ var/last_message_id = 0
|
||||
for (var/datum/comm_message_listener/l in comm_message_listeners)
|
||||
l.Add(message)
|
||||
|
||||
for (var/obj/item/modular_computer/computer in get_listeners_by_type(LISTENER_MODULAR_COMPUTER, /obj/item/modular_computer))
|
||||
for (var/obj/item/modular_computer/computer in get_listeners_by_type("modular_computers", /obj/item/modular_computer))
|
||||
if(computer?.working && !!computer.nano_printer && computer.hard_drive?.stored_files.len)
|
||||
var/datum/computer_file/program/comm/C = locate(/datum/computer_file/program/comm) in computer.hard_drive.stored_files
|
||||
if(C?.intercept)
|
||||
|
||||
@@ -494,3 +494,18 @@
|
||||
continue
|
||||
to_chat(M, SPAN_DANGER("Suddenly the gravity pushed you up to the ceiling and dropped you back on the floor with great force!"))
|
||||
M.fall_impact(1)
|
||||
|
||||
|
||||
#undef POWER_IDLE
|
||||
#undef POWER_UP
|
||||
#undef POWER_DOWN
|
||||
|
||||
#undef GRAV_NEEDS_SCREWDRIVER
|
||||
#undef GRAV_NEEDS_WELDING
|
||||
#undef GRAV_NEEDS_PLASTEEL
|
||||
#undef GRAV_NEEDS_WRENCH
|
||||
|
||||
#undef AREA_ERRNONE
|
||||
#undef AREA_STATION
|
||||
#undef AREA_SPACE
|
||||
#undef AREA_SPECIAL
|
||||
|
||||
@@ -147,3 +147,5 @@
|
||||
*******************/
|
||||
/atom/proc/singuloCanEat()
|
||||
return 1
|
||||
|
||||
#undef I_SINGULO
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#define EMITTER_DAMAGE_POWER_TRANSFER 450 //used to transfer power to containment field generators
|
||||
#define EMITTER_LOOSE 0
|
||||
#define EMITTER_BOLTED 1
|
||||
#define EMITTER_WELDED 2
|
||||
@@ -258,3 +257,8 @@
|
||||
activate(null)
|
||||
else
|
||||
visible_message("[icon2html(src, viewers(get_turf(src)))] [src] whines, \"Access denied!\"")
|
||||
|
||||
|
||||
#undef EMITTER_LOOSE
|
||||
#undef EMITTER_BOLTED
|
||||
#undef EMITTER_WELDED
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
|
||||
#define I_SINGULO "singulo"
|
||||
|
||||
/obj/singularity/
|
||||
name = "gravitational singularity"
|
||||
@@ -510,3 +510,5 @@
|
||||
var/turf/destination = (direction == UP) ? GetAbove(src) : GetBelow(src)
|
||||
if(destination)
|
||||
forceMove(destination)
|
||||
|
||||
#undef I_SINGULO
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
#define SOLAR_MAX_DIST 40
|
||||
#define SOLARGENRATE 1500
|
||||
|
||||
/obj/machinery/power/solar
|
||||
name = "solar panel"
|
||||
desc = "A solar electrical generator."
|
||||
|
||||
@@ -440,3 +440,6 @@
|
||||
|
||||
else if(closest_structure)
|
||||
closest_structure.tesla_act(power, melt)
|
||||
|
||||
#undef TESLA_DEFAULT_POWER
|
||||
#undef TESLA_MINI_POWER
|
||||
|
||||
@@ -1,16 +1,3 @@
|
||||
#define HOLD_CASINGS 0 //do not do anything after firing. Manual action, like pump shotguns, or guns that want to define custom behaviour
|
||||
#define EJECT_CASINGS 1 //drop spent casings on the ground after firing
|
||||
#define CYCLE_CASINGS 2 //experimental: cycle casings, like a revolver. Also works for multibarrelled guns
|
||||
#define DELETE_CASINGS 3 //deletes the casing, used in caseless ammunition guns or something
|
||||
#define ROF_SMG 2 //ROF stands for "RATE OF FIRE"
|
||||
#define ROF_PISTOL 3
|
||||
#define ROF_INTERMEDIATE 4
|
||||
#define ROF_RIFLE 5
|
||||
#define ROF_HEAVY 8
|
||||
#define ROF_SUPERHEAVY 12
|
||||
#define ROF_UNWIELDY 16
|
||||
#define ROF_SPECIAL 40
|
||||
|
||||
/obj/item/gun/projectile
|
||||
name = "gun"
|
||||
desc = "A gun that fires bullets."
|
||||
|
||||
@@ -681,3 +681,5 @@
|
||||
/image/proc/flick_remove_overlay(var/atom/A)
|
||||
if(A)
|
||||
A.overlays.Remove(src)
|
||||
|
||||
#undef MUZZLE_EFFECT_PIXEL_INCREMENT
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#define CELL_ALIVE(VAL) (VAL == cell_live_value)
|
||||
#define KILL_CELL(CELL, NEXT_MAP) NEXT_MAP[CELL] = cell_dead_value;
|
||||
#define REVIVE_CELL(CELL, NEXT_MAP) NEXT_MAP[CELL] = cell_live_value;
|
||||
|
||||
/datum/random_map/automata
|
||||
descriptor = "generic caves"
|
||||
initial_wall_cell = 55
|
||||
|
||||
@@ -223,3 +223,10 @@
|
||||
return
|
||||
|
||||
new /datum/random_map/droppod(null, usr.x-1, usr.y-1, usr.z, supplied_drops = spawned_mobs, automated = automatic_pod)
|
||||
|
||||
|
||||
#undef SD_FLOOR_TILE
|
||||
#undef SD_WALL_TILE
|
||||
#undef SD_DOOR_TILE
|
||||
#undef SD_EMPTY_TILE
|
||||
#undef SD_SUPPLY_TILE
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#define PROCESS_REACTION_ITER 5 //when processing a reaction, iterate this many times
|
||||
|
||||
/datum/reagents
|
||||
var/primary_reagent
|
||||
var/list/reagent_volumes
|
||||
|
||||
@@ -350,3 +350,5 @@
|
||||
var/obj/machinery/conveyor_switch/NC = new/obj/machinery/conveyor_switch(A, id)
|
||||
transfer_fingerprints_to(NC)
|
||||
qdel(src)
|
||||
|
||||
#undef MAX_CONVEYOR_ITEMS_MOVE
|
||||
|
||||
@@ -1,24 +1,4 @@
|
||||
|
||||
#define EFFECT_TOUCH 0
|
||||
#define EFFECT_AURA 1
|
||||
#define EFFECT_PULSE 2
|
||||
#define MAX_EFFECT 2
|
||||
|
||||
#define TRIGGER_TOUCH 0
|
||||
#define TRIGGER_WATER 1
|
||||
#define TRIGGER_ACID 2
|
||||
#define TRIGGER_VOLATILE 3
|
||||
#define TRIGGER_TOXIN 4
|
||||
#define TRIGGER_FORCE 5
|
||||
#define TRIGGER_ENERGY 6
|
||||
#define TRIGGER_HEAT 7
|
||||
#define TRIGGER_COLD 8
|
||||
#define TRIGGER_PHORON 9
|
||||
#define TRIGGER_OXY 10
|
||||
#define TRIGGER_CO2 11
|
||||
#define TRIGGER_NITRO 12
|
||||
#define MAX_TRIGGER 12
|
||||
|
||||
/obj/machinery/artifact
|
||||
name = "alien artifact"
|
||||
desc = "A large alien device."
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
File: AST Nodes
|
||||
An abstract syntax tree (AST) is a representation of source code in a computer-friendly format. It is composed of nodes,
|
||||
each of which represents a certain part of the source code. For example, an <IfStatement> node represents an if statement in the
|
||||
script's source code. Because it is a representation of the source code in memory, it is independent of any specific scripting language.
|
||||
This allows a script in any language for which a parser exists to be run by the interpreter.
|
||||
|
||||
The AST is produced by an <n_Parser> object. It consists of a <GlobalBlock> with an arbitrary amount of statements. These statements are
|
||||
run in order by an <n_Interpreter> object. A statement may in turn run another block (such as an if statement might if its condition is
|
||||
met).
|
||||
|
||||
Articles:
|
||||
- <http://en.wikipedia.org/wiki/Abstract_syntax_tree>
|
||||
*/
|
||||
var
|
||||
const
|
||||
/*
|
||||
Constants: Operator Precedence
|
||||
OOP_OR - Logical or
|
||||
OOP_AND - Logical and
|
||||
OOP_BIT - Bitwise operations
|
||||
OOP_EQUAL - Equality checks
|
||||
OOP_COMPARE - Greater than, less then, etc
|
||||
OOP_ADD - Addition and subtraction
|
||||
OOP_MULTIPLY - Multiplication and division
|
||||
OOP_POW - Exponents
|
||||
OOP_UNARY - Unary Operators
|
||||
OOP_GROUP - Parentheses
|
||||
*/
|
||||
OOP_OR = 1 //||
|
||||
OOP_AND = OOP_OR + 1 //&&
|
||||
OOP_BIT = OOP_AND + 1 //&, |
|
||||
OOP_EQUAL = OOP_BIT + 1 //==, !=
|
||||
OOP_COMPARE = OOP_EQUAL + 1 //>, <, >=, <=
|
||||
OOP_ADD = OOP_COMPARE + 1 //+, -
|
||||
OOP_MULTIPLY= OOP_ADD + 1 //*, /, %
|
||||
OOP_POW = OOP_MULTIPLY+ 1 //^
|
||||
OOP_UNARY = OOP_POW + 1 //!
|
||||
OOP_GROUP = OOP_UNARY + 1 //()
|
||||
|
||||
/*
|
||||
Class: node
|
||||
*/
|
||||
/node
|
||||
proc
|
||||
ToString()
|
||||
return "[src.type]"
|
||||
/*
|
||||
Class: identifier
|
||||
*/
|
||||
/node/identifier
|
||||
var
|
||||
id_name
|
||||
|
||||
New(id)
|
||||
.=..()
|
||||
src.id_name=id
|
||||
|
||||
ToString()
|
||||
return id_name
|
||||
|
||||
/*
|
||||
Class: expression
|
||||
*/
|
||||
/node/expression
|
||||
/*
|
||||
Class: operator
|
||||
See <Binary Operators> and <Unary Operators> for subtypes.
|
||||
*/
|
||||
/node/expression/operator
|
||||
var
|
||||
node/expression/exp
|
||||
tmp
|
||||
name
|
||||
precedence
|
||||
|
||||
New()
|
||||
.=..()
|
||||
if(!src.name) src.name="[src.type]"
|
||||
|
||||
ToString()
|
||||
return "operator: [name]"
|
||||
|
||||
/*
|
||||
Class: FunctionCall
|
||||
*/
|
||||
/node/expression/FunctionCall
|
||||
//Function calls can also be expressions or statements.
|
||||
var
|
||||
func_name
|
||||
node/identifier/object
|
||||
list/parameters=new
|
||||
|
||||
/*
|
||||
Class: literal
|
||||
*/
|
||||
/node/expression/value/literal
|
||||
var
|
||||
value
|
||||
|
||||
New(value)
|
||||
.=..()
|
||||
src.value=value
|
||||
|
||||
ToString()
|
||||
return src.value
|
||||
|
||||
/*
|
||||
Class: variable
|
||||
*/
|
||||
/node/expression/value/variable
|
||||
var
|
||||
node
|
||||
object //Either a node/identifier or another node/expression/value/variable which points to the object
|
||||
node/identifier
|
||||
id
|
||||
|
||||
|
||||
New(ident)
|
||||
.=..()
|
||||
id=ident
|
||||
if(istext(id))id=new(id)
|
||||
|
||||
ToString()
|
||||
return src.id.ToString()
|
||||
|
||||
/*
|
||||
Class: reference
|
||||
*/
|
||||
/node/expression/value/reference
|
||||
var
|
||||
datum/value
|
||||
|
||||
New(value)
|
||||
.=..()
|
||||
src.value=value
|
||||
|
||||
ToString()
|
||||
return "ref: [src.value] ([src.value.type])"
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
File: Block Types
|
||||
*/
|
||||
/*
|
||||
Class: BlockDefinition
|
||||
An object representing a set of actions to perform independently from the rest of the script. Blocks are basically just
|
||||
lists of statements to execute which also contain some local variables and methods. Note that since functions are local to a block,
|
||||
it is possible to have a function definition inside of any type of block (such as in an if statement or another function),
|
||||
and not just in the global scope as in many languages.
|
||||
*/
|
||||
/node/BlockDefinition
|
||||
var/list
|
||||
statements = new
|
||||
functions = new
|
||||
initial_variables = new
|
||||
|
||||
proc
|
||||
/*
|
||||
Proc: SetVar
|
||||
Defines a permanent variable. The variable will not be deleted when it goes out of scope.
|
||||
|
||||
Notes:
|
||||
Since all pre-existing temporary variables are deleted, it is not generally desirable to use this proc after the interpreter has been instantiated.
|
||||
Instead, use <n_Interpreter.SetVar()>.
|
||||
|
||||
See Also:
|
||||
- <n_Interpreter.SetVar()>
|
||||
*/
|
||||
SetVar(name, value)
|
||||
initial_variables[name]=value
|
||||
|
||||
|
||||
/*
|
||||
Class: GlobalBlock
|
||||
A block object representing the global scope.
|
||||
*/
|
||||
//
|
||||
GlobalBlock
|
||||
New()
|
||||
initial_variables["null"]=null
|
||||
return ..()
|
||||
|
||||
/*
|
||||
Class: FunctionBlock
|
||||
A block representing a function body.
|
||||
*/
|
||||
//
|
||||
FunctionBlock
|
||||
@@ -1,174 +0,0 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
|
||||
|
||||
/*
|
||||
File: Binary Operators
|
||||
*/
|
||||
/*
|
||||
Class: binary
|
||||
Represents a binary operator in the AST. A binary operator takes two operands (ie x and y) and returns a value.
|
||||
*/
|
||||
/node/expression/operator/binary
|
||||
var/node/expression/exp2
|
||||
|
||||
////////// Comparison Operators //////////
|
||||
/*
|
||||
Class: Equal
|
||||
Returns true if x = y.
|
||||
*/
|
||||
//
|
||||
Equal
|
||||
precedence=OOP_EQUAL
|
||||
|
||||
/*
|
||||
Class: NotEqual
|
||||
Returns true if x and y aren't equal.
|
||||
*/
|
||||
//
|
||||
NotEqual
|
||||
precedence=OOP_EQUAL
|
||||
|
||||
/*
|
||||
Class: Greater
|
||||
Returns true if x > y.
|
||||
*/
|
||||
//
|
||||
Greater
|
||||
precedence=OOP_COMPARE
|
||||
|
||||
/*
|
||||
Class: Less
|
||||
Returns true if x < y.
|
||||
*/
|
||||
//
|
||||
Less
|
||||
precedence=OOP_COMPARE
|
||||
|
||||
/*
|
||||
Class: GreaterOrEqual
|
||||
Returns true if x >= y.
|
||||
*/
|
||||
//
|
||||
GreaterOrEqual
|
||||
precedence=OOP_COMPARE
|
||||
|
||||
/*
|
||||
Class: LessOrEqual
|
||||
Returns true if x <= y.
|
||||
*/
|
||||
//
|
||||
LessOrEqual
|
||||
precedence=OOP_COMPARE
|
||||
|
||||
|
||||
////////// Logical Operators //////////
|
||||
|
||||
/*
|
||||
Class: LogicalAnd
|
||||
Returns true if x and y are true.
|
||||
*/
|
||||
//
|
||||
LogicalAnd
|
||||
precedence=OOP_AND
|
||||
|
||||
/*
|
||||
Class: LogicalOr
|
||||
Returns true if x, y, or both are true.
|
||||
*/
|
||||
//
|
||||
LogicalOr
|
||||
precedence=OOP_OR
|
||||
|
||||
/*
|
||||
Class: LogicalXor
|
||||
Returns true if either x or y but not both are true.
|
||||
*/
|
||||
//
|
||||
LogicalXor //Not implemented in nS
|
||||
precedence=OOP_OR
|
||||
|
||||
|
||||
////////// Bitwise Operators //////////
|
||||
|
||||
/*
|
||||
Class: BitwiseAnd
|
||||
Performs a bitwise and operation.
|
||||
|
||||
Example:
|
||||
011 & 110 = 010
|
||||
*/
|
||||
//
|
||||
BitwiseAnd
|
||||
precedence=OOP_BIT
|
||||
|
||||
/*
|
||||
Class: BitwiseOr
|
||||
Performs a bitwise or operation.
|
||||
|
||||
Example:
|
||||
011 | 110 = 111
|
||||
*/
|
||||
//
|
||||
BitwiseOr
|
||||
precedence=OOP_BIT
|
||||
|
||||
/*
|
||||
Class: BitwiseXor
|
||||
Performs a bitwise exclusive or operation.
|
||||
|
||||
Example:
|
||||
011 xor 110 = 101
|
||||
*/
|
||||
//
|
||||
BitwiseXor
|
||||
precedence=OOP_BIT
|
||||
|
||||
|
||||
////////// Arithmetic Operators //////////
|
||||
|
||||
/*
|
||||
Class: Add
|
||||
Returns the sum of x and y.
|
||||
*/
|
||||
//
|
||||
Add
|
||||
precedence=OOP_ADD
|
||||
|
||||
/*
|
||||
Class: Subtract
|
||||
Returns the difference of x and y.
|
||||
*/
|
||||
//
|
||||
Subtract
|
||||
precedence=OOP_ADD
|
||||
|
||||
/*
|
||||
Class: Multiply
|
||||
Returns the product of x and y.
|
||||
*/
|
||||
//
|
||||
Multiply
|
||||
precedence=OOP_MULTIPLY
|
||||
|
||||
/*
|
||||
Class: Divide
|
||||
Returns the quotient of x and y.
|
||||
*/
|
||||
//
|
||||
Divide
|
||||
precedence=OOP_MULTIPLY
|
||||
|
||||
/*
|
||||
Class: Power
|
||||
Returns x raised to the power of y.
|
||||
*/
|
||||
//
|
||||
Power
|
||||
precedence=OOP_POW
|
||||
|
||||
/*
|
||||
Class: Modulo
|
||||
Returns the remainder of x / y.
|
||||
*/
|
||||
//
|
||||
Modulo
|
||||
precedence=OOP_MULTIPLY
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
File: Unary Operators
|
||||
*/
|
||||
/*
|
||||
Class: unary
|
||||
Represents a unary operator in the AST. Unary operators take a single operand (referred to as x below) and return a value.
|
||||
*/
|
||||
/node/expression/operator/unary
|
||||
precedence=OOP_UNARY
|
||||
|
||||
/*
|
||||
Class: LogicalNot
|
||||
Returns !x.
|
||||
|
||||
Example:
|
||||
!true = false and !false = true
|
||||
*/
|
||||
//
|
||||
LogicalNot
|
||||
name="logical not"
|
||||
|
||||
/*
|
||||
Class: BitwiseNot
|
||||
Returns the value of a bitwise not operation performed on x.
|
||||
|
||||
Example:
|
||||
~10 (decimal 2) = 01 (decimal 1).
|
||||
*/
|
||||
//
|
||||
BitwiseNot
|
||||
name="bitwise not"
|
||||
|
||||
/*
|
||||
Class: Minus
|
||||
Returns -x.
|
||||
*/
|
||||
//
|
||||
Minus
|
||||
name="minus"
|
||||
|
||||
/*
|
||||
Class: group
|
||||
A special unary operator representing a value in parentheses.
|
||||
*/
|
||||
//
|
||||
group
|
||||
precedence=OOP_GROUP
|
||||
|
||||
New(node/expression/exp)
|
||||
src.exp=exp
|
||||
return ..()
|
||||
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
File: Statement Types
|
||||
*/
|
||||
/*
|
||||
Class: statement
|
||||
An object representing a single instruction run by an interpreter.
|
||||
*/
|
||||
/node/statement
|
||||
/*
|
||||
Class: FunctionCall
|
||||
Represents a call to a function.
|
||||
*/
|
||||
//
|
||||
FunctionCall
|
||||
var
|
||||
func_name
|
||||
node/identifier/object
|
||||
list/parameters=new
|
||||
|
||||
/*
|
||||
Class: FunctionDefinition
|
||||
Defines a function.
|
||||
*/
|
||||
//
|
||||
FunctionDefinition
|
||||
var
|
||||
func_name
|
||||
list/parameters=new
|
||||
node/BlockDefinition/FunctionBlock/block
|
||||
|
||||
/*
|
||||
Class: VariableAssignment
|
||||
Sets a variable in an accessible scope to the given value if one exists, otherwise initializes a new local variable to the given value.
|
||||
|
||||
Notes:
|
||||
If a variable with the same name exists in a higher block, the value will be assigned to it. If not,
|
||||
a new variable is created in the current block. To force creation of a new variable, use <VariableDeclaration>.
|
||||
|
||||
See Also:
|
||||
- <VariableDeclaration>
|
||||
*/
|
||||
//
|
||||
VariableAssignment
|
||||
var
|
||||
node
|
||||
identifier
|
||||
object
|
||||
var_name
|
||||
expression/value
|
||||
|
||||
/*
|
||||
Class: VariableDeclaration
|
||||
Intializes a local variable to a null value.
|
||||
|
||||
See Also:
|
||||
- <VariableAssignment>
|
||||
*/
|
||||
//
|
||||
VariableDeclaration
|
||||
var
|
||||
node
|
||||
identifier
|
||||
object
|
||||
var_name
|
||||
|
||||
/*
|
||||
Class: IfStatement
|
||||
*/
|
||||
//
|
||||
IfStatement
|
||||
var
|
||||
node
|
||||
BlockDefinition
|
||||
block
|
||||
else_block //may be null
|
||||
expression/cond
|
||||
|
||||
/*
|
||||
Class: WhileLoop
|
||||
Loops while a given condition is true.
|
||||
*/
|
||||
//
|
||||
WhileLoop
|
||||
var
|
||||
node
|
||||
BlockDefinition/block
|
||||
expression/cond
|
||||
|
||||
/*
|
||||
Class: ForLoop
|
||||
Loops while test is true, initializing a variable, increasing the variable
|
||||
*/
|
||||
ForLoop
|
||||
var
|
||||
node
|
||||
BlockDefinition/block
|
||||
expression/test
|
||||
expression/init
|
||||
expression/increment
|
||||
|
||||
/*
|
||||
Class: BreakStatement
|
||||
Ends a loop.
|
||||
*/
|
||||
//
|
||||
BreakStatement
|
||||
|
||||
/*
|
||||
Class: ContinueStatement
|
||||
Skips to the next iteration of a loop.
|
||||
*/
|
||||
//
|
||||
ContinueStatement
|
||||
|
||||
/*
|
||||
Class: ReturnStatement
|
||||
Ends the function and returns a value.
|
||||
*/
|
||||
//
|
||||
ReturnStatement
|
||||
var
|
||||
node/expression/value
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
File: Errors
|
||||
*/
|
||||
/*
|
||||
Class: scriptError
|
||||
An error scanning or parsing the source code.
|
||||
*/
|
||||
/scriptError
|
||||
var
|
||||
/*
|
||||
Var: message
|
||||
A message describing the problem.
|
||||
*/
|
||||
message
|
||||
New(msg=null)
|
||||
if(msg)message=msg
|
||||
|
||||
BadToken
|
||||
message="Unexpected token: "
|
||||
var/token/token
|
||||
New(token/t)
|
||||
token=t
|
||||
if(t&&t.line) message="[t.line]: [message]"
|
||||
if(istype(t))message+="[t.value]"
|
||||
else message+="[t]"
|
||||
|
||||
InvalidID
|
||||
parent_type=/scriptError/BadToken
|
||||
message="Invalid identifier name: "
|
||||
|
||||
ReservedWord
|
||||
parent_type=/scriptError/BadToken
|
||||
message="Identifer using reserved word: "
|
||||
|
||||
BadNumber
|
||||
parent_type=/scriptError/BadToken
|
||||
message = "Bad number: "
|
||||
|
||||
BadReturn
|
||||
var/token/token
|
||||
message = "Unexpected return statement outside of a function."
|
||||
New(token/t)
|
||||
src.token=t
|
||||
|
||||
EndOfFile
|
||||
message = "Unexpected end of file."
|
||||
|
||||
ExpectedToken
|
||||
message="Expected: '"
|
||||
New(id, token/T)
|
||||
if(T && T.line) message="[T.line]: [message]"
|
||||
message+="[id]'. "
|
||||
if(T)message+="Found '[T.value]'."
|
||||
|
||||
|
||||
UnterminatedComment
|
||||
message="Unterminated multi-line comment statement: expected */"
|
||||
|
||||
DuplicateFunction
|
||||
New(name, token/t)
|
||||
message="Function '[name]' defined twice."
|
||||
|
||||
/*
|
||||
Class: runtimeError
|
||||
An error thrown by the interpreter in running the script.
|
||||
*/
|
||||
/runtimeError
|
||||
var
|
||||
name
|
||||
/*
|
||||
Var: message
|
||||
A basic description as to what went wrong.
|
||||
*/
|
||||
message
|
||||
stack/stack
|
||||
|
||||
proc
|
||||
/*
|
||||
Proc: ToString
|
||||
Returns a description of the error suitable for showing to the user.
|
||||
*/
|
||||
ToString()
|
||||
. = "[name]: [message]"
|
||||
if(!stack.Top()) return
|
||||
.+="\nStack:"
|
||||
while(stack.Top())
|
||||
var/node/statement/FunctionCall/stmt=stack.Pop()
|
||||
. += "\n\t [stmt.func_name]()"
|
||||
|
||||
TypeMismatch
|
||||
name="TypeMismatchError"
|
||||
New(op, a, b)
|
||||
message="Type mismatch: '[a]' [op] '[b]'"
|
||||
|
||||
UnexpectedReturn
|
||||
name="UnexpectedReturnError"
|
||||
message="Unexpected return statement."
|
||||
|
||||
UnknownInstruction
|
||||
name="UnknownInstructionError"
|
||||
message="Unknown instruction type. This may be due to incompatible compiler and interpreter versions or a lack of implementation."
|
||||
|
||||
UndefinedVariable
|
||||
name="UndefinedVariableError"
|
||||
New(variable)
|
||||
message="Variable '[variable]' has not been declared."
|
||||
|
||||
UndefinedFunction
|
||||
name="UndefinedFunctionError"
|
||||
New(function)
|
||||
message="Function '[function]()' has not been defined."
|
||||
|
||||
DuplicateVariableDeclaration
|
||||
name="DuplicateVariableError"
|
||||
New(variable)
|
||||
message="Variable '[variable]' was already declared."
|
||||
|
||||
IterationLimitReached
|
||||
name="MaxIterationError"
|
||||
message="A loop has reached its maximum number of iterations."
|
||||
|
||||
RecursionLimitReached
|
||||
name="MaxRecursionError"
|
||||
message="The maximum amount of recursion has been reached."
|
||||
|
||||
DivisionByZero
|
||||
name="DivideByZeroError"
|
||||
message="Division by zero attempted."
|
||||
|
||||
MaxCPU
|
||||
name="MaxComputationalUse"
|
||||
message="Maximum amount of computational cycles reached (>= 1000)."
|
||||
@@ -1,210 +0,0 @@
|
||||
client/verb/tcssave()
|
||||
set hidden = 1
|
||||
if(mob.machine || issilicon(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
|
||||
if(Machine.editingcode != mob)
|
||||
return
|
||||
|
||||
if(Machine.SelectedServer)
|
||||
var/obj/machinery/telecomms/server/Server = Machine.SelectedServer
|
||||
var/tcscode=winget(src, "tcscode", "text")
|
||||
var/msg="[mob.name] is adding script to server [Server]: [tcscode]"
|
||||
log_misc(msg)
|
||||
message_admins("[mob.name] has uploaded a NTLS script to [Machine.SelectedServer] ([mob.x],[mob.y],[mob.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[mob.x];Y=[mob.y];Z=[mob.z]'>JMP</a>)",0,1)
|
||||
Server.setcode( tcscode ) // this actually saves the code from input to the server
|
||||
send_output(src, null, "tcserror") // clear the errors)
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to save: Unable to locate server machine. (Back up your code before exiting the window!)</font>", "tcserror")
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to save: Unable to locate machine. (Back up your code before exiting the window!)</font>", "tcserror")
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to save: Unable to locate machine. (Back up your code before exiting the window!)</font>", "tcserror")
|
||||
|
||||
|
||||
client/verb/tcscompile()
|
||||
set hidden = 1
|
||||
if(mob.machine || issilicon(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
|
||||
if(Machine.editingcode != mob)
|
||||
return
|
||||
|
||||
if(Machine.SelectedServer)
|
||||
var/obj/machinery/telecomms/server/Server = Machine.SelectedServer
|
||||
Server.setcode( winget(src, "tcscode", "text") ) // save code first
|
||||
var/list/compileerrors = Server.compile() // then compile the code!
|
||||
|
||||
// Output all the compile-time errors
|
||||
send_output(src, null, "tcserror")
|
||||
|
||||
if(compileerrors.len)
|
||||
to_chat(src, "<b>Compile Errors</b>", "tcserror")
|
||||
for(var/scriptError/e in compileerrors)
|
||||
send_output(src, "<font color = red>\t>[e.message]</font>", "tcserror")
|
||||
send_output(src, "([compileerrors.len] errors)", "tcserror")
|
||||
|
||||
// Output compile errors to all other people viewing the code too
|
||||
for(var/mob/M in Machine.viewingcode)
|
||||
if(M.client)
|
||||
send_output(M, null, "tcserror")
|
||||
send_output(M, "<b>Compile Errors</b>", "tcserror")
|
||||
for(var/scriptError/e in compileerrors)
|
||||
send_output(M, "<font color = red>\t>[e.message]</font>", "tcserror")
|
||||
send_output(M, "([compileerrors.len] errors)", "tcserror")
|
||||
|
||||
|
||||
else
|
||||
send_output(src, "<font color = blue>TCS compilation successful!</font>", "tcserror")
|
||||
send_output(src, "(0 errors)", "tcserror")
|
||||
|
||||
for(var/mob/M in Machine.viewingcode)
|
||||
if(M.client)
|
||||
send_output(M, "<font color = blue>TCS compilation successful!</font>", "tcserror")
|
||||
send_output(M, "(0 errors)", "tcserror")
|
||||
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to compile: Unable to locate server machine. (Back up your code before exiting the window!)</font>", "tcserror")
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to compile: Unable to locate machine. (Back up your code before exiting the window!)</font>", "tcserror")
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to compile: Unable to locate machine. (Back up your code before exiting the window!)</font>", "tcserror")
|
||||
|
||||
client/verb/tcsrun()
|
||||
set hidden = 1
|
||||
if(mob.machine || issilicon(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
|
||||
if(Machine.editingcode != mob)
|
||||
return
|
||||
|
||||
if(Machine.SelectedServer)
|
||||
var/obj/machinery/telecomms/server/Server = Machine.SelectedServer
|
||||
Server.setcode( winget(src, "tcscode", "text") ) // save code first
|
||||
var/list/compileerrors = Server.compile() // then compile the code!
|
||||
|
||||
// Output all the compile-time errors
|
||||
send_output(src, null, "tcserror")
|
||||
|
||||
if(compileerrors.len)
|
||||
send_output(src, "<b>Compile Errors</b>", "tcserror")
|
||||
for(var/scriptError/e in compileerrors)
|
||||
send_output(src, "<font color = red>\t>[e.message]</font>", "tcserror")
|
||||
send_output(src, "([compileerrors.len] errors)", "tcserror")
|
||||
|
||||
// Output compile errors to all other people viewing the code too
|
||||
for(var/mob/M in Machine.viewingcode)
|
||||
if(M.client)
|
||||
send_output(M, null, "tcserror")
|
||||
send_output(M, "<b>Compile Errors</b>", "tcserror")
|
||||
for(var/scriptError/e in compileerrors)
|
||||
send_output(M, "<font color = red>\t>[e.message]</font>", "tcserror")
|
||||
send_output(M, "([compileerrors.len] errors)", "tcserror")
|
||||
else
|
||||
// Finally, we run the code!
|
||||
send_output(src, "<font color = blue>TCS compilation successful! Code executed.</font>", "tcserror")
|
||||
send_output(src, "(0 errors)", "tcserror")
|
||||
|
||||
for(var/mob/M in Machine.viewingcode)
|
||||
if(M.client)
|
||||
send_output(M, "<font color = blue>TCS compilation successful!</font>", "tcserror")
|
||||
send_output(M, "(0 errors)", "tcserror")
|
||||
|
||||
var/datum/signal/signal = new()
|
||||
signal.data["message"] = ""
|
||||
if(Server.freq_listening.len > 0)
|
||||
signal.frequency = Server.freq_listening[1]
|
||||
else
|
||||
signal.frequency = PUB_FREQ
|
||||
signal.data["name"] = ""
|
||||
signal.data["job"] = ""
|
||||
signal.data["reject"] = 0
|
||||
signal.data["server"] = Server
|
||||
|
||||
Server.Compiler.Run(signal)
|
||||
|
||||
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to run: Unable to locate server machine. (Back up your code before exiting the window!)</font>", "tcserror")
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to run: Unable to locate machine. (Back up your code before exiting the window!)</font>", "tcserror")
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to run: Unable to locate machine. (Back up your code before exiting the window!)</font>", "tcserror")
|
||||
|
||||
|
||||
client/verb/exittcs()
|
||||
set hidden = 1
|
||||
if(mob.machine || issilicon(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
|
||||
if(Machine.editingcode == mob)
|
||||
Machine.storedcode = "[winget(mob, "tcscode", "text")]"
|
||||
Machine.editingcode = null
|
||||
else
|
||||
if(mob in Machine.viewingcode)
|
||||
Machine.viewingcode.Remove(mob)
|
||||
|
||||
client/verb/tcsrevert()
|
||||
set hidden = 1
|
||||
if(mob.machine || issilicon(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
|
||||
if(Machine.editingcode != mob)
|
||||
return
|
||||
|
||||
if(Machine.SelectedServer)
|
||||
var/obj/machinery/telecomms/server/Server = Machine.SelectedServer
|
||||
|
||||
// Replace quotation marks with quotation macros for proper winset() compatibility
|
||||
var/showcode = replacetext(Server.rawcode, "\\\"", "\\\\\"")
|
||||
showcode = replacetext(showcode, "\"", "\\\"")
|
||||
|
||||
winset(mob, "tcscode", "text=\"[showcode]\"")
|
||||
|
||||
send_output(src, null, "tcserror") // clear the errors
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to revert: Unable to locate server machine.</font>", "tcserror")
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to revert: Unable to locate machine.</font>", "tcserror")
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to revert: Unable to locate machine.</font>", "tcserror")
|
||||
|
||||
|
||||
client/verb/tcsclearmem()
|
||||
set hidden = 1
|
||||
if(mob.machine || issilicon(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
|
||||
if(Machine.editingcode != mob)
|
||||
return
|
||||
|
||||
if(Machine.SelectedServer)
|
||||
var/obj/machinery/telecomms/server/Server = Machine.SelectedServer
|
||||
Server.memory = list() // clear the memory
|
||||
// Show results
|
||||
to_chat(src, null, "tcserror")
|
||||
to_chat(src, "<font color = blue>Server memory cleared!</font>", "tcserror")
|
||||
for(var/mob/M in Machine.viewingcode)
|
||||
if(M.client)
|
||||
send_output(M, "<font color = blue>Server memory cleared!</font>", "tcserror")
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to clear memory: Unable to locate server machine.</font>", "tcserror")
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to clear memory: Unable to locate machine.</font>", "tcserror")
|
||||
else
|
||||
send_output(src, null, "tcserror")
|
||||
send_output(src, "<font color = red>Failed to clear memory: Unable to locate machine.</font>", "tcserror")
|
||||
@@ -1,237 +0,0 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
|
||||
|
||||
|
||||
/* --- Traffic Control Scripting Language --- */
|
||||
// NanoTrasen TCS Language - Made by Doohl
|
||||
|
||||
/n_Interpreter/TCS_Interpreter
|
||||
var/datum/TCS_Compiler/Compiler
|
||||
|
||||
HandleError(runtimeError/e)
|
||||
Compiler.Holder.add_entry(e.ToString(), "Execution Error")
|
||||
|
||||
/datum/TCS_Compiler
|
||||
var/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
|
||||
|
||||
/* -- 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()
|
||||
|
||||
var/list/returnerrors = list()
|
||||
|
||||
returnerrors += scanner.errors
|
||||
returnerrors += parser.errors
|
||||
|
||||
if(returnerrors.len)
|
||||
return returnerrors
|
||||
|
||||
interpreter = new(program)
|
||||
interpreter.persist = 1
|
||||
interpreter.Compiler= src
|
||||
|
||||
return returnerrors
|
||||
|
||||
/* -- Execute the compiled code -- */
|
||||
|
||||
proc/Run(var/datum/signal/subspace/vocal/signal)
|
||||
|
||||
if(!ready)
|
||||
return
|
||||
|
||||
if(!interpreter)
|
||||
return
|
||||
|
||||
interpreter.container = src
|
||||
|
||||
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.SetVar("NORTH" , NORTH) // NORTH (1)
|
||||
interpreter.SetVar("SOUTH" , SOUTH) // SOUTH (2)
|
||||
interpreter.SetVar("EAST" , EAST) // EAST (4)
|
||||
interpreter.SetVar("WEST" , WEST) // WEST (8)
|
||||
|
||||
//Language macros
|
||||
interpreter.SetVar("L_BASIC", LANGUAGE_TCB)
|
||||
interpreter.SetVar("L_SOL", LANGUAGE_SOL_COMMON)
|
||||
interpreter.SetVar("L_ELYRAN", LANGUAGE_ELYRAN_STANDARD)
|
||||
interpreter.SetVar("L_TRADE", LANGUAGE_TRADEBAND)
|
||||
interpreter.SetVar("L_GUTTER", LANGUAGE_GUTTER)
|
||||
interpreter.SetVar("L_MAAS", LANGUAGE_SIIK_MAAS)
|
||||
interpreter.SetVar("L_YASSA", LANGUAGE_YA_SSA)
|
||||
interpreter.SetVar("L_DELVAHII",LANGUAGE_DELVAHII)
|
||||
interpreter.SetVar("L_DIONAEA", LANGUAGE_ROOTSONG)
|
||||
interpreter.SetVar("L_UNATHI", LANGUAGE_UNATHI)
|
||||
interpreter.SetVar("L_SKRELL", LANGUAGE_SKRELLIAN)
|
||||
interpreter.SetVar("L_VAURCA", LANGUAGE_VAURCA)
|
||||
interpreter.SetVar("L_MACHINE", LANGUAGE_EAL)
|
||||
|
||||
// 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)
|
||||
|
||||
// Signal data
|
||||
|
||||
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("$language" , signal.data["language"])
|
||||
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
|
||||
|
||||
// Set up the script procs
|
||||
|
||||
/*
|
||||
-> Send another signal to a server
|
||||
@format: broadcast(content, frequency, source, job)
|
||||
|
||||
@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.
|
||||
@param language: The language used for the broadcast
|
||||
*/
|
||||
interpreter.SetProc("broadcast", "broadcast", signal, list("message", "freq", "source", "job", "language"))
|
||||
|
||||
/*
|
||||
-> Store a value permanently to the server machine (not the actual game hosting machine, the ingame machine)
|
||||
@format: mem(address, value)
|
||||
|
||||
@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"))
|
||||
|
||||
/*
|
||||
-> Delay code for a given amount of deciseconds
|
||||
@format: sleep(time)
|
||||
|
||||
@param time: time to sleep in deciseconds (1/10th second)
|
||||
*/
|
||||
interpreter.SetProc("sleep", /proc/delay)
|
||||
|
||||
/*
|
||||
-> Replaces a string with another string
|
||||
@format: replace(string, substring, replacestring)
|
||||
|
||||
@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
|
||||
|
||||
*/
|
||||
interpreter.SetProc("replace", /proc/string_replacetext)
|
||||
|
||||
/*
|
||||
-> Locates an element/substring inside of a list or string
|
||||
@format: find(haystack, needle, start = 1, end = 0)
|
||||
|
||||
@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)
|
||||
|
||||
// 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
|
||||
interpreter.Run()
|
||||
|
||||
// Backwards-apply variables onto signal data
|
||||
/* sanitize EVERYTHING. fucking players can't be trusted with SHIT */
|
||||
|
||||
signal.data["message"] = interpreter.GetVar("$content")
|
||||
signal.frequency = interpreter.GetVar("$freq")
|
||||
|
||||
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>"
|
||||
|
||||
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
|
||||
|
||||
// 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
|
||||
@@ -1,261 +0,0 @@
|
||||
// Script -> BYOND code procs
|
||||
#define SCRIPT_MAX_REPLACEMENTS_ALLOWED 200
|
||||
// --- List operations (lists known as vectors in n_script) ---
|
||||
|
||||
// Clone of list()
|
||||
/proc/n_list()
|
||||
var/list/returnlist = list()
|
||||
for(var/e in args)
|
||||
returnlist.Add(e)
|
||||
return returnlist
|
||||
|
||||
// Clone of pick()
|
||||
/proc/n_pick()
|
||||
var/list/finalpick = list()
|
||||
for(var/e in args)
|
||||
if(isobject(e))
|
||||
if(istype(e, /list))
|
||||
var/list/sublist = e
|
||||
for(var/sube in sublist)
|
||||
finalpick.Add(sube)
|
||||
continue
|
||||
finalpick.Add(e)
|
||||
|
||||
return pick(finalpick)
|
||||
|
||||
// Clone of list[]
|
||||
/proc/n_listpos(var/list/L, var/pos, var/value)
|
||||
if(!istype(L, /list)) return
|
||||
if(isnum(pos))
|
||||
if(!value)
|
||||
if(L.len >= pos)
|
||||
return L[pos]
|
||||
else
|
||||
if(L.len >= pos)
|
||||
L[pos] = value
|
||||
else if(istext(pos))
|
||||
if(!value)
|
||||
return L[pos]
|
||||
else
|
||||
L[pos] = value
|
||||
|
||||
// Clone of list.Copy()
|
||||
/proc/n_listcopy(var/list/L, var/start, var/end)
|
||||
if(!istype(L, /list)) return
|
||||
return L.Copy(start, end)
|
||||
|
||||
// Clone of list.Add()
|
||||
/proc/n_listadd()
|
||||
var/list/chosenlist
|
||||
var/i = 1
|
||||
for(var/e in args)
|
||||
if(i == 1)
|
||||
if(isobject(e))
|
||||
if(istype(e, /list))
|
||||
chosenlist = e
|
||||
i = 2
|
||||
else
|
||||
if(chosenlist)
|
||||
chosenlist.Add(e)
|
||||
|
||||
// Clone of list.Remove()
|
||||
/proc/n_listremove()
|
||||
var/list/chosenlist
|
||||
var/i = 1
|
||||
for(var/e in args)
|
||||
if(i == 1)
|
||||
if(isobject(e))
|
||||
if(istype(e, /list))
|
||||
chosenlist = e
|
||||
i = 2
|
||||
else
|
||||
if(chosenlist)
|
||||
chosenlist.Remove(e)
|
||||
|
||||
// Clone of list.Cut()
|
||||
/proc/n_listcut(var/list/L, var/start, var/end)
|
||||
if(!istype(L, /list)) return
|
||||
return L.Cut(start, end)
|
||||
|
||||
// Clone of list.Swap()
|
||||
/proc/n_listswap(var/list/L, var/firstindex, var/secondindex)
|
||||
if(!istype(L, /list)) return
|
||||
if(L.len >= secondindex && L.len >= firstindex)
|
||||
return L.Swap(firstindex, secondindex)
|
||||
|
||||
// Clone of list.Insert()
|
||||
/proc/n_listinsert(var/list/L, var/index, var/element)
|
||||
if(!istype(L, /list)) return
|
||||
return L.Insert(index, element)
|
||||
|
||||
// --- Miscellaneous functions ---
|
||||
|
||||
// Clone of sleep()
|
||||
/proc/delay(var/time)
|
||||
sleep(time)
|
||||
|
||||
// Clone of prob()
|
||||
/proc/prob_chance(var/chance)
|
||||
return prob(chance)
|
||||
|
||||
// Merge of list.Find() and findtext()
|
||||
/proc/smartfind(var/haystack, var/needle, var/start = 1, var/end = 0)
|
||||
if(haystack && needle)
|
||||
if(isobject(haystack))
|
||||
if(istype(haystack, /list))
|
||||
if(length(haystack) >= end && start > 0)
|
||||
var/list/listhaystack = haystack
|
||||
return listhaystack.Find(needle, start, end)
|
||||
|
||||
else
|
||||
if(istext(haystack))
|
||||
if(length(haystack) >= end && start > 0)
|
||||
return findtext(haystack, needle, start, end)
|
||||
|
||||
// Clone of copytext()
|
||||
/proc/docopytext(var/string, var/start = 1, var/end = 0)
|
||||
if(istext(string) && isnum(start) && isnum(end))
|
||||
if(start > 0)
|
||||
return copytext(string, start, end)
|
||||
|
||||
// Clone of length()
|
||||
/proc/smartlength(var/container)
|
||||
if(container)
|
||||
if(istype(container, /list) || istext(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<=length(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<=length(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, length(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 text2list(string, separator)
|
||||
|
||||
/proc/n_repeat(var/string, var/amount)
|
||||
if(istext(string) && isnum(amount))
|
||||
var/i
|
||||
var/newstring = ""
|
||||
if(length(newstring)*amount >=1000)
|
||||
return
|
||||
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=length(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)
|
||||
|
||||
|
||||
|
||||
// Non-recursive
|
||||
// Imported from Mono string.ReplaceUnchecked
|
||||
/proc/string_replacetext(var/haystack,var/a,var/b)
|
||||
if(istext(haystack)&&istext(a)&&istext(b))
|
||||
var/i = 1
|
||||
var/lenh=length(haystack)
|
||||
var/lena=length(a)
|
||||
//var/lenb=length(b)
|
||||
var/count = 0
|
||||
var/list/dat = list()
|
||||
while (i < lenh)
|
||||
var/found = findtext(haystack, a, i, 0)
|
||||
//log_misc("findtext([haystack], [a], [i], 0)=[found]")
|
||||
if (found == 0) // Not found
|
||||
break
|
||||
else
|
||||
if (count < SCRIPT_MAX_REPLACEMENTS_ALLOWED)
|
||||
dat+=found
|
||||
count+=1
|
||||
else
|
||||
//log_misc("Script found [a] [count] times, aborted")
|
||||
break
|
||||
//log_misc("Found [a] at [found]! Moving up...")
|
||||
i = found + lena
|
||||
if (count == 0)
|
||||
return haystack
|
||||
//var/nlen = lenh + ((lenb - lena) * count)
|
||||
var/buf = copytext(haystack,1,dat[1]) // Prefill
|
||||
var/lastReadPos = 0
|
||||
for (i = 1, i <= count, i++)
|
||||
var/precopy = dat[i] - lastReadPos-1
|
||||
//internal static unsafe void CharCopy (String target, int targetIndex, String source, int sourceIndex, int count)
|
||||
//fixed (char* dest = target, src = source)
|
||||
//CharCopy (dest + targetIndex, src + sourceIndex, count);
|
||||
//CharCopy (dest + curPos, source + lastReadPos, precopy);
|
||||
buf+=copytext(haystack,lastReadPos,precopy)
|
||||
log_misc("buf+=copytext([haystack],[lastReadPos],[precopy])")
|
||||
log_misc("[buf]")
|
||||
lastReadPos = dat[i] + lena
|
||||
//CharCopy (dest + curPos, replace, newValue.length);
|
||||
buf+=b
|
||||
log_misc("[buf]")
|
||||
buf+=copytext(haystack,lastReadPos, 0)
|
||||
return buf
|
||||
@@ -1,169 +0,0 @@
|
||||
/proc/isobject(x)
|
||||
return (istype(x, /datum) || istype(x, /list) || istype(x, /savefile) || istype(x, /client) || (x==world))
|
||||
|
||||
/n_Interpreter
|
||||
proc
|
||||
Eval(node/expression/exp)
|
||||
if(istype(exp, /node/expression/FunctionCall))
|
||||
return RunFunction(exp)
|
||||
else if(istype(exp, /node/expression/operator))
|
||||
return EvalOperator(exp)
|
||||
else if(istype(exp, /node/expression/value/literal))
|
||||
var/node/expression/value/literal/lit=exp
|
||||
return lit.value
|
||||
else if(istype(exp, /node/expression/value/reference))
|
||||
var/node/expression/value/reference/ref=exp
|
||||
return ref.value
|
||||
else if(istype(exp, /node/expression/value/variable))
|
||||
var/node/expression/value/variable/v=exp
|
||||
if(!v.object)
|
||||
return Eval(GetVariable(v.id.id_name))
|
||||
else
|
||||
var/datum/D
|
||||
if(istype(v.object, /node/identifier))
|
||||
D=GetVariable(v.object:id_name)
|
||||
else
|
||||
D=v.object
|
||||
D=Eval(D)
|
||||
if(!isobject(D))
|
||||
return null
|
||||
if(!D.vars.Find(v.id.id_name))
|
||||
RaiseError(new/runtimeError/UndefinedVariable("[v.object.ToString()].[v.id.id_name]"))
|
||||
return null
|
||||
return Eval(D.vars[v.id.id_name])
|
||||
else if(istype(exp, /node/expression))
|
||||
RaiseError(new/runtimeError/UnknownInstruction())
|
||||
else
|
||||
return exp
|
||||
|
||||
EvalOperator(node/expression/operator/exp)
|
||||
if(istype(exp, /node/expression/operator/binary))
|
||||
var/node/expression/operator/binary/bin=exp
|
||||
switch(bin.type)
|
||||
if(/node/expression/operator/binary/Equal)
|
||||
return Equal(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/NotEqual)
|
||||
return NotEqual(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/Greater)
|
||||
return Greater(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/Less)
|
||||
return Less(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/GreaterOrEqual)
|
||||
return GreaterOrEqual(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/LessOrEqual)
|
||||
return LessOrEqual(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/LogicalAnd)
|
||||
return LogicalAnd(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/LogicalOr)
|
||||
return LogicalOr(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/LogicalXor)
|
||||
return LogicalXor(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/BitwiseAnd)
|
||||
return BitwiseAnd(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/BitwiseOr)
|
||||
return BitwiseOr(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/BitwiseXor)
|
||||
return BitwiseXor(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/Add)
|
||||
return Add(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/Subtract)
|
||||
return Subtract(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/Multiply)
|
||||
return Multiply(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/Divide)
|
||||
return Divide(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/Power)
|
||||
return Power(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/operator/binary/Modulo)
|
||||
return Modulo(Eval(bin.exp), Eval(bin.exp2))
|
||||
else
|
||||
RaiseError(new/runtimeError/UnknownInstruction())
|
||||
else
|
||||
switch(exp.type)
|
||||
if(/node/expression/operator/unary/Minus)
|
||||
return Minus(Eval(exp.exp))
|
||||
if(/node/expression/operator/unary/LogicalNot)
|
||||
return LogicalNot(Eval(exp.exp))
|
||||
if(/node/expression/operator/unary/BitwiseNot)
|
||||
return BitwiseNot(Eval(exp.exp))
|
||||
if(/node/expression/operator/unary/group)
|
||||
return Eval(exp.exp)
|
||||
else
|
||||
RaiseError(new/runtimeError/UnknownInstruction())
|
||||
|
||||
|
||||
//Binary//
|
||||
//Comparison operators
|
||||
Equal(a, b) return a==b
|
||||
NotEqual(a, b) return a!=b //LogicalNot(Equal(a, b))
|
||||
Greater(a, b) return a>b
|
||||
Less(a, b) return a<b
|
||||
GreaterOrEqual(a, b)return a>=b
|
||||
LessOrEqual(a, b) return a<=b
|
||||
//Logical Operators
|
||||
LogicalAnd(a, b) return a&&b
|
||||
LogicalOr(a, b) return a||b
|
||||
LogicalXor(a, b) return (a||b) && !(a&&b)
|
||||
//Bitwise Operators
|
||||
BitwiseAnd(a, b) return a&b
|
||||
BitwiseOr(a, b) return a|b
|
||||
BitwiseXor(a, b) return a^b
|
||||
//Arithmetic Operators
|
||||
Add(a, b)
|
||||
if(istext(a)&&!istext(b)) b="[b]"
|
||||
else if(istext(b)&&!istext(a)) a="[a]"
|
||||
if(isobject(a) && !isobject(b))
|
||||
RaiseError(new/runtimeError/TypeMismatch("+", a, b))
|
||||
return null
|
||||
else if(isobject(b) && !isobject(a))
|
||||
RaiseError(new/runtimeError/TypeMismatch("+", a, b))
|
||||
return null
|
||||
return a+b
|
||||
Subtract(a, b)
|
||||
if(isobject(a) && !isobject(b))
|
||||
RaiseError(new/runtimeError/TypeMismatch("-", a, b))
|
||||
return null
|
||||
else if(isobject(b) && !isobject(a))
|
||||
RaiseError(new/runtimeError/TypeMismatch("-", a, b))
|
||||
return null
|
||||
return a-b
|
||||
Divide(a, b)
|
||||
if(isobject(a) && !isobject(b))
|
||||
RaiseError(new/runtimeError/TypeMismatch("/", a, b))
|
||||
return null
|
||||
else if(isobject(b) && !isobject(a))
|
||||
RaiseError(new/runtimeError/TypeMismatch("/", a, b))
|
||||
return null
|
||||
if(b==0)
|
||||
RaiseError(new/runtimeError/DivisionByZero())
|
||||
return null
|
||||
return a/b
|
||||
Multiply(a, b)
|
||||
if(isobject(a) && !isobject(b))
|
||||
RaiseError(new/runtimeError/TypeMismatch("*", a, b))
|
||||
return null
|
||||
else if(isobject(b) && !isobject(a))
|
||||
RaiseError(new/runtimeError/TypeMismatch("*", a, b))
|
||||
return null
|
||||
return a*b
|
||||
Modulo(a, b)
|
||||
if(isobject(a) && !isobject(b))
|
||||
RaiseError(new/runtimeError/TypeMismatch("%", a, b))
|
||||
return null
|
||||
else if(isobject(b) && !isobject(a))
|
||||
RaiseError(new/runtimeError/TypeMismatch("%", a, b))
|
||||
return null
|
||||
return a%b
|
||||
Power(a, b)
|
||||
if(isobject(a) && !isobject(b))
|
||||
RaiseError(new/runtimeError/TypeMismatch("**", a, b))
|
||||
return null
|
||||
else if(isobject(b) && !isobject(a))
|
||||
RaiseError(new/runtimeError/TypeMismatch("**", a, b))
|
||||
return null
|
||||
return a**b
|
||||
|
||||
//Unary//
|
||||
Minus(a) return -a
|
||||
LogicalNot(a) return !a
|
||||
BitwiseNot(a) return ~a
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
File: Interpreter (Public)
|
||||
Contains methods for interacting with the interpreter.
|
||||
*/
|
||||
/*
|
||||
Class: n_Interpreter
|
||||
Procedures allowing for interaction with the script that is being run by the interpreter object.
|
||||
*/
|
||||
|
||||
/n_Interpreter
|
||||
proc
|
||||
|
||||
/*
|
||||
Proc: Load
|
||||
Loads a 'compiled' script into memory.
|
||||
|
||||
Parameters:
|
||||
program - A <GlobalBlock> object which represents the script's global scope.
|
||||
*/
|
||||
Load(node/BlockDefinition/GlobalBlock/program)
|
||||
ASSERT(program)
|
||||
src.program = program
|
||||
CreateGlobalScope()
|
||||
|
||||
/*
|
||||
Proc: Run
|
||||
Runs the script.
|
||||
*/
|
||||
Run()
|
||||
cur_recursion = 0 // reset recursion
|
||||
cur_statements = 0 // reset CPU tracking
|
||||
alertadmins = 0
|
||||
|
||||
ASSERT(src.program)
|
||||
RunBlock(src.program)
|
||||
|
||||
/*
|
||||
Proc: SetVar
|
||||
Defines a global variable for the duration of the next execution of a script.
|
||||
|
||||
Notes:
|
||||
This differs from <Block.SetVar()> in that variables set using this procedure only last for the session,
|
||||
while those defined from the block object persist if it is ran multiple times.
|
||||
|
||||
See Also:
|
||||
- <Block.SetVar()>
|
||||
*/
|
||||
SetVar(name, value)
|
||||
if(!istext(name))
|
||||
//CRASH("Invalid variable name")
|
||||
return
|
||||
AssignVariable(name, value)
|
||||
|
||||
/*
|
||||
Proc: SetProc
|
||||
Defines a procedure to be available to the script.
|
||||
|
||||
Parameters:
|
||||
name - The name of the procedure as exposed to the script.
|
||||
path - The typepath of a proc to be called when the function call is read by the interpreter, or, if object is specified, a string representing the procedure's name.
|
||||
object - (Optional) An object which will the be target of a function call.
|
||||
params - Only required if object is not null, a list of the names of parameters the proc takes.
|
||||
*/
|
||||
SetProc(name, path, object=null, list/params=null)
|
||||
if(!istext(name))
|
||||
//CRASH("Invalid function name")
|
||||
return
|
||||
if(!object)
|
||||
globalScope.functions[name] = path
|
||||
else
|
||||
var/node/statement/FunctionDefinition/S = new()
|
||||
S.func_name = name
|
||||
S.parameters = params
|
||||
S.block = new()
|
||||
S.block.SetVar("src", object)
|
||||
var/node/expression/FunctionCall/C = new()
|
||||
C.func_name = path
|
||||
C.object = new("src")
|
||||
for(var/p in params)
|
||||
C.parameters += new/node/expression/value/variable(p)
|
||||
var/node/statement/ReturnStatement/R=new()
|
||||
R.value=C
|
||||
S.block.statements += R
|
||||
globalScope.functions[name] = S
|
||||
/*
|
||||
Proc: VarExists
|
||||
Checks whether a global variable with the specified name exists.
|
||||
*/
|
||||
VarExists(name)
|
||||
return globalScope.variables.Find(name) //convert to 1/0 first?
|
||||
|
||||
/*
|
||||
Proc: ProcExists
|
||||
Checks whether a global function with the specified name exists.
|
||||
*/
|
||||
ProcExists(name)
|
||||
return globalScope.functions.Find(name)
|
||||
|
||||
/*
|
||||
Proc: GetVar
|
||||
Returns the value of a global variable in the script. Remember to ensure that the variable exists before calling this procedure.
|
||||
|
||||
See Also:
|
||||
- <VarExists()>
|
||||
*/
|
||||
GetVar(name)
|
||||
if(!VarExists(name))
|
||||
//CRASH("No variable named '[name]'.")
|
||||
return
|
||||
var/x = globalScope.variables[name]
|
||||
return Eval(x)
|
||||
|
||||
/*
|
||||
Proc: CallProc
|
||||
Calls a global function defined in the script and, amazingly enough, returns its return value. Remember to ensure that the function
|
||||
exists before calling this procedure.
|
||||
|
||||
See Also:
|
||||
- <ProcExists()>
|
||||
*/
|
||||
CallProc(name, params[]=null)
|
||||
if(!ProcExists(name))
|
||||
//CRASH("No function named '[name]'.")
|
||||
return
|
||||
var/node/statement/FunctionDefinition/func = globalScope.functions[name]
|
||||
if(istype(func))
|
||||
var/node/statement/FunctionCall/stmt = new
|
||||
stmt.func_name = func.func_name
|
||||
stmt.parameters = params
|
||||
return RunFunction(stmt)
|
||||
else
|
||||
return call(func)(arglist(params))
|
||||
//CRASH("Unknown function type '[name]'.")
|
||||
|
||||
/*
|
||||
Event: HandleError
|
||||
Called when the interpreter throws a runtime error.
|
||||
|
||||
See Also:
|
||||
- <runtimeError>
|
||||
*/
|
||||
HandleError(runtimeError/e)
|
||||
@@ -1,314 +0,0 @@
|
||||
/*
|
||||
File: Interpreter (Internal)
|
||||
*/
|
||||
/*
|
||||
Class: n_Interpreter
|
||||
*/
|
||||
/*
|
||||
Macros: Status Macros
|
||||
RETURNING - Indicates that the current function is returning a value.
|
||||
BREAKING - Indicates that the current loop is being terminated.
|
||||
CONTINUING - Indicates that the rest of the current iteration of a loop is being skipped.
|
||||
*/
|
||||
#define RETURNING 1
|
||||
#define BREAKING 2
|
||||
#define CONTINUING 4
|
||||
/n_Interpreter
|
||||
var
|
||||
scope
|
||||
curScope
|
||||
globalScope
|
||||
node
|
||||
BlockDefinition/program
|
||||
statement/FunctionDefinition/curFunction
|
||||
stack
|
||||
scopes = new()
|
||||
functions = new()
|
||||
|
||||
datum/container // associated container for interpeter
|
||||
/*
|
||||
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>.
|
||||
*/
|
||||
status=0
|
||||
returnVal
|
||||
|
||||
max_statements=1000 // maximum amount of statements that can be called in one execution. this is to prevent massive crashes and exploitation
|
||||
cur_statements=0 // current amount of statements called
|
||||
alertadmins=0 // set to 1 if the admins shouldn't be notified of anymore issues
|
||||
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
|
||||
If 0, global variables will be reset after Run() finishes.
|
||||
*/
|
||||
persist=1
|
||||
paused=0
|
||||
|
||||
/*
|
||||
Constructor: New
|
||||
Calls <Load()> with the given parameters.
|
||||
*/
|
||||
New(node/BlockDefinition/GlobalBlock/program=null)
|
||||
.=..()
|
||||
if(program)Load(program)
|
||||
|
||||
proc
|
||||
/*
|
||||
Proc: RaiseError
|
||||
Raises a runtime error.
|
||||
*/
|
||||
RaiseError(runtimeError/e)
|
||||
e.stack=functions.Copy()
|
||||
e.stack.Push(curFunction)
|
||||
src.HandleError(e)
|
||||
|
||||
CreateScope(node/BlockDefinition/B)
|
||||
var/scope/S = new(B, curScope)
|
||||
scopes.Push(curScope)
|
||||
curScope = S
|
||||
return S
|
||||
|
||||
CreateGlobalScope()
|
||||
scopes.Clear()
|
||||
var/scope/S = new(program, null)
|
||||
globalScope = S
|
||||
return S
|
||||
|
||||
/*
|
||||
Proc: RunBlock
|
||||
Runs each statement in a block of code.
|
||||
*/
|
||||
RunBlock(node/BlockDefinition/Block, scope/scope = null)
|
||||
var/is_global = istype(Block, /node/BlockDefinition/GlobalBlock)
|
||||
if(!is_global)
|
||||
if(scope)
|
||||
curScope = scope
|
||||
else
|
||||
CreateScope(Block)
|
||||
else
|
||||
if(!persist)
|
||||
CreateGlobalScope()
|
||||
curScope = globalScope
|
||||
|
||||
if(cur_statements < max_statements)
|
||||
|
||||
for(var/node/statement/S in Block.statements)
|
||||
while(paused) sleep(10)
|
||||
|
||||
cur_statements++
|
||||
if(cur_statements >= max_statements)
|
||||
RaiseError(new/runtimeError/MaxCPU())
|
||||
|
||||
if(container && !alertadmins)
|
||||
if(istype(container, /datum/TCS_Compiler))
|
||||
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
|
||||
RaiseError(new/runtimeError/UnknownInstruction())
|
||||
if(status)
|
||||
break
|
||||
|
||||
curScope = scopes.Pop()
|
||||
|
||||
/*
|
||||
Proc: RunFunction
|
||||
Runs a function block or a proc with the arguments specified in the script.
|
||||
*/
|
||||
RunFunction(node/statement/FunctionCall/stmt)
|
||||
//Note that anywhere /node/statement/FunctionCall/stmt is used so may /node/expression/FunctionCall
|
||||
|
||||
// If recursion gets too high (max 50 nested functions) throw an error
|
||||
if(cur_recursion >= max_recursion)
|
||||
RaiseError(new/runtimeError/RecursionLimitReached())
|
||||
return 0
|
||||
|
||||
var/node/statement/FunctionDefinition/def
|
||||
if(!stmt.object) //A scope's function is being called, stmt.object is null
|
||||
def = GetFunction(stmt.func_name)
|
||||
else if(istype(stmt.object)) //A method of an object exposed as a variable is being called, stmt.object is a /node/identifier
|
||||
var/O = GetVariable(stmt.object.id_name) //Gets a reference to the object which is the target of the function call.
|
||||
if(!O) return //Error already thrown in GetVariable()
|
||||
def = Eval(O)
|
||||
|
||||
if(!def) return
|
||||
|
||||
cur_recursion++ // add recursion
|
||||
if(istype(def))
|
||||
if(curFunction) functions.Push(curFunction)
|
||||
var/scope/S = CreateScope(def.block)
|
||||
for(var/i=1 to def.parameters.len)
|
||||
var/val
|
||||
if(stmt.parameters.len>=i)
|
||||
val = stmt.parameters[i]
|
||||
//else
|
||||
// unspecified param
|
||||
AssignVariable(def.parameters[i], new/node/expression/value/literal(Eval(val)), S)
|
||||
curFunction=stmt
|
||||
RunBlock(def.block, S)
|
||||
//Handle return value
|
||||
. = returnVal
|
||||
status &= ~RETURNING
|
||||
returnVal=null
|
||||
curFunction=functions.Pop()
|
||||
cur_recursion--
|
||||
else
|
||||
cur_recursion--
|
||||
var/list/params=new
|
||||
for(var/node/expression/P in stmt.parameters)
|
||||
params+=list(Eval(P))
|
||||
if(isobject(def)) //def is an object which is the target of a function call
|
||||
if( !hascall(def, stmt.func_name) )
|
||||
RaiseError(new/runtimeError/UndefinedFunction("[stmt.object.id_name].[stmt.func_name]"))
|
||||
return
|
||||
return call(def, stmt.func_name)(arglist(params))
|
||||
else //def is a path to a global proc
|
||||
return call(def)(arglist(params))
|
||||
//else
|
||||
// RaiseError(new/runtimeError/UnknownInstruction())
|
||||
|
||||
/*
|
||||
Proc: RunIf
|
||||
Checks a condition and runs either the if block or else block.
|
||||
*/
|
||||
RunIf(node/statement/IfStatement/stmt)
|
||||
if(Eval(stmt.cond))
|
||||
RunBlock(stmt.block)
|
||||
else if(stmt.else_block)
|
||||
RunBlock(stmt.else_block)
|
||||
|
||||
/*
|
||||
Proc: RunWhile
|
||||
Runs a while loop.
|
||||
*/
|
||||
RunWhile(node/statement/WhileLoop/stmt)
|
||||
var/i=1
|
||||
while(Eval(stmt.cond) && Iterate(stmt.block, i++))
|
||||
continue
|
||||
status &= ~BREAKING
|
||||
|
||||
/*
|
||||
Proc:Iterate
|
||||
Runs a single iteration of a loop. Returns a value indicating whether or not to continue looping.
|
||||
*/
|
||||
Iterate(node/BlockDefinition/block, count)
|
||||
RunBlock(block)
|
||||
if(max_iterations > 0 && count >= max_iterations)
|
||||
RaiseError(new/runtimeError/IterationLimitReached())
|
||||
return 0
|
||||
if(status & (BREAKING|RETURNING))
|
||||
return 0
|
||||
status &= ~CONTINUING
|
||||
return 1
|
||||
|
||||
/*
|
||||
Proc: GetFunction
|
||||
Finds a function in an accessible scope with the given name. Returns a <FunctionDefinition>.
|
||||
*/
|
||||
GetFunction(name)
|
||||
var/scope/S = curScope
|
||||
while(S)
|
||||
if(S.functions.Find(name))
|
||||
return S.functions[name]
|
||||
S = S.parent
|
||||
RaiseError(new/runtimeError/UndefinedFunction(name))
|
||||
|
||||
/*
|
||||
Proc: GetVariable
|
||||
Finds a variable in an accessible scope and returns its value.
|
||||
*/
|
||||
GetVariable(name)
|
||||
var/scope/S = curScope
|
||||
while(S)
|
||||
if(S.variables.Find(name))
|
||||
return S.variables[name]
|
||||
S = S.parent
|
||||
RaiseError(new/runtimeError/UndefinedVariable(name))
|
||||
|
||||
GetVariableScope(name) //needed for when you reassign a variable in a higher scope
|
||||
var/scope/S = curScope
|
||||
while(S)
|
||||
if(S.variables.Find(name))
|
||||
return S
|
||||
S = S.parent
|
||||
|
||||
|
||||
IsVariableAccessible(name)
|
||||
var/scope/S = curScope
|
||||
while(S)
|
||||
if(S.variables.Find(name))
|
||||
return TRUE
|
||||
S = S.parent
|
||||
return FALSE
|
||||
|
||||
|
||||
/*
|
||||
Proc: AssignVariable
|
||||
Assigns a value to a variable in a specific block.
|
||||
|
||||
Parameters:
|
||||
name - The name of the variable to assign.
|
||||
value - The value to assign to it.
|
||||
S - The scope the variable resides in. If it is null, a scope with the variable already existing is found. If no scopes have a variable of the given name, the current scope is used.
|
||||
*/
|
||||
AssignVariable(name, node/expression/value, scope/S=null)
|
||||
if(!S) S = GetVariableScope(name)
|
||||
if(!S) S = curScope
|
||||
if(!S) S = globalScope
|
||||
ASSERT(istype(S))
|
||||
if(istext(value) || isnum(value) || isnull(value)) value = new/node/expression/value/literal(value)
|
||||
else if(!istype(value) && isobject(value)) value = new/node/expression/value/reference(value)
|
||||
//TODO: check for invalid name
|
||||
S.variables["[name]"] = value
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
Class: scope
|
||||
A runtime instance of a block. Used internally by the interpreter.
|
||||
*/
|
||||
scope
|
||||
var
|
||||
scope/parent = null
|
||||
node/BlockDefinition/block
|
||||
list
|
||||
functions
|
||||
variables
|
||||
|
||||
New(node/BlockDefinition/B, scope/parent)
|
||||
src.block = B
|
||||
src.parent = parent
|
||||
src.variables = B.initial_variables.Copy()
|
||||
src.functions = B.functions.Copy()
|
||||
.=..()
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
File: Options
|
||||
*/
|
||||
var/const //Ascii values of characters
|
||||
ascii_A =65
|
||||
ascii_Z =90
|
||||
ascii_a =97
|
||||
ascii_z =122
|
||||
ascii_DOLLAR = 36 // $
|
||||
ascii_ZERO=48
|
||||
ascii_NINE=57
|
||||
ascii_UNDERSCORE=95 // _
|
||||
|
||||
/*
|
||||
Class: n_scriptOptions
|
||||
*/
|
||||
n_scriptOptions
|
||||
proc
|
||||
CanStartID(char) //returns true if the character can start a variable, function, or keyword name (by default letters or an underscore)
|
||||
if(!isnum(char))char=text2ascii(char)
|
||||
return (char in ascii_A to ascii_Z) || (char in ascii_a to ascii_z) || char==ascii_UNDERSCORE || char==ascii_DOLLAR
|
||||
|
||||
IsValidIDChar(char) //returns true if the character can be in the body of a variable, function, or keyword name (by default letters, numbers, and underscore)
|
||||
if(!isnum(char))char=text2ascii(char)
|
||||
return CanStartID(char) || IsDigit(char)
|
||||
|
||||
IsDigit(char)
|
||||
if(!isnum(char))char=text2ascii(char)
|
||||
return char in ascii_ZERO to ascii_NINE
|
||||
|
||||
IsValidID(id) //returns true if all the characters in the string are okay to be in an identifier name
|
||||
if(!CanStartID(id)) //don't need to grab first char in id, since text2ascii does it automatically
|
||||
return 0
|
||||
if(length(id)==1) return 1
|
||||
for(var/i=2 to length(id))
|
||||
if(!IsValidIDChar(copytext(id, i, i+1)))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/*
|
||||
Class: nS_Options
|
||||
An implementation of <n_scriptOptions> for the n_Script language.
|
||||
*/
|
||||
nS_Options
|
||||
var
|
||||
list
|
||||
symbols = list("(", ")", "\[", "]", ";", ",", "{", "}") //scanner - Characters that can be in symbols
|
||||
/*
|
||||
Var: keywords
|
||||
An associative list used by the parser to parse keywords. Indices are strings which will trigger the keyword when parsed and the
|
||||
associated values are <nS_Keyword> types of which the <n_Keyword.Parse()> proc will be called.
|
||||
*/
|
||||
keywords = list("if" = /n_Keyword/nS_Keyword/kwIf, "else" = /n_Keyword/nS_Keyword/kwElse, \
|
||||
"while" = /n_Keyword/nS_Keyword/kwWhile, "break" = /n_Keyword/nS_Keyword/kwBreak, \
|
||||
"continue" = /n_Keyword/nS_Keyword/kwContinue, \
|
||||
"return" = /n_Keyword/nS_Keyword/kwReturn, "def" = /n_Keyword/nS_Keyword/kwDef)
|
||||
|
||||
list
|
||||
assign_operators=list("=" = null, "&=" = "&",
|
||||
"|=" = "|", "`=" = "`",
|
||||
"+=" = "+", "-=" = "-",
|
||||
"*=" = "*", "/=" = "/",
|
||||
"^=" = "^",
|
||||
"%=" = "%")
|
||||
|
||||
unary_operators =list("!" = /node/expression/operator/unary/LogicalNot, "~" = /node/expression/operator/unary/BitwiseNot,
|
||||
"-" = /node/expression/operator/unary/Minus)
|
||||
|
||||
binary_operators=list("==" = /node/expression/operator/binary/Equal, "!=" = /node/expression/operator/binary/NotEqual,
|
||||
">" = /node/expression/operator/binary/Greater, "<" = /node/expression/operator/binary/Less,
|
||||
">=" = /node/expression/operator/binary/GreaterOrEqual,"<=" = /node/expression/operator/binary/LessOrEqual,
|
||||
"&&" = /node/expression/operator/binary/LogicalAnd, "||" = /node/expression/operator/binary/LogicalOr,
|
||||
"&" = /node/expression/operator/binary/BitwiseAnd, "|" = /node/expression/operator/binary/BitwiseOr,
|
||||
"`" = /node/expression/operator/binary/BitwiseXor, "+" = /node/expression/operator/binary/Add,
|
||||
"-" = /node/expression/operator/binary/Subtract, "*" = /node/expression/operator/binary/Multiply,
|
||||
"/" = /node/expression/operator/binary/Divide, "^" = /node/expression/operator/binary/Power,
|
||||
"%" = /node/expression/operator/binary/Modulo)
|
||||
|
||||
New()
|
||||
.=..()
|
||||
for(var/O in assign_operators+binary_operators+unary_operators)
|
||||
if(!symbols.Find(O)) symbols+=O
|
||||
@@ -1,312 +0,0 @@
|
||||
/*
|
||||
File: Expressions
|
||||
Procedures for parsing expressions.
|
||||
*/
|
||||
|
||||
/*
|
||||
Macros: Expression Macros
|
||||
OPERATOR - A value indicating the parser currently expects a binary operator.
|
||||
VALUE - A value indicating the parser currently expects a value.
|
||||
SHIFT - Tells the parser to push the current operator onto the stack.
|
||||
REDUCE - Tells the parser to reduce the stack.
|
||||
*/
|
||||
#define OPERATOR 1
|
||||
#define VALUE 2
|
||||
#define SHIFT 0
|
||||
#define REDUCE 1
|
||||
|
||||
/*
|
||||
Class: nS_Parser
|
||||
*/
|
||||
/n_Parser/nS_Parser
|
||||
var
|
||||
/*
|
||||
Var: expecting
|
||||
A variable which keeps track of whether an operator or value is expected. It should be either <OPERATOR> or <VALUE>. See <ParseExpression()>
|
||||
for more information.
|
||||
*/
|
||||
expecting=VALUE
|
||||
|
||||
proc
|
||||
/*
|
||||
Proc: Precedence
|
||||
Compares two operators, decides which is higher in the order of operations, and returns <SHIFT> or <REDUCE>.
|
||||
*/
|
||||
Precedence(node/expression/operator/top, node/expression/operator/input)
|
||||
if(istype(top))
|
||||
top=top.precedence
|
||||
if(istype(input))
|
||||
input=input:precedence
|
||||
if(top>=input)
|
||||
return REDUCE
|
||||
return SHIFT
|
||||
|
||||
/*
|
||||
Proc: GetExpression
|
||||
Takes a token expected to represent a value and returns an <expression> node.
|
||||
*/
|
||||
GetExpression(token/T)
|
||||
if(!T) return
|
||||
if(istype(T, /node/expression))
|
||||
return T
|
||||
switch(T.type)
|
||||
if(/token/word)
|
||||
return new/node/expression/value/variable(T.value)
|
||||
if(/token/accessor)
|
||||
var/token/accessor/A = T
|
||||
var/node/expression/value/variable/E
|
||||
var/stack/S = new()
|
||||
while(istype(A.object, /token/accessor))
|
||||
S.Push(A)
|
||||
A=A.object
|
||||
ASSERT(istext(A.object))
|
||||
|
||||
while(A)
|
||||
var/node/expression/value/variable/V=new()
|
||||
V.id=new(A.member)
|
||||
if(E)
|
||||
V.object=E
|
||||
else
|
||||
V.object=new/node/identifier(A.object)
|
||||
E=V
|
||||
A=S.Pop()
|
||||
return E
|
||||
|
||||
if(/token/number, /token/string)
|
||||
return new/node/expression/value/literal(T.value)
|
||||
|
||||
/*
|
||||
Proc: GetOperator
|
||||
Gets a path related to a token or string and returns an instance of the given type. This is used to get an instance of either a binary or unary
|
||||
operator from a token.
|
||||
|
||||
Parameters:
|
||||
O - The input value. If this is a token, O is reset to the token's value.
|
||||
When O is a string and is in L, its associated value is used as the path to instantiate.
|
||||
type - The desired type of the returned object.
|
||||
L - The list in which to search for O.
|
||||
|
||||
See Also:
|
||||
- <GetBinaryOperator()>
|
||||
- <GetUnaryOperator()>
|
||||
*/
|
||||
GetOperator(O, type=/node/expression/operator, L[])
|
||||
if(istype(O, type)) return O //O is already the desired type
|
||||
if(istype(O, /token)) O=O:value //sets O to text
|
||||
if(istext(O)) //sets O to path
|
||||
if(L.Find(O)) O=L[O]
|
||||
else return null
|
||||
if(ispath(O))O=new O //catches path from last check
|
||||
else return null //Unknown type
|
||||
return O
|
||||
|
||||
/*
|
||||
Proc: GetBinaryOperator
|
||||
Uses <GetOperator()> to search for an instance of a binary operator type with which the given string is associated. For example, if
|
||||
O is set to "+", an <Add> node is returned.
|
||||
|
||||
See Also:
|
||||
- <GetOperator()>
|
||||
- <GetUnaryOperator()>
|
||||
*/
|
||||
GetBinaryOperator(O)
|
||||
return GetOperator(O, /node/expression/operator/binary, options.binary_operators)
|
||||
|
||||
/*
|
||||
Proc: GetUnaryOperator
|
||||
Uses <GetOperator()> to search for an instance of a unary operator type with which the given string is associated. For example, if
|
||||
O is set to "!", a <LogicalNot> node is returned.
|
||||
|
||||
See Also:
|
||||
- <GetOperator()>
|
||||
- <GetBinaryOperator()>
|
||||
*/
|
||||
GetUnaryOperator(O)
|
||||
return GetOperator(O, /node/expression/operator/unary, options.unary_operators)
|
||||
|
||||
/*
|
||||
Proc: Reduce
|
||||
Takes the operator on top of the opr stack and assigns its operand(s). Then this proc pushes the value of that operation to the top
|
||||
of the val stack.
|
||||
*/
|
||||
Reduce(stack/opr, stack/val)
|
||||
var/node/expression/operator/O=opr.Pop()
|
||||
if(!O) return
|
||||
if(!istype(O))
|
||||
errors+=new/scriptError("Error reducing expression - invalid operator.")
|
||||
return
|
||||
//Take O and assign its operands, popping one or two values from the val stack
|
||||
//depending on whether O is a binary or unary operator.
|
||||
if(istype(O, /node/expression/operator/binary))
|
||||
var/node/expression/operator/binary/B=O
|
||||
B.exp2=val.Pop()
|
||||
B.exp =val.Pop()
|
||||
val.Push(B)
|
||||
else
|
||||
O.exp=val.Pop()
|
||||
val.Push(O)
|
||||
|
||||
/*
|
||||
Proc: EndOfExpression
|
||||
Returns true if the current token represents the end of an expression.
|
||||
|
||||
Parameters:
|
||||
end - A list of values to compare the current token to.
|
||||
*/
|
||||
EndOfExpression(end[])
|
||||
if(!curToken)
|
||||
return 1
|
||||
if(istype(curToken, /token/symbol) && end.Find(curToken.value))
|
||||
return 1
|
||||
if(istype(curToken, /token/end) && end.Find(/token/end))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/*
|
||||
Proc: ParseExpression
|
||||
Uses the Shunting-yard algorithm to parse expressions.
|
||||
|
||||
Notes:
|
||||
- When an opening parenthesis is found, then <ParseParenExpression()> is called to handle it.
|
||||
- The <expecting> variable helps distinguish unary operators from binary operators (for cases like the - operator, which can be either).
|
||||
|
||||
Articles:
|
||||
- <http://epaperpress.com/oper/>
|
||||
- <http://en.wikipedia.org/wiki/Shunting-yard_algorithm>
|
||||
|
||||
See Also:
|
||||
- <ParseFunctionExpression()>
|
||||
- <ParseParenExpression()>
|
||||
- <ParseParamExpression()>
|
||||
*/
|
||||
ParseExpression(list/end=list(/token/end), list/ErrChars=list("{", "}"))
|
||||
var/stack/opr = new
|
||||
var/stack/val = new
|
||||
src.expecting=VALUE
|
||||
while (1)
|
||||
if(EndOfExpression(end))
|
||||
break
|
||||
if(istype(curToken, /token/symbol) && ErrChars.Find(curToken.value))
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
break
|
||||
|
||||
|
||||
if(index>tokens.len) //End of File
|
||||
errors+=new/scriptError/EndOfFile()
|
||||
break
|
||||
var/token/ntok
|
||||
if(index+1<=tokens.len)
|
||||
ntok=tokens[index+1]
|
||||
|
||||
if(istype(curToken, /token/symbol) && curToken.value=="(") //Parse parentheses expression
|
||||
if(expecting!=VALUE)
|
||||
errors+=new/scriptError/ExpectedToken("operator", curToken)
|
||||
NextToken()
|
||||
continue
|
||||
val.Push(ParseParenExpression())
|
||||
else if(istype(curToken, /token/symbol)) //Operator found.
|
||||
var/node/expression/operator/curOperator //Figure out whether it is unary or binary and get a new instance.
|
||||
if(src.expecting==OPERATOR)
|
||||
curOperator=GetBinaryOperator(curToken)
|
||||
if(!curOperator)
|
||||
errors+=new/scriptError/ExpectedToken("operator", curToken)
|
||||
NextToken()
|
||||
continue
|
||||
else
|
||||
curOperator=GetUnaryOperator(curToken)
|
||||
if(!curOperator) //given symbol isn't a unary operator
|
||||
errors+=new/scriptError/ExpectedToken("expression", curToken)
|
||||
NextToken()
|
||||
continue
|
||||
|
||||
if(opr.Top() && Precedence(opr.Top(), curOperator)==REDUCE) //Check order of operations and reduce if necessary
|
||||
Reduce(opr, val)
|
||||
continue
|
||||
opr.Push(curOperator)
|
||||
src.expecting=VALUE
|
||||
else if(ntok && ntok.value=="(" && istype(ntok, /token/symbol)\
|
||||
&& istype(curToken, /token/word)) //Parse function call
|
||||
var/token/preToken=curToken
|
||||
var/old_expect=src.expecting
|
||||
var/fex=ParseFunctionExpression()
|
||||
if(old_expect!=VALUE)
|
||||
errors+=new/scriptError/ExpectedToken("operator", preToken)
|
||||
NextToken()
|
||||
continue
|
||||
val.Push(fex)
|
||||
else if(istype(curToken, /token/keyword)) //inline keywords
|
||||
var/n_Keyword/kw=options.keywords[curToken.value]
|
||||
kw=new kw(inline=1)
|
||||
if(kw)
|
||||
if(!kw.Parse(src))
|
||||
return
|
||||
else
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
else if(istype(curToken, /token/end)) //semicolon found where it wasn't expected
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
NextToken()
|
||||
continue
|
||||
else
|
||||
if(expecting!=VALUE)
|
||||
errors+=new/scriptError/ExpectedToken("operator", curToken)
|
||||
NextToken()
|
||||
continue
|
||||
val.Push(GetExpression(curToken))
|
||||
src.expecting=OPERATOR
|
||||
NextToken()
|
||||
|
||||
while(opr.Top()) Reduce(opr, val) //Reduce the value stack completely
|
||||
.=val.Pop() //Return what should be the last value on the stack
|
||||
if(val.Top()) //
|
||||
var/node/N=val.Pop()
|
||||
errors+=new/scriptError("Error parsing expression. Unexpected value left on stack: [N.ToString()].")
|
||||
return null
|
||||
|
||||
/*
|
||||
Proc: ParseFunctionExpression
|
||||
Parses a function call inside of an expression.
|
||||
|
||||
See Also:
|
||||
- <ParseExpression()>
|
||||
*/
|
||||
ParseFunctionExpression()
|
||||
var/node/expression/FunctionCall/exp=new
|
||||
exp.func_name=curToken.value
|
||||
NextToken() //skip function name
|
||||
NextToken() //skip open parenthesis, already found
|
||||
var/loops = 0
|
||||
|
||||
while (1)
|
||||
loops++
|
||||
if(loops>=1000)
|
||||
CRASH("Something TERRIBLE has gone wrong in ParseFunctionExpression ;__;")
|
||||
|
||||
if(istype(curToken, /token/symbol) && curToken.value==")")
|
||||
return exp
|
||||
exp.parameters+=ParseParamExpression()
|
||||
if(curToken.value==","&&istype(curToken, /token/symbol))NextToken() //skip comma
|
||||
if(istype(curToken, /token/end)) //Prevents infinite loop...
|
||||
errors+=new/scriptError/ExpectedToken(")")
|
||||
return exp
|
||||
|
||||
/*
|
||||
Proc: ParseParenExpression
|
||||
Parses an expression that ends with a close parenthesis. This is used for parsing expressions inside of parentheses.
|
||||
|
||||
See Also:
|
||||
- <ParseExpression()>
|
||||
*/
|
||||
ParseParenExpression()
|
||||
if(!CheckToken("(", /token/symbol))
|
||||
return
|
||||
return new/node/expression/operator/unary/group(ParseExpression(list(")")))
|
||||
|
||||
/*
|
||||
Proc: ParseParamExpression
|
||||
Parses an expression that ends with either a comma or close parenthesis. This is used for parsing the parameters passed to a function call.
|
||||
|
||||
See Also:
|
||||
- <ParseExpression()>
|
||||
*/
|
||||
ParseParamExpression()
|
||||
return ParseExpression(list(",", ")"))
|
||||
@@ -1,166 +0,0 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
|
||||
|
||||
/*
|
||||
File: Keywords
|
||||
*/
|
||||
var/const/KW_FAIL = 0 //Fatal error; stop parsing entire script.
|
||||
var/const/KW_PASS = 1 //OK
|
||||
var/const/KW_ERR = 2 //Non-fatal error, keyword couldn't be handled properly. Ignore keyword but continue on.
|
||||
var/const/KW_WARN = 3 //Warning
|
||||
|
||||
/*
|
||||
var/const/Class: n_Keyword
|
||||
var/const/Represents a special statement in the code triggered by a keyword.
|
||||
*/
|
||||
/n_Keyword
|
||||
New(inline=0)
|
||||
src.inline=inline
|
||||
return ..()
|
||||
|
||||
/*
|
||||
Var: inline
|
||||
1 if the keyword is in an expression (e.g. the new keyword in many languages), 0 otherwise (such as the if and else keywords).
|
||||
*/
|
||||
var/inline
|
||||
|
||||
/*
|
||||
Proc: Parse
|
||||
Called when the parser finds a keyword in the code.
|
||||
|
||||
Parameters:
|
||||
parser - The parser that created this object. You can use the parameter to manipulate the parser in order to add statements and blocks
|
||||
to its AST.
|
||||
*/
|
||||
proc/Parse(n_Parser/parser)
|
||||
|
||||
/*
|
||||
Class: nS_Keyword
|
||||
A keyword in n_Script. By default these include return, if, else, while, and def. To enable or disable a keyword, change the
|
||||
<nS_Options.keywords> list.
|
||||
|
||||
Behavior:
|
||||
When a parser is expecting a new statement, and a keyword listed in <nS_Options.keywords> is found, it will call the keyword's
|
||||
<n_Keyword.Parse()> proc.
|
||||
*/
|
||||
//
|
||||
nS_Keyword
|
||||
New(inline=0)
|
||||
if(inline)
|
||||
qdel(src)
|
||||
|
||||
kwReturn
|
||||
Parse(n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock))
|
||||
parser.errors+=new/scriptError/BadReturn(parser.curToken)
|
||||
. = KW_WARN
|
||||
var/node/statement/ReturnStatement/stmt=new
|
||||
parser.NextToken() //skip 'return' token
|
||||
stmt.value=parser.ParseExpression()
|
||||
parser.curBlock.statements+=stmt
|
||||
|
||||
kwIf
|
||||
Parse(n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
var/node/statement/IfStatement/stmt=new
|
||||
parser.NextToken() //skip 'if' token
|
||||
stmt.cond=parser.ParseParenExpression()
|
||||
if(!parser.CheckToken(")", /token/symbol))
|
||||
return KW_FAIL
|
||||
if(!parser.CheckToken("{", /token/symbol, skip=0)) //Token needs to be preserved for parse loop, so skip=0
|
||||
return KW_ERR
|
||||
parser.curBlock.statements+=stmt
|
||||
stmt.block=new
|
||||
parser.AddBlock(stmt.block)
|
||||
|
||||
kwElse
|
||||
Parse(n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
var/list/L=parser.curBlock.statements
|
||||
var/node/statement/IfStatement/stmt
|
||||
if(L&&L.len) stmt=L[L.len] //Get the last statement in the current block
|
||||
if(!stmt || !istype(stmt) || stmt.else_block) //Ensure that it is an if statement
|
||||
parser.errors+=new/scriptError/ExpectedToken("if statement",parser.curToken)
|
||||
return KW_FAIL
|
||||
parser.NextToken() //skip 'else' token
|
||||
if(!parser.CheckToken("{", /token/symbol, skip=0))
|
||||
return KW_ERR
|
||||
stmt.else_block=new()
|
||||
parser.AddBlock(stmt.else_block)
|
||||
|
||||
kwWhile
|
||||
Parse(n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
var/node/statement/WhileLoop/stmt=new
|
||||
parser.NextToken() //skip 'while' token
|
||||
stmt.cond=parser.ParseParenExpression()
|
||||
if(!parser.CheckToken(")", /token/symbol))
|
||||
return KW_FAIL
|
||||
if(!parser.CheckToken("{", /token/symbol, skip=0))
|
||||
return KW_ERR
|
||||
parser.curBlock.statements+=stmt
|
||||
stmt.block=new
|
||||
parser.AddBlock(stmt.block)
|
||||
|
||||
kwBreak
|
||||
Parse(n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock))
|
||||
parser.errors+=new/scriptError/BadToken(parser.curToken)
|
||||
. = KW_WARN
|
||||
var/node/statement/BreakStatement/stmt=new
|
||||
parser.NextToken() //skip 'break' token
|
||||
parser.curBlock.statements+=stmt
|
||||
|
||||
kwContinue
|
||||
Parse(n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock))
|
||||
parser.errors+=new/scriptError/BadToken(parser.curToken)
|
||||
. = KW_WARN
|
||||
var/node/statement/ContinueStatement/stmt=new
|
||||
parser.NextToken() //skip 'break' token
|
||||
parser.curBlock.statements+=stmt
|
||||
|
||||
kwDef
|
||||
Parse(n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
var/node/statement/FunctionDefinition/def=new
|
||||
parser.NextToken() //skip 'def' token
|
||||
if(!parser.options.IsValidID(parser.curToken.value))
|
||||
parser.errors+=new/scriptError/InvalidID(parser.curToken)
|
||||
return KW_FAIL
|
||||
def.func_name=parser.curToken.value
|
||||
parser.NextToken()
|
||||
if(!parser.CheckToken("(", /token/symbol))
|
||||
return KW_FAIL
|
||||
while (1) //for now parameters can be separated by whitespace - they don't need a comma in between
|
||||
if(istype(parser.curToken, /token/symbol))
|
||||
switch(parser.curToken.value)
|
||||
if(",")
|
||||
parser.NextToken()
|
||||
if(")")
|
||||
break
|
||||
else
|
||||
parser.errors+=new/scriptError/BadToken(parser.curToken)
|
||||
return KW_ERR
|
||||
|
||||
else if(istype(parser.curToken, /token/word))
|
||||
def.parameters+=parser.curToken.value
|
||||
parser.NextToken()
|
||||
else
|
||||
parser.errors+=new/scriptError/InvalidID(parser.curToken)
|
||||
return KW_ERR
|
||||
if(!parser.CheckToken(")", /token/symbol))
|
||||
return KW_FAIL
|
||||
|
||||
if(istype(parser.curToken, /token/end)) //Function prototype
|
||||
parser.curBlock.statements+=def
|
||||
else if(parser.curToken.value=="{" && istype(parser.curToken, /token/symbol))
|
||||
def.block = new
|
||||
parser.curBlock.statements+=def
|
||||
parser.curBlock.functions[def.func_name]=def
|
||||
parser.AddBlock(def.block)
|
||||
else
|
||||
parser.errors+=new/scriptError/BadToken(parser.curToken)
|
||||
return KW_FAIL
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
File: Parser
|
||||
*/
|
||||
/*
|
||||
Class: n_Parser
|
||||
An object that reads tokens and produces an AST (abstract syntax tree).
|
||||
*/
|
||||
/n_Parser
|
||||
var
|
||||
/*
|
||||
Var: index
|
||||
The parser's current position in the token's list.
|
||||
*/
|
||||
index = 1
|
||||
list
|
||||
/*
|
||||
Var: tokens
|
||||
A list of tokens in the source code generated by a scanner.
|
||||
*/
|
||||
tokens = new
|
||||
/*
|
||||
Var: errors
|
||||
A list of fatal errors found by the parser. If there are any items in this list, then it is not safe to run the returned AST.
|
||||
|
||||
See Also:
|
||||
- <scriptError>
|
||||
*/
|
||||
errors = new
|
||||
/*
|
||||
Var: warnings
|
||||
A list of non-fatal problems in the script.
|
||||
*/
|
||||
warnings = new
|
||||
token
|
||||
/*
|
||||
Var: curToken
|
||||
The token at <index> in <tokens>.
|
||||
*/
|
||||
curToken
|
||||
stack
|
||||
blocks=new
|
||||
node/BlockDefinition
|
||||
GlobalBlock/global_block=new
|
||||
curBlock
|
||||
|
||||
proc
|
||||
/*
|
||||
Proc: Parse
|
||||
Reads the tokens and returns the AST's <GlobalBlock> node. Be sure to populate the tokens list before calling this procedure.
|
||||
*/
|
||||
Parse()
|
||||
|
||||
/*
|
||||
Proc: NextToken
|
||||
Sets <curToken> to the next token in the <tokens> list, or null if there are no more tokens.
|
||||
*/
|
||||
NextToken()
|
||||
if(index>=tokens.len)
|
||||
curToken=null
|
||||
else
|
||||
curToken=tokens[++index]
|
||||
return curToken
|
||||
|
||||
/*
|
||||
Class: nS_Parser
|
||||
An implmentation of a parser for n_Script.
|
||||
*/
|
||||
/n_Parser/nS_Parser
|
||||
var/n_scriptOptions/nS_Options/options
|
||||
/*
|
||||
Constructor: New
|
||||
|
||||
Parameters:
|
||||
tokens - A list of tokens to parse.
|
||||
options - An object used for configuration.
|
||||
*/
|
||||
New(tokens[], n_scriptOptions/options)
|
||||
src.tokens=tokens
|
||||
src.options=options
|
||||
curBlock=global_block
|
||||
return ..()
|
||||
|
||||
Parse()
|
||||
ASSERT(tokens)
|
||||
for(,src.index<=src.tokens.len, src.index++)
|
||||
curToken=tokens[index]
|
||||
switch(curToken.type)
|
||||
if(/token/keyword)
|
||||
var/n_Keyword/kw=options.keywords[curToken.value]
|
||||
kw=new kw()
|
||||
if(kw)
|
||||
if(!kw.Parse(src))
|
||||
return
|
||||
if(/token/word)
|
||||
var/token/ntok
|
||||
if(index+1>tokens.len)
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
continue
|
||||
ntok=tokens[index+1]
|
||||
if(!istype(ntok, /token/symbol))
|
||||
errors+=new/scriptError/BadToken(ntok)
|
||||
continue
|
||||
if(ntok.value=="(")
|
||||
ParseFunctionStatement()
|
||||
else if(options.assign_operators.Find(ntok.value))
|
||||
ParseAssignment()
|
||||
else
|
||||
errors+=new/scriptError/BadToken(ntok)
|
||||
continue
|
||||
if(!istype(curToken, /token/end))
|
||||
errors+=new/scriptError/ExpectedToken(";", curToken)
|
||||
continue
|
||||
if(/token/symbol)
|
||||
if(curToken.value=="}")
|
||||
if(!EndBlock())
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
continue
|
||||
else
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
continue
|
||||
if(/token/end)
|
||||
warnings+=new/scriptError/BadToken(curToken)
|
||||
continue
|
||||
else
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
return
|
||||
return global_block
|
||||
|
||||
proc
|
||||
CheckToken(val, type, err=1, skip=1)
|
||||
if(curToken.value!=val || !istype(curToken,type))
|
||||
if(err)
|
||||
errors+=new/scriptError/ExpectedToken(val, curToken)
|
||||
return 0
|
||||
if(skip)NextToken()
|
||||
return 1
|
||||
|
||||
AddBlock(node/BlockDefinition/B)
|
||||
blocks.Push(curBlock)
|
||||
curBlock=B
|
||||
|
||||
EndBlock()
|
||||
if(curBlock==global_block) return 0
|
||||
curBlock=blocks.Pop()
|
||||
return 1
|
||||
|
||||
ParseAssignment()
|
||||
var/name=curToken.value
|
||||
if(!options.IsValidID(name))
|
||||
errors+=new/scriptError/InvalidID(curToken)
|
||||
return
|
||||
NextToken()
|
||||
var/t=options.binary_operators[options.assign_operators[curToken.value]]
|
||||
var/node/statement/VariableAssignment/stmt=new()
|
||||
stmt.var_name=new(name)
|
||||
NextToken()
|
||||
if(t)
|
||||
stmt.value=new t()
|
||||
stmt.value:exp=new/node/expression/value/variable(stmt.var_name)
|
||||
stmt.value:exp2=ParseExpression()
|
||||
else
|
||||
stmt.value=ParseExpression()
|
||||
curBlock.statements+=stmt
|
||||
|
||||
ParseFunctionStatement()
|
||||
if(!istype(curToken, /token/word))
|
||||
errors+=new/scriptError("Bad identifier in function call.")
|
||||
return
|
||||
var/node/statement/FunctionCall/stmt=new
|
||||
stmt.func_name=curToken.value
|
||||
NextToken() //skip function name
|
||||
if(!CheckToken("(", /token/symbol)) //Check for and skip open parenthesis
|
||||
return
|
||||
var/loops = 0
|
||||
while (1)
|
||||
loops++
|
||||
if(loops>=6000)
|
||||
CRASH("Something TERRIBLE has gone wrong in ParseFunctionStatement ;__;")
|
||||
|
||||
if(!curToken)
|
||||
errors+=new/scriptError/EndOfFile()
|
||||
return
|
||||
if(istype(curToken, /token/symbol) && curToken.value==")")
|
||||
curBlock.statements+=stmt
|
||||
NextToken() //Skip close parenthesis
|
||||
return
|
||||
var/node/expression/P=ParseParamExpression()
|
||||
stmt.parameters+=P
|
||||
if(istype(curToken, /token/symbol) && curToken.value==",") NextToken()
|
||||
@@ -1,280 +0,0 @@
|
||||
/*
|
||||
File: Scanner
|
||||
*/
|
||||
/*
|
||||
Class: n_Scanner
|
||||
An object responsible for breaking up source code into tokens for use by the parser.
|
||||
*/
|
||||
/n_Scanner
|
||||
var/code
|
||||
|
||||
/*
|
||||
Var: errors
|
||||
A list of fatal errors found by the scanner. If there are any items in this list, then it is not safe to parse the returned tokens.
|
||||
|
||||
See Also:
|
||||
- <scriptError>
|
||||
*/
|
||||
var/list/errors = new
|
||||
/*
|
||||
Var: warnings
|
||||
A list of non-fatal problems in the source code found by the scanner.
|
||||
*/
|
||||
var/list/warnings = new
|
||||
|
||||
proc
|
||||
/*
|
||||
Proc: LoadCode
|
||||
Loads source code.
|
||||
*/
|
||||
LoadCode(c)
|
||||
code=c
|
||||
|
||||
/*
|
||||
Proc: LoadCodeFromFile
|
||||
Gets the code from a file and calls <LoadCode()>.
|
||||
*/
|
||||
LoadCodeFromFile(f)
|
||||
LoadCode(file2text(f))
|
||||
|
||||
/*
|
||||
Proc: Scan
|
||||
Runs the scanner and returns the resulting list of tokens. Ensure that <LoadCode()> has been called first.
|
||||
*/
|
||||
Scan()
|
||||
|
||||
/*
|
||||
Class: nS_Scanner
|
||||
A scanner implementation for n_Script.
|
||||
*/
|
||||
/n_Scanner/nS_Scanner
|
||||
/*
|
||||
Variable: codepos
|
||||
The scanner's position in the source code.
|
||||
*/
|
||||
var/codepos = 1
|
||||
var/line = 1
|
||||
var/linepos = 0 //column=codepos-linepos
|
||||
var/n_scriptOptions/nS_Options/options
|
||||
|
||||
var/commenting = 0
|
||||
// 1: single-line
|
||||
// 2: multi-line
|
||||
|
||||
/*
|
||||
Variable: ignore
|
||||
A list of characters that are ignored by the scanner.
|
||||
|
||||
Default Value:
|
||||
Whitespace
|
||||
*/
|
||||
var/list/ignore = list(" ", "\t", "\n") //Don't add tokens for whitespace
|
||||
|
||||
/*
|
||||
Variable: end_stmt
|
||||
A list of characters that end a statement. Each item may only be one character long.
|
||||
|
||||
Default Value:
|
||||
Semicolon
|
||||
*/
|
||||
var/list/end_stmt = list(";")
|
||||
/*
|
||||
Variable: string_delim
|
||||
A list of characters that can start and end strings.
|
||||
|
||||
Default Value:
|
||||
Double and single quotes.
|
||||
*/
|
||||
var/list/string_delim = list("\"", "'")
|
||||
/*
|
||||
Variable: delim
|
||||
A list of characters that denote the start of a new token. This list is automatically populated.
|
||||
*/
|
||||
var/list/delim = new
|
||||
|
||||
/*
|
||||
Macro: COL
|
||||
The current column number.
|
||||
*/
|
||||
#define COL codepos-linepos
|
||||
|
||||
/*
|
||||
Constructor: New
|
||||
Parameters:
|
||||
code - The source code to tokenize.
|
||||
options - An <nS_Options> object used to configure the scanner.
|
||||
*/
|
||||
New(code, n_scriptOptions/nS_Options/options)
|
||||
.=..()
|
||||
ignore+= ascii2text(13) //Carriage return
|
||||
delim += ignore + options.symbols + end_stmt + string_delim
|
||||
src.options=options
|
||||
LoadCode(code)
|
||||
|
||||
Scan() //Creates a list of tokens from source code
|
||||
var/list/tokens=new
|
||||
for(, src.codepos<=length(code), src.codepos++)
|
||||
|
||||
var/char=copytext(code, codepos, codepos+1)
|
||||
if(char=="\n")
|
||||
line++
|
||||
linepos=codepos
|
||||
|
||||
if(ignore.Find(char))
|
||||
continue
|
||||
else if(char == "/")
|
||||
ReadComment()
|
||||
else if(end_stmt.Find(char))
|
||||
tokens+=new /token/end(char, line, COL)
|
||||
else if(string_delim.Find(char))
|
||||
codepos++ //skip string delimiter
|
||||
tokens+=ReadString(char)
|
||||
else if(options.CanStartID(char))
|
||||
tokens+=ReadWord()
|
||||
else if(options.IsDigit(char))
|
||||
tokens+=ReadNumber()
|
||||
else if(options.symbols.Find(char))
|
||||
tokens+=ReadSymbol()
|
||||
|
||||
|
||||
codepos=initial(codepos)
|
||||
line=initial(line)
|
||||
linepos=initial(linepos)
|
||||
return tokens
|
||||
|
||||
proc
|
||||
/*
|
||||
Proc: ReadString
|
||||
Reads a string in the source code into a token.
|
||||
|
||||
Parameters:
|
||||
start - The character used to start the string.
|
||||
*/
|
||||
ReadString(start)
|
||||
var/buf
|
||||
for(, codepos <= length(code), codepos++)//codepos to length(code))
|
||||
var/char=copytext(code, codepos, codepos+1)
|
||||
switch(char)
|
||||
if("\\") //Backslash (\) encountered in string
|
||||
codepos++ //Skip next character in string, since it was escaped by a backslash
|
||||
char=copytext(code, codepos, codepos+1)
|
||||
switch(char)
|
||||
if("\\") //Double backslash
|
||||
buf+="\\"
|
||||
if("n") //\n Newline
|
||||
buf+="\n"
|
||||
else
|
||||
if(char==start) //\" Doublequote
|
||||
buf+=start
|
||||
else //Unknown escaped text
|
||||
buf+=char
|
||||
if("\n")
|
||||
. = new/token/string(buf, line, COL)
|
||||
errors+=new/scriptError("Unterminated string. Newline reached.", .)
|
||||
line++
|
||||
linepos=codepos
|
||||
break
|
||||
else
|
||||
if(char==start) //string delimiter found, end string
|
||||
break
|
||||
else
|
||||
buf+=char //Just a normal character in a string
|
||||
if(!.) return new/token/string(buf, line, COL)
|
||||
|
||||
/*
|
||||
Proc: ReadWord
|
||||
Reads characters separated by an item in <delim> into a token.
|
||||
*/
|
||||
ReadWord()
|
||||
var/char=copytext(code, codepos, codepos+1)
|
||||
var/buf
|
||||
while(!delim.Find(char) && codepos<=length(code))
|
||||
buf+=char
|
||||
char=copytext(code, ++codepos, codepos+1)
|
||||
codepos-- //allow main Scan() proc to read the delimiter
|
||||
if(options.keywords.Find(buf))
|
||||
return new /token/keyword(buf, line, COL)
|
||||
else
|
||||
return new /token/word(buf, line, COL)
|
||||
|
||||
/*
|
||||
Proc: ReadSymbol
|
||||
Reads a symbol into a token.
|
||||
*/
|
||||
ReadSymbol()
|
||||
var/char=copytext(code, codepos, codepos+1)
|
||||
var/buf
|
||||
|
||||
while(options.symbols.Find(buf+char))
|
||||
buf+=char
|
||||
if(++codepos>length(code)) break
|
||||
char=copytext(code, codepos, codepos+1)
|
||||
|
||||
codepos-- //allow main Scan() proc to read the next character
|
||||
return new /token/symbol(buf, line, COL)
|
||||
|
||||
/*
|
||||
Proc: ReadNumber
|
||||
Reads a number into a token.
|
||||
*/
|
||||
ReadNumber()
|
||||
var/char = copytext(code, codepos, codepos+1)
|
||||
var/buf
|
||||
var/dec = 0
|
||||
|
||||
while(options.IsDigit(char) || (char=="." && !dec))
|
||||
if(char==".") dec=1
|
||||
buf+=char
|
||||
codepos++
|
||||
char=copytext(code, codepos, codepos+1)
|
||||
var/token/number/T=new(buf, line, COL)
|
||||
if(isnull(text2num(buf)))
|
||||
errors+=new/scriptError("Bad number: ", T)
|
||||
T.value=0
|
||||
codepos-- //allow main Scan() proc to read the next character
|
||||
return T
|
||||
|
||||
/*
|
||||
Proc: ReadComment
|
||||
Reads a comment and outputs the type of comment
|
||||
*/
|
||||
|
||||
ReadComment()
|
||||
var/char = copytext(code, codepos, codepos+1)
|
||||
var/nextchar = copytext(code, codepos+1, codepos+2)
|
||||
var/charstring = char+nextchar
|
||||
var/comm = 1
|
||||
// 1: single-line comment
|
||||
// 2: multi-line comment
|
||||
var/expectedend = 0
|
||||
|
||||
if(charstring == "//" || charstring == "/*")
|
||||
if(charstring == "/*")
|
||||
comm = 2 // starts a multi-line comment
|
||||
|
||||
while(comm)
|
||||
if(++codepos>length(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()
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
|
||||
|
||||
/*
|
||||
Class: Token
|
||||
Represents an entity and position in the source code.
|
||||
*/
|
||||
/token
|
||||
var/value
|
||||
var/line
|
||||
var/column
|
||||
|
||||
New(v, l=0, c=0)
|
||||
value=v
|
||||
line=l
|
||||
column=c
|
||||
|
||||
string
|
||||
symbol
|
||||
word
|
||||
keyword
|
||||
number
|
||||
New()
|
||||
.=..()
|
||||
if(!isnum(value))
|
||||
value=text2num(value)
|
||||
ASSERT(!isnull(value))
|
||||
accessor
|
||||
var/object
|
||||
var/member
|
||||
|
||||
New(object, member, l=0, c=0)
|
||||
src.object=object
|
||||
src.member=member
|
||||
src.value="[object].[member]" //for debugging only
|
||||
src.line=l
|
||||
src.column=c
|
||||
|
||||
end
|
||||
@@ -301,3 +301,8 @@
|
||||
return prob(10)
|
||||
else
|
||||
return !density
|
||||
|
||||
|
||||
#undef POWER_INACTIVE
|
||||
#undef POWER_STARTING
|
||||
#undef POWER_ACTIVE
|
||||
|
||||
@@ -190,3 +190,5 @@
|
||||
//Note that this is called when the shuttle leaves the WAIT_FINISHED state, the proc name is a little misleading
|
||||
/datum/shuttle/autodock/proc/arrived()
|
||||
return //do nothing for now
|
||||
|
||||
#undef DOCK_ATTEMPT_TIMEOUT
|
||||
|
||||
@@ -461,5 +461,21 @@
|
||||
/obj/machinery/power/supermatter/shard/announce_warning() //Shards don't get announcements
|
||||
return
|
||||
|
||||
#undef LIGHT_POWER_CALC
|
||||
|
||||
|
||||
#undef NITROGEN_RETARDATION_FACTOR
|
||||
#undef THERMAL_RELEASE_MODIFIER
|
||||
#undef PHORON_RELEASE_MODIFIER
|
||||
#undef OXYGEN_RELEASE_MODIFIER
|
||||
#undef REACTION_POWER_MODIFIER
|
||||
#undef POWER_FACTOR
|
||||
#undef DECAY_FACTOR
|
||||
#undef CRITICAL_TEMPERATURE
|
||||
#undef CHARGING_FACTOR
|
||||
#undef DAMAGE_RATE_LIMIT
|
||||
#undef SPACED_DAMAGE_FACTOR
|
||||
#undef DETONATION_RADS
|
||||
#undef DETONATION_HALLUCINATION
|
||||
#undef WARNING_DELAY
|
||||
#undef SUPERMATTER_ACCENT_SOUND_MIN_COOLDOWN
|
||||
#undef LIGHT_POWER_CALC
|
||||
|
||||
Reference in New Issue
Block a user