diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm index c1aaed9e42..44273c80ff 100644 --- a/code/__defines/species_languages.dm +++ b/code/__defines/species_languages.dm @@ -5,12 +5,15 @@ #define NO_PAIN 0x8 // Cannot suffer halloss/recieves deceptive health indicator. #define NO_SLIP 0x10 // Cannot fall over. #define NO_POISON 0x20 // Cannot not suffer toxloss. +#define NO_EMBED 0x40 // Can step on broken glass with no ill-effects and cannot have shrapnel embedded in it. // unused: 0x8000 - higher than this will overflow // Species spawn flags #define SPECIES_IS_WHITELISTED 0x1 // Must be whitelisted to play. #define SPECIES_IS_RESTRICTED 0x2 // Is not a core/normally playable species. (castes, mutantraces) #define SPECIES_CAN_JOIN 0x4 // Species is selectable in chargen. +#define SPECIES_NO_FBP_CONSTRUCTION 0x8 // FBP of this species can't be made in-game. +#define SPECIES_NO_FBP_CHARGEN 0x10 // FBP of this species can't be selected at chargen. // Species appearance flags #define HAS_SKIN_TONE 0x1 // Skin tone selectable in chargen. (0-255) @@ -22,15 +25,19 @@ #define RADIATION_GLOWS 0x40 // Radiation causes this character to glow. // Languages. +#define LANGUAGE_GALCOM "Galactic Common" +#define LANGUAGE_EAL "Encoded Audio Language" #define LANGUAGE_SOL_COMMON "Sol Common" #define LANGUAGE_UNATHI "Sinta'unathi" #define LANGUAGE_SIIK "Siik" #define LANGUAGE_SKRELLIAN "Skrellian" -#define LANGUAGE_ROOTSPEAK "Rootspeak" #define LANGUAGE_TRADEBAND "Tradeband" #define LANGUAGE_GUTTER "Gutter" #define LANGUAGE_SCHECHI "Schechi" +#define LANGUAGE_ROOTLOCAL "Local Rootspeak" +#define LANGUAGE_ROOTGLOBAL "Global Rootspeak" #define LANGUAGE_CULT "Cult" +#define LANGUAGE_SIGN "Sign Language" // Language flags. #define WHITELISTED 1 // Language is available if the speaker is whitelisted. @@ -42,3 +49,4 @@ #define INNATE 64 // All mobs can be assumed to speak and understand this language. (audible emotes) #define NO_TALK_MSG 128 // Do not show the "\The [speaker] talks into \the [radio]" message #define NO_STUTTER 256 // No stuttering, slurring, or other speech problems +#define ALT_TRANSMIT 512 // Language is not based on vision or sound (Todo: add this into the say code and use it for the rootspeak languages) \ No newline at end of file diff --git a/code/__defines/unit_tests.dm b/code/__defines/unit_tests.dm index 478c75fdb2..840673221c 100644 --- a/code/__defines/unit_tests.dm +++ b/code/__defines/unit_tests.dm @@ -1,4 +1,5 @@ #define ASCII_ESC ascii2text(27) #define ASCII_RED "[ASCII_ESC]\[31m" #define ASCII_GREEN "[ASCII_ESC]\[32m" +#define ASCII_YELLOW "[ASCII_ESC]\[33m" #define ASCII_RESET "[ASCII_ESC]\[0m" \ No newline at end of file diff --git a/code/_helpers/turfs.dm b/code/_helpers/turfs.dm index 8583628114..1926246856 100644 --- a/code/_helpers/turfs.dm +++ b/code/_helpers/turfs.dm @@ -32,3 +32,10 @@ if(!available_turfs.len) available_turfs = start_turfs return pick(available_turfs) + +/proc/is_below_sound_pressure(var/turf/T) + var/datum/gas_mixture/environment = T ? T.return_air() : null + var/pressure = environment ? environment.return_pressure() : 0 + if(pressure < SOUND_MINIMUM_PRESSURE) + return TRUE + return FALSE \ No newline at end of file diff --git a/code/_helpers/type2type.dm b/code/_helpers/type2type.dm index 0bcf546123..8dc9cb020b 100644 --- a/code/_helpers/type2type.dm +++ b/code/_helpers/type2type.dm @@ -73,14 +73,14 @@ // Turns a direction into text /proc/dir2text(direction) switch (direction) - if (1.0) return "north" - if (2.0) return "south" - if (4.0) return "east" - if (8.0) return "west" - if (5.0) return "northeast" - if (6.0) return "southeast" - if (9.0) return "northwest" - if (10.0) return "southwest" + if (NORTH) return "north" + if (SOUTH) return "south" + if (EAST) return "east" + if (WEST) return "west" + if (NORTHEAST) return "northeast" + if (SOUTHEAST) return "southeast" + if (NORTHWEST) return "northwest" + if (SOUTHWEST) return "southwest" // Turns text into proper directions /proc/text2dir(direction) diff --git a/code/controllers/communications.dm b/code/controllers/communications.dm index f9e7b67c74..97d193bc5b 100644 --- a/code/controllers/communications.dm +++ b/code/controllers/communications.dm @@ -108,6 +108,7 @@ var/const/ERT_FREQ = 1345 var/const/AI_FREQ = 1343 var/const/DTH_FREQ = 1341 var/const/SYND_FREQ = 1213 +var/const/ENT_FREQ = 1461 //entertainment frequency. This is not a diona exclusive frequency. // department channels var/const/PUB_FREQ = 1459 @@ -135,6 +136,7 @@ var/list/radiochannels = list( "Supply" = SUP_FREQ, "Service" = SRV_FREQ, "AI Private" = AI_FREQ, + "Entertainment" = ENT_FREQ, "Medical(I)" = MED_I_FREQ, "Security(I)" = SEC_I_FREQ ) @@ -146,7 +148,7 @@ var/list/CENT_FREQS = list(ERT_FREQ, DTH_FREQ) var/list/ANTAG_FREQS = list(SYND_FREQ) //Department channels, arranged lexically -var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, MED_FREQ, SEC_FREQ, SCI_FREQ, SRV_FREQ, SUP_FREQ) +var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, ENT_FREQ, MED_FREQ, SEC_FREQ, SCI_FREQ, SRV_FREQ, SUP_FREQ) #define TRANSMISSION_WIRE 0 #define TRANSMISSION_RADIO 1 @@ -177,6 +179,8 @@ var/list/DEPT_FREQS = list(AI_FREQ, COMM_FREQ, ENG_FREQ, MED_FREQ, SEC_FREQ, SCI return "supradio" if(frequency == SRV_FREQ) // service return "srvradio" + if(frequency == ENT_FREQ) // entertainment + return "entradio" if(frequency in DEPT_FREQS) return "deptradio" diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index ae0d5a2544..43424f97df 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -160,6 +160,7 @@ var/list/gamemode_cache = list() var/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt var/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt var/use_age_restriction_for_jobs = 0 //Do jobs use account age restrictions? --requires database + var/use_age_restriction_for_antags = 0 //Do antags use account age restrictions? --requires database var/simultaneous_pm_warning_timeout = 100 @@ -278,6 +279,9 @@ var/list/gamemode_cache = list() if ("use_age_restriction_for_jobs") config.use_age_restriction_for_jobs = 1 + if ("use_age_restriction_for_antags") + config.use_age_restriction_for_antags = 1 + if ("jobs_have_minimal_access") config.jobs_have_minimal_access = 1 diff --git a/code/datums/EPv2.dm b/code/datums/EPv2.dm index a4e57d346d..37a1a0ba1f 100644 --- a/code/datums/EPv2.dm +++ b/code/datums/EPv2.dm @@ -112,23 +112,27 @@ var/global/list/all_exonet_connections = list() return null // Proc: send_message() -// Parameters: 3 (target_address - the desired address to send the message to, message - the message to send, text - the message text if message is of type "text") -// Description: Sends the message to target_address, by calling receive_message() on the desired datum. -/datum/exonet_protocol/proc/send_message(var/target_address, var/message, var/text) +// Parameters: 3 (target_address - the desired address to send the message to, data_type - text stating what the content is meant to be used for, +// content - the actual 'message' being sent to the address) +// Description: Sends the message to target_address, by calling receive_message() on the desired datum. Returns true if the message is recieved. +/datum/exonet_protocol/proc/send_message(var/target_address, var/data_type, var/content) if(!address) - return 0 + return FALSE + var/obj/machinery/exonet_node/node = get_exonet_node() + if(!node) // Telecomms went boom, ion storm, etc. + return FALSE for(var/datum/exonet_protocol/exonet in all_exonet_connections) if(exonet.address == target_address) - exonet.receive_message(holder, address, message, text) - break + node.write_log(src.address, target_address, data_type, content) + return exonet.receive_message(holder, address, data_type, content) // Proc: receive_message() -// Parameters: 4 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, message - the message that was sent, -// text - the message text if message is of type "text") +// Parameters: 4 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, +// data_type - text stating what the content is meant to be used for, content - the actual 'message' being sent from origin_atom) // Description: Called when send_message() successfully reaches the intended datum. By default, calls receive_exonet_message() on the holder atom. -/datum/exonet_protocol/proc/receive_message(var/atom/origin_atom, var/origin_address, var/message, var/text) - holder.receive_exonet_message(origin_atom, origin_address, message, text) - return +/datum/exonet_protocol/proc/receive_message(var/atom/origin_atom, var/origin_address, var/data_type, var/content) + holder.receive_exonet_message(origin_atom, origin_address, data_type, content) + return TRUE // for send_message() // Proc: receive_exonet_message() // Parameters: 3 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, message - the message that was sent) diff --git a/code/datums/underwear/bottom.dm b/code/datums/underwear/bottom.dm index 379bb1aca4..944d373889 100644 --- a/code/datums/underwear/bottom.dm +++ b/code/datums/underwear/bottom.dm @@ -62,4 +62,9 @@ /datum/category_item/underwear/bottom/striped_panties name = "Striped Panties" icon_state = "striped_panties" + has_color = TRUE + +/datum/category_item/underwear/bottom/longjon + name = "Long John Bottoms" + icon_state = "ljonb" has_color = TRUE \ No newline at end of file diff --git a/code/datums/underwear/undershirts.dm b/code/datums/underwear/undershirts.dm index 273c5cba9e..9a4ab9600b 100644 --- a/code/datums/underwear/undershirts.dm +++ b/code/datums/underwear/undershirts.dm @@ -51,6 +51,18 @@ name = "Tank top, fire, feminine" icon_state = "tank_fire_fem_s" +/datum/category_item/underwear/undershirt/tank_top_rainbow + name = "Tank top, rainbow" + icon_state = "tank_rainbow_s" + +/datum/category_item/underwear/undershirt/tank_top_stripes + name = "Tank top, striped" + icon_state = "tank_stripes_s" + +/datum/category_item/underwear/undershirt/tank_top_sun + name = "Tank top, sun" + icon_state = "tank_sun_s" + /datum/category_item/underwear/undershirt/shirt_heart name = "Shirt, heart" icon_state = "lover_s" @@ -125,4 +137,17 @@ /datum/category_item/underwear/undershirt/bowlingw name = "Bowling Shirt, White" - icon_state = "bowlingw" \ No newline at end of file + icon_state = "bowlingw" + +/datum/category_item/underwear/undershirt/longjon + name = "Long John Shirt" + icon_state = "ljont" + has_color = TRUE + +/datum/category_item/underwear/undershirt/longstripe_black + name = "Longsleeve Striped Shirt, Black" + icon_state = "longstripe" + +/datum/category_item/underwear/undershirt/longstripe_blue + name = "Longsleeve Striped Shirt, Blue" + icon_state = "longstripe_blue" \ No newline at end of file diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index 348bf6244d..47b82b82ac 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -47,6 +47,7 @@ var/mob_path = /mob/living/carbon/human // Mobtype this antag will use if none is provided. var/feedback_tag = "traitor_objective" // End of round var/bantype = "Syndicate" // Ban to check when spawning this antag. + var/minimum_player_age = 7 // Players need to be at least minimum_player_age days old before they are eligable for auto-spawning var/suspicion_chance = 50 // Prob of being on the initial Command report var/flags = 0 // Various runtime options. @@ -105,6 +106,8 @@ if(ghosts_only && !istype(player.current, /mob/observer/dead)) candidates -= player log_debug("[key_name(player)] is not eligible to become a [role_text]: Only ghosts may join as this role! They have been removed from the draft.") + else if(config.use_age_restriction_for_antags && player.current.client.player_age < minimum_player_age) + log_debug("[key_name(player)] is not eligible to become a [role_text]: Is only [player.current.client.player_age] day\s old, has to be [minimum_player_age] day\s!") else if(istype(player.current, /mob/living/voice)) candidates -= player log_debug("[key_name(player)] is not eligible to become a [role_text]: They are only a communicator voice. They have been removed from the draft.") diff --git a/code/game/antagonist/station/changeling.dm b/code/game/antagonist/station/changeling.dm index 7ace822b1a..4f60792810 100644 --- a/code/game/antagonist/station/changeling.dm +++ b/code/game/antagonist/station/changeling.dm @@ -56,23 +56,24 @@ return /datum/antagonist/changeling/can_become_antag(var/datum/mind/player, var/ignore_role) - if(..()) - if(player.current) - if(ishuman(player.current)) - var/mob/living/carbon/human/H = player.current - if(H.isSynthetic()) + if(!..()) + return 0 + if(player.current) + if(ishuman(player.current)) + var/mob/living/carbon/human/H = player.current + if(H.isSynthetic()) + return 0 + if(H.species.flags & NO_SCAN) + return 0 + return 1 + else if(isnewplayer(player.current)) + if(player.current.client && player.current.client.prefs) + var/datum/species/S = all_species[player.current.client.prefs.species] + if(S && (S.flags & NO_SCAN)) return 0 - if(H.species.flags & NO_SCAN) + if(player.current.client.prefs.organ_data["torso"] == "cyborg") // Full synthetic. return 0 return 1 - else if(isnewplayer(player.current)) - if(player.current.client && player.current.client.prefs) - var/datum/species/S = all_species[player.current.client.prefs.species] - if(S && (S.flags & NO_SCAN)) - return 0 - if(player.current.client.prefs.organ_data["torso"] == "cyborg") // Full synthetic. - return 0 - return 1 return 0 /datum/antagonist/changeling/print_player_full(var/datum/mind/ply) diff --git a/code/game/gamemodes/game_mode_latespawn.dm b/code/game/gamemodes/game_mode_latespawn.dm index 4fc1bc6f77..ecafc0dbc5 100644 --- a/code/game/gamemodes/game_mode_latespawn.dm +++ b/code/game/gamemodes/game_mode_latespawn.dm @@ -31,6 +31,16 @@ if(emergency_shuttle.departed || !round_autoantag) return + if(emergency_shuttle.shuttle && (emergency_shuttle.shuttle.moving_status == SHUTTLE_WARMUP || emergency_shuttle.shuttle.moving_status == SHUTTLE_INTRANSIT)) + return // Don't do anything if the shuttle's coming. + + var/mills = round_duration_in_ticks + var/mins = round((mills % 36000) / 600) + var/hours = round(mills / 36000) + + if(hours >= 2 && mins >= 40) // Don't do anything in the last twenty minutes of the round, as well. + return + if(world.time < next_spawn) return diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 7205d0e850..393d3aee74 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -5,11 +5,11 @@ /var/list/meteors_normal = list(/obj/effect/meteor/dust=3, /obj/effect/meteor/medium=8, /obj/effect/meteor/big=3, \ /obj/effect/meteor/flaming=1, /obj/effect/meteor/irradiated=3) //for normal meteor event -/var/list/meteors_threatening = list(/obj/effect/meteor/medium=4, /obj/effect/meteor/big=8, \ - /obj/effect/meteor/flaming=3, /obj/effect/meteor/irradiated=3) //for threatening meteor event +/var/list/meteors_threatening = list(/obj/effect/meteor/medium=5, /obj/effect/meteor/big=10, \ + /obj/effect/meteor/flaming=3, /obj/effect/meteor/irradiated=3, /obj/effect/meteor/emp=3) //for threatening meteor event /var/list/meteors_catastrophic = list(/obj/effect/meteor/medium=5, /obj/effect/meteor/big=75, \ - /obj/effect/meteor/flaming=10, /obj/effect/meteor/irradiated=10, /obj/effect/meteor/tunguska = 1) //for catastrophic meteor event + /obj/effect/meteor/flaming=10, /obj/effect/meteor/irradiated=10, /obj/effect/meteor/emp=10, /obj/effect/meteor/tunguska = 1) //for catastrophic meteor event /var/list/meteors_dust = list(/obj/effect/meteor/dust) //for space dust event @@ -38,7 +38,6 @@ var/Me = pickweight(meteortypes) var/obj/effect/meteor/M = new Me(pickedstart) M.dest = pickedgoal - M.z_original = startLevel spawn(0) walk_towards(M, M.dest, 1) return @@ -97,11 +96,16 @@ var/dest pass_flags = PASSTABLE var/heavy = 0 - var/z_original = 1 + var/z_original var/meteordrop = /obj/item/weapon/ore/iron var/dropamt = 2 +/obj/effect/meteor/New() + ..() + z_original = z + + /obj/effect/meteor/Move() if(z != z_original || loc == dest) qdel(src) @@ -151,7 +155,7 @@ hits-- if(hits <= 0) make_debris() - meteor_effect(heavy) + meteor_effect() qdel(src) /obj/effect/meteor/ex_act() @@ -168,8 +172,8 @@ var/obj/item/O = new meteordrop(get_turf(src)) O.throw_at(dest, 5, 10) -/obj/effect/meteor/proc/meteor_effect(var/effect=1) - if(effect) +/obj/effect/meteor/proc/meteor_effect() + if(heavy) for(var/mob/M in player_list) var/turf/T = get_turf(M) if(!T || T.z != src.z) @@ -197,7 +201,7 @@ dropamt = 3 /obj/effect/meteor/medium/meteor_effect() - ..(heavy) + ..() explosion(src.loc, 0, 1, 2, 3, 0) //Large-sized @@ -209,7 +213,7 @@ dropamt = 4 /obj/effect/meteor/big/meteor_effect() - ..(heavy) + ..() explosion(src.loc, 1, 2, 3, 4, 0) //Flaming meteor @@ -221,7 +225,7 @@ meteordrop = /obj/item/weapon/ore/phoron /obj/effect/meteor/flaming/meteor_effect() - ..(heavy) + ..() explosion(src.loc, 1, 2, 3, 4, 0, 0, 5) //Radiation meteor @@ -233,12 +237,25 @@ /obj/effect/meteor/irradiated/meteor_effect() - ..(heavy) + ..() explosion(src.loc, 0, 0, 4, 3, 0) new /obj/effect/decal/cleanable/greenglow(get_turf(src)) for(var/mob/living/L in view(5, src)) L.apply_effect(40, IRRADIATE) +/obj/effect/meteor/emp + name = "conducting meteor" + icon_state = "glowing_blue" + desc = "Hide your floppies!" + meteordrop = /obj/item/weapon/ore/osmium + dropamt = 3 + +/obj/effect/meteor/emp/meteor_effect() + ..() + // Best case scenario: Comparable to a low-yield EMP grenade. + // Worst case scenario: Comparable to a standard yield EMP grenade. + empulse(src, rand(2, 4), rand(4, 10)) + //Station buster Tunguska /obj/effect/meteor/tunguska name = "tunguska meteor" @@ -250,7 +267,7 @@ meteordrop = /obj/item/weapon/ore/phoron /obj/effect/meteor/tunguska/meteor_effect() - ..(heavy) + ..() explosion(src.loc, 5, 10, 15, 20, 0) /obj/effect/meteor/tunguska/Bump() diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 1f0b5f454f..03d3c1170f 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -219,6 +219,25 @@ light_range_on = 2 network = list(NETWORK_THUNDER) circuit = /obj/item/weapon/circuitboard/security/telescreen/entertainment + var/obj/item/device/radio/radio = null + +/obj/machinery/computer/security/telescreen/entertainment/initialize() + ..() + radio = new(src) + radio.listening = TRUE + radio.broadcasting = FALSE + radio.set_frequency(ENT_FREQ) + radio.canhear_range = 7 // Same as default sight range. + power_change() + +/obj/machinery/computer/security/telescreen/entertainment/power_change() + ..() + if(radio) + if(stat & NOPOWER) + radio.on = FALSE + else + radio.on = TRUE + /obj/machinery/computer/security/wooden_tv name = "security camera monitor" desc = "An old TV hooked into the stations camera network." @@ -228,6 +247,7 @@ circuit = null light_color = "#3848B3" light_power_on = 0.5 + /obj/machinery/computer/security/mining name = "outpost camera monitor" desc = "Used to access the various cameras on the outpost." @@ -236,6 +256,7 @@ network = list("MINE") circuit = /obj/item/weapon/circuitboard/security/mining light_color = "#F9BBFC" + /obj/machinery/computer/security/engineering name = "engineering camera monitor" desc = "Used to monitor fires and breaches." @@ -243,16 +264,19 @@ icon_screen = "engie_cams" circuit = /obj/item/weapon/circuitboard/security/engineering light_color = "#FAC54B" + /obj/machinery/computer/security/engineering/New() if(!network) network = engineering_networks.Copy() ..() + /obj/machinery/computer/security/nuclear name = "head mounted camera monitor" desc = "Used to access the built-in cameras in helmets." icon_state = "syndicam" network = list(NETWORK_MERCENARY) circuit = null + /obj/machinery/computer/security/nuclear/New() ..() req_access = list(150) \ No newline at end of file diff --git a/code/game/machinery/exonet_node.dm b/code/game/machinery/exonet_node.dm index aa36e34c9e..d871a3ec38 100644 --- a/code/game/machinery/exonet_node.dm +++ b/code/game/machinery/exonet_node.dm @@ -15,6 +15,8 @@ var/opened = 0 + var/list/logs = list() // Gets written to by exonet's send_message() function. + // Proc: New() // Parameters: None // Description: Adds components to the machine for deconstruction. @@ -60,6 +62,7 @@ else on = 0 idle_power_usage = 0 + update_icon() // Proc: emp_act() // Parameters: 1 (severity - how strong the EMP is, with lower numbers being stronger) @@ -114,6 +117,7 @@ data["allowPDAs"] = allow_external_PDAs data["allowCommunicators"] = allow_external_communicators data["allowNewscasters"] = allow_external_newscasters + data["logs"] = logs // update the ui if it exists, returns null if no ui is passed/found @@ -171,3 +175,14 @@ for(var/obj/machinery/exonet_node/E in machines) if(E.on) return E + +// Proc: write_log() +// Parameters: 4 (origin_address - Where the message is from, target_address - Where the message is going, data_type - Instructions on how to interpet content, +// content - The actual message. +// Description: This writes to the logs list, so that people can see what people are doing on the Exonet ingame. Note that this is not an admin logging function. +// Communicators are already logged seperately. +/obj/machinery/exonet_node/proc/write_log(var/origin_address, var/target_address, var/data_type, var/content) + //var/timestamp = time2text(station_time_in_ticks, "hh:mm:ss") + var/timestamp = "[stationdate2text()] [stationtime2text()]" + var/msg = "[timestamp] | FROM [origin_address] TO [target_address] | TYPE: [data_type] | CONTENT: [content]" + logs.Add(msg) diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm index 4a6aded43b..93d6743b8e 100644 --- a/code/game/machinery/telecomms/presets.dm +++ b/code/game/machinery/telecomms/presets.dm @@ -56,7 +56,7 @@ id = "Receiver A" network = "tcommsat" autolinkers = list("receiverA") // link to relay - freq_listening = list(AI_FREQ, SCI_FREQ, MED_FREQ, SUP_FREQ, SRV_FREQ, COMM_FREQ, ENG_FREQ, SEC_FREQ) + freq_listening = list(AI_FREQ, SCI_FREQ, MED_FREQ, SUP_FREQ, SRV_FREQ, COMM_FREQ, ENG_FREQ, SEC_FREQ, ENT_FREQ) //Common and other radio frequencies for people to freely use New() @@ -102,7 +102,7 @@ /obj/machinery/telecomms/bus/preset_four id = "Bus 4" network = "tcommsat" - freq_listening = list(ENG_FREQ, AI_FREQ, PUB_FREQ) + freq_listening = list(ENG_FREQ, AI_FREQ, PUB_FREQ, ENT_FREQ) autolinkers = list("processor4", "engineering", "common") /obj/machinery/telecomms/bus/preset_cent @@ -168,7 +168,7 @@ /obj/machinery/telecomms/server/presets/common id = "Common Server" - freq_listening = list(PUB_FREQ, AI_FREQ) // AI Private and Common + freq_listening = list(PUB_FREQ, AI_FREQ, ENT_FREQ) // AI Private and Common autolinkers = list("common") // "Unused" channels, AKA all others. diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 40e05b695c..0559b626e1 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -206,37 +206,16 @@ R.activate_module(src) R.hud_used.update_robot_modules_display() -// Due to storage type consolidation this should get used more now. -// I have cleaned it up a little, but it could probably use more. -Sayu /obj/item/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W,/obj/item/weapon/storage)) + if(istype(W, /obj/item/weapon/storage)) var/obj/item/weapon/storage/S = W if(S.use_to_pickup) - if(S.collection_mode) //Mode is set to collect all items on a tile and we clicked on a valid one. + if(S.collection_mode) //Mode is set to collect all items if(isturf(src.loc)) - var/list/rejections = list() - var/success = 0 - var/failure = 0 - - for(var/obj/item/I in src.loc) - if(I.type in rejections) // To limit bag spamming: any given type only complains once - continue - if(!S.can_be_inserted(I)) // Note can_be_inserted still makes noise when the answer is no - rejections += I.type // therefore full bags are still a little spammy - failure = 1 - continue - success = 1 - S.handle_item_insertion(I, 1) //The 1 stops the "You put the [src] into [S]" insertion message from being displayed. - if(success && !failure) - user << "You put everything in [S]." - else if(success) - user << "You put some things in [S]." - else - user << "You fail to pick anything up with \the [S]." + S.gather_all(src.loc, user) else if(S.can_be_inserted(src)) S.handle_item_insertion(src) - return /obj/item/proc/talk_into(mob/M as mob, text) @@ -461,12 +440,13 @@ var/list/global/slot_flags_enumeration = list( user << "You cannot locate any eyes on [M]!" return - var/hit_zone = get_zone_with_miss_chance(U.zone_sel.selecting, M, U.get_accuracy_penalty(U)) - if(!hit_zone) - U.do_attack_animation(M) - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("\red [U] attempts to stab [M] in the eyes, but misses!") - return + if(U.get_accuracy_penalty(U)) //Should only trigger if they're not aiming well + var/hit_zone = get_zone_with_miss_chance(U.zone_sel.selecting, M, U.get_accuracy_penalty(U)) + if(!hit_zone) + U.do_attack_animation(M) + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("\red [U] attempts to stab [M] in the eyes, but misses!") + return user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)])" diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 8562ac7f28..b553f4416c 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -13,6 +13,8 @@ var/times_used = 0 //Number of times it's been used. var/broken = 0 //Is the flash burnt out? var/last_used = 0 //last world.time it was used. + var/max_flashes = 10 // How many times the flash can be used before needing to self recharge. + var/halloss_per_flash = 30 /obj/item/device/flash/proc/clown_check(var/mob/user) if(user && (CLUMSY in user.mutations) && prob(50)) @@ -22,15 +24,36 @@ return 1 /obj/item/device/flash/proc/flash_recharge() - //capacitor recharges over time - for(var/i=0, i<3, i++) - if(last_used+600 > world.time) + //Every ten seconds the flash doesn't get used, the times_used variable goes down by one, making the flash less likely to burn out, + // as well as being able to flash more before reaching max_flashes cap. + for(var/i=0, i < max_flashes, i++) + if(last_used + 10 SECONDS > world.time) break - last_used += 600 - times_used -= 2 + last_used += 10 SECONDS + times_used-- last_used = world.time times_used = max(0,round(times_used)) //sanity +// Returns true if the device can flash. +/obj/item/device/flash/proc/check_capacitor(var/mob/user) + //spamming the flash before it's fully charged (60 seconds) increases the chance of it breaking + //It will never break on the first use. + if(times_used <= max_flashes) + last_used = world.time + if(prob( round(times_used / 2) )) //if you use it 10 times in a minute it has a 5% chance to break. + broken = 1 + if(user) + user << "The bulb has burnt out!" + icon_state = "flashburnt" + return FALSE + else + times_used++ + return TRUE + else //can only use it 10 times a minute + if(user) + user << "*click* *click*" + return FALSE + //attack_as_weapon /obj/item/device/flash/attack(mob/living/M, mob/living/user, var/target_zone) if(!user || !M) return //sanity @@ -49,20 +72,8 @@ flash_recharge() - //spamming the flash before it's fully charged (60seconds) increases the chance of it breaking - //It will never break on the first use. - switch(times_used) - if(0 to 5) - last_used = world.time - if(prob(times_used)) //if you use it 5 times in a minute it has a 10% chance to break! - broken = 1 - user << "The bulb has burnt out!" - icon_state = "flashburnt" - return - times_used++ - else //can only use it 5 times a minute - user << "*click* *click*" - return + if(!check_capacitor(user)) + return user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) user.do_attack_animation(M) @@ -71,12 +82,13 @@ var/flashfail = 0 if(iscarbon(M)) - if(M.stat!=DEAD) - var/safety = M:eyecheck() + var/mob/living/carbon/C = M + if(C.stat != DEAD) + var/safety = C.eyecheck() if(safety <= 0) var/flash_strength = 5 - if(ishuman(M)) - var/mob/living/carbon/human/H = M + if(ishuman(C)) + var/mob/living/carbon/human/H = C flash_strength *= H.species.flash_mod if(flash_strength > 0) @@ -84,6 +96,7 @@ H.eye_blind = max(H.eye_blind, flash_strength) H.eye_blurry = max(H.eye_blurry, flash_strength + 5) H.flash_eyes() + H.adjustHalLoss(halloss_per_flash * (flash_strength / 5)) // Should take four flashes to stun. else flashfail = 1 @@ -132,19 +145,9 @@ flash_recharge() - //spamming the flash before it's fully charged (60seconds) increases the chance of it breaking - //It will never break on the first use. - switch(times_used) - if(0 to 5) - if(prob(2*times_used)) //if you use it 5 times in a minute it has a 10% chance to break! - broken = 1 - user << "The bulb has burnt out!" - icon_state = "flashburnt" - return - times_used++ - else //can only use it 5 times a minute - user.show_message("*click* *click*", 2) - return + if(!check_capacitor(user)) + return + playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1) flick("flash2", src) if(user && isrobot(user)) @@ -158,32 +161,29 @@ sleep(5) qdel(animation) - for(var/mob/living/carbon/M in oviewers(3, null)) - var/safety = M:eyecheck() + for(var/mob/living/carbon/C in oviewers(3, null)) + var/safety = C.eyecheck() if(!safety) - if(!M.blinded) - M.flash_eyes() + if(!C.blinded) + C.flash_eyes() return /obj/item/device/flash/emp_act(severity) if(broken) return flash_recharge() - switch(times_used) - if(0 to 5) - if(prob(2*times_used)) - broken = 1 - icon_state = "flashburnt" - return - times_used++ - if(istype(loc, /mob/living/carbon)) - var/mob/living/carbon/M = loc - var/safety = M.eyecheck() - if(safety <= 0) - M.Weaken(10) - M.flash_eyes() - for(var/mob/O in viewers(M, null)) - O.show_message("[M] is blinded by the flash!") + if(!check_capacitor()) + return + + if(istype(loc, /mob/living/carbon)) + var/mob/living/carbon/C = loc + var/safety = C.eyecheck() + if(safety <= 0) + C.adjustHalLoss(halloss_per_flash) + //C.Weaken(10) + C.flash_eyes() + for(var/mob/M in viewers(C, null)) + M.show_message("[C] is blinded by the flash!") ..() /obj/item/device/flash/synthetic diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index 72d4c50685..216e2e59d0 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -43,6 +43,10 @@ icon_state = "medintercom" frequency = SEC_I_FREQ +/obj/item/device/radio/intercom/entertainment + name = "entertainment intercom" + frequency = ENT_FREQ + /obj/item/device/radio/intercom/New() ..() processing_objects += src @@ -59,6 +63,13 @@ num2text(SEC_I_FREQ) = list(access_security) ) +/obj/item/device/radio/intercom/entertainment/New() + ..() + internal_channels = list( + num2text(PUB_FREQ) = list(), + num2text(ENT_FREQ) = list() + ) + /obj/item/device/radio/intercom/syndicate name = "illicit intercom" desc = "Talk through this. Evilly" diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index c173e0344e..cec23e818f 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -2,6 +2,7 @@ var/global/list/default_internal_channels = list( num2text(PUB_FREQ) = list(), num2text(AI_FREQ) = list(access_synth), + num2text(ENT_FREQ) = list(), num2text(ERT_FREQ) = list(access_cent_specops), num2text(COMM_FREQ)= list(access_heads), num2text(ENG_FREQ) = list(access_engine_equip, access_atmospherics), diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index f9d414267f..56311a52df 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -81,12 +81,14 @@ REAGENT SCANNER user.show_message("Localized Damage, Brute/Burn:",1) if(length(damaged)>0) for(var/obj/item/organ/external/org in damaged) - user.show_message(text(" [][]: [][] - []", - capitalize(org.name), - (org.robotic >= ORGAN_ROBOT) ? "(Cybernetic)" : "", - (org.brute_dam > 0) ? "[org.brute_dam]" : 0, - (org.status & ORGAN_BLEEDING)?"\[Bleeding\]":"", - (org.burn_dam > 0) ? "[org.burn_dam]" : 0),1) + if(org.robotic >= ORGAN_ROBOT) + continue + else + user.show_message(text(" []: [][] - []", + capitalize(org.name), + (org.brute_dam > 0) ? "[org.brute_dam]" : 0, + (org.status & ORGAN_BLEEDING)?"\[Bleeding\]":"", + (org.burn_dam > 0) ? "[org.burn_dam]" : 0),1) else user.show_message(" Limbs are OK.",1) diff --git a/code/game/objects/items/devices/tvcamera.dm b/code/game/objects/items/devices/tvcamera.dm new file mode 100644 index 0000000000..b449a6ce3b --- /dev/null +++ b/code/game/objects/items/devices/tvcamera.dm @@ -0,0 +1,95 @@ +/obj/item/device/tvcamera + name = "press camera drone" + desc = "A Ward-Takahashi EyeBuddy media streaming hovercam. Weapon of choice for war correspondents and reality show cameramen." + icon_state = "camcorder" + item_state = "camcorder" + w_class = ITEMSIZE_LARGE + slot_flags = SLOT_BELT + var/channel = "NCS Northern Star News Feed" + var/obj/machinery/camera/network/thunder/camera + var/obj/item/device/radio/radio + +/obj/item/device/tvcamera/New() + ..() + listening_objects += src + +/obj/item/device/tvcamera/Destroy() + listening_objects -= src + qdel(camera) + qdel(radio) + camera = null + radio = null + ..() + +/obj/item/device/tvcamera/examine() + ..() + to_chat(usr, "Video feed is [camera.status ? "on" : "off"]") + to_chat(usr, "Audio feed is [radio.broadcasting ? "on" : "off"]") + +/obj/item/device/tvcamera/initialize() + ..() + camera = new(src) + camera.c_tag = channel + camera.status = FALSE + radio = new(src) + radio.listening = FALSE + radio.set_frequency(ENT_FREQ) + radio.icon = src.icon + radio.icon_state = src.icon_state + update_icon() + +/obj/item/device/tvcamera/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null) + radio.hear_talk(M,msg,verb,speaking) + ..() + +/obj/item/device/tvcamera/attack_self(mob/user) + add_fingerprint(user) + user.set_machine(src) + var/dat = list() + dat += "Channel name is: [channel ? channel : "unidentified broadcast"]
" + dat += "Video streaming is [camera.status ? "on" : "off"]
" + dat += "Mic is [radio.broadcasting ? "on" : "off"]
" + dat += "Sound is being broadcasted on frequency [format_frequency(radio.frequency)] ([get_frequency_name(radio.frequency)])
" + var/datum/browser/popup = new(user, "Hovercamera", "Eye Buddy", 300, 390, src) + popup.set_content(jointext(dat,null)) + popup.open() + +/obj/item/device/tvcamera/Topic(bred, href_list, state = physical_state) + if(..()) + return 1 + if(href_list["channel"]) + var/nc = input(usr, "Channel name", "Select new channel name", channel) as text|null + if(nc) + channel = nc + camera.c_tag = channel + to_chat(usr, "New channel name - '[channel]' is set") + if(href_list["video"]) + camera.set_status(!camera.status) + if(camera.status) + to_chat(usr,"Video streaming activated. Broadcasting on channel '[channel]'") + else + to_chat(usr,"Video streaming deactivated.") + update_icon() + if(href_list["sound"]) + radio.ToggleBroadcast() + if(radio.broadcasting) + to_chat(usr,"Audio streaming activated. Broadcasting on frequency [format_frequency(radio.frequency)].") + else + to_chat(usr,"Audio streaming deactivated.") + if(!href_list["close"]) + attack_self(usr) + +/obj/item/device/tvcamera/update_icon() + ..() + if(camera.status) + icon_state = "camcorder_on" + item_state = "camcorder_on" + else + icon_state = "camcorder" + item_state = "camcorder" + var/mob/living/carbon/human/H = loc + if(istype(H)) + H.update_inv_r_hand() + H.update_inv_l_hand() + H.update_inv_belt() + diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 17d3e32f92..eec5638523 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -54,6 +54,18 @@ part.implants.Remove(src) ..() +/obj/item/weapon/implant/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/implanter)) + var/obj/item/weapon/implanter/implanter = I + if(implanter.imp) + return // It's full. + user.drop_from_inventory(src) + forceMove(implanter) + implanter.imp = src + implanter.update() + else + ..() + /obj/item/weapon/implant/tracking name = "tracking implant" desc = "Track with this." diff --git a/code/game/objects/items/weapons/implants/implantcircuits.dm b/code/game/objects/items/weapons/implants/implantcircuits.dm new file mode 100644 index 0000000000..cf55cbd706 --- /dev/null +++ b/code/game/objects/items/weapons/implants/implantcircuits.dm @@ -0,0 +1,44 @@ +/obj/item/weapon/implant/integrated_circuit + name = "electronic implant" + icon = 'icons/obj/electronic_assemblies.dmi' + icon_state = "setup_implant" + var/obj/item/device/electronic_assembly/implant/IC = null + +/obj/item/weapon/implant/integrated_circuit/islegal() + return TRUE + +/obj/item/weapon/implant/integrated_circuit/New() + ..() + IC = new(src) + IC.implant = src + +/obj/item/weapon/implant/integrated_circuit/Destroy() + IC.implant = null + qdel(IC) + ..() + +/obj/item/weapon/implant/integrated_circuit/get_data() + var/dat = {" + Implant Specifications:
+ Name: Modular Implant
+ Life: 3 years.
+ Important Notes: EMP can cause malfunctions in the internal electronics of this implant.
+
+ Implant Details:
+ Function: Contains no innate functions until other components are added.
+ Special Features: + Modular Circuitry- Can be loaded with specific modular circuitry in order to fulfill a wide possibility of functions.
+ Integrity: Implant is not shielded from electromagnetic interferance, otherwise it is independant of subject's status."} + return dat + +/obj/item/weapon/implant/integrated_circuit/emp_act(severity) + IC.emp_act(severity) + +/obj/item/weapon/implant/integrated_circuit/examine(mob/user) + IC.examine(user) + +/obj/item/weapon/implant/integrated_circuit/attackby(var/obj/item/O, var/mob/user) + if(istype(O, /obj/item/weapon/crowbar) || istype(O, /obj/item/device/integrated_electronics) || istype(O, /obj/item/integrated_circuit) || istype(O, /obj/item/weapon/screwdriver) ) + IC.attackby(O, user) + else + ..() \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index e691ed2795..8c1c47713a 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -478,6 +478,27 @@ src.add_fingerprint(user) return +/obj/item/weapon/storage/proc/gather_all(turf/T as turf, mob/user as mob) + var/list/rejections = list() + var/success = 0 + var/failure = 0 + + for(var/obj/item/I in T) + if(I.type in rejections) // To limit bag spamming: any given type only complains once + continue + if(!can_be_inserted(I, user)) // Note can_be_inserted still makes noise when the answer is no + rejections += I.type // therefore full bags are still a little spammy + failure = 1 + continue + success = 1 + handle_item_insertion(I, 1) //The 1 stops the "You put the [src] into [S]" insertion message from being displayed. + if(success && !failure) + to_chat(user, "You put everything in [src].") + else if(success) + to_chat(user, "You put some things in [src].") + else + to_chat(user, "You fail to pick anything up with \the [src].") + /obj/item/weapon/storage/verb/toggle_gathering_mode() set name = "Switch Gathering Method" set category = "Object" diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index 588517a7ed..0d8a94944d 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -78,6 +78,9 @@ else user << "[src] can't hold any more signs." + else if(istype(I, /obj/item/weapon/reagent_containers/glass)) + return // So we do not put them in the trash bag as we mean to fill the mop bucket + else if(mybag) mybag.attackby(I, user) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index e3cdd8328a..ecc8c49c4b 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -68,6 +68,13 @@ step(user.pulling, get_dir(user.pulling.loc, src)) return 1 +turf/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/storage)) + var/obj/item/weapon/storage/S = W + if(S.use_to_pickup && S.collection_mode) + S.gather_all(src, user) + return ..() + /turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area) if(movement_disabled && usr.ckey != movement_disabled_exception) usr << "Movement is admin-disabled." //This is to identify lag problems diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index 2a0f3b6607..793df9dc43 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -37,6 +37,8 @@ log_ooc("[mob.name]/[key] : [msg]") + handle_spam_prevention(MUTE_OOC) + var/ooc_style = "everyone" if(holder && !holder.fakekey) ooc_style = "elevated" @@ -105,6 +107,8 @@ log_ooc("(LOCAL) [mob.name]/[key] : [msg]") + handle_spam_prevention(MUTE_OOC) + var/mob/source = mob.get_looc_source() var/turf/T = get_turf(source) if(!T) return @@ -137,7 +141,7 @@ // Send a message for(var/client/target in receivers) var/admin_stuff = "" - + if(target in admins) admin_stuff += "/([key])" @@ -145,7 +149,7 @@ for(var/client/target in r_receivers) var/admin_stuff = "/([key])([admin_jump_link(mob, target.holder)])" - + target << "" + create_text_tag("looc", "LOOC:", target) + " (R)[display_name][admin_stuff]: [msg]" /mob/proc/get_looc_source() diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 0c059517d3..91a504f421 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -160,7 +160,8 @@ var/list/admin_verbs_server = list( /datum/admins/proc/toggle_space_ninja, /client/proc/toggle_random_events, /client/proc/check_customitem_activity, - /client/proc/nanomapgen_DumpImage + /client/proc/nanomapgen_DumpImage, + /client/proc/modify_server_news ) var/list/admin_verbs_debug = list( /client/proc/getruntimelog, //allows us to access runtime logs to somebody, diff --git a/code/modules/admin/news.dm b/code/modules/admin/news.dm new file mode 100644 index 0000000000..b9e1b616b4 --- /dev/null +++ b/code/modules/admin/news.dm @@ -0,0 +1,42 @@ +#define NEWSFILE "data/news.sav" //where the memos are saved + +/client/ + //var/last_news_hash = null // Stores a hash of the last news window it saw, which gets compared to the current one to see if it is different. + +// Returns true if news was updated since last seen. +/client/proc/check_for_new_server_news() + var/savefile/F = get_server_news() + if(F) + if(md5(F["body"]) != prefs.lastnews) + return TRUE + return FALSE + +/client/proc/modify_server_news() + set name = "Modify Public News" + set category = "Server" + + if(!check_rights(0)) + return + + var/savefile/F = new(NEWSFILE) + if(F) + var/title = F["title"] + var/body = F["body"] + var/new_title = sanitize(input(src,"Write a good title for the news update. Note: HTML is NOT supported.","Write News", title) as null|text, extra = 0) + if(!new_title) + return + var/new_body = sanitize(input(src,"Write the body of the news update here. Note: HTML is NOT supported.","Write News", body) as null|message, extra = 0) + if(findtext(new_body,"[new_title]
[new_body]") + +/proc/get_server_news() + var/savefile/F = new(NEWSFILE) + if(F) + return F + +#undef NEWSFILE \ No newline at end of file diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 8f8532590e..90d9c9d275 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -17,6 +17,8 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," adminhelped = 1 //Determines if they get the message to reply by clicking the name. + handle_spam_prevention(MUTE_ADMINHELP) + //clean the input msg if(!msg) return diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index 1307086a87..64640b10b6 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -10,6 +10,7 @@ if(!msg) return if(usr.client) + client.handle_spam_prevention(MUTE_PRAY) if(usr.client.prefs.muted & MUTE_PRAY) usr << "\red You cannot pray (muted)." return diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 662b945b33..251dec5fb1 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -158,7 +158,8 @@ proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0) if(automute) - if(!config.automute_on) return + if(!config.automute_on) + return else if(!usr || !usr.client) return @@ -169,8 +170,10 @@ proc/cmd_admin_mute(mob/M as mob, mute_type, automute = 0) usr << "Error: cmd_admin_mute: This mob doesn't have a client tied to it." if(M.client.holder) usr << "Error: cmd_admin_mute: You cannot mute an admin/mod." - if(!M.client) return - if(M.client.holder) return + if(!M.client) + return + if(M.client.holder) + return var/muteunmute var/mute_string diff --git a/code/modules/client/preference_setup/global/02_settings.dm b/code/modules/client/preference_setup/global/02_settings.dm index c7635cbb91..f213c15a8a 100644 --- a/code/modules/client/preference_setup/global/02_settings.dm +++ b/code/modules/client/preference_setup/global/02_settings.dm @@ -8,12 +8,14 @@ /datum/category_item/player_setup_item/player_global/settings/load_preferences(var/savefile/S) S["lastchangelog"] >> pref.lastchangelog + S["lastnews"] >> pref.lastnews S["default_slot"] >> pref.default_slot S["preferences"] >> pref.preferences_enabled S["preferences_disabled"] >> pref.preferences_disabled /datum/category_item/player_setup_item/player_global/settings/save_preferences(var/savefile/S) S["lastchangelog"] << pref.lastchangelog + S["lastnews"] << pref.lastnews S["default_slot"] << pref.default_slot S["preferences"] << pref.preferences_enabled S["preferences_disabled"] << pref.preferences_disabled @@ -47,6 +49,7 @@ pref.preferences_disabled -= key pref.lastchangelog = sanitize_text(pref.lastchangelog, initial(pref.lastchangelog)) + pref.lastnews = sanitize_text(pref.lastnews, initial(pref.lastnews)) pref.default_slot = sanitize_integer(pref.default_slot, 1, config.character_slots, initial(pref.default_slot)) /datum/category_item/player_setup_item/player_global/settings/content(var/mob/user) diff --git a/code/modules/client/preference_setup/loadout/loadout_uniform.dm b/code/modules/client/preference_setup/loadout/loadout_uniform.dm index f951450134..518b11a521 100644 --- a/code/modules/client/preference_setup/loadout/loadout_uniform.dm +++ b/code/modules/client/preference_setup/loadout/loadout_uniform.dm @@ -387,7 +387,7 @@ path = /obj/item/clothing/under/pt /datum/gear/uniform/pt/expeditionary - display_name = "pt uniform, expeditionary" + display_name = "pt uniform, sifguard" path = /obj/item/clothing/under/pt/expeditionary /datum/gear/uniform/pt/fleet diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index db12940bd9..4b04dd0046 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -114,6 +114,8 @@ datum/preferences var/datum/category_collection/player_setup_collection/player_setup var/datum/browser/panel + var/lastnews // Hash of last seen lobby news content. + /datum/preferences/New(client/C) player_setup = new(src) set_biological_gender(pick(MALE, FEMALE)) @@ -262,7 +264,7 @@ datum/preferences if(be_random_name) real_name = random_name(identifying_gender,species) - // Ask the preferences datums to apply their own settings to the new mob + // Ask the preferences datums to apply their own settings to the new mob player_setup.copy_to_mob(character) if(icon_updates) diff --git a/code/modules/client/spam_prevention.dm b/code/modules/client/spam_prevention.dm new file mode 100644 index 0000000000..6802e1d695 --- /dev/null +++ b/code/modules/client/spam_prevention.dm @@ -0,0 +1,13 @@ +// Based on Aurora's anti-spam system. +/client/ + var/last_message_time = 0 + var/spam_alert = 0 + +/client/proc/handle_spam_prevention(var/mute_type = MUTE_ALL, var/spam_delay = 0.5 SECONDS) + if(world.time - last_message_time < spam_delay) + spam_alert++ + if(spam_alert > 3) + cmd_admin_mute(src.mob, mute_type, 1) + else + spam_alert = max(0, spam_alert--) + last_message_time = world.time \ No newline at end of file diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index df3b7944a3..39f437f93a 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -408,6 +408,7 @@ if(usr.put_in_hands(holding)) usr.visible_message("\The [usr] pulls a knife out of their boot!") + playsound(src.loc, 'sound/weapons/flipblade.ogg', 40, 1) holding = null else usr << "Your need an empty, unbroken hand to do that." @@ -419,6 +420,11 @@ update_icon() return +/obj/item/clothing/shoes/attack_hand(var/mob/living/M) + if(can_hold_knife == 1 && holding && src.loc == M) + draw_knife() + return + ..() /obj/item/clothing/shoes/attackby(var/obj/item/I, var/mob/user) if((can_hold_knife == 1) && (istype(I, /obj/item/weapon/material/shard) || \ diff --git a/code/modules/clothing/head/solgov.dm b/code/modules/clothing/head/solgov.dm index 9ed37a4eda..f7d4c417b4 100644 --- a/code/modules/clothing/head/solgov.dm +++ b/code/modules/clothing/head/solgov.dm @@ -11,8 +11,8 @@ ) /obj/item/clothing/head/soft/sol/expedition - name = "\improper Expeditionary Corps cap" - desc = "It's a black ballcap bearing a Expeditonary Corps crest." + name = "\improper SifGuard cap" + desc = "It's a black ballcap bearing a Sif Homeguard Corps crest." icon_state = "expeditionsoft" item_state_slots = list( slot_l_hand_str = "blacksoft", @@ -114,13 +114,13 @@ body_parts_covered = 0 /obj/item/clothing/head/dress/expedition - name = "expedition dress cap" - desc = "A peaked grey dress uniform cap belonging to the SCG Expeditionary Corps." + name = "\improper SifGuard dress cap" + desc = "A peaked grey dress uniform cap belonging to the Sif Homeguard Corps." icon_state = "greydresscap" /obj/item/clothing/head/dress/expedition/command - name = "expedition command dress cap" - desc = "A peaked grey dress uniform cap belonging to the SCG Expeditionary Corps. This one is trimmed in gold." + name = "\improper SifGuard command dress cap" + desc = "A peaked grey dress uniform cap belonging to the Sif Homeguard Corps. This one is trimmed in gold." icon_state = "greydresscap_com" /obj/item/clothing/head/dress/fleet @@ -181,33 +181,33 @@ icon_state = "beret_white" /obj/item/clothing/head/beret/sol/expedition - name = "expeditionary beret" - desc = "A black beret belonging to the SCG Expeditionary Corps. For personnel that are more inclined towards style than safety." + name = "\improper SifGuard beret" + desc = "A black beret belonging to the Sif Homeguard Corps. For personnel that are more inclined towards style than safety." icon_state = "beret_black" /obj/item/clothing/head/beret/sol/expedition/security - name = "expeditionary security beret" - desc = "An SCG Expeditionary Corps beret with a security crest. For personnel that are more inclined towards style than safety." + name = "\improper SifGuard security beret" + desc = "An Sif Homeguard Corps beret with a security crest. For personnel that are more inclined towards style than safety." icon_state = "beret_black_security" /obj/item/clothing/head/beret/sol/expedition/medical - name = "expeditionary medical beret" - desc = "An SCG Expeditionary Corps beret with a medical crest. For personnel that are more inclined towards style than safety." + name = "\improper SifGuard medical beret" + desc = "An Sif Homeguard Corps beret with a medical crest. For personnel that are more inclined towards style than safety." icon_state = "beret_black_medical" /obj/item/clothing/head/beret/sol/expedition/engineering - name = "expeditionary engineering beret" - desc = "An SCG Expeditionary Corps beret with an engineering crest. For personnel that are more inclined towards style than safety." + name = "\improper SifGuard engineering beret" + desc = "An Sif Homeguard Corps beret with an engineering crest. For personnel that are more inclined towards style than safety." icon_state = "beret_black_engineering" /obj/item/clothing/head/beret/sol/expedition/supply - name = "expeditionary supply beret" - desc = "An SCG Expeditionary Corps beret with a supply crest. For personnel that are more inclined towards style than safety." + name = "\improper SifGuard supply beret" + desc = "An Sif Homeguard Corps beret with a supply crest. For personnel that are more inclined towards style than safety." icon_state = "beret_black_supply" /obj/item/clothing/head/beret/sol/expedition/command - name = "expeditionary command beret" - desc = "An SCG Expeditionary Corps beret with a command crest. For personnel that are more inclined towards style than safety." + name = "\improper SifGuard command beret" + desc = "An Sif Homeguard Corps beret with a command crest. For personnel that are more inclined towards style than safety." icon_state = "beret_black_command" /obj/item/clothing/head/beret/sol/fleet diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 4d1cfe6088..755c657bac 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -27,36 +27,7 @@ armor = list(melee = 80, bullet = 60, laser = 50,energy = 25, bomb = 50, bio = 10, rad = 0) item_flags = NOSLIP siemens_coefficient = 0.6 - var/obj/item/weapon/material/hatchet/tacknife - -/obj/item/clothing/shoes/swat/attack_hand(var/mob/living/M) - if(tacknife) - tacknife.loc = get_turf(src) - if(M.put_in_active_hand(tacknife)) - M << "You slide \the [tacknife] out of [src]." - playsound(M, 'sound/weapons/flipblade.ogg', 40, 1) - tacknife = null - update_icon() - return - ..() - -/obj/item/clothing/shoes/swat/attackby(var/obj/item/I, var/mob/living/M) - if(istype(I, /obj/item/weapon/material/hatchet/tacknife)) - if(tacknife) - return - M.drop_item() - tacknife = I - I.loc = src - M << "You slide the [I] into [src]." - playsound(M, 'sound/weapons/flipblade.ogg', 40, 1) - update_icon() - ..() - -/obj/item/clothing/shoes/swat/update_icon() - if(tacknife) - icon_state = "swat_1" - else - icon_state = initial(icon_state) + can_hold_knife = 1 //Stolen from CM, refurbished to be less terrible. /obj/item/clothing/shoes/marine @@ -66,36 +37,7 @@ item_state_slots = list(slot_r_hand_str = "jackboots", slot_l_hand_str = "jackboots") armor = list(melee = 80, bullet = 60, laser = 50,energy = 25, bomb = 50, bio = 10, rad = 0) siemens_coefficient = 0.6 - var/obj/item/weapon/material/hatchet/tacknife - -/obj/item/clothing/shoes/marine/attack_hand(var/mob/living/M) - if(tacknife) - tacknife.loc = get_turf(src) - if(M.put_in_active_hand(tacknife)) - M << "You slide \the [tacknife] out of [src]." - playsound(M, 'sound/weapons/flipblade.ogg', 40, 1) - tacknife = null - update_icon() - return - ..() - -/obj/item/clothing/shoes/marine/attackby(var/obj/item/I, var/mob/living/M) - if(istype(I, /obj/item/weapon/material/hatchet/tacknife)) - if(tacknife) - return - M.drop_item() - tacknife = I - I.loc = src - M << "You slide the [I] into [src]." - playsound(M, 'sound/weapons/flipblade.ogg', 40, 1) - update_icon() - ..() - -/obj/item/clothing/shoes/marine/update_icon() - if(tacknife) - icon_state = "jackboots_1" - else - icon_state = initial(icon_state) + can_hold_knife = 1 /obj/item/clothing/shoes/combat //Basically SWAT shoes combined with galoshes. name = "combat boots" @@ -105,6 +47,7 @@ armor = list(melee = 80, bullet = 60, laser = 50,energy = 25, bomb = 50, bio = 10, rad = 0) item_flags = NOSLIP siemens_coefficient = 0.6 + can_hold_knife = 1 cold_protection = FEET min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE @@ -118,6 +61,7 @@ force = 3 armor = list(melee = 30, bullet = 10, laser = 10, energy = 15, bomb = 20, bio = 10, rad = 0) siemens_coefficient = 0.7 + can_hold_knife = 1 /obj/item/clothing/shoes/dutyboots name = "duty boots" @@ -125,6 +69,7 @@ icon_state = "duty" armor = list(melee = 40, bullet = 0, laser = 0, energy = 15, bomb = 20, bio = 0, rad = 20) siemens_coefficient = 0.7 + can_hold_knife = 1 /obj/item/clothing/shoes/tactical name = "tactical boots" @@ -133,6 +78,7 @@ force = 3 armor = list(melee = 40, bullet = 30, laser = 40,energy = 25, bomb = 50, bio = 0, rad = 0) siemens_coefficient = 0.7 + can_hold_knife = 1 /obj/item/clothing/shoes/dress name = "dress shoes" diff --git a/code/modules/clothing/suits/solgov.dm b/code/modules/clothing/suits/solgov.dm index 04621f5b60..e38e68164d 100644 --- a/code/modules/clothing/suits/solgov.dm +++ b/code/modules/clothing/suits/solgov.dm @@ -13,48 +13,48 @@ allowed = list(/obj/item/weapon/tank/emergency/oxygen,/obj/item/device/flashlight,/obj/item/weapon/pen,/obj/item/clothing/head/soft,/obj/item/clothing/head/beret,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/flame/lighter,/obj/item/device/taperecorder,/obj/item/device/analyzer,/obj/item/device/radio,/obj/item/taperoll) /obj/item/clothing/suit/storage/service/expeditionary - name = "expeditionary jacket" - desc = "A uniform service jacket belonging to the SCG Expeditionary Corps. It has silver buttons." + name = "\improper SifGuard jacket" + desc = "A uniform service jacket belonging to the Sif Homeguard Corps. It has silver buttons." icon_state = "blackservice_crew" /obj/item/clothing/suit/storage/service/expeditionary/medical - name = "expeditionary medical jacket" - desc = "A uniform service jacket belonging to the SCG Expeditionary Corps. It has silver buttons and blue trim." + name = "\improper SifGuard medical jacket" + desc = "A uniform service jacket belonging to the Sif Homeguard Corps. It has silver buttons and blue trim." icon_state = "blackservice_med" /obj/item/clothing/suit/storage/service/expeditionary/medical/command - name = "expeditionary medical command jacket" - desc = "A uniform service jacket belonging to the SCG Expeditionary Corps. It has gold buttons and blue trim." + name = "\improper SifGuard medical command jacket" + desc = "A uniform service jacket belonging to the Sif Homeguard Corps. It has gold buttons and blue trim." icon_state = "blackservice_medcom" /obj/item/clothing/suit/storage/service/expeditionary/engineering - name = "expeditionary engineering jacket" - desc = "A uniform service jacket belonging to the SCG Expeditionary Corps. It has silver buttons and orange trim." + name = "\improper SifGuard engineering jacket" + desc = "A uniform service jacket belonging to the Sif Homeguard Corps. It has silver buttons and orange trim." icon_state = "blackservice_eng" /obj/item/clothing/suit/storage/service/expeditionary/engineering/command - name = "expeditionary engineering command jacket" - desc = "A uniform service jacket belonging to the SCG Expeditionary Corps. It has gold buttons and orange trim." + name = "\improper SifGuard engineering command jacket" + desc = "A uniform service jacket belonging to the Sif Homeguard Corps. It has gold buttons and orange trim." icon_state = "blackservice_engcom" /obj/item/clothing/suit/storage/service/expeditionary/supply - name = "expeditionary supply jacket" - desc = "A uniform service jacket belonging to the SCG Expeditionary Corps. It has silver buttons and brown trim." + name = "\improper SifGuard supply jacket" + desc = "A uniform service jacket belonging to the Sif Homeguard Corps. It has silver buttons and brown trim." icon_state = "blackservice_sup" /obj/item/clothing/suit/storage/service/expeditionary/security - name = "expeditionary security jacket" - desc = "A uniform service jacket belonging to the SCG Expeditionary Corps. It has silver buttons and red trim." + name = "\improper SifGuard security jacket" + desc = "A uniform service jacket belonging to the Sif Homeguard Corps. It has silver buttons and red trim." icon_state = "blackservice_sec" /obj/item/clothing/suit/storage/service/expeditionary/security/command - name = "expeditionary security command jacket" - desc = "A uniform service jacket belonging to the SCG Expeditionary Corps. It has gold buttons and red trim." + name = "\improper SifGuard security command jacket" + desc = "A uniform service jacket belonging to the Sif Homeguard Corps. It has gold buttons and red trim." icon_state = "blackservice_seccom" /obj/item/clothing/suit/storage/service/expeditionary/command - name = "expeditionary command jacket" - desc = "A uniform service jacket belonging to the SCG Expeditionary Corps. It has gold buttons and gold trim." + name = "\improper SifGuard command jacket" + desc = "A uniform service jacket belonging to the Sif Homeguard Corps. It has gold buttons and gold trim." icon_state = "blackservice_com" /obj/item/clothing/suit/storage/service/marine diff --git a/code/modules/clothing/under/solgov.dm b/code/modules/clothing/under/solgov.dm index 6dc92e1238..eb3ed28a85 100644 --- a/code/modules/clothing/under/solgov.dm +++ b/code/modules/clothing/under/solgov.dm @@ -11,8 +11,8 @@ body_parts_covered = UPPER_TORSO|LOWER_TORSO /obj/item/clothing/under/pt/expeditionary - name = "expeditionary pt uniform" - desc = "A baggy shirt bearing the seal of the SCG Expeditionary Corps and some dorky looking blue shorts." + name = "\improper SifGuard pt uniform" + desc = "A baggy shirt bearing the seal of the Sif Homeguard Corps and some dorky looking blue shorts." icon_state = "expeditionpt" worn_state = "expeditionpt" @@ -40,57 +40,57 @@ siemens_coefficient = 0.9 /obj/item/clothing/under/utility/expeditionary - name = "expeditionary uniform" - desc = "The utility uniform of the SCG Expeditionary Corps, made from biohazard resistant material. This one has silver trim." + name = "\improper SifGuard uniform" + desc = "The utility uniform of the Sif Homeguard Corps, made from biohazard resistant material. This one has silver trim." icon_state = "blackutility_crew" worn_state = "blackutility_crew" armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 10) /obj/item/clothing/under/utility/expeditionary/medical - name = "expeditionary medical uniform" - desc = "The utility uniform of the SCG Expeditionary Corps, made from biohazard resistant material. This one has silver trim and blue blazes." + name = "\improper SifGuard medical uniform" + desc = "The utility uniform of the Sif Homeguard Corps, made from biohazard resistant material. This one has silver trim and blue blazes." icon_state = "blackutility_med" worn_state = "blackutility_med" /obj/item/clothing/under/utility/expeditionary/medical/command - name = "expeditionary medical command uniform" - desc = "The utility uniform of the SCG Expeditionary Corps, made from biohazard resistant material. This one has gold trim and blue blazes." + name = "\improper SifGuard medical command uniform" + desc = "The utility uniform of the Sif Homeguard Corps, made from biohazard resistant material. This one has gold trim and blue blazes." icon_state = "blackutility_medcom" worn_state = "blackutility_medcom" /obj/item/clothing/under/utility/expeditionary/engineering - name = "expeditionary engineering uniform" - desc = "The utility uniform of the SCG Expeditionary Corps, made from biohazard resistant material. This one has silver trim and organge blazes." + name = "\improper SifGuard engineering uniform" + desc = "The utility uniform of the Sif Homeguard Corps, made from biohazard resistant material. This one has silver trim and organge blazes." icon_state = "blackutility_eng" worn_state = "blackutility_eng" /obj/item/clothing/under/utility/expeditionary/engineering/command - name = "expeditionary engineering command uniform" - desc = "The utility uniform of the SCG Expeditionary Corps, made from biohazard resistant material. This one has gold trim and organge blazes." + name = "\improper SifGuard engineering command uniform" + desc = "The utility uniform of the Sif Homeguard Corps, made from biohazard resistant material. This one has gold trim and organge blazes." icon_state = "blackutility_engcom" worn_state = "blackutility_engcom" /obj/item/clothing/under/utility/expeditionary/supply - name = "expeditionary supply uniform" - desc = "The utility uniform of the SCG Expeditionary Corps, made from biohazard resistant material. This one has silver trim and brown blazes." + name = "\improper SifGuard supply uniform" + desc = "The utility uniform of the Sif Homeguard Corps, made from biohazard resistant material. This one has silver trim and brown blazes." icon_state = "blackutility_sup" worn_state = "blackutility_sup" /obj/item/clothing/under/utility/expeditionary/security - name = "expeditionary security uniform" - desc = "The utility uniform of the SCG Expeditionary Corps, made from biohazard resistant material. This one has silver trim and red blazes." + name = "\improper SifGuard security uniform" + desc = "The utility uniform of the Sif Homeguard Corps, made from biohazard resistant material. This one has silver trim and red blazes." icon_state = "blackutility_sec" worn_state = "blackutility_sec" /obj/item/clothing/under/utility/expeditionary/security/command - name = "expeditionary security command uniform" - desc = "The utility uniform of the SCG Expeditionary Corps, made from biohazard resistant material. This one has gold trim and red blazes." + name = "\improper SifGuard security command uniform" + desc = "The utility uniform of the Sif Homeguard Corps, made from biohazard resistant material. This one has gold trim and red blazes." icon_state = "blackutility_seccom" worn_state = "blackutility_seccom" /obj/item/clothing/under/utility/expeditionary/command - name = "expeditionary command uniform" - desc = "The utility uniform of the SCG Expeditionary Corps, made from biohazard resistant material. This one has gold trim and gold blazes." + name = "\improper SifGuard command uniform" + desc = "The utility uniform of the Sif Homeguard Corps, made from biohazard resistant material. This one has gold trim and gold blazes." icon_state = "blackutility_com" worn_state = "blackutility_com" @@ -221,14 +221,14 @@ siemens_coefficient = 0.9 /obj/item/clothing/under/dress/expeditionary - name = "expeditionary dress uniform" - desc = "The dress uniform of the SCG Expeditionary Corps in silver trim." + name = "\improper SifGuard dress uniform" + desc = "The dress uniform of the Sif Homeguard Corps in silver trim." icon_state = "greydress" worn_state = "greydress" /obj/item/clothing/under/dress/expeditionary/command - name = "expeditionary command dress uniform" - desc = "The dress uniform of the SCG Expeditionary Corps in gold trim." + name = "\improper SifGuard command dress uniform" + desc = "The dress uniform of the Sif Homeguard Corps in gold trim." icon_state = "greydress_com" worn_state = "greydress_com" diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm index 5416ab2666..e09c062ab0 100644 --- a/code/modules/events/carp_migration.dm +++ b/code/modules/events/carp_migration.dm @@ -32,7 +32,7 @@ spawn_locations.Add(C.loc) spawn_locations = shuffle(spawn_locations) num_groups = min(num_groups, spawn_locations.len) - + var/i = 1 while (i <= num_groups) var/group_size = rand(group_size_min, group_size_max) @@ -45,4 +45,5 @@ if(!C.stat) var/turf/T = get_turf(C) if(istype(T, /turf/space)) - qdel(C) + if(!prob(25)) + qdel(C) \ No newline at end of file diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index 9a91cd0664..37a576a442 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -136,6 +136,7 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Lotto", /datum/event/money_lotto, 0, list(ASSIGNMENT_ANY = 1), 1, 5, 15), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Mundane News", /datum/event/mundane_news, 300), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "PDA Spam", /datum/event/pda_spam, 0, list(ASSIGNMENT_ANY = 4), 0, 25, 50), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Shipping Error", /datum/event/shipping_error , 30, list(ASSIGNMENT_ANY = 2), 0), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Space Dust", /datum/event/dust , 60, list(ASSIGNMENT_ENGINEER = 20), 0, 0, 50), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Trivial News", /datum/event/trivial_news, 400), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation",/datum/event/infestation, 100, list(ASSIGNMENT_JANITOR = 100)), diff --git a/code/modules/events/shipping_error.dm b/code/modules/events/shipping_error.dm new file mode 100644 index 0000000000..ba1492e65a --- /dev/null +++ b/code/modules/events/shipping_error.dm @@ -0,0 +1,6 @@ +/datum/event/shipping_error/start() + var/datum/supply_order/O = new /datum/supply_order() + O.ordernum = supply_controller.ordernum + O.object = supply_controller.supply_packs[pick(supply_controller.supply_packs)] + O.orderedby = random_name(pick(MALE,FEMALE), species = "Human") + supply_controller.shoppinglist += O \ No newline at end of file diff --git a/code/modules/games/spaceball_cards.dm b/code/modules/games/spaceball_cards.dm index 11ded83550..9488192a72 100644 --- a/code/modules/games/spaceball_cards.dm +++ b/code/modules/games/spaceball_cards.dm @@ -14,7 +14,7 @@ P.name = "Spaceball Jones, [year] Brickburn Galaxy Trekers" P.card_icon = "spaceball_jones" else - var/language_type = pick(/datum/language/human,/datum/language/diona,/datum/language/tajaran,/datum/language/unathi) + var/language_type = pick(/datum/language/human,/datum/language/diona_local,/datum/language/tajaran,/datum/language/unathi) var/datum/language/L = new language_type() var/team = pick("Brickburn Galaxy Trekers","Mars Rovers", "Qerrbalak Saints", "Moghes Rockets", "Meralar Lightning", starsys_name+" Vixens", "Euphoric-Earth Alligators") P.name = "[L.get_random_name(pick(MALE,FEMALE))], [year - rand(0,50)] [team]" diff --git a/code/modules/integrated_electronics/_defines.dm b/code/modules/integrated_electronics/_defines.dm index de8f00dddb..d9daa035d5 100644 --- a/code/modules/integrated_electronics/_defines.dm +++ b/code/modules/integrated_electronics/_defines.dm @@ -29,6 +29,7 @@ var/list/all_integrated_circuits = list() var/cooldown_per_use = 1 SECOND var/spawn_flags = null // Used for world initializing, see the #defines above. var/category_text = "NO CATEGORY" // To show up on circuit printer, and perhaps other places. + var/autopulse = -1 // When input is received, the circuit will pulse itself if set to 1. 0 means it won't. -1 means it is permanently off. /obj/item/integrated_circuit/examine(mob/user) ..() @@ -71,7 +72,8 @@ var/list/all_integrated_circuits = list() /obj/item/integrated_circuit/nano_host() if(istype(src.loc, /obj/item/device/electronic_assembly)) - return loc + var/obj/item/device/electronic_assembly/assembly = loc + return assembly.resolve_nano_host() return ..() /obj/item/integrated_circuit/emp_act(severity) @@ -112,6 +114,14 @@ var/list/all_integrated_circuits = list() if(!CanInteract(user, physical_state)) return + var/window_height = 350 + var/window_width = 600 + + //var/table_edge_width = "[(window_width - window_width * 0.1) / 4]px" + //var/table_middle_width = "[(window_width - window_width * 0.1) - (table_edge_width * 2)]px" + var/table_edge_width = "30%" + var/table_middle_width = "40%" + var/HTML = list() HTML += "[src.name]" HTML += "
" @@ -122,9 +132,12 @@ var/list/all_integrated_circuits = list() HTML += "\[Remove\]
" HTML += "" - HTML += "" - HTML += "" - HTML += "" + //HTML += "" + //HTML += "" + //HTML += "" + HTML += "" + HTML += "" + HTML += "" HTML += "" var/column_width = 3 @@ -196,11 +209,16 @@ var/list/all_integrated_circuits = list() HTML += "" HTML += "
" - HTML += "
Complexity: [complexity]" - HTML += "
[extended_desc]" + if(autopulse != -1) + HTML += "
Meta Variables;" + HTML += "
\[Autopulse\] = [autopulse ? "ON" : "OFF"]" + HTML += "
" + + HTML += "
Complexity: [complexity]" + HTML += "
[extended_desc]" HTML += "" - user << browse(jointext(HTML, null), "window=circuit-\ref[src];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1") + user << browse(jointext(HTML, null), "window=circuit-\ref[src];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1") onclose(user, "circuit-\ref[src]") @@ -229,6 +247,10 @@ var/list/all_integrated_circuits = list() if(href_list["rename"]) rename_component(usr) + if(href_list["autopulse"]) + if(autopulse != -1) + autopulse = !autopulse + if(href_list["remove"]) if(istype(held_item, /obj/item/weapon/screwdriver)) disconnect_all() @@ -267,7 +289,7 @@ var/list/all_integrated_circuits = list() . = ..() /datum/integrated_io/nano_host() - return holder + return holder.nano_host() /datum/integrated_io/proc/data_as_type(var/as_type) @@ -285,7 +307,8 @@ var/list/all_integrated_circuits = list() if(isweakref(data)) var/weakref/w = data var/atom/A = w.resolve() - return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed. + //return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed. + return A ? "(\ref[A] \[Ref\])" : "(null)" return "([data])" // Nothing special needed for numbers or other stuff. /datum/integrated_io/activate/display_data() diff --git a/code/modules/integrated_electronics/arithmetic.dm b/code/modules/integrated_electronics/arithmetic.dm index 00676e778a..37eabf2027 100644 --- a/code/modules/integrated_electronics/arithmetic.dm +++ b/code/modules/integrated_electronics/arithmetic.dm @@ -5,6 +5,11 @@ outputs = list("result") activators = list("compute") category_text = "Arithmetic" + autopulse = 1 + +/obj/item/integrated_circuit/arithmetic/on_data_written() + if(autopulse == 1) + check_then_do_work() // +Adding+ // @@ -195,8 +200,8 @@ var/result = 0 for(var/datum/integrated_io/input/I in inputs) I.pull_data() - if(isnum(I.data) && I.data != 0) - result = abs(result) + if(isnum(I.data)) + result = abs(I.data) for(var/datum/integrated_io/output/O in outputs) O.data = result @@ -260,4 +265,45 @@ for(var/datum/integrated_io/output/O in outputs) O.data = result - O.push_data() \ No newline at end of file + O.push_data() + +// Square Root // + +/obj/item/integrated_circuit/arithmetic/square_root + name = "square root circuit" + desc = "This outputs the square root of a number you put in." + icon_state = "square_root" + inputs = list("A") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/arithmetic/square_root/do_work() + var/result = 0 + for(var/datum/integrated_io/input/I in inputs) + I.pull_data() + if(isnum(I.data)) + result = sqrt(I.data) + + for(var/datum/integrated_io/output/O in outputs) + O.data = result + O.push_data() + +// % Modulo % // + +/obj/item/integrated_circuit/arithmetic/modulo + name = "modulo circuit" + desc = "Gets the remainder of A / B." + icon_state = "modulo" + inputs = list("A", "B") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/arithmetic/modulo/do_work() + var/result = 0 + var/datum/integrated_io/input/A = inputs[1] + var/datum/integrated_io/input/B = inputs[2] + if(isnum(A.data) && isnum(B.data) && B.data != 0) + result = A.data % B.data + + for(var/datum/integrated_io/output/O in outputs) + O.data = result + O.push_data() + diff --git a/code/modules/integrated_electronics/assemblies.dm b/code/modules/integrated_electronics/assemblies.dm index 3b9e7aab06..ff994aa43c 100644 --- a/code/modules/integrated_electronics/assemblies.dm +++ b/code/modules/integrated_electronics/assemblies.dm @@ -1,33 +1,59 @@ +#define IC_COMPONENTS_BASE 20 +#define IC_COMPLEXITY_BASE 80 + /obj/item/device/electronic_assembly name = "electronic assembly" desc = "It's a case, for building electronics with." - w_class = 2 + w_class = ITEMSIZE_SMALL icon = 'icons/obj/electronic_assemblies.dmi' icon_state = "setup_small" - var/max_components = 10 - var/max_complexity = 40 + show_messages = TRUE + var/max_components = IC_COMPONENTS_BASE + var/max_complexity = IC_COMPLEXITY_BASE var/opened = 0 /obj/item/device/electronic_assembly/medium name = "electronic mechanism" icon_state = "setup_medium" - w_class = 3 - max_components = 20 - max_complexity = 80 + w_class = ITEMSIZE_NORMAL + max_components = IC_COMPONENTS_BASE * 2 + max_complexity = IC_COMPLEXITY_BASE * 2 /obj/item/device/electronic_assembly/large name = "electronic machine" icon_state = "setup_large" - w_class = 4 - max_components = 30 - max_complexity = 120 + w_class = ITEMSIZE_LARGE + max_components = IC_COMPONENTS_BASE * 3 + max_complexity = IC_COMPLEXITY_BASE * 3 /obj/item/device/electronic_assembly/drone name = "electronic drone" icon_state = "setup_drone" - w_class = 3 - max_components = 25 - max_complexity = 100 + w_class = ITEMSIZE_NORMAL + max_components = IC_COMPONENTS_BASE * 1.5 + max_complexity = IC_COMPLEXITY_BASE * 1.5 + +/obj/item/device/electronic_assembly/implant + name = "electronic implant" + icon_state = "setup_implant" + w_class = ITEMSIZE_TINY + max_components = IC_COMPONENTS_BASE / 2 + max_complexity = IC_COMPLEXITY_BASE / 2 + var/obj/item/weapon/implant/integrated_circuit/implant = null + +/obj/item/device/electronic_assembly/implant/update_icon() + ..() + implant.icon_state = icon_state + + +/obj/item/device/electronic_assembly/implant/nano_host() + return implant + +/obj/item/device/electronic_assembly/proc/resolve_nano_host() + return src + +/obj/item/device/electronic_assembly/implant/resolve_nano_host() + return implant /obj/item/device/electronic_assembly/interact(mob/user) if(!CanInteract(user, physical_state)) @@ -79,6 +105,12 @@ to_chat(M, "The machine now has a label reading '[input]'.") name = input +/obj/item/device/electronic_assembly/proc/can_move() + return FALSE + +/obj/item/device/electronic_assembly/drone/can_move() + return TRUE + /obj/item/device/electronic_assembly/update_icon() if(opened) icon_state = initial(icon_state) + "-open" diff --git a/code/modules/integrated_electronics/converters.dm b/code/modules/integrated_electronics/converters.dm index b039299a55..96494ba469 100644 --- a/code/modules/integrated_electronics/converters.dm +++ b/code/modules/integrated_electronics/converters.dm @@ -5,6 +5,11 @@ outputs = list("output") activators = list("convert") category_text = "Converter" + autopulse = 1 + +/obj/item/integrated_circuit/converter/on_data_written() + if(autopulse == 1) + check_then_do_work() /obj/item/integrated_circuit/converter/num2text name = "number to string" @@ -104,4 +109,67 @@ var/datum/integrated_io/outgoing = outputs[1] outgoing.data = result - outgoing.push_data() \ No newline at end of file + outgoing.push_data() + +/obj/item/integrated_circuit/converter/radians2degrees + name = "radians to degrees converter" + desc = "Converts radians to degrees." + inputs = list("radian") + outputs = list("degrees") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/converter/radians2degrees/do_work() + var/result = null + var/datum/integrated_io/incoming = inputs[1] + var/datum/integrated_io/outgoing = outputs[1] + incoming.pull_data() + if(incoming.data && isnum(incoming.data)) + result = ToDegrees(incoming.data) + + outgoing.data = result + outgoing.push_data() + +/obj/item/integrated_circuit/converter/degrees2radians + name = "degrees to radians converter" + desc = "Converts degrees to radians." + inputs = list("degrees") + outputs = list("radians") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/converter/degrees2radians/do_work() + var/result = null + var/datum/integrated_io/incoming = inputs[1] + var/datum/integrated_io/outgoing = outputs[1] + incoming.pull_data() + if(incoming.data && isnum(incoming.data)) + result = ToRadians(incoming.data) + + outgoing.data = result + outgoing.push_data() + + +/obj/item/integrated_circuit/converter/abs_to_rel_coords + name = "abs to rel coordinate converter" + desc = "Easily convert absolute coordinates to relative coordinates with this." + complexity = 4 + inputs = list("X1 (abs)", "Y1 (abs)", "X2 (abs)", "Y2 (abs)") + outputs = list("X (rel)", "Y (rel)") + activators = list("compute rel coordinates") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work() + var/datum/integrated_io/x1 = inputs[1] + var/datum/integrated_io/y1 = inputs[2] + + var/datum/integrated_io/x2 = inputs[3] + var/datum/integrated_io/y2 = inputs[4] + + var/datum/integrated_io/result_x = outputs[1] + var/datum/integrated_io/result_y = outputs[2] + + if(x1.data && y1.data && x2.data && y2.data) + result_x.data = x1.data - x2.data + result_y.data = y1.data - y2.data + + for(var/datum/integrated_io/output/O in outputs) + O.push_data() \ No newline at end of file diff --git a/code/modules/integrated_electronics/coordinate.dm b/code/modules/integrated_electronics/coordinate.dm deleted file mode 100644 index 0941c290f4..0000000000 --- a/code/modules/integrated_electronics/coordinate.dm +++ /dev/null @@ -1,54 +0,0 @@ -//This circuit gives information on where the machine is. -/obj/item/integrated_circuit/gps - name = "global positioning system" - desc = "This allows you to easily know the position of a machine containing this device." - icon_state = "gps" - complexity = 4 - inputs = list() - outputs = list("X (abs)", "Y (abs)") - activators = list("get coordinates") - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - category_text = "Coords" - -/obj/item/integrated_circuit/gps/do_work() - var/turf/T = get_turf(src) - var/datum/integrated_io/result_x = outputs[1] - var/datum/integrated_io/result_y = outputs[2] - - result_x.data = null - result_y.data = null - if(!T) - return - - result_x.data = T.x - result_y.data = T.y - - for(var/datum/integrated_io/output/O in outputs) - O.push_data() - -/obj/item/integrated_circuit/abs_to_rel_coords - name = "abs to rel coordinate converter" - desc = "Easily convert absolute coordinates to relative coordinates with this." - complexity = 4 - inputs = list("X1 (abs)", "Y1 (abs)", "X2 (abs)", "Y2 (abs)") - outputs = list("X (rel)", "Y (rel)") - activators = list("compute rel coordinates") - spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - category_text = "Coords" - -/obj/item/integrated_circuit/abs_to_rel_coords/do_work() - var/datum/integrated_io/x1 = inputs[1] - var/datum/integrated_io/y1 = inputs[2] - - var/datum/integrated_io/x2 = inputs[3] - var/datum/integrated_io/y2 = inputs[4] - - var/datum/integrated_io/result_x = outputs[1] - var/datum/integrated_io/result_y = outputs[2] - - if(x1.data && y1.data && x2.data && y2.data) - result_x.data = x1.data - x2.data - result_y.data = y1.data - y2.data - - for(var/datum/integrated_io/output/O in outputs) - O.push_data() \ No newline at end of file diff --git a/code/modules/integrated_electronics/data_transfer.dm b/code/modules/integrated_electronics/data_transfer.dm index bf4ddf4b6f..7e37995df5 100644 --- a/code/modules/integrated_electronics/data_transfer.dm +++ b/code/modules/integrated_electronics/data_transfer.dm @@ -1,5 +1,10 @@ /obj/item/integrated_circuit/transfer category_text = "Data Transfer" + autopulse = 1 + +/obj/item/integrated_circuit/transfer/on_data_written() + if(autopulse == 1) + check_then_do_work() /obj/item/integrated_circuit/transfer/splitter name = "splitter" diff --git a/code/modules/integrated_electronics/input_output.dm b/code/modules/integrated_electronics/input_output.dm index 5bb3ea6aec..c77ad3dc69 100644 --- a/code/modules/integrated_electronics/input_output.dm +++ b/code/modules/integrated_electronics/input_output.dm @@ -321,11 +321,80 @@ data_received.write_data_to_pin(message) text_received.write_data_to_pin(text) + for(var/datum/integrated_io/output/O in outputs) + O.push_data() + +//This circuit gives information on where the machine is. +/obj/item/integrated_circuit/input/gps + name = "global positioning system" + desc = "This allows you to easily know the position of a machine containing this device." + icon_state = "gps" + complexity = 4 + inputs = list() + outputs = list("X (abs)", "Y (abs)") + activators = list("get coordinates") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/input/gps/do_work() + var/turf/T = get_turf(src) + var/datum/integrated_io/result_x = outputs[1] + var/datum/integrated_io/result_y = outputs[2] + + result_x.data = null + result_y.data = null + if(!T) + return + + result_x.data = T.x + result_y.data = T.y + + for(var/datum/integrated_io/output/O in outputs) + O.push_data() + + +/obj/item/integrated_circuit/input/microphone + name = "microphone" + desc = "Useful for spying on people or for voice activated machines." + icon_state = "recorder" + complexity = 8 + inputs = list() + outputs = list("speaker \", "message \") + activators = list("on message received") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/input/microphone/New() + ..() + listening_objects |= src + +/obj/item/integrated_circuit/input/microphone/Destroy() + listening_objects -= src + ..() + +/obj/item/integrated_circuit/input/microphone/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null) + var/datum/integrated_io/V = outputs[1] + var/datum/integrated_io/O = outputs[2] + var/datum/integrated_io/A = activators[1] + if(M && msg) + if(speaking) + if(!speaking.machine_understands) + msg = speaking.scramble(msg) + V.data = M.GetVoice() + O.data = msg + A.push_data() + + for(var/datum/integrated_io/output/out in outputs) + out.push_data() + + + + + + /obj/item/integrated_circuit/output category_text = "Output" /obj/item/integrated_circuit/output/screen - name = "screen" + name = "small screen" desc = "This small screen can display a single piece of data, when the machine is examined closely." icon_state = "screen" inputs = list("displayed data") @@ -343,6 +412,28 @@ else stuff_to_display = I.data +/obj/item/integrated_circuit/output/screen/medium + name = "screen" + desc = "This screen allows for people holding the device to see a piece of data." + icon_state = "screen_medium" + +/obj/item/integrated_circuit/output/screen/medium/do_work() + ..() + var/list/nearby_things = range(0, get_turf(src)) + for(var/mob/M in nearby_things) + var/obj/O = istype(loc, /obj/item/device/electronic_assembly) ? loc : src + visible_message("\icon[O] [stuff_to_display]") + +/obj/item/integrated_circuit/output/screen/large + name = "large screen" + desc = "This screen allows for people able to see the device to see a piece of data." + icon_state = "screen_large" + +/obj/item/integrated_circuit/output/screen/large/do_work() + ..() + var/obj/O = istype(loc, /obj/item/device/electronic_assembly) ? loc : src + O.visible_message("\icon[O] [stuff_to_display]") + /obj/item/integrated_circuit/output/light name = "light" desc = "This light can turn on and off on command." @@ -415,6 +506,24 @@ activators = list("play sound") var/list/sounds = list() +/obj/item/integrated_circuit/output/text_to_speech + name = "text-to-speech circuit" + desc = "A miniature speaker is attached to this component." + extended_desc = "This unit is more advanced than the plain speaker circuit, able to transpose any valid text to speech." + icon_state = "speaker" + complexity = 12 + cooldown_per_use = 4 SECONDS + inputs = list("text") + outputs = list() + activators = list("to speech") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/output/text_to_speech/do_work() + var/datum/integrated_io/text = inputs[1] + if(istext(text.data)) + var/obj/O = istype(loc, /obj/item/device/electronic_assembly) ? loc : src + audible_message("\icon[O] \The [O.name] states, \"[text.data]\"") + /obj/item/integrated_circuit/output/sound/New() ..() extended_desc = list() diff --git a/code/modules/integrated_electronics/logic.dm b/code/modules/integrated_electronics/logic.dm index 6d53f6aae7..d477be3cbe 100644 --- a/code/modules/integrated_electronics/logic.dm +++ b/code/modules/integrated_electronics/logic.dm @@ -6,6 +6,11 @@ outputs = list("result") activators = list("compare", "on true result") category_text = "Logic" + autopulse = 1 + +/obj/item/integrated_circuit/logic/on_data_written() + if(autopulse == 1) + check_then_do_work() /obj/item/integrated_circuit/logic/do_work() var/datum/integrated_io/O = outputs[1] diff --git a/code/modules/integrated_electronics/manipulation.dm b/code/modules/integrated_electronics/manipulation.dm index 524c060d2d..f49b96d16c 100644 --- a/code/modules/integrated_electronics/manipulation.dm +++ b/code/modules/integrated_electronics/manipulation.dm @@ -105,7 +105,7 @@ Southwest = 10
\
\ Pulsing the 'step towards dir' activator pin will cause the machine to move a meter in that direction, assuming it is not \ - being held, or anchored in some way. It should be noted that heavy machines will be unable to move." + being held, or anchored in some way. It should be noted that the ability to move is dependant on the type of assembly that this circuit inhabits." complexity = 20 inputs = list("dir num") outputs = list() @@ -117,7 +117,7 @@ var/turf/T = get_turf(src) if(T && istype(loc, /obj/item/device/electronic_assembly)) var/obj/item/device/electronic_assembly/machine = loc - if(machine.anchored || machine.w_class >= ITEMSIZE_LARGE) + if(machine.anchored || !machine.can_move()) return if(machine.loc == T) // Check if we're held by someone. If the loc is the floor, we're not held. var/datum/integrated_io/wanted_dir = inputs[1] diff --git a/code/modules/integrated_electronics/memory.dm b/code/modules/integrated_electronics/memory.dm index edf263dd96..f9cd109dce 100644 --- a/code/modules/integrated_electronics/memory.dm +++ b/code/modules/integrated_electronics/memory.dm @@ -61,7 +61,7 @@ "output pin 6", "output pin 7", "output pin 8") - spawn_flags = IC_SPAWN_RESEARCH + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3) /obj/item/integrated_circuit/memory/huge diff --git a/code/modules/integrated_electronics/time.dm b/code/modules/integrated_electronics/time.dm index 8a6a0c9c04..50bcc5e386 100644 --- a/code/modules/integrated_electronics/time.dm +++ b/code/modules/integrated_electronics/time.dm @@ -44,7 +44,7 @@ This circuit is set to send a pulse after a delay of half a second." icon_state = "delay-5" delay = 5 - spawn_flags = IC_SPAWN_RESEARCH + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/time/delay/tenth_sec name = "tenth-sec delay circuit" @@ -52,7 +52,7 @@ This circuit is set to send a pulse after a delay of 1/10th of a second." icon_state = "delay-1" delay = 1 - spawn_flags = IC_SPAWN_RESEARCH + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/time/delay/custom name = "custom delay circuit" diff --git a/code/modules/integrated_electronics/tools.dm b/code/modules/integrated_electronics/tools.dm index 1d3b2cf4a9..6c76b9b4ff 100644 --- a/code/modules/integrated_electronics/tools.dm +++ b/code/modules/integrated_electronics/tools.dm @@ -164,15 +164,33 @@ icon = 'icons/obj/electronic_assemblies.dmi' icon_state = "circuit_kit" w_class = 3 - display_contents_with_number = 1 + display_contents_with_number = 0 + can_hold = list( + /obj/item/integrated_circuit, + /obj/item/weapon/storage/bag/circuits/mini, + /obj/item/device/electronic_assembly, + /obj/item/device/integrated_electronics, + /obj/item/weapon/crowbar, + /obj/item/weapon/screwdriver + ) /obj/item/weapon/storage/bag/circuits/basic/New() ..() spawn(2 SECONDS) // So the list has time to initialize. - for(var/obj/item/integrated_circuit/IC in all_integrated_circuits) - if(IC.spawn_flags & IC_SPAWN_DEFAULT) - for(var/i = 1 to 3) - new IC.type(src) +// for(var/obj/item/integrated_circuit/IC in all_integrated_circuits) +// if(IC.spawn_flags & IC_SPAWN_DEFAULT) +// for(var/i = 1 to 3) +// new IC.type(src) + new /obj/item/weapon/storage/bag/circuits/mini/arithmetic(src) + new /obj/item/weapon/storage/bag/circuits/mini/trig(src) + new /obj/item/weapon/storage/bag/circuits/mini/input(src) + new /obj/item/weapon/storage/bag/circuits/mini/output(src) + new /obj/item/weapon/storage/bag/circuits/mini/memory(src) + new /obj/item/weapon/storage/bag/circuits/mini/logic(src) + new /obj/item/weapon/storage/bag/circuits/mini/time(src) + new /obj/item/weapon/storage/bag/circuits/mini/reagents(src) + new /obj/item/weapon/storage/bag/circuits/mini/transfer(src) + new /obj/item/weapon/storage/bag/circuits/mini/converter(src) new /obj/item/device/electronic_assembly(src) new /obj/item/device/integrated_electronics/wirer(src) @@ -193,4 +211,151 @@ new /obj/item/device/integrated_electronics/debugger(src) new /obj/item/weapon/crowbar(src) new /obj/item/weapon/screwdriver(src) - make_exact_fit() \ No newline at end of file + make_exact_fit() + +/obj/item/weapon/storage/bag/circuits/mini/ + name = "circuit box" + desc = "Used to partition categories of circuits, for a neater workspace." + w_class = 2 + display_contents_with_number = 1 + can_hold = list(/obj/item/integrated_circuit) + +/obj/item/weapon/storage/bag/circuits/mini/arithmetic + name = "arithmetic circuit box" + desc = "Warning: Contains math." + icon_state = "box_arithmetic" + +/obj/item/weapon/storage/bag/circuits/mini/arithmetic/New() + ..() + for(var/obj/item/integrated_circuit/arithmetic/IC in all_integrated_circuits) + if(IC.spawn_flags & IC_SPAWN_DEFAULT) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() + + +/obj/item/weapon/storage/bag/circuits/mini/trig + name = "trig circuit box" + desc = "Danger: Contains more math." + icon_state = "box_trig" + +/obj/item/weapon/storage/bag/circuits/mini/trig/New() + ..() + for(var/obj/item/integrated_circuit/trig/IC in all_integrated_circuits) + if(IC.spawn_flags & IC_SPAWN_DEFAULT) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() + + +/obj/item/weapon/storage/bag/circuits/mini/input + name = "input circuit box" + desc = "Tell these circuits everything you know." + icon_state = "box_input" + +/obj/item/weapon/storage/bag/circuits/mini/input/New() + ..() + for(var/obj/item/integrated_circuit/input/IC in all_integrated_circuits) + if(IC.spawn_flags & IC_SPAWN_DEFAULT) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() + + +/obj/item/weapon/storage/bag/circuits/mini/output + name = "output circuit box" + desc = "Circuits to interface with the world beyond itself." + icon_state = "box_output" + +/obj/item/weapon/storage/bag/circuits/mini/output/New() + ..() + for(var/obj/item/integrated_circuit/output/IC in all_integrated_circuits) + if(IC.spawn_flags & IC_SPAWN_DEFAULT) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() + + +/obj/item/weapon/storage/bag/circuits/mini/memory + name = "memory circuit box" + desc = "Machines can be quite forgetful without these." + icon_state = "box_memory" + +/obj/item/weapon/storage/bag/circuits/mini/memory/New() + ..() + for(var/obj/item/integrated_circuit/memory/IC in all_integrated_circuits) + if(IC.spawn_flags & IC_SPAWN_DEFAULT) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() + + + +/obj/item/weapon/storage/bag/circuits/mini/logic + name = "logic circuit box" + desc = "May or may not be Turing complete." + icon_state = "box_logic" + +/obj/item/weapon/storage/bag/circuits/mini/logic/New() + ..() + for(var/obj/item/integrated_circuit/logic/IC in all_integrated_circuits) + if(IC.spawn_flags & IC_SPAWN_DEFAULT) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() + + +/obj/item/weapon/storage/bag/circuits/mini/time + name = "time circuit box" + desc = "No time machine parts, sadly." + icon_state = "box_time" + +/obj/item/weapon/storage/bag/circuits/mini/time/New() + ..() + for(var/obj/item/integrated_circuit/time/IC in all_integrated_circuits) + if(IC.spawn_flags & IC_SPAWN_DEFAULT) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() + + +/obj/item/weapon/storage/bag/circuits/mini/reagents + name = "reagent circuit box" + desc = "Unlike most electronics, these circuits are supposed to come in contact with liquids." + icon_state = "box_reagents" + +/obj/item/weapon/storage/bag/circuits/mini/reagents/New() + ..() + for(var/obj/item/integrated_circuit/reagent/IC in all_integrated_circuits) + if(IC.spawn_flags & IC_SPAWN_DEFAULT) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() + + +/obj/item/weapon/storage/bag/circuits/mini/transfer + name = "transfer circuit box" + desc = "Useful for moving data representing something arbitrary to another arbitrary virtual place." + icon_state = "box_transfer" + +/obj/item/weapon/storage/bag/circuits/mini/transfer/New() + ..() + for(var/obj/item/integrated_circuit/transfer/IC in all_integrated_circuits) + if(IC.spawn_flags & IC_SPAWN_DEFAULT) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() + + +/obj/item/weapon/storage/bag/circuits/mini/converter + name = "converter circuit box" + desc = "Transform one piece of data to another type of data with these." + icon_state = "box_converter" + +/obj/item/weapon/storage/bag/circuits/mini/converter/New() + ..() + for(var/obj/item/integrated_circuit/converter/IC in all_integrated_circuits) + if(IC.spawn_flags & IC_SPAWN_DEFAULT) + for(var/i = 1 to 3) + new IC.type(src) + make_exact_fit() \ No newline at end of file diff --git a/code/modules/integrated_electronics/trig.dm b/code/modules/integrated_electronics/trig.dm new file mode 100644 index 0000000000..e8e2e09ca9 --- /dev/null +++ b/code/modules/integrated_electronics/trig.dm @@ -0,0 +1,135 @@ +//These circuits do not-so-simple math. +/obj/item/integrated_circuit/trig + complexity = 1 + inputs = list("A","B","C","D","E","F","G","H") + outputs = list("result") + activators = list("compute") + category_text = "Trig" + extended_desc = "Input and output are in degrees." + autopulse = 1 + +/obj/item/integrated_circuit/trig/on_data_written() + if(autopulse == 1) + check_then_do_work() + +// Sine // + +/obj/item/integrated_circuit/trig/sine + name = "sin circuit" + desc = "Has nothing to do with evil, unless you consider trigonometry to be evil. Outputs the sine of A." + icon_state = "sine" + inputs = list("A") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/trig/sine/do_work() + var/result = null + var/datum/integrated_io/input/A = inputs[1] + A.pull_data() + if(isnum(A.data)) + result = sin(A.data) + + var/datum/integrated_io/output/O = outputs[1] + O.data = result + O.push_data() + +// Cosine // + +/obj/item/integrated_circuit/trig/cosine + name = "cos circuit" + desc = "Outputs the cosine of A." + icon_state = "cosine" + inputs = list("A") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/trig/cosine/do_work() + var/result = null + var/datum/integrated_io/input/A = inputs[1] + A.pull_data() + if(isnum(A.data)) + result = cos(A.data) + + var/datum/integrated_io/output/O = outputs[1] + O.data = result + O.push_data() + +// Tangent // + +/obj/item/integrated_circuit/trig/tangent + name = "tan circuit" + desc = "Outputs the tangent of A. Guaranteed to not go on a tangent about its existance." + icon_state = "tangent" + inputs = list("A") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/trig/tangent/do_work() + var/result = null + var/datum/integrated_io/input/A = inputs[1] + A.pull_data() + if(isnum(A.data)) + result = Tan(A.data) + + var/datum/integrated_io/output/O = outputs[1] + O.data = result + O.push_data() + +// Cosecant // + +/obj/item/integrated_circuit/trig/cosecant + name = "csc circuit" + desc = "Outputs the cosecant of A." + icon_state = "cosecant" + inputs = list("A") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/trig/cosecant/do_work() + var/result = null + var/datum/integrated_io/input/A = inputs[1] + A.pull_data() + if(isnum(A.data)) + result = Csc(A.data) + + var/datum/integrated_io/output/O = outputs[1] + O.data = result + O.push_data() + + +// Secant // + +/obj/item/integrated_circuit/trig/secant + name = "sec circuit" + desc = "Outputs the secant of A. Has nothing to do with the security department." + icon_state = "secant" + inputs = list("A") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/trig/secant/do_work() + var/result = null + var/datum/integrated_io/input/A = inputs[1] + A.pull_data() + if(isnum(A.data)) + result = Sec(A.data) + + var/datum/integrated_io/output/O = outputs[1] + O.data = result + O.push_data() + + +// Cotangent // + +/obj/item/integrated_circuit/trig/cotangent + name = "cot circuit" + desc = "Outputs the cotangent of A. Has nothing to do with the security department." + icon_state = "cotangent" + inputs = list("A") + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + +/obj/item/integrated_circuit/trig/cotangent/do_work() + var/result = null + var/datum/integrated_io/input/A = inputs[1] + A.pull_data() + if(isnum(A.data)) + result = Cot(A.data) + + var/datum/integrated_io/output/O = outputs[1] + O.data = result + O.push_data() \ No newline at end of file diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index b20d39ddce..b7a686fef0 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -843,3 +843,9 @@ mob/observer/dead/MayRespawn(var/feedback = 0) if(finalized == "No") icon_state = previous_state + +/mob/observer/dead/is_blind() + return FALSE + +/mob/observer/dead/is_deaf() + return FALSE diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm index ada597f46b..4d348c8d71 100644 --- a/code/modules/mob/dead/observer/say.dm +++ b/code/modules/mob/dead/observer/say.dm @@ -7,6 +7,7 @@ log_say("Ghost/[src.key] : [message]") if (src.client) + client.handle_spam_prevention(MUTE_DEADCHAT) if(src.client.prefs.muted & MUTE_DEADCHAT) src << "\red You cannot talk in deadchat (muted)." return @@ -26,6 +27,7 @@ log_emote("Ghost/[src.key] : [message]") if(src.client) + client.handle_spam_prevention(MUTE_DEADCHAT) if(src.client.prefs.muted & MUTE_DEADCHAT) src << "\red You cannot emote in deadchat (muted)." return diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index 343b8e4225..a240277d38 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -59,7 +59,7 @@ if(is_preference_enabled(/datum/client_preference/ghost_ears) && (speaker in view(src))) message = "[message]" - if((sdisabilities & DEAF) || ear_deaf) + if(is_deaf()) if(!language || !(language.flags & INNATE)) // INNATE is the flag for audible-emote-language, so we don't want to show an "x talks but you cannot hear them" message if it's set if(speaker == src) src << "You cannot hear yourself speak!" diff --git a/code/modules/mob/language/generic.dm b/code/modules/mob/language/generic.dm index 8e22cd0493..7df164c821 100644 --- a/code/modules/mob/language/generic.dm +++ b/code/modules/mob/language/generic.dm @@ -20,7 +20,7 @@ // 'basic' language; spoken by default. /datum/language/common - name = "Galactic Common" + name = LANGUAGE_GALCOM desc = "The common galactic tongue." speech_verb = "says" whisper_verb = "whispers" @@ -39,7 +39,7 @@ // Galactic common languages (systemwide accepted standards). /datum/language/trader - name = "Tradeband" + name = LANGUAGE_TRADEBAND desc = "Maintained by the various trading cartels in major systems, this elegant, structured language is used for bartering and bargaining." speech_verb = "enunciates" colour = "say_quote" @@ -56,7 +56,7 @@ // Criminal language. /datum/language/gutter - name = "Gutter" + name = LANGUAGE_GUTTER desc = "There is no true language named Gutter. 'Gutter' is a catchall term for a collection of unofficial SolCom dialects that has somehow managed to spread across the stars." speech_verb = "growls" colour = "rough" @@ -115,7 +115,7 @@ "his", "ing", "ion", "ith", "not", "ome", "oul", "our", "sho", "ted", "ter", "tha", "the", "thi") /datum/language/sign - name = "Sign Language" + name = LANGUAGE_SIGN desc = "A sign language commonly used for those who are deaf or mute." signlang_verb = list("gestures") colour = "say_quote" diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm index f3d59d3649..b9eb226e12 100644 --- a/code/modules/mob/language/language.dm +++ b/code/modules/mob/language/language.dm @@ -160,12 +160,15 @@ // Can we speak this language, as opposed to just understanding it? /mob/proc/can_speak(datum/language/speaking) //Prevents someone from speaking a null language. - if(speaking) - return (speaking.can_speak_special(src) && (universal_speak || (speaking && (speaking.flags & INNATE)) || speaking in src.languages)) - else + if(!speaking) log_debug("[src] attempted to speak a null language.") return 0 + if (only_species_language && speaking != all_languages[species_language]) + return 0 + + return (speaking.can_speak_special(src) && (universal_speak || (speaking && (speaking.flags & INNATE)) || speaking in src.languages)) + /mob/proc/get_language_prefix() if(client && client.prefs.language_prefixes && client.prefs.language_prefixes.len) return client.prefs.language_prefixes[1] @@ -213,7 +216,10 @@ /mob/living/Topic(href, href_list) if(href_list["default_lang"]) if(href_list["default_lang"] == "reset") - set_default_language(null) + if (species_language) + set_default_language(all_languages[species_language]) + else + set_default_language(null) else var/datum/language/L = locate(href_list["default_lang"]) if(L && (L in languages)) @@ -223,4 +229,10 @@ else return ..() +/proc/transfer_languages(var/mob/source, var/mob/target, var/except_flags) + for(var/datum/language/L in source.languages) + if(L.flags & except_flags) + continue + target.add_language(L.name) + #undef SCRAMBLE_CACHE_LEN diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm index 77cb8f1ad5..b69c9cca5f 100644 --- a/code/modules/mob/language/station.dm +++ b/code/modules/mob/language/station.dm @@ -1,6 +1,6 @@ -/datum/language/diona - name = "Rootspeak" - desc = "A creaking, subvocal language spoken instinctively by the Dionaea. Due to the unique makeup of the average Diona, a phrase of Rootspeak can be a combination of anywhere from one to twelve individual voices and notes." +/datum/language/diona_local + name = LANGUAGE_ROOTLOCAL + desc = "A complex language known instinctively by Dionaea, 'spoken' by emitting modulated radio waves. This version uses high frequency waves for quick communication at short ranges." speech_verb = "creaks and rustles" ask_verb = "creaks" exclaim_verb = "rustles" @@ -9,13 +9,19 @@ flags = RESTRICTED syllables = list("hs","zt","kr","st","sh") -/datum/language/diona/get_random_name() +/datum/language/diona_local/get_random_name() var/new_name = "[pick(list("To Sleep Beneath","Wind Over","Embrace of","Dreams of","Witnessing","To Walk Beneath","Approaching the"))]" new_name += " [pick(list("the Void","the Sky","Encroaching Night","Planetsong","Starsong","the Wandering Star","the Empty Day","Daybreak","Nightfall","the Rain"))]" return new_name +/datum/language/diona_global + name = LANGUAGE_ROOTGLOBAL + desc = "A complex language known instinctively by Dionaea, 'spoken' by emitting modulated radio waves. This version uses low frequency waves for slow communication at long ranges." + key = "w" + flags = RESTRICTED | HIVEMIND + /datum/language/unathi - name = "Sinta'unathi" + name = LANGUAGE_UNATHI desc = "The common language of Moghes, composed of sibilant hisses and rattles. Spoken natively by Unathi." speech_verb = "hisses" ask_verb = "hisses" @@ -42,7 +48,7 @@ return capitalize(new_name) /datum/language/tajaran - name = "Siik" + name = LANGUAGE_SIIK desc = "The most prevalant language of Meralar, composed of expressive yowls and chirps. Native to the Tajaran." speech_verb = "mrowls" ask_verb = "mrowls" @@ -65,7 +71,7 @@ return new_name /datum/language/skrell - name = "Skrellian" + name = LANGUAGE_SKRELLIAN desc = "A melodic and complex language spoken by the Skrell of Qerrbalak. Some of the notes are inaudible to humans." speech_verb = "warbles" ask_verb = "warbles" @@ -76,7 +82,7 @@ syllables = list("qr","qrr","xuq","qil","quum","xuqm","vol","xrim","zaoo","qu-uu","qix","qoo","zix","*","!") /datum/language/human - name = "Sol Common" + name = LANGUAGE_SOL_COMMON desc = "A bastardized hybrid of informal English and elements of Mandarin Chinese; the common language of the Sol system." speech_verb = "says" whisper_verb = "whispers" @@ -104,8 +110,8 @@ return ..() /datum/language/machine - name = "Encoded Audio Language" - desc = "A efficient language of encoded tones developed by synthetics and cyborgs." + name = LANGUAGE_EAL + desc = "An efficient language of encoded tones developed by synthetics and cyborgs." speech_verb = "whistles" ask_verb = "chirps" exclaim_verb = "whistles loudly" @@ -127,7 +133,7 @@ return pick(ai_names) /datum/language/seromi - name = "Schechi" + name = LANGUAGE_SCHECHI desc = "A trilling language spoken by the diminutive Teshari." speech_verb = "chirps" ask_verb = "chirrups" diff --git a/code/modules/mob/living/carbon/alien/diona/diona.dm b/code/modules/mob/living/carbon/alien/diona/diona.dm index ba8932ebf9..ebcd4d7774 100644 --- a/code/modules/mob/living/carbon/alien/diona/diona.dm +++ b/code/modules/mob/living/carbon/alien/diona/diona.dm @@ -7,9 +7,11 @@ speak_emote = list("chirrups") icon_state = "nymph" item_state = "nymph" - language = "Rootspeak" + language = LANGUAGE_ROOTLOCAL + species_language = LANGUAGE_ROOTLOCAL + only_species_language = 1 death_msg = "expires with a pitiful chirrup..." - universal_understand = 1 + universal_understand = 0 universal_speak = 0 // Dionaea do not need to speak to people other than other dionaea. can_pull_size = ITEMSIZE_SMALL @@ -22,6 +24,8 @@ ..() species = all_species["Diona"] + add_language(LANGUAGE_ROOTGLOBAL) + add_language(LANGUAGE_GALCOM) verbs += /mob/living/carbon/alien/diona/proc/merge /mob/living/carbon/alien/diona/put_in_hands(var/obj/item/W) // No hands. diff --git a/code/modules/mob/living/carbon/alien/progression.dm b/code/modules/mob/living/carbon/alien/progression.dm index 371058511b..4a22c34c6d 100644 --- a/code/modules/mob/living/carbon/alien/progression.dm +++ b/code/modules/mob/living/carbon/alien/progression.dm @@ -28,6 +28,8 @@ adult.set_species(new_species) show_evolution_blurb() + transfer_languages(src, adult) + if(mind) mind.transfer_to(adult) if (can_namepick_as_adult) diff --git a/code/modules/mob/living/carbon/alien/say.dm b/code/modules/mob/living/carbon/alien/say.dm index 28ae01391f..b92b5dc06d 100644 --- a/code/modules/mob/living/carbon/alien/say.dm +++ b/code/modules/mob/living/carbon/alien/say.dm @@ -17,9 +17,6 @@ var/datum/language/speaking = parse_language(message) - if(speaking) - message = copytext(message, 2+length(speaking.key)) - message = trim(message) if(!message || stat) diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index 27cdc59d80..8060e328ee 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -177,7 +177,7 @@ /obj/item/device/mmi/digital/New() src.brainmob = new(src) src.brainmob.add_language("Robot Talk") - src.brainmob.add_language("Encoded Audio Language") + src.brainmob.add_language(LANGUAGE_EAL) src.brainmob.loc = src src.brainmob.container = src src.brainmob.stat = 0 diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 5ca686cae3..b0110137f1 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -4,6 +4,8 @@ ingested = new/datum/reagents/metabolism(1000, src, CHEM_INGEST) touching = new/datum/reagents/metabolism(1000, src, CHEM_TOUCH) reagents = bloodstr + if (!default_language && species_language) + default_language = all_languages[species_language] ..() /mob/living/carbon/Life() diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 1c50cf498b..fccf6afbf6 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -22,12 +22,13 @@ // Should this all be in Touch()? if(istype(H)) - var/hit_zone = get_zone_with_miss_chance(H.zone_sel.selecting, src, get_accuracy_penalty(H)) - if(!hit_zone) - H.do_attack_animation(src) - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("\red [H] attempts to punch [src], but misses!") - return 0 + if(get_accuracy_penalty(H)) //Should only trigger if they're not aiming well + var/hit_zone = get_zone_with_miss_chance(H.zone_sel.selecting, src, get_accuracy_penalty(H)) + if(!hit_zone) + H.do_attack_animation(src) + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + visible_message("\red [H] reaches for [src], but misses!") + return 0 if(H != src && check_shields(0, null, H, H.zone_sel.selecting, H.name)) H.do_attack_animation(src) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 7682f675b0..67561125f1 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -90,6 +90,54 @@ return 0 +/mob/living/carbon/human + var/next_sonar_ping = 0 + +/mob/living/carbon/human/proc/sonar_ping() + set name = "Listen In" + set desc = "Allows you to listen in to movement and noises around you." + set category = "Abilities" + + if(incapacitated()) + src << "You need to recover before you can use this ability." + return + if(world.time < next_sonar_ping) + src << "You need another moment to focus." + return + if(is_deaf() || is_below_sound_pressure(get_turf(src))) + src << "You are for all intents and purposes currently deaf!" + return + next_sonar_ping += 10 SECONDS + var/heard_something = FALSE + src << "You take a moment to listen in to your environment..." + for(var/mob/living/L in range(client.view, src)) + var/turf/T = get_turf(L) + if(!T || L == src || L.stat == DEAD || is_below_sound_pressure(T)) + continue + heard_something = TRUE + var/feedback = list() + feedback += "There are noises of movement " + var/direction = get_dir(src, L) + if(direction) + feedback += "towards the [dir2text(direction)], " + switch(get_dist(src, L) / client.view) + if(0 to 0.2) + feedback += "very close by." + if(0.2 to 0.4) + feedback += "close by." + if(0.4 to 0.6) + feedback += "some distance away." + if(0.6 to 0.8) + feedback += "further away." + else + feedback += "far away." + else // No need to check distance if they're standing right on-top of us + feedback += "right on top of you." + feedback += "" + src << jointext(feedback,null) + if(!heard_something) + src << "You hear no movement but your own." + #undef HUMAN_EATING_NO_ISSUE #undef HUMAN_EATING_NO_MOUTH #undef HUMAN_EATING_BLOCKED_MOUTH diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index 948f338297..7a27e3c341 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -114,11 +114,15 @@ set name = "Split" set desc = "Split your humanoid form into its constituent nymphs." set category = "Abilities" + diona_split_into_nymphs(5) // Separate proc to void argments being supplied when used as a verb +/mob/living/carbon/human/proc/diona_split_into_nymphs(var/number_of_resulting_nymphs) var/turf/T = get_turf(src) var/mob/living/carbon/alien/diona/S = new(T) S.set_dir(dir) + transfer_languages(src, S) + if(mind) mind.transfer_to(S) @@ -129,12 +133,14 @@ for(var/mob/living/carbon/alien/diona/D in src) nymphs++ - D.loc = T + D.forceMove(T) + transfer_languages(src, D, WHITELISTED|RESTRICTED) D.set_dir(pick(NORTH, SOUTH, EAST, WEST)) - if(nymphs < 5) - for(var/i in nymphs to 4) + if(nymphs < number_of_resulting_nymphs) + for(var/i in nymphs to (number_of_resulting_nymphs - 1)) var/mob/M = new /mob/living/carbon/alien/diona(T) + transfer_languages(src, M, WHITELISTED|RESTRICTED) M.set_dir(pick(NORTH, SOUTH, EAST, WEST)) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 42ec14d46b..7b53d86214 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -40,13 +40,13 @@ var/max_age = 70 // Language/culture vars. - var/default_language = "Galactic Common" // Default language is used when 'say' is used without modifiers. - var/language = "Galactic Common" // Default racial language, if any. + var/default_language = LANGUAGE_GALCOM // Default language is used when 'say' is used without modifiers. + var/language = LANGUAGE_GALCOM // Default racial language, if any. var/list/secondary_langs = list() // The names of secondary languages that are available to this species. var/list/speech_sounds // A list of sounds to potentially play when speaking. var/list/speech_chance // The likelihood of a speech sound playing. var/num_alternate_languages = 0 // How many secondary languages are available to select at character creation - var/name_language = "Galactic Common" // The language to use when determining names for this species, or null to use the first name/last name generator + var/name_language = LANGUAGE_GALCOM // The language to use when determining names for this species, or null to use the first name/last name generator // Combat vars. var/total_health = 100 // Point at which the mob will enter crit. diff --git a/code/modules/mob/living/carbon/human/species/station/seromi.dm b/code/modules/mob/living/carbon/human/species/station/seromi.dm index 9316eaecad..df2bbd8cc8 100644 --- a/code/modules/mob/living/carbon/human/species/station/seromi.dm +++ b/code/modules/mob/living/carbon/human/species/station/seromi.dm @@ -7,8 +7,8 @@ are only recently becoming known on human stations after reaching space with Skrell assistance." num_alternate_languages = 3 - secondary_langs = list("Schechi", "Skrellian") - name_language = "Schechi" + secondary_langs = list(LANGUAGE_SCHECHI, LANGUAGE_SKRELLIAN) + name_language = LANGUAGE_SCHECHI min_age = 12 max_age = 45 health_hud_intensity = 3 @@ -31,8 +31,9 @@ brute_mod = 1.35 burn_mod = 1.35 mob_size = MOB_SMALL + pass_flags = PASSTABLE holder_type = /obj/item/weapon/holder/human - short_sighted = 1 +// short_sighted = 1 gluttonous = 1 blood_volume = 400 hunger_factor = 0.2 @@ -84,40 +85,13 @@ /datum/unarmed_attack/claws, /datum/unarmed_attack/stomp/weak ) -/* - var/shock_cap = 30 - var/hallucination_cap = 25 -// I'm... so... ronrery, so ronery... -/datum/species/teshari/handle_environment_special(var/mob/living/carbon/human/H) - - // If they're dead or unconcious they're a bit beyond this kind of thing. - if(H.stat) - return - - // No point processing if we're already stressing the hell out. - if(H.hallucination >= hallucination_cap && H.shock_stage >= shock_cap) - return - - // Check for company. - for(var/mob/living/M in viewers(H)) - if(M == H || M.stat == DEAD || M.invisibility > H.see_invisible) - continue - if(M.faction == "neutral" || M.faction == H.faction) - return - - // No company? Suffer :( - if(H.shock_stage < shock_cap) - H.shock_stage += 1 - if(H.shock_stage >= shock_cap && H.hallucination < hallucination_cap) - H.hallucination += 2.5 -*/ -/datum/species/teshari/get_vision_flags(var/mob/living/carbon/human/H) - if(!(H.sdisabilities & DEAF) && !H.ear_deaf) - return SEE_SELF|SEE_MOBS - else - return SEE_SELF + inherent_verbs = list( + /mob/living/carbon/human/proc/sonar_ping, + /mob/living/proc/hide + ) /datum/species/teshari/equip_survival_gear(var/mob/living/carbon/human/H) ..() H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H),slot_shoes) + diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index 6393ef4720..d68a399f7f 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -9,7 +9,7 @@ interests, rampant cyber and bio-augmentation and secretive factions make life on most human \ worlds tumultous at best." num_alternate_languages = 3 - secondary_langs = list("Sol Common") + secondary_langs = list(LANGUAGE_SOL_COMMON) name_language = null // Use the first-name last-name generator rather than a language scrambler min_age = 17 max_age = 110 @@ -35,8 +35,8 @@ slowdown = 0.5 brute_mod = 0.8 num_alternate_languages = 3 - secondary_langs = list("Sinta'unathi") - name_language = "Sinta'unathi" + secondary_langs = list(LANGUAGE_UNATHI) + name_language = LANGUAGE_UNATHI health_hud_intensity = 2.5 min_age = 18 @@ -94,10 +94,11 @@ slowdown = -0.5 brute_mod = 1.15 burn_mod = 1.15 + metabolic_rate = 1.1 gluttonous = 1 num_alternate_languages = 3 - secondary_langs = list("Siik") - name_language = "Siik" + secondary_langs = list(LANGUAGE_SIIK) + name_language = LANGUAGE_SIIK health_hud_intensity = 2.5 min_age = 17 @@ -152,8 +153,8 @@ herbivores on the whole and tend to be co-operative with the other species of the galaxy, although they rarely reveal \ the secrets of their empire to their allies." num_alternate_languages = 3 - secondary_langs = list("Skrellian", "Schechi") - name_language = "Skrellian" + secondary_langs = list(LANGUAGE_SKRELLIAN, LANGUAGE_SCHECHI) + name_language = LANGUAGE_SKRELLIAN health_hud_intensity = 2 min_age = 19 @@ -197,7 +198,7 @@ name_plural = "Dionaea" icobase = 'icons/mob/human_races/r_diona.dmi' deform = 'icons/mob/human_races/r_def_plant.dmi' - language = "Rootspeak" + language = LANGUAGE_ROOTLOCAL unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/diona) //primitive_form = "Nymph" slowdown = 5 @@ -206,7 +207,8 @@ siemens_coefficient = 0.3 show_ssd = "completely quiescent" num_alternate_languages = 2 - name_language = "Rootspeak" + secondary_langs = list(LANGUAGE_ROOTGLOBAL) + name_language = LANGUAGE_ROOTLOCAL health_hud_intensity = 2.5 min_age = 1 diff --git a/code/modules/mob/living/default_language.dm b/code/modules/mob/living/default_language.dm index 5204fb879b..b9eae4b5a1 100644 --- a/code/modules/mob/living/default_language.dm +++ b/code/modules/mob/living/default_language.dm @@ -5,11 +5,18 @@ set name = "Set Default Language" set category = "IC" - if(language && !can_speak(language)) - src << "You are unable to speak that language." - return + if (only_species_language && language != all_languages[src.species_language]) + to_chat(src, "You can only speak your species language, [src.species_language].") + return 0 + + if(language == all_languages[src.species_language]) + to_chat(src, "You will now speak your standard default language, [language], if you do not specify a language when speaking.") + else if (language) + + if(language && !can_speak(language)) + to_chat(src, "You are unable to speak that language.") + return - if(language) src << "You will now speak [language] if you do not specify a language when speaking." else src << "You will now speak whatever your standard default language is if you do not specify one when speaking." diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index ed6ae3358c..c7856f5082 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -131,6 +131,7 @@ proc/get_radio_key_from_channel(var/channel) /mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/whispering = 0) //If you're muted for IC chat if(client) + client.handle_spam_prevention(MUTE_IC) if((client.prefs.muted & MUTE_IC) || say_disabled) src << "You cannot speak in IC (Muted)." return diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index fd38776dd5..2ef6e62c9d 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -148,15 +148,16 @@ var/list/ai_verbs_hidden = list( // For why this exists, refer to https://xkcd.c //Languages add_language("Robot Talk", 1) - add_language("Galactic Common", 1) - add_language("Sol Common", 0) - add_language("Sinta'unathi", 0) - add_language("Siik", 0) - add_language("Skrellian", 0) - add_language("Tradeband", 1) - add_language("Gutter", 0) - add_language("Encoded Audio Language", 1) - add_language("Schechi", 0) + add_language(LANGUAGE_GALCOM, 1) + add_language(LANGUAGE_SOL_COMMON, 0) + add_language(LANGUAGE_UNATHI, 0) + add_language(LANGUAGE_SIIK, 0) + add_language(LANGUAGE_SKRELLIAN, 0) + add_language(LANGUAGE_TRADEBAND, 1) + add_language(LANGUAGE_GUTTER, 0) + add_language(LANGUAGE_EAL, 1) + add_language(LANGUAGE_SCHECHI, 0) + add_language(LANGUAGE_SIGN, 0) if(!safety)//Only used by AIize() to successfully spawn an AI. if (!B)//If there is no player/brain inside. diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 57a9dd837b..7ba76ecfb5 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -89,10 +89,11 @@ radio = card.radio //Default languages without universal translator software - add_language("Sol Common", 1) - add_language("Tradeband", 1) - add_language("Gutter", 1) - add_language("Encoded Audio Language", 1) + add_language(LANGUAGE_SOL_COMMON, 1) + add_language(LANGUAGE_TRADEBAND, 1) + add_language(LANGUAGE_GUTTER, 1) + add_language(LANGUAGE_EAL, 1) + add_language(LANGUAGE_SIGN, 0) verbs += /mob/living/silicon/pai/proc/choose_chassis verbs += /mob/living/silicon/pai/proc/choose_verbs diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index 1b11e4e984..83f68056b7 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -468,13 +468,15 @@ // Sol Common, Tradeband and Gutter are added with New() and are therefore the current default, always active languages user.translator_on = !user.translator_on if(user.translator_on) - user.add_language("Sinta'unathi") - user.add_language("Siik") - user.add_language("Skrellian") + user.add_language(LANGUAGE_UNATHI) + user.add_language(LANGUAGE_SIIK) + user.add_language(LANGUAGE_SKRELLIAN) + user.add_language(LANGUAGE_SCHECHI) else - user.remove_language("Sinta'unathi") - user.remove_language("Siik") - user.remove_language("Skrellian") + user.remove_language(LANGUAGE_UNATHI) + user.remove_language(LANGUAGE_SIIK) + user.remove_language(LANGUAGE_SKRELLIAN) + user.remove_language(LANGUAGE_SCHECHI) is_active(mob/living/silicon/pai/user) return user.translator_on diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 27a98d5d01..1059e270a4 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -99,7 +99,7 @@ spark_system.attach(src) add_language("Robot Talk", 1) - add_language("Encoded Audio Language", 1) + add_language(LANGUAGE_EAL, 1) wires = new(src) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 45af995df8..e4b4ff9427 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -23,7 +23,7 @@ var/global/list/robot_modules = list( var/hide_on_manifest = 0 var/channels = list() var/networks = list() - var/languages = list(LANGUAGE_SOL_COMMON = 1, LANGUAGE_TRADEBAND = 1, LANGUAGE_UNATHI = 0, LANGUAGE_SIIK = 0, LANGUAGE_SKRELLIAN = 0, LANGUAGE_GUTTER = 0, LANGUAGE_SCHECHI = 0) + var/languages = list(LANGUAGE_SOL_COMMON = 1, LANGUAGE_TRADEBAND = 1, LANGUAGE_UNATHI = 0, LANGUAGE_SIIK = 0, LANGUAGE_SKRELLIAN = 0, LANGUAGE_GUTTER = 0, LANGUAGE_SCHECHI = 0, LANGUAGE_SIGN = 0) var/sprites = list() var/can_be_pushed = 1 var/no_slip = 0 @@ -478,10 +478,12 @@ var/global/list/robot_modules = list( LANGUAGE_UNATHI = 1, LANGUAGE_SIIK = 1, LANGUAGE_SKRELLIAN = 1, - LANGUAGE_ROOTSPEAK = 1, + LANGUAGE_ROOTLOCAL = 0, LANGUAGE_TRADEBAND = 1, LANGUAGE_GUTTER = 1, - LANGUAGE_SCHECHI = 1 + LANGUAGE_SCHECHI = 1, + LANGUAGE_EAL = 1, + LANGUAGE_SIGN = 0 ) /obj/item/weapon/robot_module/robot/clerical/butler @@ -631,9 +633,11 @@ var/global/list/robot_modules = list( LANGUAGE_UNATHI = 0, LANGUAGE_SIIK = 0, LANGUAGE_SKRELLIAN = 0, - LANGUAGE_ROOTSPEAK = 0, + LANGUAGE_ROOTLOCAL = 0, LANGUAGE_GUTTER = 1, - LANGUAGE_SCHECHI = 0 + LANGUAGE_SCHECHI = 0, + LANGUAGE_EAL = 1, + LANGUAGE_SIGN = 0 ) sprites = list( "Dread" = "securityrobot", diff --git a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm index fadfafc458..6ef066a257 100644 --- a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm +++ b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm @@ -43,8 +43,8 @@ /mob/living/simple_animal/spiderbot/New() ..() - add_language("Galactic Common") - default_language = all_languages["Galactic Common"] + add_language(LANGUAGE_GALCOM) + default_language = all_languages[LANGUAGE_GALCOM] verbs |= /mob/living/proc/ventcrawl verbs |= /mob/living/proc/hide diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index f774ce699a..030f9b8e6b 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -82,11 +82,12 @@ . = ..() if(ishuman(.)) var/mob/living/carbon/human/H = . - if(prob(poison_chance)) + if(prob(5)) var/obj/item/organ/external/O = pick(H.organs) if(!(O.robotic >= ORGAN_ROBOT)) var/eggs = PoolOrNew(/obj/effect/spider/eggcluster/, list(O, src)) O.implants += eggs + H << "The [src] injects something into your [O.name]!" /mob/living/simple_animal/hostile/giant_spider/Life() ..() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index aaea193734..7d969569d4 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -50,13 +50,13 @@ if(!client) return if (type) - if((type & 1) && ((sdisabilities & BLIND) || blinded || paralysis) )//Vision related + if((type & 1) && (is_blind() || paralysis) )//Vision related if (!( alt )) return else msg = alt type = alt_type - if ((type & 2) && ((sdisabilities & DEAF) || ear_deaf))//Hearing related + if ((type & 2) && is_deaf())//Hearing related if (!( alt )) return else @@ -154,6 +154,12 @@ return UNBUCKLED return restrained() ? FULLY_BUCKLED : PARTIALLY_BUCKLED +/mob/proc/is_blind() + return ((sdisabilities & BLIND) || blinded || incapacitated(INCAPACITATION_KNOCKOUT)) + +/mob/proc/is_deaf() + return ((sdisabilities & DEAF) || ear_deaf || incapacitated(INCAPACITATION_KNOCKOUT)) + /mob/proc/is_physically_disabled() return incapacitated(INCAPACITATION_DISABLED) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 47bbdcd3a6..6a5e39e961 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -90,6 +90,8 @@ var/list/pinned = list() // List of things pinning this creature to walls (see living_defense.dm) var/list/embedded = list() // Embedded items, since simple mobs don't have organs. var/list/languages = list() // For speaking/listening. + var/species_language = null // For species who want reset to use a specified default. + var/only_species_language = 0 // For species who can only speak their default and no other languages. Does not affect understanding. var/list/speak_emote = list("says") // Verbs used when speaking. Defaults to 'say' if speak_emote is null. var/emote_type = 1 // Define emote default type, 1 for seen emotes, 2 for heard emotes var/facing_dir = null // Used for the ancient art of moonwalking. diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 76226220b4..066fd5b0a4 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -60,6 +60,11 @@ else output += "

Show Player Polls

" + if(client.check_for_new_server_news()) + output += "

Show News (NEW!)

" + else + output += "

Show News

" + output += "" panel = new(src, "Welcome","Welcome", 210, 280, src) @@ -277,6 +282,29 @@ if(!isnull(href_list["option_[optionid]"])) //Test if this optionid was selected vote_on_poll(pollid, optionid, 1) + if(href_list["shownews"]) + handle_server_news() + return + +/mob/new_player/proc/handle_server_news() + if(!client) + return + var/savefile/F = get_server_news() + if(F) + client.prefs.lastnews = md5(F["body"]) + client.prefs.save_preferences() + + var/dat = "
" + dat += "

[F["title"]]

" + dat += "
" + dat += "[F["body"]]" + dat += "
" + dat += "Last written by [F["author"]], on [F["timestamp"]]." + dat += "
" + var/datum/browser/popup = new(src, "Server News", "Server News", 450, 300, src) + popup.set_content(dat) + popup.open() + /mob/new_player/proc/IsJobAvailable(rank) var/datum/job/job = job_master.GetJob(rank) if(!job) return 0 diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 4845dfb0e7..9e2cdf02e0 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -61,51 +61,6 @@ name = "Short Hair 2" icon_state = "hair_shorthair3" - teshari - name = "Teshari Default" - icon_state = "seromi_default" - species_allowed = list("Teshari") - - teshari_altdefault - name = "Teshari Alt. Default" - icon_state = "seromi_ears" - species_allowed = list("Teshari") - - teshari_tight - name = "Teshari Tight" - icon_state = "seromi_tight" - species_allowed = list("Teshari") - - teshari_excited - name = "Teshari Spiky" - icon_state = "seromi_spiky" - species_allowed = list("Teshari") - - teshari_spike - name = "Teshari Spike" - icon_state = "seromi_spike" - species_allowed = list("Teshari") - - teshari_long - name = "Teshari Overgrown" - icon_state = "seromi_long" - species_allowed = list("Teshari") - - teshari_burst - name = "Teshari Starburst" - icon_state = "seromi_burst" - species_allowed = list("Teshari") - - teshari_shortburst - name = "Teshari Short Starburst" - icon_state = "seromi_burst_short" - species_allowed = list("Teshari") - - teshari_mohawk - name = "Teshari Mohawk" - icon_state = "seromi_mohawk" - species_allowed = list("Teshari") - cut name = "Cut Hair" icon_state = "hair_c" @@ -328,6 +283,10 @@ name = "Emo" icon_state = "hair_emo" + emo2 + name = "Emo Alt" + icon_state = "hair_emo2" + longemo name = "Long Emo" icon_state = "hair_emolong" @@ -522,6 +481,60 @@ name = "Oxton" icon_state = "hair_oxton" + lowfade + name = "Low Fade" + icon_state = "hair_lowfade" + gender = MALE + + medfade + name = "Medium Fade" + icon_state = "hair_medfade" + + highfade + name = "High Fade" + icon_state = "hair_highfade" + gender = MALE + + baldfade + name = "Balding Fade" + icon_state = "hair_baldfade" + gender = MALE + + nofade + name = "Regulation Cut" + icon_state = "hair_nofade" + gender = MALE + + trimflat + name = "Trimmed Flat Top" + icon_state = "hair_trimflat" + gender = MALE + + trimmed + name = "Trimmed" + icon_state = "hair_trimmed" + gender = MALE + + tightbun + name = "Tight Bun" + icon_state = "hair_tightbun" + gender = FEMALE + + coffeehouse + name = "Coffee House Cut" + icon_state = "hair_coffeehouse" + gender = MALE + + undercut + name = "Undercut" + icon_state = "hair_undercut" + gender = MALE + + partfade + name = "Parted Fade" + icon_state = "hair_shavedpart" + gender = MALE + /* /////////////////////////////////// @@ -542,24 +555,6 @@ gender = NEUTER species_allowed = list("Human","Unathi","Tajara","Skrell", "Machine","Teshari", "Vox") - teshari_beard - name = "Teshari Beard" - icon_state = "seromi_chin" - species_allowed = list("Teshari") - gender = NEUTER - - teshari_scraggly - name = "Teshari Scraggly" - icon_state = "seromi_scraggly" - species_allowed = list("Teshari") - gender = NEUTER - - teshari_chops - name = "Teshari Chops" - icon_state = "seromi_gap" - species_allowed = list("Teshari") - gender = NEUTER - watson name = "Watson Mustache" icon_state = "facial_watson" @@ -629,31 +624,41 @@ name = "Dwarf Beard" icon_state = "facial_dwarf" - shadow - name = "Five O'Clock Shadow" - icon_state = "facial_shadow" + threeOclock + name = "3 O'clock Shadow" + icon_state = "facial_3oclock" -//unathi horn beards and the like + threeOclockstache + name = "3 O'clock Shadow and Moustache" + icon_state = "facial_3oclockmoustache" - una_chinhorn - name = "Unathi Chin Horn" - icon_state = "facial_chinhorns" - species_allowed = list("Unathi") + fiveOclock + name = "5 O'clock Shadow" + icon_state = "facial_5oclock" - una_hornadorns - name = "Unathi Horn Adorns" - icon_state = "facial_hornadorns" - species_allowed = list("Unathi") + fiveOclockstache + name = "5 O'clock Shadow and Moustache" + icon_state = "facial_5oclockmoustache" - una_spinespikes - name = "Unathi Spine Spikes" - icon_state = "facial_spikes" - species_allowed = list("Unathi") + sevenOclock + name = "7 O'clock Shadow" + icon_state = "facial_7oclock" - una_dorsalfrill - name = "Unathi Dorsal Frill" - icon_state = "facial_dorsalfrill" - species_allowed = list("Unathi") + sevenOclockstache + name = "7 O'clock Shadow and Moustache" + icon_state = "facial_7oclockmoustache" + + mutton + name = "Mutton Chops" + icon_state = "facial_mutton" + + muttonstache + name = "Mutton Chops and Moustache" + icon_state = "facial_muttonmus" + + walrus + name = "Walrus Moustache" + icon_state = "facial_walrus" /* /////////////////////////////////// @@ -709,6 +714,7 @@ icon_state = "unathi_sidefrills" species_allowed = list("Unathi") +//Skrell 'hairstyles' skr_tentacle_m name = "Skrell Male Tentacles" icon_state = "skrell_hair_m" @@ -721,6 +727,7 @@ species_allowed = list("Skrell") gender = FEMALE +//Tajaran hairstyles taj_ears name = "Tajaran Ears" icon_state = "ears_plain" @@ -806,6 +813,77 @@ icon_state = "hair_fingerwave" species_allowed = list("Tajara") +//Teshari things + teshari + name = "Teshari Default" + icon_state = "teshari_default" + species_allowed = list("Teshari") + + teshari_altdefault + name = "Teshari Alt. Default" + icon_state = "teshari_ears" + species_allowed = list("Teshari") + + teshari_tight + name = "Teshari Tight" + icon_state = "teshari_tight" + species_allowed = list("Teshari") + + teshari_excited + name = "Teshari Spiky" + icon_state = "teshari_spiky" + species_allowed = list("Teshari") + + teshari_spike + name = "Teshari Spike" + icon_state = "teshari_spike" + species_allowed = list("Teshari") + + teshari_long + name = "Teshari Overgrown" + icon_state = "teshari_long" + species_allowed = list("Teshari") + + teshari_burst + name = "Teshari Starburst" + icon_state = "teshari_burst" + species_allowed = list("Teshari") + + teshari_shortburst + name = "Teshari Short Starburst" + icon_state = "teshari_burst_short" + species_allowed = list("Teshari") + + teshari_mohawk + name = "Teshari Mohawk" + icon_state = "teshari_mohawk" + species_allowed = list("Teshari") + + teshari_pointy + name = "Teshari Pointy" + icon_state = "teshari_pointy" + species_allowed = list("Teshari") + + teshari_upright + name = "Teshari Upright" + icon_state = "teshari_upright" + species_allowed = list("Teshari") + + teshari_mane + name = "Teshari Mane" + icon_state = "teshari_mane" + species_allowed = list("Teshari") + + teshari_droopy + name = "Teshari Droopy" + icon_state = "teshari_droopy" + species_allowed = list("Teshari") + + teshari_mushroom + name = "Teshari Mushroom" + icon_state = "teshari_mushroom" + species_allowed = list("Teshari") + vox_quills_short name = "Short Vox Quills" icon_state = "vox_shortquills" @@ -853,6 +931,48 @@ icon_state = "facial_smallstache" species_allowed = list("Tajara") +//unathi horn beards and the like + + una_chinhorn + name = "Unathi Chin Horn" + icon_state = "facial_chinhorns" + species_allowed = list("Unathi") + + una_hornadorns + name = "Unathi Horn Adorns" + icon_state = "facial_hornadorns" + species_allowed = list("Unathi") + + una_spinespikes + name = "Unathi Spine Spikes" + icon_state = "facial_spikes" + species_allowed = list("Unathi") + + una_dorsalfrill + name = "Unathi Dorsal Frill" + icon_state = "facial_dorsalfrill" + species_allowed = list("Unathi") + + +//Teshari things + teshari_beard + name = "Teshari Beard" + icon_state = "teshari_chin" + species_allowed = list("Teshari") + gender = NEUTER + + teshari_scraggly + name = "Teshari Scraggly" + icon_state = "teshari_scraggly" + species_allowed = list("Teshari") + gender = NEUTER + + teshari_chops + name = "Teshari Chops" + icon_state = "teshari_gap" + species_allowed = list("Teshari") + gender = NEUTER + //skin styles - WIP //going to have to re-integrate this with surgery //let the icon_state hold an icon preview for now diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index b41c1b090b..41e8c9a53d 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -55,3 +55,14 @@ force = 10 matter = list(DEFAULT_WALL_MATERIAL = 200000) projectile_type = /obj/item/projectile/energy/bolt/large + +/obj/item/weapon/gun/energy/plasmastun + name = "plasma pulse projector" + desc = "The Mars Military Industries MA21 Selkie is a weapon that uses a laser pulse to ionise the local atmosphere, creating a disorienting pulse of plasma and deafening shockwave as the wave expands." + icon_state = "plasma_stun" + item_state = "plasma_stun" + fire_sound = 'sound/weapons/blaster.ogg' + origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2, TECH_POWER = 3) + fire_delay = 20 + charge_cost = 600 + projectile_type = /obj/item/projectile/energy/plasmastun \ No newline at end of file diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 484c1e0163..750164a260 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -65,6 +65,8 @@ var/tracer_type var/impact_type + var/vacuum_traversal = 1 //Determines if the projectile can exist in vacuum, if false, the projectile will be deleted if it enters vacuum. + var/datum/plot_vector/trajectory // used to plot the path of the projectile var/datum/vector_loc/location // current location of the projectile in pixel space var/matrix/effect_transform // matrix to rotate and scale projectile effects - putting it here so it doesn't @@ -300,6 +302,10 @@ qdel(src) // if it's left the world... kill it return + if (is_below_sound_pressure(get_turf(src)) && !vacuum_traversal) //Deletes projectiles that aren't supposed to bein vacuum if they leave pressurised areas + qdel(src) + return + before_move() Move(location.return_turf()) diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index 3eb848c733..c45ea1917b 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -33,7 +33,7 @@ H.confused = max(H.confused, flash_strength + 5) H.eye_blind = max(H.eye_blind, flash_strength) H.eye_blurry = max(H.eye_blurry, flash_strength + 5) - + H.adjustHalLoss(22 * (flash_strength / 5)) // Five flashes to stun. Bit weaker than melee flashes due to being ranged. //snap pop playsound(src, 'sound/effects/snap.ogg', 50, 1) @@ -133,3 +133,42 @@ light_range = 2 light_power = 0.5 light_color = "#33CC00" + +/obj/item/projectile/energy/plasmastun + name = "plasma pulse" + icon_state = "plasma_stun" + armor_penetration = 10 + kill_count = 4 + damage = 5 + agony = 70 + damage_type = BURN + vacuum_traversal = 0 //Projectile disappears in empty space + +/obj/item/projectile/energy/plasmastun/proc/bang(var/mob/living/carbon/M) + + to_chat(M, "You hear a loud roar.") + playsound(M.loc, 'sound/effects/bang.ogg', 50, 1) + var/ear_safety = 0 + ear_safety = M.get_ear_protection() + if(ear_safety == 1) + M.Weaken(2) + else if (ear_safety > 1) + M.Weaken(1) + else if (!ear_safety) + M.Stun(10) + M.Weaken(3) + M.ear_damage += rand(1, 10) + M.ear_deaf = max(M.ear_deaf,15) + if (M.ear_damage >= 15) + to_chat(M, "Your ears start to ring badly!") + if (prob(M.ear_damage - 5)) + to_chat(M, "You can't hear anything!") + M.sdisabilities |= DEAF + else + if (M.ear_damage >= 5) + to_chat(M, "Your ears start to ring!") + M.update_icons() + +/obj/item/projectile/energy/plasmastun/on_hit(var/atom/target) + bang(target) + . = ..() \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index 57b62e609d..c2b4157ff3 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -323,13 +323,13 @@ // This does not handle transferring reagents to things. // For example, splashing someone with water will get them wet and extinguish them if they are on fire, // even if they are wearing an impermeable suit that prevents the reagents from contacting the skin. -/datum/reagents/proc/touch(var/atom/target) +/datum/reagents/proc/touch(var/atom/target, var/amount) if(ismob(target)) - touch_mob(target) + touch_mob(target, amount) if(isturf(target)) - touch_turf(target) + touch_turf(target, amount) if(isobj(target)) - touch_obj(target) + touch_obj(target, amount) return /datum/reagents/proc/touch_mob(var/mob/target) @@ -341,21 +341,21 @@ update_total() -/datum/reagents/proc/touch_turf(var/turf/target) +/datum/reagents/proc/touch_turf(var/turf/target, var/amount) if(!target || !istype(target)) return for(var/datum/reagent/current in reagent_list) - current.touch_turf(target, current.volume) + current.touch_turf(target, amount) update_total() -/datum/reagents/proc/touch_obj(var/obj/target) +/datum/reagents/proc/touch_obj(var/obj/target, var/amount) if(!target || !istype(target)) return for(var/datum/reagent/current in reagent_list) - current.touch_obj(target, current.volume) + current.touch_obj(target, amount) update_total() @@ -402,7 +402,7 @@ var/datum/reagents/R = new /datum/reagents(amount * multiplier) . = trans_to_holder(R, amount, multiplier, copy) - R.touch_turf(target) + R.touch_turf(target, amount) return /datum/reagents/proc/trans_to_obj(var/obj/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Objects may or may not; if they do, it's probably a beaker or something and we need to transfer properly; otherwise, just touch. @@ -412,7 +412,7 @@ if(!target.reagents) var/datum/reagents/R = new /datum/reagents(amount * multiplier) . = trans_to_holder(R, amount, multiplier, copy) - R.touch_obj(target) + R.touch_obj(target, amount) return return trans_to_holder(target.reagents, amount, multiplier, copy) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm index cf2f7f7968..27f40820e7 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm @@ -156,9 +156,9 @@ glass_name = "welder fuel" glass_desc = "Unless you are an industrial tool, this is probably not safe for consumption." -/datum/reagent/fuel/touch_turf(var/turf/T) - new /obj/effect/decal/cleanable/liquid_fuel(T, volume) - remove_self(volume) +/datum/reagent/fuel/touch_turf(var/turf/T, var/amount) + new /obj/effect/decal/cleanable/liquid_fuel(T, amount) + remove_self(amount) return /datum/reagent/fuel/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm index f67fffe651..94f433c55e 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm @@ -87,6 +87,8 @@ var/strength_mod = 1 if(alien == IS_SKRELL) strength_mod *= 5 + if(alien == IS_TAJARA) + strength_mod *= 1.75 if(alien == IS_DIONA) strength_mod = 0 diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm index 57a95b338f..eab46ba8a0 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm @@ -651,16 +651,25 @@ if(alien == IS_DIONA) return ..() - + if(alien == IS_TAJARA) + M.adjustToxLoss(0.5 * removed) + M.make_jittery(4) //extra sensitive to caffine if(adj_temp > 0) holder.remove_reagent("frostoil", 10 * removed) /datum/reagent/nutriment/coffee/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) ..() + if(alien == IS_TAJARA) + M.adjustToxLoss(2 * removed) + M.make_jittery(4) + return /datum/reagent/drink/coffee/overdose(var/mob/living/carbon/M, var/alien) if(alien == IS_DIONA) return + if(alien == IS_TAJARA) + M.adjustToxLoss(4 * REM) + M.apply_effect(3, STUTTER) M.make_jittery(5) /datum/reagent/drink/coffee/icecoffee @@ -1148,10 +1157,23 @@ M.sleeping = max(0, M.sleeping - 2) if(M.bodytemperature > 310) M.bodytemperature = max(310, M.bodytemperature - (5 * TEMPERATURE_DAMAGE_COEFFICIENT)) + if(alien == IS_TAJARA) + M.adjustToxLoss(0.5 * removed) + M.make_jittery(4) //extra sensitive to caffine + +/datum/reagent/ethanol/coffee/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + if(alien == IS_TAJARA) + M.adjustToxLoss(2 * removed) + M.make_jittery(4) + return + ..() /datum/reagent/ethanol/coffee/overdose(var/mob/living/carbon/M, var/alien) if(alien == IS_DIONA) return + if(alien == IS_TAJARA) + M.adjustToxLoss(4 * REM) + M.apply_effect(3, STUTTER) M.make_jittery(5) /datum/reagent/ethanol/coffee/kahlua diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm index 273589e493..bbaad03664 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm @@ -67,11 +67,11 @@ return ..() -/datum/reagent/toxin/phoron/touch_turf(var/turf/simulated/T) +/datum/reagent/toxin/phoron/touch_turf(var/turf/simulated/T, var/amount) if(!istype(T)) return - T.assume_gas("volatile_fuel", volume, T20C) - remove_self(volume) + T.assume_gas("volatile_fuel", amount, T20C) + remove_self(amount) /datum/reagent/toxin/cyanide //Fast and Lethal name = "Cyanide" @@ -97,6 +97,8 @@ strength = 2 /datum/reagent/toxin/hyperzine/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + if(alien == IS_TAJARA) + removed *= 1.25 ..() if(prob(5)) M.emote(pick("twitch", "blink_r", "shiver")) @@ -112,6 +114,8 @@ strength = 3 /datum/reagent/toxin/stimm/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + if(alien == IS_TAJARA) + removed *= 1.25 ..() if(prob(15)) M.emote(pick("twitch", "blink_r", "shiver")) @@ -220,17 +224,14 @@ W.visible_message("The fungi are completely dissolved by the solution!") /datum/reagent/toxin/plantbgone/touch_obj(var/obj/O, var/volume) - ..() if(istype(O, /obj/effect/plant)) qdel(O) /datum/reagent/toxin/plantbgone/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) - ..() if(alien == IS_DIONA) M.adjustToxLoss(50 * removed) /datum/reagent/toxin/plantbgone/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) - ..() if(alien == IS_DIONA) M.adjustToxLoss(50 * removed) diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index b2f6a9c447..8e91f3f06a 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -1557,6 +1557,7 @@ CIRCUITS BELOW req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3, TECH_POWER = 3) materials = list(DEFAULT_WALL_MATERIAL = 20000) build_path = /obj/item/device/electronic_assembly/medium + sort_string = "VCAAB" /datum/design/item/custom_circuit_assembly/drone name = "Drone custom assembly" @@ -1565,6 +1566,7 @@ CIRCUITS BELOW req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) materials = list(DEFAULT_WALL_MATERIAL = 30000) build_path = /obj/item/device/electronic_assembly/drone + sort_string = "VCAAC" /datum/design/item/custom_circuit_assembly/large name = "Large custom assembly" @@ -1573,6 +1575,16 @@ CIRCUITS BELOW req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 4) materials = list(DEFAULT_WALL_MATERIAL = 40000) build_path = /obj/item/device/electronic_assembly/large + sort_string = "VCAAD" + +/datum/design/item/custom_circuit_assembly/implant + name = "Implant custom assembly" + desc = "An customizable assembly for very small devices, implanted into living entities." + id = "assembly-implant" + req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 3, TECH_BIO = 5) + materials = list(DEFAULT_WALL_MATERIAL = 2000) + build_path = /obj/item/weapon/implant/integrated_circuit + sort_string = "VCAAE" /* Uncomment if someone makes these buildable /datum/design/circuit/general_alert diff --git a/code/modules/research/prosfab_designs.dm b/code/modules/research/prosfab_designs.dm index 43e933c00c..02a05eb64d 100644 --- a/code/modules/research/prosfab_designs.dm +++ b/code/modules/research/prosfab_designs.dm @@ -44,7 +44,7 @@ H.real_name = "Synthmorph #[rand(100,999)]" H.name = H.real_name H.dir = 2 - H.add_language("Encoded Audio Language") + H.add_language(LANGUAGE_EAL) return H //////////////////// Prosthetics //////////////////// diff --git a/code/modules/xenobio2/mob/slime/slime.dm b/code/modules/xenobio2/mob/slime/slime.dm index 65d4ad64d8..48f5ce5756 100644 --- a/code/modules/xenobio2/mob/slime/slime.dm +++ b/code/modules/xenobio2/mob/slime/slime.dm @@ -18,7 +18,7 @@ Slime definitions, Life and New live here. var/is_child = 1 var/cores = 3 var/growthcounter = 0 - var/growthpoint = 50 //At what point they grow up. + var/growthpoint = 25 //At what point they grow up. var/shiny = 0 move_to_delay = 17 //Slimes shouldn't be able to go faster than humans. default_chems = list("slimejelly" = 5) @@ -26,11 +26,11 @@ Slime definitions, Life and New live here. response_help = "pats" response_disarm = "tries to stop" response_harm = "hits" - + var/emote_on = null - + maleable = MAX_MALEABLE - + //Slimes can speak all of the languages, oh no! universal_speak = 1 speak_chance = 1 @@ -45,7 +45,7 @@ Slime definitions, Life and New live here. //Overlay information var/overlay = 1 // 1 = normal lighting, 0 = shiny, 2 = too shiny, -1 = no overlay - + chemreact = list( "nutriment" = list("nutr" = 0.5), "radium" = list("toxic" = 0.3, "mut" = 1), "mutagen" = list("nutr" = 0.4, "mut" = 2), @@ -79,7 +79,7 @@ Slime definitions, Life and New live here. "glycerol" = list("nutr" = 0.6), "woodpulp" = list("heal" = 0.1, "nutr" = 0.7), "docilitytoxin" = list("nutr" = 0.3) ) - + /mob/living/simple_animal/xeno/slime/New() ..() for(var/datum/language/L in (typesof(/datum/language) - /datum/language)) @@ -91,4 +91,3 @@ Slime definitions, Life and New live here. resistances[TOX] = 1.5 GenerateChild() return 1 - \ No newline at end of file diff --git a/code/stylesheet.dm b/code/stylesheet.dm index d42ac80b7c..32e69caea6 100644 --- a/code/stylesheet.dm +++ b/code/stylesheet.dm @@ -47,6 +47,7 @@ em {font-style: normal;font-weight: bold;} .syndradio {color: #6D3F40;} .centradio {color: #5C5C8A;} .airadio {color: #FF00FF;} +.entradio {color: #339966;} .secradio {color: #A30000;} .engradio {color: #A66300;} diff --git a/code/unit_tests/integrated_circuits/arithmetic.dm b/code/unit_tests/integrated_circuits/arithmetic.dm new file mode 100644 index 0000000000..1e62f6e7b7 --- /dev/null +++ b/code/unit_tests/integrated_circuits/arithmetic.dm @@ -0,0 +1,174 @@ +/datum/unit_test/integrated_circuits/additon_1 + name = "Arithmetic Circuits: Addition - Basic" + circuit_type = /obj/item/integrated_circuit/arithmetic/addition + inputs_to_give = list(25, 75) + expected_outputs = list(100) + +/datum/unit_test/integrated_circuits/additon_2 + name = "Arithmetic Circuits: Addition - Multiple" + circuit_type = /obj/item/integrated_circuit/arithmetic/addition + inputs_to_give = list(7, 5, 3, 26, 974, -51, 77, 0) + expected_outputs = list(1041) + + + +/datum/unit_test/integrated_circuits/subtraction_1 + name = "Arithmetic Circuits: Subtraction - Basic" + circuit_type = /obj/item/integrated_circuit/arithmetic/subtraction + inputs_to_give = list(20, 15) + expected_outputs = list(5) + +/datum/unit_test/integrated_circuits/subtraction_2 + name = "Arithmetic Circuits: Subtraction - Multiple" + circuit_type = /obj/item/integrated_circuit/arithmetic/subtraction + inputs_to_give = list(5, 50, 30) + expected_outputs = list(-75) + + + +/datum/unit_test/integrated_circuits/multiplication_1 + name = "Arithmetic Circuits: Multiplication - Basic" + circuit_type = /obj/item/integrated_circuit/arithmetic/multiplication + inputs_to_give = list(5, 20) + expected_outputs = list(100) + +/datum/unit_test/integrated_circuits/multiplication_2 + name = "Arithmetic Circuits: Multiplication - Multiple" + circuit_type = /obj/item/integrated_circuit/arithmetic/multiplication + inputs_to_give = list(2, 10, 20) + expected_outputs = list(400) + +/datum/unit_test/integrated_circuits/multiplication_3 + name = "Arithmetic Circuits: Multiplication - Decimal" + circuit_type = /obj/item/integrated_circuit/arithmetic/multiplication + inputs_to_give = list(100, 0.5) + expected_outputs = list(50) + + +/datum/unit_test/integrated_circuits/division_1 + name = "Arithmetic Circuits: Division - Basic" + circuit_type = /obj/item/integrated_circuit/arithmetic/division + inputs_to_give = list(100, 5) + expected_outputs = list(20) + +/datum/unit_test/integrated_circuits/division_2 + name = "Arithmetic Circuits: Division - Multiple" + circuit_type = /obj/item/integrated_circuit/arithmetic/division + inputs_to_give = list(500, 100, 10) + expected_outputs = list(0.5) + +/datum/unit_test/integrated_circuits/division_3 + name = "Arithmetic Circuits: Division - Decimal" + circuit_type = /obj/item/integrated_circuit/arithmetic/division + inputs_to_give = list(100, 0.5) + expected_outputs = list(200) + + + +/datum/unit_test/integrated_circuits/exponent_1 + name = "Arithmetic Circuits: Exponent - Basic" + circuit_type = /obj/item/integrated_circuit/arithmetic/exponent + inputs_to_give = list(20, 2) + expected_outputs = list(400) + +/datum/unit_test/integrated_circuits/exponent_2 + name = "Arithmetic Circuits: Exponent - Powers" + circuit_type = /obj/item/integrated_circuit/arithmetic/exponent + inputs_to_give = list(5, 4) + expected_outputs = list(625) + + + +/datum/unit_test/integrated_circuits/sign_1 + name = "Arithmetic Circuits: Sign - Positive" + circuit_type = /obj/item/integrated_circuit/arithmetic/sign + inputs_to_give = list(5) + expected_outputs = list(1) + +/datum/unit_test/integrated_circuits/sign_2 + name = "Arithmetic Circuits: Sign - Negative" + circuit_type = /obj/item/integrated_circuit/arithmetic/sign + inputs_to_give = list(-500) + expected_outputs = list(-1) + +/datum/unit_test/integrated_circuits/sign_3 + name = "Arithmetic Circuits: Sign - Zero" + circuit_type = /obj/item/integrated_circuit/arithmetic/sign + inputs_to_give = list(0) + expected_outputs = list(0) + + + +/datum/unit_test/integrated_circuits/round_1 + name = "Arithmetic Circuits: Round - Basic" + circuit_type = /obj/item/integrated_circuit/arithmetic/round + inputs_to_give = list(4.25) + expected_outputs = list(4) + +/datum/unit_test/integrated_circuits/round_2 + name = "Arithmetic Circuits: Round - Floor" + circuit_type = /obj/item/integrated_circuit/arithmetic/round + inputs_to_give = list(8.95) + expected_outputs = list(8) + +/datum/unit_test/integrated_circuits/round_3 + name = "Arithmetic Circuits: Round - Round to X" + circuit_type = /obj/item/integrated_circuit/arithmetic/round + inputs_to_give = list(45.68, 0.1) + expected_outputs = list(45.7) + + + +/datum/unit_test/integrated_circuits/absolute_1 + name = "Arithmetic Circuits: Absolute - Positive" + circuit_type = /obj/item/integrated_circuit/arithmetic/absolute + inputs_to_give = list(50) + expected_outputs = list(50) + +/datum/unit_test/integrated_circuits/absolute_2 + name = "Arithmetic Circuits: Absolute - Negative" + circuit_type = /obj/item/integrated_circuit/arithmetic/absolute + inputs_to_give = list(-20) + expected_outputs = list(20) + +/datum/unit_test/integrated_circuits/absolute_3 + name = "Arithmetic Circuits: Absolute - Zero" + circuit_type = /obj/item/integrated_circuit/arithmetic/absolute + inputs_to_give = list(0) + expected_outputs = list(0) + + + +/datum/unit_test/integrated_circuits/average_1 + name = "Arithmetic Circuits: Average - Basic" + circuit_type = /obj/item/integrated_circuit/arithmetic/average + inputs_to_give = list(8, 20, 14, 6) + expected_outputs = list(12) + +/datum/unit_test/integrated_circuits/average_2 + name = "Arithmetic Circuits: Average - Negatives" + circuit_type = /obj/item/integrated_circuit/arithmetic/average + inputs_to_give = list(30, -5, 8, -50, 4) + expected_outputs = list(-2.6) + + + +/datum/unit_test/integrated_circuits/square_root_1 + name = "Arithmetic Circuits: Square Root" + circuit_type = /obj/item/integrated_circuit/arithmetic/square_root + inputs_to_give = list(64) + expected_outputs = list(8) + + + +/datum/unit_test/integrated_circuits/modulo_1 + name = "Arithmetic Circuits: Modulo - 1" + circuit_type = /obj/item/integrated_circuit/arithmetic/modulo + inputs_to_give = list(8, 5) + expected_outputs = list(3) + +/datum/unit_test/integrated_circuits/modulo_2 + name = "Arithmetic Circuits: Modulo - 2" + circuit_type = /obj/item/integrated_circuit/arithmetic/modulo + inputs_to_give = list(20, 5) + expected_outputs = list(0) \ No newline at end of file diff --git a/code/unit_tests/integrated_circuits/circuits.dm b/code/unit_tests/integrated_circuits/circuits.dm new file mode 100644 index 0000000000..16fb2728de --- /dev/null +++ b/code/unit_tests/integrated_circuits/circuits.dm @@ -0,0 +1,73 @@ + +/datum/unit_test/integrated_circuits + name = "circuit template" + var/circuit_type = null + var/obj/item/integrated_circuit/IC = null + var/list/inputs_to_give = list() + var/list/expected_outputs = list() + +// Use this to set up. +/datum/unit_test/integrated_circuits/proc/arrange() + IC = new circuit_type(get_standard_turf()) // Make the circuit + IC.cooldown_per_use = 0 + +// Use this when finished to remove clutter for the next test. +/datum/unit_test/integrated_circuits/proc/clean_up() + qdel(IC) + +// Override this if needing special output (e.g. rounding to avoid floating point fun). +/datum/unit_test/integrated_circuits/proc/assess() + var/output_wrong = FALSE + var/i = 1 + for(var/datum/integrated_io/io in IC.outputs) + if(io.data != expected_outputs[i]) + log_bad("[io.name] did not match expected output of [expected_outputs[i]]. Output was [isnull(io.data) ? "NULL" : io.data].") + output_wrong = TRUE + i++ + return output_wrong + +// Useful when doing floating point fun. +/datum/unit_test/integrated_circuits/floor/assess() + var/output_wrong = FALSE + var/i = 1 + for(var/datum/integrated_io/io in IC.outputs) + if(round(io.data) != expected_outputs[i]) + log_bad("[io.name] did not match expected output of [expected_outputs[i]]. Output was [isnull(io.data) ? "NULL" : round(io.data)].") + output_wrong = TRUE + i++ + return output_wrong + +/datum/unit_test/integrated_circuits/start_test() + var/output_wrong = FALSE + if(!circuit_type) + fail("[name] did not supply a circuit_type path.") + return TRUE + try + // Arrange + arrange() + + var/i = 1 + for(var/input in inputs_to_give) + var/datum/integrated_io/io = IC.inputs[i] + io.write_data_to_pin(input) + i++ + + // Act + IC.do_work() + + output_wrong = assess() + + clean_up() + + catch(var/exception/e) + log_bad("[name] caught an exception: [e] on [e.file]:[e.line]") + output_wrong = TRUE + + // Assert + if(output_wrong) + fail("[name] failed.") + return TRUE + else + pass("[name] matched all expected outputs.") + return TRUE + diff --git a/code/unit_tests/integrated_circuits/converter.dm b/code/unit_tests/integrated_circuits/converter.dm new file mode 100644 index 0000000000..b2a414f4d8 --- /dev/null +++ b/code/unit_tests/integrated_circuits/converter.dm @@ -0,0 +1,52 @@ +/datum/unit_test/integrated_circuits/num2text + name = "Converter Circuits: Num2Text" + circuit_type = /obj/item/integrated_circuit/converter/num2text + inputs_to_give = list(10250) + expected_outputs = list("10250") + + + +/datum/unit_test/integrated_circuits/text2num + name = "Converter Circuits: Text2Num" + circuit_type = /obj/item/integrated_circuit/converter/text2num + inputs_to_give = list("2005") + expected_outputs = list(2005) + + + +/datum/unit_test/integrated_circuits/lowercase + name = "Converter Circuits: Lowercase" + circuit_type = /obj/item/integrated_circuit/converter/lowercase + inputs_to_give = list("Lorem ipsum...") + expected_outputs = list("lorem ipsum...") + + + +/datum/unit_test/integrated_circuits/uppercase + name = "Converter Circuits: Uppercase" + circuit_type = /obj/item/integrated_circuit/converter/uppercase + inputs_to_give = list("Lorem ipsum...") + expected_outputs = list("LOREM IPSUM...") + + + +/datum/unit_test/integrated_circuits/concatenatior + name = "Converter Circuits: Concatenatior" + circuit_type = /obj/item/integrated_circuit/converter/concatenatior + inputs_to_give = list("Lorem", " ", "ipsum", "...") + expected_outputs = list("Lorem ipsum...") + + + +/datum/unit_test/integrated_circuits/floor/radians2degrees + name = "Converter Circuits: Radians2Degrees" + circuit_type = /obj/item/integrated_circuit/converter/radians2degrees + inputs_to_give = list(1.57) + expected_outputs = list(89) // 89.95437 + + +/datum/unit_test/integrated_circuits/floor/degrees2radians + name = "Converter Circuits: Degrees2Radians" + circuit_type = /obj/item/integrated_circuit/converter/degrees2radians + inputs_to_give = list(90) + expected_outputs = list(1) // 1.570796 \ No newline at end of file diff --git a/code/unit_tests/integrated_circuits/data_transfer.dm b/code/unit_tests/integrated_circuits/data_transfer.dm new file mode 100644 index 0000000000..1d02e8f837 --- /dev/null +++ b/code/unit_tests/integrated_circuits/data_transfer.dm @@ -0,0 +1,17 @@ +/datum/unit_test/integrated_circuits/splitter + name = "Data Transfer Circuits: Splitter" + circuit_type = /obj/item/integrated_circuit/transfer/splitter + inputs_to_give = list("Test") + expected_outputs = list("Test", "Test") + +/datum/unit_test/integrated_circuits/splitter4 + name = "Data Transfer Circuits: Splitter 4" + circuit_type = /obj/item/integrated_circuit/transfer/splitter/medium + inputs_to_give = list("Test") + expected_outputs = list("Test", "Test", "Test", "Test") + +/datum/unit_test/integrated_circuits/splitter8 + name = "Data Transfer Circuits: Splitter 8" + circuit_type = /obj/item/integrated_circuit/transfer/splitter/large + inputs_to_give = list("Test") + expected_outputs = list("Test", "Test", "Test", "Test", "Test", "Test", "Test", "Test") \ No newline at end of file diff --git a/code/unit_tests/integrated_circuits/logic.dm b/code/unit_tests/integrated_circuits/logic.dm new file mode 100644 index 0000000000..314150f3b4 --- /dev/null +++ b/code/unit_tests/integrated_circuits/logic.dm @@ -0,0 +1,186 @@ +/datum/unit_test/integrated_circuits/equals_1 + name = "Logic Circuits: Equals - String True" + circuit_type = /obj/item/integrated_circuit/logic/binary/equals + inputs_to_give = list("Test", "Test") + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/equals_2 + name = "Logic Circuits: Equals - String False" + circuit_type = /obj/item/integrated_circuit/logic/binary/equals + inputs_to_give = list("Test", "Nope") + expected_outputs = list(FALSE) + +/datum/unit_test/integrated_circuits/equals_3 + name = "Logic Circuits: Equals - Number True" + circuit_type = /obj/item/integrated_circuit/logic/binary/equals + inputs_to_give = list(525, 525) + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/equals_4 + name = "Logic Circuits: Equals - Number False" + circuit_type = /obj/item/integrated_circuit/logic/binary/equals + inputs_to_give = list(1020, -580) + expected_outputs = list(FALSE) + +/datum/unit_test/integrated_circuits/equals_5 + name = "Logic Circuits: Equals - Null True" + circuit_type = /obj/item/integrated_circuit/logic/binary/equals + inputs_to_give = list(null, null) + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/equals_6 + name = "Logic Circuits: Equals - Ref True" + circuit_type = /obj/item/integrated_circuit/logic/binary/equals + inputs_to_give = list() + expected_outputs = list(TRUE) + var/obj/A = null + +/datum/unit_test/integrated_circuits/equals_6/arrange() + A = new(get_standard_turf()) + inputs_to_give = list(weakref(A), weakref(A)) + ..() + +/datum/unit_test/integrated_circuits/equals_6/clean_up() + qdel(A) + ..() + +/datum/unit_test/integrated_circuits/equals_7 + name = "Logic Circuits: Equals - Ref False" + circuit_type = /obj/item/integrated_circuit/logic/binary/equals + inputs_to_give = list() + expected_outputs = list(FALSE) + var/obj/A = null + var/obj/B = null + +/datum/unit_test/integrated_circuits/equals_7/arrange() + A = new(get_standard_turf()) + B = new(get_standard_turf()) + inputs_to_give = list(weakref(A), weakref(B)) + ..() + +/datum/unit_test/integrated_circuits/equals_7/clean_up() + qdel(A) + qdel(B) + ..() + + + +/datum/unit_test/integrated_circuits/and_1 + name = "Logic Circuits: And - True" + circuit_type = /obj/item/integrated_circuit/logic/binary/and + inputs_to_give = list("One", "Two") + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/and_2 + name = "Logic Circuits: And - False" + circuit_type = /obj/item/integrated_circuit/logic/binary/and + inputs_to_give = list("One", null) + expected_outputs = list(FALSE) + + + +/datum/unit_test/integrated_circuits/or_1 + name = "Logic Circuits: Or - True First" + circuit_type = /obj/item/integrated_circuit/logic/binary/or + inputs_to_give = list("One", null) + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/or_2 + name = "Logic Circuits: Or - True Second" + circuit_type = /obj/item/integrated_circuit/logic/binary/or + inputs_to_give = list(null, "Two") + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/or_3 + name = "Logic Circuits: Or - True Both" + circuit_type = /obj/item/integrated_circuit/logic/binary/or + inputs_to_give = list("One", "Two") + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/or_4 + name = "Logic Circuits: Or - False" + circuit_type = /obj/item/integrated_circuit/logic/binary/or + inputs_to_give = list(null, null) + expected_outputs = list(FALSE) + + + +/datum/unit_test/integrated_circuits/less_than_1 + name = "Logic Circuits: Less Than - True" + circuit_type = /obj/item/integrated_circuit/logic/binary/less_than + inputs_to_give = list(50, 100) + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/less_than_2 + name = "Logic Circuits: Less Than - False" + circuit_type = /obj/item/integrated_circuit/logic/binary/less_than + inputs_to_give = list(500, 50) + expected_outputs = list(FALSE) + + + +/datum/unit_test/integrated_circuits/less_than_or_equal_1 + name = "Logic Circuits: Less Than Or Equal - True 1" + circuit_type = /obj/item/integrated_circuit/logic/binary/less_than_or_equal + inputs_to_give = list(40, 50) + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/less_than_or_equal_2 + name = "Logic Circuits: Less Than Or Equal - True 2" + circuit_type = /obj/item/integrated_circuit/logic/binary/less_than_or_equal + inputs_to_give = list(40, 40) + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/less_than_or_equal_3 + name = "Logic Circuits: Less Than Or Equal - False" + circuit_type = /obj/item/integrated_circuit/logic/binary/less_than_or_equal + inputs_to_give = list(40, 30) + expected_outputs = list(FALSE) + + + +/datum/unit_test/integrated_circuits/greater_than_1 + name = "Logic Circuits: Greater Than - True" + circuit_type = /obj/item/integrated_circuit/logic/binary/greater_than + inputs_to_give = list(100, 50) + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/greater_than_2 + name = "Logic Circuits: Greater Than - False" + circuit_type = /obj/item/integrated_circuit/logic/binary/greater_than + inputs_to_give = list(25, 800) + expected_outputs = list(FALSE) + + + +/datum/unit_test/integrated_circuits/greater_than_or_equal_1 + name = "Logic Circuits: Greater Than Or Equal - True 1" + circuit_type = /obj/item/integrated_circuit/logic/binary/greater_than_or_equal + inputs_to_give = list(250, 30) + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/greater_than_or_equal_2 + name = "Logic Circuits: Greater Than Or Equal - True 2" + circuit_type = /obj/item/integrated_circuit/logic/binary/greater_than_or_equal + inputs_to_give = list(30, 30) + expected_outputs = list(TRUE) + +/datum/unit_test/integrated_circuits/greater_than_or_equal_3 + name = "Logic Circuits: Greater Than Or Equal - False" + circuit_type = /obj/item/integrated_circuit/logic/binary/greater_than_or_equal + inputs_to_give = list(-40, 100) + expected_outputs = list(FALSE) + + + +/datum/unit_test/integrated_circuits/not_1 + name = "Logic Circuits: Not - Invert to False" + circuit_type = /obj/item/integrated_circuit/logic/unary/not + inputs_to_give = list(1) + expected_outputs = list(0) + +/datum/unit_test/integrated_circuits/not_2 + name = "Logic Circuits: Not - Invert to True" + circuit_type = /obj/item/integrated_circuit/logic/unary/not + inputs_to_give = list(0) + expected_outputs = list(1) \ No newline at end of file diff --git a/code/unit_tests/integrated_circuits/prefabs.dm b/code/unit_tests/integrated_circuits/prefabs.dm new file mode 100644 index 0000000000..056c0d1568 --- /dev/null +++ b/code/unit_tests/integrated_circuits/prefabs.dm @@ -0,0 +1,55 @@ +/datum/unit_test/integrated_circuit_prefabs_shall_respect_complexity_and_size_contraints + name = "Integrated Circuit Prefabs Shall Respect Complexity and Size Constraints" + +/datum/unit_test/integrated_circuit_prefabs_shall_respect_complexity_and_size_contraints/start_test() + var/list/failed_prefabs = list() + for(var/prefab_type in subtypesof(/decl/prefab/ic_assembly)) + var/decl/prefab/ic_assembly/prefab = decls_repository.get_decl(prefab_type) + var/obj/item/device/electronic_assembly/assembly = prefab.assembly_type + + var/available_size = initial(assembly.max_components) + var/available_complexity = initial(assembly.max_complexity) + for(var/ic in prefab.integrated_circuits) + var/datum/ic_assembly_integrated_circuits/iaic = ic + var/obj/item/integrated_circuit/circuit = iaic.circuit_type + available_size -= initial(circuit.size) + available_complexity -= initial(circuit.complexity) + if(available_size < 0) + log_bad("[prefab_type] has an excess component size of [abs(available_size)]") + failed_prefabs |= prefab_type + if(available_complexity < 0) + log_bad("[prefab_type] has an excess component complexity of [abs(available_complexity)]") + failed_prefabs |= prefab_type + + if(failed_prefabs.len) + fail("The following integrated prefab types are out of bounds: [english_list(failed_prefabs)]") + else + pass("All integrated circuit prefabs are within complexity and size limits.") + + return 1 + +/datum/unit_test/integrated_circuit_prefabs_shall_not_fail_to_create + name = "Integrated Circuit Prefabs Shall Not Fail To Create" + +/datum/unit_test/integrated_circuit_prefabs_shall_not_fail_to_create/start_test() + var/list/failed_prefabs = list() + for(var/prefab_type in subtypesof(/decl/prefab/ic_assembly)) + var/decl/prefab/ic_assembly/prefab = decls_repository.get_decl(prefab_type) + + try + var/built_item = prefab.create(get_standard_turf()) + if(built_item) + qdel(built_item) + else + log_bad("[prefab_type] failed to create or return its item.") + failed_prefabs |= prefab_type + catch(var/exception/e) + log_bad("[prefab_type] caused an exception: [e] on [e.file]:[e.line]") + failed_prefabs |= prefab_type + + if(failed_prefabs.len) + fail("The following integrated prefab types failed to create their assemblies: [english_list(failed_prefabs)]") + else + pass("All integrated circuit prefabs are within complexity and size limits.") + + return 1 \ No newline at end of file diff --git a/code/unit_tests/integrated_circuits/trig.dm b/code/unit_tests/integrated_circuits/trig.dm new file mode 100644 index 0000000000..5ba351e2df --- /dev/null +++ b/code/unit_tests/integrated_circuits/trig.dm @@ -0,0 +1,33 @@ +/datum/unit_test/integrated_circuits/floor/sine_1 + name = "Trig Circuits: Sine - 1" + circuit_type = /obj/item/integrated_circuit/trig/sine + inputs_to_give = list(90) + expected_outputs = list(1) + +/datum/unit_test/integrated_circuits/floor/sine_2 + name = "Trig Circuits: Sine - 2" + circuit_type = /obj/item/integrated_circuit/trig/sine + inputs_to_give = list(0) + expected_outputs = list(0) + + + +/datum/unit_test/integrated_circuits/floor/cosine_1 + name = "Trig Circuits: Cosine - 1" + circuit_type = /obj/item/integrated_circuit/trig/cosine + inputs_to_give = list(90) + expected_outputs = list(0) + +/datum/unit_test/integrated_circuits/floor/cosine_2 + name = "Trig Circuits: Cosine - 2" + circuit_type = /obj/item/integrated_circuit/trig/cosine + inputs_to_give = list(0) + expected_outputs = list(1) + + + +/datum/unit_test/integrated_circuits/floor/tangent_1 + name = "Trig Circuits: Tangent - 1" + circuit_type = /obj/item/integrated_circuit/trig/tangent + inputs_to_give = list(45) + expected_outputs = list(1) \ No newline at end of file diff --git a/code/unit_tests/unit_test.dm b/code/unit_tests/unit_test.dm index a090548623..f05514ce74 100644 --- a/code/unit_tests/unit_test.dm +++ b/code/unit_tests/unit_test.dm @@ -96,4 +96,13 @@ var/total_unit_tests = 0 world.Del() else log_unit_test("[ASCII_RED]!!! \[[failed_unit_tests]\\[total_unit_tests]\] Unit Tests Failed !!![ASCII_RESET]") - world.Del() \ No newline at end of file + world.Del() + +/datum/unit_test/proc/get_standard_turf() + return locate(20,20,1) + +/datum/unit_test/proc/log_bad(var/message) + log_unit_test("[ASCII_RED]\[[name]\]: [message][ASCII_RESET]") + +/datum/unit_test/proc/log_debug(var/message) + log_unit_test("[ASCII_YELLOW]--- DEBUG --- \[[name]\]: [message][ASCII_RESET]") \ No newline at end of file diff --git a/config/example/config.txt b/config/example/config.txt index 3839b63bac..884316c45c 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -25,6 +25,11 @@ JOBS_HAVE_MINIMAL_ACCESS ## you have noone older than 0 days, since noone has been logged yet. Only turn this on once you have had the database up for 30 days. #USE_AGE_RESTRICTION_FOR_JOBS +## Unhash this entry to have certain antag roles require your account to be at least a certain number of days old for round start and auto-spawn selection. +## Non-automatic antagonist recruitment, such as being converted to cultism is not affected. Has the same database requirements and notes as USE_AGE_RESTRICTION_FOR_JOBS. +#USE_AGE_RESTRICTION_FOR_ANTAGS + + ## Unhash this to use recursive explosions, keep it hashed to use circle explosions. Recursive explosions react to walls, airlocks and blast doors, making them look a lot cooler than the boring old circular explosions. They require more CPU and are (as of january 2013) experimental #USE_RECURSIVE_EXPLOSIONS diff --git a/html/changelog.html b/html/changelog.html index 6587ec4cd3..4ea1ab9d63 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,18 @@ -->
+

12 January 2017

+

Anewbe updated:

+
    +
  • Ported over a bunch of hairstyles and underclothes from Baystation.
  • +
  • Nurse spiders inject eggs less frequently.
  • +
  • Nurse spiders give a warning to the victim when they implant eggs.
  • +
+

Neerti updated:

+
    +
  • Hand-held flashes and flash rounds will now stun upon repeated applications, similar to stun batons.
  • +
+

03 January 2017

Anewbe updated:

    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index d868296d9a..0f4251f4ca 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -3221,3 +3221,11 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - rscadd: Tape recorders and their tapes now fit in security and detective belts. - rscadd: Lasers can now ignite thermite on walls. - bugfix: Device cells now fit in wall rechargers. +2017-01-12: + Anewbe: + - rscadd: Ported over a bunch of hairstyles and underclothes from Baystation. + - tweak: Nurse spiders inject eggs less frequently. + - rscadd: Nurse spiders give a warning to the victim when they implant eggs. + Neerti: + - rscadd: Hand-held flashes and flash rounds will now stun upon repeated applications, + similar to stun batons. diff --git a/html/changelogs/Anewbe - Antag_Age.yml b/html/changelogs/Anewbe - Antag_Age.yml new file mode 100644 index 0000000000..0360f8184a --- /dev/null +++ b/html/changelogs/Anewbe - Antag_Age.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: PsiOmegaDelta + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - tweak: "The round start and auto-antag spawners can now check if players have played long enough to be eligable for selection." diff --git a/html/changelogs/Anewbe - Boot Knives.yml b/html/changelogs/Anewbe - Boot Knives.yml new file mode 100644 index 0000000000..dcb76602c2 --- /dev/null +++ b/html/changelogs/Anewbe - Boot Knives.yml @@ -0,0 +1,37 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Anewbe + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Can now just click ones boots to draw a holstered knife." + - rscadd: "More boots can hold knives now." \ No newline at end of file diff --git a/html/changelogs/Anewbe - Carp.yml b/html/changelogs/Anewbe - Carp.yml new file mode 100644 index 0000000000..2e02463ad6 --- /dev/null +++ b/html/changelogs/Anewbe - Carp.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Anewbe + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Space Carp have a chance of sticking around after their event completes." diff --git a/html/changelogs/Anewbe - CyberLimbs.yml b/html/changelogs/Anewbe - CyberLimbs.yml new file mode 100644 index 0000000000..e454a4a8b5 --- /dev/null +++ b/html/changelogs/Anewbe - CyberLimbs.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Anewbe + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - tweak: "Robotic limbs will no longer show up on the health scanners." \ No newline at end of file diff --git a/html/changelogs/Anewbe - Languages.yml b/html/changelogs/Anewbe - Languages.yml new file mode 100644 index 0000000000..df087346dc --- /dev/null +++ b/html/changelogs/Anewbe - Languages.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: FTangSteve + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - wip: "RootSpeak is now split into a local and a global variant. For now the global acts as a hivemind." \ No newline at end of file diff --git a/html/changelogs/Anewbe - ShippingError.yml b/html/changelogs/Anewbe - ShippingError.yml new file mode 100644 index 0000000000..f0f43d8cdd --- /dev/null +++ b/html/changelogs/Anewbe - ShippingError.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Techhead + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Added a new random event: Shipping Error - A random crate is mistakenly shipped to the station." diff --git a/html/changelogs/Anewbe - TajChems.yml b/html/changelogs/Anewbe - TajChems.yml new file mode 100644 index 0000000000..eef2b30668 --- /dev/null +++ b/html/changelogs/Anewbe - TajChems.yml @@ -0,0 +1,39 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Anewbe + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Tajaran now process reagents slightly faster." + - rscdel: "Taj are now allergic to coffee again, per loremaster request." + - tweak: "Taj now get drunk faster." + - tweak: "Hyperzine is now more toxic to Taj." diff --git a/html/changelogs/Hubblenaut - Custodial.yml b/html/changelogs/Hubblenaut - Custodial.yml new file mode 100644 index 0000000000..881c51aa3b --- /dev/null +++ b/html/changelogs/Hubblenaut - Custodial.yml @@ -0,0 +1,37 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Hubblenaut + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - tweak: "Can now click on turfs with trash bags and similar to quick-gather everything on it. No longer pixelhunting for cigarettes and bullets." + - bugfix: "Buckets and other reagent holders will no longer simply be put into the janitorial cart's trash bag." \ No newline at end of file diff --git a/icons/mob/belt.dmi b/icons/mob/belt.dmi index 18c6f0e46c..134f719c3a 100644 Binary files a/icons/mob/belt.dmi and b/icons/mob/belt.dmi differ diff --git a/icons/mob/human.dmi b/icons/mob/human.dmi index b629d862b8..9bc29db45f 100644 Binary files a/icons/mob/human.dmi and b/icons/mob/human.dmi differ diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index 6cec55a8fc..201a8ffee5 100644 Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ diff --git a/icons/mob/items/lefthand.dmi b/icons/mob/items/lefthand.dmi index 55f131159d..9b95d51dc3 100644 Binary files a/icons/mob/items/lefthand.dmi and b/icons/mob/items/lefthand.dmi differ diff --git a/icons/mob/items/righthand.dmi b/icons/mob/items/righthand.dmi index 158f56b45f..754d4309e9 100644 Binary files a/icons/mob/items/righthand.dmi and b/icons/mob/items/righthand.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 07719dce61..74f49d6376 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/mob/ties.dmi b/icons/mob/ties.dmi index 010b04137f..ff4a15e679 100644 Binary files a/icons/mob/ties.dmi and b/icons/mob/ties.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 8714d670a1..3c5b0ce667 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/electronic_assemblies.dmi b/icons/obj/electronic_assemblies.dmi index bd5263b7f3..8fd1c4f5e1 100644 Binary files a/icons/obj/electronic_assemblies.dmi and b/icons/obj/electronic_assemblies.dmi differ diff --git a/icons/obj/gun.dmi b/icons/obj/gun.dmi index 996ab9699d..6bf741b8af 100644 Binary files a/icons/obj/gun.dmi and b/icons/obj/gun.dmi differ diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi index 9a32f79a4c..a725b4cc86 100644 Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ diff --git a/icons/obj/meteor.dmi b/icons/obj/meteor.dmi index b9a83d510e..27ebc22445 100644 Binary files a/icons/obj/meteor.dmi and b/icons/obj/meteor.dmi differ diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi index 2e254cc5cb..522d540bdb 100644 Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi index 15152c2159..884b8ac41e 100644 Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ diff --git a/maps/polaris-1.dmm b/maps/polaris-1.dmm index 0f7388e211..13942ea385 100644 --- a/maps/polaris-1.dmm +++ b/maps/polaris-1.dmm @@ -391,7 +391,7 @@ "ahA" = (/obj/machinery/power/breakerbox/activated{RCon_tag = "Civilian Substation Bypass"},/turf/simulated/floor,/area/maintenance/substation/civilian) "ahB" = (/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/obj/structure/cable/green{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/wood,/area/library) "ahC" = (/obj/structure/cable/green{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/wood,/area/library) -"ahD" = (/obj/machinery/firealarm{dir = 1; pixel_y = -24},/obj/machinery/alarm{dir = 8; pixel_x = 25; pixel_y = 0},/turf/simulated/floor/carpet,/area/library) +"ahD" = (/obj/machinery/firealarm{dir = 1; pixel_y = -24},/obj/machinery/alarm{dir = 8; pixel_x = 25; pixel_y = 0},/obj/structure/table/woodentable,/obj/item/device/tvcamera,/turf/simulated/floor/carpet,/area/library) "ahE" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/wood,/area/library) "ahF" = (/obj/structure/bed/chair/comfy/beige{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor/carpet,/area/library) "ahG" = (/obj/machinery/sleep_console,/obj/effect/floor_decal/corner/paleblue{dir = 5},/obj/machinery/alarm{pixel_y = 22},/turf/simulated/floor/tiled/white,/area/medical/first_aid_station_starboard) diff --git a/nano/templates/exonet_node.tmpl b/nano/templates/exonet_node.tmpl index f9d81d4e92..df075c8b89 100644 --- a/nano/templates/exonet_node.tmpl +++ b/nano/templates/exonet_node.tmpl @@ -38,3 +38,12 @@ Used In File(s): code\game\machinery/exonet_node.dm {{:helper.link('Open', 'check', {'toggle_newscaster_port' : 1}, data.allowNewscasters ? 'selected' : null)}}{{:helper.link('Close', 'close', {'toggle_newscaster_port' : 1}, data.allowNewscasters ? null : 'selected')}}
+ +

Logging

+
+ {{for data.logs}} +
+ {{:value}} +
+ {{/for}} +
diff --git a/polaris.dme b/polaris.dme index e820a81230..c05f4a6db3 100644 --- a/polaris.dme +++ b/polaris.dme @@ -777,6 +777,7 @@ #include "code\game\objects\items\devices\taperecorder.dm" #include "code\game\objects\items\devices\traitordevices.dm" #include "code\game\objects\items\devices\transfer_valve.dm" +#include "code\game\objects\items\devices\tvcamera.dm" #include "code\game\objects\items\devices\uplink.dm" #include "code\game\objects\items\devices\uplink_random_lists.dm" #include "code\game\objects\items\devices\violin.dm" @@ -879,6 +880,7 @@ #include "code\game\objects\items\weapons\implants\implant.dm" #include "code\game\objects\items\weapons\implants\implantcase.dm" #include "code\game\objects\items\weapons\implants\implantchair.dm" +#include "code\game\objects\items\weapons\implants\implantcircuits.dm" #include "code\game\objects\items\weapons\implants\implanter.dm" #include "code\game\objects\items\weapons\implants\implantfreedom.dm" #include "code\game\objects\items\weapons\implants\implantlanguage.dm" @@ -1031,6 +1033,7 @@ #include "code\modules\admin\IsBanned.dm" #include "code\modules\admin\map_capture.dm" #include "code\modules\admin\NewBan.dm" +#include "code\modules\admin\news.dm" #include "code\modules\admin\player_notes.dm" #include "code\modules\admin\player_panel.dm" #include "code\modules\admin\topic.dm" @@ -1143,6 +1146,7 @@ #include "code\modules\client\preferences_savefile.dm" #include "code\modules\client\preferences_spawnpoints.dm" #include "code\modules\client\preferences_toggle_procs.dm" +#include "code\modules\client\spam_prevention.dm" #include "code\modules\client\ui_style.dm" #include "code\modules\client\preference_setup\_defines.dm" #include "code\modules\client\preference_setup\preference_setup.dm" @@ -1318,6 +1322,7 @@ #include "code\modules\events\radiation_storm.dm" #include "code\modules\events\random_antagonist.dm" #include "code\modules\events\rogue_drones.dm" +#include "code\modules\events\shipping_error.dm" #include "code\modules\events\solar_storm.dm" #include "code\modules\events\space_ninja.dm" #include "code\modules\events\spacevine.dm" @@ -1392,7 +1397,6 @@ #include "code\modules\integrated_electronics\arithmetic.dm" #include "code\modules\integrated_electronics\assemblies.dm" #include "code\modules\integrated_electronics\converters.dm" -#include "code\modules\integrated_electronics\coordinate.dm" #include "code\modules\integrated_electronics\data_transfer.dm" #include "code\modules\integrated_electronics\input_output.dm" #include "code\modules\integrated_electronics\logic.dm" @@ -1401,6 +1405,7 @@ #include "code\modules\integrated_electronics\reagents.dm" #include "code\modules\integrated_electronics\time.dm" #include "code\modules\integrated_electronics\tools.dm" +#include "code\modules\integrated_electronics\trig.dm" #include "code\modules\integrated_electronics\~defines.dm" #include "code\modules\library\lib_items.dm" #include "code\modules\library\lib_machines.dm" @@ -2120,6 +2125,12 @@ #include "code\unit_tests\research_tests.dm" #include "code\unit_tests\unit_test.dm" #include "code\unit_tests\zas_tests.dm" +#include "code\unit_tests\integrated_circuits\arithmetic.dm" +#include "code\unit_tests\integrated_circuits\circuits.dm" +#include "code\unit_tests\integrated_circuits\converter.dm" +#include "code\unit_tests\integrated_circuits\data_transfer.dm" +#include "code\unit_tests\integrated_circuits\logic.dm" +#include "code\unit_tests\integrated_circuits\trig.dm" #include "code\ZAS\_docs.dm" #include "code\ZAS\Airflow.dm" #include "code\ZAS\Atom.dm"