Merge branch 'master' into upstream-merge-9307

This commit is contained in:
cadyn
2020-11-15 00:48:22 -08:00
committed by GitHub
149 changed files with 17211 additions and 466 deletions

View File

@@ -155,6 +155,8 @@
#define MAT_METALHYDROGEN "mhydrogen" #define MAT_METALHYDROGEN "mhydrogen"
#define MAT_OSMIUM "osmium" #define MAT_OSMIUM "osmium"
#define MAT_GRAPHITE "graphite" #define MAT_GRAPHITE "graphite"
#define MAT_LEATHER "leather"
#define MAT_CHITIN "chitin"
#define SHARD_SHARD "shard" #define SHARD_SHARD "shard"
#define SHARD_SHRAPNEL "shrapnel" #define SHARD_SHRAPNEL "shrapnel"

View File

@@ -114,11 +114,12 @@
trigger_aiming(TARGET_CAN_CLICK) trigger_aiming(TARGET_CAN_CLICK)
return 1 return 1
// VOREStation Addition Start: inbelly interaction // VOREStation Addition Start: inbelly item interaction
if(isbelly(loc) && (loc == A.loc)) if(isbelly(loc) && (loc == A.loc))
if(W) if(W)
to_chat(src, "The firm confines prevent that kind of dexterity!") //Only hand-based interactions in bellies var/resolved = W.resolve_attackby(A,src)
return if(!resolved && A && W)
W.afterattack(A, src, 1, params) // 1: clicking something Adjacent
else else
if(ismob(A)) // No instant mob attacking if(ismob(A)) // No instant mob attacking
setClickCooldown(get_attack_speed()) setClickCooldown(get_attack_speed())

View File

@@ -7,7 +7,7 @@ datum/controller/transfer_controller
var/shift_last_vote = 0 //VOREStation Edit var/shift_last_vote = 0 //VOREStation Edit
datum/controller/transfer_controller/New() datum/controller/transfer_controller/New()
timerbuffer = config.vote_autotransfer_initial timerbuffer = config.vote_autotransfer_initial
shift_hard_end = config.vote_autotransfer_initial + (config.vote_autotransfer_interval * 3) //CHOMPStation Edit //Change this "1" to how many extend votes you want there to be. shift_hard_end = config.vote_autotransfer_initial + (config.vote_autotransfer_interval * 2) //CHOMPStation Edit //Change this "1" to how many extend votes you want there to be. //Note: Fuck you whoever just slapped a number here instead of using the FUCKING CONFIG LIKE ALL THE OTHER NUMBERS HERE
shift_last_vote = shift_hard_end - config.vote_autotransfer_interval //VOREStation Edit shift_last_vote = shift_hard_end - config.vote_autotransfer_interval //VOREStation Edit
START_PROCESSING(SSprocessing, src) START_PROCESSING(SSprocessing, src)

View File

@@ -0,0 +1,43 @@
#define FIRE_PRIORITY_REFLECTOR 20
SUBSYSTEM_DEF(reflector)
name = "Reflectors"
priority = FIRE_PRIORITY_REFLECTOR
flags = SS_BACKGROUND|SS_NO_INIT
wait = 5
var/stat_tag = "R" //Used for logging
var/list/processing = list()
var/list/currentrun = list()
var/process_proc = /datum/proc/process
var/obj/structure/reflector/current_thing
/datum/controller/subsystem/reflector/Recover()
log_debug("[name] subsystem Recover().")
if(SSreflector.current_thing)
log_debug("current_thing was: (\ref[SSreflector.current_thing])[SSreflector.current_thing]([SSreflector.current_thing.type]) - currentrun: [SSreflector.currentrun.len] vs total: [SSreflector.processing.len]")
var/list/old_processing = SSreflector.processing.Copy()
for(var/datum/D in old_processing)
if(CHECK_BITFIELD(D.datum_flags, DF_ISPROCESSING))
processing |= D
/datum/controller/subsystem/reflector/stat_entry()
..("[stat_tag]:[processing.len]")
/datum/controller/subsystem/reflector/fire(resumed = 0)
if (!resumed)
currentrun = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/current_run = currentrun
while(current_run.len)
current_thing = current_run[current_run.len]
current_run.len--
if(QDELETED(current_thing))
processing -= current_thing
current_thing.Fire()
if (MC_TICK_CHECK)
current_thing = null
return
current_thing = null

View File

@@ -72,13 +72,24 @@ SUBSYSTEM_DEF(vote)
/datum/controller/subsystem/vote/proc/get_result() // Get the highest number of votes /datum/controller/subsystem/vote/proc/get_result() // Get the highest number of votes
var/greatest_votes = 0 var/greatest_votes = 0
var/total_votes = 0 var/total_votes = 0
//CHOMPEdit Begin
if(mode == VOTE_CREW_TRANSFER)
var/transfer_votes = choices["Initiate Crew Transfer"]
var/extend_votes = choices["Extend the Shift"]
total_votes = extend_votes + transfer_votes
if(transfer_votes / total_votes > 0.7)
greatest_votes = transfer_votes
. = list("Initiate Crew Transfer")
else
greatest_votes = extend_votes
. = list("Extend the Shift")
else
for(var/option in choices) for(var/option in choices)
var/votes = choices[option] var/votes = choices[option]
total_votes += votes total_votes += votes
if(votes > greatest_votes) if(votes > greatest_votes)
greatest_votes = votes greatest_votes = votes
//CHOMPEdit End
if(!config.vote_no_default && choices.len) // Default-vote for everyone who didn't vote if(!config.vote_no_default && choices.len) // Default-vote for everyone who didn't vote
var/non_voters = (GLOB.clients.len - total_votes) var/non_voters = (GLOB.clients.len - total_votes)
if(non_voters > 0) if(non_voters > 0)
@@ -107,12 +118,14 @@ SUBSYSTEM_DEF(vote)
choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] * factor) choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] * factor)
to_world("<font color='purple'>Crew Transfer Factor: [factor]</font>") to_world("<font color='purple'>Crew Transfer Factor: [factor]</font>")
greatest_votes = max(choices["Initiate Crew Transfer"], choices["Extend the Shift"]) //VOREStation Edit greatest_votes = max(choices["Initiate Crew Transfer"], choices["Extend the Shift"]) //VOREStation Edit
//CHOMPEdit Begin
if(!(mode == VOTE_CREW_TRANSFER))
. = list() // Get all options with that many votes and return them in a list . = list() // Get all options with that many votes and return them in a list
if(greatest_votes) if(greatest_votes)
for(var/option in choices) for(var/option in choices)
if(choices[option] == greatest_votes) if(choices[option] == greatest_votes)
. += option . += option
//CHOMPEdit End
/datum/controller/subsystem/vote/proc/announce_result() /datum/controller/subsystem/vote/proc/announce_result()
var/list/winners = get_result() var/list/winners = get_result()

View File

@@ -12,6 +12,7 @@
var/signal_enabled = FALSE var/signal_enabled = FALSE
var/weakref/weakref // Holder of weakref instance pointing to this datum var/weakref/weakref // Holder of weakref instance pointing to this datum
var/datum_flags = NONE var/datum_flags = NONE
var/trigger_uid //CHOMPEdit
#ifdef TESTING #ifdef TESTING
var/tmp/running_find_references var/tmp/running_find_references

View File

@@ -19,10 +19,13 @@
alt_titles = list("Intern" = /datum/alt_title/intern, alt_titles = list("Intern" = /datum/alt_title/intern,
"Apprentice Engineer" = /datum/alt_title/intern_eng, "Apprentice Engineer" = /datum/alt_title/intern_eng,
"Medical Intern" = /datum/alt_title/intern_med, "Medical Intern" = /datum/alt_title/intern_med,
"Lab Assistant" = /datum/alt_title/intern_sci, "Lab Assistant" = /datum/alt_title/intern_sci, //CHOMPEdit
"Security Cadet" = /datum/alt_title/intern_sec, "Security Cadet" = /datum/alt_title/intern_sec,
"Jr. Cargo Tech" = /datum/alt_title/intern_crg, "Jr. Cargo Tech" = /datum/alt_title/intern_crg,
"Server" = /datum/alt_title/server) "Server" = /datum/alt_title/server,
//CHOMPSTATION edit start.
"Belly Filler" = /datum/alt_title/prey)
//CHOMPSTATION edit end.
job_description = "An Intern does whatever is requested of them, often doing so in process of learning \ job_description = "An Intern does whatever is requested of them, often doing so in process of learning \
another job. Though they are part of the crew, they have no real authority." another job. Though they are part of the crew, they have no real authority."
timeoff_factor = 0 // Interns, noh timeoff_factor = 0 // Interns, noh
@@ -33,7 +36,7 @@
/datum/alt_title/intern_eng /datum/alt_title/intern_eng
title = "Apprentice Engineer" title = "Apprentice Engineer"
title_blurb = "An Apprentice Engineer attempts to provide whatever the Engineering department needs. They are not proper Engineers, and are \ title_blurb = "An Apprentice Engineer attempts to provide whatever the Engineering department needs. They are not proper Engineers, and are \
often in training to become an Engineer. A Technical Assistant has no real authority." often in training to become an Engineer. An Apprentice Engineer has no real authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/engineer title_outfit = /decl/hierarchy/outfit/job/assistant/engineer
/datum/alt_title/intern_med /datum/alt_title/intern_med
@@ -43,9 +46,9 @@
title_outfit = /decl/hierarchy/outfit/job/assistant/medic title_outfit = /decl/hierarchy/outfit/job/assistant/medic
/datum/alt_title/intern_sci /datum/alt_title/intern_sci
title = "Lab Assistant" title = "Lab Assistant" //CHOMPEdit
title_blurb = "A Lab Assistant attempts to provide whatever the Research department needs. They are not proper Scientists, and are \ title_blurb = "A Lab Assistant attempts to provide whatever the Research department needs. They are not proper Scientists, and are \
often in training to become a Scientist. A Lab Assistant has no real authority." often in training to become a Scientist. A Lab Assistant has no real authority." //CHOMPEdit
title_outfit = /decl/hierarchy/outfit/job/assistant/scientist title_outfit = /decl/hierarchy/outfit/job/assistant/scientist
/datum/alt_title/intern_sec /datum/alt_title/intern_sec
@@ -65,10 +68,13 @@
title_blurb = "A Server helps out kitchen and diner staff with various tasks, primarily food delivery. A Server has no real authority." title_blurb = "A Server helps out kitchen and diner staff with various tasks, primarily food delivery. A Server has no real authority."
title_outfit = /decl/hierarchy/outfit/job/service/server title_outfit = /decl/hierarchy/outfit/job/service/server
//CHOMPSTATION edit start: Thought it would be funny for people to wear their reason for being on station on their shoulder.
////////////////////////////////// /datum/alt_title/prey
// Visitor title = "Belly Filler"
////////////////////////////////// title_blurb = "Considering the needs of this particular region of space, a Belly Filler is a crewmember who has willingly consigned themselves to \
serving the voracious appetites of their fellow crewmembers. A Belly Filler has no authority."
title_outfit = /decl/hierarchy/outfit/job/assistant/intern
//CHOMPSTATION edit end.
/datum/job/intern/New() /datum/job/intern/New()
..() ..()
@@ -82,11 +88,17 @@
else else
return list() return list()
//////////////////////////////////
// Visitor
//////////////////////////////////
/datum/job/assistant // Visitor /datum/job/assistant // Visitor
title = USELESS_JOB title = USELESS_JOB
supervisors = "nobody! You don't work here" supervisors = "nobody! You don't work here"
job_description = "A Visitor is just there to visit the place. They have no real authority or responsibility." job_description = "A Visitor is just there to visit the place. They have no real authority or responsibility."
timeoff_factor = 0 timeoff_factor = 0
alt_titles = list("Guest" = /datum/alt_title/guest, "Traveler" = /datum/alt_title/traveler)
/datum/job/assistant/New() /datum/job/assistant/New()
..() ..()
@@ -96,3 +108,9 @@
/datum/job/assistant/get_access() /datum/job/assistant/get_access()
return list() return list()
/datum/alt_title/guest
title = "Guest"
/datum/alt_title/traveler
title = "Traveler"

View File

@@ -2,6 +2,14 @@
disallow_jobhop = TRUE disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN pto_type = PTO_CIVILIAN
dept_time_required = 80 //Pending something more complicated dept_time_required = 80 //Pending something more complicated
alt_titles = list("Overseer"= /datum/alt_title/overseer, "Facility Director" = /datum/alt_title/facility_director, "Chief Supervisor" = /datum/alt_title/chief_supervisor)
/datum/alt_title/facility_director
title = "Facility Director"
/datum/alt_title/chief_supervisor
title = "Chief Supervisor"
/datum/job/hop /datum/job/hop
disallow_jobhop = TRUE disallow_jobhop = TRUE
@@ -10,8 +18,8 @@
departments_managed = list(DEPARTMENT_CIVILIAN, DEPARTMENT_CARGO, DEPARTMENT_PLANET) departments_managed = list(DEPARTMENT_CIVILIAN, DEPARTMENT_CARGO, DEPARTMENT_PLANET)
dept_time_required = 60 dept_time_required = 60
alt_titles = list("Crew Resources Officer" = /datum/alt_title/cro, alt_titles = list("Crew Resources Officer" = /datum/alt_title/cro, "Deputy Director" = /datum/alt_title/deputy_director, "Staff Manager" = /datum/alt_title/staff_manager,
"Deputy Director" = /datum/alt_title/deputy_director) "Facility Steward" = /datum/alt_title/facility_steward) //CHOMPEdit
access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers, access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads, access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
@@ -29,6 +37,27 @@
/datum/alt_title/deputy_director /datum/alt_title/deputy_director
title = "Deputy Director" title = "Deputy Director"
/datum/alt_title/staff_manager
title = "Staff Manager"
/datum/alt_title/facility_steward
title = "Facility Steward"
/datum/job/secretary /datum/job/secretary
disallow_jobhop = TRUE disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN pto_type = PTO_CIVILIAN
alt_titles = list("Command Liaison" = /datum/alt_title/command_liaison, "Bridge Secretary" = /datum/alt_title/bridge_secretary,
"Command Assistant" = /datum/alt_title/command_assistant, "Command Intern" = /datum/alt_title/command_intern)
/datum/alt_title/command_liaison
title = "Command Liaison"
/datum/alt_title/bridge_secretary
title = "Bridge Secretary"
/datum/alt_title/command_assistant
title = "Command Assistant"
/datum/alt_title/command_intern
title = "Command Intern"

View File

@@ -1,34 +1,104 @@
/datum/job/bartender /datum/job/bartender
pto_type = PTO_CIVILIAN pto_type = PTO_CIVILIAN
alt_titles = list("Barkeeper" = /datum/alt_title/barkeeper, "Barmaid" = /datum/alt_title/barmaid, "Barista" = /datum/alt_title/barista, "Mixologist" = /datum/alt_title/mixologist)
/datum/alt_title/barkeeper
title = "Barkeeper"
/datum/alt_title/barmaid
title = "Barmaid"
/datum/alt_title/mixologist
title = "Mixologist"
/datum/job/chef /datum/job/chef
total_positions = 2 //IT TAKES A LOT TO MAKE A STEW total_positions = 2 //IT TAKES A LOT TO MAKE A STEW
spawn_positions = 2 //A PINCH OF SALT AND LAUGHTER, TOO spawn_positions = 2 //A PINCH OF SALT AND LAUGHTER, TOO
pto_type = PTO_CIVILIAN pto_type = PTO_CIVILIAN
alt_titles = list("Sous-chef" = /datum/alt_title/souschef,"Cook" = /datum/alt_title/cook, "Kitchen Worker" = /datum/alt_title/kitchen_worker)
/datum/alt_title/souschef
title = "Sous-chef"
/datum/alt_title/kitchen_worker
title = "Kitchen Worker"
title_blurb = "A Kitchen Worker has the same duties, though they may be less experienced."
/datum/job/hydro /datum/job/hydro
spawn_positions = 2 spawn_positions = 2
pto_type = PTO_CIVILIAN pto_type = PTO_CIVILIAN
alt_titles = list("Hydroponicist" = /datum/alt_title/hydroponicist, "Cultivator" = /datum/alt_title/cultivator, "Farmer" = /datum/alt_title/farmer,
"Gardener" = /datum/alt_title/gardener, "Florist" = /datum/alt_title/florsit)
/datum/alt_title/hydroponicist
title = "Hydroponicist"
/datum/alt_title/cultivator
title = "Cultivator"
/datum/alt_title/farmer
title = "Farmer"
/datum/alt_title/florsit
title = "Florist"
title_blurb = "A Florist may be less professional than their counterparts, and are more likely to tend to the public gardens if they aren't needed elsewhere."
/datum/job/qm /datum/job/qm
pto_type = PTO_CARGO pto_type = PTO_CARGO
dept_time_required = 20 dept_time_required = 20
alt_titles = list("Supply Chief" = /datum/alt_title/supply_chief, "Logistics Manager" = /datum/alt_title/logistics_manager)
/datum/alt_title/logistics_manager
title = "Logistics Manager"
/datum/job/cargo_tech /datum/job/cargo_tech
total_positions = 3 total_positions = 3
spawn_positions = 3 spawn_positions = 3
pto_type = PTO_CARGO pto_type = PTO_CARGO
alt_titles = list("Cargo Loader" = /datum/alt_title/cargo_loader, "Cargo Handler" = /datum/alt_title/cargo_handler, "Supply Courier" = /datum/alt_title/supply_courier,
"Disposals Sorter" = /datum/alt_title/disposal_sorter)
/datum/alt_title/supply_courier
title = "Supply Courier"
title_blurb = "A Supply Courier is usually tasked with devlivering packages or cargo directly to whoever requires it."
/datum/alt_title/cargo_loader
title = "Cargo Loader"
title_blurb = "A Cargo Loader is usually tasked with more menial labor within Supply department, such as loading and unloading supply shuttle."
/datum/alt_title/cargo_handler
title = "Cargo Handler"
title_blurb = "A Cargo Loader is usually tasked with more menial labor within Supply department, such as loading and unloading supply shuttle."
/datum/alt_title/disposal_sorter
title = "Disposals Sorter"
title_blurb = "A Disposals Sorter is usually tasked with operating disposals delivery system, sorting the trash and tagging parcels for delivery."
/datum/job/mining /datum/job/mining
total_positions = 4 total_positions = 4
spawn_positions = 4 spawn_positions = 4
pto_type = PTO_CARGO pto_type = PTO_CARGO
alt_titles = list(/*CHOMPEdit Removal "Deep Space Miner" = /datum/alt_title/deep_space_miner*/, "Drill Technician" = /datum/alt_title/drill_tech, "Prospector" = /datum/alt_title/prospector)
/datum/alt_title/deep_space_miner
title = "Deep Space Miner"
title_blurb = "A Deep Space Miner specializes primarily in mining operations in zero-g environments, mostly in asteroid and debris fields."
/datum/alt_title/prospector
title = "Prospector"
/datum/job/janitor //Lots of janitor substations on station. /datum/job/janitor //Lots of janitor substations on station.
total_positions = 3 total_positions = 3
spawn_positions = 3 spawn_positions = 3
alt_titles = list("Custodian" = /datum/alt_title/custodian, "Sanitation Technician" = /datum/alt_title/sanitation_tech, "Maid" = /datum/alt_title/maid)
pto_type = PTO_CIVILIAN pto_type = PTO_CIVILIAN
alt_titles = list("Custodian" = /datum/alt_title/custodian, "Sanitation Technician" = /datum/alt_title/sanitation_tech,
"Maid" = /datum/alt_title/maid, "Garbage Collector" = /datum/alt_title/garbage_collector)
/datum/alt_title/sanitation_tech /datum/alt_title/sanitation_tech
title = "Sanitation Technician" title = "Sanitation Technician"
@@ -36,26 +106,73 @@
/datum/alt_title/maid /datum/alt_title/maid
title = "Maid" title = "Maid"
/datum/alt_title/garbage_collector
title = "Garbage Collector"
title_blurb = "A Garbage Collector keeps the station clean, though focuses moreso on collecting larger trash, with wet cleaning being secondary task."
/datum/job/librarian /datum/job/librarian
total_positions = 2 total_positions = 2
spawn_positions = 2 spawn_positions = 2
alt_titles = list("Journalist" = /datum/alt_title/journalist, "Writer" = /datum/alt_title/writer, "Historian" = /datum/alt_title/historian, "Professor" = /datum/alt_title/professor) alt_titles = list("Journalist" = /datum/alt_title/journalist, "Reporter" = /datum/alt_title/reporter, "Writer" = /datum/alt_title/writer,
"Historian" = /datum/alt_title/historian, "Archivist" = /datum/alt_title/archivist, "Professor" = /datum/alt_title/professor,
"Academic" = /datum/alt_title/academic, "Philosopher" = /datum/alt_title/philosopher)
pto_type = PTO_CIVILIAN pto_type = PTO_CIVILIAN
/datum/alt_title/reporter
title = "Reporter"
title_blurb = "The Reporter uses the Library as a base of operations, from which they can report the news and goings-on on the station with their camera."
/datum/alt_title/historian /datum/alt_title/historian
title = "Historian" title = "Historian"
title_blurb = "The Historian uses the Library as a base of operation to record any important events occuring on station." title_blurb = "The Historian uses the Library as a base of operation to record any important events occuring on station."
/datum/alt_title/archivist
title = "Archivist"
title_blurb = "The Archivist uses the Library as a base of operation to record any important events occuring on station."
/datum/alt_title/professor /datum/alt_title/professor
title = "Professor" title = "Professor"
title_blurb = "The Professor uses the Library as a base of operations to share their vast knowledge with the crew." title_blurb = "The Professor uses the Library as a base of operations to share their vast knowledge with the crew."
/datum/alt_title/academic
title = "Academic"
title_blurb = "The Academic uses the Library as a base of operations to share their vast knowledge with the crew."
/datum/alt_title/philosopher
title = "Philosopher"
title_blurb = "The Philosopher uses the Library as a base of operation to ruminate on nature of life and other great questions, and share their opinions with the crew."
/datum/job/lawyer /datum/job/lawyer
disallow_jobhop = TRUE disallow_jobhop = TRUE
pto_type = PTO_CIVILIAN pto_type = PTO_CIVILIAN
alt_titles = list("Internal Affairs Liaison" = /datum/alt_title/ia_liaison, "Internal Affairs Delegate" = /datum/alt_title/ia_delegate,
"Internal Affairs Investigator" = /datum/alt_title/ia_investigator)
/datum/alt_title/ia_liaison
title = "Internal Affairs Liaison"
/datum/alt_title/ia_delegate
title = "Internal Affairs Delegate"
/datum/alt_title/ia_investigator
title = "Internal Affairs Investigator"
/datum/job/chaplain /datum/job/chaplain
pto_type = PTO_CIVILIAN pto_type = PTO_CIVILIAN
alt_titles = list("Missionary" = /datum/alt_title/missionary, "Preacher" = /datum/alt_title/preacher, "Counselor" = /datum/alt_title/counselor, "Guru" = /datum/alt_title/guru)
/datum/alt_title/guru
title = "Guru"
title_blurb = "The Guru primarily tries to offer spiritual guidance to those who come seeking it."
/datum/alt_title/missionary
title = "Missionary"
/datum/alt_title/preacher
title = "Preacher"
@@ -79,17 +196,43 @@
outfit_type = /decl/hierarchy/outfit/job/assistant outfit_type = /decl/hierarchy/outfit/job/assistant
job_description = "An entertainer does just that, entertains! Put on plays, play music, sing songs, tell stories, or read your favorite fanfic." job_description = "An entertainer does just that, entertains! Put on plays, play music, sing songs, tell stories, or read your favorite fanfic."
alt_titles = list("Performer" = /datum/alt_title/performer, "Musician" = /datum/alt_title/musician, "Stagehand" = /datum/alt_title/stagehand) alt_titles = list("Performer" = /datum/alt_title/performer, "Musician" = /datum/alt_title/musician, "Stagehand" = /datum/alt_title/stagehand,
"Actor" = /datum/alt_title/actor, "Dancer" = /datum/alt_title/dancer, "Singer" = /datum/alt_title/singer,
"Magician" = /datum/alt_title/magician, "Comedian" = /datum/alt_title/comedian, "Tragedian" = /datum/alt_title/tragedian)
// Entertainer Alt Titles // Entertainer Alt Titles
/datum/alt_title/actor
title = "Actor"
title_blurb = "An Actor is someone who acts out a role! Whatever sort of character it is, get into it and impress people with power of comedy and tragedy!"
/datum/alt_title/performer /datum/alt_title/performer
title = "Performer" title = "Performer"
title_blurb = "A Performer is someone who performs! Acting, dancing, wrestling, etc!" title_blurb = "A Performer is someone who performs! Whatever sort of performance will come to your mind, the world's a stage!"
/datum/alt_title/musician /datum/alt_title/musician
title = "Musician" title = "Musician"
title_blurb = "A Musician is someone who makes music! Singing, playing instruments, slam poetry, it's your call!" title_blurb = "A Musician is someone who makes music with a wide variety of musical instruments!"
/datum/alt_title/stagehand /datum/alt_title/stagehand
title = "Stagehand" title = "Stagehand"
title_blurb = "A Stagehand typically performs everything the rest of the entertainers don't. Operate lights, shutters, windows, or narrate through your voicebox!" title_blurb = "A Stagehand typically performs everything the rest of the entertainers don't. Operate lights, shutters, windows, or narrate through your voicebox!"
/datum/alt_title/dancer
title = "Dancer"
title_blurb = "A Dancer is someone who impresses people through power of their own body! From waltz to breakdance, as long as crowd as cheering!"
/datum/alt_title/singer
title = "Singer"
title_blurb = "A Singer is someone with gift of melodious voice! Impress people with your vocal range!"
/datum/alt_title/magician
title = "Magician"
title_blurb = "A Magician is someone who awes those around them with impossible! Show off your repertoire of magic tricks, while keeping the secret hidden!"
/datum/alt_title/comedian
title = "Comedian"
title_blurb = "A Comedian will focus on making people laugh with the power of wit! Telling jokes, stand-up comedy, you are here to make others smile!"
/datum/alt_title/tragedian
title = "Tragedian"
title_blurb = "A Tragedian will focus on making people think about life and world around them! Life is a tragedy, and who's better to convey its emotions than you?"

View File

@@ -12,10 +12,38 @@
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva, access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction, access_heads, access_construction,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload) access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload)
alt_titles = list("Head Engineer" = /datum/alt_title/head_engineer, "Foreman" = /datum/alt_title/foreman, "Maintenance Manager" = /datum/alt_title/maintenance_manager)
/datum/alt_title/head_engineer
title = "Head Engineer"
/datum/alt_title/foreman
title = "Foreman"
/datum/alt_title/maintenance_manager
title = "Maintenance Manager"
/datum/job/engineer /datum/job/engineer
pto_type = PTO_ENGINEERING pto_type = PTO_ENGINEERING
alt_titles = list("Maintenance Technician" = /datum/alt_title/maint_tech, "Engine Technician" = /datum/alt_title/engine_tech,
"Electrician" = /datum/alt_title/electrician, "Construction Engineer" = /datum/alt_title/construction_engi)
/datum/alt_title/construction_engi
title = "Construction Engineer"
title_blurb = "A Construction Engineer fulfills similar duties to other engineers, but usually occupies spare time with construction of extra facilities in dedicated areas or \
as additions to station layout."
/datum/job/atmos /datum/job/atmos
spawn_positions = 3 spawn_positions = 3
pto_type = PTO_ENGINEERING pto_type = PTO_ENGINEERING
alt_titles = list("Atmospherics Maintainer" = /datum/alt_title/atmos_maint, /*CHOMPEdit "Disposals Technician" = /datum/alt_title/disposals_tech*/)
/datum/alt_title/atmos_maint
title = "Atmospherics Maintainer"
/datum/alt_title/disposals_tech
title = "Disposals Technician"
title_blurb = "A Disposals Technician is an Atmospheric Technician still and can fulfill all the same duties, although specializes more in disposals delivery system's operations and configurations."

View File

@@ -29,6 +29,8 @@ var/const/SAR =(1<<14)
color = "#bab421" color = "#bab421"
sorting_order = 2 // Same as cargo in importance. sorting_order = 2 // Same as cargo in importance.
/datum/job/pathfinder /datum/job/pathfinder
title = "Pathfinder" title = "Pathfinder"
flag = PATHFINDER flag = PATHFINDER
@@ -50,9 +52,14 @@ var/const/SAR =(1<<14)
minimal_access = list(access_eva, access_maint_tunnels, access_external_airlocks, access_pilot, access_explorer, access_gateway) minimal_access = list(access_eva, access_maint_tunnels, access_external_airlocks, access_pilot, access_explorer, access_gateway)
outfit_type = /decl/hierarchy/outfit/job/pathfinder outfit_type = /decl/hierarchy/outfit/job/pathfinder
job_description = "The Pathfinder's job is to lead and manage expeditions, and is the primary authority on all off-station expeditions." job_description = "The Pathfinder's job is to lead and manage expeditions, and is the primary authority on all off-station expeditions."
alt_titles = list("Expedition Lead" = /datum/alt_title/expedition_lead, "Exploration Manager" = /datum/alt_title/exploration_manager)
/datum/alt_title/expedition_lead
title = "Expedition Lead"
/datum/alt_title/exploration_manager
title = "Exploration Manager"
/datum/alt_title/pathfinder
title = "Pathfinder"
/datum/job/pilot /datum/job/pilot
title = "Pilot" title = "Pilot"
@@ -71,9 +78,15 @@ var/const/SAR =(1<<14)
minimal_access = list(access_pilot) minimal_access = list(access_pilot)
outfit_type = /decl/hierarchy/outfit/job/pilot outfit_type = /decl/hierarchy/outfit/job/pilot
job_description = "A Pilot flies the various shuttles in the Virgo-Erigone System." job_description = "A Pilot flies the various shuttles in the Virgo-Erigone System."
alt_titles = list("Co-Pilot" = /datum/alt_title/co_pilot, "Navigator" = /datum/alt_title/navigator)
/datum/alt_title/co_pilot
title = "Co-Pilot"
title_blurb = "A Co-Pilot is there primarily to assist main pilot as well as learn from them"
/datum/alt_title/navigator
title = "Navigator"
/datum/alt_title/pilot
title = "Pilot"
/datum/job/explorer /datum/job/explorer
title = "Explorer" title = "Explorer"
@@ -91,9 +104,14 @@ var/const/SAR =(1<<14)
minimal_access = list(access_explorer, access_external_airlocks, access_eva) minimal_access = list(access_explorer, access_external_airlocks, access_eva)
outfit_type = /decl/hierarchy/outfit/job/explorer2 outfit_type = /decl/hierarchy/outfit/job/explorer2
job_description = "An Explorer searches for interesting things, and returns them to the station." job_description = "An Explorer searches for interesting things, and returns them to the station."
alt_titles = list("Surveyor" = /datum/alt_title/surveyor, "Offsite Scout" = /datum/alt_title/offsite_scout)
/datum/alt_title/surveyor
title = "Surveyor"
/datum/alt_title/offsite_scout
title = "Offsite Scout"
/datum/alt_title/explorer
title = "Explorer"
/datum/job/sar /datum/job/sar
title = "Field Medic" title = "Field Medic"
@@ -112,25 +130,7 @@ var/const/SAR =(1<<14)
minimal_access = list(access_medical, access_medical_equip, access_morgue, access_pilot) minimal_access = list(access_medical, access_medical_equip, access_morgue, access_pilot)
outfit_type = /decl/hierarchy/outfit/job/medical/sar outfit_type = /decl/hierarchy/outfit/job/medical/sar
job_description = "A Field medic works as the field doctor of expedition teams." job_description = "A Field medic works as the field doctor of expedition teams."
alt_titles = list("Expedition Medic" = /datum/alt_title/expedition_medic)
/datum/alt_title/field_medic /datum/alt_title/expedition_medic
title = "Field Medic" title = "Expedition Medic"
/datum/job/offduty_exploration
title = "Off-duty Explorer"
latejoin_only = TRUE
timeoff_factor = -1
total_positions = -1
faction = "Station"
departments = list(DEPARTMENT_OFFDUTY)
supervisors = "nobody! Enjoy your time off"
selection_color = "#999440"
access = list(access_maint_tunnels, access_external_airlocks)
minimal_access = list(access_maint_tunnels, access_external_airlocks)
outfit_type = /decl/hierarchy/outfit/job/assistant/explorer
job_description = "Off-duty crew has no responsibilities or authority and is just there to spend their well-deserved time off."
pto_type = PTO_EXPLORATION
economic_modifier = 5
/datum/alt_title/offduty_exp
title = "Off-duty Explorer"

View File

@@ -16,10 +16,10 @@
req_admin_notify = 1 req_admin_notify = 1
economic_modifier = 10 economic_modifier = 10
access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads, access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_teleporter,
access_keycard_auth, access_sec_doors, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels) access_keycard_auth, access_sec_doors, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
minimal_access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads, minimal_access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_teleporter,
access_keycard_auth, access_sec_doors, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels) access_keycard_auth, access_sec_doors, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
minimum_character_age = 25 minimum_character_age = 25

View File

@@ -4,22 +4,77 @@
dept_time_required = 60 dept_time_required = 60
access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads, access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_teleporter, //CHOMPEdit
access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels) access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
minimal_access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads, minimal_access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_teleporter,//CHOMPEdit
access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels) access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
alt_titles = list("Chief Physician" = /datum/alt_title/chief_physician, "Medical Director" = /datum/alt_title/medical_director, /*CHOMPEdit Removal"Healthcare Manager" = /datum/alt_title/healthcare_manager*/)
/datum/alt_title/chief_physician
title = "Chief Physician"
/datum/alt_title/medical_director
title = "Medical Director"
/datum/alt_title/healthcare_manager
title = "Healthcare Manager"
/datum/job/doctor /datum/job/doctor
spawn_positions = 5 spawn_positions = 5
pto_type = PTO_MEDICAL pto_type = PTO_MEDICAL
alt_titles = list("Physician" = /datum/alt_title/physician, "Medical Practitioner" = /datum/alt_title/medical_practitioner, "Surgeon" = /datum/alt_title/surgeon,
"Emergency Physician" = /datum/alt_title/emergency_physician, "Nurse" = /datum/alt_title/nurse, "Orderly" = /datum/alt_title/orderly,
"Virologist" = /datum/alt_title/virologist)
/datum/alt_title/physician
title = "Physician"
/datum/alt_title/medical_practitioner
title = "Medical Practitioner"
/datum/alt_title/orderly
title = "Orderly"
title_blurb = "An Orderly acts as Medbay's general helping hand, assisting any doctor that might need some form of help, as well as handling manual \
and dirty labor around the department."
title_outfit = /decl/hierarchy/outfit/job/medical/doctor/nurse
/datum/job/chemist /datum/job/chemist
pto_type = PTO_MEDICAL pto_type = PTO_MEDICAL
alt_titles = list("Pharmacist" = /datum/alt_title/pharmacist, "Pharmacologist" = /datum/alt_title/pharmacologist)
/datum/alt_title/pharmacologist
title = "Pharmacologist"
title_blurb = "A Pharmacologist focuses on the chemical needs of the Medical Department, primarily specializing in producing more advanced forms of medicine."
/datum/job/psychiatrist /datum/job/psychiatrist
pto_type = PTO_MEDICAL pto_type = PTO_MEDICAL
alt_titles = list("Psychologist" = /datum/alt_title/psychologist, "Psychoanalyst" = /datum/alt_title/psychoanalyst, "Psychotherapist" = /datum/alt_title/psychotherapist)
/datum/alt_title/psychoanalyst
title = "Psychoanalyst"
title_blurb = "A Psychoanalyst provides mental health services to crew members in need, focusing more on therapy than medication. They may also be \
called upon to determine whatever ails the mentally unwell, frequently under Security supervision."
title_outfit = /decl/hierarchy/outfit/job/medical/psychiatrist/psychologist
/datum/alt_title/psychotherapist
title = "Psychotherapist"
title_blurb = "A Psychotherapist provides mental health services to crew members in need, focusing more on therapy than medication. They may also be \
called upon to determine whatever ails the mentally unwell, frequently under Security supervision."
title_outfit = /decl/hierarchy/outfit/job/medical/psychiatrist/psychologist
/datum/job/paramedic /datum/job/paramedic
pto_type = PTO_MEDICAL pto_type = PTO_MEDICAL
alt_titles = list("Emergency Medical Technician" = /datum/alt_title/emt, "Medical Responder" = /datum/alt_title/medical_responder)
/datum/alt_title/medical_responder
title = "Medical Responder"
title_blurb = "A Medical Responder is primarily concerned with the recovery of patients who are unable to make it to the Medical Department on their \
own. They are capable of keeping a patient stabilized until they reach the hands of someone with more training."
title_outfit = /decl/hierarchy/outfit/job/medical/paramedic/emt

View File

@@ -18,9 +18,6 @@
pto_type = PTO_CIVILIAN pto_type = PTO_CIVILIAN
economic_modifier = 2 economic_modifier = 2
/datum/alt_title/offduty_civ
title = "Off-duty Worker"
/datum/job/offduty_cargo /datum/job/offduty_cargo
title = "Off-duty Cargo" title = "Off-duty Cargo"
latejoin_only = TRUE latejoin_only = TRUE
@@ -37,9 +34,6 @@
pto_type = PTO_CARGO pto_type = PTO_CARGO
economic_modifier = 2 economic_modifier = 2
/datum/alt_title/offduty_crg
title = "Off-duty Cargo"
/datum/job/offduty_engineering /datum/job/offduty_engineering
title = "Off-duty Engineer" title = "Off-duty Engineer"
latejoin_only = TRUE latejoin_only = TRUE
@@ -56,9 +50,6 @@
pto_type = PTO_ENGINEERING pto_type = PTO_ENGINEERING
economic_modifier = 5 economic_modifier = 5
/datum/alt_title/offduty_eng
title = "Off-duty Engineer"
/datum/job/offduty_medical /datum/job/offduty_medical
title = "Off-duty Medic" title = "Off-duty Medic"
latejoin_only = TRUE latejoin_only = TRUE
@@ -75,9 +66,6 @@
pto_type = PTO_MEDICAL pto_type = PTO_MEDICAL
economic_modifier = 5 economic_modifier = 5
/datum/alt_title/offduty_med
title = "Off-duty Medic"
/datum/job/offduty_science /datum/job/offduty_science
title = "Off-duty Scientist" title = "Off-duty Scientist"
latejoin_only = TRUE latejoin_only = TRUE
@@ -94,9 +82,6 @@
pto_type = PTO_SCIENCE pto_type = PTO_SCIENCE
economic_modifier = 5 economic_modifier = 5
/datum/alt_title/offduty_sci
title = "Off-duty Scientist"
/datum/job/offduty_security /datum/job/offduty_security
title = "Off-duty Officer" title = "Off-duty Officer"
latejoin_only = TRUE latejoin_only = TRUE
@@ -113,5 +98,18 @@
pto_type = PTO_SECURITY pto_type = PTO_SECURITY
economic_modifier = 5 economic_modifier = 5
/datum/alt_title/offduty_sec /datum/job/offduty_exploration
title = "Off-duty Officer" title = "Off-duty Explorer"
latejoin_only = TRUE
timeoff_factor = -1
total_positions = -1
faction = "Station"
departments = list(DEPARTMENT_OFFDUTY)
supervisors = "nobody! Enjoy your time off"
selection_color = "#999440"
access = list(access_maint_tunnels, access_external_airlocks)
minimal_access = list(access_maint_tunnels, access_external_airlocks)
outfit_type = /decl/hierarchy/outfit/job/assistant/explorer
job_description = "Off-duty crew has no responsibilities or authority and is just there to spend their well-deserved time off."
pto_type = PTO_EXPLORATION
economic_modifier = 5

View File

@@ -13,30 +13,73 @@
access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage, access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage,
access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_eva, access_network, access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_eva, access_network,
access_explorer, access_pathfinder, access_xenobotany) //YW Edit access_gateway, _explorer, _pathfinder, and _xenobotany access_explorer, access_pathfinder, access_xenobotany) //YW Edit access_gateway, _explorer, _pathfinder, and _xenobotany
/datum/alt_title/research_manager
title = "Research Manager"
/datum/alt_title/head_of_development
title = "Head of Development"
/datum/alt_title/head_scientist
title = "Head Scientist"
/datum/job/scientist /datum/job/scientist
spawn_positions = 5 spawn_positions = 5
pto_type = PTO_SCIENCE pto_type = PTO_SCIENCE
alt_titles = list("Xenoarchaeologist" = /datum/alt_title/xenoarch, "Anomalist" = /datum/alt_title/anomalist, \ alt_titles = list("Lab Assistant" = /datum/alt_title/lab_assistant, "Xenoarchaeologist" = /datum/alt_title/xenoarch, "Xenopaleontologist" = /datum/alt_title/xenopaleontologist, \
"Phoron Researcher" = /datum/alt_title/phoron_research, "Circuit Designer" = /datum/alt_title/circuit_designer) "Anomalist" = /datum/alt_title/anomalist, "Phoron Researcher" = /datum/alt_title/phoron_research, "Gas Physicist" = /datum/alt_title/gas_physicist, \
"Circuit Designer" = /datum/alt_title/circuit_designer, "Circuit Programmer" = /datum/alt_title/circuit_programmer)
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_xenoarch, access_xenobotany) access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_xenoarch, access_xenobotany)
minimal_access = list(access_tox, access_tox_storage, access_research, access_xenoarch) // Unchanged (for now?), mostly here for reference minimal_access = list(access_tox, access_tox_storage, access_research, access_xenoarch) // Unchanged (for now?), mostly here for reference
/datum/alt_title/lab_assistant
title = "Lab Assistant"
title_blurb = "A Lab Assistant is a lower-level member of research staff, whose main purpose is to help scientists with their specialized work in more menial fashion, while also \
learning the specializations in process."
/datum/alt_title/xenopaleontologist
title = "Xenopaleontologist"
title_blurb = "A Xenopaleontologist enters digsites in search of fossils and other ancient remants of alien life. These digsites are frequently in vacuum or other inhospitable \
locations, and as such a Xenopaleontologist should be prepared to handle hostile evironmental conditions."
/datum/alt_title/gas_physicist
title = "Gas Physicist"
title_blurb = "A Gas Physicist is a specialist in various practical applications of gasses, but currently focuses their attention on phoron, and has knowledge of its practical uses and dangers. \
Many Gas Physicists are interested in the combustability and explosive properties of gaseous phoron, as well as the specific hazards \
of working with the substance in that state."
/datum/alt_title/circuit_designer /datum/alt_title/circuit_designer
title = "Circuit Designer" title = "Circuit Designer"
title_blurb = "A Circuit Designer is a Scientist whose expertise is working with integrated circuits. They are familar with the workings and programming of those devices. \ title_blurb = "A Circuit Designer is a Scientist whose expertise is working with integrated circuits. They are familar with the workings and programming of those devices. \
They work to create various useful devices using the capabilities of integrated circuitry." They work to create various useful devices using the capabilities of integrated circuitry."
/datum/alt_title/circuit_programmer
title = "Circuit Programmer"
title_blurb = "A Circuit Programmer is a Scientist whose expertise is working with integrated circuits. They are familar with the workings and programming of those devices. \
They work to create various useful devices using the capabilities of integrated circuitry."
/datum/job/xenobiologist /datum/job/xenobiologist
spawn_positions = 3 spawn_positions = 3
pto_type = PTO_SCIENCE pto_type = PTO_SCIENCE
alt_titles = list("Xenozoologist" = /datum/alt_title/xenozoologist, "Xenoanthropologist" = /datum/alt_title/xenoanthropologist)
/datum/alt_title/xenozoologist
title = "Xenozoologist"
/datum/alt_title/xenoanthropologist
title = "Xenoanthropologist"
title_blurb = "Xenoanthropologist still heavily focuses their study on alien lifeforms, but their specialty leans more towards fellow sapient beings than simple animals."
/datum/job/roboticist /datum/job/roboticist
total_positions = 3 total_positions = 3
pto_type = PTO_SCIENCE pto_type = PTO_SCIENCE
alt_titles = list("Assembly Technician" = /datum/alt_title/assembly_tech, "Biomechanical Engineer" = /datum/alt_title/biomech, "Mechatronic Engineer" = /datum/alt_title/mech_tech)
/datum/alt_title/assembly_tech
title = "Assembly Technician"
////////////////////////////////// //////////////////////////////////
// Xenobotanist // Xenobotanist
@@ -61,3 +104,7 @@
outfit_type = /decl/hierarchy/outfit/job/science/xenobiologist outfit_type = /decl/hierarchy/outfit/job/science/xenobiologist
job_description = "A Xenobotanist grows and cares for a variety of abnormal, custom made, and frequently dangerous plant life. When the products of these plants \ job_description = "A Xenobotanist grows and cares for a variety of abnormal, custom made, and frequently dangerous plant life. When the products of these plants \
are both safe and beneficial to the station, they may choose to introduce it to the rest of the crew." are both safe and beneficial to the station, they may choose to introduce it to the rest of the crew."
alt_titles = list("Xenoflorist" = /datum/alt_title/xenoflorist)
/datum/alt_title/xenoflorist
title = "Xenoflorist"

View File

@@ -3,23 +3,55 @@
pto_type = PTO_SECURITY pto_type = PTO_SECURITY
dept_time_required = 60 dept_time_required = 60
access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory, access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory, access_teleporter,
access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers,
access_construction, access_construction,
access_heads, access_hos, access_RC_announce, access_keycard_auth, access_external_airlocks) access_heads, access_hos, access_RC_announce, access_keycard_auth, access_external_airlocks)
minimal_access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory, minimal_access = list(access_security, access_eva, access_sec_doors, access_brig, access_armory, access_teleporter,
access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers, access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers,
access_construction, access_construction,
access_heads, access_hos, access_RC_announce, access_keycard_auth, access_external_airlocks) access_heads, access_hos, access_RC_announce, access_keycard_auth, access_external_airlocks)
alt_titles = list("Security Commander" = /datum/alt_title/sec_commander, "Chief of Security" = /datum/alt_title/sec_chief, "Security Manager" = /datum/alt_title/security_manager)
/datum/alt_title/security_manager
title = "Security Manager"
/datum/job/warden /datum/job/warden
pto_type = PTO_SECURITY pto_type = PTO_SECURITY
dept_time_required = 20 dept_time_required = 20
alt_titles = list("Brig Sentry" = /datum/alt_title/brig_sentry, "Armory Superintendent" = /datum/alt_title/armory_superintendent)
/datum/alt_title/brig_sentry
title = "Brig Sentry"
/datum/alt_title/armory_superintendent
title = "Armory Superintendent"
/datum/job/detective /datum/job/detective
pto_type = PTO_SECURITY pto_type = PTO_SECURITY
alt_titles = list("Investigator" = /datum/alt_title/investigator, "Security Inspector" = /datum/alt_title/security_inspector, "Forensic Technician" = /datum/alt_title/forensic_tech)
/datum/alt_title/investigator
title = "Investigator"
/datum/alt_title/security_inspector
title = "Security Inspector"
/datum/job/officer /datum/job/officer
total_positions = 5 total_positions = 5
spawn_positions = 5 spawn_positions = 5
pto_type = PTO_SECURITY pto_type = PTO_SECURITY
alt_titles = list("Patrol Officer" = /datum/alt_title/patrol_officer, "Security Guard" = /datum/alt_title/security_guard,
"Security Deputy" = /datum/alt_title/security_guard, "Junior Officer" = /datum/alt_title/junior_officer)
/datum/alt_title/patrol_officer
title = "Patrol Officer"
/datum/alt_title/security_guard
title = "Security Guard"
/datum/alt_title/security_deputy
title = "Security Deputy"

View File

@@ -85,18 +85,18 @@
selection_color = "#515151" selection_color = "#515151"
economic_modifier = 1 economic_modifier = 1
job_description = "A Clown is there to entertain the crew and keep high morale using various harmless pranks and ridiculous jokes!" job_description = "A Clown is there to entertain the crew and keep high morale using various harmless pranks and ridiculous jokes!"
alt_titles = list("Clown" = /datum/alt_title/clown, "Jester" = /datum/alt_title/jester)
whitelist_only = 1 whitelist_only = 1
latejoin_only = 1 latejoin_only = 1
outfit_type = /decl/hierarchy/outfit/job/clown outfit_type = /decl/hierarchy/outfit/job/clown
pto_type = PTO_CIVILIAN pto_type = PTO_CIVILIAN
alt_titles = list("Jester" = /datum/alt_title/jester, "Fool" = /datum/alt_title/fool)
/datum/alt_title/clown
title = "Clown"
/datum/alt_title/jester /datum/alt_title/jester
title = "Jester" title = "Jester"
/datum/alt_title/fool
title = "Fool"
/datum/job/clown/get_access() /datum/job/clown/get_access()
if(config.assistant_maint) if(config.assistant_maint)
return list(access_maint_tunnels, access_entertainment) return list(access_maint_tunnels, access_entertainment)
@@ -115,17 +115,14 @@
selection_color = "#515151" selection_color = "#515151"
economic_modifier = 1 economic_modifier = 1
job_description = "A Mime is there to entertain the crew and keep high morale using unbelievable performances and acting skills!" job_description = "A Mime is there to entertain the crew and keep high morale using unbelievable performances and acting skills!"
alt_titles = list("Mime" = /datum/alt_title/mime, "Interpretive Dancer" = /datum/alt_title/interpretive_dancer) alt_titles = list("Poseur" = /datum/alt_title/poseur)
whitelist_only = 1 whitelist_only = 1
latejoin_only = 1 latejoin_only = 1
outfit_type = /decl/hierarchy/outfit/job/mime outfit_type = /decl/hierarchy/outfit/job/mime
pto_type = PTO_CIVILIAN pto_type = PTO_CIVILIAN
/datum/alt_title/mime /datum/alt_title/poseur
title = "Mime" title = "Poseur"
/datum/alt_title/interpretive_dancer
title = "Interpretive Dancer"
/datum/job/mime/get_access() /datum/job/mime/get_access()
if(config.assistant_maint) if(config.assistant_maint)

View File

@@ -85,7 +85,7 @@
if(do_after(user,30 SECONDS,src)) //CHOMPedit . Increased time to force open welded door for alien if(do_after(user,30 SECONDS,src)) //CHOMPedit . Increased time to force open welded door for alien
visible_message("<span class='danger'>\The [user] tears \the [src] open, sparks flying from its electronics!</span>") //CHOMPedit visible_message("<span class='danger'>\The [user] tears \the [src] open, sparks flying from its electronics!</span>") //CHOMPedit
src.do_animate("spark") src.do_animate("spark")
playsound(src, 'sound/machines/door/airlock_creaking.ogg', 100, 1, volume_channel = VOLUME_CHANNEL_DOORS) playsound(src, 'sound/machines/door/airlock_creaking_xeno.ogg', 100, 1, volume_channel = VOLUME_CHANNEL_DOORS) //CHOMPedit gave xeno airlock breaking its own sound effect
src.locked = 0 src.locked = 0
src.welded = 0 src.welded = 0
update_icon() update_icon()

View File

@@ -0,0 +1,122 @@
/obj/machinery/feeder
name = "\improper Feeder"
icon = 'icons/obj/feeder.dmi'
desc = "This is a feeder. Put in a reagent container, then click and drag the feeder to someone!"
anchored = FALSE
density = FALSE
var/mob/living/carbon/human/attached = null
var/obj/item/weapon/reagent_containers/beaker = null
/obj/machinery/feeder/update_icon()
if(attached)
icon_state = "feeding"
else
icon_state = ""
overlays.Cut()
if(beaker)
var/datum/reagents/reagents = beaker.reagents
if(reagents.total_volume)
var/image/filling = image('icons/obj/feeder.dmi', src, "reagent")
var/percent = round((reagents.total_volume / beaker.volume) * 100)
switch(percent)
if(0 to 9) filling.icon_state = "reagent0"
if(10 to 19) filling.icon_state = "reagent10"
if(20 to 44) filling.icon_state = "reagent20"
if(45 to 59) filling.icon_state = "reagent45"
if(60 to 74) filling.icon_state = "reagent60"
if(75 to 89) filling.icon_state = "reagent75"
if(90 to 94) filling.icon_state = "reagent90"
if(95 to INFINITY) filling.icon_state = "reagent100"
filling.icon += reagents.get_color()
overlays += filling
/obj/machinery/feeder/MouseDrop(over_object, src_location, over_location)
..()
if(!isliving(usr))
return
if(attached)
visible_message("The feeding tube is pulled out of [attached].")
attached = null
update_icon()
return
if(in_range(src, usr) && ishuman(over_object) && get_dist(over_object, src) <= 1)
visible_message("[usr] inserts the feeding tube into \the [over_object].")
attached = over_object
update_icon()
/obj/machinery/feeder/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/reagent_containers))
if(!isnull(beaker))
. += "There is already a reagent container inserted!"
return
user.drop_item()
W.loc = src
beaker = W
. += "You insert \the [W] into \the [src]."
update_icon()
return
if(default_deconstruction_screwdriver(user, W))
if(do_after(user, 15))
to_chat(user, "You deconstruct the feeder.")
var/obj/item/stack/material/plastic/A = new /obj/item/stack/material/plastic(src.loc)
A.amount = 4
if(beaker)
beaker.loc = get_turf(src)
beaker = null
qdel(src)
return
/obj/machinery/feeder/process()
set background = 1
if(attached)
if(!(get_dist(src, attached) <= 1 && isturf(attached.loc)))
visible_message("The tube is pulled out of [attached].")
attached = null
update_icon()
return
if(attached && beaker)
// Give food
if(beaker.volume > 0)
var/transfer_amount = 2
beaker.reagents.trans_to_mob(attached, transfer_amount, CHEM_INGEST)
update_icon()
/obj/machinery/feeder/attack_hand(mob/user as mob)
if(beaker)
beaker.loc = get_turf(src)
beaker = null
update_icon()
else
return ..()
/obj/machinery/feeder/examine(mob/user)
.=..()
if(!(user in view(2)) && user != src.loc) return
if(beaker)
if(beaker.reagents && beaker.reagents.reagent_list.len)
. += "<span class='notice'>Inserted is \a [beaker] with [beaker.reagents.total_volume] units of liquid.</span>"
else
. += "<span class='notice'>Inserted is an empty [beaker].</span>"
else
. += "<span class='notice'>No container is inserted.</span>"
. += "<span class='notice'>[attached ? attached : "No one"] is being fed by it.</span>"
/obj/machinery/feeder/CanPass(atom/movable/mover, turf/target, height = 0, air_group = 0)
if(height && istype(mover) && mover.checkpass(PASSTABLE)) //allow bullets, beams, thrown objects, mice, drones, and the like through.
return 1
return ..()

File diff suppressed because it is too large Load Diff

View File

@@ -67,9 +67,14 @@
//Tanning! //Tanning!
for(var/obj/item/stack/hairlesshide/HH in washing) for(var/obj/item/stack/hairlesshide/HH in washing)
var/obj/item/stack/wetleather/WL = new(src) var/obj/item/stack/WL = new HH.wet_type(src)
if(istype(WL))
WL.amount = HH.amount WL.amount = HH.amount
qdel(HH) washing -= HH
HH.forceMove(get_turf(src))
HH.use(HH.amount)
washing += WL
if(locate(/mob,washing)) if(locate(/mob,washing))
state = 7 state = 7
@@ -130,7 +135,7 @@
to_chat(user, "<span class='warning'>You can't fit \the [W] inside.</span>") to_chat(user, "<span class='warning'>You can't fit \the [W] inside.</span>")
return return
else if(istype(W, /obj/item/clothing) || istype(W, /obj/item/weapon/bedsheet)) else if(istype(W, /obj/item/clothing) || istype(W, /obj/item/weapon/bedsheet) || istype(W, /obj/item/stack/hairlesshide))
if(washing.len < 5) if(washing.len < 5)
if(state in list(1, 3)) if(state in list(1, 3))
user.drop_item() user.drop_item()

View File

@@ -21,9 +21,61 @@
/obj/item/device/starcaster_news/attack_self(mob/user as mob) /obj/item/device/starcaster_news/attack_self(mob/user as mob)
user.set_machine(src) user.set_machine(src)
ui_interact(user) //Activates nanoUI. Fuck nanoUI. tgui_interact(user) //Activates tgui. Bless tgui.
return return
/obj/item/device/starcaster_news/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "StarcasterCh", name)
ui.open()
/obj/item/device/starcaster_news/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) //Mostly ripped off from news_browser.dm
var/list/data = list()
var/list/all_articles = list()
data["showing_archived"] = show_archived
data["article"] = null
if(loaded_article) // Viewing an article.
data["article"] = list(
"title" = loaded_article.filename,
"cover" = loaded_article.cover,
"content" = loaded_article.stored_data,
)
else // Viewing list of articles
for(var/datum/computer_file/data/news_article/F in ntnet_global.available_news)
if(!show_archived && F.archived)
continue
all_articles.Add(list(list(
"name" = F.filename,
"uid" = F.uid,
"archived" = F.archived
)))
data["all_articles"] = all_articles
return data
/obj/item/device/starcaster_news/tgui_act(action, list/params, datum/tgui/ui) //Also ripped from news_browser.dm. Bless tgui
if(..())
return TRUE
switch(action)
if("PRG_openarticle")
. = TRUE
if(loaded_article)
return TRUE
for(var/datum/computer_file/data/news_article/N in ntnet_global.available_news)
if(N.uid == text2num(params["uid"]))
loaded_article = N.clone()
break
if("PRG_reset")
. = TRUE
loaded_article = null
if("PRG_toggle_archived")
. = TRUE
show_archived = !show_archived
/* Deprecated nanoUI code. Keeping mostly for reference.
/obj/item/device/starcaster_news/Topic(href, href_list) //Mostly ripped off from news_browser.dm /obj/item/device/starcaster_news/Topic(href, href_list) //Mostly ripped off from news_browser.dm
if(..()) if(..())
return 1 return 1
@@ -73,3 +125,4 @@
ui.auto_update_layout = 1 ui.auto_update_layout = 1
ui.set_initial_data(data) ui.set_initial_data(data)
ui.open() ui.open()
*/

View File

@@ -1,70 +1,75 @@
/obj/item/stack/animalhide
name = "hide"
desc = "The hide of some creature."
icon_state = "sheet-hide"
drop_sound = 'sound/items/drop/cloth.ogg'
pickup_sound = 'sound/items/pickup/cloth.ogg'
amount = 1
stacktype = "hide"
no_variants = TRUE
var/process_type = /obj/item/stack/hairlesshide
/obj/item/stack/animalhide/human /obj/item/stack/animalhide/human
name = "human skin" name = "skin"
desc = "The by-product of human farming." desc = "The by-product of sapient farming."
singular_name = "human skin piece" singular_name = "skin piece"
icon_state = "sheet-hide" icon_state = "sheet-hide"
no_variants = FALSE no_variants = FALSE
drop_sound = 'sound/items/drop/leather.ogg' drop_sound = 'sound/items/drop/leather.ogg'
pickup_sound = 'sound/items/pickup/leather.ogg' pickup_sound = 'sound/items/pickup/leather.ogg'
amount = 1
/obj/item/stack/animalhide/human stacktype = "hide-human"
amount = 50
/obj/item/stack/animalhide/corgi /obj/item/stack/animalhide/corgi
name = "corgi hide" name = "corgi hide"
desc = "The by-product of corgi farming." desc = "The by-product of corgi farming."
singular_name = "corgi hide piece" singular_name = "corgi hide piece"
icon_state = "sheet-corgi" icon_state = "sheet-corgi"
amount = 1
/obj/item/stack/animalhide/corgi stacktype = "hide-corgi"
amount = 50
/obj/item/stack/animalhide/cat /obj/item/stack/animalhide/cat
name = "cat hide" name = "cat hide"
desc = "The by-product of cat farming." desc = "The by-product of cat farming."
singular_name = "cat hide piece" singular_name = "cat hide piece"
icon_state = "sheet-cat" icon_state = "sheet-cat"
amount = 1
/obj/item/stack/animalhide/cat stacktype = "hide-cat"
amount = 50
/obj/item/stack/animalhide/monkey /obj/item/stack/animalhide/monkey
name = "monkey hide" name = "monkey hide"
desc = "The by-product of monkey farming." desc = "The by-product of monkey farming."
singular_name = "monkey hide piece" singular_name = "monkey hide piece"
icon_state = "sheet-monkey" icon_state = "sheet-monkey"
amount = 1
/obj/item/stack/animalhide/monkey stacktype = "hide-monkey"
amount = 50
/obj/item/stack/animalhide/lizard /obj/item/stack/animalhide/lizard
name = "lizard skin" name = "lizard skin"
desc = "Sssssss..." desc = "Sssssss..."
singular_name = "lizard skin piece" singular_name = "lizard skin piece"
icon_state = "sheet-lizard" icon_state = "sheet-lizard"
amount = 1
/obj/item/stack/animalhide/lizard stacktype = "hide-lizard"
amount = 50
/obj/item/stack/animalhide/xeno /obj/item/stack/animalhide/xeno
name = "alien hide" name = "alien hide"
desc = "The skin of a terrible creature." desc = "The skin of a terrible creature."
singular_name = "alien hide piece" singular_name = "alien hide piece"
icon_state = "sheet-xeno" icon_state = "sheet-xeno"
amount = 1
/obj/item/stack/animalhide/xeno stacktype = "hide-xeno"
amount = 50
//don't see anywhere else to put these, maybe together they could be used to make the xenos suit? //don't see anywhere else to put these, maybe together they could be used to make the xenos suit?
/obj/item/stack/xenochitin /obj/item/stack/xenochitin
name = "alien chitin" name = "alien chitin"
desc = "A piece of the hide of a terrible creature." desc = "A piece of the hide of a terrible creature."
singular_name = "alien hide piece" singular_name = "alien chitin piece"
icon = 'icons/mob/alien.dmi' icon = 'icons/mob/alien.dmi'
icon_state = "chitin" icon_state = "chitin"
amount = 1
/obj/item/stack/xenochitin stacktype = "hide-chitin"
amount = 50
/obj/item/xenos_claw /obj/item/xenos_claw
name = "alien claw" name = "alien claw"
@@ -84,9 +89,22 @@
singular_name = "hairless hide piece" singular_name = "hairless hide piece"
icon_state = "sheet-hairlesshide" icon_state = "sheet-hairlesshide"
no_variants = FALSE no_variants = FALSE
amount = 1
stacktype = "hairlesshide"
var/cleaning = FALSE // Can we be water_acted, or are we busy? To prevent accidental hide duplication and the collapse of causality.
/obj/item/stack/hairlesshide var/wet_type = /obj/item/stack/wetleather
amount = 50
/obj/item/stack/hairlesshide/water_act(var/wateramount)
..()
cleaning = TRUE
while(amount > 0 && wateramount > 0)
use(1)
wateramount--
new wet_type(get_turf(src))
cleaning = FALSE
return
/obj/item/stack/wetleather /obj/item/stack/wetleather
name = "wet leather" name = "wet leather"
@@ -96,28 +114,27 @@
var/wetness = 30 //Reduced when exposed to high temperautres var/wetness = 30 //Reduced when exposed to high temperautres
var/drying_threshold_temperature = 500 //Kelvin to start drying var/drying_threshold_temperature = 500 //Kelvin to start drying
no_variants = FALSE no_variants = FALSE
amount = 1
stacktype = "wetleather"
/obj/item/stack/wetleather var/dry_type = /obj/item/stack/material/leather
amount = 50
//Step one - dehairing. //Step one - dehairing.
/obj/item/stack/animalhide/attackby(obj/item/weapon/W as obj, mob/user as mob) /obj/item/stack/animalhide/attackby(obj/item/weapon/W as obj, mob/user as mob)
if( istype(W, /obj/item/weapon/material/knife) || \ if(has_edge(W) || is_sharp(W))
istype(W, /obj/item/weapon/material/twohanded/fireaxe) || \
istype(W, /obj/item/weapon/material/knife/machete/hatchet) )
//visible message on mobs is defined as visible_message(var/message, var/self_message, var/blind_message) //visible message on mobs is defined as visible_message(var/message, var/self_message, var/blind_message)
usr.visible_message("<span class='notice'>\The [usr] starts cutting hair off \the [src]</span>", "<span class='notice'>You start cutting the hair off \the [src]</span>", "You hear the sound of a knife rubbing against flesh") usr.visible_message("<span class='notice'>\The [usr] starts cutting hair off \the [src]</span>", "<span class='notice'>You start cutting the hair off \the [src]</span>", "You hear the sound of a knife rubbing against flesh")
if(do_after(user,50)) if(do_after(user,50))
to_chat(usr, "<span class='notice'>You cut the hair from this [src.singular_name]</span>") to_chat(usr, "<span class='notice'>You cut the hair from this [src.singular_name]</span>")
//Try locating an exisitng stack on the tile and add to there if possible //Try locating an exisitng stack on the tile and add to there if possible
for(var/obj/item/stack/hairlesshide/HS in usr.loc) for(var/obj/item/stack/hairlesshide/HS in usr.loc)
if(HS.amount < 50) if(HS.amount < 50 && istype(HS, process_type))
HS.amount++ HS.amount++
src.use(1) src.use(1)
break return
//If it gets to here it means it did not find a suitable stack on the tile. //If it gets to here it means it did not find a suitable stack on the tile.
var/obj/item/stack/hairlesshide/HS = new(usr.loc) var/obj/item/stack/HS = new process_type(usr.loc)
if(istype(HS))
HS.amount = 1 HS.amount = 1
src.use(1) src.use(1)
else else
@@ -132,15 +149,20 @@
if(exposed_temperature >= drying_threshold_temperature) if(exposed_temperature >= drying_threshold_temperature)
wetness-- wetness--
if(wetness == 0) if(wetness == 0)
dry()
/obj/item/stack/wetleather/proc/dry()
//Try locating an exisitng stack on the tile and add to there if possible //Try locating an exisitng stack on the tile and add to there if possible
for(var/obj/item/stack/material/leather/HS in src.loc) for(var/obj/item/stack/material/leather/HS in src.loc)
if(HS.amount < 50) if(HS.amount < 50)
HS.amount++ HS.amount++
src.use(1)
wetness = initial(wetness) wetness = initial(wetness)
break src.use(1)
return
//If it gets to here it means it did not find a suitable stack on the tile. //If it gets to here it means it did not find a suitable stack on the tile.
var/obj/item/stack/material/leather/HS = new(src.loc) var/obj/item/stack/HS = new dry_type(src.loc)
if(istype(HS))
HS.amount = 1 HS.amount = 1
wetness = initial(wetness) wetness = initial(wetness)
src.use(1) src.use(1)

View File

@@ -380,7 +380,7 @@
var/use_material var/use_material
var/pass_color var/pass_color
New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0, supplied_material = null, pass_stack_color) /datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0, supplied_material = null, pass_stack_color)
src.title = title src.title = title
src.result_type = result_type src.result_type = result_type
src.req_amount = req_amount src.req_amount = req_amount

View File

@@ -1,9 +1,9 @@
/obj/item/weapon/implant/reagent_generator/egg /obj/item/weapon/implant/reagent_generator/egg
name = "egg laying implant" name = "regular egg laying implant"
desc = "This is an implant that allows the user to lay eggs." desc = "This is an implant that allows the user to lay eggs."
generated_reagents = list("egg" = 2) generated_reagents = list("egg" = 2)
usable_volume = 500 usable_volume = 1500
transfer_amount = 50 transfer_amount = 300
var/verb_descriptor = list("squeezes", "pushes", "hugs") var/verb_descriptor = list("squeezes", "pushes", "hugs")
var/self_verb_descriptor = list("squeeze", "push", "hug") var/self_verb_descriptor = list("squeeze", "push", "hug")
var/short_emote_descriptor = list("lays", "forces out", "pushes out") var/short_emote_descriptor = list("lays", "forces out", "pushes out")
@@ -11,11 +11,13 @@
random_emote = list("lets out an embarrassed moan", "yelps in embarrassment", "quietly groans in a mixture of discomfort and pleasure") random_emote = list("lets out an embarrassed moan", "yelps in embarrassment", "quietly groans in a mixture of discomfort and pleasure")
assigned_proc = /mob/living/carbon/human/proc/use_reagent_implant_egg assigned_proc = /mob/living/carbon/human/proc/use_reagent_implant_egg
var/eggtype = /obj/item/weapon/reagent_containers/food/snacks/egg var/eggtype = /obj/item/weapon/reagent_containers/food/snacks/egg
var/cascade
/obj/item/weapon/implant/reagent_generator/egg/post_implant(mob/living/carbon/source) /obj/item/weapon/implant/reagent_generator/egg/post_implant(mob/living/carbon/source)
START_PROCESSING(SSobj, src) START_PROCESSING(SSobj, src)
to_chat(source, "<span class='notice'>You implant [source] with \the [src].</span>") to_chat(source, "<span class='notice'>You implant [source] with \the [src].</span>")
source.verbs |= assigned_proc source.verbs |= assigned_proc
source.verbs |= /mob/living/carbon/human/proc/toggle_cascade
return 1 return 1
/mob/living/carbon/human/proc/use_reagent_implant_egg() /mob/living/carbon/human/proc/use_reagent_implant_egg()
@@ -51,8 +53,9 @@
to_chat(usr, "<span class='notice'>It seems that [src] is out of eggs!</span>") to_chat(usr, "<span class='notice'>It seems that [src] is out of eggs!</span>")
to_chat(src, "<span class='notice'>[pick(rimplant.empty_message)]</span>") to_chat(src, "<span class='notice'>[pick(rimplant.empty_message)]</span>")
return return
visible_message("<span class='notice'>[usr] starts squeezing [src]'s lower body firmly...</span>") visible_message("<span class='danger'>[usr] starts squeezing [src]'s lower body firmly...</span>")
if (rimplant && do_after(usr,60)) if (rimplant && do_after(usr,120,src))
if(src.Adjacent(usr))
var/egg = rimplant.eggtype var/egg = rimplant.eggtype
new egg(get_turf(src)) new egg(get_turf(src))
src.SetStunned(3) src.SetStunned(3)
@@ -73,37 +76,59 @@
visible_message("<span class='notice'>[src] [pick(rimplant.random_emote)].</span>") visible_message("<span class='notice'>[src] [pick(rimplant.random_emote)].</span>")
rimplant.reagents.remove_any(rimplant.transfer_amount) rimplant.reagents.remove_any(rimplant.transfer_amount)
if(prob(70*rimplant.reagents.total_volume/rimplant.usable_volume)) if(rimplant.cascade)
to_chat(src, "<span class='notice'>You feel your legs quake as your muscles fail to stand strong!</span>") to_chat(src, "<span class='notice'>You feel your legs quake as your muscles fail to stand strong!</span>")
while(rimplant.reagents.total_volume >= rimplant.transfer_amount) while(rimplant.reagents.total_volume >= rimplant.transfer_amount)
if(do_after(src,30)) if(do_after(src,30))
src.SetStunned(5) src.SetStunned(3)
playsound(src,'sound/vore/insert.ogg',50,1) playsound(src,'sound/vore/insert.ogg',50,1)
src.apply_effect(10,STUTTER,0) src.apply_effect(10,STUTTER,0)
new egg(get_turf(src)) new egg(get_turf(src))
rimplant.reagents.remove_any(rimplant.transfer_amount) rimplant.reagents.remove_any(rimplant.transfer_amount)
if(prob(25)) if(prob(25))
visible_message("<span class='notice'>[src] [pick(rimplant.random_emote)].</span>") visible_message("<span class='notice'>[src] [pick(rimplant.random_emote)].</span>")
else
return
/mob/living/carbon/human/proc/toggle_cascade()
set name = "Toggle cascading"
set desc = "Toggle whether or not being forced to lay an egg will cause you to lay all others as well, in rapid succession"
set category = "Local"
var/obj/item/weapon/implant/reagent_generator/egg/rimplant
for(var/obj/item/organ/external/E in organs)
for(var/obj/item/weapon/implant/I in E.implants)
if(istype(I, /obj/item/weapon/implant/reagent_generator))
rimplant = I
break
if(rimplant.cascade)
rimplant.cascade = 0
to_chat(src, "<span class='notice'>You toggle cascading off</span>")
else
rimplant.cascade = 1
to_chat(src, "<span class='notice'>You toggle cascading on</span>")
/obj/item/weapon/implant/reagent_generator/egg/slow /obj/item/weapon/implant/reagent_generator/egg/slow
name = "slow egg laying implant" name = "slow egg laying implant"
usable_volume = 3000 usable_volume = 3000
transfer_amount = 300 transfer_amount = 600
/obj/item/weapon/implant/reagent_generator/egg/veryslow /obj/item/weapon/implant/reagent_generator/egg/veryslow
name = "very slow egg laying implant" name = "very slow egg laying implant"
usable_volume = 6000 usable_volume = 6000
transfer_amount = 600 transfer_amount = 1200
/obj/item/weapon/implant/reagent_generator/egg/hicap /obj/item/weapon/implant/reagent_generator/egg/hicap
name = "high capacity egg laying implant" // Note that the capacity does not affect the regeneration rate, rather, the transfer amount does name = "high capacity egg laying implant" // Note that the capacity does not affect the regeneration rate, rather, the transfer amount does
usable_volume = 1000 // Effectively, the transfer_amount is the cost/time of making an egg. Usable volume is simply the max number of eggs. usable_volume = 3000 // Effectively, the transfer_amount is the cost/time of making an egg. Usable volume is simply the max number of eggs.
transfer_amount = 50 transfer_amount = 300
/obj/item/weapon/implant/reagent_generator/egg/doublehicap /obj/item/weapon/implant/reagent_generator/egg/doublehicap
name = "extreme capacity egg laying implant" name = "extreme capacity egg laying implant"
usable_volume = 2000 usable_volume = 6000
transfer_amount = 50 transfer_amount = 300
/obj/item/weapon/implant/reagent_generator/egg/slowlowcap /obj/item/weapon/implant/reagent_generator/egg/slowlowcap
name = "slow, low capacity egg laying implant" name = "slow, low capacity egg laying implant"

View File

@@ -68,7 +68,7 @@
item_state = "candlebox5" item_state = "candlebox5"
throwforce = 2 throwforce = 2
slot_flags = SLOT_BELT slot_flags = SLOT_BELT
max_storage_space = ITEMSIZE_COST_SMALL * 5 max_storage_space = ITEMSIZE_COST_TINY * 5 //CHOMPEdit
starts_with = list(/obj/item/weapon/flame/candle = 5) starts_with = list(/obj/item/weapon/flame/candle = 5)
/obj/item/weapon/storage/fancy/whitecandle_box /obj/item/weapon/storage/fancy/whitecandle_box
@@ -80,7 +80,7 @@
item_state = "whitecandlebox5" item_state = "whitecandlebox5"
throwforce = 2 throwforce = 2
slot_flags = SLOT_BELT slot_flags = SLOT_BELT
max_storage_space = ITEMSIZE_COST_SMALL * 5 max_storage_space = ITEMSIZE_COST_TINY * 5 //CHOMPEdit
starts_with = list(/obj/item/weapon/flame/candle/white = 5) starts_with = list(/obj/item/weapon/flame/candle/white = 5)
/obj/item/weapon/storage/fancy/blackcandle_box /obj/item/weapon/storage/fancy/blackcandle_box
@@ -92,7 +92,7 @@
item_state = "blackcandlebox5" item_state = "blackcandlebox5"
throwforce = 2 throwforce = 2
slot_flags = SLOT_BELT slot_flags = SLOT_BELT
max_storage_space = ITEMSIZE_COST_SMALL * 5 max_storage_space = ITEMSIZE_COST_TINY * 5 //CHOMPEdit
starts_with = list(/obj/item/weapon/flame/candle/black = 5) starts_with = list(/obj/item/weapon/flame/candle/black = 5)

View File

@@ -0,0 +1,7 @@
/obj/item/weapon/storage/fancy/cigar/cohiba
name = "cohiban cigar case"
starts_with = list(/obj/item/clothing/mask/smokable/cigarette/cigar/cohiba = 7)
/obj/item/weapon/storage/fancy/cigar/havana
name = "havanian cigar case"
starts_with = list(/obj/item/clothing/mask/smokable/cigarette/cigar/havana = 7)

View File

@@ -349,6 +349,8 @@
to_chat(user, "<span class='danger'>You go blind!</span>") to_chat(user, "<span class='danger'>You go blind!</span>")
user.Blind(5) user.Blind(5)
user.eye_blurry = 5 user.eye_blurry = 5
// Don't cure being nearsighted
if(!(H.disabilities & NEARSIGHTED))
user.disabilities |= NEARSIGHTED user.disabilities |= NEARSIGHTED
spawn(100) spawn(100)
user.disabilities &= ~NEARSIGHTED user.disabilities &= ~NEARSIGHTED

View File

@@ -0,0 +1,96 @@
//Try not to question it too hard. These are the spicy tools.
/obj/item/weapon/tool/crowbar/heavysniper
name = "anti-materiel sniper crowbar"
desc = "This abomination or piece of art, depending on how you view it, seems to use a 14.5mm anti-materiel sniper rifle to the same effect of a crowbar."
icon = 'icons/obj/gun.dmi'
icon_state = "heavysniper"
item_icons = list(slot_l_hand_str = 'icons/mob/items/lefthand_guns.dmi',slot_r_hand_str = 'icons/mob/items/righthand_guns.dmi')
item_state = "heavysniper"
toolspeed = 0.1
force = 30
usesound = 'sound/weapons/Gunshot_cannon.ogg'
/obj/item/weapon/weldingtool/lasercannon
name = "laser cannon welding tool"
desc = "This abomination or piece of art, depending on how you view it, seems to be a laser cannon converted into a welding tool."
icon = 'icons/obj/gun.dmi'
icon_state = "lasercannon"
item_icons = list(slot_l_hand_str = 'icons/mob/items/lefthand_guns.dmi',slot_r_hand_str = 'icons/mob/items/righthand_guns.dmi')
item_state = "mhdhowitzer-wielded"
toolspeed = 0.1
usesound = 'sound/weapons/lasercannonfire.ogg'
acti_sound = 'sound/weapons/kenetic_reload.ogg'
always_process = TRUE
/obj/item/weapon/weldingtool/lasercannon/process()
if(get_fuel() <= get_max_fuel())
reagents.add_reagent("fuel", 1)
..()
/obj/item/weapon/weldingtool/lasercannon/update_icon()
// Lights
if(welding && flame_intensity)
set_light(flame_intensity, flame_intensity, flame_color)
else
set_light(0)
// icon_state = welding ? "[icon_state]1" : "[initial(icon_state)]"
var/mob/M = loc
if(istype(M))
M.update_inv_l_hand()
M.update_inv_r_hand()
/obj/item/weapon/tool/wrench/fuelrod
name = "fuel-rod cannon wrench"
desc = "This abomination or piece of art, depending on how you view it, seems to by some means use a fuel rod cannon as a wrench... how this is possible, one can only theorize."
icon = 'icons/obj/railgun.dmi'
icon_state = "fuelrodgun"
item_icons = list(slot_l_hand_str = 'icons/mob/items/lefthand_guns.dmi',slot_r_hand_str = 'icons/mob/items/righthand_guns.dmi')
item_state = "coilgun"
usesound = 'sound/weapons/railgun.ogg'
toolspeed = 0.1
force = 30
/obj/item/weapon/tool/wirecutters/chainsaw
name = "chainsaw wirecutters"
desc = "This abomination or piece of art, depending on how you view it, seems to be a chainsaw that is by some means converted into wirecutters."
icon = 'icons/obj/weapons.dmi'
icon_state = "chainsaw0"
item_state = "chainsaw0"
usesound = 'sound/weapons/chainsaw_attack.ogg'
random_color = FALSE
toolspeed = 0.1
force = 30
/obj/item/weapon/tool/screwdriver/diamonddrill
name = "diamond drill power screwdriver"
desc = "This abomination or piece of art, depending on how you view it, seems to be a diamond drill that was converted into a power screwdriver."
icon = 'icons/obj/items.dmi'
icon_state = "diamonddrill"
item_state = "jackhammer"
hitsound = 'sound/items/drill_hit.ogg'
usesound = 'sound/items/drill_use.ogg'
random_color = FALSE
toolspeed = 0.1
force = 30
/obj/item/stack/cable_coil/alien/blood
name = "Blood cable coil"
desc = "This seems to be a blood red cable coil which magically replenishes itself, and if you look closely at the insulation you can read the words \"forged from the blood of our enemies\""
icon = 'icons/obj/power.dmi'
icon_state = "coil"
item_state = "coil"
color = "#8A0303"
catalogue_data = null
toolspeed = 0.1
/obj/item/weapon/storage/belt/utility/spicyfull
starts_with = list(
/obj/item/weapon/tool/crowbar/heavysniper,
/obj/item/weapon/weldingtool/lasercannon,
/obj/item/weapon/tool/wrench/fuelrod,
/obj/item/weapon/tool/wirecutters/chainsaw,
/obj/item/weapon/tool/screwdriver/diamonddrill,
/obj/item/stack/cable_coil/alien/blood
)

View File

@@ -0,0 +1,230 @@
/obj/kbutton
name = "button"
icon = 'icons/obj/objects.dmi'
icon_state = "launcherbtt"
desc = "A remote control switch for something."
anchored = 1.0
var/nothing_sound_file //Sound to play when button fails to be pressed
var/nothing_sound_volume //Volume of sound when button fails to be pressed
var/pressed_sound_file = 'sound/machines/button.ogg'//Sound to play when button is successfully pressed
var/pressed_sound_volume = 100 //Volume of sound when button is successfully pressed
var/list/trig_target_paths = list() //What are the paths of whatever we want to call our proc on?
var/trig_target_trigger_uid //What is the trigger_uid of whatever we want to call our proc on?
var/trig_proc //What proc do we want to call?
var/list/trig_args = list() //What are the arguments for said proc?
var/trig_message = "You press the button" //Should we send a message to the person who pressed the button?
var/trig_message_span_class = "notice" //Span class used for pressed message, normal ones include notice, warning, and danger.
var/nothing_message = "Nothing happens." //Should we send a message if nothing happens when the button is pressed?
var/nothing_message_span_class = "warning" //Span class used for nothing message, normal ones include notice, warning, and danger.
var/list/trig_targets = list()
var/trig_target_is_trigerrer = FALSE //Should we use the button presser as the target?
/obj/kbutton/attackby(obj/item/weapon/W, mob/user as mob)
return attack_hand(user)
/obj/kbutton/attack_hand(mob/user as mob)
. = ..()
if(can_press(user))
if(trig_target_is_trigerrer)
trig_targets = list(user)
button_trigger()
if(pressed_sound_file)
playsound(src, pressed_sound_file, pressed_sound_volume, 1)
if(trig_message)
to_chat(user,"<span class='[trig_message_span_class]'>"+trig_message+"</span>")
else
if(nothing_sound_file)
playsound(src, nothing_sound_file, nothing_sound_volume, 1)
if(nothing_message)
to_chat(user,"<span class='[nothing_message_span_class]'>"+nothing_message+"</span>")
return
/obj/kbutton/proc/button_trigger()
if(trig_proc)
if(trig_targets.len)
var/testname = trig_proc
//Find one of the 3 possible ways they could have written /proc/PROCNAME
if(findtext(trig_proc, "/proc/"))
testname = replacetext(trig_proc, "/proc/", "")
else if(findtext(trig_proc, "/proc"))
testname = replacetext(trig_proc, "/proc", "")
else if(findtext(trig_proc, "proc/"))
testname = replacetext(trig_proc, "proc/", "")
//Clear out any parenthesis if they're a dummy
testname = replacetext(testname, "()", "")
for(var/trig_target in trig_targets)
if(trig_target && !hascall(trig_target,testname))
message_admins("TRIGGER ERROR: ONE OR MORE TRIGGER TARGETS LACKS THE MENTIONED PROC")
return
for(var/trig_target in trig_targets)
call(trig_target,testname)(arglist(trig_args))
else
var/procpath = text2path(trig_proc)
if(!procpath)
message_admins("TRIGGER ERROR: INVALID PROC")
return
call(procpath)(arglist(trig_args))
/obj/kbutton/proc/can_press(mob/user)
return TRUE
/obj/kbutton/proc/update_trig_targets()
trig_targets = list()
for(var/path in trig_target_paths)
var/trig_target_path = text2path(path)
if(trig_target_path && trig_target_trigger_uid)
var/list/candidates = get_all_of_type(trig_target_path)
for(var/candidate in candidates)
var/datum/cand_datum = candidate
if(istype(cand_datum))
if(cand_datum.trigger_uid == trig_target_trigger_uid)
trig_targets += candidate
continue
continue
if(!trig_targets.len)
message_admins("TRIGGER ERROR: trig_targets STILL EMPTY AFTER CALLED update_trig_targets()")
/obj/kbutton/Initialize(mapload)
. = ..()
update_trig_targets()
return
/obj/kbutton/single_use
name = "single use button"
var/has_been_pressed = FALSE
/obj/kbutton/single_use/button_trigger()
has_been_pressed = TRUE
..()
/obj/kbutton/single_use/can_press(mob/user)
return !has_been_pressed
/obj/kbutton/single_use_per_mob
name = "button"
var/list/been_triggered_by = list()
/obj/kbutton/single_use_per_mob/can_press(mob/user)
if(user in been_triggered_by)
return FALSE
else
been_triggered_by |= user
return TRUE
/obj/kbutton/toggle
name = "toggle button"
var/toggled = FALSE
//For each of the following, each of the following variables will be used when switching to that state,
//and if it's set to null, it will use def(short for default)
var/trig_message_types = list(\
"def" = "You toggle the button.", \
"on" = null, \
"off" = null)
var/nothing_message_types = list(\
"def" = "Nothing happens.", \
"on" = null, \
"off" = null)
var/pressed_sound_file_types = list(\
"def" = 'sound/machines/button.ogg', \
"on" = null, \
"off" = null)
var/pressed_sound_volume_types = list(\
"def" = 100, \
"on" = null, \
"off" = null)
var/nothing_sound_file_types = list(\
"def" = null, \
"on" = null, \
"off" = null)
var/nothing_sound_volume_types = list(\
"def" = null, \
"on" = null, \
"off" = null)
var/icon_types = list(\
"def" = 'icons/obj/objects.dmi', \
"on" = null, \
"off" = null)
var/icon_state_types = list(\
"def" = "launcherbtt", \
"on" = null, \
"off" = null)
var/trig_proc_types = list(\
"def" = null, \
"on" = null, \
"off" = null)
var/trig_args_types = list(\
"def" = list(), \
"on" = list(), \
"off" = list())
/obj/kbutton/toggle/Initialize(mapload)
. = ..()
update_variables()
/obj/kbutton/toggle/proc/update_variables()
var/index = toggled ? "on" : "off"
trig_message = trig_message_types[index] ? trig_message_types[index] : trig_message_types["def"]
nothing_message = nothing_message_types[index] ? nothing_message_types[index] : nothing_message_types["def"]
pressed_sound_file = pressed_sound_file_types[index] ? pressed_sound_file_types[index] : pressed_sound_file_types["def"]
pressed_sound_volume = pressed_sound_volume_types[index] ? pressed_sound_volume_types[index] : pressed_sound_volume_types["def"]
nothing_sound_file = nothing_sound_file_types[index] ? nothing_sound_file_types[index] : nothing_sound_file_types["def"]
nothing_sound_volume = nothing_sound_volume_types[index] ? nothing_sound_volume_types[index] : nothing_sound_volume_types["def"]
icon = icon_types[index] ? icon_types[index] : icon_types["def"]
icon_state = icon_state_types[index] ? icon_state_types[index] : icon_state_types["def"]
trig_proc = trig_proc_types[index] ? trig_proc_types[index] : trig_proc_types["def"]
trig_args = trig_args_types[index].len ? trig_args_types[index] : trig_args_types["def"]
/obj/kbutton/toggle/button_trigger()
toggled = !toggled
update_variables()
..()
//An example button which opens and closes a closet.
/obj/kbutton/toggle/example
var/press_wait_time = 25
var/last_pressed = 0
trig_target_paths = list("/obj/structure/closet")
trig_target_trigger_uid = 97482
trig_message_types = list(\
"def" = "You toggle the button.", \
"on" = "You switch the button on.", \
"off" = "You switch the button off.")
nothing_message_types = list(\
"def" = "Nothing happens.", \
"on" = "You fail to switch the button off.", \
"off" = "You fail to switch the button on.")
pressed_sound_file_types = list(\
"def" = 'sound/machines/button.ogg', \
"on" = 'sound/machines/chime.ogg', \
"off" = 'sound/machines/buttonbeep.ogg')
pressed_sound_volume_types = list(\
"def" = 80, \
"on" = 80, \
"off" = 80)
nothing_sound_file_types = list(\
"def" = 'sound/machines/buzz-sigh.ogg', \
"on" = 'sound/machines/buzz-sigh.ogg', \
"off" = 'sound/machines/buzz-two.ogg')
nothing_sound_volume_types = list(\
"def" = 100, \
"on" = 100, \
"off" = 100)
icon_state_types = list(\
"def" = "launcherbtt", \
"on" = "launcheract", \
"off" = "launcherbtt")
trig_proc_types = list(\
"def" = "close", \
"on" = "open", \
"off" = "close")
/obj/kbutton/toggle/example/can_press(mob/user)
if(world.time > last_pressed + press_wait_time)
last_pressed = world.time
return TRUE
else
return FALSE
//Corresponding closet for example button
/obj/structure/closet/button_example
trigger_uid = 97482

View File

@@ -250,6 +250,16 @@
removed.add_thermal_energy(heat_transfer) removed.add_thermal_energy(heat_transfer)
for(var/mob/living/L in view(3, src))
L.add_modifier(/datum/modifier/endothermic, 10 SECONDS, null, TRUE)
for(var/obj/item/stack/wetleather/WL in view(2, src))
if(WL.wetness >= 0)
WL.dry()
continue
WL.wetness = max(0, WL.wetness - rand(1, 4))
env.merge(removed) env.merge(removed)
/obj/structure/bonfire/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) /obj/structure/bonfire/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)

View File

@@ -494,3 +494,47 @@
/obj/structure/flora/sif/tendrils/get_harvestable_desc() /obj/structure/flora/sif/tendrils/get_harvestable_desc()
return "<span class='notice'>\The [src] seems to be growing over something.</span>" return "<span class='notice'>\The [src] seems to be growing over something.</span>"
/datum/category_item/catalogue/flora/frostbelle
name = "Sivian Flora - Frostbelle"
desc = "A rare plant native to Sif, with very peculiar growing requirements. Rarely seen outside of their original habitat,\
or the homes of the wealthy, the plant's unique vein structure is actually used to carry the plant's reproductive material \
to forming buds, the petals of which secrete the luminescent sap containing the pollen at the time of blooming. Certain \
horticulturists have found ways of halting this process prior to the secretion of the sap, leaving the flower's petals \
bright, at the cost of making that bud sterile."
value = CATALOGUER_REWARD_HARD
/obj/structure/flora/sif/frostbelle
name = "gnarly shrub"
desc = "A stocky plant with fins bearing luminescent veins along its branches."
icon_state = "grass"
randomize_size = TRUE
catalogue_data = list(/datum/category_item/catalogue/flora/frostbelle)
harvest_tool = /obj/item/weapon/material/knife
max_harvests = 2
min_harvests = -4
harvest_loot = list(
/obj/item/weapon/reagent_containers/food/snacks/frostbelle = 1
)
var/variantnum = null
/obj/structure/flora/sif/frostbelle/Initialize()
. = ..()
variantnum = rand(1,3)
update_icon()
/obj/structure/flora/sif/frostbelle/update_icon()
..()
if(max_harvests > 0 && harvest_count < max_harvests)
icon_state = "[initial(icon_state)][variantnum]"
else
icon_state = initial(icon_state)
/obj/structure/flora/sif/frostbelle/get_harvestable_desc()
return "<span class='notice'>\The [src] seems to be budding.</span>"

View File

@@ -0,0 +1,313 @@
/obj/structure/reflector
name = "reflector base"
icon = 'icons/obj/tgs_structures_ch.dmi'
icon_state = "reflector_map"
desc = "A base for reflector assemblies."
anchored = FALSE
density = FALSE
var/deflector_icon_state
var/image/deflector_overlay
var/finished = FALSE
var/admin = FALSE //Can't be rotated or deconstructed
var/can_rotate = TRUE
var/framebuildstacktype = /obj/item/stack/material//metal
var/framebuildstackamount = 5
var/buildstacktype = /obj/item/stack/material//metal
var/buildstackamount = 0
var/fires_projectile = /obj/item/projectile/beam/emitter
var/fires_accuracy = 10000
var/fires_dispersion = 0
var/list/allowed_projectile_typecache = list(/obj/item/projectile/beam)
var/rotation_angle = -1
var/can_decon = TRUE
var/list/has_projectiles = list()
var/bullet_act_in_progress = FALSE
/obj/structure/reflector/Initialize()
. = ..()
icon_state = "reflector_base"
allowed_projectile_typecache = typecacheof(allowed_projectile_typecache)
if(deflector_icon_state)
deflector_overlay = image(icon, deflector_icon_state)
add_overlay(deflector_overlay)
if(rotation_angle == -1)
setAngle(dir2angle(dir))
else
setAngle(rotation_angle)
if(admin)
can_rotate = FALSE
SSreflector.processing += src
/obj/structure/reflector/examine(mob/user)
. = ..()
if(finished)
. += "It is set to [rotation_angle] degrees, and the rotation is [can_rotate ? "unlocked" : "locked"]."
if(!admin)
if(can_rotate)
. += "<span class='notice'>Alt-click to adjust its direction.</span>"
else
. += "<span class='notice'>Use screwdriver to unlock the rotation.</span>"
/obj/structure/reflector/proc/Fire()
UNTIL(!bullet_act_in_progress)
var/list/angles = list()
for(var/obj/item/projectile/P in has_projectiles)
angles[num2text(has_projectiles[P])] += P.damage
for(var/angle in angles)
var/obj/item/projectile/P = new fires_projectile(src)
P.firer = src
P.damage = angles[angle]
P.accuracy = 350
P.dispersion = 0
P.fire(text2num(angle))
has_projectiles = list()
/obj/structure/reflector/proc/setAngle(new_angle)
if(can_rotate)
rotation_angle = new_angle
if(deflector_overlay)
cut_overlay(deflector_overlay)
deflector_overlay.transform = turn(matrix(), new_angle)
add_overlay(deflector_overlay)
/obj/structure/reflector/proc/redirect_projectile(obj/item/projectile/P,pangle)
has_projectiles[P] = pangle
qdel(P)
/obj/structure/reflector/set_dir(new_dir)
return ..(NORTH)
/obj/structure/reflector/Crossed(atom/movable/AM) //Ok so this is my solution to garbage projectile code. Please god let this work.
if(istype(AM,/obj/item/projectile))
AM.Bump(src)
/obj/structure/reflector/bullet_act(obj/item/projectile/P)
bullet_act_in_progress = TRUE
var/pdir = P.dir
var/pangle = P.Angle
var/ploc = get_turf(P)
if(!finished || !allowed_projectile_typecache[P.type] || !(P.dir in cardinal))
return ..()
if(auto_reflect(P, pdir, ploc, pangle) != 2)
return ..()
bullet_act_in_progress = FALSE
/obj/structure/reflector/proc/auto_reflect(obj/item/projectile/P, pdir, turf/ploc, pangle)
P.ignore_source_check = TRUE
return 2
/obj/structure/reflector/attackby(obj/item/W, mob/user, params)
if(admin)
return
if(W.is_screwdriver())
can_rotate = !can_rotate
to_chat(user, "<span class='notice'>You [can_rotate ? "unlock" : "lock"] [src]'s rotation.</span>")
playsound(W, W.usesound, 50, 1)
return
if(W.is_wrench() && can_decon)
if(anchored)
to_chat(user, "<span class='warning'>Unweld [src] from the floor first!</span>")
return
user.visible_message("<span class='notice'>[user] starts to dismantle [src].</span>", "<span class='notice'>You start to dismantle [src]...</span>")
to_chat(user, "<span class='notice'>You dismantle [src].</span>")
new framebuildstacktype(drop_location(), framebuildstackamount)
if(buildstackamount)
new buildstacktype(drop_location(), buildstackamount)
qdel(src)
else if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/I = W
if(!anchored)
if(!I.remove_fuel(1,user))
return
user.visible_message("<span class='notice'>[user] starts to weld [src] to the floor.</span>",
"<span class='notice'>You start to weld [src] to the floor...</span>",
"<span class='hear'>You hear welding.</span>")
anchored = TRUE
to_chat(user, "<span class='notice'>You weld [src] to the floor.</span>")
else
if(!I.remove_fuel(1,user))
return
user.visible_message("<span class='notice'>[user] starts to cut [src] free from the floor.</span>",
"<span class='notice'>You start to cut [src] free from the floor...</span>",
"<span class='hear'>You hear welding.</span>")
anchored = FALSE
to_chat(user, "<span class='notice'>You cut [src] free from the floor.</span>")
//Finishing the frame
else if(istype(W, /obj/item/stack/material))
if(finished)
return
var/obj/item/stack/material/S = W
if(istype(S, /obj/item/stack/material/glass))
if(S.use(5))
new /obj/structure/reflector/single(drop_location())
qdel(src)
else
to_chat(user, "<span class='warning'>You need five sheets of glass to create a reflector!</span>")
return
if(istype(S, /obj/item/stack/material/glass/reinforced))
if(S.use(10))
new /obj/structure/reflector/double(drop_location())
qdel(src)
else
to_chat(user, "<span class='warning'>You need ten sheets of reinforced glass to create a double reflector!</span>")
return
if(istype(S, /obj/item/stack/material/diamond))
if(S.use(1))
new /obj/structure/reflector/box(drop_location())
qdel(src)
else
return ..()
/obj/structure/reflector/proc/rotate(mob/user)
if (!can_rotate || admin)
to_chat(user, "<span class='warning'>The rotation is locked!</span>")
return FALSE
var/new_angle = input(user, "Input a new angle for primary reflection face.", "Reflector Angle", rotation_angle) as null|num
if(!CanUseTopic(user))
return
if(!isnull(new_angle))
setAngle(SIMPLIFY_DEGREES(new_angle))
return TRUE
/obj/structure/reflector/AltClick(mob/user)
if(!CanUseTopic(user))
return
else if(finished)
rotate(user)
//TYPES OF REFLECTORS, SINGLE, DOUBLE, BOX
//SINGLE
/obj/structure/reflector/single
name = "reflector"
deflector_icon_state = "reflector"
desc = "An angled mirror for reflecting laser beams."
density = TRUE
finished = TRUE
buildstacktype = /obj/item/stack/material//glass
buildstackamount = 5
/obj/structure/reflector/single/anchored
anchored = TRUE
/obj/structure/reflector/single/mapping
admin = TRUE
anchored = TRUE
/obj/structure/reflector/single/auto_reflect(obj/item/projectile/P, pdir, turf/ploc, pangle)
var/incidence = GET_ANGLE_OF_INCIDENCE(rotation_angle, (P.Angle + 180))
if(abs(incidence) > 90 && abs(incidence) < 270)
return FALSE
var/new_angle = SIMPLIFY_DEGREES(rotation_angle + incidence)
redirect_projectile(P,new_angle)
return ..()
//DOUBLE
/obj/structure/reflector/double
name = "double sided reflector"
deflector_icon_state = "reflector_double"
desc = "A double sided angled mirror for reflecting laser beams."
density = TRUE
finished = TRUE
buildstacktype = /obj/item/stack/material/glass/reinforced
buildstackamount = 10
/obj/structure/reflector/double/anchored
anchored = TRUE
/obj/structure/reflector/double/mapping
admin = TRUE
anchored = TRUE
/obj/structure/reflector/double/auto_reflect(obj/item/projectile/P, pdir, turf/ploc, pangle)
var/incidence = GET_ANGLE_OF_INCIDENCE(rotation_angle, (P.Angle + 180))
var/new_angle = SIMPLIFY_DEGREES(rotation_angle + incidence)
redirect_projectile(P,new_angle)
return ..()
//BOX
/obj/structure/reflector/box
name = "reflector box"
deflector_icon_state = "reflector_box"
desc = "A box with an internal set of mirrors that reflects all laser beams in a single direction."
density = TRUE
finished = TRUE
buildstacktype = /obj/item/stack/material/diamond
buildstackamount = 1
/obj/structure/reflector/box/Fire() //Since they all end up at the same angle, this should save a tad bit of processing power and memory <3
UNTIL(!bullet_act_in_progress)
var/total_damage = 0
for(var/obj/item/projectile/P in has_projectiles)
total_damage += P.damage
if(total_damage)
var/obj/item/projectile/P = new fires_projectile(src)
P.firer = src
P.damage = total_damage
P.accuracy = 350
P.dispersion = 0
P.fire(rotation_angle)
has_projectiles = list()
/obj/structure/reflector/box/anchored
anchored = TRUE
/obj/structure/reflector/box/mapping
admin = TRUE
anchored = TRUE
/obj/structure/reflector/box/auto_reflect(obj/item/projectile/P)
redirect_projectile(P,rotation_angle)
return ..()
/obj/structure/reflector/ex_act()
if(admin)
return
else
return ..()
/obj/structure/reflector/singularity_act()
if(admin)
return
else
return ..()
/obj/structure/reflector/box/orderable
name = "NanoTrasen reflector box"
desc = "A box with an internal set of mirrors that reflects all laser beams in a single direction. This one is marked with NanoTrasen's logo."
can_decon = FALSE
/datum/material/steel/generate_recipes()
..()
recipes += new/datum/stack_recipe("reflector frame", /obj/structure/reflector, 5, time = 25, one_per_turf = TRUE, on_floor = TRUE)
/datum/supply_pack/eng/reflector
name = "Reflector crate"
cost = 35
containername = "Reflector crate"
containertype = /obj/structure/closet/crate/secure/einstein
contains = list(/obj/structure/reflector/box/orderable = 3)
//Below is mostly mapping stuff for the spicy storage I added to house these new reflectors ;p
/area/engineering/secret_storage
name = "Engineering Secret Storage"
/obj/machinery/portable_atmospherics/canister
var/dont_burst = FALSE
/obj/machinery/portable_atmospherics/canister/phoron/cold/New()
src.air_contents.temperature = 2.72
..()

View File

@@ -3,7 +3,7 @@ GLOBAL_VAR(trader_loaded)
/proc/consider_trader_load() /proc/consider_trader_load()
if(!GLOB.trader_loaded) if(!GLOB.trader_loaded)
GLOB.trader_loaded = TRUE GLOB.trader_loaded = TRUE
var/datum/map_template/MT = SSmapping.map_templates["Special Area - Trader"] var/datum/map_template/MT = SSmapping.map_templates["Special Area - Salamander Trader"] //was: "Special Area - Trader"
if(!istype(MT)) if(!istype(MT))
error("Trader is not a valid map template!") error("Trader is not a valid map template!")
else else

View File

@@ -147,6 +147,8 @@
if(M.slip("the [floor_type] floor", slip_stun)) if(M.slip("the [floor_type] floor", slip_stun))
for(var/i = 1 to slip_dist) for(var/i = 1 to slip_dist)
if(M.slip_vore_in_progress) //CHOMPEdit
break //CHOMPEdit
step(M, M.dir) step(M, M.dir)
sleep(1) sleep(1)
else else

View File

@@ -90,5 +90,10 @@ var/list/grass_types = list(
icon_state = "grass_sif_dark0" icon_state = "grass_sif_dark0"
edge_blending_priority = 5 edge_blending_priority = 5
tree_chance = 4 tree_chance = 4
grass_chance = 0 grass_chance = 1
grass_types = list(
/obj/structure/flora/sif/frostbelle = 1,
/obj/structure/flora/sif/eyes = 5,
/obj/structure/flora/sif/tendrils = 30
)

View File

@@ -0,0 +1,88 @@
/turf/simulated
var/triggers = FALSE
var/list/potential_triggerers = list() //What can set off our trigger?
var/list/trig_target_paths = list() //What are the paths of whatever we want to call our proc on?
var/trig_target_trigger_uid //What is the trigger_uid of whatever we want to call our proc on?
var/trig_proc //What proc do we want to call?
var/list/trig_args = list() //What are the arguments for said proc?
var/trig_message //Should we send a message to the person who stepped here?
var/message_span_class = "notice" //If we're gonna send them a message, what span class to use?
var/trig_single_use = FALSE //Is this only a single use trigger, or can it be used multiple times?
var/has_been_used = FALSE //Has this trigger been set off yet?
var/list/trig_targets = list() //This is set automatically if the other target vars are set.
var/list/been_triggered_by = list() //Who has set this off so far?
var/trig_single_use_per_triggerer = FALSE //Do we want to make so each atom can only trigger this once?
var/trig_target_is_trigerrer = FALSE //Do we want to use the atom that trigerred us as the target?
/turf/simulated/proc/can_use_trigger(atom/movable/mover)
if(trig_single_use && has_been_used)
return FALSE
if(trig_single_use_per_triggerer && (mover in been_triggered_by))
return FALSE
if(!potential_triggerers.len)
return TRUE
else
for(var/path in potential_triggerers)
if(istype(mover,text2path(trim(path))))
return TRUE
else
continue
return FALSE
/turf/simulated/Entered(atom/movable/mover, atom/oldloc)
. = ..()
if(triggers && can_use_trigger(mover))
if(trig_proc)
if(trig_target_is_trigerrer)
trig_targets = list(mover)
if(trig_targets.len)
var/testname = trig_proc
//Find one of the 3 possible ways they could have written /proc/PROCNAME
if(findtext(trig_proc, "/proc/"))
testname = replacetext(trig_proc, "/proc/", "")
else if(findtext(trig_proc, "/proc"))
testname = replacetext(trig_proc, "/proc", "")
else if(findtext(trig_proc, "proc/"))
testname = replacetext(trig_proc, "proc/", "")
//Clear out any parenthesis if they're a dummy
testname = replacetext(testname, "()", "")
for(var/trig_target in trig_targets)
if(trig_target && !hascall(trig_target,testname))
message_admins("TRIGGER ERROR: ONE OR MORE TRIGGER TARGETS LACKS THE MENTIONED PROC")
return
for(var/trig_target in trig_targets)
call(trig_target,testname)(arglist(trig_args))
else
var/procpath = text2path(trig_proc)
if(!procpath)
message_admins("TRIGGER ERROR: INVALID PROC")
return
call(procpath)(arglist(trig_args))
if(trig_message)
to_chat(mover,"<span class='[message_span_class]'>"+trig_message+"</span>")
has_been_used = TRUE
been_triggered_by |= mover
else
return
/turf/simulated/proc/update_trig_targets()
trig_targets = list()
for(var/path in trig_target_paths)
var/trig_target_path = text2path(path)
if(trig_target_path && trig_target_trigger_uid)
var/list/candidates = get_all_of_type(trig_target_path)
for(var/candidate in candidates)
var/datum/cand_datum = candidate
if(istype(cand_datum))
if(cand_datum.trigger_uid == trig_target_trigger_uid)
trig_targets += candidate
continue
continue
if(!trig_targets.len)
message_admins("TRIGGER ERROR: trig_targets STILL EMPTY AFTER CALLED update_trig_targets()")
/turf/simulated/Initialize(mapload)
. = ..()
if(triggers)
update_trig_targets()

View File

@@ -5,7 +5,7 @@
var/input_NIF var/input_NIF
if(!check_rights(R_ADMIN|R_EVENT|R_DEBUG)) //CHOMPStation Edit TFF 24/4/19: Allow Devs to use Quick-NIF verb. if(!check_rights(R_ADMIN|R_EVENT|R_DEBUG|R_MOD)) //CHOMPStation Edit TFF 24/4/19: Allow Devs to use Quick-NIF verb. 11/9/20: Also allow mods :3
return return
var/mob/living/carbon/human/H = input("Pick a mob with a player","Quick NIF") as null|anything in player_list var/mob/living/carbon/human/H = input("Pick a mob with a player","Quick NIF") as null|anything in player_list

View File

@@ -0,0 +1,11 @@
/datum/gear/cigar_case
display_name = "cigar case"
path = /obj/item/weapon/storage/fancy/cigar
/datum/gear/cigar_case/New()
..()
var/list/cigars = list()
for(var/cigar in (typesof(/obj/item/weapon/storage/fancy/cigar)))
var/obj/item/weapon/storage/fancy/cigar/cigar_brand = cigar
cigars[initial(cigar_brand.name)] = cigar_brand
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(cigars))

View File

@@ -614,3 +614,34 @@
display_name = "disheveled suit" display_name = "disheveled suit"
path = /obj/item/clothing/under/disheveled path = /obj/item/clothing/under/disheveled
/datum/gear/uniform/orangedress
display_name = "orange dress"
path = /obj/item/clothing/under/dress/dress_orange
/datum/gear/uniform/sundress_pink
display_name = "pink sundress"
path = /obj/item/clothing/under/dress/sundress_pink
/datum/gear/uniform/sundress_white
display_name = "white sundress"
path = /obj/item/clothing/under/dress/sundress_white
/datum/gear/uniform/sundress_pinkbow
display_name = "bowed pink sundress"
path = /obj/item/clothing/under/dress/sundress_pinkbow
/datum/gear/uniform/sundress_blue
display_name = "long blue sundress"
path = /obj/item/clothing/under/dress/sundress_blue
/datum/gear/uniform/sundress_pinkshort
display_name = "short pink sundress"
path = /obj/item/clothing/under/dress/sundress_pinkshort
/datum/gear/uniform/twopiece
display_name = "two-piece dress"
path = /obj/item/clothing/under/dress/twopiece
/datum/gear/uniform/gothic2
display_name = "lacey gothic dress"
path = /obj/item/clothing/under/dress/gothic2

View File

@@ -184,9 +184,12 @@
return TOPIC_REFRESH return TOPIC_REFRESH
else if(href_list["clicked_pos_trait"]) else if(href_list["clicked_pos_trait"])
var/traitpath = text2path(href_list["clicked_pos_trait"]) //CHOMPEdit
var/datum/trait/trait = text2path(href_list["clicked_pos_trait"]) var/datum/trait/trait = text2path(href_list["clicked_pos_trait"])
var/choice = alert("Remove [initial(trait.name)] and regain [initial(trait.cost)] points?","Remove Trait","Remove","Cancel") var/choice = alert("Remove [initial(trait.name)] and regain [initial(trait.cost)] points?","Remove Trait","Remove","Cancel")
if(choice == "Remove") if(choice == "Remove")
if(traitpath == /datum/trait/linguist) //CHOMPEdit
pref.num_languages = 0 //CHOMPEdit
pref.pos_traits -= trait pref.pos_traits -= trait
return TOPIC_REFRESH return TOPIC_REFRESH
@@ -287,7 +290,8 @@
alert("You cannot take this trait and [conflict] at the same time. \ alert("You cannot take this trait and [conflict] at the same time. \
Please remove that trait, or pick another trait to add.","Error") Please remove that trait, or pick another trait to add.","Error")
return TOPIC_REFRESH return TOPIC_REFRESH
if(path==/datum/trait/linguist) //CHOMPEdit
pref.num_languages = 12 //CHOMPEdit
mylist += path mylist += path
return TOPIC_REFRESH return TOPIC_REFRESH

View File

@@ -159,6 +159,12 @@
icon_state = "scrubsnavyblue" icon_state = "scrubsnavyblue"
item_state_slots = list(slot_r_hand_str = "blue", slot_l_hand_str = "blue") item_state_slots = list(slot_r_hand_str = "blue", slot_l_hand_str = "blue")
/obj/item/clothing/under/rank/medical/scrubs/white
name = "scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards"
icon_state = "scrubs"
item_state_slots = list(slot_r_hand_str = "white", slot_l_hand_str = "white")
/obj/item/clothing/under/rank/psych /obj/item/clothing/under/rank/psych
desc = "A basic white jumpsuit. It has turqouise markings that denote the wearer as a psychiatrist." desc = "A basic white jumpsuit. It has turqouise markings that denote the wearer as a psychiatrist."
name = "psychiatrist's jumpsuit" name = "psychiatrist's jumpsuit"

View File

@@ -621,7 +621,7 @@ Uniforms and such
*/ */
/obj/item/clothing/under/sundress /obj/item/clothing/under/sundress
name = "sundress" name = "flowery white sundress"
desc = "Makes you want to frolic in a field of daisies." desc = "Makes you want to frolic in a field of daisies."
icon_state = "sundress" icon_state = "sundress"
body_parts_covered = UPPER_TORSO|LOWER_TORSO body_parts_covered = UPPER_TORSO|LOWER_TORSO
@@ -632,6 +632,47 @@ Uniforms and such
icon_state = "sundress_white" icon_state = "sundress_white"
body_parts_covered = UPPER_TORSO|LOWER_TORSO body_parts_covered = UPPER_TORSO|LOWER_TORSO
/obj/item/clothing/under/dress/sundress_pink
name = "pink stripied sundress"
desc = "A cute pink sundress."
icon_state = "pinksun"
body_parts_covered = UPPER_TORSO|LOWER_TORSO
/obj/item/clothing/under/dress/sundress_white
name = "white sundress"
desc = "A white sundress, it's short."
icon_state = "whitesun"
body_parts_covered = UPPER_TORSO|LOWER_TORSO
/obj/item/clothing/under/dress/sundress_pinkbow
name = "bowed pink sundress"
desc = "A cute pink sundress with a bow."
icon_state = "bowsun"
body_parts_covered = UPPER_TORSO|LOWER_TORSO
/obj/item/clothing/under/dress/sundress_blue
name = "long blue sundress"
desc = "A long blue sun dress with white frills towards the bottom."
icon_state = "bluesun"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS
/obj/item/clothing/under/dress/sundress_pinkshort
name = "short pink sundress"
desc = "A very short pink sundress, it's more like a chemise."
icon_state = "shortpink"
body_parts_covered = UPPER_TORSO|LOWER_TORSO
/obj/item/clothing/under/dress/twopiece
name = "two-piece dress"
desc = "A fancy two-piece dress, the pieces are sewn together."
icon_state = "twopiece"
body_parts_covered = UPPER_TORSO|LOWER_TORSO
/obj/item/clothing/under/dress/gothic2
name = "lacey gothic dress"
desc = "An elegant gothic dress with lace decorations."
icon_state = "gothic2"
/obj/item/clothing/under/captainformal /obj/item/clothing/under/captainformal
name = "site manager's formal uniform" name = "site manager's formal uniform"
desc = "A Site Manager's formal-wear, for special occasions." desc = "A Site Manager's formal-wear, for special occasions."

View File

@@ -7,7 +7,7 @@
// List of all non-destroyed canisters on station levels // List of all non-destroyed canisters on station levels
var/list/all_canisters = list() var/list/all_canisters = list()
for(var/obj/machinery/portable_atmospherics/canister/C in machines) for(var/obj/machinery/portable_atmospherics/canister/C in machines)
if(!C.destroyed && (C.z in using_map.station_levels) && C.air_contents.total_moles >= MOLES_CELLSTANDARD) if(!C.destroyed && (C.z in using_map.station_levels) && C.air_contents.total_moles >= MOLES_CELLSTANDARD && !C.dont_burst) //CHOMPEdit
all_canisters += C all_canisters += C
for(var/i in 1 to 10) for(var/i in 1 to 10)

View File

@@ -73,7 +73,7 @@
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Carp School", /datum/event/carp_migration, -20, list(ASSIGNMENT_ENGINEER = 10, ASSIGNMENT_SECURITY = 30, ASSIGNMENT_HOS = 10, ASSIGNMENT_WARDEN = 5), 1), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Carp School", /datum/event/carp_migration, -20, list(ASSIGNMENT_ENGINEER = 10, ASSIGNMENT_SECURITY = 30, ASSIGNMENT_HOS = 10, ASSIGNMENT_WARDEN = 5), 1),
// Just disables comms for a short while. // Just disables comms for a short while.
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Communication Blackout", /datum/event/communications_blackout, 500, list(ASSIGNMENT_AI = 150, ASSIGNMENT_SECURITY = 120), 1), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Communication Blackout", /datum/event/communications_blackout, 500, list(ASSIGNMENT_AI = 150, ASSIGNMENT_SECURITY = 120), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Drone Pod Drop", /datum/event/drone_pod_drop, 10, list(ASSIGNMENT_SCIENTIST = 40), 1),
// Just blows out a few lights // Just blows out a few lights
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Electrical Storm", /datum/event/electrical_storm, 250, list(ASSIGNMENT_ENGINEER = 20, ASSIGNMENT_JANITOR = 150), 1), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Electrical Storm", /datum/event/electrical_storm, 250, list(ASSIGNMENT_ENGINEER = 20, ASSIGNMENT_JANITOR = 150), 1),
//Escaped slime event itself needs to be rejiggered because of the mob refactor. //Escaped slime event itself needs to be rejiggered because of the mob refactor.
@@ -102,6 +102,8 @@
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meteor Shower", /datum/event/meteor_wave, 30, list(ASSIGNMENT_ENGINEER = 20)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meteor Shower", /datum/event/meteor_wave, 30, list(ASSIGNMENT_ENGINEER = 20)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Random Antagonist", /datum/event/random_antag, 2.5, list(ASSIGNMENT_SECURITY = 1), 1, 0, 5), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Random Antagonist", /datum/event/random_antag, 2.5, list(ASSIGNMENT_SECURITY = 1), 1, 0, 5),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Carp School", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 30), 1), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Carp School", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 30), 1),
//Commenting this event out, the pod is not mapped in.
//new /datum/event_meta(EVENT_LEVEL_MODERATE, "Drone Pod Drop", /datum/event/drone_pod_drop, 10, list(ASSIGNMENT_SCIENTIST = 40), 1),
//Spacedust doesn't work, commenting this out. //Spacedust doesn't work, commenting this out.
//new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Dust", /datum/event/dust, 0, list(ASSIGNMENT_ENGINEER = 20), 1, 0, 50), //new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Dust", /datum/event/dust, 0, list(ASSIGNMENT_ENGINEER = 20), 1, 0, 50),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Predator", /datum/event/maintenance_predator, 75, list(ASSIGNMENT_SECURITY = 25, ASSIGNMENT_SCIENTIST = 10), 1), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Maintenance Predator", /datum/event/maintenance_predator, 75, list(ASSIGNMENT_SECURITY = 25, ASSIGNMENT_SCIENTIST = 10), 1),
@@ -120,6 +122,7 @@
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, -100, list(ASSIGNMENT_SECURITY = 40, ASSIGNMENT_HOS = 10, ASSIGNMENT_WARDEN = 10, ASSIGNMENT_ENGINEER = 5), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, -100, list(ASSIGNMENT_SECURITY = 40, ASSIGNMENT_HOS = 10, ASSIGNMENT_WARDEN = 10, ASSIGNMENT_ENGINEER = 5), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, -110, list(ASSIGNMENT_SECURITY = 50, ASSIGNMENT_HOS = 10, ASSIGNMENT_WARDEN = 10), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, -110, list(ASSIGNMENT_SECURITY = 50, ASSIGNMENT_HOS = 10, ASSIGNMENT_WARDEN = 10), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Containment Breach", /datum/event/prison_break/station,0, list(ASSIGNMENT_ANY = 5), 0), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Containment Breach", /datum/event/prison_break/station,0, list(ASSIGNMENT_ANY = 5), 0),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Drone Pod Drop", /datum/event/drone_pod_drop, 10, list(ASSIGNMENT_SCIENTIST = 40), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, -110, list(ASSIGNMENT_ENGINEER = 50), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, -110, list(ASSIGNMENT_ENGINEER = 50), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Space Vines", /datum/event/spacevine, 20, list(ASSIGNMENT_ENGINEER = 15), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Space Vines", /datum/event/spacevine, 20, list(ASSIGNMENT_ENGINEER = 15), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Viral Infection", /datum/event/viral_infection, -50, list(ASSIGNMENT_MEDICAL = 25), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Viral Infection", /datum/event/viral_infection, -50, list(ASSIGNMENT_MEDICAL = 25), 1),

View File

@@ -4039,6 +4039,40 @@
/obj/item/weapon/reagent_containers/food/snacks/rawsunflower/Initialize() /obj/item/weapon/reagent_containers/food/snacks/rawsunflower/Initialize()
. = ..() . = ..()
/obj/item/weapon/reagent_containers/food/snacks/frostbelle
name = "frostbelle bud"
desc = "A frostbelle flower from Sif. Its petals shimmer with an inner light."
icon = 'icons/obj/food_ingredients.dmi'
icon_state = "frostbelle"
bitesize = 1
nutriment_amt = 1
nutriment_desc = list("another world" = 2)
catalogue_data = list(/datum/category_item/catalogue/flora/frostbelle)
filling_color = "#5dadcf"
/obj/item/weapon/reagent_containers/food/snacks/frostbelle/Initialize()
. = ..()
set_light(1, 1, "#5dadcf")
reagents.add_reagent("oxycodone", 1)
reagents.add_reagent("sifsap", 5)
reagents.add_reagent("space_drugs", 5)
/obj/item/weapon/reagent_containers/food/snacks/bellefritter
name = "frostbelle fritters"
desc = "Frostbelles, prepared traditionally."
icon = 'icons/obj/food_syn.dmi'
icon_state = "bellefritter"
filling_color = "#5dadcf"
center_of_mass = list("x"=16, "y"=12)
do_coating_prefix = 0
/obj/item/weapon/reagent_containers/food/snacks/bellefritter/Initialize()
. = ..()
reagents.add_reagent("batter", 10)
reagents.add_reagent("sugar", 5)
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/roastedsunflower /obj/item/weapon/reagent_containers/food/snacks/roastedsunflower
name = "sunflower seeds" name = "sunflower seeds"
desc = "Sunflower seeds!" desc = "Sunflower seeds!"

View File

@@ -192,3 +192,60 @@
..() ..()
reagents.add_reagent("tealeavesgreen", 6) reagents.add_reagent("tealeavesgreen", 6)
bitesize = 1 bitesize = 1
/obj/item/weapon/reagent_containers/food/snacks/butterscotch
name = "Butterscotch"
desc = "A sweet, golden-brown liquid, usually used as part of confectionary. Just a spoonful wouldn't hurt, right?"
icon = 'icons/obj/food_ch.dmi'
icon_state = "butterscotch" //Sprite by Dinnel
nutriment_amt = 1
nutriment_desc = list("sickly sweet deliciousness" = 1)
/obj/item/weapon/reagent_containers/food/snacks/butterscotch/Initialize()
..()
bitesize = 1
/obj/item/weapon/reagent_containers/food/snacks/slicable/buttspie
name = "Butterscotch-Cinnamon Pie"
desc = "A delightfully caramel-coloured filling in a crispy pie base, dotted with sprays of cream."
icon = 'icons/obj/food_ch.dmi'
icon_state = "butts_pie" //Sprite by Dinnel
slice_path = /obj/item/weapon/reagent_containers/food/snacks/slice/buttspie
slices_num = 6
nutriment_amt = 12
nutriment_desc = list("a warm, buttery sweetness that reminds you of home" = 5)
center_of_mass = list("x"=16, "y"=9)
/obj/item/weapon/reagent_containers/food/snacks/slicable/buttspie/Initialize()
..()
bitesize = 4
/obj/item/weapon/reagent_containers/food/snacks/slice/buttspie //TODO: Fix the numbers.
name = "Slice of Butterscotch-Cinnamon Pie"
desc = "A slice of pie, filled with delightfully caramel-coloured filling. There a spray of cream on top."
icon = 'icons/obj/food_ch.dmi'
icon_state = "butts_pie_slice" //Sprite by Dinnel
trash = /obj/item/trash/plate
whole_path = /obj/item/weapon/reagent_containers/food/snacks/slicable/buttspie
/obj/item/weapon/reagent_containers/food/snacks/slice/buttspie/Initialize()
..()
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/spicy_boys //These are off-brand red hots/atomic fireballs
name = "Spicy Boys"
desc = "Spicy little candy rounds for very naughty individuals."
icon = 'icons/obj/food_ch.dmi'
icon_state = "spicy_boys" //Sprite by Dinnel
nutriment_amt = 1 //todo - change numbers
nutriment_desc = list("a sweet, candy-like spiciness." = 2) //WIP flavour??
/obj/item/weapon/reagent_containers/food/snacks/cinnamonroll
name = "cinnamon roll"
desc = "A precious little cinnamon roll, just begging to be eaten."
icon = 'icons/obj/food_ch.dmi'
icon_state = "cinnamon_roll" //Sprite by Dinnel
nutriment_amt = 1 //Todo - Change numbers.
nutriment_desc = list("a precious sweetness that needs protecting" = 2) //This is a WIP flavour, Could keep it if you don't mind the "gotta protect the precious cinnamon roll" joke
//TODO: Maybe butterscotch candies?

View File

@@ -188,18 +188,13 @@
update_icon() update_icon()
var/slab_name = occupant.name var/slab_name = occupant.name
var/slab_count = 3 var/slab_count = 2 + occupant.meat_amount
var/slab_type = /obj/item/weapon/reagent_containers/food/snacks/meat var/slab_type = occupant.meat_type ? occupant.meat_type : /obj/item/weapon/reagent_containers/food/snacks/meat
var/slab_nutrition = src.occupant.nutrition / 15 var/slab_nutrition = src.occupant.nutrition / 15
// Some mobs have specific meat item types. var/list/byproducts = occupant?.butchery_loot?.Copy()
if(istype(src.occupant,/mob/living/simple_mob))
var/mob/living/simple_mob/critter = src.occupant if(istype(src.occupant,/mob/living/carbon/human))
if(critter.meat_amount)
slab_count = critter.meat_amount
if(critter.meat_type)
slab_type = critter.meat_type
else if(istype(src.occupant,/mob/living/carbon/human))
var/mob/living/carbon/human/H = occupant var/mob/living/carbon/human/H = occupant
slab_name = src.occupant.real_name slab_name = src.occupant.real_name
slab_type = H.isSynthetic() ? /obj/item/stack/material/steel : H.species.meat_type slab_type = H.isSynthetic() ? /obj/item/stack/material/steel : H.species.meat_type
@@ -209,7 +204,8 @@
slab_nutrition *= 0.5 slab_nutrition *= 0.5
slab_nutrition /= slab_count slab_nutrition /= slab_count
for(var/i=1 to slab_count) while(slab_count)
slab_count--
var/obj/item/weapon/reagent_containers/food/snacks/meat/new_meat = new slab_type(src, rand(3,8)) var/obj/item/weapon/reagent_containers/food/snacks/meat/new_meat = new slab_type(src, rand(3,8))
if(istype(new_meat)) if(istype(new_meat))
new_meat.name = "[slab_name] [new_meat.name]" new_meat.name = "[slab_name] [new_meat.name]"
@@ -222,16 +218,25 @@
src.occupant.ghostize() src.occupant.ghostize()
spawn(gib_time) spawn(gib_time)
operating = 0
occupant.gib() occupant.gib()
occupant = null occupant = null
playsound(src, 'sound/effects/splat.ogg', 50, 1) playsound(src, 'sound/effects/splat.ogg', 50, 1)
operating = 0 operating = 0
if(LAZYLEN(byproducts))
for(var/path in byproducts)
while(byproducts[path])
if(prob(min(90,30 * byproducts[path])))
new path(src)
byproducts[path] -= 1
for (var/obj/thing in contents) for (var/obj/thing in contents)
// There's a chance that the gibber will fail to destroy some evidence. // There's a chance that the gibber will fail to destroy or butcher some evidence.
if(istype(thing,/obj/item/organ) && prob(80)) if(istype(thing,/obj/item/organ) && prob(80))
var/obj/item/organ/OR = thing
if(OR.can_butcher(src))
OR.butcher(src, null, src) // Butcher it, and add it to our list of things to launch.
else
qdel(thing) qdel(thing)
continue continue
thing.forceMove(get_turf(thing)) // Drop it onto the turf for throwing. thing.forceMove(get_turf(thing)) // Drop it onto the turf for throwing.

View File

@@ -137,6 +137,10 @@
var/obj/item/weapon/reagent_containers/food/snacks/S = O var/obj/item/weapon/reagent_containers/food/snacks/S = O
if (S.dried_type) if (S.dried_type)
return 1 return 1
if(istype(O, /obj/item/stack/wetleather))
return 1
return 0 return 0
/obj/machinery/smartfridge/drying_rack/process() /obj/machinery/smartfridge/drying_rack/process()
@@ -180,6 +184,17 @@
new D(get_turf(src)) new D(get_turf(src))
qdel(S) qdel(S)
return return
for(var/obj/item/stack/wetleather/WL in I.instances)
if(!WL.wetness)
if(WL.amount == 1)
WL.forceMove(get_turf(src))
I.instances -= WL
WL.dry()
break
WL.wetness = max(0, WL.wetness - rand(1, 3))
return return
/obj/machinery/smartfridge/process() /obj/machinery/smartfridge/process()

View File

@@ -27,6 +27,11 @@
reagent_mix = RECIPE_REAGENT_REPLACE //Simplify end product reagent_mix = RECIPE_REAGENT_REPLACE //Simplify end product
result = /obj/item/weapon/reagent_containers/food/snacks/risottoballs result = /obj/item/weapon/reagent_containers/food/snacks/risottoballs
/datum/recipe/bellefritter
appliance = FRYER
reagents = list("sugar" = 5, "batter" = 10)
items = list(/obj/item/weapon/reagent_containers/food/snacks/frostbelle)
result = /obj/item/weapon/reagent_containers/food/snacks/bellefritter
//Meaty Recipes //Meaty Recipes
//==================== //====================

View File

@@ -97,3 +97,12 @@
/obj/item/weapon/reagent_containers/food/snacks/steamrolltealeaf /obj/item/weapon/reagent_containers/food/snacks/steamrolltealeaf
) )
result = /obj/item/weapon/reagent_containers/food/snacks/greentealeaf result = /obj/item/weapon/reagent_containers/food/snacks/greentealeaf
/datum/recipe/butterscotch
reagents = list("sugar" = 10, "cream" = 5)
reagent_mix = RECIPE_REAGENT_REPLACE //No actual reagents since it's meant to be a cooking item
items = list(
/obj/item/weapon/reagent_containers/food/snacks/spreads/butter
)
result = /obj/item/weapon/reagent_containers/food/snacks/butterscotch
result_quantity = 2

View File

@@ -0,0 +1,23 @@
/datum/recipe/buttspie
appliance = OVEN
reagents = list("cinnamonpowder" = 10)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/butterscotch,
/obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough
)
result = /obj/item/weapon/reagent_containers/food/snacks/slicable/buttspie
/datum/recipe/cinnamon_roll
appliance = OVEN
reagents = list("cinnamonpowder" = 5, "sugar" = 10)
items = list(
/obj/item/weapon/reagent_containers/food/snacks/dough,
/obj/item/weapon/reagent_containers/food/snacks/spreads/butter
)
result = /obj/item/weapon/reagent_containers/food/snacks/cinnamonroll
/datum/recipe/spicy_boys
appliance = OVEN
reagents = list("cinnamonpowder" = 5, "sugar" = 10, "cornoil" = 10)
result = /obj/item/weapon/reagent_containers/food/snacks/spicy_boys
result_quantity = 6

View File

@@ -201,3 +201,22 @@
set_trait(TRAIT_IDEAL_HEAT, 283) set_trait(TRAIT_IDEAL_HEAT, 283)
set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0) set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0)
set_trait(TRAIT_WATER_CONSUMPTION, 0) set_trait(TRAIT_WATER_CONSUMPTION, 0)
/datum/seed/cinnamon //WIP - I have no idea what I'm doing with growables in code right now.
name = "cinnamon"
seed_name = "cinnamon"
display_name = "cinnamon tree"
chems = list("cinnamonpowder" = list(5,25))
mutants = null
kitchen_tag = "cinnamon"
/datum/seed/cinnamon/New()
..()
set_trait(TRAIT_HARVEST_REPEAT,1)
set_trait(TRAIT_MATURATION,6)
set_trait(TRAIT_PRODUCTION,6)
set_trait(TRAIT_YIELD,5)
set_trait(TRAIT_POTENCY,10)
set_trait(TRAIT_PRODUCT_ICON, "stalk")
set_trait(TRAIT_PRODUCT_COLOUR, "#FF9A85")
set_trait(TRAIT_PLANT_ICON,"tree2")

View File

@@ -2,5 +2,9 @@
/obj/item/seeds/teaseed /obj/item/seeds/teaseed
seed_type = "tea" seed_type = "tea"
/obj/item/seeds/cinnamon
seed_type = "cinnamon"
/obj/item/seeds/pitcherseed /obj/item/seeds/pitcherseed
seed_type = "pitcher plant" seed_type = "pitcher plant"

View File

@@ -77,12 +77,16 @@
update_lighting() update_lighting()
/obj/item/integrated_circuit/output/light/proc/update_lighting() /obj/item/integrated_circuit/output/light/proc/update_lighting()
//CHOMPEdit Begin
if(assembly)
var/atom/light_source = assembly
if(istype(assembly,/obj/item/device/electronic_assembly/clothing))
light_source = assembly.loc
if(light_toggled) if(light_toggled)
if(assembly) light_source.set_light(l_range = light_brightness, l_power = light_brightness, l_color = light_rgb)
assembly.set_light(l_range = light_brightness, l_power = light_brightness, l_color = light_rgb)
else else
if(assembly) light_source.set_light(0)
assembly.set_light(0) //CHOMPEdit End
power_draw_idle = light_toggled ? light_brightness * light_brightness : 0 // Should be the same draw as regular lights. power_draw_idle = light_toggled ? light_brightness * light_brightness : 0 // Should be the same draw as regular lights.
/obj/item/integrated_circuit/output/light/power_fail() // Turns off the flashlight if there's no power left. /obj/item/integrated_circuit/output/light/power_fail() // Turns off the flashlight if there's no power left.

View File

@@ -140,6 +140,7 @@
recipes += new/datum/stack_recipe("plastic net", /obj/item/weapon/material/fishing_net, 25, time = 1 MINUTE, pass_stack_color = TRUE) recipes += new/datum/stack_recipe("plastic net", /obj/item/weapon/material/fishing_net, 25, time = 1 MINUTE, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("plastic fishtank", /obj/item/glass_jar/fish/plastic, 2, time = 30 SECONDS) recipes += new/datum/stack_recipe("plastic fishtank", /obj/item/glass_jar/fish/plastic, 2, time = 30 SECONDS)
recipes += new/datum/stack_recipe("reagent tubing", /obj/item/stack/hose, 1, 4, 20, pass_stack_color = TRUE) recipes += new/datum/stack_recipe("reagent tubing", /obj/item/stack/hose, 1, 4, 20, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("Feeder", /obj/machinery/feeder, 4, time = 20, one_per_turf = 1, on_floor = 1) //CHOMP Addition
/datum/material/wood/generate_recipes() /datum/material/wood/generate_recipes()
..() ..()
@@ -248,3 +249,24 @@
recipes += new/datum/stack_recipe("[display_name] net", /obj/item/weapon/material/fishing_net, 10, time = 5 SECONDS, supplied_material = "[name]", pass_stack_color = TRUE) recipes += new/datum/stack_recipe("[display_name] net", /obj/item/weapon/material/fishing_net, 10, time = 5 SECONDS, supplied_material = "[name]", pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("[display_name] membrane", /obj/effect/alien/resin/membrane, 1, time = 2 SECONDS, pass_stack_color = TRUE) recipes += new/datum/stack_recipe("[display_name] membrane", /obj/effect/alien/resin/membrane, 1, time = 2 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("[display_name] node", /obj/effect/alien/weeds/node, 1, time = 4 SECONDS) recipes += new/datum/stack_recipe("[display_name] node", /obj/effect/alien/weeds/node, 1, time = 4 SECONDS)
/datum/material/leather/generate_recipes()
recipes = list()
recipes += new/datum/stack_recipe("bedsheet", /obj/item/weapon/bedsheet, 10, time = 30 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("uniform", /obj/item/clothing/under/color/white, 8, time = 15 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("foot wraps", /obj/item/clothing/shoes/footwraps, 2, time = 5 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("gloves", /obj/item/clothing/gloves/white, 2, time = 5 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("wig", /obj/item/clothing/head/powdered_wig, 4, time = 10 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("philosopher's wig", /obj/item/clothing/head/philosopher_wig, 50, time = 2 MINUTES, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("taqiyah", /obj/item/clothing/head/taqiyah, 3, time = 6 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("turban", /obj/item/clothing/head/turban, 3, time = 6 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("hijab", /obj/item/clothing/head/hijab, 3, time = 6 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("kippa", /obj/item/clothing/head/kippa, 3, time = 6 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("scarf", /obj/item/clothing/accessory/scarf/white, 4, time = 5 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("baggy pants", /obj/item/clothing/under/pants/baggy/white, 8, time = 10 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("belt pouch", /obj/item/weapon/storage/belt/fannypack/white, 25, time = 1 MINUTE, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("crude [display_name] bandage", /obj/item/stack/medical/crude_pack, 1, time = 2 SECONDS, pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("[display_name] net", /obj/item/weapon/material/fishing_net, 10, time = 5 SECONDS, supplied_material = "[name]", pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("[display_name] ring", /obj/item/clothing/gloves/ring/material, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("[display_name] bracelet", /obj/item/clothing/accessory/bracelet/material, 1, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)
recipes += new/datum/stack_recipe("[display_name] armor plate", /obj/item/weapon/material/armor_plating, 1, time = 20, on_floor = 1, supplied_material = "[name]", pass_stack_color = TRUE)

View File

@@ -444,7 +444,18 @@
name = "leather" name = "leather"
desc = "The by-product of mob grinding." desc = "The by-product of mob grinding."
icon_state = "sheet-leather" icon_state = "sheet-leather"
default_type = "leather" default_type = MAT_LEATHER
no_variants = FALSE
pass_color = TRUE
strict_color_stacking = TRUE
drop_sound = 'sound/items/drop/leather.ogg'
pickup_sound = 'sound/items/pickup/leather.ogg'
/obj/item/stack/material/chitin
name = "chitin"
desc = "The by-product of mob grinding."
icon_state = "chitin"
default_type = MAT_CHITIN
no_variants = FALSE no_variants = FALSE
pass_color = TRUE pass_color = TRUE
strict_color_stacking = TRUE strict_color_stacking = TRUE

View File

@@ -922,7 +922,7 @@ var/list/name_to_material
sheet_singular_name = null sheet_singular_name = null
sheet_plural_name = "pile" sheet_plural_name = "pile"
pass_stack_colors = TRUE pass_stack_colors = TRUE
supply_conversion_value = 3 //YW Adds: logs worth points supply_conversion_value = 1
/datum/material/wood/log/sif /datum/material/wood/log/sif
name = MAT_SIFLOG name = MAT_SIFLOG
@@ -1008,6 +1008,7 @@ var/list/name_to_material
flags = MATERIAL_PADDING flags = MATERIAL_PADDING
conductive = 0 conductive = 0
pass_stack_colors = TRUE pass_stack_colors = TRUE
supply_conversion_value = 2
/datum/material/cult /datum/material/cult
name = "cult" name = "cult"
@@ -1033,16 +1034,32 @@ var/list/name_to_material
/datum/material/cult/reinf/place_dismantled_product(var/turf/target) /datum/material/cult/reinf/place_dismantled_product(var/turf/target)
new /obj/effect/decal/remains/human(target) new /obj/effect/decal/remains/human(target)
/datum/material/chitin
name = MAT_CHITIN
icon_colour = "#8d6653"
stack_type = /obj/item/stack/material/chitin
stack_origin_tech = list(TECH_MATERIAL = 3, TECH_BIO = 4)
icon_base = "solid"
icon_reinf = "reinf_mesh"
integrity = 60
ignition_point = T0C+400
melting_point = T0C+500
protectiveness = 25
conductive = 0
supply_conversion_value = 4
//TODO PLACEHOLDERS: //TODO PLACEHOLDERS:
/datum/material/leather /datum/material/leather
name = "leather" name = MAT_LEATHER
icon_colour = "#5C4831" icon_colour = "#5C4831"
stack_origin_tech = list(TECH_MATERIAL = 2) stack_type = /obj/item/stack/material/leather
stack_origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2)
flags = MATERIAL_PADDING flags = MATERIAL_PADDING
ignition_point = T0C+300 ignition_point = T0C+300
melting_point = T0C+300 melting_point = T0C+300
protectiveness = 3 // 13% protectiveness = 3 // 13%
conductive = 0 conductive = 0
supply_conversion_value = 3
//CHOMPstation Removal Start: Moved to materials_ch and changed to allow for material var //CHOMPstation Removal Start: Moved to materials_ch and changed to allow for material var
/* /*

View File

@@ -0,0 +1,66 @@
/mob/living
var/meat_amount = 0 // How much meat to drop from this mob when butchered
var/obj/meat_type // The meat object to drop
var/gib_on_butchery = FALSE
var/list/butchery_loot // Associated list, path = number.
// Harvest an animal's delicious byproducts
/mob/living/proc/harvest(var/mob/user, var/obj/item/I)
if(meat_type && meat_amount>0 && (stat == DEAD))
while(meat_amount > 0 && do_after(user, 0.5 SECONDS * (mob_size / 10), src))
var/obj/item/meat = new meat_type(get_turf(src))
meat.name = "[src.name] [meat.name]"
new /obj/effect/decal/cleanable/blood/splatter(get_turf(src))
meat_amount--
if(!meat_amount)
handle_butcher(user, I)
/mob/living/proc/can_butcher(var/mob/user, var/obj/item/I) // Override for special butchering checks.
if(((meat_type && meat_amount) || LAZYLEN(butchery_loot)) && stat == DEAD)
return TRUE
return FALSE
/mob/living/proc/handle_butcher(var/mob/user, var/obj/item/I)
if(!user || do_after(user, 2 SECONDS * mob_size / 10, src))
if(LAZYLEN(butchery_loot))
if(LAZYLEN(butchery_loot))
for(var/path in butchery_loot)
while(butchery_loot[path])
butchery_loot[path] -= 1
var/obj/item/loot = new path(get_turf(src))
loot.pixel_x = rand(-12, 12)
loot.pixel_y = rand(-12, 12)
butchery_loot.Cut()
butchery_loot = null
if(LAZYLEN(organs))
organs_by_name.Cut()
for(var/obj/item/organ/OR in organs)
OR.removed()
organs -= OR
if(LAZYLEN(internal_organs))
internal_organs_by_name.Cut()
for(var/obj/item/organ/OR in internal_organs)
OR.removed()
internal_organs -= OR
if(!ckey)
if(issmall(src))
user?.visible_message("<span class='danger'>[user] chops up \the [src]!</span>")
new /obj/effect/decal/cleanable/blood/splatter(get_turf(src))
if(gib_on_butchery)
qdel(src)
else
user?.visible_message("<span class='danger'>[user] butchers \the [src] messily!</span>")
if(gib_on_butchery)
gib()

View File

@@ -1,4 +1,4 @@
/mob/living/carbon/ /mob/living/carbon
gender = MALE gender = MALE
var/datum/species/species //Contains icon generation and language information, set during New(). var/datum/species/species //Contains icon generation and language information, set during New().
var/list/stomach_contents = list() var/list/stomach_contents = list()

View File

@@ -283,3 +283,11 @@
message = "hides their wings." message = "hides their wings."
visible_message("[src] [message]") visible_message("[src] [message]")
// Chomp Edit Start
/mob/living/carbon/human/verb/hide_nutrition_vr()
set name = "Show/Hide Nutrition Levels"
set category = "IC"
set desc = "Allow other player to see your current nutrition level or not."
nutrition_hidden = !nutrition_hidden
to_chat(src, "Players will [nutrition_hidden ? "no longer" : "now"] see your nutrition levels.")
// Chomp Edit End

View File

@@ -68,6 +68,8 @@
/mob/living/carbon/human/proc/examine_nutrition() /mob/living/carbon/human/proc/examine_nutrition()
if(!show_pudge()) //Some clothing or equipment can hide this. if(!show_pudge()) //Some clothing or equipment can hide this.
return "" return ""
if(nutrition_hidden) // Chomp Edit
return ""
var/message = "" var/message = ""
var/nutrition_examine = round(nutrition) var/nutrition_examine = round(nutrition)
var/t_He = "It" //capitalised for use at the start of each line. var/t_He = "It" //capitalised for use at the start of each line.

View File

@@ -1,3 +1,6 @@
/mob/living/carbon/human
var/datum/unarmed_attack/default_attack
/mob/living/carbon/human/proc/get_unarmed_attack(var/mob/living/carbon/human/target, var/hit_zone) /mob/living/carbon/human/proc/get_unarmed_attack(var/mob/living/carbon/human/target, var/hit_zone)
// VOREStation Edit - Begin // VOREStation Edit - Begin
if(nif && nif.flag_check(NIF_C_HARDCLAWS,NIF_FLAGS_COMBAT)){return unarmed_hardclaws} if(nif && nif.flag_check(NIF_C_HARDCLAWS,NIF_FLAGS_COMBAT)){return unarmed_hardclaws}
@@ -16,6 +19,12 @@
if(soft_type) if(soft_type)
return soft_type return soft_type
return G.special_attack return G.special_attack
if(src.default_attack && src.default_attack.is_usable(src, target, hit_zone))
if(pulling_punches)
var/datum/unarmed_attack/soft_type = src.default_attack.get_sparring_variant()
if(soft_type)
return soft_type
return src.default_attack
for(var/datum/unarmed_attack/u_attack in species.unarmed_attacks) for(var/datum/unarmed_attack/u_attack in species.unarmed_attacks)
if(u_attack.is_usable(src, target, hit_zone)) if(u_attack.is_usable(src, target, hit_zone))
if(pulling_punches) if(pulling_punches)
@@ -434,3 +443,37 @@
user.visible_message("\The [user] stops applying pressure to [src]'s [organ.name]!", "You stop applying pressure to [src]'s [organ.name]!") user.visible_message("\The [user] stops applying pressure to [src]'s [organ.name]!", "You stop applying pressure to [src]'s [organ.name]!")
return TRUE return TRUE
/mob/living/carbon/human/verb/check_attacks()
set name = "Check Attacks"
set category = "IC"
set src = usr
var/dat = "<b><font size = 5>Known Attacks</font></b><br/><br/>"
if(default_attack)
dat += "Current default attack: [default_attack.attack_name] - <a href='byond://?src=\ref[src];default_attk=reset_attk'>reset</a><br/><br/>"
for(var/datum/unarmed_attack/u_attack in species.unarmed_attacks)
if(u_attack == default_attack)
dat += "<b>Primarily [u_attack.attack_name]</b> - default - <a href='byond://?src=\ref[src];default_attk=reset_attk'>reset</a><br/><br/><br/>"
else
dat += "<b>Primarily [u_attack.attack_name]</b> - <a href='byond://?src=\ref[src];default_attk=\ref[u_attack]'>set default</a><br/><br/><br/>"
src << browse(dat, "window=checkattack")
/mob/living/carbon/human/Topic(href, href_list)
if(href_list["default_attk"])
if(href_list["default_attk"] == "reset_attk")
set_default_attack(null)
else
var/datum/unarmed_attack/u_attack = locate(href_list["default_attk"])
if(u_attack && (u_attack in species.unarmed_attacks))
set_default_attack(u_attack)
check_attacks()
return 1
else
return ..()
/mob/living/carbon/human/proc/set_default_attack(var/datum/unarmed_attack/u_attack)
default_attack = u_attack

View File

@@ -439,13 +439,14 @@ This function restores all organs.
return 0 return 0
return return
/*
/mob/living/carbon/human/proc/get_organ(var/zone) /mob/living/carbon/human/proc/get_organ(var/zone)
if(!zone) if(!zone)
zone = BP_TORSO zone = BP_TORSO
else if (zone in list( O_EYES, O_MOUTH )) else if (zone in list( O_EYES, O_MOUTH ))
zone = BP_HEAD zone = BP_HEAD
return organs_by_name[zone] return organs_by_name[zone]
*/
/mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/soaked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null) /mob/living/carbon/human/apply_damage(var/damage = 0, var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/soaked = 0, var/sharp = 0, var/edge = 0, var/obj/used_weapon = null)
if(Debug2) if(Debug2)

View File

@@ -44,7 +44,7 @@
var/age = 30 //Player's age (pure fluff) var/age = 30 //Player's age (pure fluff)
var/b_type = "A+" //Player's bloodtype var/b_type = "A+" //Player's bloodtype
var/datum/robolimb/synthetic //If they are a synthetic (aka synthetic torso) var/datum/robolimb/synthetic //If they are a synthetic (aka synthetic torso). Also holds the datum for the type of robolimb.
var/list/all_underwear = list() var/list/all_underwear = list()
var/list/all_underwear_metadata = list() var/list/all_underwear_metadata = list()
@@ -85,7 +85,6 @@
var/special_voice = "" // For changing our voice. Used by a symptom. var/special_voice = "" // For changing our voice. Used by a symptom.
var/last_dam = -1 //Used for determining if we need to process all organs or just some or even none. var/last_dam = -1 //Used for determining if we need to process all organs or just some or even none.
var/list/bad_external_organs = list()// organs we check until they are good.
var/xylophone = 0 //For the spoooooooky xylophone cooldown var/xylophone = 0 //For the spoooooooky xylophone cooldown
@@ -118,3 +117,4 @@
var/obj/machinery/machine_visual //machine that is currently applying visual effects to this mob. Only used for camera monitors currently. var/obj/machinery/machine_visual //machine that is currently applying visual effects to this mob. Only used for camera monitors currently.
inventory_panel_type = /datum/inventory_panel/human inventory_panel_type = /datum/inventory_panel/human
butchery_loot = list(/obj/item/stack/animalhide/human = 1)

View File

@@ -10,6 +10,7 @@
var/ability_flags = 0 //Shadekin abilities/potentially other species-based? var/ability_flags = 0 //Shadekin abilities/potentially other species-based?
var/sensorpref = 5 //Suit sensor loadout pref var/sensorpref = 5 //Suit sensor loadout pref
var/wings_hidden = FALSE var/wings_hidden = FALSE
var/nutrition_hidden = FALSE // Chomp Edit
/mob/living/carbon/human/proc/shadekin_get_energy() /mob/living/carbon/human/proc/shadekin_get_energy()
var/datum/species/shadekin/SK = species var/datum/species/shadekin/SK = species

View File

@@ -5,6 +5,7 @@
update_icons_body() //Body handles eyes update_icons_body() //Body handles eyes
update_eyes() //For floating eyes only update_eyes() //For floating eyes only
/*
/mob/living/carbon/var/list/internal_organs = list() /mob/living/carbon/var/list/internal_organs = list()
/mob/living/carbon/human/var/list/organs = list() /mob/living/carbon/human/var/list/organs = list()
/mob/living/carbon/human/var/list/organs_by_name = list() // map organ names to organs /mob/living/carbon/human/var/list/organs_by_name = list() // map organ names to organs
@@ -13,6 +14,7 @@
/mob/living/carbon/human/proc/get_bodypart_name(var/zone) /mob/living/carbon/human/proc/get_bodypart_name(var/zone)
var/obj/item/organ/external/E = get_organ(zone) var/obj/item/organ/external/E = get_organ(zone)
if(E) . = E.name if(E) . = E.name
*/
/mob/living/carbon/human/proc/recheck_bad_external_organs() /mob/living/carbon/human/proc/recheck_bad_external_organs()
var/damage_this_tick = getToxLoss() var/damage_this_tick = getToxLoss()

View File

@@ -1,4 +1,5 @@
/datum/unarmed_attack/bite/sharp //eye teeth /datum/unarmed_attack/bite/sharp //eye teeth
attack_name = "sharp bite"
attack_verb = list("bit", "chomped on") attack_verb = list("bit", "chomped on")
attack_sound = 'sound/weapons/bite.ogg' attack_sound = 'sound/weapons/bite.ogg'
shredding = 0 shredding = 0
@@ -6,12 +7,14 @@
edge = 1 edge = 1
/datum/unarmed_attack/diona /datum/unarmed_attack/diona
attack_name = "tendrils"
attack_verb = list("lashed", "bludgeoned") attack_verb = list("lashed", "bludgeoned")
attack_noun = list("tendril") attack_noun = list("tendril")
eye_attack_text = "a tendril" eye_attack_text = "a tendril"
eye_attack_text_victim = "a tendril" eye_attack_text_victim = "a tendril"
/datum/unarmed_attack/claws /datum/unarmed_attack/claws
attack_name = "claws"
attack_verb = list("scratched", "clawed", "slashed") attack_verb = list("scratched", "clawed", "slashed")
attack_noun = list("claws") attack_noun = list("claws")
eye_attack_text = "claws" eye_attack_text = "claws"
@@ -54,6 +57,7 @@
if(5) user.visible_message("<span class='danger'>[user] tears [T.his] [pick(attack_noun)] [pick("deep into", "into", "across")] [target]'s [affecting.name]!</span>") if(5) user.visible_message("<span class='danger'>[user] tears [T.his] [pick(attack_noun)] [pick("deep into", "into", "across")] [target]'s [affecting.name]!</span>")
/datum/unarmed_attack/claws/strong /datum/unarmed_attack/claws/strong
attack_name = "strong claws"
attack_verb = list("slashed") attack_verb = list("slashed")
damage = 5 damage = 5
shredding = 1 shredding = 1
@@ -67,6 +71,7 @@
damage = 15 damage = 15
/datum/unarmed_attack/bite/strong /datum/unarmed_attack/bite/strong
attack_name = "strong bite"
attack_verb = list("mauled") attack_verb = list("mauled")
damage = 8 damage = 8
shredding = 1 shredding = 1
@@ -75,6 +80,7 @@
damage = 10 damage = 10
/datum/unarmed_attack/slime_glomp /datum/unarmed_attack/slime_glomp
attack_name = "glomp"
attack_verb = list("glomped") attack_verb = list("glomped")
attack_noun = list("body") attack_noun = list("body")
damage = 2 damage = 2
@@ -84,6 +90,7 @@
user.apply_stored_shock_to(target) user.apply_stored_shock_to(target)
/datum/unarmed_attack/stomp/weak /datum/unarmed_attack/stomp/weak
attack_name = "weak stomp"
attack_verb = list("jumped on") attack_verb = list("jumped on")
/datum/unarmed_attack/stomp/weak/get_unarmed_damage() /datum/unarmed_attack/stomp/weak/get_unarmed_damage()

View File

@@ -142,8 +142,8 @@
) )
unarmed_types = list( unarmed_types = list(
/datum/unarmed_attack/bite/sharp,
/datum/unarmed_attack/claws, /datum/unarmed_attack/claws,
/datum/unarmed_attack/bite/sharp,
/datum/unarmed_attack/stomp/weak /datum/unarmed_attack/stomp/weak
) )

View File

@@ -30,11 +30,10 @@
excludes = list(/datum/trait/lonely) excludes = list(/datum/trait/lonely)
/datum/trait/lonely/proc/check_mob_company(var/mob/living/carbon/human/H,var/mob/living/M) /datum/trait/lonely/proc/check_mob_company(var/mob/living/carbon/human/H,var/mob/living/M)
if(only_people && !istype(M, /mob/living/carbon) && !istype(M, /mob/living/silicon/robot)) var/social_check = only_people && !istype(M, /mob/living/carbon) && !istype(M, /mob/living/silicon/robot)
return 0 var/self_dead_invisible_check = M == H || M.stat == DEAD || M.invisibility > H.see_invisible
if(M == H || M.stat == DEAD || M.invisibility > H.see_invisible) var/ckey_check = only_people && !M.ckey
return 0 if(social_check || self_dead_invisible_check || ckey_check)
if(only_people && !M.ckey)
return 0 return 0
if(M.faction == "neutral" || M.faction == H.faction) if(M.faction == "neutral" || M.faction == H.faction)
if(H.loneliness_stage > 0) if(H.loneliness_stage > 0)
@@ -71,9 +70,13 @@
H.loneliness_stage -= 4 H.loneliness_stage -= 4
return return
// Check for company. // Check for company.
for(var/mob/living/M in viewers(H)) for(var/mob/living/M in H.contents)
if(istype(M) && check_mob_company(H,M))
return
for(var/mob/living/M in viewers(get_turf(H)))
if(check_mob_company(H,M)) if(check_mob_company(H,M))
return return
//Check to see if there's anyone in our belly
if(H.vore_organs) if(H.vore_organs)
for(var/obj/belly/B in H.vore_organs) for(var/obj/belly/B in H.vore_organs)
for(var/mob/living/content in B.contents) for(var/mob/living/content in B.contents)

View File

@@ -34,4 +34,4 @@
desc = "Your body is able to produce nutrition from being in light." desc = "Your body is able to produce nutrition from being in light."
cost = 3 cost = 3
var_changes = list("photosynthesizing" = TRUE) var_changes = list("photosynthesizing" = TRUE)
not_for_synths = 1 //Synths don't use nutrition. not_for_synths = 0 //Synths actually use nutrition, just with a fancy covering.

View File

@@ -2,6 +2,7 @@ var/global/list/sparring_attack_cache = list()
//Species unarmed attacks //Species unarmed attacks
/datum/unarmed_attack /datum/unarmed_attack
var/attack_name = "fist"
var/attack_verb = list("attack") // Empty hand hurt intent verb. var/attack_verb = list("attack") // Empty hand hurt intent verb.
var/attack_noun = list("fist") var/attack_noun = list("fist")
var/damage = 0 // Extra empty hand attack damage. var/damage = 0 // Extra empty hand attack damage.
@@ -109,6 +110,7 @@ var/global/list/sparring_attack_cache = list()
return FALSE //return true if the unarmed override prevents further attacks return FALSE //return true if the unarmed override prevents further attacks
/datum/unarmed_attack/bite /datum/unarmed_attack/bite
attack_name = "bite"
attack_verb = list("bit") attack_verb = list("bit")
attack_sound = 'sound/weapons/bite.ogg' attack_sound = 'sound/weapons/bite.ogg'
shredding = 0 shredding = 0
@@ -127,6 +129,7 @@ var/global/list/sparring_attack_cache = list()
return TRUE return TRUE
/datum/unarmed_attack/punch /datum/unarmed_attack/punch
attack_name = "punch"
attack_verb = list("punched") attack_verb = list("punched")
attack_noun = list("fist") attack_noun = list("fist")
eye_attack_text = "fingers" eye_attack_text = "fingers"
@@ -181,6 +184,7 @@ var/global/list/sparring_attack_cache = list()
user.visible_message("<span class='danger'>[user] [pick("punched", "threw a punch against", "struck", "slammed [TU.his] [pick(attack_noun)] into")] [target]'s [organ]!</span>") //why do we have a separate set of verbs for lying targets? user.visible_message("<span class='danger'>[user] [pick("punched", "threw a punch against", "struck", "slammed [TU.his] [pick(attack_noun)] into")] [target]'s [organ]!</span>") //why do we have a separate set of verbs for lying targets?
/datum/unarmed_attack/kick /datum/unarmed_attack/kick
attack_name = "kick"
attack_verb = list("kicked", "kicked", "kicked", "kneed") attack_verb = list("kicked", "kicked", "kicked", "kneed")
attack_noun = list("kick", "kick", "kick", "knee strike") attack_noun = list("kick", "kick", "kick", "knee strike")
attack_sound = "swing_hit" attack_sound = "swing_hit"
@@ -224,6 +228,7 @@ var/global/list/sparring_attack_cache = list()
if(5) user.visible_message("<span class='danger'>[user] landed a strong [pick(attack_noun)] against [target]'s [organ]!</span>") if(5) user.visible_message("<span class='danger'>[user] landed a strong [pick(attack_noun)] against [target]'s [organ]!</span>")
/datum/unarmed_attack/stomp /datum/unarmed_attack/stomp
attack_name = "stomp"
attack_verb = null attack_verb = null
attack_noun = list("stomp") attack_noun = list("stomp")
attack_sound = "swing_hit" attack_sound = "swing_hit"
@@ -269,6 +274,7 @@ var/global/list/sparring_attack_cache = list()
if(5) user.visible_message("<span class='danger'>[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed [TU.his] [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!</span>") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/ if(5) user.visible_message("<span class='danger'>[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed [TU.his] [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!</span>") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/
/datum/unarmed_attack/light_strike /datum/unarmed_attack/light_strike
attack_name = "light hit"
attack_noun = list("tap","light strike") attack_noun = list("tap","light strike")
attack_verb = list("tapped", "lightly struck") attack_verb = list("tapped", "lightly struck")
damage = 3 damage = 3

View File

@@ -31,9 +31,25 @@
nest = null nest = null
if(buckled) if(buckled)
buckled.unbuckle_mob(src, TRUE) buckled.unbuckle_mob(src, TRUE)
qdel(selected_image) qdel(selected_image)
QDEL_NULL(vorePanel) //VOREStation Add QDEL_NULL(vorePanel) //VOREStation Add
QDEL_LIST_NULL(vore_organs) //VOREStation Add QDEL_LIST_NULL(vore_organs) //VOREStation Add
if(LAZYLEN(organs))
organs_by_name.Cut()
while(organs.len)
var/obj/item/OR = organs[1]
organs -= OR
qdel(OR)
if(LAZYLEN(internal_organs))
internal_organs_by_name.Cut()
while(internal_organs.len)
var/obj/item/OR = internal_organs[1]
internal_organs -= OR
qdel(OR)
return ..() return ..()
//mob verbs are faster than object verbs. See mob/verb/examine. //mob verbs are faster than object verbs. See mob/verb/examine.
@@ -924,6 +940,12 @@ default behaviour is:
/mob/living/Moved(var/atom/oldloc, direct, forced, movetime) /mob/living/Moved(var/atom/oldloc, direct, forced, movetime)
. = ..() . = ..()
handle_footstep(loc) handle_footstep(loc)
// Begin VOREstation edit
if(is_shifted)
is_shifted = FALSE
pixel_x = 0
pixel_y = 0
// End VOREstation edit
if(pulling) // we were pulling a thing and didn't lose it during our move. if(pulling) // we were pulling a thing and didn't lose it during our move.
var/pull_dir = get_dir(src, pulling) var/pull_dir = get_dir(src, pulling)

View File

@@ -0,0 +1,28 @@
/mob/living
var/list/internal_organs = list()
var/list/organs = list()
var/list/organs_by_name = list() // map organ names to organs
var/list/internal_organs_by_name = list() // so internal organs have less ickiness too
var/list/bad_external_organs = list()// organs we check until they are good.
/mob/living/proc/get_bodypart_name(var/zone)
var/obj/item/organ/external/E = get_organ(zone)
if(E) . = E.name
/mob/living/proc/get_organ(var/zone)
if(!zone)
zone = BP_TORSO
else if (zone in list( O_EYES, O_MOUTH ))
zone = BP_HEAD
return organs_by_name[zone]
/mob/living/gib()
for(var/obj/item/organ/I in internal_organs)
I.removed()
if(isturf(I?.loc)) // Some organs qdel themselves or other things when removed
I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30)
for(var/obj/item/organ/external/E in src.organs)
E.droplimb(0,DROPLIMB_EDGE,1)
..()

View File

@@ -145,6 +145,7 @@
name = "MediHound hypospray" name = "MediHound hypospray"
desc = "An advanced chemical synthesizer and injection system utilizing carrier's reserves, designed for heavy-duty medical equipment." desc = "An advanced chemical synthesizer and injection system utilizing carrier's reserves, designed for heavy-duty medical equipment."
charge_cost = 10 charge_cost = 10
reagent_ids = list("inaprovaline", "dexalin", "bicaridine", "kelotane", "anti_toxin", "spaceacillin", "paracetamol")
var/datum/matter_synth/water = null var/datum/matter_synth/water = null
/obj/item/weapon/reagent_containers/borghypo/hound/process() //Recharges in smaller steps and uses the water reserves as well. /obj/item/weapon/reagent_containers/borghypo/hound/process() //Recharges in smaller steps and uses the water reserves as well.

View File

@@ -39,6 +39,7 @@
var/datum/matter_synth/water = null var/datum/matter_synth/water = null
var/digest_brute = 2 var/digest_brute = 2
var/digest_burn = 3 var/digest_burn = 3
var/digest_multiplier = 1
var/recycles = FALSE var/recycles = FALSE
var/medsensor = TRUE //Does belly sprite come with patient ok/dead light? var/medsensor = TRUE //Does belly sprite come with patient ok/dead light?
@@ -541,8 +542,8 @@
else else
var/old_brute = T.getBruteLoss() var/old_brute = T.getBruteLoss()
var/old_burn = T.getFireLoss() var/old_burn = T.getFireLoss()
T.adjustBruteLoss(digest_brute) T.adjustBruteLoss(digest_brute * digest_multiplier)
T.adjustFireLoss(digest_burn) T.adjustFireLoss(digest_burn * digest_multiplier)
var/actual_brute = T.getBruteLoss() - old_brute var/actual_brute = T.getBruteLoss() - old_brute
var/actual_burn = T.getFireLoss() - old_burn var/actual_burn = T.getFireLoss() - old_burn
var/damage_gain = actual_brute + actual_burn var/damage_gain = actual_brute + actual_burn
@@ -717,6 +718,7 @@
icon_state = "sleeperc" icon_state = "sleeperc"
injection_chems = list("glucose","inaprovaline","tricordrazine") injection_chems = list("glucose","inaprovaline","tricordrazine")
max_item_count = 1 max_item_count = 1
/obj/item/device/dogborg/sleeper/command //Command borg belly // CH addition /obj/item/device/dogborg/sleeper/command //Command borg belly // CH addition
name = "Bluespace Filing Belly" name = "Bluespace Filing Belly"
desc = "A mounted bluespace storage unit for carrying paperwork" desc = "A mounted bluespace storage unit for carrying paperwork"

View File

@@ -71,6 +71,5 @@
/mob/living/simple_mob/proc/remove_eyes() /mob/living/simple_mob/proc/remove_eyes()
cut_overlay(eye_layer) cut_overlay(eye_layer)
/mob/living/simple_mob/gib() /mob/living/simple_mob/gib()
..(icon_gib,1,icon) // we need to specify where the gib animation is stored ..(icon_gib,1,icon) // we need to specify where the gib animation is stored

View File

@@ -0,0 +1,8 @@
/mob/living/simple_mob
gib_on_butchery = TRUE
/mob/living/simple_mob/can_butcher(var/mob/user, var/obj/item/I) // Override for special butchering checks.
. = ..()
if(. && (!is_sharp(I) || !has_edge(I)))
return FALSE

View File

@@ -68,9 +68,9 @@
else else
var/datum/gender/T = gender_datums[src.get_visible_gender()] var/datum/gender/T = gender_datums[src.get_visible_gender()]
to_chat(user, "<span class='notice'>\The [src] is dead, medical items won't bring [T.him] back to life.</span>") // the gender lookup is somewhat overkill, but it functions identically to the obsolete gender macros and future-proofs this code to_chat(user, "<span class='notice'>\The [src] is dead, medical items won't bring [T.him] back to life.</span>") // the gender lookup is somewhat overkill, but it functions identically to the obsolete gender macros and future-proofs this code
if(meat_type && (stat == DEAD)) //if the animal has a meat, and if it is dead. if(can_butcher(user, O)) //if the animal can be butchered, do so and return. It's likely to be gibbed.
if(istype(O, /obj/item/weapon/material/knife)) harvest(user, O)
harvest(user) return
if(user.a_intent == I_HELP && harvest_tool && istype(O, harvest_tool) && stat != DEAD) if(user.a_intent == I_HELP && harvest_tool && istype(O, harvest_tool) && stat != DEAD)
if(world.time > (harvest_recent + harvest_cooldown)) if(world.time > (harvest_recent + harvest_cooldown))

View File

@@ -17,7 +17,7 @@
/mob/living/simple_mob/examine(mob/user) /mob/living/simple_mob/examine(mob/user)
. = ..() . = ..()
if(user && harvest_tool && (get_dist(user, src) <= 3)) if(stat != DEAD && user && harvest_tool && (get_dist(user, src) <= 3))
. += "<span class='notice'>\The [src] can be [harvest_verb] with a [initial(harvest_tool.name)] every [round(harvest_cooldown, 0.1)] minutes.</span>" . += "<span class='notice'>\The [src] can be [harvest_verb] with a [initial(harvest_tool.name)] every [round(harvest_cooldown, 0.1)] minutes.</span>"
var/time_to_harvest = (harvest_recent + harvest_cooldown) - world.time var/time_to_harvest = (harvest_recent + harvest_cooldown) - world.time
if(time_to_harvest > 0) if(time_to_harvest > 0)

View File

@@ -14,6 +14,8 @@
handle_special() handle_special()
handle_guts()
return TRUE return TRUE
@@ -137,6 +139,12 @@
else else
adjustOxyLoss(-unsuitable_atoms_damage) adjustOxyLoss(-unsuitable_atoms_damage)
/mob/living/simple_mob/proc/handle_guts()
for(var/obj/item/organ/OR in internal_organs)
OR.process()
for(var/obj/item/organ/OR in organs)
OR.process()
/mob/living/simple_mob/proc/handle_supernatural() /mob/living/simple_mob/proc/handle_supernatural()
if(purge) if(purge)

View File

@@ -57,8 +57,6 @@
var/response_harm = "tries to hurt" // If clicked on harm intent var/response_harm = "tries to hurt" // If clicked on harm intent
var/list/friends = list() // Mobs on this list wont get attacked regardless of faction status. var/list/friends = list() // Mobs on this list wont get attacked regardless of faction status.
var/harm_intent_damage = 3 // How much an unarmed harm click does to this mob. var/harm_intent_damage = 3 // How much an unarmed harm click does to this mob.
var/meat_amount = 0 // How much meat to drop from this mob when butchered
var/obj/meat_type // The meat object to drop
var/list/loot_list = list() // The list of lootable objects to drop, with "/path = prob%" structure var/list/loot_list = list() // The list of lootable objects to drop, with "/path = prob%" structure
var/obj/item/weapon/card/id/myid// An ID card if they have one to give them access to stuff. var/obj/item/weapon/card/id/myid// An ID card if they have one to give them access to stuff.
@@ -158,6 +156,10 @@
// don't process me if there's nobody around to see it // don't process me if there's nobody around to see it
low_priority = TRUE low_priority = TRUE
// Used for if the mob can drop limbs. Overrides species dmi.
var/limb_icon
// Used for if the mob can drop limbs. Overrides the icon cache key, so it doesn't keep remaking the icon needlessly.
var/limb_icon_key
/mob/living/simple_mob/Initialize() /mob/living/simple_mob/Initialize()
verbs -= /mob/verb/observe verbs -= /mob/verb/observe
@@ -170,8 +172,31 @@
if(has_eye_glow) if(has_eye_glow)
add_eyes() add_eyes()
return ..()
if(LAZYLEN(organs))
for(var/path in organs)
if(ispath(path))
var/obj/item/organ/external/neworg = new path(src)
neworg.name = "[name] [neworg.name]"
neworg.meat_type = meat_type
if(limb_icon)
neworg.force_icon = limb_icon
neworg.force_icon_key = limb_icon_key
organs |= neworg
organs -= path
if(LAZYLEN(internal_organs))
for(var/path in internal_organs)
if(ispath(path))
var/obj/item/organ/neworg = new path(src)
neworg.name = "[name] [neworg.name]"
neworg.meat_type = meat_type
internal_organs |= neworg
internal_organs -= path
return ..()
/mob/living/simple_mob/Destroy() /mob/living/simple_mob/Destroy()
default_language = null default_language = null
@@ -190,7 +215,6 @@
update_icon() update_icon()
..() ..()
//Client attached //Client attached
/mob/living/simple_mob/Login() /mob/living/simple_mob/Login()
. = ..() . = ..()
@@ -269,27 +293,6 @@
/mob/living/simple_mob/get_speech_ending(verb, var/ending) /mob/living/simple_mob/get_speech_ending(verb, var/ending)
return verb return verb
// Harvest an animal's delicious byproducts
/mob/living/simple_mob/proc/harvest(var/mob/user, var/invisible)
var/actual_meat_amount = max(1,(meat_amount/2))
var/attacker_name = user.name
if(invisible)
attacker_name = "someone"
if(meat_type && actual_meat_amount>0 && (stat == DEAD))
for(var/i=0;i<actual_meat_amount;i++)
var/obj/item/meat = new meat_type(get_turf(src))
meat.name = "[src.name] [meat.name]"
if(issmall(src))
user.visible_message("<span class='danger'>[attacker_name] chops up \the [src]!</span>")
new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
qdel(src)
else
user.visible_message("<span class='danger'>[attacker_name] butchers \the [src] messily!</span>")
gib()
/mob/living/simple_mob/is_sentient() /mob/living/simple_mob/is_sentient()
return mob_class & MOB_CLASS_HUMANOID|MOB_CLASS_ANIMAL|MOB_CLASS_SLIME // Update this if needed. return mob_class & MOB_CLASS_HUMANOID|MOB_CLASS_ANIMAL|MOB_CLASS_SLIME // Update this if needed.

View File

@@ -7,3 +7,16 @@
response_harm = "hits" response_harm = "hits"
ai_holder_type = /datum/ai_holder/simple_mob/melee ai_holder_type = /datum/ai_holder/simple_mob/melee
internal_organs = list(\
/obj/item/organ/internal/brain,\
/obj/item/organ/internal/heart,\
/obj/item/organ/internal/liver,\
/obj/item/organ/internal/stomach,\
/obj/item/organ/internal/intestine,\
/obj/item/organ/internal/lungs\
)
butchery_loot = list(\
/obj/item/stack/animalhide = 3\
)

View File

@@ -110,6 +110,10 @@
var/poison_chance = 10 // Chance for injection to occur. var/poison_chance = 10 // Chance for injection to occur.
var/poison_per_bite = 5 // Amount added per injection. var/poison_per_bite = 5 // Amount added per injection.
butchery_loot = list(\
/obj/item/stack/material/chitin = 1\
)
/mob/living/simple_mob/animal/giant_spider/apply_melee_effects(var/atom/A) /mob/living/simple_mob/animal/giant_spider/apply_melee_effects(var/atom/A)
if(isliving(A)) if(isliving(A))
var/mob/living/L = A var/mob/living/L = A

View File

@@ -0,0 +1,301 @@
#define BULLET_AP_DIVISOR 200
#define AP_DIVISOR 4152
#define ARMOR_Y_INTERCEPT 0.2
#define ARMOR_SLOPE 0.017
#define PENETRATION_PROBABILITY_EXP_BASE 2
#define PENETRATION_PROBABILITY_EXP_MULT 30
#define BULLET_DEFLECTED_PAIN_DIVISOR 5000
#define BULLET_DEFLECTED_BULLET_DIVISOR 70
#define BULLET_DEFLECTED_MELEE_DIVISOR 280
#define BULLET_DEFLECTED_PAIN_EXPONENT 1.5
#define BULLET_DEFLECTED_BRUISE_SUBTRACT 5
GLOBAL_VAR_INIT(SKIN_LOSS_COEFFICIENT,16)
GLOBAL_VAR_INIT(ARMOR_LOSS_COEFFICIENT,150)
GLOBAL_VAR_INIT(ARMOR_LOSS_MIN_MULT,0.5)
GLOBAL_VAR_INIT(ARMOR_LOSS_MIN_ARMOR,20)
GLOBAL_VAR_INIT(INTERNAL_LOSS_COEFFICIENT,195)
#define ORGAN_LOSS_COEFFICIENT 350
#define HIT_VITAL_ORGAN_CHANCE 35
#define BONE_HIT_CHANCE_UNENCASED 45
#define BONE_HIT_CHANCE_ENCASED 80
GLOBAL_VAR_INIT(BONE_JOULES_PERHP_AVG,2)
GLOBAL_VAR_INIT(BONE_JOULES_PERHP_DEV,1)
GLOBAL_VAR_INIT(BONE_JOULES_MIN,100)
#define BONE_HP_AVG 25
GLOBAL_VAR_INIT(HOLLOW_POINT_VELLOSS_BONUS,2.35)
GLOBAL_VAR_INIT(HOLLOW_POINT_CONVERSION_EFF,1.15)
#define PROB_LEAVE_EARLY_FIRST 20
#define PROB_LEAVE_EARLY_SECOND 40
GLOBAL_VAR_INIT(ENERGY_DAMAGE_FLESH_FACTOR,0.03)
GLOBAL_VAR_INIT(ENERGY_DAMAGE_ORGAN_FACTOR,0.035)
#ifndef GAUSSIAN_RANDOM
#define GAUSSIAN_RANDOM(vars...) ((-2*log(rand()))**0.5 * cos(6.28318530718*rand()))
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////// CADYN'S BALLISTICS ////////////////////////////////////////////////////////////////////////// ORIGINAL FROM CHOMPSTATION ////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/mob/living/proc/handle_ballistics(var/obj/item/projectile/bullet/P, var/def_zone)
var/list/updated_organ_weight = list()
var/ballistic_armor = getarmor(def_zone, "bullet")
var/melee_armor = getarmor(def_zone, "melee")
var/obj/item/organ/external/hit_organ
var/mob/living/carbon/human/H = src
if(istype(H))
hit_organ = H.get_organ(def_zone)
for(var/ext_organ in ballistic_variables["organ_hit_weight"])
var/list/input = list()
var/obj/item/organ/external/ref_ext_organ = H.get_organ(ext_organ)
for(var/int_organ in ballistic_variables["organ_hit_weight"][ext_organ])
var/ref_int_organ = H.internal_organs_by_name[int_organ]
if(ref_ext_organ && ref_int_organ && (ref_int_organ in ref_ext_organ.internal_organs))
input[ref_int_organ] = ballistic_variables["organ_hit_weight"][ext_organ][int_organ]
if(input.len)
updated_organ_weight[ref_ext_organ] = input
//log_and_message_admins("Beginning handle_ballistics")
var/penetration_chance = armor_penetration_probability(ballistic_armor,P)
if(!prob(penetration_chance)) //Boo-hoo we got deflected. Do boring agony/bruises stuff.
//log_and_message_admins("Bullet deflected")
var/pain_hit = hit_organ ? "into your [hit_organ]" : "into you"
var/hurt_value = P.velocity * P.grains / (BULLET_DEFLECTED_PAIN_DIVISOR * (1 + ballistic_armor/BULLET_DEFLECTED_BULLET_DIVISOR + melee_armor/BULLET_DEFLECTED_MELEE_DIVISOR)) //Better armor spreads out the energy better.
var/hurt_value_pain = hurt_value ** BULLET_DEFLECTED_PAIN_EXPONENT
var/hurt_value_bruise = max(0,hurt_value-BULLET_DEFLECTED_BRUISE_SUBTRACT)
var/absorber = ballistic_armor ? "armor" : "body" //There is a super tiny chance that small rounds can get deflected without armor, so this is just incase.
to_chat(src,"<span class='warning'>You feel the energy of the bullet painfully transfered [pain_hit] as your [absorber] deflects it!</span>")
apply_damage(hurt_value_pain,HALLOSS,def_zone)
if(hurt_value_bruise)
apply_damage(hurt_value_bruise,BRUTE,def_zone)
P.sub_velocity(P.velocity)
return 2
else //Now the FUN begins
//log_and_message_admins("Bullet penetrated")
var/area_over_mass = P.diam * P.diam / P.grains
//Most of these calculations don't involve energies because I'm treating flesh and organic tissue as a fluid since it's squishy and stuff.
//Since drag is proportional to velocity, we can do things on an m*v basis instead of an mv^2 basis.
//Obviously bones are more solid, so we do actual energy calculations for that.
var/conversion_efficiency = P.hollow_point ? GLOB.HOLLOW_POINT_CONVERSION_EFF : 1
var/vel_loss_multiplier = P.hollow_point ? GLOB.HOLLOW_POINT_VELLOSS_BONUS : 1
var/energy_dumped_organic = 0
var/vel_lost_armor = ballistic_armor >= GLOB.ARMOR_LOSS_MIN_ARMOR ? GLOB.ARMOR_LOSS_COEFFICIENT * area_over_mass * ((1 + GLOB.ARMOR_LOSS_MIN_MULT) - penetration_chance/100) : 0
P.sub_velocity(vel_lost_armor)
var/energy_past = P.energy
var/internal_loss = vel_loss_multiplier * GLOB.INTERNAL_LOSS_COEFFICIENT * area_over_mass
var/vel_lost_skin = vel_loss_multiplier * GLOB.SKIN_LOSS_COEFFICIENT * area_over_mass
P.sub_velocity(vel_lost_skin + internal_loss)
energy_dumped_organic += (energy_past - P.energy)
if(prob(PROB_LEAVE_EARLY_FIRST) || !P.velocity)
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
return 1
if(hit_organ)
//log_and_message_admins("organ_handle_ballistics called. hit_organ = [hit_organ], energy_dumped_organic = [energy_dumped_organic], internal_loss = [internal_loss], ballistic_armor = [ballistic_armor], P.velocity = [P.velocity], P.energy = [P.energy]")
return organ_handle_ballistics(P,hit_organ,energy_dumped_organic,internal_loss,ballistic_armor,updated_organ_weight)
else
//log_and_message_admins("general_handle_ballistics called.")
return general_handle_ballistics(P,def_zone,energy_dumped_organic,internal_loss,ballistic_armor)
/mob/living/proc/organ_handle_ballistics(var/obj/item/projectile/bullet/P,var/obj/item/organ/external/hit_organ,var/energy_dumped_organic,var/internal_loss,var/ballistic_armor,var/list/updated_organ_weight)
var/conversion_efficiency = P.hollow_point ? GLOB.HOLLOW_POINT_CONVERSION_EFF : 1
var/energy_past
var/area_over_mass = P.diam * P.diam / P.grains
var/bone_chance = BONE_HIT_CHANCE_UNENCASED
if(hit_organ.encased)
bone_chance = BONE_HIT_CHANCE_ENCASED
else
bone_chance = ballistic_variables["bone_chance_unencased"][hit_organ.organ_tag]
//log_and_message_admins("Bone hit chance is [bone_chance], organ is [hit_organ]")
if(prob(bone_chance))
var/energy_to_fracture = max(GLOB.BONE_JOULES_MIN, hit_organ.min_broken_damage * (GAUSSIAN_RANDOM()*GLOB.BONE_JOULES_PERHP_DEV + GLOB.BONE_JOULES_PERHP_AVG))
//log_and_message_admins("Bone hit, bone_chance1. energy_to_fracture = [energy_to_fracture]")
if(energy_to_fracture>=P.energy) //We don't have enough energy to get through the bone. This is the end for us!
energy_dumped_organic += P.energy/2 //About half of our remaining energy will go into fucking up this boi, the rest is absorbed by the bone
P.sub_velocity(P.velocity)
//log_and_message_admins("Insufficient projectile energy. Stopping projectile.")
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
return 2
else
//log_and_message_admins("Sufficient projectile energy to pass through bone.")
P.sub_energy(energy_to_fracture)
energy_dumped_organic += P.energy / 3 //About a third of the energy that goes into fracturing the bone also goes into fucking up tissues.
if(!(hit_organ.status & ORGAN_BROKEN))
//log_and_message_admins("Fracturing [hit_organ]")
hit_organ.fracture()
//log_and_message_admins("Bone checking done. hit_organ = [hit_organ], energy_dumped_organic = [energy_dumped_organic], internal_loss = [internal_loss], ballistic_armor = [ballistic_armor], P.velocity = [P.velocity], P.energy = [P.energy]")
if(hit_organ.internal_organs.len && P.velocity > area_over_mass*ORGAN_LOSS_COEFFICIENT && prob(ballistic_variables["organ_hit_chance"][hit_organ.organ_tag]) && updated_organ_weight[hit_organ] && updated_organ_weight[hit_organ].len)
//log_and_message_admins("Organ was hit by bullet.")
energy_past = P.energy
P.sub_velocity(internal_loss)
damage_organ_energy((energy_past - P.energy) * conversion_efficiency, pickweight(updated_organ_weight[hit_organ]))
if(!P.velocity)
//log_and_message_admins("Organ stopped bullet.")
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
return 2
//log_and_message_admins("Organ check done, hit_organ = [hit_organ], energy_dumped_organic = [energy_dumped_organic], internal_loss = [internal_loss], ballistic_armor = [ballistic_armor], P.velocity = [P.velocity], P.energy = [P.energy]")
energy_past = P.energy
P.sub_velocity(internal_loss)
energy_dumped_organic += energy_past - P.energy
if(!P.velocity || (hit_organ.organ_tag in ballistic_variables["organ_leave_early"]) || prob(PROB_LEAVE_EARLY_SECOND))
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
return P.velocity ? -1 : 2
//log_and_message_admins("Internal_loss 2 stopped bullet")
//log_and_message_admins("Internal_loss 2 completed, hit_organ = [hit_organ], energy_dumped_organic = [energy_dumped_organic], internal_loss = [internal_loss], ballistic_armor = [ballistic_armor], P.velocity = [P.velocity], P.energy = [P.energy]")
if(prob(bone_chance))
var/energy_to_fracture = max(GLOB.BONE_JOULES_MIN, hit_organ.min_broken_damage * (GAUSSIAN_RANDOM()*GLOB.BONE_JOULES_PERHP_DEV + GLOB.BONE_JOULES_PERHP_AVG))
//log_and_message_admins("Bone hit, bone_chance1. energy_to_fracture = [energy_to_fracture]")
if(energy_to_fracture>=P.energy) //We don't have enough energy to get through the bone. This is the end for us!
energy_dumped_organic += P.energy/2 //About half of our remaining energy will go into fucking up this boi, the rest is absorbed by the bone
P.sub_velocity(P.velocity)
//log_and_message_admins("Insufficient projectile energy. Stopping projectile.")
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
return 2
else
//log_and_message_admins("Sufficient projectile energy to pass through bone.")
P.sub_energy(energy_to_fracture)
energy_dumped_organic += P.energy / 3 //About a third of the energy that goes into fracturing the bone also goes into fucking up tissues.
if(!(hit_organ.status & ORGAN_BROKEN))
//log_and_message_admins("Fracturing [hit_organ]")
hit_organ.fracture()
energy_past = P.energy
P.sub_velocity(internal_loss)
energy_dumped_organic += energy_past - P.energy
if(!P.velocity)
//log_and_message_admins("Internal_loss 3 stopped bullet")
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
return 2
//log_and_message_admins("Internal_loss 3 completed. hit_organ = [hit_organ], energy_dumped_organic = [energy_dumped_organic], internal_loss = [internal_loss], ballistic_armor = [ballistic_armor], P.velocity = [P.velocity], P.energy = [P.energy]")
var/penetration_chance = armor_penetration_probability(ballistic_armor,P)
if(prob(penetration_chance))
//log_and_message_admins("Projectile exiting.")
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
return -1
else
//log_and_message_admins("Projectile continuing inside body")
energy_dumped_organic += P.energy / 3
P.sub_velocity(P.velocity)
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
return 2
/mob/living/proc/general_handle_ballistics(var/obj/item/projectile/bullet/P,var/def_zone,var/energy_dumped_organic,var/internal_loss,var/ballistic_armor)
var/conversion_efficiency = P.hollow_point ? GLOB.HOLLOW_POINT_CONVERSION_EFF : 1
var/energy_past
var/area_over_mass = P.diam * P.diam / P.grains
var/bone_chance = BONE_HIT_CHANCE_UNENCASED
//if(def_zone in ballistic_variables["bone_chance_unencased"])
//bone_chance = ballistic_variables["bone_chance_unencased"][def_zone]
if(prob(bone_chance))
var/energy_to_fracture = max(GLOB.BONE_JOULES_MIN, BONE_HP_AVG * (GAUSSIAN_RANDOM()*GLOB.BONE_JOULES_PERHP_DEV + GLOB.BONE_JOULES_PERHP_AVG))
if(energy_to_fracture>=P.energy) //We don't have enough energy to get through the bone. This is the end for us!
energy_dumped_organic += P.energy/2 //About half of our remaining energy will go into fucking up this boi, the rest is absorbed by the bone
P.sub_velocity(P.velocity)
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
return 2
else
P.sub_energy(energy_to_fracture)
energy_dumped_organic += P.energy / 3 //About a third of the energy that goes into fracturing the bone also goes into fucking up tissues.
if(P.velocity > area_over_mass * ORGAN_LOSS_COEFFICIENT && prob(HIT_VITAL_ORGAN_CHANCE))
energy_past = P.energy
P.sub_velocity(internal_loss)
energy_dumped_organic += (energy_past - P.energy) * 1.5
if(!P.velocity)
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
return 2
energy_past = P.energy
P.sub_velocity(internal_loss)
energy_dumped_organic += energy_past - P.energy
if(!P.velocity || (def_zone in ballistic_variables["organ_leave_early"]) || prob(PROB_LEAVE_EARLY_SECOND))
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
return P.velocity ? -1 : 2
if(prob(bone_chance))
var/energy_to_fracture = max(GLOB.BONE_JOULES_MIN, BONE_HP_AVG * (GAUSSIAN_RANDOM()*GLOB.BONE_JOULES_PERHP_DEV + GLOB.BONE_JOULES_PERHP_AVG))
if(energy_to_fracture>=P.energy) //We don't have enough energy to get through the bone. This is the end for us!
energy_dumped_organic += P.energy/2 //About half of our remaining energy will go into fucking up this boi, the rest is absorbed by the bone
P.sub_velocity(P.velocity)
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
return 2
else
P.sub_energy(energy_to_fracture)
energy_dumped_organic += P.energy / 3 //About a third of the energy that goes into fracturing the bone also goes into fucking up tissues.
energy_past = P.energy
P.sub_velocity(internal_loss)
energy_dumped_organic += energy_past - P.energy
if(!P.velocity)
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
return 2
var/penetration_chance = armor_penetration_probability(ballistic_armor,P)
if(prob(penetration_chance))
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
return -1
else
energy_dumped_organic += P.energy / 3
P.sub_velocity(P.velocity)
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
return 2
/mob/living/proc/damage_organ_energy(var/energy,var/obj/item/organ/internal/target)
var/damage = round(energy*GLOB.ENERGY_DAMAGE_ORGAN_FACTOR)
//log_and_message_admins("damage_organ_energy([energy]) : [target].take_damage([damage])")
target.take_damage(damage)
return
/mob/living/proc/energy_to_damage(var/energy,var/def_zone)
var/damage = round(energy*GLOB.ENERGY_DAMAGE_FLESH_FACTOR)
//log_and_message_admins("energy_to_damage([energy]) : apply_damage([damage], BRUTE, [def_zone])")
apply_damage(damage, BRUTE, def_zone)
return
/mob/living/proc/armor_penetration_probability(var/armor, var/obj/item/projectile/bullet/P)
var/bullet_ap_value = (1+((P.armor_penetration)/BULLET_AP_DIVISOR))
var/ap_value = P.velocity * bullet_ap_value * (P.grains / P.diam)**(2/3) / AP_DIVISOR
var/armor_value = ARMOR_Y_INTERCEPT + ARMOR_SLOPE * armor
var/penetration_chance = 100 / (1 + PENETRATION_PROBABILITY_EXP_BASE**(-PENETRATION_PROBABILITY_EXP_MULT*(ap_value - armor_value)))
return penetration_chance
/mob/living/bullet_act(var/obj/item/projectile/P, var/def_zone)
//log_and_message_admins("bullet_act_ch")
var/obj/item/projectile/bullet/B = P
if(P.check_armour == "bullet" && istype(B) && !B.old_bullet_act)
//log_and_message_admins("is bullet")
return handle_ballistics(P,def_zone)
else
//log_and_message_admins("is not bullet")
return ..()
/mob/living
var/list/ballistic_variables = list(\
"bone_chance_unencased" = list(BP_HEAD = 5, BP_TORSO = 20, BP_GROIN = 20, BP_L_FOOT = 80, BP_R_FOOT = 80, BP_L_LEG = 35, BP_R_LEG = 35, BP_L_ARM = 65, BP_R_ARM = 65, BP_L_HAND = 80, BP_R_HAND = 80), \
"organ_leave_early" = list("l_arm", "r_arm", "l_hand", "r_hand", "l_foot", "r_foot"), \
"organ_hit_weight" = list(\
BP_HEAD = list(\
/*Standard organs*/O_BRAIN = 90, O_EYES = 5, \
/*Diona organs*/O_RESPONSE = 10, O_RESPONSE = 15, O_GBLADDER = 15, \
/*Replicant organs*/O_VRLINK = 20, \
/*Xeno organs*/O_ACID = 10, O_RESIN = 10), \
BP_TORSO = list(\
/*Standard organs*/O_HEART = 5, O_LUNGS = 50, O_SPLEEN = 15, O_VOICE = 10, \
/*Synth organs*/O_CELL = 5, O_PUMP = 15, O_HEATSINK = 35, O_CYCLER = 15, O_DIAGNOSTIC = 10, \
/*Promethean organs*/O_REGBRUTE = 20, O_REGBURN = 20, O_REGOXY = 20, O_REGTOX = 20, \
/*Diona organs*/O_STRATA = 35, O_BRAIN = 20, O_NUTRIENT = 10, \
/*Replicant organs*/O_AREJECT = 35, \
/*Xeno organs*/O_PLASMA = 10, O_HIVE = 10), \
BP_GROIN = list(\
/*Standard organs*/O_INTESTINES = 50, O_STOMACH = 20, O_LIVER = 20, O_KIDNEYS = 15, O_APPENDIX = 5, \
/*Diona organs*/O_POLYP = 10, O_ANCHOR = 15, \
/*Replicant organs*/O_VENTC = 20, \
/*Xeno organs*/ O_EGG = 25) ), \
"organ_hit_chance" = list(BP_HEAD = 95, BP_TORSO = 90, BP_GROIN = 90) )

View File

@@ -0,0 +1,236 @@
#define BULLET_PENETRATED 1<<0
#define BULLET_BONECHECK1_TRUE 1<<1
#define BULLET_ORGANCHECK_TRUE 1<<2
#define BULLET_BONECHECK2_TRUE 1<<3
#define BULLET_PASSED_LEAVE_EARLY 1<<4
#define BULLET_PASSED_BONECHECK1 1<<5
#define BULLET_PASSED_ORGANCHECK 1<<6
#define BULLET_PASSED_INTERNALCHECK2 1<<7
#define BULLET_PASSED_BONECHECK2 1<<8
#define BULLET_PASSED_INTERNALCHECK3 1<<9
#define BULLET_TESTS 150
/mob/living/carbon/human/monkey/testerboyo
name = "testerboyo"
var/the_big_armor = 0
/mob/living/carbon/human/monkey/testerboyo/getarmor(var/def_zone,var/type)
return the_big_armor
/proc/test_all_ballistics()
var/mob/living/carbon/human/monkey/testerboyo/tester = new()
var/obj/item/projectile/bullet/pistol/test1 = new()
var/obj/item/projectile/bullet/pistol/ap/test2 = new()
var/obj/item/projectile/bullet/pistol/hp/test3 = new()
var/obj/item/projectile/bullet/pistol/medium/test4 = new()
var/obj/item/projectile/bullet/pistol/medium/ap/test5 = new()
var/obj/item/projectile/bullet/pistol/medium/hp/test6 = new()
var/obj/item/projectile/bullet/pistol/strong/test7 = new()
var/obj/item/projectile/bullet/shotgun/test8 = new()
var/obj/item/projectile/bullet/shotgun/buckshot/test9 = new()
var/obj/item/projectile/bullet/rifle/a762/test10 = new()
var/obj/item/projectile/bullet/rifle/a762/ap/test11 = new()
var/obj/item/projectile/bullet/rifle/a762/hp/test12 = new()
var/obj/item/projectile/bullet/rifle/a545/test13 = new()
var/obj/item/projectile/bullet/rifle/a545/ap/test14 = new()
var/obj/item/projectile/bullet/rifle/a545/hp/test15 = new()
var/obj/item/projectile/bullet/rifle/a145/test16 = new()
var/obj/item/projectile/bullet/rifle/a145/highvel/test17 = new()
var/obj/item/projectile/bullet/rifle/a44rifle/test18 = new()
var/obj/item/projectile/bullet/rifle/a95/test19 = new()
var/obj/item/projectile/bullet/rifle/a762/lmg/test20 = new()
test_ballistics(test1,tester)
test_ballistics(test2,tester)
test_ballistics(test3,tester)
test_ballistics(test4,tester)
test_ballistics(test5,tester)
test_ballistics(test6,tester)
test_ballistics(test7,tester)
test_ballistics(test8,tester)
test_ballistics(test9,tester)
test_ballistics(test10,tester)
test_ballistics(test11,tester)
test_ballistics(test12,tester)
test_ballistics(test13,tester)
test_ballistics(test14,tester)
test_ballistics(test15,tester)
test_ballistics(test16,tester)
test_ballistics(test17,tester)
test_ballistics(test18,tester)
test_ballistics(test19,tester)
test_ballistics(test20,tester)
qdel(tester)
qdel(test1)
qdel(test2)
qdel(test3)
qdel(test4)
qdel(test5)
qdel(test6)
qdel(test7)
qdel(test8)
qdel(test9)
qdel(test10)
qdel(test11)
qdel(test12)
qdel(test13)
qdel(test14)
qdel(test15)
qdel(test16)
qdel(test17)
qdel(test18)
qdel(test19)
qdel(test20)
/proc/test_ballistics(var/obj/item/projectile/bullet/P,var/mob/living/carbon/human/monkey/testerboyo/tester)
var/list/data = list()
for(var/armor_level in list(0,5,10,20,50,80))
data["[armor_level]"] = list()
data["[armor_level]"]["average"] = list()
tester.the_big_armor = armor_level
var/bp_num = 0
for(var/body_part in list(BP_TORSO,BP_HEAD,BP_R_LEG,BP_R_ARM,BP_R_HAND))
bp_num++
data["[armor_level]"][body_part] = list()
for(var/i = 0,i<BULLET_TESTS,i++)
P.velocity = initial(P.velocity)
P.sub_velocity(0)
var/out = tester.handle_ballistics(P,body_part)
for(var/x = 0,x<10,x++)
var/input = (out["chex"] & (1<<x)) ? 1 : 0
data["[armor_level]"][body_part]["[x]"] += input
data["[armor_level]"]["average"]["[x]"] += input
data["[armor_level]"][body_part]["10"] += out["energy"]
data["[armor_level]"][body_part]["10"] /= BULLET_TESTS
data["[armor_level]"]["average"]["10"] += data["[armor_level]"][body_part]["10"]
for(var/x = 0,x<11,x++)
data["[armor_level]"]["average"]["[x]"] /= bp_num
for(var/entry in data["[armor_level]"])
var/string_to_send = "[P.type]: Armor level [armor_level]: [entry]:"
for(var/x = 0,x<11,x++)
string_to_send += " [x]:[data["[armor_level]"][entry]["[x]"]]"
log_and_message_admins(string_to_send)
/proc/lazy_return_testing(var/chex,var/energy)
return list("chex" = chex, "energy" = energy)
/mob/living/carbon/human/monkey/testerboyo/handle_ballistics(var/obj/item/projectile/bullet/P, var/def_zone)
var/chex = 0
var/list/updated_organ_weight = list()
var/ballistic_armor = getarmor(def_zone, "bullet")
var/melee_armor = getarmor(def_zone, "melee")
var/obj/item/organ/external/hit_organ
var/mob/living/carbon/human/H = src
if(istype(H))
hit_organ = H.get_organ(def_zone)
for(var/ext_organ in ballistic_variables["organ_hit_weight"])
var/list/input = list()
var/obj/item/organ/external/ref_ext_organ = H.get_organ(ext_organ)
for(var/int_organ in ballistic_variables["organ_hit_weight"][ext_organ])
var/ref_int_organ = H.internal_organs_by_name[int_organ]
if(ref_ext_organ && ref_int_organ && (ref_int_organ in ref_ext_organ.internal_organs))
input[ref_int_organ] = ballistic_variables["organ_hit_weight"][ext_organ][int_organ]
if(input.len)
updated_organ_weight[ref_ext_organ] = input
var/penetration_chance = armor_penetration_probability(ballistic_armor,P)
if(!prob(penetration_chance)) //Boo-hoo we got deflected. Do boring agony/bruises stuff.
var/pain_hit = hit_organ ? "into your [hit_organ]" : "into you"
var/hurt_value = P.velocity * P.grains / (BULLET_DEFLECTED_PAIN_DIVISOR * (1 + ballistic_armor/BULLET_DEFLECTED_BULLET_DIVISOR + melee_armor/BULLET_DEFLECTED_MELEE_DIVISOR)) //Better armor spreads out the energy better.
var/hurt_value_pain = hurt_value ** BULLET_DEFLECTED_PAIN_EXPONENT
var/hurt_value_bruise = max(0,hurt_value-BULLET_DEFLECTED_BRUISE_SUBTRACT)
var/absorber = ballistic_armor ? "armor" : "body" //There is a super tiny chance that small rounds can get deflected without armor, so this is just incase.
to_chat(src,"<span class='warning'>You feel the energy of the bullet painfully transfered [pain_hit] as your [absorber] deflects it!</span>")
apply_damage(hurt_value_pain,HALLOSS,def_zone)
if(hurt_value_bruise)
apply_damage(hurt_value_bruise,BRUTE,def_zone)
P.sub_velocity(P.velocity)
return lazy_return_testing(chex,0)
else //Now the FUN begins
chex |= BULLET_PENETRATED
var/area_over_mass = P.diam * P.diam / P.grains
//Most of these calculations don't involve energies because I'm treating flesh and organic tissue as a fluid since it's squishy and stuff.
//Since drag is proportional to velocity, we can do things on an m*v basis instead of an mv^2 basis.
//Obviously bones are more solid, so we do actual energy calculations for that.
//var/conversion_efficiency = P.hollow_point ? 0.925 : 1
var/vel_loss_multiplier = P.hollow_point ? GLOB.HOLLOW_POINT_VELLOSS_BONUS : 1
var/energy_dumped_organic = 0
var/vel_lost_armor = ballistic_armor >= GLOB.ARMOR_LOSS_MIN_ARMOR ? GLOB.ARMOR_LOSS_COEFFICIENT * area_over_mass * ((1 + GLOB.ARMOR_LOSS_MIN_MULT) - penetration_chance/100) : 0
P.sub_velocity(vel_lost_armor)
var/energy_past = P.energy
var/internal_loss = vel_loss_multiplier * GLOB.INTERNAL_LOSS_COEFFICIENT * area_over_mass
var/vel_lost_skin = vel_loss_multiplier * GLOB.SKIN_LOSS_COEFFICIENT * area_over_mass
P.sub_velocity(vel_lost_skin + internal_loss)
energy_dumped_organic += (energy_past - P.energy)
if(prob(PROB_LEAVE_EARLY_FIRST) || !P.velocity)
return lazy_return_testing(chex,energy_dumped_organic)
if(hit_organ)
chex |= BULLET_PASSED_LEAVE_EARLY
return organ_handle_ballistics(P,hit_organ,energy_dumped_organic,internal_loss,ballistic_armor,updated_organ_weight,chex)
else
return general_handle_ballistics(P,def_zone,energy_dumped_organic,internal_loss,ballistic_armor)
/mob/living/carbon/human/monkey/testerboyo/organ_handle_ballistics(var/obj/item/projectile/bullet/P,var/obj/item/organ/external/hit_organ,var/energy_dumped_organic,var/internal_loss,var/ballistic_armor,var/list/updated_organ_weight,var/chex)
//var/conversion_efficiency = P.hollow_point ? 0.8 : 1
var/energy_past
var/area_over_mass = P.diam * P.diam / P.grains
var/bone_chance = BONE_HIT_CHANCE_UNENCASED
if(hit_organ.encased)
bone_chance = BONE_HIT_CHANCE_ENCASED
else
bone_chance = ballistic_variables["bone_chance_unencased"][hit_organ.organ_tag]
if(prob(bone_chance))
chex |= BULLET_BONECHECK1_TRUE
var/energy_to_fracture = max(GLOB.BONE_JOULES_MIN, hit_organ.min_broken_damage * (GAUSSIAN_RANDOM()*GLOB.BONE_JOULES_PERHP_DEV + GLOB.BONE_JOULES_PERHP_AVG))
if(energy_to_fracture>=P.energy) //We don't have enough energy to get through the bone. This is the end for us!
energy_dumped_organic += P.energy/2 //About half of our remaining energy will go into fucking up this boi, the rest is absorbed by the bone
P.sub_velocity(P.velocity)
return lazy_return_testing(chex,energy_dumped_organic)
else
P.sub_energy(energy_to_fracture)
energy_dumped_organic += energy_to_fracture / 3 //About a third of the energy that goes into fracturing the bone also goes into fucking up tissues.
chex |= BULLET_PASSED_BONECHECK1
if(hit_organ.internal_organs.len && P.velocity > area_over_mass*ORGAN_LOSS_COEFFICIENT && prob(ballistic_variables["organ_hit_chance"][hit_organ.organ_tag]) && updated_organ_weight[hit_organ] && updated_organ_weight[hit_organ].len)
chex |= BULLET_ORGANCHECK_TRUE
energy_past = P.energy
P.sub_velocity(internal_loss)
if(!P.velocity)
return lazy_return_testing(chex,energy_dumped_organic)
chex |= BULLET_PASSED_ORGANCHECK
energy_past = P.energy
P.sub_velocity(internal_loss)
energy_dumped_organic += energy_past - P.energy
if(!P.velocity || (hit_organ.organ_tag in ballistic_variables["organ_leave_early"]) || prob(PROB_LEAVE_EARLY_SECOND))
return lazy_return_testing(chex,energy_dumped_organic)
chex |= BULLET_PASSED_INTERNALCHECK2
if(prob(bone_chance))
chex |= BULLET_BONECHECK2_TRUE
var/energy_to_fracture = max(GLOB.BONE_JOULES_MIN, hit_organ.min_broken_damage * (GAUSSIAN_RANDOM()*GLOB.BONE_JOULES_PERHP_DEV + GLOB.BONE_JOULES_PERHP_AVG))
if(energy_to_fracture>=P.energy) //We don't have enough energy to get through the bone. This is the end for us!
energy_dumped_organic += P.energy/2 //About half of our remaining energy will go into fucking up this boi, the rest is absorbed by the bone
P.sub_velocity(P.velocity)
return lazy_return_testing(chex,energy_dumped_organic)
else
P.sub_energy(energy_to_fracture)
energy_dumped_organic += energy_to_fracture / 3 //About a third of the energy that goes into fracturing the bone also goes into fucking up tissues.
chex |= BULLET_PASSED_BONECHECK2
energy_past = P.energy
P.sub_velocity(internal_loss)
energy_dumped_organic += energy_past - P.energy
if(!P.velocity)
return lazy_return_testing(chex,energy_dumped_organic)
chex |= BULLET_PASSED_INTERNALCHECK3
var/penetration_chance = armor_penetration_probability(ballistic_armor,P)
if(prob(penetration_chance))
return lazy_return_testing(chex,energy_dumped_organic)
else
energy_dumped_organic += P.energy / 3
P.sub_velocity(P.velocity)
return lazy_return_testing(chex,energy_dumped_organic)

View File

@@ -1022,6 +1022,40 @@ mob/proc/yank_out_object()
set hidden = 1 set hidden = 1
set_face_dir(client.client_dir(WEST)) set_face_dir(client.client_dir(WEST))
// Begin VOREstation edit
/mob/verb/shiftnorth()
set hidden = TRUE
if(!canface())
return FALSE
if(pixel_y <= 16)
pixel_y++
is_shifted = TRUE
/mob/verb/shiftsouth()
set hidden = TRUE
if(!canface())
return FALSE
if(pixel_y >= -16)
pixel_y--
is_shifted = TRUE
/mob/verb/shiftwest()
set hidden = TRUE
if(!canface())
return FALSE
if(pixel_x >= -16)
pixel_x--
is_shifted = TRUE
mob/verb/shifteast()
set hidden = TRUE
if(!canface())
return FALSE
if(pixel_x <= 16)
pixel_x++
is_shifted = TRUE
// End VOREstation edit
/mob/proc/adjustEarDamage() /mob/proc/adjustEarDamage()
return return

View File

@@ -83,6 +83,7 @@
var/resting = 0 //Carbon var/resting = 0 //Carbon
var/lying = 0 var/lying = 0
var/lying_prev = 0 var/lying_prev = 0
var/is_shifted = FALSE // VoreStation Edit; pixel shifting
var/canmove = 1 var/canmove = 1
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects. //Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas. var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas.

View File

@@ -1184,17 +1184,6 @@
bee_stripes bee_stripes
name = "bee stripes" name = "bee stripes"
icon_state = "beestripes" icon_state = "beestripes"
<<<<<<< HEAD
body_parts = list(BP_TORSO,BP_GROIN)
||||||| parent of bbd7600f00... Merge pull request #9307 from KasparoVy/port-some-citrp-stuff
body_parts = list(BP_TORSO,BP_GROIN)
vas_toes
name = "Bug Paws (Vasilissan)"
icon_state = "vas_toes"
color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_L_FOOT,BP_R_FOOT)
=======
body_parts = list(BP_TORSO,BP_GROIN) body_parts = list(BP_TORSO,BP_GROIN)
vas_toes vas_toes
@@ -1269,4 +1258,4 @@
color_blend_mode = ICON_MULTIPLY color_blend_mode = ICON_MULTIPLY
body_parts = list(BP_L_LEG,BP_R_LEG,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN,BP_HEAD) body_parts = list(BP_L_LEG,BP_R_LEG,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN,BP_HEAD)
species_allowed = list(SPECIES_TESHARI) species_allowed = list(SPECIES_TESHARI)
>>>>>>> bbd7600f00... Merge pull request #9307 from KasparoVy/port-some-citrp-stuff body_parts = list(BP_L_FOOT,BP_R_FOOT)

View File

@@ -100,6 +100,8 @@
/datum/nifsoft/medichines_syn/life() /datum/nifsoft/medichines_syn/life()
if((. = ..())) if((. = ..()))
var/mob/living/carbon/human/H = nif.human // Chomp Edit
var/HP_percent = H.health/H.getMaxHealth() // Chomp Edit
//We're good! //We're good!
if(!nif.human.bad_external_organs.len) if(!nif.human.bad_external_organs.len)
if(mode || active) if(mode || active)
@@ -117,7 +119,7 @@
var/obj/item/organ/external/EO = eo var/obj/item/organ/external/EO = eo
for(var/w in EO.wounds) for(var/w in EO.wounds)
var/datum/wound/W = w var/datum/wound/W = w
if(W.damage <= 5) if(W.damage <= 30) // Chomp Edit // The current limb break threshold.
W.heal_damage(0.1) W.heal_damage(0.1)
EO.update_damages() EO.update_damages()
if(EO.update_icon()) if(EO.update_icon())
@@ -127,6 +129,17 @@
else if(mode == 1) else if(mode == 1)
mode = 2 mode = 2
nif.notify("Medichines unable to repair all damage. Perform manual repairs.",TRUE) nif.notify("Medichines unable to repair all damage. Perform manual repairs.",TRUE)
// Chomp Edit Start //
else if(mode == 2 && HP_percent < -0.4)
nif.notify("User Status: CRITICAL. Notifying medical!",TRUE)
H << 'sound/voice/nifmed_critical.ogg' //CHOMP Add
mode = 0
if(!isbelly(H.loc)) //Not notified in case of vore, for gameplay purposes.
var/turf/T = get_turf(H)
var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset/heads/captain(null)
a.autosay("[H.real_name] is in critical condition, located at ([T.x],[T.y],[T.z])!", "[H.real_name]'s NIF", "Medical")
qdel(a)
// Chomp Edit End //
return TRUE return TRUE

View File

@@ -14,6 +14,8 @@
target_parent_classes = list() // Is the parent supposed to be organic, robotic, assisted? target_parent_classes = list() // Is the parent supposed to be organic, robotic, assisted?
forgiving_class = TRUE // Will the organ give its verbs when it isn't a perfect match? I.E., assisted in organic, synthetic in organic. forgiving_class = TRUE // Will the organ give its verbs when it isn't a perfect match? I.E., assisted in organic, synthetic in organic.
butcherable = FALSE
var/obj/item/integrated_object // Objects held by the organ, used for re-usable, deployable things. var/obj/item/integrated_object // Objects held by the organ, used for re-usable, deployable things.
var/integrated_object_type // Object type the organ will spawn. var/integrated_object_type // Object type the organ will spawn.
var/target_slot = null var/target_slot = null

View File

@@ -83,7 +83,10 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain)
health = config.default_brain_health health = config.default_brain_health
defib_timer = (config.defib_timer MINUTES) / 2 defib_timer = (config.defib_timer MINUTES) / 2
spawn(5) spawn(5)
if(brainmob && brainmob.client) if(brainmob)
butcherable = FALSE
if(brainmob.client)
brainmob.client.screen.len = null //clear the hud brainmob.client.screen.len = null //clear the hud
/obj/item/organ/internal/brain/Destroy() /obj/item/organ/internal/brain/Destroy()
@@ -96,6 +99,8 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain)
brainmob = new(src) brainmob = new(src)
brainmob.name = H.real_name brainmob.name = H.real_name
brainmob.real_name = H.real_name brainmob.real_name = H.real_name
if(istype(H))
brainmob.dna = H.dna.Clone() brainmob.dna = H.dna.Clone()
brainmob.timeofhostdeath = H.timeofdeath brainmob.timeofhostdeath = H.timeofdeath
brainmob.ooc_notes = H.ooc_notes //VOREStation Edit brainmob.ooc_notes = H.ooc_notes //VOREStation Edit
@@ -125,13 +130,13 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain)
if(name == initial(name)) if(name == initial(name))
name = "\the [owner.real_name]'s [initial(name)]" name = "\the [owner.real_name]'s [initial(name)]"
var/mob/living/simple_mob/animal/borer/borer = owner.has_brain_worms() var/mob/living/simple_mob/animal/borer/borer = owner?.has_brain_worms()
if(borer) if(borer)
borer.detatch() //Should remove borer if the brain is removed - RR borer.detatch() //Should remove borer if the brain is removed - RR
var/obj/item/organ/internal/brain/B = src var/obj/item/organ/internal/brain/B = src
if(istype(B) && istype(owner)) if(istype(B) && owner)
B.transfer_identity(owner) B.transfer_identity(owner)
..() ..()

View File

@@ -8,7 +8,7 @@
/obj/item/organ/internal/liver/process() /obj/item/organ/internal/liver/process()
..() ..()
if(!owner) return if(!iscarbon(owner)) return
if(owner.life_tick % PROCESS_ACCURACY == 0) if(owner.life_tick % PROCESS_ACCURACY == 0)

View File

@@ -9,3 +9,4 @@
decays = FALSE // Ditto. Rust takes a while. decays = FALSE // Ditto. Rust takes a while.
robotic = ORGAN_ROBOT robotic = ORGAN_ROBOT
butcherable = FALSE

View File

@@ -44,6 +44,9 @@ var/list/organ_cache = list()
var/list/target_parent_classes = list() // Is the parent supposed to be organic, robotic, assisted? var/list/target_parent_classes = list() // Is the parent supposed to be organic, robotic, assisted?
var/forgiving_class = TRUE // Will the organ give its verbs when it isn't a perfect match? I.E., assisted in organic, synthetic in organic. var/forgiving_class = TRUE // Will the organ give its verbs when it isn't a perfect match? I.E., assisted in organic, synthetic in organic.
var/butcherable = TRUE
var/meat_type // What does butchering, if possible, make?
/obj/item/organ/Destroy() /obj/item/organ/Destroy()
handle_organ_mod_special(TRUE) handle_organ_mod_special(TRUE)
@@ -59,21 +62,42 @@ var/list/organ_cache = list()
/obj/item/organ/proc/update_health() /obj/item/organ/proc/update_health()
return return
/obj/item/organ/New(var/mob/living/carbon/holder, var/internal) /obj/item/organ/New(var/mob/living/holder, var/internal)
..(holder) ..(holder)
create_reagents(5) create_reagents(5)
if(!max_damage)
max_damage = min_broken_damage * 2 if(isliving(holder))
if(istype(holder))
src.owner = holder src.owner = holder
src.w_class = max(src.w_class + mob_size_difference(holder.mob_size, MOB_MEDIUM), 1) //smaller mobs have smaller organs. src.w_class = max(src.w_class + mob_size_difference(holder.mob_size, MOB_MEDIUM), 1) //smaller mobs have smaller organs.
if(internal)
if(!LAZYLEN(holder.internal_organs))
holder.internal_organs = list()
if(!LAZYLEN(holder.internal_organs_by_name))
holder.internal_organs_by_name = list()
holder.internal_organs |= src
holder.internal_organs_by_name[organ_tag] = src
else
if(!LAZYLEN(holder.organs))
holder.organs = list()
if(!LAZYLEN(holder.organs_by_name))
holder.organs_by_name = list()
holder.internal_organs |= src
holder.internal_organs_by_name[organ_tag] = src
if(!max_damage)
max_damage = min_broken_damage * 2
if(iscarbon(holder))
var/mob/living/carbon/C = holder
species = GLOB.all_species[SPECIES_HUMAN] species = GLOB.all_species[SPECIES_HUMAN]
if(holder.dna) if(holder.dna)
dna = holder.dna.Clone() dna = C.dna.Clone()
species = holder.species //VOREStation Edit - For custom species species = C.species //VOREStation Edit - For custom species
else else
log_debug("[src] at [loc] spawned without a proper DNA.") log_debug("[src] at [loc] spawned without a proper DNA.")
var/mob/living/carbon/human/H = holder var/mob/living/carbon/human/H = C
if(istype(H)) if(istype(H))
if(internal) if(internal)
var/obj/item/organ/external/E = H.get_organ(parent_organ) var/obj/item/organ/external/E = H.get_organ(parent_organ)
@@ -81,18 +105,32 @@ var/list/organ_cache = list()
if(E.internal_organs == null) if(E.internal_organs == null)
E.internal_organs = list() E.internal_organs = list()
E.internal_organs |= src E.internal_organs |= src
H.internal_organs_by_name[organ_tag] = src
if(dna) if(dna)
if(!blood_DNA) if(!blood_DNA)
blood_DNA = list() blood_DNA = list()
blood_DNA[dna.unique_enzymes] = dna.b_type blood_DNA[dna.unique_enzymes] = dna.b_type
if(internal)
holder.internal_organs |= src
else else
species = GLOB.all_species["Human"] species = GLOB.all_species["Human"]
handle_organ_mod_special() handle_organ_mod_special()
/obj/item/organ/Initialize()
..()
if(owner)
if(!meat_type)
if(owner.isSynthetic())
meat_type = /obj/item/stack/material/steel
else if(ishuman(owner))
var/mob/living/carbon/human/H = owner
meat_type = H?.species?.meat_type
if(!meat_type)
if(owner.meat_type)
meat_type = owner.meat_type
else
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
/obj/item/organ/proc/set_dna(var/datum/dna/new_dna) /obj/item/organ/proc/set_dna(var/datum/dna/new_dna)
if(new_dna) if(new_dna)
dna = new_dna.Clone() dna = new_dna.Clone()
@@ -134,7 +172,7 @@ var/list/organ_cache = list()
handle_organ_proc_special() handle_organ_proc_special()
//Process infections //Process infections
if(robotic >= ORGAN_ROBOT || (owner && owner.species && (owner.species.flags & IS_PLANT || (owner.species.flags & NO_INFECT)))) if(robotic >= ORGAN_ROBOT || (istype(owner) && (owner.species && (owner.species.flags & (IS_PLANT | NO_INFECT)))))
germ_level = 0 germ_level = 0
return return
@@ -152,7 +190,7 @@ var/list/organ_cache = list()
if(germ_level >= INFECTION_LEVEL_THREE) if(germ_level >= INFECTION_LEVEL_THREE)
die() die()
else if(owner && owner.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs else if(owner && owner?.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs
//** Handle antibiotics and curing infections //** Handle antibiotics and curing infections
handle_antibiotics() handle_antibiotics()
handle_rejection() handle_rejection()
@@ -170,7 +208,7 @@ var/list/organ_cache = list()
germ_level = 0 germ_level = 0
return 0 return 0
var/antibiotics = owner.chem_effects[CE_ANTIBIOTIC] || 0 var/antibiotics = iscarbon(owner) ? owner.chem_effects[CE_ANTIBIOTIC] || 0 : 0
var/infection_damage = 0 var/infection_damage = 0
@@ -203,10 +241,12 @@ var/list/organ_cache = list()
//Level 1 qualifies for specific organ processing effects //Level 1 qualifies for specific organ processing effects
if(germ_level >= INFECTION_LEVEL_ONE) if(germ_level >= INFECTION_LEVEL_ONE)
. = 1 . = 1 //Organ qualifies for effect-specific processing
var/fever_temperature = owner.species.heat_discomfort_level * 1.10 //Heat discomfort level plus 10% //var/fever_temperature = (owner.species.heat_level_1 - owner.species.body_temperature - 5)* min(germ_level/INFECTION_LEVEL_TWO, 1) + owner.species.body_temperature
if(owner.bodytemperature < fever_temperature) //owner.bodytemperature += between(0, (fever_temperature - T20C)/BODYTEMP_COLD_DIVISOR + 1, fever_temperature - owner.bodytemperature)
owner.bodytemperature += min(0.2,(fever_temperature - owner.bodytemperature) / 10) //Will usually climb by 0.2, else 10% of the difference if less var/fever_temperature = owner?.species.heat_discomfort_level * 1.10 //Heat discomfort level plus 10%
if(owner?.bodytemperature < fever_temperature)
owner?.bodytemperature += min(0.2,(fever_temperature - owner?.bodytemperature) / 10) //Will usually climb by 0.2, else 10% of the difference if less
//Level two qualifies for further processing effects //Level two qualifies for further processing effects
if (germ_level >= INFECTION_LEVEL_TWO) if (germ_level >= INFECTION_LEVEL_TWO)
@@ -269,6 +309,7 @@ var/list/organ_cache = list()
//Germs //Germs
/obj/item/organ/proc/handle_antibiotics() /obj/item/organ/proc/handle_antibiotics()
if(istype(owner))
var/antibiotics = owner.chem_effects[CE_ANTIBIOTIC] || 0 var/antibiotics = owner.chem_effects[CE_ANTIBIOTIC] || 0
if (!germ_level || antibiotics < ANTIBIO_NORM) if (!germ_level || antibiotics < ANTIBIO_NORM)
@@ -304,7 +345,7 @@ var/list/organ_cache = list()
//only show this if the organ is not robotic //only show this if the organ is not robotic
if(owner && parent_organ && amount > 0) if(owner && parent_organ && amount > 0)
var/obj/item/organ/external/parent = owner.get_organ(parent_organ) var/obj/item/organ/external/parent = owner?.get_organ(parent_organ)
if(parent && !silent) if(parent && !silent)
owner.custom_pain("Something inside your [parent.name] hurts a lot.", amount) owner.custom_pain("Something inside your [parent.name] hurts a lot.", amount)
@@ -322,6 +363,7 @@ var/list/organ_cache = list()
robotic = ORGAN_ASSISTED robotic = ORGAN_ASSISTED
min_bruised_damage = 15 min_bruised_damage = 15
min_broken_damage = 35 min_broken_damage = 35
butcherable = FALSE
/obj/item/organ/proc/digitize() //Used to make the circuit-brain. On this level in the event more circuit-organs are added/tweaks are wanted. /obj/item/organ/proc/digitize() //Used to make the circuit-brain. On this level in the event more circuit-organs are added/tweaks are wanted.
robotize() robotize()
@@ -341,10 +383,7 @@ var/list/organ_cache = list()
take_damage(rand(1,3)) take_damage(rand(1,3))
/obj/item/organ/proc/removed(var/mob/living/user) /obj/item/organ/proc/removed(var/mob/living/user)
if(owner)
if(!istype(owner))
return
owner.internal_organs_by_name[organ_tag] = null owner.internal_organs_by_name[organ_tag] = null
owner.internal_organs_by_name -= organ_tag owner.internal_organs_by_name -= organ_tag
owner.internal_organs_by_name -= null owner.internal_organs_by_name -= null
@@ -356,6 +395,8 @@ var/list/organ_cache = list()
forceMove(owner.drop_location()) forceMove(owner.drop_location())
START_PROCESSING(SSobj, src) START_PROCESSING(SSobj, src)
rejecting = null rejecting = null
if(istype(owner))
var/datum/reagent/blood/organ_blood = locate(/datum/reagent/blood) in reagents.reagent_list var/datum/reagent/blood/organ_blood = locate(/datum/reagent/blood) in reagents.reagent_list
if(!organ_blood || !organ_blood.data["blood_DNA"]) if(!organ_blood || !organ_blood.data["blood_DNA"])
owner.vessel.trans_to(src, 5, 1, 1) owner.vessel.trans_to(src, 5, 1, 1)
@@ -379,13 +420,13 @@ var/list/organ_cache = list()
var/datum/reagent/blood/transplant_blood = locate(/datum/reagent/blood) in reagents.reagent_list var/datum/reagent/blood/transplant_blood = locate(/datum/reagent/blood) in reagents.reagent_list
transplant_data = list() transplant_data = list()
if(!transplant_blood) if(!transplant_blood)
transplant_data["species"] = target.species.name transplant_data["species"] = target?.species.name
transplant_data["blood_type"] = target.dna.b_type transplant_data["blood_type"] = target?.dna.b_type
transplant_data["blood_DNA"] = target.dna.unique_enzymes transplant_data["blood_DNA"] = target?.dna.unique_enzymes
else else
transplant_data["species"] = transplant_blood.data["species"] transplant_data["species"] = transplant_blood?.data["species"]
transplant_data["blood_type"] = transplant_blood.data["blood_type"] transplant_data["blood_type"] = transplant_blood?.data["blood_type"]
transplant_data["blood_DNA"] = transplant_blood.data["blood_DNA"] transplant_data["blood_DNA"] = transplant_blood?.data["blood_DNA"]
owner = target owner = target
loc = owner loc = owner
@@ -428,6 +469,46 @@ var/list/organ_cache = list()
bitten(user) bitten(user)
return return
/obj/item/organ/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(can_butcher(W, user))
butcher(W, user)
return
return ..()
/obj/item/organ/proc/can_butcher(var/obj/item/O, var/mob/living/user)
if(butcherable && meat_type)
if(istype(O, /obj/machinery/gibber)) // The great equalizer.
return TRUE
if(robotic >= ORGAN_ROBOT)
if(O.is_screwdriver())
return TRUE
else
if(is_sharp(O) && has_edge(O))
return TRUE
return FALSE
/obj/item/organ/proc/butcher(var/obj/item/O, var/mob/living/user, var/atom/newtarget)
if(robotic >= ORGAN_ROBOT)
user?.visible_message("<span class='notice'>[user] disassembles \the [src].</span>")
else
user?.visible_message("<span class='notice'>[user] butchers \the [src].</span>")
if(!newtarget)
newtarget = get_turf(src)
var/obj/item/newmeat = new meat_type(newtarget)
if(istype(newmeat, /obj/item/weapon/reagent_containers/food/snacks/meat))
newmeat.name = "[src.name] [newmeat.name]" // "liver meat" "heart meat", etc.
qdel(src)
/obj/item/organ/proc/organ_can_feel_pain() /obj/item/organ/proc/organ_can_feel_pain()
if(species.flags & NO_PAIN) if(species.flags & NO_PAIN)
return 0 return 0

View File

@@ -34,7 +34,8 @@
var/body_part = null // Part flag var/body_part = null // Part flag
var/icon_position = 0 // Used in mob overlay layering calculations. var/icon_position = 0 // Used in mob overlay layering calculations.
var/model // Used when caching robolimb icons. var/model // Used when caching robolimb icons.
var/force_icon // Used to force override of species-specific limb icons (for prosthetics). var/force_icon // Used to force override of species-specific limb icons (for prosthetics). Also used for any limbs chopped from a simple mob, and then attached to humans.
var/force_icon_key // Used to force the override of the icon-key generated using the species. Must be used in tandem with the above.
var/icon/mob_icon // Cached icon for use in mob overlays. var/icon/mob_icon // Cached icon for use in mob overlays.
var/gendered_icon = 0 // Whether or not the icon state appends a gender. var/gendered_icon = 0 // Whether or not the icon state appends a gender.
var/s_tone // Skin tone. var/s_tone // Skin tone.
@@ -97,7 +98,7 @@
qdel(splinted) qdel(splinted)
splinted = null splinted = null
if(owner) if(istype(owner))
owner.organs -= src owner.organs -= src
owner.organs_by_name[organ_tag] = null owner.organs_by_name[organ_tag] = null
owner.organs_by_name -= organ_tag owner.organs_by_name -= organ_tag
@@ -199,7 +200,7 @@
return return
dislocated = 1 dislocated = 1
if(owner) if(istype(owner))
owner.verbs |= /mob/living/carbon/human/proc/relocate owner.verbs |= /mob/living/carbon/human/proc/relocate
/obj/item/organ/external/proc/relocate() /obj/item/organ/external/proc/relocate()
@@ -207,7 +208,7 @@
return return
dislocated = 0 dislocated = 0
if(owner) if(istype(owner))
owner.shock_stage += 20 owner.shock_stage += 20
//check to see if we still need the verb //check to see if we still need the verb
@@ -221,7 +222,7 @@
/obj/item/organ/external/New(var/mob/living/carbon/holder) /obj/item/organ/external/New(var/mob/living/carbon/holder)
..(holder, 0) ..(holder, 0)
if(owner) if(istype(owner))
replaced(owner) replaced(owner)
sync_colour_to_human(owner) sync_colour_to_human(owner)
spawn(1) spawn(1)
@@ -887,11 +888,11 @@ Note that amputating the affected organ does in fact remove the infection from t
var/mob/living/carbon/human/victim = owner //Keep a reference for post-removed(). var/mob/living/carbon/human/victim = owner //Keep a reference for post-removed().
var/obj/item/organ/external/parent_organ = parent var/obj/item/organ/external/parent_organ = parent
var/use_flesh_colour = species.get_flesh_colour(owner) var/use_flesh_colour = species?.get_flesh_colour(owner) ? species.get_flesh_colour(owner) : "#C80000"
var/use_blood_colour = species.get_blood_colour(owner) var/use_blood_colour = species?.get_blood_colour(owner) ? species.get_blood_colour(owner) : "#C80000"
removed(null, ignore_children) removed(null, ignore_children)
victim.traumatic_shock += 60 victim?.traumatic_shock += 60
if(parent_organ) if(parent_organ)
var/datum/wound/lost_limb/W = new (src, disintegrate, clean) var/datum/wound/lost_limb/W = new (src, disintegrate, clean)
@@ -907,9 +908,12 @@ Note that amputating the affected organ does in fact remove the infection from t
stump.update_damages() stump.update_damages()
spawn(1) spawn(1)
if(istype(victim))
victim.updatehealth() victim.updatehealth()
victim.UpdateDamageIcon() victim.UpdateDamageIcon()
victim.update_icons_body() victim.update_icons_body()
else
victim.update_icons()
dir = 2 dir = 2
var/atom/droploc = victim.drop_location() var/atom/droploc = victim.drop_location()
@@ -1236,7 +1240,7 @@ Note that amputating the affected organ does in fact remove the infection from t
organ.loc = src organ.loc = src
// Remove parent references // Remove parent references
parent.children -= src parent?.children -= src
parent = null parent = null
release_restraints(victim) release_restraints(victim)

View File

@@ -58,7 +58,7 @@ var/global/list/limb_icon_cache = list()
cut_overlays() cut_overlays()
//Every 'addon' below requires information from species //Every 'addon' below requires information from species
if(!owner || !owner.species) if(!iscarbon(owner) || !owner.species)
return return
//Eye color/icon //Eye color/icon
@@ -135,7 +135,10 @@ var/global/list/limb_icon_cache = list()
if(owner && owner.gender == FEMALE) if(owner && owner.gender == FEMALE)
gender = "f" gender = "f"
if(!force_icon_key)
icon_cache_key = "[icon_name]_[species ? species.get_bodytype() : SPECIES_HUMAN]" //VOREStation Edit icon_cache_key = "[icon_name]_[species ? species.get_bodytype() : SPECIES_HUMAN]" //VOREStation Edit
else
icon_cache_key = "[icon_name]_[force_icon_key]"
if(force_icon) if(force_icon)
mob_icon = new /icon(force_icon, "[icon_name][gendered_icon ? "_[gender]" : ""]") mob_icon = new /icon(force_icon, "[icon_name][gendered_icon ? "_[gender]" : ""]")

View File

@@ -38,6 +38,7 @@
var/brain_type = /obj/item/device/mmi var/brain_type = /obj/item/device/mmi
var/obj/item/device/mmi/stored_mmi var/obj/item/device/mmi/stored_mmi
robotic = ORGAN_ASSISTED robotic = ORGAN_ASSISTED
butcherable = FALSE
/obj/item/organ/internal/mmi_holder/Destroy() /obj/item/organ/internal/mmi_holder/Destroy()
if(stored_mmi && (stored_mmi.loc == src)) if(stored_mmi && (stored_mmi.loc == src))

View File

@@ -282,6 +282,7 @@
/obj/item/organ/external/head/removed() /obj/item/organ/external/head/removed()
if(owner) if(owner)
if(iscarbon(owner))
name = "[owner.real_name]'s head" name = "[owner.real_name]'s head"
owner.drop_from_inventory(owner.glasses) owner.drop_from_inventory(owner.glasses)
owner.drop_from_inventory(owner.head) owner.drop_from_inventory(owner.head)

View File

@@ -112,7 +112,7 @@
var/can_hold_val = 0 var/can_hold_val = 0
loading = TRUE loading = TRUE
while(mat_storage + SHEET_MATERIAL_AMOUNT <= max_mat_storage && do_after(user,1.5 SECONDS)) while(can_hold_val < M.amount && mat_storage + SHEET_MATERIAL_AMOUNT <= max_mat_storage && do_after(user,1.5 SECONDS)) //CHOMPEdit
can_hold_val ++ can_hold_val ++
mat_storage += SHEET_MATERIAL_AMOUNT mat_storage += SHEET_MATERIAL_AMOUNT
playsound(src, 'sound/effects/phasein.ogg', 15, 1) playsound(src, 'sound/effects/phasein.ogg', 15, 1)

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