Merge remote-tracking branch 'ParadiseSS13/master' into multi-instance-support
@@ -0,0 +1,2 @@
|
||||
/// Version of RUST-G that this codebase wants
|
||||
#define RUST_G_VERSION "0.5.0-P"
|
||||
@@ -7,58 +7,59 @@
|
||||
|
||||
#define JOBCAT_ENGSEC (1<<0)
|
||||
|
||||
#define JOB_CAPTAIN (1<<0)
|
||||
#define JOB_HOS (1<<1)
|
||||
#define JOB_WARDEN (1<<2)
|
||||
#define JOB_CAPTAIN (1<<0)
|
||||
#define JOB_HOS (1<<1)
|
||||
#define JOB_WARDEN (1<<2)
|
||||
#define JOB_DETECTIVE (1<<3)
|
||||
#define JOB_OFFICER (1<<4)
|
||||
#define JOB_OFFICER (1<<4)
|
||||
#define JOB_CHIEF (1<<5)
|
||||
#define JOB_ENGINEER (1<<6)
|
||||
#define JOB_ATMOSTECH (1<<7)
|
||||
#define JOB_AI (1<<8)
|
||||
#define JOB_CYBORG (1<<9)
|
||||
#define JOB_CENTCOM (1<<10)
|
||||
#define JOB_AI (1<<8)
|
||||
#define JOB_CYBORG (1<<9)
|
||||
#define JOB_CENTCOM (1<<10)
|
||||
#define JOB_SYNDICATE (1<<11)
|
||||
#define JOB_JUDGE (1<<12)
|
||||
|
||||
#define JOBCAT_MEDSCI (1<<1)
|
||||
|
||||
#define JOB_RD (1<<0)
|
||||
#define JOB_RD (1<<0)
|
||||
#define JOB_SCIENTIST (1<<1)
|
||||
#define JOB_CHEMIST (1<<2)
|
||||
#define JOB_CMO (1<<3)
|
||||
#define JOB_DOCTOR (1<<4)
|
||||
#define JOB_GENETICIST (1<<5)
|
||||
#define JOB_VIROLOGIST (1<<6)
|
||||
#define JOB_CHEMIST (1<<2)
|
||||
#define JOB_CMO (1<<3)
|
||||
#define JOB_DOCTOR (1<<4)
|
||||
#define JOB_GENETICIST (1<<5)
|
||||
#define JOB_VIROLOGIST (1<<6)
|
||||
#define JOB_PSYCHIATRIST (1<<7)
|
||||
#define JOB_ROBOTICIST (1<<8)
|
||||
#define JOB_ROBOTICIST (1<<8)
|
||||
#define JOB_PARAMEDIC (1<<9)
|
||||
#define JOB_CORONER (1<<10)
|
||||
#define JOB_CORONER (1<<10)
|
||||
|
||||
|
||||
#define JOBCAT_SUPPORT (1<<2)
|
||||
|
||||
#define JOB_HOP (1<<0)
|
||||
#define JOB_HOP (1<<0)
|
||||
#define JOB_BARTENDER (1<<1)
|
||||
#define JOB_BOTANIST (1<<2)
|
||||
#define JOB_CHEF (1<<3)
|
||||
#define JOB_JANITOR (1<<4)
|
||||
#define JOB_JANITOR (1<<4)
|
||||
#define JOB_LIBRARIAN (1<<5)
|
||||
#define JOB_QUARTERMASTER (1<<6)
|
||||
#define JOB_CARGOTECH (1<<7)
|
||||
#define JOB_MINER (1<<8)
|
||||
#define JOB_LAWYER (1<<9)
|
||||
#define JOB_LAWYER (1<<9)
|
||||
#define JOB_CHAPLAIN (1<<10)
|
||||
#define JOB_CLOWN (1<<11)
|
||||
#define JOB_MIME (1<<12)
|
||||
#define JOB_CIVILIAN (1<<13)
|
||||
#define JOB_EXPLORER (1<<14)
|
||||
|
||||
#define JOBCAT_KARMA (1<<3)
|
||||
#define JOBCAT_KARMA (1<<3)
|
||||
|
||||
#define JOB_NANO (1<<0)
|
||||
#define JOB_BLUESHIELD (1<<1)
|
||||
#define JOB_BARBER (1<<3)
|
||||
#define JOB_BLUESHIELD (1<<1)
|
||||
#define JOB_BARBER (1<<3)
|
||||
// #define JOB_MECHANIC (1<<4) // AA07 2021-10-02 - Removed: Kept for history sake
|
||||
#define JOB_BRIGDOC (1<<5)
|
||||
#define JOB_JUDGE (1<<6)
|
||||
// #define JOB_PILOT (1<<7) // AA07 2021-10-02 - Removed: Kept for history sake
|
||||
#define JOB_BRIGDOC (1<<5)
|
||||
// #define JOB_JUDGE (1<<6) // AA07 2021-10-09 - Moved to ENGSEC (Non karma): Define kept for history sake
|
||||
// #define JOB_PILOT (1<<7) // AA07 2021-10-02 - Removed: Kept for history sake
|
||||
|
||||
@@ -1,80 +1,130 @@
|
||||
// rust_g.dm - DM API for rust_g extension library
|
||||
//
|
||||
// To configure, create a `rust_g.config.dm` and set what you care about from
|
||||
// the following options:
|
||||
//
|
||||
// #define RUST_G "path/to/rust_g"
|
||||
// Override the .dll/.so detection logic with a fixed path or with detection
|
||||
// logic of your own.
|
||||
//
|
||||
// #define RUSTG_OVERRIDE_BUILTINS
|
||||
// Enable replacement rust-g functions for certain builtins. Off by default.
|
||||
|
||||
#ifndef RUST_G
|
||||
/// Locator for the RUSTG DLL or SO depending on system type. Override if needed.
|
||||
#define RUST_G (world.system_type == UNIX ? "./librust_g.so" : "./rust_g.dll")
|
||||
// Default automatic RUST_G detection.
|
||||
// On Windows, looks in the standard places for `rust_g.dll`.
|
||||
// On Linux, looks in `.`, `$LD_LIBRARY_PATH`, and `~/.byond/bin` for either of
|
||||
// `librust_g.so` (preferred) or `rust_g` (old).
|
||||
|
||||
/* This comment bypasses grep checks */ /var/__rust_g
|
||||
|
||||
/proc/__detect_rust_g()
|
||||
if (world.system_type == UNIX)
|
||||
if (fexists("./librust_g.so"))
|
||||
// No need for LD_LIBRARY_PATH badness.
|
||||
return __rust_g = "./librust_g.so"
|
||||
else if (fexists("./rust_g"))
|
||||
// Old dumb filename.
|
||||
return __rust_g = "./rust_g"
|
||||
else if (fexists("[world.GetConfig("env", "HOME")]/.byond/bin/rust_g"))
|
||||
// Old dumb filename in `~/.byond/bin`.
|
||||
return __rust_g = "rust_g"
|
||||
else
|
||||
// It's not in the current directory, so try others
|
||||
return __rust_g = "librust_g.so"
|
||||
else
|
||||
return __rust_g = "rust_g.dll"
|
||||
|
||||
#define RUST_G (__rust_g || __detect_rust_g())
|
||||
#endif
|
||||
|
||||
// Gets the version of RUSTG
|
||||
/// Gets the version of rust_g
|
||||
/proc/rustg_get_version() return call(RUST_G, "get_version")()
|
||||
|
||||
// Defines for internal job subsystem //
|
||||
#define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET"
|
||||
#define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB"
|
||||
#define RUSTG_JOB_ERROR "JOB PANICKED"
|
||||
// Cellular Noise Operations //
|
||||
|
||||
// DMI related operations //
|
||||
/**
|
||||
* This proc generates a cellular automata noise grid which can be used in procedural generation methods.
|
||||
*
|
||||
* Returns a single string that goes row by row, with values of 1 representing an alive cell, and a value of 0 representing a dead cell.
|
||||
*
|
||||
* Arguments:
|
||||
* * percentage: The chance of a turf starting closed
|
||||
* * smoothing_iterations: The amount of iterations the cellular automata simulates before returning the results
|
||||
* * birth_limit: If the number of neighboring cells is higher than this amount, a cell is born
|
||||
* * death_limit: If the number of neighboring cells is lower than this amount, a cell dies
|
||||
* * width: The width of the grid.
|
||||
* * height: The height of the grid.
|
||||
*/
|
||||
#define rustg_cnoise_generate(percentage, smoothing_iterations, birth_limit, death_limit, width, height) \
|
||||
call(RUST_G, "cnoise_generate")(percentage, smoothing_iterations, birth_limit, death_limit, width, height)
|
||||
|
||||
// DMI Operations //
|
||||
#define rustg_dmi_strip_metadata(fname) call(RUST_G, "dmi_strip_metadata")(fname)
|
||||
#define rustg_dmi_create_png(path, width, height, data) call(RUST_G, "dmi_create_png")(path, width, height, data)
|
||||
#define rustg_dmi_resize_png(path, width, height, resizetype) call(RUST_G, "dmi_resize_png")(path, width, height, resizetype)
|
||||
|
||||
// Noise related operations //
|
||||
#define rustg_noise_get_at_coordinates(seed, x, y) call(RUST_G, "noise_get_at_coordinates")(seed, x, y)
|
||||
|
||||
// File related operations //
|
||||
// File Operations //
|
||||
#define rustg_file_read(fname) call(RUST_G, "file_read")(fname)
|
||||
#define rustg_file_exists(fname) call(RUST_G, "file_exists")(fname)
|
||||
#define rustg_file_write(text, fname) call(RUST_G, "file_write")(text, fname)
|
||||
#define rustg_file_append(text, fname) call(RUST_G, "file_append")(text, fname)
|
||||
|
||||
#ifdef RUSTG_OVERRIDE_BUILTINS
|
||||
#define file2text(fname) rustg_file_read(fname)
|
||||
#define text2file(text, fname) rustg_file_append(text, fname)
|
||||
#define file2text(fname) rustg_file_read("[fname]")
|
||||
#define text2file(text, fname) rustg_file_append(text, "[fname]")
|
||||
#endif
|
||||
|
||||
// Git related operations //
|
||||
// Git Operations //
|
||||
#define rustg_git_revparse(rev) call(RUST_G, "rg_git_revparse")(rev)
|
||||
#define rustg_git_commit_date(rev) call(RUST_G, "rg_git_commit_date")(rev)
|
||||
|
||||
// Hash related operations //
|
||||
// Hashing Operations //
|
||||
#define rustg_hash_string(algorithm, text) call(RUST_G, "hash_string")(algorithm, text)
|
||||
#define rustg_hash_file(algorithm, fname) call(RUST_G, "hash_file")(algorithm, fname)
|
||||
#define rustg_hash_generate_totp(seed) call(RUST_G, "generate_totp")(seed)
|
||||
#define rustg_hash_generate_totp_tolerance(seed, tolerance) call(RUST_G, "generate_totp_tolerance")(seed, tolerance)
|
||||
|
||||
#define RUSTG_HASH_MD5 "md5"
|
||||
#define RUSTG_HASH_SHA1 "sha1"
|
||||
#define RUSTG_HASH_SHA256 "sha256"
|
||||
#define RUSTG_HASH_SHA512 "sha512"
|
||||
#define RUSTG_HASH_XXH64 "xxh64"
|
||||
#define RUSTG_HASH_BASE64 "base64"
|
||||
|
||||
#ifdef RUSTG_OVERRIDE_BUILTINS
|
||||
#define md5(thing) (isfile(thing) ? rustg_hash_file(RUSTG_HASH_MD5, "[thing]") : rustg_hash_string(RUSTG_HASH_MD5, thing))
|
||||
#define md5(thing) (isfile(thing) ? rustg_hash_file(RUSTG_HASH_MD5, "[thing]") : rustg_hash_string(RUSTG_HASH_MD5, thing))
|
||||
#endif
|
||||
|
||||
// Logging stuff //
|
||||
#define rustg_log_write(fname, text) call(RUST_G, "log_write")(fname, text)
|
||||
/proc/rustg_log_close_all() return call(RUST_G, "log_close_all")()
|
||||
|
||||
// URL encoding stuff
|
||||
#define rustg_url_encode(text) call(RUST_G, "url_encode")(text)
|
||||
#define rustg_url_decode(text) call(RUST_G, "url_decode")(text)
|
||||
|
||||
#ifdef RUSTG_OVERRIDE_BUILTINS
|
||||
#define url_encode(text) rustg_url_encode(text)
|
||||
#define url_decode(text) rustg_url_decode(text)
|
||||
#endif
|
||||
|
||||
// HTTP library stuff //
|
||||
// HTTP Operations //
|
||||
#define RUSTG_HTTP_METHOD_GET "get"
|
||||
#define RUSTG_HTTP_METHOD_PUT "put"
|
||||
#define RUSTG_HTTP_METHOD_DELETE "delete"
|
||||
#define RUSTG_HTTP_METHOD_PATCH "patch"
|
||||
#define RUSTG_HTTP_METHOD_HEAD "head"
|
||||
#define RUSTG_HTTP_METHOD_POST "post"
|
||||
|
||||
// Commented out because this thing locks up the entire DD process when you use it
|
||||
// DO NOT USE FOR THE LOVE OF GOD
|
||||
// #define rustg_http_request_blocking(method, url, body, headers) call(RUST_G, "http_request_blocking")(method, url, body, headers)
|
||||
#define rustg_http_request_async(method, url, body, headers) call(RUST_G, "http_request_async")(method, url, body, headers)
|
||||
#define rustg_http_request_blocking(method, url, body, headers, options) call(RUST_G, "http_request_blocking")(method, url, body, headers, options)
|
||||
#define rustg_http_request_async(method, url, body, headers, options) call(RUST_G, "http_request_async")(method, url, body, headers, options)
|
||||
#define rustg_http_check_request(req_id) call(RUST_G, "http_check_request")(req_id)
|
||||
/proc/rustg_create_async_http_client() return call(RUST_G, "start_http_client")()
|
||||
/proc/rustg_close_async_http_client() return call(RUST_G, "shutdown_http_client")()
|
||||
|
||||
// SQL stuff //
|
||||
// Jobs Subsystem Operations //
|
||||
#define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET"
|
||||
#define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB"
|
||||
#define RUSTG_JOB_ERROR "JOB PANICKED"
|
||||
|
||||
// JSON Operations //
|
||||
#define rustg_json_is_valid(text) (call(RUST_G, "json_is_valid")(text) == "true")
|
||||
|
||||
// Logging Operations //
|
||||
#define rustg_log_write(fname, text) call(RUST_G, "log_write")(fname, text)
|
||||
/proc/rustg_log_close_all() return call(RUST_G, "log_close_all")()
|
||||
|
||||
// Noise Operations //
|
||||
#define rustg_noise_get_at_coordinates(seed, x, y) call(RUST_G, "noise_get_at_coordinates")(seed, x, y)
|
||||
|
||||
// SQL Opeartions //
|
||||
#define rustg_sql_connect_pool(options) call(RUST_G, "sql_connect_pool")(options)
|
||||
#define rustg_sql_query_async(handle, query, params) call(RUST_G, "sql_query_async")(handle, query, params)
|
||||
#define rustg_sql_query_blocking(handle, query, params) call(RUST_G, "sql_query_blocking")(handle, query, params)
|
||||
@@ -82,8 +132,19 @@
|
||||
#define rustg_sql_disconnect_pool(handle) call(RUST_G, "sql_disconnect_pool")(handle)
|
||||
#define rustg_sql_check_query(job_id) call(RUST_G, "sql_check_query")("[job_id]")
|
||||
|
||||
// toml2json stuff //
|
||||
#define rustg_toml2json(tomlfile) call(RUST_G, "toml2json")(tomlfile)
|
||||
// TOML Operations //
|
||||
#define rustg_read_toml_file(path) json_decode(call(RUST_G, "toml_file_to_json")(path) || "null")
|
||||
|
||||
// Unzip Operations //
|
||||
#define rustg_unzip_download_async(url, unzip_directory) call(RUST_G, "unzip_download_async")(url, unzip_directory)
|
||||
#define rustg_unzip_check(job_id) call(RUST_G, "unzip_check")("[job_id]")
|
||||
|
||||
// URL Encoder/Decoder Operations //
|
||||
#define rustg_url_encode(text) call(RUST_G, "url_encode")("[text]")
|
||||
#define rustg_url_decode(text) call(RUST_G, "url_decode")(text)
|
||||
|
||||
#ifdef RUSTG_OVERRIDE_BUILTINS
|
||||
#define url_encode(text) rustg_url_encode(text)
|
||||
#define url_decode(text) rustg_url_decode(text)
|
||||
#endif
|
||||
|
||||
// RUSTG Version //
|
||||
#define RUST_G_VERSION "0.4.5-P3"
|
||||
|
||||
@@ -622,6 +622,13 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
stone = null
|
||||
return ..()
|
||||
|
||||
/obj/screen/alert/notify_mapvote
|
||||
name = "Map Vote"
|
||||
desc = "Vote on which map you would like to play on next!"
|
||||
icon_state = "map_vote"
|
||||
|
||||
/obj/screen/alert/notify_mapvote/Click()
|
||||
SSvote.browse_to(usr.client)
|
||||
|
||||
//OBJECT-BASED
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ GLOBAL_DATUM_INIT(configuration, /datum/server_configuration, new())
|
||||
var/config_file = "config/config.toml"
|
||||
if(!fexists(config_file))
|
||||
config_file = "config/example/config.toml" // Fallback to example if user hasnt setup config properly
|
||||
var/raw_json = rustg_toml2json(config_file)
|
||||
var/raw_json = rustg_read_toml_file(config_file)
|
||||
raw_data = json_decode(raw_json)
|
||||
|
||||
// Now pass through all our stuff
|
||||
@@ -141,7 +141,7 @@ GLOBAL_DATUM_INIT(configuration, /datum/server_configuration, new())
|
||||
DIRECT_OUTPUT(world.log, "Overrides found for this instance. Loading them.")
|
||||
var/start = start_watch() // Time tracking
|
||||
|
||||
var/raw_json = rustg_toml2json(override_file)
|
||||
var/raw_json = rustg_read_toml_file(override_file)
|
||||
raw_data = json_decode(raw_json)
|
||||
|
||||
// Now safely load our overrides.
|
||||
|
||||
@@ -408,12 +408,65 @@ SUBSYSTEM_DEF(ticker)
|
||||
if(player.mind.assigned_role != player.mind.special_role)
|
||||
SSjobs.AssignRank(player, player.mind.assigned_role, FALSE)
|
||||
SSjobs.EquipRank(player, player.mind.assigned_role, FALSE)
|
||||
EquipCustomItems(player)
|
||||
equip_cuis(player)
|
||||
|
||||
if(captainless)
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(!isnewplayer(M))
|
||||
to_chat(M, "Captainship not forced on anyone.")
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/equip_cuis(mob/living/carbon/human/H)
|
||||
if(!H.client)
|
||||
return // If they are spawning without a client (somehow), they *cant* have a CUI list
|
||||
for(var/datum/custom_user_item/cui in H.client.cui_entries)
|
||||
// Skip items with invalid character names
|
||||
if((cui.characer_name != H.real_name) && !cui.all_characters_allowed)
|
||||
continue
|
||||
|
||||
var/ok = FALSE
|
||||
|
||||
if(!cui.all_jobs_allowed)
|
||||
var/alt_blocked = FALSE
|
||||
if(H.mind.role_alt_title)
|
||||
if(!(H.mind.role_alt_title in cui.allowed_jobs))
|
||||
alt_blocked = TRUE
|
||||
if(!(H.mind.assigned_role in cui.allowed_jobs) || alt_blocked)
|
||||
continue
|
||||
|
||||
var/obj/item/I = new cui.object_typepath()
|
||||
var/name_override = cui.item_name_override
|
||||
var/desc_override = cui.item_desc_override
|
||||
|
||||
if(name_override)
|
||||
I.name = name_override
|
||||
if(desc_override)
|
||||
I.desc = desc_override
|
||||
|
||||
if(istype(H.back, /obj/item/storage)) // Try to place it in something on the mob's back
|
||||
var/obj/item/storage/S = H.back
|
||||
if(length(S.contents) < S.storage_slots)
|
||||
I.forceMove(H.back)
|
||||
ok = TRUE
|
||||
to_chat(H, "<span class='notice'>Your [I.name] has been added to your [H.back.name].</span>")
|
||||
|
||||
if(!ok)
|
||||
for(var/obj/item/storage/S in H.contents) // Try to place it in any item that can store stuff, on the mob.
|
||||
if(length(S.contents) < S.storage_slots)
|
||||
I.forceMove(S)
|
||||
ok = TRUE
|
||||
to_chat(H, "<span class='notice'>Your [I.name] has been added to your [S.name].</span>")
|
||||
break
|
||||
|
||||
if(!ok) // Finally, since everything else failed, place it on the ground
|
||||
var/turf/T = get_turf(H)
|
||||
if(T)
|
||||
I.forceMove(T)
|
||||
to_chat(H, "<span class='notice'>Your [I.name] is on the [T.name] below you.</span>")
|
||||
else
|
||||
to_chat(H, "<span class='notice'>Your [I.name] couldnt spawn anywhere on you or even on the floor below you. Please file a bug report.</span>")
|
||||
qdel(I)
|
||||
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
|
||||
var/m
|
||||
if(selected_tip)
|
||||
|
||||
@@ -266,8 +266,12 @@ SUBSYSTEM_DEF(vote)
|
||||
<a href='?src=[UID()];vote=open'>Click here or type vote to place your vote.</a>
|
||||
You have [GLOB.configuration.vote.vote_time / 10] seconds to vote.</font>"})
|
||||
switch(vote_type)
|
||||
if("crew transfer", "gamemode", "custom", "map")
|
||||
if("crew transfer", "gamemode", "custom")
|
||||
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
|
||||
if("map")
|
||||
SEND_SOUND(world, sound('sound/ambience/alarm4.ogg'))
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
M.throw_alert("Map Vote", /obj/screen/alert/notify_mapvote, timeout_override = GLOB.configuration.vote.vote_time)
|
||||
if(mode == "gamemode" && SSticker.ticker_going)
|
||||
SSticker.ticker_going = FALSE
|
||||
to_chat(world, "<font color='red'><b>Round start has been delayed.</b></font>")
|
||||
|
||||
@@ -423,6 +423,13 @@
|
||||
/datum/action/item_action/remove_badge
|
||||
name = "Remove Holobadge"
|
||||
|
||||
|
||||
// Clown Acrobat Shoes
|
||||
/datum/action/item_action/slipping
|
||||
name = "Tactical Slip"
|
||||
desc = "Activates the clown shoes' ankle-stimulating module, allowing the user to do a short slip forward going under anyone."
|
||||
button_icon_state = "clown"
|
||||
|
||||
// Jump boots
|
||||
/datum/action/item_action/bhop
|
||||
name = "Activate Jump Boots"
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* # Custom User Item
|
||||
*
|
||||
* Holder for CUIs
|
||||
*
|
||||
* This datum is a holder that is essentially a "model" of the `customuseritems`
|
||||
* database table, and is used for giving people their CUIs on spawn.
|
||||
* It is instanced as part of the client data loading framework on the client.
|
||||
*
|
||||
*/
|
||||
/datum/custom_user_item
|
||||
/// Can this be used on all characters?
|
||||
var/all_characters_allowed = FALSE
|
||||
/// Name of the character that can have this item.
|
||||
var/characer_name
|
||||
/// Are all jobs allowed?
|
||||
var/all_jobs_allowed = FALSE
|
||||
/// List of allowed jobs
|
||||
var/list/allowed_jobs = list()
|
||||
/// Custom item typepath
|
||||
var/object_typepath
|
||||
/// Custom item name override
|
||||
var/item_name_override
|
||||
/// Custom item description override
|
||||
var/item_desc_override
|
||||
/// Raw job mask
|
||||
var/raw_job_mask
|
||||
|
||||
|
||||
/**
|
||||
* CUI Info Parser
|
||||
*
|
||||
* Parses all the raw info into usable stuff, and also does validity checks
|
||||
* Returns TRUE if its a valid item, and FALSE if not
|
||||
*
|
||||
* Arguments:
|
||||
* * owning_ckey - Player who owns this item. Used for logging purposes.
|
||||
*/
|
||||
/datum/custom_user_item/proc/parse_info(owning_ckey)
|
||||
. = FALSE // Setting this here means it will return false even if it runtimes
|
||||
|
||||
// Sort path
|
||||
if(!object_typepath || !ispath(object_typepath))
|
||||
stack_trace("Incorrect database entry found in table 'customuseritems' path value is [object_typepath ? object_typepath : "(NULL)"], which doesnt exist. Ask the host to look at CUI entries for [owning_ckey]")
|
||||
return
|
||||
|
||||
// Sort job mask
|
||||
if(raw_job_mask == "*")
|
||||
all_jobs_allowed = TRUE
|
||||
else
|
||||
var/list/local_allowed_jobs = splittext(raw_job_mask, ",")
|
||||
for(var/i in 1 to length(local_allowed_jobs))
|
||||
if(istext(local_allowed_jobs[i]))
|
||||
local_allowed_jobs[i] = trim(local_allowed_jobs[i])
|
||||
|
||||
allowed_jobs = local_allowed_jobs
|
||||
|
||||
// Sort character name
|
||||
if(characer_name == "*")
|
||||
all_characters_allowed = TRUE
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/custom_user_item/vv_edit_var(var_name, var_value)
|
||||
return FALSE // fuck off
|
||||
@@ -19,6 +19,8 @@
|
||||
var/headers
|
||||
/// URL that the request is being sent to
|
||||
var/url
|
||||
/// If present, response body will be saved to this file.
|
||||
var/output_file
|
||||
/// The raw response, which will be decoeded into a [/datum/http_response]
|
||||
var/_raw_response
|
||||
/// Callback for executing after async requests. Will be called with an argument of [/datum/http_response] as first argument
|
||||
@@ -42,7 +44,7 @@ THE METHODS IN THIS FILE ARE TO BE USED BY THE SUBSYSTEM AS A MANGEMENT HUB
|
||||
* * _body - The body of the request, if applicable
|
||||
* * _headers - Associative list of HTTP headers to send, if applicab;e
|
||||
*/
|
||||
/datum/http_request/proc/prepare(_method, _url, _body = "", list/_headers)
|
||||
/datum/http_request/proc/prepare(_method, _url, _body = "", list/_headers, _output_file)
|
||||
if(!length(_headers))
|
||||
headers = ""
|
||||
else
|
||||
@@ -51,6 +53,7 @@ THE METHODS IN THIS FILE ARE TO BE USED BY THE SUBSYSTEM AS A MANGEMENT HUB
|
||||
method = _method
|
||||
url = _url
|
||||
body = _body
|
||||
output_file = _output_file
|
||||
|
||||
/**
|
||||
* Blocking executor
|
||||
@@ -60,7 +63,7 @@ THE METHODS IN THIS FILE ARE TO BE USED BY THE SUBSYSTEM AS A MANGEMENT HUB
|
||||
*/
|
||||
/datum/http_request/proc/execute_blocking()
|
||||
CRASH("Attempted to execute a blocking HTTP request")
|
||||
// _raw_response = rustg_http_request_blocking(method, url, body, headers)
|
||||
// _raw_response = rustg_http_request_blocking(method, url, body, headers, build_options())
|
||||
|
||||
/**
|
||||
* Async execution starter
|
||||
@@ -73,7 +76,7 @@ THE METHODS IN THIS FILE ARE TO BE USED BY THE SUBSYSTEM AS A MANGEMENT HUB
|
||||
if(in_progress)
|
||||
CRASH("Attempted to re-use a request object.")
|
||||
|
||||
id = rustg_http_request_async(method, url, body, headers)
|
||||
id = rustg_http_request_async(method, url, body, headers, build_options())
|
||||
|
||||
if(isnull(text2num(id)))
|
||||
_raw_response = "Proc error: [id]"
|
||||
@@ -81,6 +84,16 @@ THE METHODS IN THIS FILE ARE TO BE USED BY THE SUBSYSTEM AS A MANGEMENT HUB
|
||||
else
|
||||
in_progress = TRUE
|
||||
|
||||
/**
|
||||
* Options builder
|
||||
*
|
||||
* Builds options for if we want to download files with SShttp
|
||||
*/
|
||||
/datum/http_request/proc/build_options()
|
||||
if(output_file)
|
||||
return json_encode(list("output_filename" = output_file, "body_filename" = null))
|
||||
return null
|
||||
|
||||
/**
|
||||
* Async completion checker
|
||||
*
|
||||
|
||||
@@ -1456,6 +1456,12 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containername = "shaft miner starter kit"
|
||||
|
||||
/datum/supply_packs/misc/carpet
|
||||
name = "Carpet Crate"
|
||||
cost = 20
|
||||
contains = list(/obj/item/stack/tile/carpet/twenty)
|
||||
containername = "carpet crate"
|
||||
|
||||
|
||||
///////////// Paper Work
|
||||
|
||||
|
||||
@@ -167,18 +167,19 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
//Clown
|
||||
/datum/uplink_item/jobspecific/clowngrenade
|
||||
name = "Banana Grenade"
|
||||
desc = "A grenade that explodes into HONK! brand banana peels that are genetically modified to be extra slippery and extrude caustic acid when stepped on"
|
||||
desc = "A grenade that explodes into HONK! brand banana peels that are genetically modified to be extra slippery and extrude caustic acid when stepped on."
|
||||
reference = "BG"
|
||||
item = /obj/item/grenade/clown_grenade
|
||||
cost = 5
|
||||
job = list("Clown")
|
||||
|
||||
/datum/uplink_item/jobspecific/clownmagboots
|
||||
name = "Clown Magboots"
|
||||
desc = "A pair of modified clown shoes fitted with an advanced magnetic traction system. Look and sound exactly like regular clown shoes unless closely inspected."
|
||||
reference = "CM"
|
||||
item = /obj/item/clothing/shoes/magboots/clown
|
||||
/datum/uplink_item/jobspecific/clownslippers
|
||||
name = "Clown Acrobatic Shoes"
|
||||
desc = "A pair of modified clown shoes fitted with a built-in propulsion system that allows the user to perform a short slip below anyone. Turning on the waddle dampeners removes the slowdown on the shoes."
|
||||
reference = "CAS"
|
||||
item = /obj/item/clothing/shoes/clown_shoes/slippers
|
||||
cost = 3
|
||||
surplus = 75
|
||||
job = list("Clown")
|
||||
|
||||
/datum/uplink_item/jobspecific/trick_revolver
|
||||
|
||||
@@ -786,3 +786,24 @@
|
||||
/datum/AI_Module/large/cameracrack/upgrade(mob/living/silicon/ai/AI)
|
||||
if(AI.builtInCamera)
|
||||
QDEL_NULL(AI.builtInCamera)
|
||||
|
||||
/datum/AI_Module/large/engi_upgrade
|
||||
module_name = "Engineering Cyborg Emitter Upgrade"
|
||||
mod_pick_name = "emitter"
|
||||
description = "Downloads firmware that activates the built in emitter in all engineering cyborgs linked to you. Cyborgs built after this upgrade will have it pre-installed."
|
||||
cost = 50 // IDK look into this
|
||||
one_purchase = TRUE
|
||||
upgrade = TRUE
|
||||
unlock_text = "<span class='notice'>Firmware downloaded. Bugs removed. Built in emitters operating at 73% efficiency.</span>"
|
||||
unlock_sound = 'sound/items/rped.ogg'
|
||||
|
||||
/datum/AI_Module/large/engi_upgrade/upgrade(mob/living/silicon/ai/AI)
|
||||
AI.purchased_modules += /obj/item/robot_module/engineering
|
||||
log_game("[key_name(usr)] purchased emitters for all engineering cyborgs.")
|
||||
message_admins("<span class='notice'>[key_name_admin(usr)] purchased emitters for all engineering cyborgs!</span>")
|
||||
for(var/mob/living/silicon/robot/R in AI.connected_robots)
|
||||
if(!istype(R.module, /obj/item/robot_module/engineering))
|
||||
continue
|
||||
R.module.malfhacked = TRUE
|
||||
R.module.rebuild_modules()
|
||||
to_chat(R, "<span class='notice'>New firmware downloaded. Emitter is now online.</span>")
|
||||
|
||||
@@ -205,6 +205,15 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective)
|
||||
|
||||
/datum/objective/protect/mindslave //subytpe for mindslave implants
|
||||
|
||||
/datum/objective/protect/mindslave/on_target_cryo()
|
||||
if(owner?.current)
|
||||
to_chat(owner.current, "<BR><span class='userdanger'>You notice that your master has entered cryogenic storage, and revert to your normal self, until they return again. You are no longer a mindslave!</span>")
|
||||
SEND_SOUND(owner.current, sound('sound/ambience/alarm4.ogg'))
|
||||
owner.remove_antag_datum(/datum/antagonist/mindslave)
|
||||
SSticker.mode.implanted.Remove(owner)
|
||||
log_admin("[key_name(owner.current)]'s mindslave master has cryo'd, and is no longer a mindslave.")
|
||||
message_admins("[key_name_admin(owner.current)]'s mindslave master has cryo'd, and is no longer a mindslave.") //Since they were on antag hud earlier, this feels important to log
|
||||
qdel(src)
|
||||
|
||||
/datum/objective/hijack
|
||||
martyr_compatible = 0 //Technically you won't get both anyway.
|
||||
|
||||
@@ -343,6 +343,21 @@
|
||||
playsound(get_turf(user), 'sound/effects/ghost2.ogg', 50, 1)
|
||||
return TRUE
|
||||
|
||||
/datum/spellbook_entry/summon/slience_ghosts
|
||||
name = "Silence Ghosts"
|
||||
desc = "Tired of people talking behind your back, and spooking you? Why not silence them, and make the dead deader."
|
||||
cost = 2
|
||||
log_name = "SLG"
|
||||
is_ragin_restricted = TRUE //Salt needs to flow here, to be honest
|
||||
|
||||
/datum/spellbook_entry/summon/slience_ghosts/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
|
||||
new /datum/event/wizard/ghost_mute()
|
||||
active = TRUE
|
||||
to_chat(user, "<span class='notice'>You have silenced all ghosts!</span>")
|
||||
playsound(get_turf(user), 'sound/effects/ghost.ogg', 50, 1)
|
||||
message_admins("[key_name_admin(usr)] silenced all ghosts as a wizard! (Deadchat is now DISABLED)")
|
||||
return TRUE
|
||||
|
||||
/datum/spellbook_entry/summon/guns
|
||||
name = "Summon Guns"
|
||||
desc = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill you. There is a good chance that they will shoot each other first."
|
||||
|
||||
@@ -194,16 +194,18 @@ GLOBAL_DATUM_INIT(captain_announcement, /datum/announcement/minor, new(do_newsca
|
||||
/datum/job/judge
|
||||
title = "Magistrate"
|
||||
flag = JOB_JUDGE
|
||||
department_flag = JOBCAT_KARMA
|
||||
department_flag = JOBCAT_ENGSEC
|
||||
total_positions = 1
|
||||
spawn_positions = 1
|
||||
supervisors = "the Nanotrasen Supreme Court"
|
||||
department_head = list("Captain")
|
||||
selection_color = "#ddddff"
|
||||
req_admin_notify = 1
|
||||
is_legal = 1
|
||||
req_admin_notify = TRUE
|
||||
is_legal = TRUE
|
||||
transfer_allowed = FALSE
|
||||
minimal_player_age = 30
|
||||
exp_requirements = 6000 // 100 hours baby
|
||||
exp_type = EXP_TYPE_SECURITY
|
||||
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_FORENSICS_LOCKERS,
|
||||
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_EVA, ACCESS_HEADS,
|
||||
ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
|
||||
|
||||
@@ -96,8 +96,7 @@ GLOBAL_LIST_INIT(whitelisted_positions, list(
|
||||
"Blueshield",
|
||||
"Nanotrasen Representative",
|
||||
"Barber",
|
||||
"Brig Physician",
|
||||
"Magistrate"
|
||||
"Brig Physician"
|
||||
))
|
||||
|
||||
|
||||
|
||||
@@ -322,6 +322,8 @@
|
||||
if(shock(user, 100))
|
||||
return
|
||||
if(!is_operational())
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return ..()
|
||||
if(panel_open)
|
||||
to_chat(usr, "<span class='warning'>Close the maintenance panel first.</span>")
|
||||
else
|
||||
|
||||
@@ -88,6 +88,70 @@
|
||||
/obj/item/stack/tile/carpet/black/twenty
|
||||
amount = 20
|
||||
|
||||
/obj/item/stack/tile/carpet/blue
|
||||
name = "blue carpet"
|
||||
icon_state = "tile-carpet-blue"
|
||||
turf_type = /turf/simulated/floor/carpet/blue
|
||||
|
||||
/obj/item/stack/tile/carpet/blue/twenty
|
||||
amount = 20
|
||||
|
||||
/obj/item/stack/tile/carpet/cyan
|
||||
name = "cyan carpet"
|
||||
icon_state = "tile-carpet-cyan"
|
||||
turf_type = /turf/simulated/floor/carpet/cyan
|
||||
|
||||
/obj/item/stack/tile/carpet/cyan/twenty
|
||||
amount = 20
|
||||
|
||||
/obj/item/stack/tile/carpet/green
|
||||
name = "green carpet"
|
||||
icon_state = "tile-carpet-green"
|
||||
turf_type = /turf/simulated/floor/carpet/green
|
||||
|
||||
/obj/item/stack/tile/carpet/green/twenty
|
||||
amount = 20
|
||||
|
||||
/obj/item/stack/tile/carpet/orange
|
||||
name = "orange carpet"
|
||||
icon_state = "tile-carpet-orange"
|
||||
turf_type = /turf/simulated/floor/carpet/orange
|
||||
|
||||
/obj/item/stack/tile/carpet/orange/twenty
|
||||
amount = 20
|
||||
|
||||
/obj/item/stack/tile/carpet/purple
|
||||
name = "purple carpet"
|
||||
icon_state = "tile-carpet-purple"
|
||||
turf_type = /turf/simulated/floor/carpet/purple
|
||||
|
||||
/obj/item/stack/tile/carpet/purple/twenty
|
||||
amount = 20
|
||||
|
||||
/obj/item/stack/tile/carpet/red
|
||||
name = "red carpet"
|
||||
icon_state = "tile-carpet-red"
|
||||
turf_type = /turf/simulated/floor/carpet/red
|
||||
|
||||
/obj/item/stack/tile/carpet/red/twenty
|
||||
amount = 20
|
||||
|
||||
/obj/item/stack/tile/carpet/royalblack
|
||||
name = "royal black carpet"
|
||||
icon_state = "tile-carpet-royalblack"
|
||||
turf_type = /turf/simulated/floor/carpet/royalblack
|
||||
|
||||
/obj/item/stack/tile/carpet/royalblack/twenty
|
||||
amount = 20
|
||||
|
||||
/obj/item/stack/tile/carpet/royalblue
|
||||
name = "royal blue carpet"
|
||||
icon_state = "tile-carpet-royalblue"
|
||||
turf_type = /turf/simulated/floor/carpet/royalblue
|
||||
|
||||
/obj/item/stack/tile/carpet/royalblue/twenty
|
||||
amount = 20
|
||||
|
||||
//Plasteel
|
||||
/obj/item/stack/tile/plasteel
|
||||
name = "floor tiles"
|
||||
|
||||
@@ -371,6 +371,7 @@
|
||||
icon = 'icons/obj/food/containers.dmi'
|
||||
icon_state = "tray"
|
||||
desc = "A metal tray to lay food on."
|
||||
storage_slots = 8
|
||||
force = 5
|
||||
throwforce = 10
|
||||
throw_speed = 3
|
||||
|
||||
@@ -68,6 +68,9 @@
|
||||
playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1)
|
||||
make_plating()
|
||||
|
||||
|
||||
//Carpets
|
||||
|
||||
/turf/simulated/floor/carpet
|
||||
name = "carpet"
|
||||
icon = 'icons/turf/floors/carpet.dmi'
|
||||
@@ -112,6 +115,48 @@
|
||||
floor_tile = /obj/item/stack/tile/carpet/black
|
||||
canSmoothWith = list(/turf/simulated/floor/carpet/black)
|
||||
|
||||
/turf/simulated/floor/carpet/blue
|
||||
icon = 'icons/turf/floors/carpet_blue.dmi'
|
||||
floor_tile = /obj/item/stack/tile/carpet/blue
|
||||
canSmoothWith = list(/turf/simulated/floor/carpet/blue)
|
||||
|
||||
/turf/simulated/floor/carpet/cyan
|
||||
icon = 'icons/turf/floors/carpet_cyan.dmi'
|
||||
floor_tile = /obj/item/stack/tile/carpet/cyan
|
||||
canSmoothWith = list(/turf/simulated/floor/carpet/cyan)
|
||||
|
||||
/turf/simulated/floor/carpet/green
|
||||
icon = 'icons/turf/floors/carpet_green.dmi'
|
||||
floor_tile = /obj/item/stack/tile/carpet/green
|
||||
canSmoothWith = list(/turf/simulated/floor/carpet/green)
|
||||
|
||||
/turf/simulated/floor/carpet/orange
|
||||
icon = 'icons/turf/floors/carpet_orange.dmi'
|
||||
floor_tile = /obj/item/stack/tile/carpet/orange
|
||||
canSmoothWith = list(/turf/simulated/floor/carpet/orange)
|
||||
|
||||
/turf/simulated/floor/carpet/purple
|
||||
icon = 'icons/turf/floors/carpet_purple.dmi'
|
||||
floor_tile = /obj/item/stack/tile/carpet/purple
|
||||
canSmoothWith = list(/turf/simulated/floor/carpet/purple)
|
||||
|
||||
/turf/simulated/floor/carpet/red
|
||||
icon = 'icons/turf/floors/carpet_red.dmi'
|
||||
floor_tile = /obj/item/stack/tile/carpet/red
|
||||
canSmoothWith = list(/turf/simulated/floor/carpet/red)
|
||||
|
||||
/turf/simulated/floor/carpet/royalblack
|
||||
icon = 'icons/turf/floors/carpet_royalblack.dmi'
|
||||
floor_tile = /obj/item/stack/tile/carpet/royalblack
|
||||
canSmoothWith = list(/turf/simulated/floor/carpet/royalblack)
|
||||
|
||||
/turf/simulated/floor/carpet/royalblue
|
||||
icon = 'icons/turf/floors/carpet_royalblue.dmi'
|
||||
floor_tile = /obj/item/stack/tile/carpet/royalblue
|
||||
canSmoothWith = list(/turf/simulated/floor/carpet/royalblue)
|
||||
|
||||
//End of carpets
|
||||
|
||||
/turf/simulated/floor/fakespace
|
||||
icon = 'icons/turf/space.dmi'
|
||||
icon_state = "0"
|
||||
|
||||
@@ -706,8 +706,9 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
|
||||
|
||||
if(istext(flags))
|
||||
flags = text2num(flags)
|
||||
var/client/check_client = GLOB.directory[ckey]
|
||||
// Do a little check here
|
||||
if(GLOB.configuration.system.is_production && (flags & R_ADMIN) && prefs._2fa_status == _2FA_DISABLED) // If they are an admin and their 2FA is disabled
|
||||
if(GLOB.configuration.system.is_production && (flags & R_ADMIN) && check_client.prefs._2fa_status == _2FA_DISABLED) // If they are an admin and their 2FA is disabled
|
||||
to_chat(src,"<span class='boldannounce'><big>You do not have 2FA enabled. Admin verbs will be unavailable until you have enabled 2FA.</big></span>") // Very fucking obvious
|
||||
qdel(admin_read)
|
||||
return
|
||||
|
||||
@@ -117,10 +117,16 @@
|
||||
/// Client's pAI save
|
||||
var/datum/pai_save/pai_save
|
||||
|
||||
/// List of the clients CUIs
|
||||
var/list/datum/custom_user_item/cui_entries = list()
|
||||
|
||||
/client/vv_edit_var(var_name, var_value)
|
||||
switch(var_name)
|
||||
// I know we will never be in a world where admins are editing client vars to let people bypass TOS
|
||||
// But guess what, if I have the ability to overengineer something, I am going to do it
|
||||
if("tos_consent")
|
||||
return FALSE
|
||||
// Dont fuck with this
|
||||
if("cui_entries")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
@@ -149,8 +149,6 @@
|
||||
karma_purchase(karma,30,"job","Nanotrasen Representative")
|
||||
if("4")
|
||||
karma_purchase(karma,30,"job","Blueshield")
|
||||
if("5")
|
||||
karma_purchase(karma,45,"job","Magistrate")
|
||||
return
|
||||
if(href_list["KarmaBuy2"])
|
||||
var/karma=verify_karma()
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/datum/client_login_processor/cuis
|
||||
priority = 45
|
||||
|
||||
/datum/client_login_processor/cuis/get_query(client/C)
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT cuiRealName, cuiPath, cuiItemName, cuiDescription, cuiJobMask FROM customuseritems WHERE cuiCKey=:ckey", list(
|
||||
"ckey" = C.ckey
|
||||
))
|
||||
return query
|
||||
|
||||
/datum/client_login_processor/cuis/process_result(datum/db_query/Q, client/C)
|
||||
while(Q.NextRow())
|
||||
var/datum/custom_user_item/cui = new()
|
||||
cui.characer_name = Q.item[1]
|
||||
cui.object_typepath = text2path(Q.item[2])
|
||||
cui.item_name_override = Q.item[3]
|
||||
cui.item_desc_override = Q.item[4]
|
||||
cui.raw_job_mask = Q.item[5]
|
||||
|
||||
if(cui.parse_info(C.ckey))
|
||||
C.cui_entries += cui
|
||||
@@ -96,6 +96,9 @@
|
||||
if(user.get_active_hand() != src)
|
||||
to_chat(user, "You must hold [src] in your hand to do this.")
|
||||
return
|
||||
toggle_waddle(user)
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/proc/toggle_waddle(mob/living/user)
|
||||
if(!enabled_waddle)
|
||||
to_chat(user, "<span class='notice'>You switch off the waddle dampeners!</span>")
|
||||
enabled_waddle = TRUE
|
||||
@@ -111,6 +114,45 @@
|
||||
desc = "Standard-issue shoes of the wizarding class clown. Damn they're huge! And powerful! Somehow."
|
||||
magical = TRUE
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/slippers
|
||||
actions_types = list(/datum/action/item_action/slipping)
|
||||
var/slide_distance = 6
|
||||
var/recharging_rate = 8 SECONDS
|
||||
var/recharging_time = 0
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/slippers/item_action_slot_check(slot, mob/user)
|
||||
if(slot == slot_shoes)
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/slippers/ui_action_click(mob/user, action)
|
||||
if(recharging_time > world.time)
|
||||
to_chat(user, "<span class='warning'>The boot's internal propulsion needs to recharge still!</span>")
|
||||
return
|
||||
var/prev_dir = user.dir
|
||||
var/prev_pass_flags = user.pass_flags
|
||||
user.pass_flags |= PASSMOB
|
||||
user.Weaken(2)
|
||||
user.dir = prev_dir
|
||||
playsound(src, 'sound/effects/stealthoff.ogg', 50, TRUE, 1)
|
||||
recharging_time = world.time + recharging_rate
|
||||
user.visible_message("<span class='warning'>[user] slips forward!</span>")
|
||||
for(var/i in 1 to slide_distance)
|
||||
step(user, user.dir)
|
||||
sleep(1)
|
||||
user.SetWeakened(0)
|
||||
user.pass_flags = prev_pass_flags
|
||||
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/slippers/toggle_waddle(mob/living/user)
|
||||
if(!enabled_waddle)
|
||||
to_chat(user, "<span class='notice'>You switch off the waddle dampeners!</span>")
|
||||
enabled_waddle = TRUE
|
||||
slowdown = initial(slowdown)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You switch on the waddle dampeners, [src] no longer slow you down!</span>")
|
||||
enabled_waddle = FALSE
|
||||
slowdown = SHOES_SLOWDOWN
|
||||
|
||||
/obj/item/clothing/shoes/jackboots
|
||||
name = "jackboots"
|
||||
desc = "Nanotrasen-issue Security combat boots for combat scenarios or combat situations. All combat, all the time."
|
||||
|
||||
@@ -373,7 +373,71 @@
|
||||
result = list(/obj/item/stack/tile/carpet/black)
|
||||
time = 20
|
||||
reqs = list(/obj/item/stack/tile/carpet = 1)
|
||||
pathtools = list(/obj/item/toy/crayon)
|
||||
pathtools = list(/obj/item/toy/crayon/black)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/bluecarpet
|
||||
name = "Black Carpet"
|
||||
result = list(/obj/item/stack/tile/carpet/blue)
|
||||
time = 20
|
||||
reqs = list(/obj/item/stack/tile/carpet = 1)
|
||||
pathtools = list(/obj/item/toy/crayon/blue)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/cyancarpet
|
||||
name = "Cyan Carpet"
|
||||
result = list(/obj/item/stack/tile/carpet/blue)
|
||||
time = 20
|
||||
reqs = list(/obj/item/stack/tile/carpet = 1)
|
||||
pathtools = list(/obj/item/toy/crayon/blue, /obj/item/toy/crayon/green)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/greencarpet
|
||||
name = "Green Carpet"
|
||||
result = list(/obj/item/stack/tile/carpet/green)
|
||||
time = 20
|
||||
reqs = list(/obj/item/stack/tile/carpet = 1)
|
||||
pathtools = list(/obj/item/toy/crayon/green)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/orangecarpet
|
||||
name = "Orange Carpet"
|
||||
result = list(/obj/item/stack/tile/carpet/orange)
|
||||
time = 20
|
||||
reqs = list(/obj/item/stack/tile/carpet = 1)
|
||||
pathtools = list(/obj/item/toy/crayon/yellow, /obj/item/toy/crayon/red)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/purplecarpet
|
||||
name = "Purple Carpet"
|
||||
result = list(/obj/item/stack/tile/carpet/purple)
|
||||
time = 20
|
||||
reqs = list(/obj/item/stack/tile/carpet = 1)
|
||||
pathtools = list(/obj/item/toy/crayon/red, /obj/item/toy/crayon/blue)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/redcarpet
|
||||
name = "Red Carpet"
|
||||
result = list(/obj/item/stack/tile/carpet/purple)
|
||||
time = 20
|
||||
reqs = list(/obj/item/stack/tile/carpet = 1)
|
||||
pathtools = list(/obj/item/toy/crayon/red)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/royalblackcarpet
|
||||
name = "Royal Black Carpet"
|
||||
result = list(/obj/item/stack/tile/carpet/royalblack = 10)
|
||||
time = 20
|
||||
reqs = list(/obj/item/stack/tile/carpet/black = 10,
|
||||
/obj/item/stack/sheet/mineral/gold = 2)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/royalbluecarpet
|
||||
name = "Royal Blue Carpet"
|
||||
result = list(/obj/item/stack/tile/carpet/royalblue = 10)
|
||||
time = 20
|
||||
reqs = list(/obj/item/stack/tile/carpet/blue = 10,
|
||||
/obj/item/stack/sheet/mineral/gold = 2)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/showercurtain
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
/proc/EquipCustomItems(mob/living/carbon/human/M)
|
||||
if(!SSdbcore.IsConnected())
|
||||
return
|
||||
|
||||
// Grab the info we want.
|
||||
var/datum/db_query/query = SSdbcore.NewQuery({"
|
||||
SELECT cuiPath, cuiPropAdjust, cuiJobMask, cuiDescription, cuiItemName FROM customuseritems
|
||||
WHERE cuiCKey=:ckey AND (cuiRealName=:realname OR cuiRealName='*')"}, list(
|
||||
"ckey" = M.ckey,
|
||||
"realname" = M.real_name
|
||||
))
|
||||
if(!query.warn_execute(async = FALSE)) // Dont make this async. Youll make roundstart slow. Trust me.
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
while(query.NextRow())
|
||||
var/path = text2path(query.item[1])
|
||||
var/propadjust = query.item[2]
|
||||
var/jobmask = query.item[3]
|
||||
var/ok = 0
|
||||
if(!path || !ispath(path))
|
||||
log_debug("Incorrect database entry found in table 'customuseritems' path value = [path], cuiPath is null. cuiCKey='[M.ckey]' AND (cuiRealName='[M.real_name]' OR cuiRealName='*'")
|
||||
continue
|
||||
if(jobmask != "*")
|
||||
var/list/allowed_jobs = splittext(jobmask,",")
|
||||
for(var/i = 1, i <= allowed_jobs.len, i++)
|
||||
if(istext(allowed_jobs[i]))
|
||||
allowed_jobs[i] = trim(allowed_jobs[i])
|
||||
var/alt_blocked = 0
|
||||
if(M.mind.role_alt_title)
|
||||
if(!(M.mind.role_alt_title in allowed_jobs))
|
||||
alt_blocked = 1
|
||||
if(!(M.mind.assigned_role in allowed_jobs) || alt_blocked)
|
||||
continue
|
||||
|
||||
var/obj/item/Item = new path()
|
||||
var/description = query.item[4]
|
||||
var/newname = query.item[5]
|
||||
if(istype(Item,/obj/item/card/id))
|
||||
var/obj/item/card/id/I = Item
|
||||
for(var/obj/item/card/id/C in M)
|
||||
//default settings
|
||||
I.name = "[M.real_name]'s ID Card ([M.mind.role_alt_title ? M.mind.role_alt_title : M.mind.assigned_role])"
|
||||
I.registered_name = M.real_name
|
||||
I.access = C.access
|
||||
I.assignment = C.assignment
|
||||
I.blood_type = C.blood_type
|
||||
I.dna_hash = C.dna_hash
|
||||
I.fingerprint_hash = C.fingerprint_hash
|
||||
qdel(C)
|
||||
ok = M.equip_or_collect(I, slot_wear_id, 0) //if 1, last argument deletes on fail
|
||||
break
|
||||
else if(istype(M.back, /obj/item/storage)) // Try to place it in something on the mob's back
|
||||
var/obj/item/storage/S = M.back
|
||||
if(S.contents.len < S.storage_slots)
|
||||
Item.loc = M.back
|
||||
ok = 1
|
||||
to_chat(M, "<span class='notice'>Your [Item.name] has been added to your [M.back.name].</span>")
|
||||
if(ok == 0)
|
||||
for(var/obj/item/storage/S in M.contents) // Try to place it in any item that can store stuff, on the mob.
|
||||
if(S.contents.len < S.storage_slots)
|
||||
Item.loc = S
|
||||
ok = 1
|
||||
to_chat(M, "<span class='notice'>Your [Item.name] has been added to your [S.name].</span>")
|
||||
break
|
||||
if(description)
|
||||
Item.desc = description
|
||||
if(newname)
|
||||
Item.name = newname
|
||||
|
||||
if(ok == 0) // Finally, since everything else failed, place it on the ground
|
||||
Item.loc = get_turf(M.loc)
|
||||
|
||||
HackProperties(Item,propadjust)
|
||||
M.regenerate_icons()
|
||||
qdel(query)
|
||||
|
||||
// This is hacky, but since it's difficult as fuck to make a proper parser in BYOND without killing the server, here it is. - N3X
|
||||
/proc/HackProperties(mob/living/carbon/human/M, obj/item/I, script)
|
||||
var/list/statements = splittext(script,";")
|
||||
if(statements.len == 0)
|
||||
return
|
||||
for(var/statement in statements)
|
||||
var/list/assignmentChunks = splittext(statement,"=")
|
||||
var/varname = assignmentChunks[1]
|
||||
var/list/typeChunks=splittext(script,":")
|
||||
var/desiredType=typeChunks[1]
|
||||
switch(desiredType)
|
||||
if("string")
|
||||
var/output = typeChunks[2]
|
||||
output = replacetext(output,"{REALNAME}", M.real_name)
|
||||
output = replacetext(output,"{ROLE}", M.mind.assigned_role)
|
||||
output = replacetext(output,"{ROLE_ALT}", "[M.mind.role_alt_title ? M.mind.role_alt_title : M.mind.assigned_role]")
|
||||
I.vars[varname]=output
|
||||
if("number")
|
||||
I.vars[varname]=text2num(typeChunks[2])
|
||||
if("icon")
|
||||
if(typeChunks.len==2)
|
||||
I.vars[varname]=new /icon(typeChunks[2])
|
||||
if(typeChunks.len==3)
|
||||
I.vars[varname]=new /icon(typeChunks[2],typeChunks[3])
|
||||
@@ -3,3 +3,12 @@
|
||||
/datum/event/wizard/ghost/start()
|
||||
var/msg = "<span class='warning'>You suddenly feel extremely obvious...</span>"
|
||||
set_observer_default_invisibility(0, msg)
|
||||
|
||||
/datum/event/wizard/ghost_mute //The spook is silent
|
||||
|
||||
/datum/event/wizard/ghost_mute/start()
|
||||
GLOB.dsay_enabled = FALSE
|
||||
var/sound/S = sound('sound/hallucinations/wail.ogg')
|
||||
for(var/mob/dead/observer/silenced in GLOB.player_list)
|
||||
to_chat(silenced, "<span class='warning'>Magical forces wrap around your spectral form. You can no longer speak to other ghosts!</span>")
|
||||
SEND_SOUND(silenced, S)
|
||||
|
||||
@@ -200,11 +200,12 @@
|
||||
deckshuffle()
|
||||
|
||||
/obj/item/deck/verb/verb_shuffle()
|
||||
set category = "Object"
|
||||
set name = "Shuffle"
|
||||
set desc = "Shuffle the cards in the deck."
|
||||
set src in view(1)
|
||||
deckshuffle()
|
||||
if(!isobserver(usr))
|
||||
set category = "Object"
|
||||
set name = "Shuffle"
|
||||
set desc = "Shuffle the cards in the deck."
|
||||
set src in view(1)
|
||||
deckshuffle()
|
||||
|
||||
/obj/item/deck/proc/deckshuffle()
|
||||
var/mob/living/user = usr
|
||||
|
||||
@@ -275,10 +275,6 @@ GLOBAL_LIST_EMPTY(karma_spenders)
|
||||
dat += "<a href='?src=[UID()];karmashop=shop;KarmaBuy=4'>Unlock Blueshield -- 30KP</a><br>"
|
||||
else
|
||||
dat += "Blueshield - <font color='green'>Unlocked</font><br>"
|
||||
if(!("Magistrate" in joblist))
|
||||
dat += "<a href='?src=[UID()];karmashop=shop;KarmaBuy=5'>Unlock Magistrate -- 45KP</a><br>"
|
||||
else
|
||||
dat+= "Magistrate - <font color='green'>Unlocked</font><br>"
|
||||
|
||||
if(1) // Species Unlocks
|
||||
if(!("Machine" in specieslist))
|
||||
@@ -349,6 +345,9 @@ GLOBAL_LIST_EMPTY(karma_spenders)
|
||||
if("Security Pod Pilot" in purchased)
|
||||
refundable += "Security Pod Pilot"
|
||||
dat += "<a href='?src=[UID()];karmashop=shop;KarmaRefund=Security Pod Pilot;KarmaRefundType=job;KarmaRefundCost=30'>Refund Security Pod Pilot -- 30KP</a><br>"
|
||||
if("Magistrate" in purchased)
|
||||
refundable += "Magistrate"
|
||||
dat += "<a href='?src=[UID()];karmashop=shop;KarmaRefund=Magistrate;KarmaRefundType=job;KarmaRefundCost=45'>Refund Magistrate -- 45KP</a><br>"
|
||||
|
||||
if(!refundable.len)
|
||||
dat += "You do not have any refundable karma purchases.<br>"
|
||||
@@ -515,6 +514,8 @@ GLOBAL_LIST_EMPTY(karma_spenders)
|
||||
cost = 30
|
||||
if("Nanotrasen Recruiter")
|
||||
cost = 10
|
||||
if("Magistrate")
|
||||
cost = 45
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>That job is not refundable.</span>")
|
||||
return
|
||||
|
||||
@@ -79,6 +79,9 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
|
||||
var/obj/machinery/power/apc/malfhack = null
|
||||
var/explosive = 0 //does the AI explode when it dies?
|
||||
|
||||
/// List of modules the AI has purchased malf upgrades for.
|
||||
var/list/purchased_modules = list()
|
||||
|
||||
var/mob/living/silicon/ai/parent = null
|
||||
var/camera_light_on = 0
|
||||
var/list/obj/machinery/camera/lit_cameras = list()
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
"Parrot" = "parrot",
|
||||
"Box Bot" = "boxbot",
|
||||
"Spider Bot" = "spiderbot",
|
||||
"Fairy" = "fairy"
|
||||
"Fairy" = "fairy",
|
||||
"Snake" = "snake"
|
||||
)
|
||||
|
||||
var/global/list/possible_say_verbs = list(
|
||||
@@ -35,7 +36,8 @@
|
||||
"Beep" = list("beeps","beeps loudly","boops"),
|
||||
"Chirp" = list("chirps","chirrups","cheeps"),
|
||||
"Feline" = list("purrs","yowls","meows"),
|
||||
"Canine" = list("yaps","barks","growls")
|
||||
"Canine" = list("yaps","barks","growls"),
|
||||
"Hiss" = list("hisses","hisses","hisses")
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1264,6 +1264,8 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
|
||||
connected_ai = AI
|
||||
connected_ai.connected_robots |= src
|
||||
notify_ai(1)
|
||||
if(module)
|
||||
module.rebuild_modules() //This way, if a borg gets linked to a malf AI that has upgrades, they get their upgrades.
|
||||
sync()
|
||||
|
||||
/mob/living/silicon/robot/adjustOxyLoss(amount)
|
||||
|
||||
@@ -6,12 +6,17 @@
|
||||
item_state = "electronic"
|
||||
flags = CONDUCT
|
||||
|
||||
/// Has the AI hacked the borg module, allowing access to the malf AI exclusive item.
|
||||
var/malfhacked = FALSE
|
||||
|
||||
/// A list of all currently usable and created modules the robot currently has access too.
|
||||
var/list/modules = list()
|
||||
/// A list of module-specific, non-emag modules the borg will gain when this module is chosen.
|
||||
var/list/basic_modules = list()
|
||||
/// A list of modules the robot gets when emagged.
|
||||
var/list/emag_modules = list()
|
||||
/// A list of modules that the robot gets when malf AI buys it.
|
||||
var/list/malf_modules = list()
|
||||
/// A list of modules that require special recharge handling. Examples include things like flashes, sprays and welding tools.
|
||||
var/list/special_rechargables = list()
|
||||
/// A list of all "energy stacks", i.e metal, glass, brute kits, splints, etc.
|
||||
@@ -43,12 +48,17 @@
|
||||
emag_modules += I
|
||||
emag_modules -= i
|
||||
|
||||
for(var/i in malf_modules)
|
||||
var/obj/item/I = new i(src)
|
||||
malf_modules += I
|
||||
malf_modules -= i
|
||||
|
||||
// Flashes need a special recharge, and since basically every module uses it, add it here.
|
||||
// Even if the module doesn't use a flash, it wont cause any issues to have it in this list.
|
||||
special_rechargables += /obj/item/flash/cyborg
|
||||
|
||||
// This is done so we can loop through this list later and call cyborg_recharge() on the items while the borg is recharging.
|
||||
var/all_modules = basic_modules | emag_modules
|
||||
var/all_modules = basic_modules | emag_modules | malf_modules
|
||||
for(var/path in special_rechargables)
|
||||
var/obj/item/I = locate(path) in all_modules
|
||||
if(I) // If it exists, add the object reference.
|
||||
@@ -70,6 +80,7 @@
|
||||
QDEL_LIST(modules)
|
||||
QDEL_LIST(basic_modules)
|
||||
QDEL_LIST(emag_modules)
|
||||
QDEL_LIST(malf_modules)
|
||||
QDEL_LIST(storages)
|
||||
QDEL_LIST(special_rechargables)
|
||||
return ..()
|
||||
@@ -88,6 +99,7 @@
|
||||
var/list/lists = list(
|
||||
basic_modules,
|
||||
emag_modules,
|
||||
malf_modules,
|
||||
storages,
|
||||
special_rechargables
|
||||
)
|
||||
@@ -155,13 +167,17 @@
|
||||
return I
|
||||
|
||||
/**
|
||||
* Builds the usable module list from the modules we have in `basic_modules` and `emag_modules`
|
||||
* Builds the usable module list from the modules we have in `basic_modules`, `emag_modules` and `malf_modules`
|
||||
*/
|
||||
/obj/item/robot_module/proc/rebuild_modules()
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
R.uneq_all()
|
||||
modules = list()
|
||||
|
||||
if(!malfhacked && R.connected_ai)
|
||||
if(type in R.connected_ai.purchased_modules)
|
||||
malfhacked = TRUE
|
||||
|
||||
// By this point these lists should only contain items. It's safe to use typeless loops here.
|
||||
for(var/item in basic_modules)
|
||||
add_module(item, FALSE)
|
||||
@@ -170,6 +186,10 @@
|
||||
for(var/item in emag_modules)
|
||||
add_module(item, FALSE)
|
||||
|
||||
if(malfhacked)
|
||||
for(var/item in malf_modules)
|
||||
add_module(item, FALSE)
|
||||
|
||||
if(R.hud_used)
|
||||
R.hud_used.update_robot_modules_display()
|
||||
|
||||
@@ -354,8 +374,9 @@
|
||||
/obj/item/stack/sheet/glass/cyborg,
|
||||
/obj/item/stack/sheet/rglass/cyborg
|
||||
)
|
||||
emag_modules = list(/obj/item/borg/stun)
|
||||
special_rechargables = list(/obj/item/extinguisher, /obj/item/weldingtool/largetank/cyborg)
|
||||
emag_modules = list(/obj/item/borg/stun, /obj/item/restraints/handcuffs/cable/zipties/cyborg)
|
||||
malf_modules = list(/obj/item/gun/energy/emitter/cyborg)
|
||||
special_rechargables = list(/obj/item/extinguisher, /obj/item/weldingtool/largetank/cyborg, /obj/item/gun/energy/emitter/cyborg)
|
||||
|
||||
/obj/item/robot_module/engineering/handle_death(mob/living/silicon/robot/R, gibbed)
|
||||
var/obj/item/gripper/G = locate(/obj/item/gripper) in modules
|
||||
@@ -400,7 +421,7 @@
|
||||
/obj/item/holosign_creator,
|
||||
/obj/item/extinguisher/mini
|
||||
)
|
||||
emag_modules = list(/obj/item/reagent_containers/spray/cyborg_lube)
|
||||
emag_modules = list(/obj/item/reagent_containers/spray/cyborg_lube, /obj/item/restraints/handcuffs/cable/zipties/cyborg)
|
||||
special_rechargables = list(
|
||||
/obj/item/lightreplacer,
|
||||
/obj/item/reagent_containers/spray/cyborg_lube,
|
||||
@@ -471,7 +492,7 @@
|
||||
/obj/item/storage/bag/tray/cyborg,
|
||||
/obj/item/reagent_containers/food/drinks/shaker
|
||||
)
|
||||
emag_modules = list(/obj/item/reagent_containers/food/drinks/cans/beer/sleepy_beer)
|
||||
emag_modules = list(/obj/item/reagent_containers/food/drinks/cans/beer/sleepy_beer, /obj/item/restraints/handcuffs/cable/zipties/cyborg)
|
||||
special_rechargables = list(
|
||||
/obj/item/reagent_containers/food/condiment/enzyme,
|
||||
/obj/item/reagent_containers/food/drinks/cans/beer/sleepy_beer
|
||||
@@ -530,7 +551,7 @@
|
||||
/obj/item/gun/energy/kinetic_accelerator/cyborg,
|
||||
/obj/item/gps/cyborg
|
||||
)
|
||||
emag_modules = list(/obj/item/borg/stun, /obj/item/pickaxe/drill/cyborg/diamond)
|
||||
emag_modules = list(/obj/item/borg/stun, /obj/item/pickaxe/drill/cyborg/diamond, /obj/item/restraints/handcuffs/cable/zipties/cyborg)
|
||||
special_rechargables = list(/obj/item/extinguisher/mini, /obj/item/weldingtool/mini)
|
||||
|
||||
// Replace their normal drill with a diamond drill.
|
||||
|
||||
@@ -359,7 +359,7 @@
|
||||
character.buckled.dir = character.dir
|
||||
|
||||
character = SSjobs.EquipRank(character, rank, 1) //equips the human
|
||||
EquipCustomItems(character)
|
||||
SSticker.equip_cuis(character) // Gives them their CUIs
|
||||
|
||||
SSticker.mode.latespawn(character)
|
||||
|
||||
|
||||
@@ -140,6 +140,7 @@
|
||||
var/on = 0
|
||||
var/brightness_on = 2
|
||||
light_color = LIGHT_COLOR_RED
|
||||
armour_penetration = 20
|
||||
|
||||
/obj/item/pen/edagger/attack_self(mob/living/user)
|
||||
if(on)
|
||||
|
||||
@@ -271,6 +271,17 @@
|
||||
delay = 50
|
||||
select_name = "snipe"
|
||||
|
||||
/obj/item/ammo_casing/energy/emitter
|
||||
projectile_type = /obj/item/projectile/beam/emitter
|
||||
muzzle_flash_color = LIGHT_COLOR_GREEN
|
||||
fire_sound = 'sound/weapons/emitter.ogg'
|
||||
e_cost = 100
|
||||
delay = 2 SECONDS // Lasers fire twice every second for 40 dps, this fires every 2 seconds for 15 dps. Seems fair, since every cyborg will have this with more shots?
|
||||
select_name = "emitter"
|
||||
|
||||
/obj/item/ammo_casing/energy/emitter/cyborg
|
||||
e_cost = 500 // about 28 shots on an engineering borg from a borging machine, assuming some power is used for lights / movement. May need to change.
|
||||
|
||||
/obj/item/ammo_casing/energy/bsg
|
||||
projectile_type = /obj/item/projectile/energy/bsg
|
||||
muzzle_flash_color = LIGHT_COLOR_DARKBLUE
|
||||
|
||||
@@ -141,6 +141,29 @@
|
||||
name = "cyborg immolator cannon"
|
||||
ammo_type = list(/obj/item/ammo_casing/energy/immolator/scatter/cyborg, /obj/item/ammo_casing/energy/immolator/strong/cyborg) // scatter is default, because it is more useful
|
||||
|
||||
/obj/item/gun/energy/emitter
|
||||
name = "mobile emitter"
|
||||
desc = "An emitter removed from its base, and attached to a laser cannon frame."
|
||||
icon_state = "emittercannon"
|
||||
item_state = "laser"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
shaded_charge = TRUE
|
||||
can_holster = FALSE
|
||||
origin_tech = "combat=4;magnets=4;powerstorage=3"
|
||||
ammo_type = list(/obj/item/ammo_casing/energy/emitter)
|
||||
ammo_x_offset = 3
|
||||
|
||||
/obj/item/gun/energy/emitter/cyborg
|
||||
name = "mounted emitter"
|
||||
desc = "An emitter built into to your cyborg frame, draining charge from your cell."
|
||||
ammo_type = list(/obj/item/ammo_casing/energy/emitter/cyborg)
|
||||
|
||||
/obj/item/gun/energy/emitter/cyborg/newshot()
|
||||
..()
|
||||
robocharge()
|
||||
|
||||
/obj/item/gun/energy/emitter/cyborg/emp_act()
|
||||
return
|
||||
|
||||
////////Laser Tag////////////////////
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 6.8 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
@@ -23,6 +23,7 @@
|
||||
#include "code\__DEFINES\_spacemandmm.dm"
|
||||
#include "code\__DEFINES\_tgs_defines.dm"
|
||||
#include "code\__DEFINES\_tick.dm"
|
||||
#include "code\__DEFINES\_versions.dm"
|
||||
#include "code\__DEFINES\access.dm"
|
||||
#include "code\__DEFINES\admin.dm"
|
||||
#include "code\__DEFINES\antagonists.dm"
|
||||
@@ -278,6 +279,7 @@
|
||||
#include "code\datums\callback.dm"
|
||||
#include "code\datums\chatmessage.dm"
|
||||
#include "code\datums\click_intercept.dm"
|
||||
#include "code\datums\custom_user_item.dm"
|
||||
#include "code\datums\datacore.dm"
|
||||
#include "code\datums\datum.dm"
|
||||
#include "code\datums\datumvars.dm"
|
||||
@@ -1390,6 +1392,7 @@
|
||||
#include "code\modules\client\login_processing\38-alts_cid.dm"
|
||||
#include "code\modules\client\login_processing\39-cid_count.dm"
|
||||
#include "code\modules\client\login_processing\40-pai_save.dm"
|
||||
#include "code\modules\client\login_processing\45-cuis.dm"
|
||||
#include "code\modules\client\login_processing\__client_login_processor.dm"
|
||||
#include "code\modules\client\preference\character.dm"
|
||||
#include "code\modules\client\preference\link_processing.dm"
|
||||
@@ -1484,7 +1487,6 @@
|
||||
#include "code\modules\crafting\recipes.dm"
|
||||
#include "code\modules\crafting\tailoring.dm"
|
||||
#include "code\modules\customitems\item_defines.dm"
|
||||
#include "code\modules\customitems\item_spawning.dm"
|
||||
#include "code\modules\detective_work\detective_work.dm"
|
||||
#include "code\modules\detective_work\evidence.dm"
|
||||
#include "code\modules\detective_work\footprints_and_rag.dm"
|
||||
|
||||
@@ -37,7 +37,7 @@ else:
|
||||
fail("RUSTG DM header file does NOT exist")
|
||||
|
||||
# Parse the version from the DM file
|
||||
f = open("code/__DEFINES/rust_g.dm", "r")
|
||||
f = open("code/__DEFINES/_versions.dm", "r")
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
dm_version = None
|
||||
@@ -92,16 +92,16 @@ else:
|
||||
# Make sure we can parse TOML
|
||||
string_array = c_char_p * 1
|
||||
sa = string_array(bytes(ci_toml_file_location, "ascii"))
|
||||
rustg_dll.toml2json.argtypes = [c_int, c_char_p * 1]
|
||||
rustg_dll.toml_file_to_json.argtypes = [c_int, c_char_p * 1]
|
||||
# Set args for JSON retrieval
|
||||
rustg_dll.toml2json.restype = c_char_p
|
||||
rustg_dll.toml_file_to_json.restype = c_char_p
|
||||
|
||||
try:
|
||||
# Run it
|
||||
output_json = rustg_dll.toml2json(1, sa).decode()
|
||||
output_json = rustg_dll.toml_file_to_json(1, sa).decode()
|
||||
json.loads(output_json)
|
||||
success("toml2json conversion successful")
|
||||
success("toml_file_to_json successful")
|
||||
except Exception:
|
||||
fail("Failed to convert toml2json")
|
||||
fail("Failed to run toml_file_to_json")
|
||||
|
||||
exit(0) # Success
|
||||
|
||||