mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-13 11:43:31 +00:00
Merge branch 'master' into upstream-merge-9307
This commit is contained in:
@@ -155,6 +155,8 @@
|
||||
#define MAT_METALHYDROGEN "mhydrogen"
|
||||
#define MAT_OSMIUM "osmium"
|
||||
#define MAT_GRAPHITE "graphite"
|
||||
#define MAT_LEATHER "leather"
|
||||
#define MAT_CHITIN "chitin"
|
||||
|
||||
#define SHARD_SHARD "shard"
|
||||
#define SHARD_SHRAPNEL "shrapnel"
|
||||
|
||||
@@ -114,11 +114,12 @@
|
||||
trigger_aiming(TARGET_CAN_CLICK)
|
||||
return 1
|
||||
|
||||
// VOREStation Addition Start: inbelly interaction
|
||||
// VOREStation Addition Start: inbelly item interaction
|
||||
if(isbelly(loc) && (loc == A.loc))
|
||||
if(W)
|
||||
to_chat(src, "The firm confines prevent that kind of dexterity!") //Only hand-based interactions in bellies
|
||||
return
|
||||
var/resolved = W.resolve_attackby(A,src)
|
||||
if(!resolved && A && W)
|
||||
W.afterattack(A, src, 1, params) // 1: clicking something Adjacent
|
||||
else
|
||||
if(ismob(A)) // No instant mob attacking
|
||||
setClickCooldown(get_attack_speed())
|
||||
|
||||
@@ -7,7 +7,7 @@ datum/controller/transfer_controller
|
||||
var/shift_last_vote = 0 //VOREStation Edit
|
||||
datum/controller/transfer_controller/New()
|
||||
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
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
|
||||
|
||||
43
code/controllers/subsystems/reflect_ch.dm
Normal file
43
code/controllers/subsystems/reflect_ch.dm
Normal 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
|
||||
@@ -72,13 +72,24 @@ SUBSYSTEM_DEF(vote)
|
||||
/datum/controller/subsystem/vote/proc/get_result() // Get the highest number of votes
|
||||
var/greatest_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)
|
||||
var/votes = choices[option]
|
||||
total_votes += votes
|
||||
if(votes > greatest_votes)
|
||||
greatest_votes = votes
|
||||
|
||||
//CHOMPEdit End
|
||||
if(!config.vote_no_default && choices.len) // Default-vote for everyone who didn't vote
|
||||
var/non_voters = (GLOB.clients.len - total_votes)
|
||||
if(non_voters > 0)
|
||||
@@ -107,12 +118,14 @@ SUBSYSTEM_DEF(vote)
|
||||
choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] * factor)
|
||||
to_world("<font color='purple'>Crew Transfer Factor: [factor]</font>")
|
||||
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
|
||||
if(greatest_votes)
|
||||
for(var/option in choices)
|
||||
if(choices[option] == greatest_votes)
|
||||
. += option
|
||||
//CHOMPEdit End
|
||||
|
||||
/datum/controller/subsystem/vote/proc/announce_result()
|
||||
var/list/winners = get_result()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
var/signal_enabled = FALSE
|
||||
var/weakref/weakref // Holder of weakref instance pointing to this datum
|
||||
var/datum_flags = NONE
|
||||
var/trigger_uid //CHOMPEdit
|
||||
|
||||
#ifdef TESTING
|
||||
var/tmp/running_find_references
|
||||
|
||||
@@ -19,10 +19,13 @@
|
||||
alt_titles = list("Intern" = /datum/alt_title/intern,
|
||||
"Apprentice Engineer" = /datum/alt_title/intern_eng,
|
||||
"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,
|
||||
"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 \
|
||||
another job. Though they are part of the crew, they have no real authority."
|
||||
timeoff_factor = 0 // Interns, noh
|
||||
@@ -33,7 +36,7 @@
|
||||
/datum/alt_title/intern_eng
|
||||
title = "Apprentice Engineer"
|
||||
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
|
||||
|
||||
/datum/alt_title/intern_med
|
||||
@@ -43,9 +46,9 @@
|
||||
title_outfit = /decl/hierarchy/outfit/job/assistant/medic
|
||||
|
||||
/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 \
|
||||
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
|
||||
|
||||
/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_outfit = /decl/hierarchy/outfit/job/service/server
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
// Visitor
|
||||
//////////////////////////////////
|
||||
//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
|
||||
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()
|
||||
..()
|
||||
@@ -82,11 +88,17 @@
|
||||
else
|
||||
return list()
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
// Visitor
|
||||
//////////////////////////////////
|
||||
|
||||
/datum/job/assistant // Visitor
|
||||
title = USELESS_JOB
|
||||
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."
|
||||
timeoff_factor = 0
|
||||
alt_titles = list("Guest" = /datum/alt_title/guest, "Traveler" = /datum/alt_title/traveler)
|
||||
|
||||
/datum/job/assistant/New()
|
||||
..()
|
||||
@@ -96,3 +108,9 @@
|
||||
|
||||
/datum/job/assistant/get_access()
|
||||
return list()
|
||||
|
||||
/datum/alt_title/guest
|
||||
title = "Guest"
|
||||
|
||||
/datum/alt_title/traveler
|
||||
title = "Traveler"
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
disallow_jobhop = TRUE
|
||||
pto_type = PTO_CIVILIAN
|
||||
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
|
||||
disallow_jobhop = TRUE
|
||||
@@ -10,8 +18,8 @@
|
||||
departments_managed = list(DEPARTMENT_CIVILIAN, DEPARTMENT_CARGO, DEPARTMENT_PLANET)
|
||||
dept_time_required = 60
|
||||
|
||||
alt_titles = list("Crew Resources Officer" = /datum/alt_title/cro,
|
||||
"Deputy Director" = /datum/alt_title/deputy_director)
|
||||
alt_titles = list("Crew Resources Officer" = /datum/alt_title/cro, "Deputy Director" = /datum/alt_title/deputy_director, "Staff Manager" = /datum/alt_title/staff_manager,
|
||||
"Facility Steward" = /datum/alt_title/facility_steward) //CHOMPEdit
|
||||
|
||||
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,
|
||||
@@ -29,6 +37,27 @@
|
||||
/datum/alt_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
|
||||
disallow_jobhop = TRUE
|
||||
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"
|
||||
|
||||
@@ -1,34 +1,104 @@
|
||||
/datum/job/bartender
|
||||
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
|
||||
total_positions = 2 //IT TAKES A LOT TO MAKE A STEW
|
||||
spawn_positions = 2 //A PINCH OF SALT AND LAUGHTER, TOO
|
||||
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
|
||||
spawn_positions = 2
|
||||
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
|
||||
pto_type = PTO_CARGO
|
||||
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
|
||||
total_positions = 3
|
||||
spawn_positions = 3
|
||||
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
|
||||
total_positions = 4
|
||||
spawn_positions = 4
|
||||
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.
|
||||
total_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
|
||||
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
|
||||
title = "Sanitation Technician"
|
||||
@@ -36,26 +106,73 @@
|
||||
/datum/alt_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
|
||||
total_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
|
||||
|
||||
/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
|
||||
title = "Historian"
|
||||
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
|
||||
title = "Professor"
|
||||
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
|
||||
disallow_jobhop = TRUE
|
||||
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
|
||||
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
|
||||
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
|
||||
/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
|
||||
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
|
||||
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
|
||||
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!"
|
||||
|
||||
/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?"
|
||||
|
||||
@@ -12,10 +12,38 @@
|
||||
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
|
||||
access_heads, access_construction,
|
||||
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
|
||||
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
|
||||
spawn_positions = 3
|
||||
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."
|
||||
|
||||
@@ -29,6 +29,8 @@ var/const/SAR =(1<<14)
|
||||
color = "#bab421"
|
||||
sorting_order = 2 // Same as cargo in importance.
|
||||
|
||||
|
||||
|
||||
/datum/job/pathfinder
|
||||
title = "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)
|
||||
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."
|
||||
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
|
||||
title = "Pilot"
|
||||
@@ -71,9 +78,15 @@ var/const/SAR =(1<<14)
|
||||
minimal_access = list(access_pilot)
|
||||
outfit_type = /decl/hierarchy/outfit/job/pilot
|
||||
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
|
||||
title = "Explorer"
|
||||
@@ -91,9 +104,14 @@ var/const/SAR =(1<<14)
|
||||
minimal_access = list(access_explorer, access_external_airlocks, access_eva)
|
||||
outfit_type = /decl/hierarchy/outfit/job/explorer2
|
||||
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
|
||||
title = "Field Medic"
|
||||
@@ -112,25 +130,7 @@ var/const/SAR =(1<<14)
|
||||
minimal_access = list(access_medical, access_medical_equip, access_morgue, access_pilot)
|
||||
outfit_type = /decl/hierarchy/outfit/job/medical/sar
|
||||
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
|
||||
title = "Field 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"
|
||||
/datum/alt_title/expedition_medic
|
||||
title = "Expedition Medic"
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
req_admin_notify = 1
|
||||
economic_modifier = 10
|
||||
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)
|
||||
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)
|
||||
|
||||
minimum_character_age = 25
|
||||
|
||||
@@ -4,22 +4,77 @@
|
||||
dept_time_required = 60
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
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
|
||||
spawn_positions = 5
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
pto_type = PTO_CIVILIAN
|
||||
economic_modifier = 2
|
||||
|
||||
/datum/alt_title/offduty_civ
|
||||
title = "Off-duty Worker"
|
||||
|
||||
/datum/job/offduty_cargo
|
||||
title = "Off-duty Cargo"
|
||||
latejoin_only = TRUE
|
||||
@@ -37,9 +34,6 @@
|
||||
pto_type = PTO_CARGO
|
||||
economic_modifier = 2
|
||||
|
||||
/datum/alt_title/offduty_crg
|
||||
title = "Off-duty Cargo"
|
||||
|
||||
/datum/job/offduty_engineering
|
||||
title = "Off-duty Engineer"
|
||||
latejoin_only = TRUE
|
||||
@@ -56,9 +50,6 @@
|
||||
pto_type = PTO_ENGINEERING
|
||||
economic_modifier = 5
|
||||
|
||||
/datum/alt_title/offduty_eng
|
||||
title = "Off-duty Engineer"
|
||||
|
||||
/datum/job/offduty_medical
|
||||
title = "Off-duty Medic"
|
||||
latejoin_only = TRUE
|
||||
@@ -75,9 +66,6 @@
|
||||
pto_type = PTO_MEDICAL
|
||||
economic_modifier = 5
|
||||
|
||||
/datum/alt_title/offduty_med
|
||||
title = "Off-duty Medic"
|
||||
|
||||
/datum/job/offduty_science
|
||||
title = "Off-duty Scientist"
|
||||
latejoin_only = TRUE
|
||||
@@ -94,9 +82,6 @@
|
||||
pto_type = PTO_SCIENCE
|
||||
economic_modifier = 5
|
||||
|
||||
/datum/alt_title/offduty_sci
|
||||
title = "Off-duty Scientist"
|
||||
|
||||
/datum/job/offduty_security
|
||||
title = "Off-duty Officer"
|
||||
latejoin_only = TRUE
|
||||
@@ -113,5 +98,18 @@
|
||||
pto_type = PTO_SECURITY
|
||||
economic_modifier = 5
|
||||
|
||||
/datum/alt_title/offduty_sec
|
||||
title = "Off-duty Officer"
|
||||
/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
|
||||
|
||||
@@ -13,30 +13,73 @@
|
||||
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_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
|
||||
spawn_positions = 5
|
||||
pto_type = PTO_SCIENCE
|
||||
alt_titles = list("Xenoarchaeologist" = /datum/alt_title/xenoarch, "Anomalist" = /datum/alt_title/anomalist, \
|
||||
"Phoron Researcher" = /datum/alt_title/phoron_research, "Circuit Designer" = /datum/alt_title/circuit_designer)
|
||||
alt_titles = list("Lab Assistant" = /datum/alt_title/lab_assistant, "Xenoarchaeologist" = /datum/alt_title/xenoarch, "Xenopaleontologist" = /datum/alt_title/xenopaleontologist, \
|
||||
"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)
|
||||
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
|
||||
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. \
|
||||
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
|
||||
spawn_positions = 3
|
||||
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
|
||||
total_positions = 3
|
||||
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
|
||||
@@ -61,3 +104,7 @@
|
||||
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 \
|
||||
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"
|
||||
|
||||
@@ -3,23 +3,55 @@
|
||||
pto_type = PTO_SECURITY
|
||||
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_construction,
|
||||
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_construction,
|
||||
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
|
||||
pto_type = PTO_SECURITY
|
||||
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
|
||||
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
|
||||
total_positions = 5
|
||||
spawn_positions = 5
|
||||
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"
|
||||
@@ -85,18 +85,18 @@
|
||||
selection_color = "#515151"
|
||||
economic_modifier = 1
|
||||
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
|
||||
latejoin_only = 1
|
||||
outfit_type = /decl/hierarchy/outfit/job/clown
|
||||
pto_type = PTO_CIVILIAN
|
||||
|
||||
/datum/alt_title/clown
|
||||
title = "Clown"
|
||||
alt_titles = list("Jester" = /datum/alt_title/jester, "Fool" = /datum/alt_title/fool)
|
||||
|
||||
/datum/alt_title/jester
|
||||
title = "Jester"
|
||||
|
||||
/datum/alt_title/fool
|
||||
title = "Fool"
|
||||
|
||||
/datum/job/clown/get_access()
|
||||
if(config.assistant_maint)
|
||||
return list(access_maint_tunnels, access_entertainment)
|
||||
@@ -115,17 +115,14 @@
|
||||
selection_color = "#515151"
|
||||
economic_modifier = 1
|
||||
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
|
||||
latejoin_only = 1
|
||||
outfit_type = /decl/hierarchy/outfit/job/mime
|
||||
pto_type = PTO_CIVILIAN
|
||||
|
||||
/datum/alt_title/mime
|
||||
title = "Mime"
|
||||
|
||||
/datum/alt_title/interpretive_dancer
|
||||
title = "Interpretive Dancer"
|
||||
/datum/alt_title/poseur
|
||||
title = "Poseur"
|
||||
|
||||
/datum/job/mime/get_access()
|
||||
if(config.assistant_maint)
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
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
|
||||
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.welded = 0
|
||||
update_icon()
|
||||
|
||||
122
code/game/machinery/feeder.dm
Normal file
122
code/game/machinery/feeder.dm
Normal 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
@@ -67,9 +67,14 @@
|
||||
|
||||
//Tanning!
|
||||
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
|
||||
qdel(HH)
|
||||
washing -= HH
|
||||
HH.forceMove(get_turf(src))
|
||||
HH.use(HH.amount)
|
||||
|
||||
washing += WL
|
||||
|
||||
if(locate(/mob,washing))
|
||||
state = 7
|
||||
@@ -130,7 +135,7 @@
|
||||
to_chat(user, "<span class='warning'>You can't fit \the [W] inside.</span>")
|
||||
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(state in list(1, 3))
|
||||
user.drop_item()
|
||||
|
||||
@@ -21,9 +21,61 @@
|
||||
/obj/item/device/starcaster_news/attack_self(mob/user as mob)
|
||||
|
||||
user.set_machine(src)
|
||||
ui_interact(user) //Activates nanoUI. Fuck nanoUI.
|
||||
tgui_interact(user) //Activates tgui. Bless tgui.
|
||||
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
|
||||
if(..())
|
||||
return 1
|
||||
@@ -73,3 +125,4 @@
|
||||
ui.auto_update_layout = 1
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
*/
|
||||
@@ -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
|
||||
name = "human skin"
|
||||
desc = "The by-product of human farming."
|
||||
singular_name = "human skin piece"
|
||||
name = "skin"
|
||||
desc = "The by-product of sapient farming."
|
||||
singular_name = "skin piece"
|
||||
icon_state = "sheet-hide"
|
||||
no_variants = FALSE
|
||||
drop_sound = 'sound/items/drop/leather.ogg'
|
||||
pickup_sound = 'sound/items/pickup/leather.ogg'
|
||||
|
||||
/obj/item/stack/animalhide/human
|
||||
amount = 50
|
||||
amount = 1
|
||||
stacktype = "hide-human"
|
||||
|
||||
/obj/item/stack/animalhide/corgi
|
||||
name = "corgi hide"
|
||||
desc = "The by-product of corgi farming."
|
||||
singular_name = "corgi hide piece"
|
||||
icon_state = "sheet-corgi"
|
||||
|
||||
/obj/item/stack/animalhide/corgi
|
||||
amount = 50
|
||||
amount = 1
|
||||
stacktype = "hide-corgi"
|
||||
|
||||
/obj/item/stack/animalhide/cat
|
||||
name = "cat hide"
|
||||
desc = "The by-product of cat farming."
|
||||
singular_name = "cat hide piece"
|
||||
icon_state = "sheet-cat"
|
||||
|
||||
/obj/item/stack/animalhide/cat
|
||||
amount = 50
|
||||
amount = 1
|
||||
stacktype = "hide-cat"
|
||||
|
||||
/obj/item/stack/animalhide/monkey
|
||||
name = "monkey hide"
|
||||
desc = "The by-product of monkey farming."
|
||||
singular_name = "monkey hide piece"
|
||||
icon_state = "sheet-monkey"
|
||||
|
||||
/obj/item/stack/animalhide/monkey
|
||||
amount = 50
|
||||
amount = 1
|
||||
stacktype = "hide-monkey"
|
||||
|
||||
/obj/item/stack/animalhide/lizard
|
||||
name = "lizard skin"
|
||||
desc = "Sssssss..."
|
||||
singular_name = "lizard skin piece"
|
||||
icon_state = "sheet-lizard"
|
||||
|
||||
/obj/item/stack/animalhide/lizard
|
||||
amount = 50
|
||||
amount = 1
|
||||
stacktype = "hide-lizard"
|
||||
|
||||
/obj/item/stack/animalhide/xeno
|
||||
name = "alien hide"
|
||||
desc = "The skin of a terrible creature."
|
||||
singular_name = "alien hide piece"
|
||||
icon_state = "sheet-xeno"
|
||||
|
||||
/obj/item/stack/animalhide/xeno
|
||||
amount = 50
|
||||
amount = 1
|
||||
stacktype = "hide-xeno"
|
||||
|
||||
//don't see anywhere else to put these, maybe together they could be used to make the xenos suit?
|
||||
/obj/item/stack/xenochitin
|
||||
name = "alien chitin"
|
||||
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_state = "chitin"
|
||||
|
||||
/obj/item/stack/xenochitin
|
||||
amount = 50
|
||||
amount = 1
|
||||
stacktype = "hide-chitin"
|
||||
|
||||
/obj/item/xenos_claw
|
||||
name = "alien claw"
|
||||
@@ -84,9 +89,22 @@
|
||||
singular_name = "hairless hide piece"
|
||||
icon_state = "sheet-hairlesshide"
|
||||
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
|
||||
amount = 50
|
||||
var/wet_type = /obj/item/stack/wetleather
|
||||
|
||||
/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
|
||||
name = "wet leather"
|
||||
@@ -96,28 +114,27 @@
|
||||
var/wetness = 30 //Reduced when exposed to high temperautres
|
||||
var/drying_threshold_temperature = 500 //Kelvin to start drying
|
||||
no_variants = FALSE
|
||||
amount = 1
|
||||
stacktype = "wetleather"
|
||||
|
||||
/obj/item/stack/wetleather
|
||||
amount = 50
|
||||
var/dry_type = /obj/item/stack/material/leather
|
||||
|
||||
//Step one - dehairing.
|
||||
/obj/item/stack/animalhide/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if( istype(W, /obj/item/weapon/material/knife) || \
|
||||
istype(W, /obj/item/weapon/material/twohanded/fireaxe) || \
|
||||
istype(W, /obj/item/weapon/material/knife/machete/hatchet) )
|
||||
|
||||
if(has_edge(W) || is_sharp(W))
|
||||
//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")
|
||||
if(do_after(user,50))
|
||||
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
|
||||
for(var/obj/item/stack/hairlesshide/HS in usr.loc)
|
||||
if(HS.amount < 50)
|
||||
if(HS.amount < 50 && istype(HS, process_type))
|
||||
HS.amount++
|
||||
src.use(1)
|
||||
break
|
||||
return
|
||||
//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
|
||||
src.use(1)
|
||||
else
|
||||
@@ -132,15 +149,20 @@
|
||||
if(exposed_temperature >= drying_threshold_temperature)
|
||||
wetness--
|
||||
if(wetness == 0)
|
||||
dry()
|
||||
|
||||
/obj/item/stack/wetleather/proc/dry()
|
||||
//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)
|
||||
if(HS.amount < 50)
|
||||
HS.amount++
|
||||
src.use(1)
|
||||
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.
|
||||
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
|
||||
wetness = initial(wetness)
|
||||
src.use(1)
|
||||
|
||||
@@ -380,7 +380,7 @@
|
||||
var/use_material
|
||||
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.result_type = result_type
|
||||
src.req_amount = req_amount
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/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."
|
||||
generated_reagents = list("egg" = 2)
|
||||
usable_volume = 500
|
||||
transfer_amount = 50
|
||||
usable_volume = 1500
|
||||
transfer_amount = 300
|
||||
var/verb_descriptor = list("squeezes", "pushes", "hugs")
|
||||
var/self_verb_descriptor = list("squeeze", "push", "hug")
|
||||
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")
|
||||
assigned_proc = /mob/living/carbon/human/proc/use_reagent_implant_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)
|
||||
START_PROCESSING(SSobj, src)
|
||||
to_chat(source, "<span class='notice'>You implant [source] with \the [src].</span>")
|
||||
source.verbs |= assigned_proc
|
||||
source.verbs |= /mob/living/carbon/human/proc/toggle_cascade
|
||||
return 1
|
||||
|
||||
/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(src, "<span class='notice'>[pick(rimplant.empty_message)]</span>")
|
||||
return
|
||||
visible_message("<span class='notice'>[usr] starts squeezing [src]'s lower body firmly...</span>")
|
||||
if (rimplant && do_after(usr,60))
|
||||
visible_message("<span class='danger'>[usr] starts squeezing [src]'s lower body firmly...</span>")
|
||||
if (rimplant && do_after(usr,120,src))
|
||||
if(src.Adjacent(usr))
|
||||
var/egg = rimplant.eggtype
|
||||
new egg(get_turf(src))
|
||||
src.SetStunned(3)
|
||||
@@ -73,37 +76,59 @@
|
||||
visible_message("<span class='notice'>[src] [pick(rimplant.random_emote)].</span>")
|
||||
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>")
|
||||
while(rimplant.reagents.total_volume >= rimplant.transfer_amount)
|
||||
if(do_after(src,30))
|
||||
src.SetStunned(5)
|
||||
src.SetStunned(3)
|
||||
playsound(src,'sound/vore/insert.ogg',50,1)
|
||||
src.apply_effect(10,STUTTER,0)
|
||||
new egg(get_turf(src))
|
||||
rimplant.reagents.remove_any(rimplant.transfer_amount)
|
||||
if(prob(25))
|
||||
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
|
||||
name = "slow egg laying implant"
|
||||
usable_volume = 3000
|
||||
transfer_amount = 300
|
||||
transfer_amount = 600
|
||||
|
||||
/obj/item/weapon/implant/reagent_generator/egg/veryslow
|
||||
name = "very slow egg laying implant"
|
||||
usable_volume = 6000
|
||||
transfer_amount = 600
|
||||
transfer_amount = 1200
|
||||
|
||||
/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
|
||||
usable_volume = 1000 // Effectively, the transfer_amount is the cost/time of making an egg. Usable volume is simply the max number of eggs.
|
||||
transfer_amount = 50
|
||||
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 = 300
|
||||
|
||||
/obj/item/weapon/implant/reagent_generator/egg/doublehicap
|
||||
name = "extreme capacity egg laying implant"
|
||||
usable_volume = 2000
|
||||
transfer_amount = 50
|
||||
usable_volume = 6000
|
||||
transfer_amount = 300
|
||||
|
||||
/obj/item/weapon/implant/reagent_generator/egg/slowlowcap
|
||||
name = "slow, low capacity egg laying implant"
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
item_state = "candlebox5"
|
||||
throwforce = 2
|
||||
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)
|
||||
|
||||
/obj/item/weapon/storage/fancy/whitecandle_box
|
||||
@@ -80,7 +80,7 @@
|
||||
item_state = "whitecandlebox5"
|
||||
throwforce = 2
|
||||
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)
|
||||
|
||||
/obj/item/weapon/storage/fancy/blackcandle_box
|
||||
@@ -92,7 +92,7 @@
|
||||
item_state = "blackcandlebox5"
|
||||
throwforce = 2
|
||||
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)
|
||||
|
||||
|
||||
|
||||
7
code/game/objects/items/weapons/storage/fancy_ch.dm
Normal file
7
code/game/objects/items/weapons/storage/fancy_ch.dm
Normal 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)
|
||||
@@ -349,6 +349,8 @@
|
||||
to_chat(user, "<span class='danger'>You go blind!</span>")
|
||||
user.Blind(5)
|
||||
user.eye_blurry = 5
|
||||
// Don't cure being nearsighted
|
||||
if(!(H.disabilities & NEARSIGHTED))
|
||||
user.disabilities |= NEARSIGHTED
|
||||
spawn(100)
|
||||
user.disabilities &= ~NEARSIGHTED
|
||||
|
||||
96
code/game/objects/items/weapons/tools/zspicytools_ch.dm
Normal file
96
code/game/objects/items/weapons/tools/zspicytools_ch.dm
Normal 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
|
||||
)
|
||||
230
code/game/objects/kasscbuttons_ch.dm
Normal file
230
code/game/objects/kasscbuttons_ch.dm
Normal 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
|
||||
@@ -250,6 +250,16 @@
|
||||
|
||||
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)
|
||||
|
||||
/obj/structure/bonfire/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
|
||||
@@ -494,3 +494,47 @@
|
||||
|
||||
/obj/structure/flora/sif/tendrils/get_harvestable_desc()
|
||||
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>"
|
||||
|
||||
313
code/game/objects/structures/reflectors_ch.dm
Normal file
313
code/game/objects/structures/reflectors_ch.dm
Normal 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
|
||||
..()
|
||||
@@ -3,7 +3,7 @@ GLOBAL_VAR(trader_loaded)
|
||||
/proc/consider_trader_load()
|
||||
if(!GLOB.trader_loaded)
|
||||
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))
|
||||
error("Trader is not a valid map template!")
|
||||
else
|
||||
|
||||
@@ -147,6 +147,8 @@
|
||||
|
||||
if(M.slip("the [floor_type] floor", slip_stun))
|
||||
for(var/i = 1 to slip_dist)
|
||||
if(M.slip_vore_in_progress) //CHOMPEdit
|
||||
break //CHOMPEdit
|
||||
step(M, M.dir)
|
||||
sleep(1)
|
||||
else
|
||||
|
||||
@@ -90,5 +90,10 @@ var/list/grass_types = list(
|
||||
icon_state = "grass_sif_dark0"
|
||||
edge_blending_priority = 5
|
||||
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
|
||||
)
|
||||
|
||||
88
code/game/turfs/triggers_ch.dm
Normal file
88
code/game/turfs/triggers_ch.dm
Normal 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()
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
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
|
||||
|
||||
var/mob/living/carbon/human/H = input("Pick a mob with a player","Quick NIF") as null|anything in player_list
|
||||
|
||||
@@ -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))
|
||||
@@ -614,3 +614,34 @@
|
||||
display_name = "disheveled suit"
|
||||
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
|
||||
@@ -184,9 +184,12 @@
|
||||
return TOPIC_REFRESH
|
||||
|
||||
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/choice = alert("Remove [initial(trait.name)] and regain [initial(trait.cost)] points?","Remove Trait","Remove","Cancel")
|
||||
if(choice == "Remove")
|
||||
if(traitpath == /datum/trait/linguist) //CHOMPEdit
|
||||
pref.num_languages = 0 //CHOMPEdit
|
||||
pref.pos_traits -= trait
|
||||
return TOPIC_REFRESH
|
||||
|
||||
@@ -287,7 +290,8 @@
|
||||
alert("You cannot take this trait and [conflict] at the same time. \
|
||||
Please remove that trait, or pick another trait to add.","Error")
|
||||
return TOPIC_REFRESH
|
||||
|
||||
if(path==/datum/trait/linguist) //CHOMPEdit
|
||||
pref.num_languages = 12 //CHOMPEdit
|
||||
mylist += path
|
||||
return TOPIC_REFRESH
|
||||
|
||||
|
||||
@@ -159,6 +159,12 @@
|
||||
icon_state = "scrubsnavyblue"
|
||||
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
|
||||
desc = "A basic white jumpsuit. It has turqouise markings that denote the wearer as a psychiatrist."
|
||||
name = "psychiatrist's jumpsuit"
|
||||
|
||||
@@ -621,7 +621,7 @@ Uniforms and such
|
||||
*/
|
||||
|
||||
/obj/item/clothing/under/sundress
|
||||
name = "sundress"
|
||||
name = "flowery white sundress"
|
||||
desc = "Makes you want to frolic in a field of daisies."
|
||||
icon_state = "sundress"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO
|
||||
@@ -632,6 +632,47 @@ Uniforms and such
|
||||
icon_state = "sundress_white"
|
||||
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
|
||||
name = "site manager's formal uniform"
|
||||
desc = "A Site Manager's formal-wear, for special occasions."
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// List of all non-destroyed canisters on station levels
|
||||
var/list/all_canisters = list()
|
||||
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
|
||||
|
||||
for(var/i in 1 to 10)
|
||||
|
||||
@@ -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),
|
||||
// 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, "Drone Pod Drop", /datum/event/drone_pod_drop, 10, list(ASSIGNMENT_SCIENTIST = 40), 1),
|
||||
|
||||
// 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),
|
||||
//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, "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),
|
||||
//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.
|
||||
//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),
|
||||
@@ -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, "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_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, "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),
|
||||
|
||||
@@ -4039,6 +4039,40 @@
|
||||
/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
|
||||
name = "sunflower seeds"
|
||||
desc = "Sunflower seeds!"
|
||||
|
||||
@@ -192,3 +192,60 @@
|
||||
..()
|
||||
reagents.add_reagent("tealeavesgreen", 6)
|
||||
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?
|
||||
@@ -188,18 +188,13 @@
|
||||
update_icon()
|
||||
|
||||
var/slab_name = occupant.name
|
||||
var/slab_count = 3
|
||||
var/slab_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
var/slab_count = 2 + occupant.meat_amount
|
||||
var/slab_type = occupant.meat_type ? occupant.meat_type : /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
var/slab_nutrition = src.occupant.nutrition / 15
|
||||
|
||||
// Some mobs have specific meat item types.
|
||||
if(istype(src.occupant,/mob/living/simple_mob))
|
||||
var/mob/living/simple_mob/critter = src.occupant
|
||||
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/list/byproducts = occupant?.butchery_loot?.Copy()
|
||||
|
||||
if(istype(src.occupant,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = occupant
|
||||
slab_name = src.occupant.real_name
|
||||
slab_type = H.isSynthetic() ? /obj/item/stack/material/steel : H.species.meat_type
|
||||
@@ -209,7 +204,8 @@
|
||||
slab_nutrition *= 0.5
|
||||
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))
|
||||
if(istype(new_meat))
|
||||
new_meat.name = "[slab_name] [new_meat.name]"
|
||||
@@ -222,16 +218,25 @@
|
||||
src.occupant.ghostize()
|
||||
|
||||
spawn(gib_time)
|
||||
|
||||
operating = 0
|
||||
occupant.gib()
|
||||
occupant = null
|
||||
|
||||
playsound(src, 'sound/effects/splat.ogg', 50, 1)
|
||||
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)
|
||||
// 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))
|
||||
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)
|
||||
continue
|
||||
thing.forceMove(get_turf(thing)) // Drop it onto the turf for throwing.
|
||||
|
||||
@@ -137,6 +137,10 @@
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/S = O
|
||||
if (S.dried_type)
|
||||
return 1
|
||||
|
||||
if(istype(O, /obj/item/stack/wetleather))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/smartfridge/drying_rack/process()
|
||||
@@ -180,6 +184,17 @@
|
||||
new D(get_turf(src))
|
||||
qdel(S)
|
||||
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
|
||||
|
||||
/obj/machinery/smartfridge/process()
|
||||
|
||||
@@ -27,6 +27,11 @@
|
||||
reagent_mix = RECIPE_REAGENT_REPLACE //Simplify end product
|
||||
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
|
||||
//====================
|
||||
|
||||
@@ -97,3 +97,12 @@
|
||||
/obj/item/weapon/reagent_containers/food/snacks/steamrolltealeaf
|
||||
)
|
||||
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
|
||||
23
code/modules/food/recipes_oven_ch.dm
Normal file
23
code/modules/food/recipes_oven_ch.dm
Normal 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
|
||||
@@ -201,3 +201,22 @@
|
||||
set_trait(TRAIT_IDEAL_HEAT, 283)
|
||||
set_trait(TRAIT_NUTRIENT_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")
|
||||
@@ -2,5 +2,9 @@
|
||||
/obj/item/seeds/teaseed
|
||||
seed_type = "tea"
|
||||
|
||||
|
||||
/obj/item/seeds/cinnamon
|
||||
seed_type = "cinnamon"
|
||||
|
||||
/obj/item/seeds/pitcherseed
|
||||
seed_type = "pitcher plant"
|
||||
@@ -77,12 +77,16 @@
|
||||
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(assembly)
|
||||
assembly.set_light(l_range = light_brightness, l_power = light_brightness, l_color = light_rgb)
|
||||
light_source.set_light(l_range = light_brightness, l_power = light_brightness, l_color = light_rgb)
|
||||
else
|
||||
if(assembly)
|
||||
assembly.set_light(0)
|
||||
light_source.set_light(0)
|
||||
//CHOMPEdit End
|
||||
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.
|
||||
|
||||
@@ -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 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("Feeder", /obj/machinery/feeder, 4, time = 20, one_per_turf = 1, on_floor = 1) //CHOMP Addition
|
||||
|
||||
/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] 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)
|
||||
|
||||
/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)
|
||||
|
||||
@@ -444,7 +444,18 @@
|
||||
name = "leather"
|
||||
desc = "The by-product of mob grinding."
|
||||
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
|
||||
pass_color = TRUE
|
||||
strict_color_stacking = TRUE
|
||||
|
||||
@@ -922,7 +922,7 @@ var/list/name_to_material
|
||||
sheet_singular_name = null
|
||||
sheet_plural_name = "pile"
|
||||
pass_stack_colors = TRUE
|
||||
supply_conversion_value = 3 //YW Adds: logs worth points
|
||||
supply_conversion_value = 1
|
||||
|
||||
/datum/material/wood/log/sif
|
||||
name = MAT_SIFLOG
|
||||
@@ -1008,6 +1008,7 @@ var/list/name_to_material
|
||||
flags = MATERIAL_PADDING
|
||||
conductive = 0
|
||||
pass_stack_colors = TRUE
|
||||
supply_conversion_value = 2
|
||||
|
||||
/datum/material/cult
|
||||
name = "cult"
|
||||
@@ -1033,16 +1034,32 @@ var/list/name_to_material
|
||||
/datum/material/cult/reinf/place_dismantled_product(var/turf/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:
|
||||
/datum/material/leather
|
||||
name = "leather"
|
||||
name = MAT_LEATHER
|
||||
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
|
||||
ignition_point = T0C+300
|
||||
melting_point = T0C+300
|
||||
protectiveness = 3 // 13%
|
||||
conductive = 0
|
||||
supply_conversion_value = 3
|
||||
|
||||
//CHOMPstation Removal Start: Moved to materials_ch and changed to allow for material var
|
||||
/*
|
||||
|
||||
66
code/modules/mob/living/butchering.dm
Normal file
66
code/modules/mob/living/butchering.dm
Normal 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()
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/living/carbon/
|
||||
/mob/living/carbon
|
||||
gender = MALE
|
||||
var/datum/species/species //Contains icon generation and language information, set during New().
|
||||
var/list/stomach_contents = list()
|
||||
|
||||
@@ -283,3 +283,11 @@
|
||||
message = "hides their wings."
|
||||
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
|
||||
|
||||
@@ -68,6 +68,8 @@
|
||||
/mob/living/carbon/human/proc/examine_nutrition()
|
||||
if(!show_pudge()) //Some clothing or equipment can hide this.
|
||||
return ""
|
||||
if(nutrition_hidden) // Chomp Edit
|
||||
return ""
|
||||
var/message = ""
|
||||
var/nutrition_examine = round(nutrition)
|
||||
var/t_He = "It" //capitalised for use at the start of each line.
|
||||
|
||||
@@ -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)
|
||||
// VOREStation Edit - Begin
|
||||
if(nif && nif.flag_check(NIF_C_HARDCLAWS,NIF_FLAGS_COMBAT)){return unarmed_hardclaws}
|
||||
@@ -16,6 +19,12 @@
|
||||
if(soft_type)
|
||||
return soft_type
|
||||
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)
|
||||
if(u_attack.is_usable(src, target, hit_zone))
|
||||
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]!")
|
||||
|
||||
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
|
||||
|
||||
@@ -439,13 +439,14 @@ This function restores all organs.
|
||||
return 0
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
/mob/living/carbon/human/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/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)
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
var/age = 30 //Player's age (pure fluff)
|
||||
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_metadata = list()
|
||||
@@ -85,7 +85,6 @@
|
||||
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/list/bad_external_organs = list()// organs we check until they are good.
|
||||
|
||||
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.
|
||||
|
||||
inventory_panel_type = /datum/inventory_panel/human
|
||||
butchery_loot = list(/obj/item/stack/animalhide/human = 1)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
var/ability_flags = 0 //Shadekin abilities/potentially other species-based?
|
||||
var/sensorpref = 5 //Suit sensor loadout pref
|
||||
var/wings_hidden = FALSE
|
||||
var/nutrition_hidden = FALSE // Chomp Edit
|
||||
|
||||
/mob/living/carbon/human/proc/shadekin_get_energy()
|
||||
var/datum/species/shadekin/SK = species
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
update_icons_body() //Body handles eyes
|
||||
update_eyes() //For floating eyes only
|
||||
|
||||
/*
|
||||
/mob/living/carbon/var/list/internal_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
|
||||
@@ -13,6 +14,7 @@
|
||||
/mob/living/carbon/human/proc/get_bodypart_name(var/zone)
|
||||
var/obj/item/organ/external/E = get_organ(zone)
|
||||
if(E) . = E.name
|
||||
*/
|
||||
|
||||
/mob/living/carbon/human/proc/recheck_bad_external_organs()
|
||||
var/damage_this_tick = getToxLoss()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/datum/unarmed_attack/bite/sharp //eye teeth
|
||||
attack_name = "sharp bite"
|
||||
attack_verb = list("bit", "chomped on")
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
shredding = 0
|
||||
@@ -6,12 +7,14 @@
|
||||
edge = 1
|
||||
|
||||
/datum/unarmed_attack/diona
|
||||
attack_name = "tendrils"
|
||||
attack_verb = list("lashed", "bludgeoned")
|
||||
attack_noun = list("tendril")
|
||||
eye_attack_text = "a tendril"
|
||||
eye_attack_text_victim = "a tendril"
|
||||
|
||||
/datum/unarmed_attack/claws
|
||||
attack_name = "claws"
|
||||
attack_verb = list("scratched", "clawed", "slashed")
|
||||
attack_noun = list("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>")
|
||||
|
||||
/datum/unarmed_attack/claws/strong
|
||||
attack_name = "strong claws"
|
||||
attack_verb = list("slashed")
|
||||
damage = 5
|
||||
shredding = 1
|
||||
@@ -67,6 +71,7 @@
|
||||
damage = 15
|
||||
|
||||
/datum/unarmed_attack/bite/strong
|
||||
attack_name = "strong bite"
|
||||
attack_verb = list("mauled")
|
||||
damage = 8
|
||||
shredding = 1
|
||||
@@ -75,6 +80,7 @@
|
||||
damage = 10
|
||||
|
||||
/datum/unarmed_attack/slime_glomp
|
||||
attack_name = "glomp"
|
||||
attack_verb = list("glomped")
|
||||
attack_noun = list("body")
|
||||
damage = 2
|
||||
@@ -84,6 +90,7 @@
|
||||
user.apply_stored_shock_to(target)
|
||||
|
||||
/datum/unarmed_attack/stomp/weak
|
||||
attack_name = "weak stomp"
|
||||
attack_verb = list("jumped on")
|
||||
|
||||
/datum/unarmed_attack/stomp/weak/get_unarmed_damage()
|
||||
|
||||
@@ -142,8 +142,8 @@
|
||||
)
|
||||
|
||||
unarmed_types = list(
|
||||
/datum/unarmed_attack/bite/sharp,
|
||||
/datum/unarmed_attack/claws,
|
||||
/datum/unarmed_attack/bite/sharp,
|
||||
/datum/unarmed_attack/stomp/weak
|
||||
)
|
||||
|
||||
|
||||
@@ -30,11 +30,10 @@
|
||||
excludes = list(/datum/trait/lonely)
|
||||
|
||||
/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))
|
||||
return 0
|
||||
if(M == H || M.stat == DEAD || M.invisibility > H.see_invisible)
|
||||
return 0
|
||||
if(only_people && !M.ckey)
|
||||
var/social_check = only_people && !istype(M, /mob/living/carbon) && !istype(M, /mob/living/silicon/robot)
|
||||
var/self_dead_invisible_check = M == H || M.stat == DEAD || M.invisibility > H.see_invisible
|
||||
var/ckey_check = only_people && !M.ckey
|
||||
if(social_check || self_dead_invisible_check || ckey_check)
|
||||
return 0
|
||||
if(M.faction == "neutral" || M.faction == H.faction)
|
||||
if(H.loneliness_stage > 0)
|
||||
@@ -71,9 +70,13 @@
|
||||
H.loneliness_stage -= 4
|
||||
return
|
||||
// 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))
|
||||
return
|
||||
//Check to see if there's anyone in our belly
|
||||
if(H.vore_organs)
|
||||
for(var/obj/belly/B in H.vore_organs)
|
||||
for(var/mob/living/content in B.contents)
|
||||
|
||||
@@ -34,4 +34,4 @@
|
||||
desc = "Your body is able to produce nutrition from being in light."
|
||||
cost = 3
|
||||
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.
|
||||
|
||||
@@ -2,6 +2,7 @@ var/global/list/sparring_attack_cache = list()
|
||||
|
||||
//Species unarmed attacks
|
||||
/datum/unarmed_attack
|
||||
var/attack_name = "fist"
|
||||
var/attack_verb = list("attack") // Empty hand hurt intent verb.
|
||||
var/attack_noun = list("fist")
|
||||
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
|
||||
|
||||
/datum/unarmed_attack/bite
|
||||
attack_name = "bite"
|
||||
attack_verb = list("bit")
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
shredding = 0
|
||||
@@ -127,6 +129,7 @@ var/global/list/sparring_attack_cache = list()
|
||||
return TRUE
|
||||
|
||||
/datum/unarmed_attack/punch
|
||||
attack_name = "punch"
|
||||
attack_verb = list("punched")
|
||||
attack_noun = list("fist")
|
||||
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?
|
||||
|
||||
/datum/unarmed_attack/kick
|
||||
attack_name = "kick"
|
||||
attack_verb = list("kicked", "kicked", "kicked", "kneed")
|
||||
attack_noun = list("kick", "kick", "kick", "knee strike")
|
||||
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>")
|
||||
|
||||
/datum/unarmed_attack/stomp
|
||||
attack_name = "stomp"
|
||||
attack_verb = null
|
||||
attack_noun = list("stomp")
|
||||
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/
|
||||
|
||||
/datum/unarmed_attack/light_strike
|
||||
attack_name = "light hit"
|
||||
attack_noun = list("tap","light strike")
|
||||
attack_verb = list("tapped", "lightly struck")
|
||||
damage = 3
|
||||
|
||||
@@ -31,9 +31,25 @@
|
||||
nest = null
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob(src, TRUE)
|
||||
|
||||
qdel(selected_image)
|
||||
QDEL_NULL(vorePanel) //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 ..()
|
||||
|
||||
//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)
|
||||
. = ..()
|
||||
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.
|
||||
var/pull_dir = get_dir(src, pulling)
|
||||
|
||||
28
code/modules/mob/living/organs.dm
Normal file
28
code/modules/mob/living/organs.dm
Normal 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)
|
||||
|
||||
..()
|
||||
@@ -145,6 +145,7 @@
|
||||
name = "MediHound hypospray"
|
||||
desc = "An advanced chemical synthesizer and injection system utilizing carrier's reserves, designed for heavy-duty medical equipment."
|
||||
charge_cost = 10
|
||||
reagent_ids = list("inaprovaline", "dexalin", "bicaridine", "kelotane", "anti_toxin", "spaceacillin", "paracetamol")
|
||||
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.
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
var/datum/matter_synth/water = null
|
||||
var/digest_brute = 2
|
||||
var/digest_burn = 3
|
||||
var/digest_multiplier = 1
|
||||
var/recycles = FALSE
|
||||
var/medsensor = TRUE //Does belly sprite come with patient ok/dead light?
|
||||
|
||||
@@ -541,8 +542,8 @@
|
||||
else
|
||||
var/old_brute = T.getBruteLoss()
|
||||
var/old_burn = T.getFireLoss()
|
||||
T.adjustBruteLoss(digest_brute)
|
||||
T.adjustFireLoss(digest_burn)
|
||||
T.adjustBruteLoss(digest_brute * digest_multiplier)
|
||||
T.adjustFireLoss(digest_burn * digest_multiplier)
|
||||
var/actual_brute = T.getBruteLoss() - old_brute
|
||||
var/actual_burn = T.getFireLoss() - old_burn
|
||||
var/damage_gain = actual_brute + actual_burn
|
||||
@@ -717,6 +718,7 @@
|
||||
icon_state = "sleeperc"
|
||||
injection_chems = list("glucose","inaprovaline","tricordrazine")
|
||||
max_item_count = 1
|
||||
|
||||
/obj/item/device/dogborg/sleeper/command //Command borg belly // CH addition
|
||||
name = "Bluespace Filing Belly"
|
||||
desc = "A mounted bluespace storage unit for carrying paperwork"
|
||||
|
||||
@@ -71,6 +71,5 @@
|
||||
/mob/living/simple_mob/proc/remove_eyes()
|
||||
cut_overlay(eye_layer)
|
||||
|
||||
|
||||
/mob/living/simple_mob/gib()
|
||||
..(icon_gib,1,icon) // we need to specify where the gib animation is stored
|
||||
8
code/modules/mob/living/simple_mob/butchering.dm
Normal file
8
code/modules/mob/living/simple_mob/butchering.dm
Normal 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
|
||||
@@ -68,9 +68,9 @@
|
||||
else
|
||||
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
|
||||
if(meat_type && (stat == DEAD)) //if the animal has a meat, and if it is dead.
|
||||
if(istype(O, /obj/item/weapon/material/knife))
|
||||
harvest(user)
|
||||
if(can_butcher(user, O)) //if the animal can be butchered, do so and return. It's likely to be gibbed.
|
||||
harvest(user, O)
|
||||
return
|
||||
|
||||
if(user.a_intent == I_HELP && harvest_tool && istype(O, harvest_tool) && stat != DEAD)
|
||||
if(world.time > (harvest_recent + harvest_cooldown))
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
/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>"
|
||||
var/time_to_harvest = (harvest_recent + harvest_cooldown) - world.time
|
||||
if(time_to_harvest > 0)
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
handle_special()
|
||||
|
||||
handle_guts()
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -137,6 +139,12 @@
|
||||
else
|
||||
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()
|
||||
if(purge)
|
||||
|
||||
@@ -57,8 +57,6 @@
|
||||
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/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/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
|
||||
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()
|
||||
verbs -= /mob/verb/observe
|
||||
@@ -170,8 +172,31 @@
|
||||
|
||||
if(has_eye_glow)
|
||||
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()
|
||||
default_language = null
|
||||
@@ -190,7 +215,6 @@
|
||||
update_icon()
|
||||
..()
|
||||
|
||||
|
||||
//Client attached
|
||||
/mob/living/simple_mob/Login()
|
||||
. = ..()
|
||||
@@ -269,27 +293,6 @@
|
||||
/mob/living/simple_mob/get_speech_ending(verb, var/ending)
|
||||
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()
|
||||
return mob_class & MOB_CLASS_HUMANOID|MOB_CLASS_ANIMAL|MOB_CLASS_SLIME // Update this if needed.
|
||||
|
||||
|
||||
@@ -7,3 +7,16 @@
|
||||
response_harm = "hits"
|
||||
|
||||
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\
|
||||
)
|
||||
|
||||
@@ -110,6 +110,10 @@
|
||||
var/poison_chance = 10 // Chance for injection to occur.
|
||||
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)
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
|
||||
301
code/modules/mob/living/zbullet_act_ch.dm
Normal file
301
code/modules/mob/living/zbullet_act_ch.dm
Normal 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) )
|
||||
|
||||
236
code/modules/mob/living/zzballistic_test_ch.dm
Normal file
236
code/modules/mob/living/zzballistic_test_ch.dm
Normal 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)
|
||||
@@ -1022,6 +1022,40 @@ mob/proc/yank_out_object()
|
||||
set hidden = 1
|
||||
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()
|
||||
return
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
var/resting = 0 //Carbon
|
||||
var/lying = 0
|
||||
var/lying_prev = 0
|
||||
var/is_shifted = FALSE // VoreStation Edit; pixel shifting
|
||||
var/canmove = 1
|
||||
//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.
|
||||
|
||||
@@ -1184,17 +1184,6 @@
|
||||
bee_stripes
|
||||
name = "bee stripes"
|
||||
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)
|
||||
|
||||
vas_toes
|
||||
@@ -1269,4 +1258,4 @@
|
||||
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)
|
||||
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)
|
||||
|
||||
@@ -100,6 +100,8 @@
|
||||
|
||||
/datum/nifsoft/medichines_syn/life()
|
||||
if((. = ..()))
|
||||
var/mob/living/carbon/human/H = nif.human // Chomp Edit
|
||||
var/HP_percent = H.health/H.getMaxHealth() // Chomp Edit
|
||||
//We're good!
|
||||
if(!nif.human.bad_external_organs.len)
|
||||
if(mode || active)
|
||||
@@ -117,7 +119,7 @@
|
||||
var/obj/item/organ/external/EO = eo
|
||||
for(var/w in EO.wounds)
|
||||
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)
|
||||
EO.update_damages()
|
||||
if(EO.update_icon())
|
||||
@@ -127,6 +129,17 @@
|
||||
else if(mode == 1)
|
||||
mode = 2
|
||||
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
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
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.
|
||||
|
||||
butcherable = FALSE
|
||||
|
||||
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/target_slot = null
|
||||
|
||||
@@ -83,7 +83,10 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain)
|
||||
health = config.default_brain_health
|
||||
defib_timer = (config.defib_timer MINUTES) / 2
|
||||
spawn(5)
|
||||
if(brainmob && brainmob.client)
|
||||
if(brainmob)
|
||||
butcherable = FALSE
|
||||
|
||||
if(brainmob.client)
|
||||
brainmob.client.screen.len = null //clear the hud
|
||||
|
||||
/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.name = H.real_name
|
||||
brainmob.real_name = H.real_name
|
||||
|
||||
if(istype(H))
|
||||
brainmob.dna = H.dna.Clone()
|
||||
brainmob.timeofhostdeath = H.timeofdeath
|
||||
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))
|
||||
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)
|
||||
borer.detatch() //Should remove borer if the brain is removed - RR
|
||||
|
||||
var/obj/item/organ/internal/brain/B = src
|
||||
if(istype(B) && istype(owner))
|
||||
if(istype(B) && owner)
|
||||
B.transfer_identity(owner)
|
||||
|
||||
..()
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
/obj/item/organ/internal/liver/process()
|
||||
..()
|
||||
if(!owner) return
|
||||
if(!iscarbon(owner)) return
|
||||
|
||||
if(owner.life_tick % PROCESS_ACCURACY == 0)
|
||||
|
||||
|
||||
@@ -9,3 +9,4 @@
|
||||
decays = FALSE // Ditto. Rust takes a while.
|
||||
|
||||
robotic = ORGAN_ROBOT
|
||||
butcherable = FALSE
|
||||
|
||||
@@ -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/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()
|
||||
|
||||
handle_organ_mod_special(TRUE)
|
||||
@@ -59,21 +62,42 @@ var/list/organ_cache = list()
|
||||
/obj/item/organ/proc/update_health()
|
||||
return
|
||||
|
||||
/obj/item/organ/New(var/mob/living/carbon/holder, var/internal)
|
||||
/obj/item/organ/New(var/mob/living/holder, var/internal)
|
||||
..(holder)
|
||||
create_reagents(5)
|
||||
if(!max_damage)
|
||||
max_damage = min_broken_damage * 2
|
||||
if(istype(holder))
|
||||
|
||||
if(isliving(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.
|
||||
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]
|
||||
if(holder.dna)
|
||||
dna = holder.dna.Clone()
|
||||
species = holder.species //VOREStation Edit - For custom species
|
||||
dna = C.dna.Clone()
|
||||
species = C.species //VOREStation Edit - For custom species
|
||||
else
|
||||
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(internal)
|
||||
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)
|
||||
E.internal_organs = list()
|
||||
E.internal_organs |= src
|
||||
H.internal_organs_by_name[organ_tag] = src
|
||||
if(dna)
|
||||
if(!blood_DNA)
|
||||
blood_DNA = list()
|
||||
blood_DNA[dna.unique_enzymes] = dna.b_type
|
||||
if(internal)
|
||||
holder.internal_organs |= src
|
||||
else
|
||||
species = GLOB.all_species["Human"]
|
||||
|
||||
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)
|
||||
if(new_dna)
|
||||
dna = new_dna.Clone()
|
||||
@@ -134,7 +172,7 @@ var/list/organ_cache = list()
|
||||
handle_organ_proc_special()
|
||||
|
||||
//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
|
||||
return
|
||||
|
||||
@@ -152,7 +190,7 @@ var/list/organ_cache = list()
|
||||
if(germ_level >= INFECTION_LEVEL_THREE)
|
||||
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()
|
||||
handle_rejection()
|
||||
@@ -170,7 +208,7 @@ var/list/organ_cache = list()
|
||||
germ_level = 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
|
||||
|
||||
@@ -203,10 +241,12 @@ var/list/organ_cache = list()
|
||||
|
||||
//Level 1 qualifies for specific organ processing effects
|
||||
if(germ_level >= INFECTION_LEVEL_ONE)
|
||||
. = 1
|
||||
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
|
||||
. = 1 //Organ qualifies for effect-specific processing
|
||||
//var/fever_temperature = (owner.species.heat_level_1 - owner.species.body_temperature - 5)* min(germ_level/INFECTION_LEVEL_TWO, 1) + owner.species.body_temperature
|
||||
//owner.bodytemperature += between(0, (fever_temperature - T20C)/BODYTEMP_COLD_DIVISOR + 1, fever_temperature - owner.bodytemperature)
|
||||
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
|
||||
if (germ_level >= INFECTION_LEVEL_TWO)
|
||||
@@ -269,6 +309,7 @@ var/list/organ_cache = list()
|
||||
|
||||
//Germs
|
||||
/obj/item/organ/proc/handle_antibiotics()
|
||||
if(istype(owner))
|
||||
var/antibiotics = owner.chem_effects[CE_ANTIBIOTIC] || 0
|
||||
|
||||
if (!germ_level || antibiotics < ANTIBIO_NORM)
|
||||
@@ -304,7 +345,7 @@ var/list/organ_cache = list()
|
||||
|
||||
//only show this if the organ is not robotic
|
||||
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)
|
||||
owner.custom_pain("Something inside your [parent.name] hurts a lot.", amount)
|
||||
|
||||
@@ -322,6 +363,7 @@ var/list/organ_cache = list()
|
||||
robotic = ORGAN_ASSISTED
|
||||
min_bruised_damage = 15
|
||||
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.
|
||||
robotize()
|
||||
@@ -341,10 +383,7 @@ var/list/organ_cache = list()
|
||||
take_damage(rand(1,3))
|
||||
|
||||
/obj/item/organ/proc/removed(var/mob/living/user)
|
||||
|
||||
if(!istype(owner))
|
||||
return
|
||||
|
||||
if(owner)
|
||||
owner.internal_organs_by_name[organ_tag] = null
|
||||
owner.internal_organs_by_name -= organ_tag
|
||||
owner.internal_organs_by_name -= null
|
||||
@@ -356,6 +395,8 @@ var/list/organ_cache = list()
|
||||
forceMove(owner.drop_location())
|
||||
START_PROCESSING(SSobj, src)
|
||||
rejecting = null
|
||||
|
||||
if(istype(owner))
|
||||
var/datum/reagent/blood/organ_blood = locate(/datum/reagent/blood) in reagents.reagent_list
|
||||
if(!organ_blood || !organ_blood.data["blood_DNA"])
|
||||
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
|
||||
transplant_data = list()
|
||||
if(!transplant_blood)
|
||||
transplant_data["species"] = target.species.name
|
||||
transplant_data["blood_type"] = target.dna.b_type
|
||||
transplant_data["blood_DNA"] = target.dna.unique_enzymes
|
||||
transplant_data["species"] = target?.species.name
|
||||
transplant_data["blood_type"] = target?.dna.b_type
|
||||
transplant_data["blood_DNA"] = target?.dna.unique_enzymes
|
||||
else
|
||||
transplant_data["species"] = transplant_blood.data["species"]
|
||||
transplant_data["blood_type"] = transplant_blood.data["blood_type"]
|
||||
transplant_data["blood_DNA"] = transplant_blood.data["blood_DNA"]
|
||||
transplant_data["species"] = transplant_blood?.data["species"]
|
||||
transplant_data["blood_type"] = transplant_blood?.data["blood_type"]
|
||||
transplant_data["blood_DNA"] = transplant_blood?.data["blood_DNA"]
|
||||
|
||||
owner = target
|
||||
loc = owner
|
||||
@@ -428,6 +469,46 @@ var/list/organ_cache = list()
|
||||
bitten(user)
|
||||
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()
|
||||
if(species.flags & NO_PAIN)
|
||||
return 0
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
var/body_part = null // Part flag
|
||||
var/icon_position = 0 // Used in mob overlay layering calculations.
|
||||
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/gendered_icon = 0 // Whether or not the icon state appends a gender.
|
||||
var/s_tone // Skin tone.
|
||||
@@ -97,7 +98,7 @@
|
||||
qdel(splinted)
|
||||
splinted = null
|
||||
|
||||
if(owner)
|
||||
if(istype(owner))
|
||||
owner.organs -= src
|
||||
owner.organs_by_name[organ_tag] = null
|
||||
owner.organs_by_name -= organ_tag
|
||||
@@ -199,7 +200,7 @@
|
||||
return
|
||||
|
||||
dislocated = 1
|
||||
if(owner)
|
||||
if(istype(owner))
|
||||
owner.verbs |= /mob/living/carbon/human/proc/relocate
|
||||
|
||||
/obj/item/organ/external/proc/relocate()
|
||||
@@ -207,7 +208,7 @@
|
||||
return
|
||||
|
||||
dislocated = 0
|
||||
if(owner)
|
||||
if(istype(owner))
|
||||
owner.shock_stage += 20
|
||||
|
||||
//check to see if we still need the verb
|
||||
@@ -221,7 +222,7 @@
|
||||
|
||||
/obj/item/organ/external/New(var/mob/living/carbon/holder)
|
||||
..(holder, 0)
|
||||
if(owner)
|
||||
if(istype(owner))
|
||||
replaced(owner)
|
||||
sync_colour_to_human(owner)
|
||||
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/obj/item/organ/external/parent_organ = parent
|
||||
|
||||
var/use_flesh_colour = species.get_flesh_colour(owner)
|
||||
var/use_blood_colour = species.get_blood_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) ? species.get_blood_colour(owner) : "#C80000"
|
||||
|
||||
removed(null, ignore_children)
|
||||
victim.traumatic_shock += 60
|
||||
victim?.traumatic_shock += 60
|
||||
|
||||
if(parent_organ)
|
||||
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()
|
||||
|
||||
spawn(1)
|
||||
if(istype(victim))
|
||||
victim.updatehealth()
|
||||
victim.UpdateDamageIcon()
|
||||
victim.update_icons_body()
|
||||
else
|
||||
victim.update_icons()
|
||||
dir = 2
|
||||
|
||||
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
|
||||
|
||||
// Remove parent references
|
||||
parent.children -= src
|
||||
parent?.children -= src
|
||||
parent = null
|
||||
|
||||
release_restraints(victim)
|
||||
|
||||
@@ -58,7 +58,7 @@ var/global/list/limb_icon_cache = list()
|
||||
cut_overlays()
|
||||
|
||||
//Every 'addon' below requires information from species
|
||||
if(!owner || !owner.species)
|
||||
if(!iscarbon(owner) || !owner.species)
|
||||
return
|
||||
|
||||
//Eye color/icon
|
||||
@@ -135,7 +135,10 @@ var/global/list/limb_icon_cache = list()
|
||||
if(owner && owner.gender == FEMALE)
|
||||
gender = "f"
|
||||
|
||||
if(!force_icon_key)
|
||||
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)
|
||||
mob_icon = new /icon(force_icon, "[icon_name][gendered_icon ? "_[gender]" : ""]")
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
var/brain_type = /obj/item/device/mmi
|
||||
var/obj/item/device/mmi/stored_mmi
|
||||
robotic = ORGAN_ASSISTED
|
||||
butcherable = FALSE
|
||||
|
||||
/obj/item/organ/internal/mmi_holder/Destroy()
|
||||
if(stored_mmi && (stored_mmi.loc == src))
|
||||
|
||||
@@ -282,6 +282,7 @@
|
||||
|
||||
/obj/item/organ/external/head/removed()
|
||||
if(owner)
|
||||
if(iscarbon(owner))
|
||||
name = "[owner.real_name]'s head"
|
||||
owner.drop_from_inventory(owner.glasses)
|
||||
owner.drop_from_inventory(owner.head)
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
|
||||
var/can_hold_val = 0
|
||||
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 ++
|
||||
mat_storage += SHEET_MATERIAL_AMOUNT
|
||||
playsound(src, 'sound/effects/phasein.ogg', 15, 1)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user