Experimental Cobbisection [150+ Hours and Ready] (#44821)

About The Pull Request & Why
Dissection (Prev Experimental Dissection) Is Now Roundstart

Goal:give medbay a task they can do outside of normal healing on the off chance they're overstaffed and/or are in need of work.
Dissection (Prev Experimental Dissection) Is Now Tiered

Goal: I'm still not seeing competition in the medical tree that I'd like to see. Now that science benefits from going to this tree, I expect it to be a prominent if not the main pick.

Goal: Provide Medical bargaining power with Science. Want you cool gear bros? Better indulge us a bit if you want us to farm corpses.

NOTE: You will NOT be punished for doing low tiered surgeries then unlocking further tiers. It adjusts your rewards depending on if the body has been experimented on before and gives you the difference, it will not block you from doing the surgery entirely.
Repeatability

Goal: Make it less balanced around the all/nothing mechanic and more with rewarding constantly running the surgery.

Failing the surgery will give you a pity amount (1%, something slightly more than none in grand scheme) but more importantly will NOT add the trait that disables you from using that body for the surgery again.
Silicons can now perform dissection

Since It's not All/Nothing I decided to allow silicons to be able to help out. This is the first (and only) surgery that they can potentially fail.
Nerfs (yikes!)

Needed to nerf it to compensate for the fact that it was now roundstart. The hardest one was pointgain. I decided to mega nerf it so tiered would be desired. This was also a result in the shift of balance off the RNG and more on the repeatability.
Dissection Can Now Be Performed on ANY LIVING MOB

Goal: Cooperation between Mining (returning Mobs) and Medbay (turning these mobs into points)

The foundation is really lacking imo since I didn't want to dance around with numbers in this PR. Currently all mobs that aren't human and aren't explicitly listed in check_value are 300 points per surgery.

I hope you guys can add more mobs to the pool with better rewards (imagine dissecting the dragon for science!)
Dissection Surgery Minor Edits
Step Configuration Edit

Needed to change just for repeatability in the dissect step (didn't like the end step being the proceeding step).

I replaced the incision step with a post-dissection clamp step to keep the theme of scalpel > hemo (dissection uses scalpel)
Implement Changes / Probability Effects

Rewards using the researched tools (further integrates medsci coop), lowers standard gear to appropriately balance higher tiers.
MISC
Prices are Define Bound

Everything is relative to a single number via calculating off a define instead of independent values. Balance discussion shifts from "Is X number fair" to a more tangible "Is this mob worth X times the amount of a normal human". If everything is strong/low we can just edit a single number!
Let me know if there's any undoc'd changes!
Changelog

cl Cobby x Medbay
balance: (Experimental) Dissection is now roundstart.
balance: (Experimental) Dissection is now tiered and give higher point outputs than their predecessors.
add: All living mobs with corpses can be dissected.
code: Attention, all ss13 gamers! I need YOUR help adding mobs to the pool so they don't get the lame 60% of normal human pricing! You can dissect DRAGONS FOR CRY IT OUT LOUD!
balance: You are NOT punished for doing the lower tier surgeries then unlocking higher ones!
add: Borgs can perform dissection but they are not 100% successful.
tweak: Shifts balance of dissection surgery towards spammability vs. rng mechanic.
balance: All point rewards are severely nerfed to promote doing this multiple times (since it's now available from the getgo).
tweak: If you fail the dissection step, you get a pity reward (1% credits) and can repeat the step until you successfully dissect the being.
tweak: Lowered probabilty of success on default tools, increased probability for researched tools.
tweak: removed 2nd incision step, added clamp step post dissection (repeatability purposes).
/cl
This commit is contained in:
moo
2019-07-08 19:57:26 -04:00
committed by Linzolle
parent 129e3a9fc9
commit f61e598dbc
5 changed files with 282 additions and 44 deletions
@@ -725,12 +725,22 @@
var/surgery
/datum/design/surgery/experimental_dissection
name = "Experimental Dissection"
desc = "A surgical procedure which deeply analyzes the biology of a corpse, and automatically adds new findings to the research database."
id = "surgery_exp_dissection"
surgery = /datum/surgery/experimental_dissection
name = "Advanced Dissection"
desc = "A surgical procedure which analyzes the biology of a corpse, and automatically adds new findings to the research database."
id = "surgery_adv_dissection"
surgery = /datum/surgery/advanced/experimental_dissection/adv
research_icon_state = "surgery_chest"
/datum/design/surgery/experimental_dissection/exp
name = "Experimental Dissection"
id = "surgery_exp_dissection"
surgery = /datum/surgery/advanced/experimental_dissection/exp
/datum/design/surgery/experimental_dissection/exp
name = "Extraterrestrial Dissection"
id = "surgery_ext_dissection"
surgery = /datum/surgery/advanced/experimental_dissection/alien
/datum/design/surgery/lobotomy
name = "Lobotomy"
desc = "An invasive surgical procedure which guarantees removal of almost all brain traumas, but might cause another permanent trauma in return."
+3 -3
View File
@@ -115,7 +115,7 @@
display_name = "Advanced Surgery"
description = "When simple medicine doesn't cut it."
prereq_ids = list("adv_biotech")
design_ids = list("surgery_lobotomy", "surgery_reconstruction", "surgery_toxinhealing", "organbox")
design_ids = list("surgery_lobotomy", "surgery_reconstruction", "surgery_toxinhealing", "organbox", "surgery_adv_dissection")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -124,7 +124,7 @@
display_name = "Experimental Surgery"
description = "When evolution isn't fast enough."
prereq_ids = list("adv_surgery")
design_ids = list("surgery_revival","surgery_pacify","surgery_vein_thread","surgery_nerve_splice","surgery_nerve_ground","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_viral_bond")
design_ids = list("surgery_revival","surgery_pacify","surgery_vein_thread","surgery_nerve_splice","surgery_nerve_ground","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_viral_bond", "surgery_exp_dissection")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
export_price = 5000
@@ -133,7 +133,7 @@
display_name = "Alien Surgery"
description = "Abductors did nothing wrong."
prereq_ids = list("exp_surgery", "alientech")
design_ids = list("surgery_brainwashing","surgery_zombie")
design_ids = list("surgery_brainwashing","surgery_zombie", "surgery_ext_dissection")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000)
export_price = 5000
+76 -29
View File
@@ -1,61 +1,87 @@
/datum/surgery/experimental_dissection
name = "Experimental Dissection"
desc = "A surgical procedure which deeply analyzes the biology of a corpse, and automatically adds new findings to the research database."
#define BASE_HUMAN_REWARD 500
#define EXPDIS_FAIL_MSG "<span class='notice'>You dissect [target], but do not find anything particularly interesting.</span>"
/datum/surgery/advanced/experimental_dissection
name = "Dissection"
desc = "A surgical procedure which analyzes the biology of a corpse, and automatically adds new findings to the research database."
steps = list(/datum/surgery_step/incise,
/datum/surgery_step/retract_skin,
/datum/surgery_step/clamp_bleeders,
/datum/surgery_step/incise,
/datum/surgery_step/dissection,
/datum/surgery_step/clamp_bleeders,
/datum/surgery_step/close)
possible_locs = list(BODY_ZONE_CHEST)
target_mobtypes = list(/mob/living/carbon) //Feel free to dissect devils but they're magic.
target_mobtypes = list(/mob/living) //Feel free to dissect devils but they're magic.
replaced_by = /datum/surgery/advanced/experimental_dissection/adv
requires_tech = FALSE
var/value_multiplier = 1
/datum/surgery/experimental_dissection/can_start(mob/user, mob/living/carbon/target)
/datum/surgery/advanced/experimental_dissection/can_start(mob/user, mob/living/target)
. = ..()
if(HAS_TRAIT(target, TRAIT_DISSECTED))
if(HAS_TRAIT_FROM(target, TRAIT_DISSECTED,"[name]"))
return FALSE
if(iscyborg(user))
return FALSE //robots cannot be creative
//(also this surgery shouldn't be consistently successful, and cyborgs have a 100% success rate on surgery)
if(target.stat != DEAD)
return FALSE
/datum/surgery_step/dissection
name = "dissection"
implements = list(/obj/item/scalpel = 60, /obj/item/kitchen/knife = 30, /obj/item/shard = 15)
implements = list(/obj/item/scalpel/augment = 75, /obj/item/scalpel/advanced = 60, /obj/item/scalpel = 45, /obj/item/kitchen/knife = 20, /obj/item/shard = 10)// special tools not only cut down time but also improve probability
time = 125
silicons_obey_prob = TRUE
repeatable = TRUE
/datum/surgery_step/dissection/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "<span class='notice'>You start dissecting [target].</span>",
"[user] starts dissecting [target].",
"[user] starts dissecting [target].")
/datum/surgery_step/dissection/proc/check_value(mob/living/carbon/target)
/datum/surgery_step/dissection/proc/check_value(mob/living/target, datum/surgery/advanced/experimental_dissection/ED)
var/cost = BASE_HUMAN_REWARD
var/multi_surgery_adjust = 0
//determine bonus applied
if(isalienroyal(target))
return 10000
cost = (BASE_HUMAN_REWARD*10)
else if(isalienadult(target))
return 5000
cost = (BASE_HUMAN_REWARD*5)
else if(ismonkey(target))
return 1000
cost = (BASE_HUMAN_REWARD*0.5)
else if(ishuman(target))
var/mob/living/carbon/human/H = target
if(H.dna && H.dna.species)
if(H?.dna?.species)
if(isabductor(H))
return 8000
if(isgolem(H) || iszombie(H))
return 4000
if(isjellyperson(H) || ispodperson(H))
return 3000
return 2000
cost = (BASE_HUMAN_REWARD*4)
else if(isgolem(H) || iszombie(H))
cost = (BASE_HUMAN_REWARD*3)
/*else if(isjellyperson(H) || ispodperson(H)) CITADEL CHANGE: jelly and pod being available roundstart shouldn't give additional points
cost = (BASE_HUMAN_REWARD*2)*/
else
cost = (BASE_HUMAN_REWARD * 0.6)
/datum/surgery_step/dissection/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "<span class='notice'>You dissect [target], and add your discoveries to the research database!</span>",
"[user] dissects [target], adding [user.p_their()] discoveries to the research database!",
//now we do math for surgeries already done (no double dipping!).
for(var/i in typesof(/datum/surgery/advanced/experimental_dissection))
var/datum/surgery/advanced/experimental_dissection/cringe = i
if(HAS_TRAIT_FROM(target,TRAIT_DISSECTED,"[initial(cringe.name)]"))
multi_surgery_adjust = max(multi_surgery_adjust,initial(cringe.value_multiplier)) - 1
multi_surgery_adjust *= cost
//multiply by multiplier in surgery
cost *= ED.value_multiplier
return (cost-multi_surgery_adjust)
/datum/surgery_step/dissection/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/points_earned = check_value(target, surgery)
display_results(user, target, "<span class='notice'>You dissect [target], and add your [points_earned] point\s worth of discoveries to the research database!</span>",
"[user] dissects [target], discovering [points_earned] point\s of data!",
"[user] dissects [target]!")
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = check_value(target)))
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points_earned))
var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST)
target.apply_damage(80, BRUTE, L)
ADD_TRAIT(target, TRAIT_DISSECTED, "surgery")
ADD_TRAIT(target, TRAIT_DISSECTED, "[surgery.name]")
repeatable = FALSE
return TRUE
/datum/surgery_step/dissection/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
@@ -63,7 +89,28 @@
"[user] dissects [target], however it seems [user.p_they()] didn't find anything useful.",
"[user] dissects [target], but looks a little dissapointed.")
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = (check_value(target) * 0.2)))
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = (round(check_value(target, surgery) * 0.01))))
var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST)
target.apply_damage(80, BRUTE, L)
ADD_TRAIT(target, TRAIT_DISSECTED, "surgery")
return TRUE
return TRUE
/datum/surgery/advanced/experimental_dissection/adv
name = "Thorough Dissection"
value_multiplier = 2
replaced_by = /datum/surgery/advanced/experimental_dissection/exp
requires_tech = TRUE
/datum/surgery/advanced/experimental_dissection/exp
name = "Experimental Dissection"
value_multiplier = 5
replaced_by = /datum/surgery/advanced/experimental_dissection/alien
requires_tech = TRUE
/datum/surgery/advanced/experimental_dissection/alien
name = "Extraterrestrial Dissection"
value_multiplier = 10
requires_tech = TRUE
#undef BASE_HUMAN_REWARD
#undef EXPDIS_FAIL_MSG
+177
View File
@@ -1,3 +1,4 @@
<<<<<<< HEAD
/datum/surgery
var/name = "surgery"
var/desc = "surgery description"
@@ -154,3 +155,179 @@
//RESOLVED ISSUES //"Todo" jobs that have been completed
//combine hands/feet into the arms - Hands/feet were removed - RR
//surgeries (not steps) that can be initiated on any body part (corresponding with damage locations) - Call this one done, see possible_locs var - c0
=======
/datum/surgery
var/name = "surgery"
var/desc = "surgery description"
var/status = 1
var/list/steps = list() //Steps in a surgery
var/step_in_progress = FALSE //Actively performing a Surgery
var/can_cancel = TRUE //Can cancel this surgery after step 1 with cautery
var/list/target_mobtypes = list(/mob/living/carbon/human) //Acceptable Species
var/location = BODY_ZONE_CHEST //Surgery location
var/requires_bodypart_type = BODYPART_ORGANIC //Prevents you from performing an operation on incorrect limbs. 0 for any limb type
var/list/possible_locs = list() //Multiple locations
var/ignore_clothes = FALSE //This surgery ignores clothes
var/mob/living/carbon/target //Operation target mob
var/obj/item/bodypart/operated_bodypart //Operable body part
var/requires_bodypart = TRUE //Surgery available only when a bodypart is present, or only when it is missing.
var/success_multiplier = 0 //Step success propability multiplier
var/requires_real_bodypart = FALSE //Some surgeries don't work on limbs that don't really exist
var/lying_required = TRUE //Does the vicitm needs to be lying down.
var/self_operable = FALSE //Can the surgery be performed on yourself.
var/requires_tech = FALSE //handles techweb-oriented surgeries, previously restricted to the /advanced subtype (You still need to add designs)
var/replaced_by //type; doesn't show up if this type exists. Set to /datum/surgery if you want to hide a "base" surgery (useful for typing parents IE healing.dm just make sure to null it out again)
/datum/surgery/New(surgery_target, surgery_location, surgery_bodypart)
..()
if(surgery_target)
target = surgery_target
target.surgeries += src
if(surgery_location)
location = surgery_location
if(surgery_bodypart)
operated_bodypart = surgery_bodypart
/datum/surgery/Destroy()
if(target)
target.surgeries -= src
target = null
operated_bodypart = null
return ..()
/datum/surgery/proc/can_start(mob/user, mob/living) //FALSE to not show in list
. = TRUE
if(replaced_by == /datum/surgery)
return FALSE
if(HAS_TRAIT(user, TRAIT_SURGEON) || HAS_TRAIT(user.mind, TRAIT_SURGEON))
if(replaced_by)
return FALSE
else
return TRUE
if(!requires_tech && !replaced_by)
return TRUE
// True surgeons (like abductor scientists) need no instructions
if(requires_tech)
. = FALSE
if(iscyborg(user))
var/mob/living/silicon/robot/R = user
var/obj/item/surgical_processor/SP = locate() in R.module.modules
if(!SP || (replaced_by in SP.advanced_surgeries))
return FALSE
if(type in SP.advanced_surgeries)
return TRUE
var/turf/T = get_turf(target)
var/obj/structure/table/optable/table = locate(/obj/structure/table/optable, T)
if(table)
if(!table.computer)
return FALSE
if(table.computer.stat & (NOPOWER|BROKEN) || (replaced_by in table.computer.advanced_surgeries))
return FALSE
if(type in table.computer.advanced_surgeries)
return TRUE
/datum/surgery/proc/next_step(mob/user, intent)
if(step_in_progress)
return TRUE
var/try_to_fail = FALSE
if(intent == INTENT_DISARM)
try_to_fail = TRUE
var/datum/surgery_step/S = get_surgery_step()
if(S)
var/obj/item/tool = user.get_active_held_item()
if(S.try_op(user, target, user.zone_selected, tool, src, try_to_fail))
return TRUE
if(iscyborg(user) && user.a_intent != INTENT_HARM) //to save asimov borgs a LOT of heartache
return TRUE
if(tool.item_flags & SURGICAL_TOOL) //Just because you used the wrong tool it doesn't mean you meant to whack the patient with it
to_chat(user, "<span class='warning'>This step requires a different tool!</span>")
return TRUE
return FALSE
/datum/surgery/proc/get_surgery_step()
var/step_type = steps[status]
return new step_type
/datum/surgery/proc/get_surgery_next_step()
if(status < steps.len)
var/step_type = steps[status + 1]
return new step_type
else
return null
/datum/surgery/proc/complete()
SSblackbox.record_feedback("tally", "surgeries_completed", 1, type)
qdel(src)
/datum/surgery/proc/get_propability_multiplier()
var/propability = 0.5
var/turf/T = get_turf(target)
if(locate(/obj/structure/table/optable, T))
propability = 1
else if(locate(/obj/machinery/stasis, T))
propability = 0.9
else if(locate(/obj/structure/table, T))
propability = 0.8
else if(locate(/obj/structure/bed, T))
propability = 0.7
return propability + success_multiplier
/datum/surgery/advanced
name = "advanced surgery"
requires_tech = TRUE
/obj/item/disk/surgery
name = "Surgery Procedure Disk"
desc = "A disk that contains advanced surgery procedures, must be loaded into an Operating Console."
icon_state = "datadisk1"
materials = list(MAT_METAL=300, MAT_GLASS=100)
var/list/surgeries
/obj/item/disk/surgery/debug
name = "Debug Surgery Disk"
desc = "A disk that contains all existing surgery procedures."
icon_state = "datadisk1"
materials = list(MAT_METAL=300, MAT_GLASS=100)
/obj/item/disk/surgery/debug/Initialize()
. = ..()
surgeries = list()
var/list/req_tech_surgeries = subtypesof(/datum/surgery)
for(var/i in req_tech_surgeries)
var/datum/surgery/beep = i
if(beep.requires_tech)
surgeries += beep
//INFO
//Check /mob/living/carbon/attackby for how surgery progresses, and also /mob/living/carbon/attack_hand.
//As of Feb 21 2013 they are in code/modules/mob/living/carbon/carbon.dm, lines 459 and 51 respectively.
//Other important variables are var/list/surgeries (/mob/living) and var/list/internal_organs (/mob/living/carbon)
// var/list/bodyparts (/mob/living/carbon/human) is the LIMBS of a Mob.
//Surgical procedures are initiated by attempt_initiate_surgery(), which is called by surgical drapes and bedsheets.
//TODO
//specific steps for some surgeries (fluff text)
//more interesting failure options
//randomised complications
//more surgeries!
//add a probability modifier for the state of the surgeon- health, twitching, etc. blindness, god forbid.
//helper for converting a zone_sel.selecting to body part (for damage)
//RESOLVED ISSUES //"Todo" jobs that have been completed
//combine hands/feet into the arms - Hands/feet were removed - RR
//surgeries (not steps) that can be initiated on any body part (corresponding with damage locations) - Call this one done, see possible_locs var - c0
>>>>>>> 8fcf42eff9... Experimental Cobbisection [150+ Hours and Ready] (#44821)
+12 -8
View File
@@ -8,7 +8,9 @@
var/repeatable = FALSE //can this step be repeated? Make shure it isn't last step, or it used in surgery with `can_cancel = 1`. Or surgion will be stuck in the loop
var/list/chems_needed = list() //list of chems needed to complete the step. Even on success, the step will have no effect if there aren't the chems required in the mob.
var/require_all_chems = TRUE //any on the list or all on the list?
/datum/surgery_step/proc/try_op(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
var/silicons_obey_prob = FALSE
/datum/surgery_step/proc/try_op(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
var/success = FALSE
if(accept_hand)
if(!tool)
@@ -46,7 +48,8 @@
else
surgery.status--
return FALSE
/datum/surgery_step/proc/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
/datum/surgery_step/proc/initiate(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
surgery.step_in_progress = TRUE
var/speed_mod = 1
var/advance = FALSE
@@ -60,7 +63,8 @@
if(implement_type) //this means it isn't a require hand or any item step.
prob_chance = implements[implement_type]
prob_chance *= surgery.get_propability_multiplier()
if((prob(prob_chance) || iscyborg(user)) && chem_check(target) && !try_to_fail)
if((prob(prob_chance) || (iscyborg(user) && !silicons_obey_prob)) && chem_check(target) && !try_to_fail)
if(success(user, target, target_zone, tool, surgery))
advance = TRUE
else
@@ -73,19 +77,18 @@
surgery.step_in_progress = FALSE
return advance
/datum/surgery_step/proc/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
/datum/surgery_step/proc/preop(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "<span class='notice'>You begin to perform surgery on [target]...</span>",
"[user] begins to perform surgery on [target].",
"[user] begins to perform surgery on [target].")
/datum/surgery_step/proc/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
/datum/surgery_step/proc/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "<span class='notice'>You succeed.</span>",
"[user] succeeds!",
"[user] finishes.")
return TRUE
/datum/surgery_step/proc/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
/datum/surgery_step/proc/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "<span class='warning'>You screw up!</span>",
"<span class='warning'>[user] screws up!</span>",
"[user] finishes.", TRUE) //By default the patient will notice if the wrong thing has been cut
@@ -93,7 +96,8 @@
/datum/surgery_step/proc/tool_check(mob/user, obj/item/tool)
return TRUE
/datum/surgery_step/proc/chem_check(mob/living/carbon/target)
/datum/surgery_step/proc/chem_check(mob/living/target)
if(!LAZYLEN(chems_needed))
return TRUE
if(require_all_chems)