Merge branch 'master' of https://github.com/PolarisSS13/Polaris into theUnboxingBegins

# Conflicts:
#	code/modules/mob/new_player/sprite_accessories.dm
#	code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
#	icons/mob/human_face.dmi
#	icons/mob/suit.dmi
This commit is contained in:
Anewbe
2017-01-17 22:05:38 -06:00
137 changed files with 2730 additions and 596 deletions

View File

@@ -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)

View File

@@ -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"

View File

@@ -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

View File

@@ -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)

View File

@@ -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"

View File

@@ -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

View File

@@ -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)

View File

@@ -63,3 +63,8 @@
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

View File

@@ -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"
@@ -126,3 +138,16 @@
/datum/category_item/underwear/undershirt/bowlingw
name = "Bowling Shirt, White"
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"

View File

@@ -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.")

View File

@@ -56,7 +56,8 @@
return
/datum/antagonist/changeling/can_become_antag(var/datum/mind/player, var/ignore_role)
if(..())
if(!..())
return 0
if(player.current)
if(ishuman(player.current))
var/mob/living/carbon/human/H = player.current

View File

@@ -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

View File

@@ -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()

View File

@@ -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)

View File

@@ -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)

View File

@@ -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.

View File

@@ -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 << "<span class='notice'>You put everything in [S].</span>"
else if(success)
user << "<span class='notice'>You put some things in [S].</span>"
else
user << "<span class='notice'>You fail to pick anything up with \the [S].</span>"
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,6 +440,7 @@ var/list/global/slot_flags_enumeration = list(
user << "<span class='warning'>You cannot locate any eyes on [M]!</span>"
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)

View File

@@ -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 << "<span class='warning'>The bulb has burnt out!</span>"
icon_state = "flashburnt"
return FALSE
else
times_used++
return TRUE
else //can only use it 10 times a minute
if(user)
user << "<span class='warning'>*click* *click*</span>"
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,19 +72,7 @@
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 << "<span class='warning'>The bulb has burnt out!</span>"
icon_state = "flashburnt"
return
times_used++
else //can only use it 5 times a minute
user << "<span class='warning'>*click* *click*</span>"
if(!check_capacitor(user))
return
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
@@ -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 << "<span class='warning'>The bulb has burnt out!</span>"
icon_state = "flashburnt"
return
times_used++
else //can only use it 5 times a minute
user.show_message("<span class='warning'>*click* *click*</span>", 2)
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"
if(!check_capacitor())
return
times_used++
if(istype(loc, /mob/living/carbon))
var/mob/living/carbon/M = loc
var/safety = M.eyecheck()
var/mob/living/carbon/C = loc
var/safety = C.eyecheck()
if(safety <= 0)
M.Weaken(10)
M.flash_eyes()
for(var/mob/O in viewers(M, null))
O.show_message("<span class='disarm'>[M] is blinded by the flash!</span>")
C.adjustHalLoss(halloss_per_flash)
//C.Weaken(10)
C.flash_eyes()
for(var/mob/M in viewers(C, null))
M.show_message("<span class='disarm'>[C] is blinded by the flash!</span>")
..()
/obj/item/device/flash/synthetic

View File

@@ -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"

View File

@@ -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),

View File

@@ -81,9 +81,11 @@ REAGENT SCANNER
user.show_message("<span class='notice'>Localized Damage, Brute/Burn:</span>",1)
if(length(damaged)>0)
for(var/obj/item/organ/external/org in damaged)
user.show_message(text("<span class='notice'> [][]: [][] - []</span>",
if(org.robotic >= ORGAN_ROBOT)
continue
else
user.show_message(text("<span class='notice'> []: [][] - []</span>",
capitalize(org.name),
(org.robotic >= ORGAN_ROBOT) ? "(Cybernetic)" : "",
(org.brute_dam > 0) ? "<span class='warning'>[org.brute_dam]</span>" : 0,
(org.status & ORGAN_BLEEDING)?"<span class='danger'>\[Bleeding\]</span>":"",
(org.burn_dam > 0) ? "<font color='#FFA500'>[org.burn_dam]</font>" : 0),1)

View File

@@ -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: <a href='?src=\ref[src];channel=1'>[channel ? channel : "unidentified broadcast"]</a><br>"
dat += "Video streaming is <a href='?src=\ref[src];video=1'>[camera.status ? "on" : "off"]</a><br>"
dat += "Mic is <a href='?src=\ref[src];sound=1'>[radio.broadcasting ? "on" : "off"]</a><br>"
dat += "Sound is being broadcasted on frequency [format_frequency(radio.frequency)] ([get_frequency_name(radio.frequency)])<br>"
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, "<span class='notice'>New channel name - '[channel]' is set</span>")
if(href_list["video"])
camera.set_status(!camera.status)
if(camera.status)
to_chat(usr,"<span class='notice'>Video streaming activated. Broadcasting on channel '[channel]'</span>")
else
to_chat(usr,"<span class='notice'>Video streaming deactivated.</span>")
update_icon()
if(href_list["sound"])
radio.ToggleBroadcast()
if(radio.broadcasting)
to_chat(usr,"<span class='notice'>Audio streaming activated. Broadcasting on frequency [format_frequency(radio.frequency)].</span>")
else
to_chat(usr,"<span class='notice'>Audio streaming deactivated.</span>")
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()

View File

@@ -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."

View File

@@ -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 = {"
<b>Implant Specifications:</b><BR>
<b>Name:</b> Modular Implant<BR>
<b>Life:</b> 3 years.<BR>
<b>Important Notes: EMP can cause malfunctions in the internal electronics of this implant.</B><BR>
<HR>
<b>Implant Details:</b><BR>
<b>Function:</b> Contains no innate functions until other components are added.<BR>
<b>Special Features:</b>
<i>Modular Circuitry</i>- Can be loaded with specific modular circuitry in order to fulfill a wide possibility of functions.<BR>
<b>Integrity:</b> 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
..()

View File

@@ -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, "<span class='notice'>You put everything in [src].</span>")
else if(success)
to_chat(user, "<span class='notice'>You put some things in [src].</span>")
else
to_chat(user, "<span class='notice'>You fail to pick anything up with \the [src].</span>")
/obj/item/weapon/storage/verb/toggle_gathering_mode()
set name = "Switch Gathering Method"
set category = "Object"

View File

@@ -78,6 +78,9 @@
else
user << "<span class='notice'>[src] can't hold any more signs.</span>"
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)

View File

@@ -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 << "<span class='warning'>Movement is admin-disabled.</span>" //This is to identify lag problems

View File

@@ -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

View File

@@ -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,

View File

@@ -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,"<script",1,0) ) // Is this needed with santize()?
return
F["title"] << new_title
F["body"] << new_body
F["author"] << key
F["timestamp"] << time2text(world.realtime, "DDD, MMM DD YYYY")
message_admins("[key] modified the news to read:<br>[new_title]<br>[new_body]")
/proc/get_server_news()
var/savefile/F = new(NEWSFILE)
if(F)
return F
#undef NEWSFILE

View File

@@ -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

View File

@@ -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

View File

@@ -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 << "<font color='red'>Error: cmd_admin_mute: This mob doesn't have a client tied to it.</font>"
if(M.client.holder)
usr << "<font color='red'>Error: cmd_admin_mute: You cannot mute an admin/mod.</font>"
if(!M.client) return
if(M.client.holder) return
if(!M.client)
return
if(M.client.holder)
return
var/muteunmute
var/mute_string

View File

@@ -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)

View File

@@ -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

View File

@@ -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))

View File

@@ -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

View File

@@ -408,6 +408,7 @@
if(usr.put_in_hands(holding))
usr.visible_message("<span class='danger'>\The [usr] pulls a knife out of their boot!</span>")
playsound(src.loc, 'sound/weapons/flipblade.ogg', 40, 1)
holding = null
else
usr << "<span class='warning'>Your need an empty, unbroken hand to do that.</span>"
@@ -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) || \

View File

@@ -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

View File

@@ -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 << "<span class='notice'>You slide \the [tacknife] out of [src].</span>"
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 << "<span class='notice'>You slide the [I] into [src].</span>"
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 << "<span class='notice'>You slide \the [tacknife] out of [src].</span>"
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 << "<span class='notice'>You slide the [I] into [src].</span>"
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"

View File

@@ -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

View File

@@ -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"

View File

@@ -45,4 +45,5 @@
if(!C.stat)
var/turf/T = get_turf(C)
if(istype(T, /turf/space))
if(!prob(25))
qdel(C)

View File

@@ -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)),

View File

@@ -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

View File

@@ -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]"

View File

@@ -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 += "<html><head><title>[src.name]</title></head><body>"
HTML += "<div align='center'>"
@@ -122,9 +132,12 @@ var/list/all_integrated_circuits = list()
HTML += "<a href='?src=\ref[src];remove=1'>\[Remove\]</a><br>"
HTML += "<colgroup>"
HTML += "<col style='width: 121px'>"
HTML += "<col style='width: 181px'>"
HTML += "<col style='width: 122px'>"
//HTML += "<col style='width: 121px'>"
//HTML += "<col style='width: 181px'>"
//HTML += "<col style='width: 122px'>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "<col style='width: [table_middle_width]'>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "</colgroup>"
var/column_width = 3
@@ -196,11 +209,16 @@ var/list/all_integrated_circuits = list()
HTML += "</table>"
HTML += "</div>"
HTML += "<br><font color='0000FF'>Complexity: [complexity]</font>"
HTML += "<br><font color='0000FF'>[extended_desc]</font>"
if(autopulse != -1)
HTML += "<br><font color='33CC33'>Meta Variables;</font>"
HTML += "<br><font color='33CC33'><a href='?src=\ref[src];autopulse=1'>\[Autopulse\]</a> = <b>[autopulse ? "ON" : "OFF"]</b></font>"
HTML += "<br>"
HTML += "<br><font color='0000AA'>Complexity: [complexity]</font>"
HTML += "<br><font color='0000AA'>[extended_desc]</font>"
HTML += "</body></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()

View File

@@ -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
@@ -261,3 +266,44 @@
for(var/datum/integrated_io/output/O in outputs)
O.data = result
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()

View File

@@ -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, "<span class='notice'>The machine now has a label reading '[input]'.</span>")
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"

View File

@@ -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"
@@ -105,3 +110,66 @@
var/datum/integrated_io/outgoing = outputs[1]
outgoing.data = result
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()

View File

@@ -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()

View File

@@ -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"

View File

@@ -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 \<String\>", "message \<String\>")
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("<span class='notice'>\icon[O] [stuff_to_display]</span>")
/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("<span class='notice'>\icon[O] [stuff_to_display]</span>")
/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()

View File

@@ -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]

View File

@@ -105,7 +105,7 @@
Southwest = 10<br>\
<br>\
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]

View File

@@ -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

View File

@@ -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"

View File

@@ -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)
@@ -194,3 +212,150 @@
new /obj/item/weapon/crowbar(src)
new /obj/item/weapon/screwdriver(src)
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()

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -59,7 +59,7 @@
if(is_preference_enabled(/datum/client_preference/ghost_ears) && (speaker in view(src)))
message = "<b>[message]</b>"
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 << "<span class='warning'>You cannot hear yourself speak!</span>"

View File

@@ -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"

View File

@@ -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,6 +216,9 @@
/mob/living/Topic(href, href_list)
if(href_list["default_lang"])
if(href_list["default_lang"] == "reset")
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"])
@@ -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

View File

@@ -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"

View File

@@ -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.

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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()

View File

@@ -22,11 +22,12 @@
// Should this all be in Touch()?
if(istype(H))
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 <B>[H] attempts to punch [src], but misses!</B>")
visible_message("\red <B>[H] reaches for [src], but misses!</B>")
return 0
if(H != src && check_shields(0, null, H, H.zone_sel.selecting, H.name))

View File

@@ -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 << "<span class='warning'>You need to recover before you can use this ability.</span>"
return
if(world.time < next_sonar_ping)
src << "<span class='warning'>You need another moment to focus.</span>"
return
if(is_deaf() || is_below_sound_pressure(get_turf(src)))
src << "<span class='warning'>You are for all intents and purposes currently deaf!</span>"
return
next_sonar_ping += 10 SECONDS
var/heard_something = FALSE
src << "<span class='notice'>You take a moment to listen in to your environment...</span>"
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 += "<span class='notice'>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 += "</span>"
src << jointext(feedback,null)
if(!heard_something)
src << "<span class='notice'>You hear no movement but your own.</span>"
#undef HUMAN_EATING_NO_ISSUE
#undef HUMAN_EATING_NO_MOUTH
#undef HUMAN_EATING_BLOCKED_MOUTH

View File

@@ -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))

View File

@@ -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.

View File

@@ -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)

View File

@@ -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

View File

@@ -5,11 +5,18 @@
set name = "Set Default Language"
set category = "IC"
if (only_species_language && language != all_languages[src.species_language])
to_chat(src, "<span class='notice'>You can only speak your species language, [src.species_language].</span>")
return 0
if(language == all_languages[src.species_language])
to_chat(src, "<span class='notice'>You will now speak your standard default language, [language], if you do not specify a language when speaking.</span>")
else if (language)
if(language && !can_speak(language))
src << "<span class='notice'>You are unable to speak that language.</span>"
to_chat(src, "<span class='notice'>You are unable to speak that language.</span>")
return
if(language)
src << "<span class='notice'>You will now speak [language] if you do not specify a language when speaking.</span>"
else
src << "<span class='notice'>You will now speak whatever your standard default language is if you do not specify one when speaking.</span>"

View File

@@ -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 << "<span class='warning'>You cannot speak in IC (Muted).</span>"
return

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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",

View File

@@ -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

View File

@@ -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 << "<span class='warning'>The [src] injects something into your [O.name]!</span>"
/mob/living/simple_animal/hostile/giant_spider/Life()
..()

View File

@@ -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)

View File

@@ -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.

View File

@@ -60,6 +60,11 @@
else
output += "<p><a href='byond://?src=\ref[src];showpoll=1'>Show Player Polls</A></p>"
if(client.check_for_new_server_news())
output += "<p><b><a href='byond://?src=\ref[src];shownews=1'>Show News</A> (NEW!)</b></p>"
else
output += "<p><a href='byond://?src=\ref[src];shownews=1'>Show News</A></p>"
output += "</div>"
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 = "<html><body><center>"
dat += "<h1>[F["title"]]</h1>"
dat += "<br>"
dat += "[F["body"]]"
dat += "<br>"
dat += "<font size='2'><i>Last written by [F["author"]], on [F["timestamp"]].</i></font>"
dat += "</center></body></html>"
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

View File

@@ -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

View File

@@ -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

View File

@@ -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())

View File

@@ -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, "<span class='danger'>You hear a loud roar.</span>")
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, "<span class='danger'>Your ears start to ring badly!</span>")
if (prob(M.ear_damage - 5))
to_chat(M, "<span class='danger'>You can't hear anything!</span>")
M.sdisabilities |= DEAF
else
if (M.ear_damage >= 5)
to_chat(M, "<span class='danger'>Your ears start to ring!</span>")
M.update_icons()
/obj/item/projectile/energy/plasmastun/on_hit(var/atom/target)
bang(target)
. = ..()

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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("<span class='notice'>The fungi are completely dissolved by the solution!</span>")
/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)

View File

@@ -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

View File

@@ -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 ////////////////////

View File

@@ -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)
@@ -91,4 +91,3 @@ Slime definitions, Life and New live here.
resistances[TOX] = 1.5
GenerateChild()
return 1

Some files were not shown because too many files have changed in this diff Show More