diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 3db6e30fa52..b86d5e613b5 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -46,4 +46,19 @@ #define PASSTABLE 1 #define PASSGLASS 2 #define PASSGRILLE 4 -#define PASSBLOB 8 \ No newline at end of file +#define PASSBLOB 8 + +//flags for species + +#define MUTCOLORS 1 +#define HAIR 2 +#define FACEHAIR 4 +#define EYECOLOR 8 +#define LIPS 16 +#define COLDRES 32 +#define HEATRES 64 +#define RADIMMUNE 128 +#define NOBREATH 256 +#define NOGUNS 512 +#define NOBLOOD 1024 +#define NOFIRE 2048 \ No newline at end of file diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 9ab0003633a..d7ecd960955 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -10,6 +10,15 @@ //underwear init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear, underwear_all, underwear_m, underwear_f) + //Species + for(var/spath in typesof(/datum/species)) + if(spath == /datum/species) + continue + var/datum/species/S = new spath() + if(S.roundstart) + roundstart_species[S.name] = S.type + species_list[S.id] = S.type + //Surgeries for(var/path in typesof(/datum/surgery)) if(path == /datum/surgery) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index b382bb1e678..6b53dcaa221 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -56,10 +56,8 @@ var/list/skin_tones = list( "african2" ) -var/list/mutant_races = list( - "human", - "lizard", - ) +var/global/list/species_list[0] +var/global/list/roundstart_species[0] proc/age2agedescription(age) switch(age) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 5e8ceba95ba..979f8042173 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -252,6 +252,15 @@ Turf and target are seperate in case you want to teleport some distance from a t if(isAI(src)) var/mob/living/silicon/ai/AI = src if(oldname != real_name) + if(AI.eyeobj) + AI.eyeobj.name = "[newname] (AI Eye)" + + // Set ai pda name + if(AI.aiPDA) + AI.aiPDA.owner = newname + AI.aiPDA.name = newname + " (" + AI.aiPDA.ownjob + ")" + + // Notify Cyborgs for(var/mob/living/silicon/robot/Slave in AI.connected_robots) Slave.show_laws() @@ -330,22 +339,7 @@ Turf and target are seperate in case you want to teleport some distance from a t if(cmptext("ai",role)) if(isAI(src)) - var/mob/living/silicon/ai/A = src oldname = null//don't bother with the records update crap - //world << "[newname] is the AI!" - //world << sound('sound/AI/newAI.ogg') - // Set eyeobj name - if(A.eyeobj) - A.eyeobj.name = "[newname] (AI Eye)" - - // Set ai pda name - if(A.aiPDA) - A.aiPDA.owner = newname - A.aiPDA.name = newname + " (" + A.aiPDA.ownjob + ")" - - // Notify Cyborgs - for(var/mob/living/silicon/robot/Slave in A.connected_robots) - Slave.show_laws() if(cmptext("cyborg",role)) if(isrobot(src)) diff --git a/code/_compile_options.dm b/code/_compile_options.dm index 2949a7e70d7..c6c1d29785f 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -43,7 +43,6 @@ #define AI_CAMERA_LUMINOSITY 5 #define AI_VOX 1 // Comment out if you don't want VOX to be enabled and have players download the voice sounds. - //Additional code for the above flags. #ifdef dellogging #warn compiling del logging. This will have additional overheads. //will warn you if compiling with dellogging diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index a4c1fac1f53..b9feeaa1124 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -77,6 +77,7 @@ var/traitor_scaling_coeff = 6 //how much does the amount of players get divided by to determine traitors var/changeling_scaling_coeff = 7 //how much does the amount of players get divided by to determine changelings + var/traitor_objectives_amount = 2 var/protect_roles_from_antagonist = 0// If security and such can be traitor/cult/other var/allow_latejoin_antagonists = 0 // If late-joining players can be traitor/changeling var/continuous_round_rev = 0 // Gamemodes which end instantly will instead keep on going until the round ends by escape shuttle or nuke. @@ -85,6 +86,7 @@ var/shuttle_refuel_delay = 12000 var/show_game_type_odds = 0 //if set this allows players to see the odds of each roundtype on the get revision screen var/mutant_races = 0 //players can choose their mutant race before joining the game + var/mutant_colors = 0 var/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced." var/alert_desc_blue_upto = "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible, random searches are permitted." @@ -344,6 +346,8 @@ config.traitor_scaling_coeff = text2num(value) if("changeling_scaling_coeff") config.changeling_scaling_coeff = text2num(value) + if("traitor_objectives_amount") + config.traitor_objectives_amount = text2num(value) if("probability") var/prob_pos = findtext(value, " ") var/prob_name = null @@ -385,6 +389,8 @@ config.default_laws = text2num(value) if("join_with_mutant_race") config.mutant_races = 1 + if("mutant_colors") + config.mutant_colors = 1 else diary << "Unknown setting in configuration: '[name]'" diff --git a/code/controllers/garbage.dm b/code/controllers/garbage.dm index 53b1d8019a1..322bc086d89 100644 --- a/code/controllers/garbage.dm +++ b/code/controllers/garbage.dm @@ -11,6 +11,9 @@ var/datum/controller/garbage_collector/garbage = new() // refID's are associated with the time at which they time out and need to be manually del() // we do this so we aren't constantly locating them and preventing them from being gc'd + var/list/logging = list() // list of all types that have failed to GC associated with the number of times that's happened. + // the types are stored as strings + /datum/controller/garbage_collector/proc/AddTrash(var/datum/A) if(!istype(A) || !isnull(A.gc_destroyed)) return @@ -37,6 +40,7 @@ var/datum/controller/garbage_collector/garbage = new() if(A && A.gc_destroyed == GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake // Something's still referring to the qdel'd object. Kill it. testing("GC: -- \ref[A] | [A.type] was unable to be GC'd and was deleted --") + logging["[A.type]"]++ del(A) dels++ // else diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm index 0858a70f7f1..6e1c9a0a078 100644 --- a/code/controllers/shuttle_controller.dm +++ b/code/controllers/shuttle_controller.dm @@ -73,7 +73,7 @@ datum/shuttle_controller last_call_loc = null if(recall_count == 2) - priority_announce("The emergency shuttle has been recalled.\n\nExcessive number of emergency shuttle calls detected. We will attempt to trace any further signals to their source. Results may be viewed on any communications console.", null, 'sound/AI/shuttlerecalled.ogg') + priority_announce("The emergency shuttle has been recalled.\n\nExcessive number of emergency shuttle calls detected. We will attempt to trace all future calls and recalls to their source. Tracing results can be viewed on any communications console.", null, 'sound/AI/shuttlerecalled.ogg') else priority_announce("The emergency shuttle has been recalled.", null, 'sound/AI/shuttlerecalled.ogg', "Priority") setdirection(-1) diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 4dba24ce357..7477a1bea43 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -249,12 +249,11 @@ client body += "" body += "" body += "" - body += "" body += "" body += "" if(ishuman(D)) body += "" - body += "" + body += "" body += "" body += "" body += "" @@ -581,17 +580,6 @@ client if(usr.client) usr.client.cmd_assume_direct_control(M) - else if(href_list["make_skeleton"]) - if(!check_rights(R_FUN)) return - - var/mob/living/carbon/human/H = locate(href_list["make_skeleton"]) - if(!istype(H)) - usr << "This can only be used on instances of type /mob/living/carbon/human" - return - - H.makeSkeleton() - href_list["datumrefresh"] = href_list["make_skeleton"] - else if(href_list["delall"]) if(!check_rights(R_DEBUG|R_SERVER)) return @@ -786,25 +774,24 @@ client return holder.Topic(href, list("makeai"=href_list["makeai"])) - else if(href_list["setmutantrace"]) + else if(href_list["setspecies"]) if(!check_rights(R_SPAWN)) return - var/mob/living/carbon/human/H = locate(href_list["setmutantrace"]) + var/mob/living/carbon/human/H = locate(href_list["setspecies"]) if(!istype(H)) usr << "This can only be done to instances of type /mob/living/carbon/human" return - var/new_mutantrace = input("Please choose a new mutantrace","Mutantrace",null) as null|anything in list("NONE","golem","lizard","slime","plant","shadow", "fly", "skeleton") - switch(new_mutantrace) - if(null) return - if("NONE") new_mutantrace = "" + var/result = input(usr, "Please choose a new species","Species") as null|anything in species_list + if(!H) usr << "Mob doesn't exist anymore" return - if(H.dna) - H.dna.mutantrace = new_mutantrace - H.update_body() - H.update_hair() + + if(result) + var/newtype = species_list[result] + H.dna.species = new newtype() + H.regenerate_icons() else if(href_list["adjustDamage"] && href_list["mobToDamage"]) if(!check_rights(0)) return diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index f1ee58534ec..8749abed60d 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -139,15 +139,14 @@ ..() switch(stage) if(1) - if(ishuman(affected_mob) && affected_mob.dna && affected_mob.dna.mutantrace == "slime") + if(ishuman(affected_mob) && affected_mob.dna && affected_mob.dna.species.id == "slime") stage = 5 if(3) if(ishuman(affected_mob)) var/mob/living/carbon/human/human = affected_mob - if(human.dna && !human.dna.mutantrace) - human.dna.mutantrace = "slime" - human.update_body() - + if(human.dna && human.dna.species.id != "slime") + human.dna.species = new /datum/species/slime() + human.update_icons() /datum/disease/transformation/corgi name = "The Barkening" diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 9b004722c96..1e2f7d20e0e 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1172,19 +1172,8 @@ datum/mind ..() mind.assigned_role = "Shade" -/mob/living/simple_animal/construct/builder/mind_initialize() +/mob/living/simple_animal/construct/mind_initialize() ..() - mind.assigned_role = "Artificer" + mind.assigned_role = "[initial(name)]" mind.special_role = "Cultist" -/mob/living/simple_animal/construct/wraith/mind_initialize() - ..() - mind.assigned_role = "Wraith" - mind.special_role = "Cultist" - -/mob/living/simple_animal/construct/armoured/mind_initialize() - ..() - mind.assigned_role = "Juggernaut" - mind.special_role = "Cultist" - - diff --git a/code/datums/spell.dm b/code/datums/spell.dm index 7da40ce6f7c..e7b69221cf4 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -8,6 +8,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin desc = "A wizard spell" panel = "Spells" anchored = 1 // Crap like fireball projectiles are proc_holders, this is needed so fireballs don't get blown back into your face via atmos etc. + pass_flags = PASSTABLE density = 0 opacity = 0 @@ -191,6 +192,11 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin var/datum/effect/effect/system/bad_smoke_spread/smoke = new /datum/effect/effect/system/bad_smoke_spread() smoke.set_up(smoke_amt, 0, location, smoke_amt == 1 ? 15 : 0) // same here smoke.start() + else if(smoke_spread == 3) + var/datum/effect/effect/system/sleep_smoke_spread/smoke = new /datum/effect/effect/system/sleep_smoke_spread() + smoke.set_up(smoke_amt, 0, location, smoke_amt == 1 ? 15 : 0) // same here + smoke.start() + /obj/effect/proc_holder/spell/proc/cast(list/targets) return diff --git a/code/datums/spells/construct_spells.dm b/code/datums/spells/construct_spells.dm index ed3248d776a..7e4221f9a03 100644 --- a/code/datums/spells/construct_spells.dm +++ b/code/datums/spells/construct_spells.dm @@ -110,3 +110,20 @@ invocation_type = "none" proj_lifespan = 10 max_targets = 6 + + +/obj/effect/proc_holder/spell/targeted/smoke/disable + name = "Paralysing Smoke" + desc = "This spell spawns a cloud of paralysing smoke." + + school = "conjuration" + charge_max = 200 + clothes_req = 0 + invocation = "none" + invocation_type = "none" + range = -1 + include_user = 1 + cooldown_min = 20 //25 deciseconds reduction per rank + + smoke_spread = 3 + smoke_amt = 10 diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 718fe4db854..d8b0638b193 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -250,6 +250,10 @@ var/list/blood_splatter_icons = list() //returns 1 if made bloody, returns 0 otherwise /atom/proc/add_blood(mob/living/carbon/M) + if(ishuman(M) && M.dna) + var/mob/living/carbon/human/H = M + if(NOBLOOD in H.dna.species.specflags) + return 0 if(rejects_blood()) return 0 if(!istype(M)) @@ -270,7 +274,7 @@ var/list/blood_splatter_icons = list() //try to find a pre-processed blood-splatter. otherwise, make a new one var/index = blood_splatter_index() var/icon/blood_splatter_icon = blood_splatter_icons[index] - if(!blood_splatter_icon ) + if(!blood_splatter_icon) blood_splatter_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent) blood_splatter_icon.Blend(icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 6d60e1c7835..22a06b41da6 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -127,7 +127,10 @@ //done throwing, either because it hit something or it finished moving src.throwing = 0 - if(isobj(src)) src.throw_impact(get_turf(src)) + if(isobj(src)) + src.throw_impact(get_turf(src)) + + return 1 //Overlays @@ -152,4 +155,4 @@ /atom/movable/overlay/attack_hand(a, b, c) if (src.master) return src.master.attack_hand(a, b, c) - return \ No newline at end of file + return diff --git a/code/game/dna.dm b/code/game/dna.dm index d969e6bc1a1..35314862a41 100644 --- a/code/game/dna.dm +++ b/code/game/dna.dm @@ -20,7 +20,8 @@ var/struc_enzymes var/uni_identity var/blood_type - var/mutantrace = null //The type of mutant race the player is if applicable (i.e. potato-man) + var/datum/species/species = new /datum/species/human() //The type of mutant race the player is if applicable (i.e. potato-man) + var/mutant_color = "FFF" // What color you are if you have certain speciess var/real_name //Stores the real name of the person who originally got this dna datum. Used primarely for changelings, /datum/dna/proc/generate_uni_identity(mob/living/carbon/character) @@ -30,6 +31,8 @@ L[DNA_GENDER_BLOCK] = construct_block((character.gender!=MALE)+1, 2) if(istype(character, /mob/living/carbon/human)) var/mob/living/carbon/human/H = character + if(!H.dna.species) + H.dna.species = new /datum/species/human() L[DNA_HAIR_STYLE_BLOCK] = construct_block(hair_styles_list.Find(H.hair_style), hair_styles_list.len) L[DNA_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.hair_color) L[DNA_FACIAL_HAIR_STYLE_BLOCK] = construct_block(facial_hair_styles_list.Find(H.facial_hair_style), facial_hair_styles_list.len) @@ -62,11 +65,17 @@ . += repeat_string(DNA_UNIQUE_ENZYMES_LEN, "0") return . -/proc/hardset_dna(mob/living/carbon/owner, ui, se, real_name, mutantrace, blood_type) +/proc/hardset_dna(mob/living/carbon/owner, ui, se, real_name, blood_type, datum/species/mrace, mcolor) if(!istype(owner, /mob/living/carbon/monkey) && !istype(owner, /mob/living/carbon/human)) return if(!owner.dna) - create_dna(owner) + create_dna(owner, mrace) + + if(mrace) + owner.dna.species = new mrace() + + if(mcolor) + owner.dna.mutant_color = mcolor if(real_name) owner.real_name = real_name @@ -79,18 +88,13 @@ owner.dna.uni_identity = ui updateappearance(owner) - var/update_mutantrace = (mutantrace != owner.dna.mutantrace) - owner.dna.mutantrace = mutantrace - if(update_mutantrace && istype(owner, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = owner - H.update_body() - H.update_hair() - if(se) owner.dna.struc_enzymes = se domutcheck(owner) check_dna_integrity(owner) + + owner.regenerate_icons() return /proc/check_dna_integrity(mob/living/carbon/character) @@ -122,8 +126,9 @@ character.dna.unique_enzymes = character.dna.generate_unique_enzymes(character) return character.dna -/proc/create_dna(mob/living/carbon/C) //don't use this unless you're about to use hardset_dna or ready_dna +/proc/create_dna(mob/living/carbon/C, datum/species/S) //don't use this unless you're about to use hardset_dna or ready_dna C.dna = new /datum/dna() + if(S) C.dna.species = new S() // do not remove; this is here to prevent runtimes /////////////////////////// DNA DATUM @@ -981,7 +986,7 @@ proc/deconstruct_block(value, values, blocksize=DNA_BLOCK_SIZE) /datum/dna/proc/is_same_as(var/datum/dna/D) if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name) - if(mutantrace == D.mutantrace && blood_type == D.blood_type) + if(species == D.species && mutant_color == D.mutant_color && blood_type == D.blood_type) return 1 return 0 diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index 946ca14f8c4..bd1b910f90e 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -90,7 +90,8 @@ new_dna.uni_identity = T.dna.uni_identity new_dna.struc_enzymes = T.dna.struc_enzymes new_dna.real_name = T.dna.real_name - new_dna.mutantrace = T.dna.mutantrace + new_dna.species = T.dna.species + new_dna.mutant_color = T.dna.mutant_color new_dna.blood_type = T.dna.blood_type absorbed_dna |= new_dna //And add the target DNA to our absorbed list. absorbedcount++ //all that done, let's increment the objective counter. \ No newline at end of file diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm index 17aae0b9b84..da147e0d128 100644 --- a/code/game/gamemodes/changeling/powers/tiny_prick.dm +++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm @@ -88,7 +88,7 @@ var/datum/dna/NewDNA = selected_dna if(ismonkey(target)) user << "We stealthily sting [target.name]." - hardset_dna(target, NewDNA.uni_identity, NewDNA.struc_enzymes, NewDNA.real_name, NewDNA.mutantrace, NewDNA.blood_type) + hardset_dna(target, NewDNA.uni_identity, NewDNA.struc_enzymes, NewDNA.real_name, NewDNA.blood_type, NewDNA.species, NewDNA.mutant_color) updateappearance(target) feedback_add_details("changeling_powers","TS") return 1 diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm index 612d7871abc..b6954ccf79c 100644 --- a/code/game/gamemodes/changeling/powers/transform.dm +++ b/code/game/gamemodes/changeling/powers/transform.dm @@ -8,16 +8,17 @@ max_genetic_damage = 3 //Change our DNA to that of somebody we've absorbed. -/obj/effect/proc_holder/changeling/transform/sting_action(var/mob/living/carbon/user) +/obj/effect/proc_holder/changeling/transform/sting_action(var/mob/living/carbon/human/user) var/datum/changeling/changeling = user.mind.changeling var/datum/dna/chosen_dna = changeling.select_dna("Select the target DNA: ", "Target DNA") if(!chosen_dna) return - user.dna = chosen_dna user.real_name = chosen_dna.real_name + user.dna.species = new chosen_dna.species.type(user) + user.dna.mutant_color = chosen_dna.mutant_color updateappearance(user) domutcheck(user, null) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index f29f7b9d1d2..5007a845681 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -13,10 +13,19 @@ datum/objective/New(var/text) datum/objective/proc/check_completion() return completed +datum/objective/proc/is_unique_objective(possible_target) + for(var/datum/objective/assassinate/O in owner.objectives) + if(O.get_target() == possible_target) + return 0 + return 1 + +datum/objective/proc/get_target() + return target + datum/objective/proc/find_target() var/list/possible_targets = list() for(var/datum/mind/possible_target in ticker.minds) - if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != 2)) + if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != 2) && is_unique_objective(possible_target)) possible_targets += possible_target if(possible_targets.len > 0) target = pick(possible_targets) @@ -255,21 +264,32 @@ datum/objective/steal var/obj/item/steal_target = null //Needed for custom objectives (they're just items, not datums). dangerrating = 5 //Overridden by the individual item's difficulty, but defaults to 5 for custom objectives. +datum/objective/steal/get_target() + return steal_target + datum/objective/steal/New() ..() if(!possible_items.len)//Only need to fill the list when it's needed. init_subtypes(/datum/objective_item/steal,possible_items) datum/objective/steal/find_target() - return set_target(pick(possible_items)) + var/approved_targets = list() + for(var/datum/objective_item/possible_item in possible_items) + if(is_unique_objective(possible_item.targetitem)) + approved_targets += possible_item + return set_target(safepick(possible_items)) datum/objective/steal/proc/set_target(var/datum/objective_item/item) - targetinfo = item + if(item) + targetinfo = item - steal_target = targetinfo.targetitem - explanation_text = "Steal [targetinfo.name]." - dangerrating = targetinfo.difficulty - return steal_target + steal_target = targetinfo.targetitem + explanation_text = "Steal [targetinfo.name]." + dangerrating = targetinfo.difficulty + return steal_target + else + explanation_text = "Free objective" + return datum/objective/steal/proc/select_target() //For admins setting objectives manually. var/list/possible_items_all = possible_items+"custom" @@ -292,7 +312,7 @@ datum/objective/steal/proc/select_target() //For admins setting objectives manua return steal_target datum/objective/steal/check_completion() - if(!steal_target || !owner.current) return 0 + if(!steal_target) return 1 if(!isliving(owner.current)) return 0 var/list/all_items = owner.current.GetAllContents() //this should get things in cheesewheels, books, etc. diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 7e30c214854..cf23fd6fccd 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -116,16 +116,17 @@ assign_exchange_role(exchange_red,"red") assign_exchange_role(exchange_blue,"blue") else - if(prob(50)) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = traitor - kill_objective.find_target() - traitor.objectives += kill_objective - else - var/datum/objective/steal/steal_objective = new - steal_objective.owner = traitor - steal_objective.find_target() - traitor.objectives += steal_objective + for(var/i = 0, i < config.traitor_objectives_amount, i++) + if(prob(50)) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = traitor + kill_objective.find_target() + traitor.objectives += kill_objective + else + var/datum/objective/steal/steal_objective = new + steal_objective.owner = traitor + steal_objective.find_target() + traitor.objectives += steal_objective if(prob(90)) if (!(locate(/datum/objective/escape) in traitor.objectives)) diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index 2e7d0f8d0f2..fb7dd81ace1 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -22,13 +22,6 @@ transfer_soul("VICTIM", M, user) return -/*/obj/item/device/soulstone/attack(mob/living/simple_animal/shade/M as mob, mob/user as mob)//APPARENTLY THEY NEED THEIR OWN SPECIAL SNOWFLAKE CODE IN THE LIVING ANIMAL DEFINES - if(!istype(M, /mob/living/simple_animal/shade))//If target is not a shade - return ..() - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to capture the soul of [M.name] ([M.ckey])") - - transfer_soul("SHADE", M, user) - return*/ ///////////////////Options for using captured souls/////////////////////////////////////// /obj/item/device/soulstone/attack_self(mob/user) @@ -46,8 +39,6 @@ return - - /obj/item/device/soulstone/Topic(href, href_list) var/mob/U = usr if (!in_range(src, U)||U.machine!=src) @@ -160,53 +151,35 @@ var/construct_class = alert(U, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer") switch(construct_class) if("Juggernaut") - var/mob/living/simple_animal/construct/armoured/Z = new /mob/living/simple_animal/construct/armoured (get_turf(T.loc)) - Z.key = A.key - if(iscultist(U)) - if(ticker.mode.name == "cult") - ticker.mode:add_cultist(Z.mind) - else - ticker.mode.cult+=Z.mind - ticker.mode.update_cult_icons_added(Z.mind) - qdel(T) - Z << "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, create shield walls and even deflect energy weapons, and rip apart enemies and walls alike." - Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." - Z.cancel_camera() - qdel(C) + makeNewConstruct(/mob/living/simple_animal/construct/armoured, A, U) if("Wraith") - var/mob/living/simple_animal/construct/wraith/Z = new /mob/living/simple_animal/construct/wraith (get_turf(T.loc)) - Z.key = A.key - if(iscultist(U)) - if(ticker.mode.name == "cult") - ticker.mode:add_cultist(Z.mind) - else - ticker.mode.cult+=Z.mind - ticker.mode.update_cult_icons_added(Z.mind) - qdel(T) - Z << "You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls." - Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." - Z.cancel_camera() - qdel(C) + makeNewConstruct(/mob/living/simple_animal/construct/wraith, A, U) if("Artificer") - var/mob/living/simple_animal/construct/builder/Z = new /mob/living/simple_animal/construct/builder (get_turf(T.loc)) - Z.key = A.key - if(iscultist(U)) - if(ticker.mode.name == "cult") - ticker.mode:add_cultist(Z.mind) - else - ticker.mode.cult+=Z.mind - ticker.mode.update_cult_icons_added(Z.mind) - qdel(T) - Z << "You are an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, use magic missile, repair allied constructs (by clicking on them), and most important of all create new constructs (Use your Artificer spell to summon a new construct shell and Summon Soulstone to create a new soulstone)." - Z << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." - Z.cancel_camera() - qdel(C) + makeNewConstruct(/mob/living/simple_animal/construct/builder, A, U) + + qdel(T) + qdel(C) else U << "Creation failed!: The soul stone is empty! Go kill someone!" return + +proc/makeNewConstruct(var/mob/living/simple_animal/construct/ctype, var/mob/target, var/mob/stoner = null, cultoverride = 0) + var/mob/living/simple_animal/construct/newstruct = new ctype(get_turf(target)) + newstruct.key = target.key + if(stoner && iscultist(stoner) || cultoverride) + if(ticker.mode.name == "cult") + ticker.mode:add_cultist(newstruct.mind) + else + ticker.mode.cult+=newstruct.mind + ticker.mode.update_cult_icons_added(newstruct.mind) + newstruct << newstruct.playstyle_string + newstruct << "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs." + newstruct.cancel_camera() + + /obj/item/device/soulstone/proc/init_shade(var/obj/item/device/soulstone/C, var/mob/living/carbon/human/T, var/mob/U as mob, var/vic = 0) new /obj/effect/decal/remains/human(T.loc) //Spawns a skeleton T.invisibility = 101 diff --git a/code/game/jobs/job/captain.dm b/code/game/jobs/job/captain.dm index 62b93744f17..bfa0a915c94 100644 --- a/code/game/jobs/job/captain.dm +++ b/code/game/jobs/job/captain.dm @@ -43,7 +43,7 @@ Captain L.imp_in = H L.implanted = 1 - world << "[H.real_name] is the captain!" + world << "Captain [H.real_name] on deck!" /datum/job/captain/get_access() return get_all_accesses() diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index 460b9fbeaa5..93c43bd653d 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -74,8 +74,14 @@ equip_backpack(H) //Equip the rest of the gear + if(H.dna) + H.dna.species.before_equip_job(src, H) + equip_items(H) + if(H.dna) + H.dna.species.after_equip_job(src, H) + //Equip ID var/obj/item/weapon/card/id/C = new default_id(H) C.access = get_access() diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 4f0df133f3b..9b404e0531b 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -807,20 +807,17 @@ table tr:first-child th:first-child { border: none;} if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/cable = W - if(cable.amount < 5) - user << "You need more cable!" + if(cable.get_amount() < 5) + user << "You need five lengths of cable to wire the fire alarm." return - - user << "You start wiring the air alarm!" - spawn(20) - cable.amount -= 5 - if(!cable.amount) - qdel(cable) - - user << "You wire the air alarm!" - wires.wires_status = 0 - buildstage = 2 - update_icon() + user << "You start wiring the air alarm." + if (do_after(user, 20)) + if (cable.get_amount() >= 5 && buildstage == 1) + cable.use(5) + user << "You wire the air alarm." + wires.wires_status = 0 + buildstage = 2 + update_icon() return if(0) if(istype(W, /obj/item/weapon/airalarm_electronics)) @@ -999,13 +996,11 @@ FIRE ALARM if(1) if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/coil = W - if(coil.amount < 5) + if(coil.get_amount() < 5) user << "You need more cable for this!" return - coil.amount -= 5 - if(!coil.amount) - qdel(coil) + coil.use(5) buildstage = 2 user << "You wire \the [src]!" diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm index 5cb9d67a849..c02e6c596f2 100644 --- a/code/game/machinery/bots/ed209bot.dm +++ b/code/game/machinery/bots/ed209bot.dm @@ -698,9 +698,6 @@ Auto Patrol: []"}, if(istype(perp:wear_suit, /obj/item/clothing/suit/wizrobe)) threatcount += 2 - if(perp.dna && perp.dna.mutantrace && perp.dna.mutantrace != "none") - threatcount += 2 - //Agent cards lower threatlevel when normal idchecking is off. if((perp.wear_id && istype(perp:wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) && src.idcheck) threatcount -= 2 @@ -967,14 +964,16 @@ Auto Patrol: []"}, if(6) if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/coil = W - var/turf/T = get_turf(user) + if (coil.get_amount() < 1) + user << "You need one length of cable to wire the ED-209." + return user << "You start to wire [src]..." - sleep(40) - if(get_turf(user) == T) - coil.use(1) - build_step++ - user << "You wire the ED-209 assembly." - name = "wired ED-209 assembly" + if (do_after(user, 40)) + if (coil.get_amount() >= 1 && build_step == 6) + coil.use(1) + build_step = 7 + user << "You wire the ED-209 assembly." + name = "wired ED-209 assembly" if(7) switch(lasercolor) diff --git a/code/game/machinery/bots/floorbot.dm b/code/game/machinery/bots/floorbot.dm index 642dcfe2ff9..bdcaea0f7e8 100644 --- a/code/game/machinery/bots/floorbot.dm +++ b/code/game/machinery/bots/floorbot.dm @@ -102,11 +102,14 @@ var/obj/item/stack/tile/plasteel/T = W if(src.amount >= 50) return - var/loaded = min(50-src.amount, T.amount) + var/loaded = min(50 - src.amount, T.get_amount()) T.use(loaded) src.amount += loaded - user << "You load [loaded] tiles into the floorbot. He now contains [src.amount] tiles." - src.updateicon() + if (loaded > 0) + user << "You load [loaded] tiles into the floorbot. He now contains [src.amount] tiles." + src.updateicon() + else + user << "You need at least one floor tile to put into the floorbot." else if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) if(src.allowed(usr) && !open && !emagged) src.locked = !src.locked @@ -409,16 +412,19 @@ ..() return if(src.contents.len >= 1) - user << "They wont fit in as there is already stuff inside." + user << "They won't fit in, as there is already stuff inside." + return + if(T.use(10)) + if(user.s_active) + user.s_active.close(user) + var/obj/item/weapon/toolbox_tiles/B = new /obj/item/weapon/toolbox_tiles + user.put_in_hands(B) + user << "You add the tiles into the empty toolbox. They protrude from the top." + user.unEquip(src, 1) + qdel(src) + else + user << "You need 10 floor tiles to start building a floorbot." return - if(user.s_active) - user.s_active.close(user) - qdel(T) - var/obj/item/weapon/toolbox_tiles/B = new /obj/item/weapon/toolbox_tiles - user.put_in_hands(B) - user << "You add the tiles into the empty toolbox. They protrude from the top." - user.unEquip(src, 1) - qdel(src) /obj/item/weapon/toolbox_tiles/attackby(var/obj/item/W, mob/user as mob) ..() diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm index e14f870ce67..7d1b29986d9 100644 --- a/code/game/machinery/bots/secbot.dm +++ b/code/game/machinery/bots/secbot.dm @@ -630,9 +630,6 @@ Auto Patrol: []"}, if(istype(humanperp.head, /obj/item/clothing/head/wizard) || istype(humanperp.head, /obj/item/clothing/head/helmet/space/rig/wizard)) threatcount += 2 - if(humanperp.dna && humanperp.dna.mutantrace && humanperp.dna.mutantrace != "none") - threatcount += 2 - //Agent cards lower threatlevel. if(humanperp.wear_id && istype(humanperp.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) threatcount -= 2 @@ -789,4 +786,4 @@ Auto Patrol: []"}, overlays -= "hs_arm" new /obj/item/robot_parts/l_arm(get_turf(src)) user << "You remove the robot arm from [src]." - build_step-- \ No newline at end of file + build_step-- diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index 32efc75734d..cc44b26c0c3 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -59,8 +59,11 @@ if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = W if(C.use(2)) - user << "You add wires to the assembly." + user << "You add wires to the assembly." state = 3 + else + user << "You need two lengths of cable to wire a camera." + return return else if(istype(W, /obj/item/weapon/weldingtool)) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 16437db55e0..ec9da16ba30 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -123,7 +123,7 @@ //Clonepod //Start growing a human clone in the pod! -/obj/machinery/clonepod/proc/growclone(var/ckey, var/clonename, var/ui, var/se, var/mindref, var/mrace) +/obj/machinery/clonepod/proc/growclone(var/ckey, var/clonename, var/ui, var/se, var/mindref, var/datum/species/mrace, var/mcolor) if(panel_open) return 0 if(mess || attempting) @@ -188,7 +188,8 @@ // -- End mode specific stuff - hardset_dna(H, ui, se, null, mrace) + hardset_dna(H, ui, se, null, null, mrace, mcolor) + if(efficiency > 2) for(var/A in bad_se_blocks) setblock(H.dna.struc_enzymes, A, construct_block(0,2)) @@ -203,6 +204,8 @@ H.facial_hair_style = "Shaved" H.hair_style = pick("Bedhead", "Bedhead 2", "Bedhead 3") + H.regenerate_icons() + H.suiciding = 0 src.attempting = 0 return 1 diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 5f0e35b08ec..5665d6997b8 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -63,14 +63,18 @@ state = 1 icon_state = "1" if(istype(P, /obj/item/stack/cable_coil)) - if(P:amount >= 5) + var/obj/item/stack/cable_coil/C = P + if(C.get_amount() >= 5) playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, 20)) - P:amount -= 5 - if(!P:amount) qdel(P) - user << "You add cables to the frame." - state = 3 - icon_state = "3" + if (C.get_amount() >= 5 && state == 3) + C.use(5) + user << "You add cables to the frame." + state = 3 + icon_state = "3" + else + user << "You need five lengths of cable to wire the AI core." + return if(3) if(istype(P, /obj/item/weapon/wirecutters)) if (brain) @@ -84,15 +88,18 @@ A.amount = 5 if(istype(P, /obj/item/stack/sheet/rglass)) - if(P:amount >= 2) + var/obj/item/stack/sheet/rglass/G = P + if(G.get_amount() >= 2) playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1) if(do_after(user, 20)) - if (P) - P:amount -= 2 - if(!P:amount) qdel(P) + if (G.get_amount() >= 2 && state == 3) + G.use(2) user << "You put in the glass panel." state = 4 icon_state = "4" + else + user << "You need two sheets of reinforced glass to insert them into AI core." + return if(istype(P, /obj/item/weapon/aiModule/core/full)) //Allows any full core boards to be applied to AI cores. var/obj/item/weapon/aiModule/core/M = P diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 012ed538d50..0b6c713d2fd 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -326,50 +326,51 @@ if(istype(P, /obj/item/weapon/screwdriver) && circuit) playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) user << "You unfasten the circuit board." - src.state = 1 - src.icon_state = "1" + state = 1 + icon_state = "1" if(istype(P, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = P - if(C.amount >= 5) + if(C.get_amount() >= 5) playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) user << "You start adding cables to the frame." if(do_after(user, 20)) - if(C && C.amount >= 5) - C.amount -= 5 - if(C.amount <= 0) qdel(C) + if(C.get_amount() >= 5 && state == 2) + C.use(5) user << "You've added cables to the frame." - src.state = 3 - src.icon_state = "3" + state = 3 + icon_state = "3" else - user << "You need more cable to do that." + user << "You need five lengths of cable to wire the frame." if(3) if(istype(P, /obj/item/weapon/wirecutters)) playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1) user << "You remove the cables." - src.state = 2 - src.icon_state = "2" + state = 2 + icon_state = "2" var/obj/item/stack/cable_coil/A = new (loc) A.amount = 5 A.add_fingerprint(user) if(istype(P, /obj/item/stack/sheet/glass)) - if(P:amount >= 2) + var/obj/item/stack/sheet/glass/G = P + if(G.get_amount() < 2) + user << "You need two glass sheets to continue construction." + return + else playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) user << "You start to put in the glass panel." if(do_after(user, 20)) - if(P) - P:use(2) + if(G.get_amount() >= 2 && state == 3) + G.use(2) user << "You've put in the glass panel." - src.state = 4 + state = 4 src.icon_state = "4" - else - user << "You need more glass to do that." if(4) if(istype(P, /obj/item/weapon/crowbar)) playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) user << "You remove the glass panel." - src.state = 3 - src.icon_state = "3" + state = 3 + icon_state = "3" var/obj/item/stack/sheet/glass/G = new (loc, 2) G.add_fingerprint(user) if(istype(P, /obj/item/weapon/screwdriver)) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 47f4870e719..f4e41af1fd2 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -34,7 +34,7 @@ if(!(pod1.occupant || pod1.mess) && (pod1.efficiency > 5)) for(var/datum/data/record/R in records) if(!(pod1.occupant || pod1.mess)) - if(pod1.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"])) + if(pod1.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["mrace"], R.fields["mcolor"])) records -= R /obj/machinery/computer/cloning/proc/updatemodules() @@ -328,7 +328,7 @@ temp = "Clonepod malfunction." else if(!config.revival_cloning) temp = "Unable to initiate cloning cycle." - else if(pod1.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"])) + else if(pod1.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["mrace"], C.fields["mcolor"])) temp = "[C.fields["name"]] => Cloning cycle in progress..." records.Remove(C) if(active_record == C) @@ -368,10 +368,10 @@ return var/datum/data/record/R = new() - if(subject.dna) - R.fields["mrace"] = subject.dna.mutantrace + if(subject.dna.species) + R.fields["mrace"] = subject.dna.species.type else - R.fields["mrace"] = null + R.fields["mrace"] = /datum/species/human R.fields["ckey"] = subject.ckey R.fields["name"] = subject.real_name R.fields["id"] = copytext(md5(subject.real_name), 2, 6) @@ -379,6 +379,7 @@ R.fields["UI"] = subject.dna.uni_identity R.fields["SE"] = subject.dna.struc_enzymes R.fields["blood_type"] = subject.dna.blood_type + R.fields["mcolor"] = subject.dna.mutant_color //Add an implant if needed var/obj/item/weapon/implant/health/imp = locate(/obj/item/weapon/implant/health, subject) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 4c5148c3dc8..7ab878e4c54 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -355,9 +355,9 @@ var/const/CALL_SHUTTLE_REASON_LENGTH = 12 if (src.authenticated) if(emergency_shuttle.recall_count > 1) if(emergency_shuttle.last_call_loc) - dat += "
Latest emergency signal trace attempt successful.
Last signal origin: [format_text(emergency_shuttle.last_call_loc.name)].
" + dat += "
Last emergency shuttle call/recall traced to: [format_text(emergency_shuttle.last_call_loc.name)].
" else - dat += "
Latest emergency signal trace attempt failed.
" + dat += "
Last emergency shuttle call/recall trace failed.
" dat += "Logged in as: [auth_id]" dat += "
\[ Log Out \]
" dat += "
General Functions" diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index f33beedab30..f5a285e8290 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -55,16 +55,18 @@ if(1) if(istype(P, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = P - if(C.amount >= 5) + if(C.get_amount() >= 5) playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) user << "You start to add cables to the frame." if(do_after(user, 20)) - if(C) - C.amount -= 5 - if(!C.amount) qdel(C) + if(C.get_amount() >= 5 && state == 1) + C.use(5) user << "You add cables to the frame." state = 2 icon_state = "box_1" + else + user << "You need five length of cable to wire the frame." + return if(istype(P, /obj/item/weapon/wrench)) playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1) user << "You dismantle the frame." @@ -138,6 +140,9 @@ success=1 if(istype(P, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/CP = P + if (CP.get_amount() < 1) + user << "You need more cable!" + return var/obj/item/stack/cable_coil/CC = new /obj/item/stack/cable_coil(src, 1, CP.item_color) if(CP.use(1)) components += CC diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index fe8e972b78a..e8d184b4b88 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1024,6 +1024,8 @@ About the new airlock wires panel: playsound(src.loc, 'sound/machines/airlock.ogg', 30, 1) if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) src.closeOther.close() + else + playsound(src.loc, 'sound/machines/airlockforced.ogg', 30, 1) if(autoclose && normalspeed) spawn(150) @@ -1060,6 +1062,9 @@ About the new airlock wires panel: playsound(src.loc, 'sound/items/bikehorn.ogg', 30, 1) else playsound(src.loc, 'sound/machines/airlock.ogg', 30, 1) + else + playsound(src.loc, 'sound/machines/airlockforced.ogg', 30, 1) + var/obj/structure/window/killthis = (locate(/obj/structure/window) in get_turf(src)) if(killthis) killthis.ex_act(2)//Smashin windows diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 7747da62bc7..e52421b06be 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -653,16 +653,12 @@ if(1) if(istype(I, /obj/item/stack/sheet/metal)) var/obj/item/stack/sheet/metal/M = I - if(M.amount>=2) //requires 2 metal sheets + if(M.use(2)) user << "You add some metal armor to the interior frame." build_step = 2 - M.amount -= 2 icon_state = "turret_frame2" - if(M.amount <= 0) - user.unEquip(M, 1) //We're deleting it anyway, so no point in having NODROP fuck shit up. - qdel(M) else - user << "You need two sheets of metal for that." + user << "You need two sheets of metal to continue construction." return else if(istype(I, /obj/item/weapon/wrench)) @@ -743,15 +739,11 @@ if(6) if(istype(I, /obj/item/stack/sheet/metal)) var/obj/item/stack/sheet/metal/M = I - if(M.amount>=2) + if(M.use(2)) user << "You add some metal armor to the exterior frame." build_step = 7 - M.amount -= 2 - if(M.amount <= 0) - user.unEquip(M, 1) //If we don't force-unequip, bugs happen because the item was deleted without updating the neccesary stuffs. - qdel(M) else - user << "You need two sheets of metal for that." + user << "You need two sheets of metal to continue construction." return else if(istype(I, /obj/item/weapon/screwdriver)) diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index f3c06c9424d..522483a63be 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -155,20 +155,19 @@ /obj/machinery/recharge_station/proc/restock_modules() if(occupier) if(occupier.module && occupier.module.modules) - var/list/um = occupier.contents|occupier.module.modules - // ^ makes sinle list of active (occupier.contents) and inactive modules (occupier.module.modules) + var/list/um = occupier.contents|occupier.module.modules // Makes single list of active (occupier.contents) and inactive (occupier.module.modules) modules var/coeff = recharge_speed / 200 + for (var/datum/robot_energy_storage/st in occupier.module.storages) + st.energy = min(st.max_energy, st.energy + coeff * st.recharge_rate) for(var/obj/O in um) - // Engineering - if(istype(O,/obj/item/stack/sheet/metal) || istype(O,/obj/item/stack/sheet/rglass) || istype(O,/obj/item/stack/rods) || istype(O,/obj/item/stack/cable_coil)|| istype(O,/obj/item/stack/tile/plasteel)) - if(O:amount < 50) - O:amount += coeff - // Security + //General if(istype(O,/obj/item/device/flash)) if(O:broken) O:broken = 0 O:times_used = 0 O:icon_state = "flash" + // Engineering + // Security if(istype(O,/obj/item/weapon/gun/energy/taser/cyborg)) if(O:power_supply.charge < O:power_supply.maxcharge) var/obj/item/weapon/gun/energy/G = O diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index d3e32c02081..796f8dcc729 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -247,14 +247,17 @@ else if(istype(W, /obj/item/stack/cable_coil) && malfunction && is_open) var/obj/item/stack/cable_coil/coil = W - user << "\blue You begin to replace the wires." - //if(do_after(user, min(60, round( ((maxhealth/health)*10)+(malfunction*10) ))) //Take longer to repair heavier damage + if (coil.get_amount() < 1) + user << "You need one length of cable to repair [src]." + return + user << "You begin to replace the wires." if(do_after(user, 30)) - if(!src || !coil) return + if(coil.get_amount() < 1) + return coil.use(1) health = max_health malfunction = 0 - user << "\blue You repair the [src]!" + user << "You repair the [src]!" update_icon() else if(istype(W, /obj/item/weapon/wrench)) diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index 9f85aa337b6..ed0b5bf6e4a 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -109,7 +109,7 @@ index2 -= message2_len update_display(line1, line2) if(4) // supply shuttle timer - var/line1 = "SUPPLY" + var/line1 = "CARGO" var/line2 if(supply_shuttle.moving) line2 = get_supply_shuttle_timer() diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index 4098ed938c8..f3d1796d3a2 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -56,7 +56,7 @@ construct_op -- stat &= ~BROKEN // the machine's not borked anymore! else - user << "You need more cable to do that." + user << "You need five lengths of cable for this machine." if(istype(P, /obj/item/weapon/crowbar)) user << "You begin prying out the circuit board and components..." playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index b2386d2b4f4..df07d30f159 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -247,11 +247,10 @@ if(prob(30 - (accurate * 10))) //oh dear a problem if(ishuman(M))//don't remove people from the round randomly you jerks var/mob/living/carbon/human/human = M - if(human.dna && !human.dna.mutantrace) + if(human.dna && human.dna.species.id == "human") M << "You hear a buzzing in your ears." - human.dna.mutantrace = "fly" - human.update_body() - human.update_hair() + human.dna.species = new /datum/species/fly() + human.regenerate_icons() human.apply_effect((rand(120 - accurate * 40, 180 - accurate * 60)), IRRADIATE, 0) return diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index e02188a5fb3..50da8e4965b 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -646,7 +646,7 @@ product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs." vend_delay = 34 icon_state = "cigs" - products = list(/obj/item/weapon/storage/fancy/cigarettes = 10,/obj/item/weapon/storage/box/matches = 10,/obj/item/weapon/lighter/random = 4,/obj/item/weapon/rollingpaperpack = 5) + products = list(/obj/item/weapon/storage/fancy/cigarettes = 10,/obj/item/weapon/storage/box/matches = 10,/obj/item/weapon/lighter/random = 4,/obj/item/weapon/storage/fancy/rollingpapers = 5) contraband = list(/obj/item/weapon/lighter/zippo = 4) premium = list(/obj/item/clothing/mask/cigarette/cigar/havana = 2) refill_canister = /obj/item/weapon/vending_refill/cigarette diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index 26bd773e80b..a8c3c48f01e 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -112,10 +112,10 @@ ore.Move(ore_box) else if(target.loc == C) log_message("Drilled through [target]") - if(ismob(target)) - var/mob/M = target - add_logs(chassis.occupant, M, "attacked", object="[name]", addition="(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])") - target.ex_act(2) + if(isliving(target)) + drill_mob(target, chassis.occupant) + else + target.ex_act(2) return 1 can_attach(obj/mecha/M as obj) @@ -124,6 +124,20 @@ return 1 return 0 +/obj/item/mecha_parts/mecha_equipment/tool/drill/proc/drill_mob(mob/living/target, mob/user, var/drill_damage=80) + target.visible_message("[chassis] drills [target] with the [src].\ + [chassis] drills [target] with the [src].") + add_logs(user, target, "attacked", object="[name]", addition="(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") + if(ishuman(target)) + var/mob/living/carbon/human/H = target + var/obj/item/organ/limb/affecting = H.get_organ("chest") + affecting.take_damage(drill_damage) + H.update_damage_overlays(0) + else + target.take_organ_damage(drill_damage) + target.Paralyse(10) + target.updatehealth() + /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill name = "diamond-tipped exosuit drill" desc = "Equipment for engineering and combat exosuits. This is an upgraded version of the drill that'll pierce the heavens!" @@ -172,10 +186,10 @@ ore.Move(ore_box) else if(target.loc == C) log_message("Drilled through [target]") - if(ismob(target)) - var/mob/M = target - add_logs(chassis.occupant, M, "attacked", object="[name]", addition="(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])") - target.ex_act(2) + if(isliving(target)) + drill_mob(target, chassis.occupant, 120) + else + target.ex_act(2) return 1 can_attach(obj/mecha/M as obj) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index df02cb26e81..00a96eafcd6 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -703,12 +703,11 @@ else if(istype(W, /obj/item/stack/cable_coil)) if(state == 3 && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) var/obj/item/stack/cable_coil/CC = W - if(CC.amount > 1) - CC.use(2) + if(CC.use(2)) clearInternalDamage(MECHA_INT_SHORT_CIRCUIT) - user << "You replace the fused wires." + user << "You replace the fused wires." else - user << "There's not enough wire to finish the task." + user << "You need two lengths of cable to fix this mecha." return else if(istype(W, /obj/item/weapon/screwdriver)) if(hasInternalDamage(MECHA_INT_TEMP_CONTROL)) @@ -933,50 +932,40 @@ return -/obj/mecha/verb/move_inside() - set category = "Object" - set name = "Enter Exosuit" - set src in oview(1) - - if (usr.stat || !ishuman(usr) || usr.restrained() || !usr.Adjacent(src)) +/obj/mecha/MouseDrop_T(mob/M as mob, mob/user as mob) + if (!user.canUseTopic(src) || (user != M)) return - src.log_message("[usr] tries to move in.") + src.log_message("[user] tries to move in.") if (src.occupant) - usr << "\blue The [src.name] is already occupied!" + usr << "The [src.name] is already occupied!" src.log_append_to_last("Permission denied.") return -/* - if (usr.abiotic()) - usr << "\blue Subject cannot have abiotic items on." - return -*/ var/passed if(src.dna) - if(check_dna_integrity(usr)) - var/mob/living/carbon/C = usr + if(check_dna_integrity(user)) + var/mob/living/carbon/C = user if(C.dna.unique_enzymes==src.dna) passed = 1 - else if(src.operation_allowed(usr)) + else if(src.operation_allowed(user)) passed = 1 if(!passed) - usr << "\red Access denied" + user << "Access denied." src.log_append_to_last("Permission denied.") return - for(var/mob/living/carbon/slime/M in range(1,usr)) - if(M.Victim == usr) - usr << "You're too busy getting your life sucked out of you." + for(var/mob/living/carbon/slime/S in range(1,user)) + if(S.Victim == user) + user << "You're too busy getting your life sucked out of you." return -// usr << "You start climbing into [src.name]" - visible_message("\blue [usr] starts to climb into [src.name]") + visible_message("[user] starts to climb into [src.name]") - if(enter_after(40,usr)) + if(enter_after(40,user)) if(!src.occupant) - moved_inside(usr) - else if(src.occupant!=usr) - usr << "[src.occupant] was faster. Try better next time, loser." + moved_inside(user) + else if(src.occupant!=user) + user << "[src.occupant] was faster. Try better next time, loser." else - usr << "You stop entering the exosuit." + user << "You stop entering the exosuit." return /obj/mecha/proc/moved_inside(var/mob/living/carbon/human/H as mob) diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm index 24a42e5f774..96f233152ef 100644 --- a/code/game/mecha/mecha_construction_paths.dm +++ b/code/game/mecha/mecha_construction_paths.dm @@ -20,12 +20,11 @@ else if(istype(used_atom, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = used_atom - if(C.amount<4) + if(C.use(4)) + playsound(holder, 'sound/items/Deconstruct.ogg', 50, 1) + else user << ("There's not enough cable to finish the task.") return 0 - else - C.use(4) - playsound(holder, 'sound/items/Deconstruct.ogg', 50, 1) else if(istype(used_atom, /obj/item/stack)) var/obj/item/stack/S = used_atom if(S.amount < 5) @@ -53,12 +52,11 @@ else if(istype(used_atom, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = used_atom - if(C.amount<4) + if (C.use(4)) + playsound(holder, 'sound/items/Deconstruct.ogg', 50, 1) + else user << ("There's not enough cable to finish the task.") return 0 - else - C.use(4) - playsound(holder, 'sound/items/Deconstruct.ogg', 50, 1) else if(istype(used_atom, /obj/item/stack)) var/obj/item/stack/S = used_atom if(S.amount < 5) diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index b5b4b4f7f5a..8dd8ad4263b 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -582,6 +582,7 @@ steam.start() -- spawns the effect icon = 'icons/effects/96x96.dmi' pixel_x = -32 pixel_y = -32 + color = "#9C3636" /obj/effect/effect/sleep_smoke/New() ..() @@ -596,7 +597,7 @@ steam.start() -- spawns the effect // if (M.wear_suit, /obj/item/clothing/suit/wizrobe && (M.hat, /obj/item/clothing/head/wizard) && (M.shoes, /obj/item/clothing/shoes/sandal)) // I'll work on it later else M.drop_item() - M:sleeping += 1 + M:sleeping += 5 if (M.coughedtime != 1) M.coughedtime = 1 M.emote("cough") @@ -612,7 +613,7 @@ steam.start() -- spawns the effect return else M.drop_item() - M:sleeping += 1 + M:sleeping += 5 if (M.coughedtime != 1) M.coughedtime = 1 M.emote("cough") diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index ff296e1dfec..cbf87e7b1c2 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -32,6 +32,8 @@ var/obj/item/device/uplink/hidden/hidden_uplink = null // All items can have an uplink hidden inside, just remember to add the triggers. var/reflect_chance = 0 //This var dictates what % of a time an object will reflect an energy based weapon's shot + var/list/species_exception = list() // even if a species cannot put items in a certain slot, if the species id is in the item's exception list, it will be able to wear that item + /obj/item/device icon = 'icons/obj/device.dmi' diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 3910f798064..4e0804e76cf 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -81,10 +81,10 @@ if(user.has_mutation(HULK)) user << "Your meaty finger is too large for the button!" return - if(iscarbon(user)) - var/mob/living/carbon/C = user - if(C.is_mutantrace("adamantine")) - user << "Your metal fingers can't press the button!" + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.dna && NOGUNS in H.dna.species.specflags) + user << "Your fingers can't press the button!" return add_fingerprint(user) diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index 9c6dbbdb37c..2b844aaa029 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -78,18 +78,15 @@ if(istype(W, /obj/item/stack/sheet/glass)) var/obj/item/stack/sheet/glass/G = W - if(G.amount - decrement >= 0 && uses < max_uses) - var/remaining = max(G.amount - decrement, 0) - if(!remaining && !(G.amount - decrement) == 0) - user << "There isn't enough glass." - return - G.amount = remaining - if(!G.amount) - user.drop_item() - qdel(G) - AddUses(increment) - user << "You insert a piece of glass into the [src.name]. You have [uses] lights remaining." + if(uses >= max_uses) + user << "span class='warning'>[src.name] is full." return + else if(G.use(decrement)) + AddUses(increment) + user << "You insert a piece of glass into the [src.name]. You have [uses] lights remaining." + return + else + user << "You need one sheet of glass to replace lights." if(istype(W, /obj/item/weapon/light)) var/obj/item/weapon/light/L = W diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 996ce6ff0b1..8d25a62be7e 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -78,16 +78,16 @@ MASS SPECTROMETER // Clumsiness/brain damage check if ((CLUMSY in user.mutations || user.getBrainLoss() >= 60) && prob(50)) - user << text("You stupidly try to analyze the floor's vitals!") - user.visible_message(text("[user] has analyzed the floor's vitals!")) - user.show_message(text("Analyzing Results for The floor:\n\t Overall Status: Healthy"), 1) - user.show_message(text("\t Damage Specifics: 0-0-0-0"), 1) + user << "You stupidly try to analyze the floor's vitals!" + user.visible_message("[user] has analyzed the floor's vitals!") + user.show_message("Analyzing Results for The floor:\n\t Overall Status: Healthy", 1) + user.show_message("\t Damage Specifics: 0-0-0-0", 1) user.show_message("Key: Suffocation/Toxin/Burn/Brute", 1) user.show_message("Body Temperature: ???", 1) return - user.visible_message(text("[] has analyzed []'s vitals!", user, M)) + user.visible_message("[user] has analyzed [M]'s vitals.") healthscan(user, M, mode) @@ -102,21 +102,26 @@ MASS SPECTROMETER var/tox_loss = M.getToxLoss() var/fire_loss = M.getFireLoss() var/brute_loss = M.getBruteLoss() - var/mob_status = (M.stat > 1 ? "Deceased" : text("[]% healthy", M.health)) + var/mob_status = (M.stat > 1 ? "Deceased" : "[M.health]% healthy") if(M.status_flags & FAKEDEATH) mob_status = "Deceased" oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss user.show_message(text("Analyzing Results for []:\n\t Overall Status: []", M, mob_status), 1) - user.show_message(text("\t Damage Specifics: []-[]-[]-[]", oxy_loss, tox_loss, fire_loss, brute_loss), 1) - + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.dna)// Show target's species, if they have one + user.show_message("Species: [H.dna.species.name]", 1) + else // Otherwise we can assume that they are a regular human + user.show_message("Species: Human", 1) + user.show_message("\t Damage Specifics: [oxy_loss]-[tox_loss]-[fire_loss]-[brute_loss]", 1) user.show_message("Key: Suffocation/Toxin/Burn/Brute", 1) user.show_message("Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1) // Time of death if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH))) - user.show_message("Time of Death: [M.tod]") + user.show_message("Time of Death: [M.tod]", 1) // Organ damage report if(istype(M, /mob/living/carbon/human) && mode == 1) @@ -131,26 +136,26 @@ MASS SPECTROMETER // Damage descriptions - user.show_message(text("[] | [] | [] | []", oxy_loss > 50 ? "\red Severe oxygen deprivation detected\blue" : "Subject bloodstream oxygen level normal", tox_loss > 50 ? "\red Dangerous amount of toxins detected\blue" : "Subject bloodstream toxin level minimal", fire_loss > 50 ? "\red Severe burn damage detected\blue" : "Subject burn injury status O.K", brute_loss > 50 ? "\red Severe anatomical damage detected\blue" : "Subject brute-force injury status O.K"), 1) + user.show_message(text("[] | [] | [] | []", oxy_loss > 50 ? " Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal", tox_loss > 50 ? " Dangerous amount of toxins detected" : "Subject bloodstream toxin level minimal", fire_loss > 50 ? " Severe burn damage detected" : "Subject burn injury status O.K", brute_loss > 50 ? " Severe anatomical damage detected" : "Subject brute-force injury status O.K"), 1) if(M.getStaminaLoss()) - user.show_message(text("Subject appears to be suffering from fatigue."), 1) + user.show_message("Subject appears to be suffering from fatigue.", 1) if (M.getCloneLoss()) - user.show_message(text("Subject appears to have been imperfectly cloned."), 1) + user.show_message("Subject appears to have been imperfectly cloned.", 1) for(var/datum/disease/D in M.viruses) if(!D.hidden[SCANNER]) - user.show_message(text("Warning: [D.form] Detected\nName: [D.name].\nType: [D.spread].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure]")) + user.show_message("Warning: [D.form] Detected\nName: [D.name].\nType: [D.spread].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure]", 1) if (M.reagents && M.reagents.get_reagent_amount("inaprovaline")) - user.show_message(text("Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals."), 1) + user.show_message("Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals.", 1) if (M.getBrainLoss() >= 100 || !M.getorgan(/obj/item/organ/brain)) - user.show_message(text("Subject brain function is non-existant."), 1) + user.show_message("Subject brain function is non-existant.", 1) else if (M.getBrainLoss() >= 60) - user.show_message(text("Severe brain damage detected. Subject likely to have mental retardation."), 1) + user.show_message("Severe brain damage detected. Subject likely to have mental retardation.", 1) else if (M.getBrainLoss() >= 10) - user.show_message(text("Significant brain damage detected. Subject may have had a concussion."), 1) + user.show_message("Significant brain damage detected. Subject may have had a concussion.", 1) /obj/item/device/healthanalyzer/verb/toggle_mode() set name = "Switch Verbosity" @@ -193,11 +198,11 @@ MASS SPECTROMETER var/pressure = environment.return_pressure() var/total_moles = environment.total_moles() - user.show_message("\blue Results:", 1) + user.show_message(" Results:", 1) if(abs(pressure - ONE_ATMOSPHERE) < 10) - user.show_message("\blue Pressure: [round(pressure,0.1)] kPa", 1) + user.show_message(" Pressure: [round(pressure,0.1)] kPa", 1) else - user.show_message("\red Pressure: [round(pressure,0.1)] kPa", 1) + user.show_message(" Pressure: [round(pressure,0.1)] kPa", 1) if(total_moles) var/o2_concentration = environment.oxygen/total_moles var/n2_concentration = environment.nitrogen/total_moles @@ -206,27 +211,27 @@ MASS SPECTROMETER var/unknown_concentration = 1-(o2_concentration+n2_concentration+co2_concentration+plasma_concentration) if(abs(n2_concentration - N2STANDARD) < 20) - user.show_message("\blue Nitrogen: [round(n2_concentration*100)]%", 1) + user.show_message(" Nitrogen: [round(n2_concentration*100)]%", 1) else - user.show_message("\red Nitrogen: [round(n2_concentration*100)]%", 1) + user.show_message(" Nitrogen: [round(n2_concentration*100)]%", 1) if(abs(o2_concentration - O2STANDARD) < 2) - user.show_message("\blue Oxygen: [round(o2_concentration*100)]%", 1) + user.show_message(" Oxygen: [round(o2_concentration*100)]%", 1) else - user.show_message("\red Oxygen: [round(o2_concentration*100)]%", 1) + user.show_message(" Oxygen: [round(o2_concentration*100)]%", 1) if(co2_concentration > 0.01) - user.show_message("\red CO2: [round(co2_concentration*100)]%", 1) + user.show_message(" CO2: [round(co2_concentration*100)]%", 1) else - user.show_message("\blue CO2: [round(co2_concentration*100)]%", 1) + user.show_message(" CO2: [round(co2_concentration*100)]%", 1) if(plasma_concentration > 0.01) - user.show_message("\red Plasma: [round(plasma_concentration*100)]%", 1) + user.show_message(" Plasma: [round(plasma_concentration*100)]%", 1) if(unknown_concentration > 0.01) - user.show_message("\red Unknown: [round(unknown_concentration*100)]%", 1) + user.show_message(" Unknown: [round(unknown_concentration*100)]%", 1) - user.show_message("\blue Temperature: [round(environment.temperature-T0C)]°C", 1) + user.show_message(" Temperature: [round(environment.temperature-T0C)]°C", 1) src.add_fingerprint(user) return @@ -262,17 +267,17 @@ MASS SPECTROMETER if (user.stat) return if (crit_fail) - user << "\red This device has critically failed and is no longer functional!" + user << " This device has critically failed and is no longer functional!" return if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") - user << "\red You don't have the dexterity to do this!" + user << " You don't have the dexterity to do this!" return if(reagents.total_volume) var/list/blood_traces = list() for(var/datum/reagent/R in reagents.reagent_list) if(R.id != "blood") reagents.clear_reagents() - user << "\red The sample was contaminated! Please insert another sample" + user.show_message(" The sample was contaminated! Please insert another sample.", 1) return else blood_traces = params2list(R.data["trace_chem"]) @@ -317,31 +322,31 @@ MASS SPECTROMETER /obj/item/device/slime_scanner/attack(mob/living/M as mob, mob/living/user as mob) if (!isslime(M)) - user << "This device can only scan slimes!" + user.show_message("This device can only scan slimes!", 1) return var/mob/living/carbon/slime/T = M - user.show_message("Slime scan results:") - user.show_message(text("[T.colour] [] slime", T.is_adult ? "adult" : "baby")) - user.show_message(text("Nutrition: [T.nutrition]/[]", T.get_max_nutrition())) + user.show_message("Slime scan results:", 1) + user.show_message(text("[T.colour] [] slime", T.is_adult ? "adult" : "baby"), 1) + user.show_message(text("Nutrition: [T.nutrition]/[]", T.get_max_nutrition()), 1) if (T.nutrition < T.get_starve_nutrition()) - user.show_message("Warning: slime is starving!") + user.show_message("Warning: slime is starving!", 1) else if (T.nutrition < T.get_hunger_nutrition()) - user.show_message("Warning: slime is hungry") - user.show_message("Electric change strength: [T.powerlevel]") - user.show_message("Health: [T.health]") + user.show_message("Warning: slime is hungry", 1) + user.show_message("Electric change strength: [T.powerlevel]", 1) + user.show_message("Health: [T.health]", 1) if (T.slime_mutation[4] == T.colour) - user.show_message("This slime does not evolve any further") + user.show_message("This slime does not evolve any further.", 1) else if (T.slime_mutation[3] == T.slime_mutation[4]) if (T.slime_mutation[2] == T.slime_mutation[1]) - user.show_message(text("Possible mutation: []", T.slime_mutation[3])) - user.show_message("Genetic destability: [T.mutation_chance/2]% chance of mutation on splitting") + user.show_message("Possible mutation: [T.slime_mutation[3]]", 1) + user.show_message("Genetic destability: [T.mutation_chance/2]% chance of mutation on splitting", 1) else - user.show_message(text("Possible mutations: [], [], [] (x2)", T.slime_mutation[1], T.slime_mutation[2], T.slime_mutation[3])) - user.show_message("Genetic destability: [T.mutation_chance]% chance of mutation on splitting") + user.show_message("Possible mutations: [T.slime_mutation[1]], [T.slime_mutation[2]], [T.slime_mutation[3]] (x2)", 1) + user.show_message("Genetic destability: [T.mutation_chance]% chance of mutation on splitting", 1) else - user.show_message(text("Possible mutations: [], [], [], []", T.slime_mutation[1], T.slime_mutation[2], T.slime_mutation[3], T.slime_mutation[4])) - user.show_message("Genetic destability: [T.mutation_chance]% chance of mutation on splitting") + user.show_message("Possible mutations: [T.slime_mutation[1]], [T.slime_mutation[2]], [T.slime_mutation[3]], [T.slime_mutation[4]]", 1) + user.show_message("Genetic destability: [T.mutation_chance]% chance of mutation on splitting", 1) if (T.cores > 1) - user.show_message("Anomalious slime core amount detected") - user.show_message("Growth progress: [T.amount_grown]/10") \ No newline at end of file + user.show_message("Anomalious slime core amount detected", 1) + user.show_message("Growth progress: [T.amount_grown]/10", 1) diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index 5173e9842e3..f88936e66d9 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -104,14 +104,18 @@ /obj/item/robot_parts/robot_suit/attackby(obj/item/W as obj, mob/user as mob) ..() if(istype(W, /obj/item/stack/sheet/metal) && !l_arm && !r_arm && !l_leg && !r_leg && !chest && !head) - var/obj/item/weapon/ed209_assembly/B = new /obj/item/weapon/ed209_assembly - B.loc = get_turf(src) - user << "You armed the robot frame" - W:use(1) - if (user.get_inactive_hand()==src) - user.unEquip(src) - user.put_in_inactive_hand(B) - qdel(src) + var/obj/item/stack/sheet/metal/M = W + if (M.use(1)) + var/obj/item/weapon/ed209_assembly/B = new /obj/item/weapon/ed209_assembly + B.loc = get_turf(src) + user << "You armed the robot frame." + if (user.get_inactive_hand()==src) + user.unEquip(src) + user.put_in_inactive_hand(B) + qdel(src) + else + user << "You need one sheet of metal to start building ED-209." + return if(istype(W, /obj/item/robot_parts/l_leg)) if(src.l_leg) return user.drop_item() @@ -313,13 +317,14 @@ user << "\blue You insert the cell!" if(istype(W, /obj/item/stack/cable_coil)) if(src.wires) - user << "\blue You have already inserted wire!" + user << "You have already inserted wire." return - else - var/obj/item/stack/cable_coil/coil = W - coil.use(1) + var/obj/item/stack/cable_coil/coil = W + if (coil.use(1)) src.wires = 1.0 - user << "\blue You insert the wire!" + user << "You insert the wire." + else + user << "You need one length of coil to wire it." return /obj/item/robot_parts/head/attackby(obj/item/W as obj, mob/user as mob) diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 47d017a5c22..ac5c1cbca99 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -19,7 +19,7 @@ if (istype(W, /obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = W - if(amount < 2) + if(get_amount() < 2) user << "\red You need at least two rods to do this." return @@ -54,7 +54,7 @@ else return 1 else - if(amount < 2) + if(get_amount() < 2) user << "\blue You need at least two rods to do this." return usr << "\blue Assembling grille..." @@ -68,3 +68,5 @@ /obj/item/stack/rods/cyborg/ m_amt = 0 + is_cyborg = 1 + cost = 250 \ No newline at end of file diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 299677c2a17..1e3e9157602 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -16,6 +16,10 @@ g_amt = MINERAL_MATERIAL_AMOUNT origin_tech = "materials=1" +/obj/item/stack/sheet/glass/cyborg + g_amt = 0 + is_cyborg = 1 + cost = 500 /obj/item/stack/sheet/glass/attack_self(mob/user as mob) construct_window(user) @@ -23,28 +27,32 @@ /obj/item/stack/sheet/glass/attackby(obj/item/W, mob/user) ..() add_fingerprint(user) - if(istype(W,/obj/item/stack/cable_coil)) + if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/CC = W - if(CC.amount < 5) - user << "\b There is not enough wire in this coil. You need 5 lengths." + if (get_amount() < 1 || CC.get_amount() < 5) + user << "You attach wire to the [name]." var/obj/item/stack/light_w/new_tile = new(user.loc) new_tile.add_fingerprint(user) - src.use(1) - else if( istype(W, /obj/item/stack/rods) ) - var/obj/item/stack/rods/V = W - var/obj/item/stack/sheet/rglass/RG = new (user.loc) - RG.add_fingerprint(user) - RG.add_to_stacks(user) - V.use(1) - var/obj/item/stack/sheet/glass/G = src - src = null - var/replace = (user.get_inactive_hand()==G) - G.use(1) - if (!G && !RG && replace) - user.put_in_hands(RG) + else if(istype(W, /obj/item/stack/rods)) + var/obj/item/stack/rods/V = W + if (V.get_amount() >= 1 && src.get_amount() >= 1) + var/obj/item/stack/sheet/rglass/RG = new (user.loc) + RG.add_fingerprint(user) + RG.add_to_stacks(user) + var/obj/item/stack/sheet/glass/G = src + src = null + var/replace = (user.get_inactive_hand()==G) + V.use(1) + G.use(1) + if (!G && replace) + user.put_in_hands(RG) + else + user << "You need one rod and one sheet of glass to make reinforced glass." + return else return ..() @@ -55,7 +63,7 @@ user << "\red You don't have the dexterity to do this!" return 0 var/title = "Sheet-Glass" - title += " ([src.amount] sheet\s left)" + title += " ([src.get_amount()] sheet\s left)" switch(alert(title, "Would you like full tile glass or one direction?", "One Direction", "Full Window", "Cancel", null)) if("One Direction") if(!src) return 1 @@ -95,7 +103,7 @@ if("Full Window") if(!src) return 1 if(src.loc != user) return 1 - if(src.amount < 2) + if(src.get_amount() < 2) user << "\red You need more glass to do that." return 1 if(locate(/obj/structure/window) in user.loc) @@ -121,16 +129,29 @@ singular_name = "reinforced glass sheet" icon_state = "sheet-rglass" g_amt = MINERAL_MATERIAL_AMOUNT - m_amt = 1000 + m_amt = MINERAL_MATERIAL_AMOUNT / 2 origin_tech = "materials=2" /obj/item/stack/sheet/rglass/cyborg - name = "reinforced glass" - desc = "Glass which seems to have rods or something stuck in them." - singular_name = "reinforced glass sheet" - icon_state = "sheet-rglass" g_amt = 0 m_amt = 0 + var/datum/robot_energy_storage/metsource + var/datum/robot_energy_storage/glasource + var/metcost = 250 + var/glacost = 500 + +/obj/item/stack/sheet/rglass/cyborg/get_amount() + return min(round(metsource.energy / metcost), round(glasource.energy / glacost)) + +/obj/item/stack/sheet/rglass/cyborg/use(var/amount) // Requires special checks, because it uses two storages + metsource.use_charge(amount * metcost) + glasource.use_charge(amount * glacost) + return + +/obj/item/stack/sheet/rglass/cyborg/add(var/amount) + metsource.add_charge(amount * metcost) + glasource.add_charge(amount * glacost) + return /obj/item/stack/sheet/rglass/attack_self(mob/user as mob) construct_window(user) @@ -142,7 +163,7 @@ user << "\red You don't have the dexterity to do this!" return 0 var/title = "Sheet Reinf. Glass" - title += " ([src.amount] sheet\s left)" + title += " ([src.get_amount()] sheet\s left)" switch(input(title, "Would you like full tile glass a one direction glass pane or a windoor?") in list("One Direction", "Full Window", "Windoor", "Cancel")) if("One Direction") if(!src) return 1 @@ -182,7 +203,7 @@ if("Full Window") if(!src) return 1 if(src.loc != user) return 1 - if(src.amount < 2) + if(src.get_amount() < 2) user << "You need more glass to do that." return 1 if(locate(/obj/structure/window) in user.loc) @@ -208,7 +229,7 @@ user << "There is already a windoor in that location." return 1 - if(src.amount < 5) + if(src.get_amount() < 5) user << "You need more glass to do that." return 1 diff --git a/code/game/objects/items/stacks/sheets/light.dm b/code/game/objects/items/stacks/sheets/light.dm index e00fe5da5e5..00bc8110c1c 100644 --- a/code/game/objects/items/stacks/sheets/light.dm +++ b/code/game/objects/items/stacks/sheets/light.dm @@ -24,15 +24,13 @@ user.unEquip(src, 1) qdel(src) - if(istype(O,/obj/item/stack/sheet/metal)) + if(istype(O, /obj/item/stack/sheet/metal)) var/obj/item/stack/sheet/metal/M = O - M.amount-- - if(M.amount <= 0) - user.unEquip(M, 1) - qdel(M) - amount-- - var/obj/item/stack/tile/light/L = new (user.loc) - L.add_fingerprint(user) - if(amount <= 0) - user.unEquip(src, 1) - qdel(src) + if (M.use(1)) + use(1) + var/obj/item/stack/tile/light/L = new (user.loc) + user << "You make a light tile." + L.add_fingerprint(user) + else + user << "You need one metal sheet to finish the light tile." + return diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 774f723db8f..8951c278576 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -55,6 +55,8 @@ var/global/list/datum/stack_recipe/metal_recipes = list ( \ /obj/item/stack/sheet/metal/cyborg m_amt = 0 + is_cyborg = 1 + cost = 500 /obj/item/stack/sheet/metal/New(var/loc, var/amount=null) recipes = metal_recipes diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index f622413ce9c..2630ca27570 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -14,14 +14,19 @@ var/singular_name var/amount = 1 var/max_amount //also see stack recipes initialisation, param "max_res_amount" must be equal to this max_amount + var/is_cyborg = 0 // It's 1 if module is used by a cyborg, and uses its storage + var/datum/robot_energy_storage/source + var/cost = 1 // How much energy from storage it costs /obj/item/stack/New(var/loc, var/amount=null) ..() if (amount) - src.amount=amount + src.amount = amount return /obj/item/stack/Destroy() + if (is_cyborg) + return // Not supposed to be destroyed if (usr && usr.machine==src) usr << browse(null, "window=stack") ..() @@ -29,27 +34,39 @@ /obj/item/stack/examine() set src in view(1) ..() - if(src.singular_name) - if(src.amount>1) - usr << "There are [src.amount] [src.singular_name]\s in the stack." + if (is_cyborg) + if(src.singular_name) + usr << "There is enough energy for [src.get_amount()] [src.singular_name]\s." else - usr << "There is [src.amount] [src.singular_name] in the stack." - else if(src.amount>1) - usr << "There are [src.amount] in the stack." + usr << "There is enough energy for [src.get_amount()]." + return + if(src.singular_name) + if(src.get_amount()>1) + usr << "There are [src.get_amount()] [src.singular_name]\s in the stack." + else + usr << "There is [src.get_amount()] [src.singular_name] in the stack." + else if(src.get_amount()>1) + usr << "There are [src.get_amount()] in the stack." else - usr << "There is [src.amount] in the stack." + usr << "There is [src.get_amount()] in the stack." return +/obj/item/stack/proc/get_amount() + if (is_cyborg) + return round(source.energy / cost) + else + return (amount) + /obj/item/stack/attack_self(mob/user as mob) interact(user) /obj/item/stack/interact(mob/user as mob) if (!recipes) return - if (!src || amount<=0) + if (!src || get_amount() <= 0) user << browse(null, "window=stack") user.set_machine(src) //for correct work of onclose - var/t1 = text("Constructions from []Amount Left: []
", src, src.amount) + var/t1 = text("Constructions from []Amount Left: []
", src, src.get_amount()) for(var/i=1;i<=recipes.len,i++) var/datum/stack_recipe/R = recipes[i] if (isnull(R)) @@ -57,7 +74,7 @@ continue if (i>1 && !isnull(recipes[i-1])) t1+="
" - var/max_multiplier = round(src.amount / R.req_amount) + var/max_multiplier = round(src.get_amount() / R.req_amount) var/title as text var/can_build = 1 can_build = can_build && (max_multiplier>0) @@ -97,12 +114,12 @@ if ((usr.restrained() || usr.stat || usr.get_active_hand() != src)) return if (href_list["make"]) - if (src.amount < 1) qdel(src) //Never should happen + if (src.get_amount() < 1) qdel(src) //Never should happen var/datum/stack_recipe/R = recipes[text2num(href_list["make"])] var/multiplier = text2num(href_list["multiplier"]) if (!multiplier) multiplier = 1 - if (src.amount < R.req_amount*multiplier) + if (src.get_amount() < R.req_amount*multiplier) if (R.req_amount*multiplier>1) usr << "\red You haven't got enough [src] to build \the [R.req_amount*multiplier] [R.title]\s!" else @@ -118,22 +135,17 @@ usr << "\blue Building [R.title] ..." if (!do_after(usr, R.time)) return - if (src.amount < R.req_amount*multiplier) + if (src.get_amount() < R.req_amount*multiplier) return var/atom/O = new R.result_type( usr.loc ) O.dir = usr.dir - if (R.max_res_amount>1) + if (R.max_res_amount > 1) var/obj/item/stack/new_item = O new_item.amount = R.res_amount*multiplier - //new_item.add_to_stacks(usr) - src.amount-=R.req_amount*multiplier - if (src.amount<=0) - var/oldsrc = src - src = null //dont kill proc after del() - usr.unEquip(oldsrc, 1) - qdel(oldsrc) - if (istype(O,/obj/item)) - usr.put_in_hands(O) + new_item.add_to_stacks(usr) + use(R.req_amount * multiplier) + if (istype(O,/obj/item)) + usr.put_in_hands(O) O.add_fingerprint(usr) //BubbleWrap - so newly formed boxes are empty if ( istype(O, /obj/item/weapon/storage) ) @@ -146,15 +158,23 @@ return return -/obj/item/stack/proc/use(var/amount) - src.amount-=amount - if (src.amount<=0) - var/oldsrc = src - src = null //dont kill proc after del() +/obj/item/stack/proc/use(var/used) // return 0 = borked; return 1 = had enough + if (is_cyborg) + return source.use_charge(used * cost) + if (amount < used) + return 0 + amount -= used + if (amount <= 0) if(usr) - usr.unEquip(oldsrc, 1) - qdel(oldsrc) - return + usr.unEquip(src, 1) + qdel(src) + return 1 + +/obj/item/stack/proc/add(var/amount) + if (is_cyborg) + source.add_charge(amount * cost) + else + src.amount += amount /obj/item/stack/proc/add_to_stacks(mob/usr as mob) var/obj/item/stack/oldsrc = src @@ -189,19 +209,28 @@ ..() if (istype(W, src.type)) var/obj/item/stack/S = W - if (S.amount >= max_amount) - return 1 - var/to_transfer as num - if (user.get_inactive_hand()==src) - to_transfer = 1 + if (S.is_cyborg) + var/to_transfer = min(src.amount, round((S.source.max_energy - S.source.energy) / S.cost)) + S.add(to_transfer) + if (S && usr.machine==S) + spawn(0) S.interact(usr) + src.use(to_transfer) + if (src && usr.machine==src) + spawn(0) src.interact(usr) else - to_transfer = min(src.amount, S.max_amount-S.amount) - S.amount+=to_transfer - if (S && usr.machine==S) - spawn(0) S.interact(usr) - src.use(to_transfer) - if (src && usr.machine==src) - spawn(0) src.interact(usr) + if (S.amount >= max_amount) + return 1 + var/to_transfer as num + if (user.get_inactive_hand()==src) + to_transfer = 1 + else + to_transfer = min(src.amount, S.max_amount-S.amount) + S.amount+=to_transfer + if (S && usr.machine==S) + spawn(0) S.interact(usr) + src.use(to_transfer) + if (src && usr.machine==src) + spawn(0) src.interact(usr) else return ..() /obj/item/stack/proc/copy_evidences(obj/item/stack/from as obj) diff --git a/code/game/objects/items/stacks/tiles/plasteel.dm b/code/game/objects/items/stacks/tiles/plasteel.dm index fce3db65f83..adf2e4f7257 100644 --- a/code/game/objects/items/stacks/tiles/plasteel.dm +++ b/code/game/objects/items/stacks/tiles/plasteel.dm @@ -15,7 +15,8 @@ /obj/item/stack/tile/plasteel/cyborg desc = "The ground you walk on" //Not the usual floor tile desc as that refers to throwing, Cyborgs can't do that - RR m_amt = 0 // All other Borg versions of items have no Metal or Glass - RR - max_amount = 50 + is_cyborg = 1 + cost = 125 /obj/item/stack/tile/plasteel/New(var/loc, var/amount=null) ..() @@ -28,7 +29,7 @@ if (istype(W, /obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = W - if(amount < 4) + if(get_amount() < 4) user << "\red You need at least four tiles to do this." return diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm index 6d13cdee986..446395634f4 100644 --- a/code/game/objects/items/weapons/AI_modules.dm +++ b/code/game/objects/items/weapons/AI_modules.dm @@ -279,8 +279,8 @@ AI MODULES /********************* Custom *********************/ /obj/item/weapon/aiModule/core/full/custom - name = "Custom Core AI Module" - desc = "A core AI module that is adjusted to fit each station's needs." + name = "Default Core AI Module" + desc = "A core AI module custom-made for each station by Nanotrasen." origin_tech = "programming=3;materials=4" //Should be the same as asimov, considering that this is the "default" lawset. /obj/item/weapon/aiModule/core/full/custom/New() diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index 35f0eadaa47..3b2c2381328 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -30,29 +30,44 @@ CIGARETTE PACKETS ARE IN FANCY.DM var/turf/location = get_turf(src) smoketime-- if(smoketime < 1) + matchburnout() + return + if(location) + location.hotspot_expose(700, 5) + return + +/obj/item/weapon/match/fire_act() + matchignite() + +/obj/item/weapon/match/proc/matchignite() + if(lit == 0) + lit = 1 + icon_state = "match_lit" + damtype = "fire" + force = 3 + hitsound = 'sound/items/welder.ogg' + item_state = "cigon" + name = "lit match" + desc = "A match. This one is lit." + attack_verb = list("burnt","singed") + processing_objects.Add(src) + update_icon() + return + +/obj/item/weapon/match/proc/matchburnout() + if(lit == 1) lit = -1 damtype = "brute" - force = 0 + force = initial(force) icon_state = "match_burnt" item_state = "cigoff" name = "burnt match" desc = "A match. This one has seen better days." attack_verb = null processing_objects.Remove(src) - return - if(location) - location.hotspot_expose(700, 5) - return /obj/item/weapon/match/dropped(mob/user as mob) - if(lit == 1) - lit = -1 - damtype = "brute" - icon_state = "match_burnt" - item_state = "cigoff" - name = "burnt match" - desc = "A match. This one has seen better days." - attack_verb = null + matchburnout() return ..() ////////////////// @@ -78,7 +93,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/cigarette/New() ..() flags |= NOREACT // so it doesn't react until you light it - create_reagents(chem_volume) // making the cigarrete a chemical holder with a maximum volume of 15 + create_reagents(chem_volume) // making the cigarette a chemical holder with a maximum volume of 15 /obj/item/clothing/mask/cigarette/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() @@ -120,7 +135,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM light("[user] lights their [name] with [W].") return - /obj/item/clothing/mask/cigarette/afterattack(obj/item/weapon/reagent_containers/glass/glass, mob/user as mob, proximity) if(!proximity) return if(istype(glass)) //you can dip cigarettes into beakers @@ -134,15 +148,14 @@ CIGARETTE PACKETS ARE IN FANCY.DM user << "[src] is full." -/obj/item/clothing/mask/cigarette/proc/light(var/flavor_text = "[usr] lights the [name].") +/obj/item/clothing/mask/cigarette/proc/light(var/flavor_text = null) if(!src.lit) src.lit = 1 name = "lit [name]" - if(!istype(src, /obj/item/clothing/mask/cigarette/pipe)) //can't burn people with pipes - attack_verb = list("burnt", "singed") - hitsound = 'sound/items/welder.ogg' - damtype = "fire" - force = 4 + attack_verb = list("burnt", "singed") + hitsound = 'sound/items/welder.ogg' + damtype = "fire" + force = 4 if(reagents.get_reagent_amount("plasma")) // the plasma explodes when exposed to fire var/datum/effect/effect/system/reagents_explosion/e = new() e.set_up(round(reagents.get_reagent_amount("plasma") / 2.5, 1), get_turf(src), 0, 0) @@ -165,8 +178,9 @@ CIGARETTE PACKETS ARE IN FANCY.DM reagents.handle_reactions() icon_state = icon_on item_state = icon_on - var/turf/T = get_turf(src) - T.visible_message(flavor_text) + if(flavor_text) + var/turf/T = get_turf(src) + T.visible_message(flavor_text) processing_objects.Add(src) //can't think of any other way to update the overlays :< @@ -176,6 +190,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM M.update_inv_l_hand(0) M.update_inv_r_hand(0) + /obj/item/clothing/mask/cigarette/proc/handle_reagents() if(iscarbon(loc)) var/mob/living/carbon/C = loc @@ -183,10 +198,9 @@ CIGARETTE PACKETS ARE IN FANCY.DM if(prob(15)) // so it's not an instarape in case of acid reagents.reaction(C, INGEST) reagents.trans_to(C, REAGENTS_METABOLISM) - else - reagents.remove_any(REAGENTS_METABOLISM) - else - reagents.remove_any(REAGENTS_METABOLISM) + return + reagents.remove_any(REAGENTS_METABOLISM) + /obj/item/clothing/mask/cigarette/process() var/turf/location = get_turf(src) @@ -231,6 +245,9 @@ CIGARETTE PACKETS ARE IN FANCY.DM else return ..() +/obj/item/clothing/mask/cigarette/fire_act() + light() + /obj/item/clothing/mask/cigarette/rollie name = "rollie" desc = "A roll of dried plant matter wrapped in thin paper." @@ -536,27 +553,3 @@ CIGARETTE PACKETS ARE IN FANCY.DM user << "You need to dry this first." else ..() - -/obj/item/weapon/rollingpaperpack - name = "rolling paper pack" - desc = "A pack of NanoTrasen brand rolling papers." - icon = 'icons/obj/cigarettes.dmi' - icon_state = "cig_paper_pack" - w_class = 1 - var/papers = 25 - -/obj/item/weapon/rollingpaperpack/attack_self(mob/user) - if(papers > 1) - var/obj/item/weapon/rollingpaper/P = new /obj/item/weapon/rollingpaper(user.loc) - user.put_in_inactive_hand(P) - user << "You take a paper out of the pack." - papers -- - else - var/obj/item/weapon/rollingpaper/P = new /obj/item/weapon/rollingpaper(user.loc) - user.put_in_inactive_hand(P) - user << "You take the last paper out of the pack, and throw the pack away." - qdel(src) - -/obj/item/weapon/rollingpaperpack/examine() - ..() - usr << "There are [src.papers] left" \ No newline at end of file diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index 8f6eab792de..99173ffb58b 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -93,10 +93,13 @@ else if(stage == EMPTY && istype(I, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = I - C.use(1) - det_time = 50 // In case the cable_coil was removed and readded. - stage_change(WIRED) - user << "You rig the [initial(name)] assembly." + if (C.use(1)) + det_time = 50 // In case the cable_coil was removed and readded. + stage_change(WIRED) + user << "You rig the [initial(name)] assembly." + else + user << "You need one length of coil to wire the assembly." + return else if(stage == READY && istype(I, /obj/item/weapon/wirecutters)) stage_change(WIRED) diff --git a/code/game/objects/items/weapons/grenades/ghettobomb.dm b/code/game/objects/items/weapons/grenades/ghettobomb.dm index f5dc378a097..e2e203d9621 100644 --- a/code/game/objects/items/weapons/grenades/ghettobomb.dm +++ b/code/game/objects/items/weapons/grenades/ghettobomb.dm @@ -54,20 +54,23 @@ if(istype(I, /obj/item/stack/cable_coil)) if(assembled == 1) var/obj/item/stack/cable_coil/C = I - times = list("5" = 10, "-1" = 20, "[rand(30,80)]" = 50, "[rand(65,180)]" = 20) // "Premature, Dud, Short Fuse, Long Fuse"=[weighting value] - C.use(1) - assembled = 2 - user << "You wire the igniter to detonate the fuel." - desc = "A weak, improvised incendiary device." - overlays += image('icons/obj/grenade.dmi', icon_state = "improvised_grenade_wired") - name = "improvised firebomb" - active = 0 - det_time = text2num(pickweight(times)) - if(det_time < 0) //checking for 'duds' - range = 1 - det_time = rand(30,80) + if (C.use(1)) + times = list("5" = 10, "-1" = 20, "[rand(30,80)]" = 50, "[rand(65,180)]" = 20) // "Premature, Dud, Short Fuse, Long Fuse"=[weighting value] + assembled = 2 + user << "You wire the igniter to detonate the fuel." + desc = "A weak, improvised incendiary device." + overlays += image('icons/obj/grenade.dmi', icon_state = "improvised_grenade_wired") + name = "improvised firebomb" + active = 0 + det_time = text2num(pickweight(times)) + if(det_time < 0) //checking for 'duds' + range = 1 + det_time = rand(30,80) + else + range = pick(2,2,2,3,3,3,4) else - range = pick(2,2,2,3,3,3,4) + user <<"span class='warning'>You need one length of cable to add an igniter.
" + return /obj/item/weapon/grenade/iedcasing/attack_self(mob/user as mob) // if(!active) diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index 36ceb898a9f..db4af86faf2 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -88,15 +88,15 @@ ..() if(istype(I, /obj/item/stack/rods)) var/obj/item/stack/rods/R = I - var/obj/item/weapon/wirerod/W = new /obj/item/weapon/wirerod - R.use(1) - - user.unEquip(src) - - user.put_in_hands(W) - user << "You wrap the cable restraint around the top of the rod." - - qdel(src) + if (R.use(1)) + var/obj/item/weapon/wirerod/W = new /obj/item/weapon/wirerod + user.unEquip(src) + user.put_in_hands(W) + user << "You wrap the cable restraint around the top of the rod." + qdel(src) + else + user << "You need one rod to make a wired rod." + return /obj/item/weapon/handcuffs/cyborg/attack(mob/living/carbon/C, mob/user) if(isrobot(user)) diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 521945ee7fd..010cb0420e5 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -470,25 +470,15 @@ w_class = 1 slot_flags = SLOT_BELT - New() - ..() - for(var/i=1; i <= storage_slots; i++) - new /obj/item/weapon/match(src) +/obj/item/weapon/storage/box/matches/New() + ..() + for(var/i=1; i <= storage_slots; i++) + new /obj/item/weapon/match(src) - attackby(obj/item/weapon/match/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/match) && W.lit == 0) - W.lit = 1 - W.icon_state = "match_lit" - W.damtype = "fire" - W.force = 3 - W.hitsound = 'sound/items/welder.ogg' - W.item_state = "cigon" - W.name = "lit match" - W.desc = "A match. This one is lit." - W.attack_verb = list("burnt","singed") - processing_objects.Add(W) - W.update_icon() - return +/obj/item/weapon/storage/box/matches/attackby(obj/item/weapon/match/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/match)) + W.matchignite() + return /obj/item/weapon/storage/box/lights name = "box of replacement bulbs" @@ -525,4 +515,4 @@ for(var/i = 0; i < 14; i++) new /obj/item/weapon/light/tube(src) for(var/i = 0; i < 7; i++) - new /obj/item/weapon/light/bulb(src) \ No newline at end of file + new /obj/item/weapon/light/bulb(src) diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index b959c652871..303850c14dd 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -192,3 +192,28 @@ desc = "A packet of six imported DromedaryCo cancer sticks. A label on the packaging reads, \"Wouldn't a slow death make a change?\"" icon_state = "Dpacket" item_state = "Dpacket" + + +/obj/item/weapon/storage/fancy/rollingpapers + name = "rolling paper pack" + desc = "A pack of NanoTrasen brand rolling papers." + w_class = 1 + icon = 'icons/obj/cigarettes.dmi' + icon_state = "cig_paper_pack" + storage_slots = 10 + icon_type = "rolling papers" + can_hold = list(/obj/item/weapon/rollingpaper) + +/obj/item/weapon/storage/fancy/rollingpapers/update_icon() + if(!contents.len) + icon_state = "[initial(icon_state)]0" + else + icon_state = initial(icon_state) + + desc = "There are [contents.len] papers\s left!" + return + +/obj/item/weapon/storage/fancy/rollingpapers/New() + ..() + for(var/i = 1 to storage_slots) + new /obj/item/weapon/rollingpaper(src) diff --git a/code/game/objects/items/weapons/table_rack_parts.dm b/code/game/objects/items/weapons/table_rack_parts.dm index 8adcedd4ff9..d8cbe11c631 100644 --- a/code/game/objects/items/weapons/table_rack_parts.dm +++ b/code/game/objects/items/weapons/table_rack_parts.dm @@ -17,15 +17,15 @@ new /obj/item/stack/sheet/metal( user.loc ) //SN src = null qdel(src) - if (istype(W, /obj/item/stack/rods)) - var/obj/item/stack/rods/R = W - if (R.amount >= 4) + if (istype(W, /obj/item/stack/rods)) + var/obj/item/stack/rods/V = W + if (V.use(4)) new /obj/item/weapon/table_parts/reinforced( user.loc ) user << "You reinforce the [name]." - R.use(4) qdel(src) - else if (R.amount < 4) - user << "You need at least 4 rods to do that." + else + user << "You need four rods to reinforce table parts." + return /obj/item/weapon/table_parts/attack_self(mob/user as mob) user << "Constructing table.." @@ -93,4 +93,4 @@ R.add_fingerprint(user) user.drop_item() qdel(src) - return \ No newline at end of file + return diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 74393eafbe3..9c1e150c3e2 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -205,13 +205,15 @@ air_contents.react() pressure = air_contents.return_pressure() var/range = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE - range = min(range, MAX_EX_LIGHT_RANGE) var/turf/epicenter = get_turf(loc) //world << "\blue Exploding Pressure: [pressure] kPa, intensity: [range]" explosion(epicenter, round(range*0.25), round(range*0.5), round(range), round(range*1.5)) - qdel(src) + if(istype(src.loc,/obj/item/device/transfer_valve)) + qdel(src.loc) + else + qdel(src) else if(pressure > TANK_RUPTURE_PRESSURE) //world << "\blue[x],[y] tank is rupturing: [pressure] kPa, integrity [integrity]" @@ -237,4 +239,4 @@ integrity-- else if(integrity < 3) - integrity++ \ No newline at end of file + integrity++ diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index 877d943f1bc..ae4c50b2ce0 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -361,13 +361,17 @@ /obj/item/weapon/weldingtool/proc/flamethrower_rods(obj/item/I, mob/user) if(!status) var/obj/item/stack/rods/R = I - R.use(1) - var/obj/item/weapon/flamethrower/F = new /obj/item/weapon/flamethrower(user.loc) - user.unEquip(src) - loc = F - F.weldtool = src - add_fingerprint(user) - user.put_in_hands(F) + if (R.use(1)) + var/obj/item/weapon/flamethrower/F = new /obj/item/weapon/flamethrower(user.loc) + user.unEquip(src) + loc = F + F.weldtool = src + add_fingerprint(user) + user << "You add a rod to a welder, starting to build a flamethrower." + user.put_in_hands(F) + else + user << "You need one rod to start building a flamethrower." + return /obj/item/weapon/weldingtool/largetank name = "industrial welding tool" diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 7ffd57d51d8..097d7b400ae 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -338,10 +338,12 @@ if(rigged) user << "[src] is already rigged!" return - user << "You rig [src]." - user.drop_item() - qdel(W) - rigged = 1 + var/obj/item/stack/cable_coil/C = W + if (C.use(5)) + user << "You rig [src]." + rigged = 1 + else + user << "You need 5 lengths of cable to rig [src]." return else if(istype(W, /obj/item/device/radio/electropack)) if(rigged) diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm index 553122c43fb..db202e16461 100644 --- a/code/game/objects/structures/door_assembly.dm +++ b/code/game/objects/structures/door_assembly.dm @@ -318,8 +318,10 @@ obj/structure/door_assembly /obj/structure/door_assembly/attackby(obj/item/W as obj, mob/user as mob) if(istype(W, /obj/item/weapon/pen)) var/t = copytext(stripped_input(user, "Enter the name for the door.", src.name, src.created_name),1,MAX_NAME_LEN) - if(!t) return - if(!in_range(src, usr) && src.loc != usr) return + if(!t) + return + if(!in_range(src, usr) && src.loc != usr) + return created_name = t return @@ -343,7 +345,8 @@ obj/structure/door_assembly icontype = input(user, "Please select a paintjob for this airlock.") in optionlist - if((!in_range(src, usr) && src.loc != usr) || !WT.use(user)) return + if((!in_range(src, usr) && src.loc != usr) || !WT.use(user)) + return var/has_solid = 0 var/has_glass = 0 switch(icontype) @@ -414,7 +417,7 @@ obj/structure/door_assembly if(mineral && mineral != "glass") mineral = null //I know this is stupid, but until we change glass to a boolean it's how this code works. - user << "\blue You change the paintjob on the airlock assembly." + user << " You change the paintjob on the airlock assembly." else if(istype(W, /obj/item/weapon/weldingtool) && !anchored ) var/obj/item/weapon/weldingtool/WT = W @@ -423,8 +426,9 @@ obj/structure/door_assembly playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1) if(do_after(user, 40)) - if(!src || !WT.isOn()) return - user << "\blue You've dissasembled the airlock assembly." + if( !WT.isOn() ) + return + user << " You've disassembled the airlock assembly." new /obj/item/stack/sheet/metal(get_turf(src), 4) if (mineral) if (mineral == "glass") @@ -435,7 +439,7 @@ obj/structure/door_assembly new M(get_turf(src)) qdel(src) else - user << "\blue You need more welding fuel to dissassemble the airlock assembly." + user << " You need more welding fuel to dissassemble the airlock assembly." return else if(istype(W, /obj/item/weapon/wrench) && !anchored ) @@ -443,8 +447,9 @@ obj/structure/door_assembly user.visible_message("[user] secures the airlock assembly to the floor.", "You start to secure the airlock assembly to the floor.") if(do_after(user, 40)) - if(!src) return - user << "\blue You've secured the airlock assembly." + if( src.anchored ) + return + user << " You've secured the airlock assembly." src.name = "secured airlock assembly" src.anchored = 1 @@ -452,19 +457,23 @@ obj/structure/door_assembly playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) user.visible_message("[user] unsecures the airlock assembly from the floor.", "You start to unsecure the airlock assembly from the floor.") if(do_after(user, 40)) - if(!src) return - user << "\blue You've unsecured the airlock assembly." + if( !src.anchored ) + return + user << " You've unsecured the airlock assembly." src.name = "airlock assembly" src.anchored = 0 else if(istype(W, /obj/item/stack/cable_coil) && state == 0 && anchored ) - var/obj/item/stack/cable_coil/coil = W + var/obj/item/stack/cable_coil/C = W + if (C.get_amount() < 1) + user << "You need one length of cable to wire the airlock assembly." + return user.visible_message("[user] wires the airlock assembly.", "You start to wire the airlock assembly.") - if(do_after(user, 40)) - if(!src) return - coil.use(1) + if(do_after(user, 40)) + if(C.get_amount() < 1 || state != 0) return + C.use(1) src.state = 1 - user << "\blue You've wired the airlock assembly." + user << "You've wired the airlock assembly." src.name = "wired airlock assembly" else if(istype(W, /obj/item/weapon/wirecutters) && state == 1 ) @@ -472,8 +481,9 @@ obj/structure/door_assembly user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly.") if(do_after(user, 40)) - if(!src) return - user << "\blue You've cut the wires from the airlock assembly." + if( src.state != 1 ) + return + user << " You've cut the wires from the airlock assembly." new/obj/item/stack/cable_coil(get_turf(user), 1) src.state = 0 src.name = "secured airlock assembly" @@ -485,8 +495,9 @@ obj/structure/door_assembly W.loc = src if(do_after(user, 40)) - if(!src) return - user << "\blue You've installed the airlock electronics." + if( src.state != 1 ) + return + user << " You've installed the airlock electronics." src.state = 2 src.name = "near finished airlock assembly" src.electronics = W @@ -500,8 +511,9 @@ obj/structure/door_assembly user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove the electronics from the airlock assembly.") if(do_after(user, 40)) - if(!src) return - user << "\blue You've removed the airlock electronics." + if( src.state != 2 ) + return + user << " You've removed the airlock electronics." src.state = 1 src.name = "wired airlock assembly" var/obj/item/weapon/airlock_electronics/ae @@ -514,12 +526,13 @@ obj/structure/door_assembly else if(istype(W, /obj/item/stack/sheet) && !mineral) var/obj/item/stack/sheet/G = W if(G) - if(G.amount>=1) + if(G.get_amount() >= 1) if(G.type == /obj/item/stack/sheet/rglass) playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] adds [G.name] to the airlock assembly.", "You start to install [G.name] into the airlock assembly.") - if(do_after(user, 40)) - user << "\blue You've installed reinforced glass windows into the airlock assembly." + if(do_after(user, 40)) + if(G.get_amount() < 1 || mineral) return + user << "You've installed reinforced glass windows into the airlock assembly." G.use(1) mineral = "glass" name = "near finished window airlock assembly" @@ -537,11 +550,12 @@ obj/structure/door_assembly glass_base_icon_state = "door_as_g[icontext]" else if(istype(G, /obj/item/stack/sheet/mineral)) var/M = G.sheettype - if(G.amount>=2) + if(G.get_amount() >= 2) playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] adds [G.name] to the airlock assembly.", "You start to install [G.name] into the airlock assembly.") - if(do_after(user, 40)) - user << "\blue You've installed [M] plating into the airlock assembly." + if(do_after(user, 40)) + if(G.get_amount() < 2 || mineral) return + user << "You've installed [M] plating into the airlock assembly." G.use(2) mineral = "[M]" name = "near finished [M] airlock assembly" @@ -552,11 +566,10 @@ obj/structure/door_assembly else if(istype(W, /obj/item/weapon/screwdriver) && state == 2 ) playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) - user << "\blue You start finishing the airlock." + user.visible_message("[user] finishes the airlock.", "You start finishing the airlock.") if(do_after(user, 40)) - if(!src) return - user << "\blue You've finished the airlock." + user << " You've finished the airlock." var/obj/machinery/door/airlock/door if(mineral == "glass") door = new src.glass_type( src.loc ) @@ -580,4 +593,4 @@ obj/structure/door_assembly icon_state = "[base_icon_state][state]" //This updates the icon_state. They are named as "door_as1_eng" where the 1 in that example //represents what state it's in. So the most generic algorithm for the correct updating of - //this is simply to change the number. \ No newline at end of file + //this is simply to change the number. diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 1311dbea0b8..d0875271714 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -73,25 +73,29 @@ if(/obj/item/stack/sheet/metal, /obj/item/stack/sheet/metal/cyborg) if(!anchored) - if(S.amount < 2) - user << "You need at least two sheets to create a false wall." + if (S.use(2)) + user << "You create a false wall! Push on it to open or close the passage." + var/obj/structure/falsewall/F = new (loc) + transfer_fingerprints_to(F) + qdel(src) + else + user << "You need two sheets of metal to create a false wall." return - S.use(2) - user << "You create a false wall! Push on it to open or close the passage." - var/obj/structure/falsewall/F = new (loc) - transfer_fingerprints_to(F) - qdel(src) else - if(S.amount < 2) return ..() + if(S.get_amount() < 2) + user << "You need two sheets of metal to finish a wall." + return user << "Now adding plating..." - if (do_after(user,40)) - if(!src || !S || S.amount < 2) return + if (do_after(user, 40)) + if(loc == null || S.get_amount() < 2) + return S.use(2) user << "You added the plating!" var/turf/Tsrc = get_turf(src) Tsrc.ChangeTurf(/turf/simulated/wall) for(var/turf/simulated/wall/X in Tsrc.loc) - if(X) transfer_fingerprints_to(X) + if(X) + transfer_fingerprints_to(X) qdel(src) return diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 630b37fac3d..0a5b131844c 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -119,7 +119,11 @@ return //window placing begin - else if( istype(W,/obj/item/stack/sheet/rglass) || istype(W,/obj/item/stack/sheet/glass) ) + else if(istype(W, /obj/item/stack/sheet/rglass) || istype(W, /obj/item/stack/sheet/glass)) + var/obj/item/stack/ST = W + if (ST.get_amount() < 1) + user << "You need at least one sheet of glass for that." + return var/dir_to_set = 1 if(loc == user.loc) dir_to_set = user.dir @@ -150,7 +154,7 @@ user << "There is already a window facing this way there." return var/obj/structure/window/WD - if(istype(W,/obj/item/stack/sheet/rglass)) + if(istype(W, /obj/item/stack/sheet/rglass)) WD = new/obj/structure/window(loc,1) //reinforced window else WD = new/obj/structure/window(loc,0) //normal window @@ -158,7 +162,6 @@ WD.ini_dir = dir_to_set WD.anchored = 0 WD.state = 0 - var/obj/item/stack/ST = W ST.use(1) user << "You place the [WD] on [src]." return diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 7c02b232b65..be5e7807136 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -199,13 +199,13 @@ turf/simulated/floor/proc/update_icon() break_tile() /turf/simulated/floor/is_plasteel_floor() - if(istype(floor_tile,/obj/item/stack/tile/plasteel)) + if(istype(floor_tile, /obj/item/stack/tile/plasteel)) return 1 else return 0 /turf/simulated/floor/is_light_floor() - if(istype(floor_tile,/obj/item/stack/tile/light)) + if(istype(floor_tile, /obj/item/stack/tile/light)) return 1 else return 0 @@ -324,7 +324,7 @@ turf/simulated/floor/proc/update_icon() intact = 1 SetLuminosity(0) if(T) - if(istype(T,/obj/item/stack/tile/plasteel)) + if(istype(T, /obj/item/stack/tile/plasteel)) floor_tile = T if (icon_regular_floor) icon_state = icon_regular_floor @@ -463,24 +463,30 @@ turf/simulated/floor/proc/update_icon() if(istype(C, /obj/item/stack/rods)) var/obj/item/stack/rods/R = C if (is_plating()) - if (R.amount >= 2) - user << "\blue Reinforcing the floor..." - if(do_after(user, 30) && R && R.amount >= 2 && is_plating()) - ChangeTurf(/turf/simulated/floor/engine) - playsound(src, 'sound/items/Deconstruct.ogg', 80, 1) - R.use(2) - return + if (R.get_amount() < 2) + user << "You need two rods to make a reinforced floor." + return else - user << "\red You need more rods." + user << "Reinforcing the floor..." + if(do_after(user, 30)) + if (R.get_amount() >= 2 && is_plating()) + ChangeTurf(/turf/simulated/floor/engine) + playsound(src, 'sound/items/Deconstruct.ogg', 80, 1) + R.use(2) + user << "You have reinforced the floor." + return else - user << "\red You must remove the plating first." + user << "You must remove the plating first." return if(istype(C, /obj/item/stack/tile)) if(is_plating()) if(!broken && !burnt) var/obj/item/stack/tile/T = C - floor_tile = new T.type + if(istype(T, /obj/item/stack/tile/plasteel/cyborg)) + floor_tile = new /obj/item/stack/tile/plasteel + else + floor_tile = new T.type intact = 1 if(istype(T,/obj/item/stack/tile/light)) var/obj/item/stack/tile/light/L = T @@ -514,7 +520,7 @@ turf/simulated/floor/proc/update_icon() return coil.turf_place(src, user) else - user << "\red You must remove the plating first." + user << "You must remove the plating first." if(istype(C, /obj/item/weapon/shovel)) if(is_grass_floor()) diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index 1dfbc9d1bb3..8126029fc18 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -75,13 +75,16 @@ return //REPAIRING (replacing the outer grille for cosmetic damage) - else if( istype(W, /obj/item/stack/rods) ) + else if(istype(W, /obj/item/stack/rods)) var/obj/item/stack/rods/O = W - src.d_state = 0 - src.icon_state = "r_wall" - relativewall_neighbours() //call smoothwall stuff - user << "You replace the outer grille." - O.use(1) + if (O.use(1)) + src.d_state = 0 + src.icon_state = "r_wall" + relativewall_neighbours() //call smoothwall stuff + user << "You replace the outer grille." + else + user << "You need one rod to repair the wall." + return return if(2) @@ -211,20 +214,23 @@ dismantle_wall() //REPAIRING - else if( istype(W, /obj/item/stack/sheet/metal) && d_state ) + else if(istype(W, /obj/item/stack/sheet/metal) && d_state) var/obj/item/stack/sheet/metal/MS = W + if (MS.get_amount() < 1) + user << "You need one sheet of metal to repair the wall." + return + user << "You begin patching-up the wall with \a [MS]." - sleep( max(20*d_state,100) ) //time taken to repair is proportional to the damage! (max 10 seconds) - if( !istype(src, /turf/simulated/wall/r_wall) || !user || !MS || !T ) return - - if( user.loc == T && user.get_active_hand() == MS && d_state ) + if (do_after(user, max(20*d_state,100)))//time taken to repair is proportional to the damage! (max 10 seconds) + if(loc == null || MS.get_amount() < 1) + return + MS.use(1) src.d_state = 0 src.icon_state = "r_wall" relativewall_neighbours() //call smoothwall stuff user << "You repair the last of the damage." - MS.use(1) //APC diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index 22b54fe0015..1e516a3cdf5 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -18,27 +18,35 @@ /turf/space/attackby(obj/item/C as obj, mob/user as mob) if (istype(C, /obj/item/stack/rods)) + var/obj/item/stack/rods/R = C var/obj/structure/lattice/L = locate(/obj/structure/lattice, src) if(L) + user << "There is already a lattice." + return + if (R.use(1)) + user << "Constructing support lattice..." + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + ReplaceWithLattice() + else + user << "You need one rod to build lattice." return - var/obj/item/stack/rods/R = C - user << "\blue Constructing support lattice ..." - playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) - ReplaceWithLattice() - R.use(1) return if (istype(C, /obj/item/stack/tile/plasteel)) var/obj/structure/lattice/L = locate(/obj/structure/lattice, src) if(L) var/obj/item/stack/tile/plasteel/S = C - qdel(L) - playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) - S.build(src) - S.use(1) + if (S.use(1)) + qdel(L) + playsound(src, 'sound/weapons/Genhit.ogg', 50, 1) + user << "You build a floor." + S.build(src) + else + user << "You need one floor tile to build a floor." + return return else - user << "\red The plating is going to need some support." + user << "The plating is going to need some support. Place metal rods first." return diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index f08e6bffef1..7a7d7c45166 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -434,7 +434,6 @@ var/global/floorIsLava = 0 dat += {" 'Random' Events

- Trigger a gravity-failure event
Spawn a wave of meteors (aka lagocolyptic shower)
Spawn a vortex anomaly
Spawn a gravitational anomaly
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index f9fcfb99bf8..25510344edc 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1584,13 +1584,6 @@ usr.client.triple_ai() feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","TriAI") - if("gravity") - alert("WIP - event unavailable") -/* E = new /datum/round_event/weightless() - log_admin("[key_name(usr)] triggered a gravity-failure event.", 1) - message_admins("\blue [key_name_admin(usr)] triggered a gravity-failure event.", 1) - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Grav") */ if("power") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","P") diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 0be71e2376b..0431d22b716 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -619,7 +619,7 @@ var/global/list/g_fancy_list_of_safe_types = null //log_admin("[key_name(src)] has alienized [M.key].") var/list/dresspacks = list( "naked", - "assistant grey", + "as job...", "standard space gear", "tournament standard red", "tournament standard green", @@ -647,6 +647,12 @@ var/global/list/g_fancy_list_of_safe_types = null var/dresscode = input("Select dress for [M]", "Robust quick dress shop") as null|anything in dresspacks if (isnull(dresscode)) return + + var/datum/job/jobdatum + if (dresscode == "as job...") + var/jobname = input("Select job", "Robust quick dress shop") as null|anything in get_all_jobs() + jobdatum = job_master.GetJob(jobname) + feedback_add_details("admin_verb","SEQ") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! for (var/obj/item/I in M) if (istype(I, /obj/item/weapon/implant)) @@ -656,25 +662,10 @@ var/global/list/g_fancy_list_of_safe_types = null if ("naked") //do nothing - if ("assistant grey") - var/obj/item/weapon/storage/backpack/BPK = new/obj/item/weapon/storage/backpack(M) - new /obj/item/weapon/storage/box/survival(BPK) - M.equip_to_slot_or_del(BPK, slot_back,1) - M.equip_to_slot_or_del(new /obj/item/device/radio/headset(M), slot_ears) - M.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(M), slot_shoes) - - var/obj/item/weapon/card/id/W = new(M) - W.assignment = "Assistant" - W.registered_name = M.real_name - W.update_label() - M.equip_to_slot_or_del(W, slot_wear_id) - var/obj/item/device/pda/P = new(M) - P.owner = M.real_name - P.ownjob = "Assistant" - P.update_label() - M.equip_to_slot_or_del(P, slot_belt) - + if ("as job...") + if(jobdatum) + dresscode = "[jobdatum.title]" + jobdatum.equip(M) if ("standard space gear") M.equip_to_slot_or_del(new /obj/item/clothing/shoes/sneakers/black(M), slot_shoes) @@ -687,6 +678,7 @@ var/global/list/g_fancy_list_of_safe_types = null J.toggle() M.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(M), slot_wear_mask) J.Topic(null, list("stat" = 1)) + if ("tournament standard red","tournament standard green") //we think stunning weapon is too overpowered to use it on tournaments. --rastaf0 if (dresscode=="tournament standard red") M.equip_to_slot_or_del(new /obj/item/clothing/under/color/red(M), slot_w_uniform) @@ -1137,3 +1129,15 @@ var/global/list/g_fancy_list_of_safe_types = null usr << list2text(clients,",") if("Joined Clients") usr << list2text(joined_player_list,",") + +/client/proc/cmd_display_del_log() + set category = "Debug" + set name = "Display del() Log" + set desc = "Displays a list of things that have failed to GC this round" + + var/dat = "List of things that failed to GC this round

" + + for(var/path in garbage.logging) + dat += "[path] - [garbage.logging[path]] times
" + + usr << browse(dat, "window=dellog") diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 8745247f96e..a567d4eaec6 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -148,6 +148,7 @@ var/intercom_range_display_status = 0 src.verbs += /client/proc/print_pointers src.verbs += /client/proc/count_movable_instances src.verbs += /client/proc/SDQL2_query + src.verbs += /client/proc/cmd_display_del_log //src.verbs += /client/proc/cmd_admin_rejuvenate feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm index 9a2d6c758b4..1f0a894cd5a 100644 --- a/code/modules/awaymissions/mission_code/wildwest.dm +++ b/code/modules/awaymissions/mission_code/wildwest.dm @@ -89,20 +89,20 @@ user.see_in_dark = 8 user.see_invisible = SEE_INVISIBLE_LEVEL_TWO user << "\blue The walls suddenly disappear." - user.dna.mutantrace = "shadow" - user.update_body() + user.dna.species = new /datum/species/shadow() + user.regenerate_icons() if("Wealth") user << "Your wish is granted, but at a terrible cost..." user << "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart." new /obj/structure/closet/syndicate/resources/everything(loc) - user.dna.mutantrace = "shadow" - user.update_body() + user.dna.species = new /datum/species/shadow() + user.regenerate_icons() if("Immortality") user << "Your wish is granted, but at a terrible cost..." user << "The Wish Granter punishes you for your selfishness, claiming your soul and warping your body to match the darkness in your heart." user.verbs += /mob/living/carbon/proc/immortality - user.dna.mutantrace = "shadow" - user.update_body() + user.dna.species = new /datum/species/shadow() + user.regenerate_icons() if("To Kill") user << "Your wish is granted, but at a terrible cost..." user << "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart." @@ -116,8 +116,8 @@ for(var/datum/objective/OBJ in user.mind.objectives) user << "Objective #[obj_count]: [OBJ.explanation_text]" obj_count++ - user.dna.mutantrace = "shadow" - user.update_body() + user.dna.species = new /datum/species/shadow() + user.regenerate_icons() if("Peace") user << "Whatever alien sentience that the Wish Granter possesses is satisfied with your wish. There is a distant wailing as the last of the Faithless begin to die, then silence." user << "You feel as if you just narrowly avoided a terrible fate..." diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 7eaacc46d10..f3085e14e0f 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -53,7 +53,8 @@ datum/preferences var/facial_hair_color = "000" //Facial hair color var/skin_tone = "caucasian1" //Skin color var/eye_color = "000" //Eye color - var/mutant_race = "human" //Mutant race + var/datum/species/pref_species = new /datum/species/human() //Mutant race + var/mutant_color = "FFF" //Mutant race skin color //Mob preview var/icon/preview_icon_front = null @@ -165,16 +166,17 @@ datum/preferences dat += "
" if(config.mutant_races) - dat += "Mutant Race:
[mutant_race]
" + dat += "Species:
[pref_species.name]
" else - dat += "Mutant Race: Human
" + dat += "Species: Human
" + dat += "Blood Type: [blood_type]
" dat += "Skin Tone:
[skin_tone]
" dat += "Underwear:
[underwear]
" dat += "Backpack:
[backbaglist[backbag]]
" - dat += "
" + dat += "" dat += "

Hair Style

" @@ -182,7 +184,7 @@ datum/preferences dat += "    Change
" - dat += "
" + dat += "" dat += "

Facial Hair Style

" @@ -190,12 +192,17 @@ datum/preferences dat += "    Change
" - dat += "
" + dat += "" dat += "

Eye Color

" dat += "    Change
" + dat += "
" + + dat += "

Alien Color

" // even if choosing your mutantrace is off, this is here in case you gain one during a round + + dat += "    Change
" dat += "
" @@ -618,10 +625,27 @@ datum/preferences if(new_eyes) eye_color = sanitize_hexcolor(new_eyes) - if("mutant_race") - var/new_mutant_race = input(user, "Choose your character's mutant race:", "Character Preference") as null|anything in mutant_races - if(new_mutant_race) - mutant_race = new_mutant_race + if("species") + + var/result = input(user, "Select a species", "Species Selection") as null|anything in roundstart_species + + if(result) + var/newtype = roundstart_species[result] + pref_species = new newtype() + if(!config.mutant_colors) + mutant_color = pref_species.default_color + + if("mutant_color") + if(!config.mutant_colors) + user << "Alien colors are disabled." + return + var/new_mutantcolor = input(user, "Choose your character's alien skin color:", "Character Preference") as color|null + if(new_mutantcolor) + var/temp_hsv = RGBtoHSV(new_mutantcolor) + if(ReadHSV(temp_hsv)[3] >= ReadHSV("#7F7F7F")[3]) // mutantcolors must be bright + mutant_color = sanitize_hexcolor(new_mutantcolor) + else + user << "Invalid color. Your color is not bright enough." if("s_tone") var/new_s_tone = input(user, "Choose your character's skin-tone:", "Character Preference") as null|anything in skin_tones @@ -685,8 +709,10 @@ datum/preferences if("ghost_sight") toggles ^= CHAT_GHOSTSIGHT + if("pull_requests") toggles ^= CHAT_PULLR + if("save") save_preferences() save_character() @@ -722,10 +748,15 @@ datum/preferences character.real_name = real_name character.name = character.real_name + if(character.dna) character.dna.real_name = character.real_name - if(mutant_race != "human" && config.mutant_races) - character.dna.mutantrace = mutant_race + if(pref_species != /datum/species/human && config.mutant_races) + character.dna.species = new pref_species.type() + else + character.dna.species = new /datum/species/human() + character.dna.mutant_color = mutant_color + character.update_mutcolor() character.gender = gender character.age = age diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 1204bf5edee..33768cb04c7 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -73,6 +73,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(11) underwear = "Ladies Kinky" if(12) underwear = "Tankini" if(13) underwear = "Nude" + if(!(pref_species in species_list)) + pref_species = new /datum/species/human() return /datum/preferences/proc/load_path(ckey,filename="preferences.sav") @@ -151,6 +153,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(needs_update == -2) //fatal, can't load any data return 0 + if(!S["species"] || !config.mutant_races) + S["species"] << new /datum/species/human() + //Character S["OOC_Notes"] >> metadata S["real_name"] >> real_name @@ -165,7 +170,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["facial_style_name"] >> facial_hair_style S["underwear"] >> underwear S["backbag"] >> backbag - S["mutant_race"] >> mutant_race + S["species"] >> pref_species + S["mutant_color"] >> mutant_color //Jobs S["userandomjob"] >> userandomjob @@ -186,6 +192,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car //Sanitize metadata = sanitize_text(metadata, initial(metadata)) real_name = reject_bad_name(real_name) + if(!(pref_species in species_list)) + pref_species = new /datum/species/human() if(!real_name) real_name = random_name(gender) be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name)) gender = sanitize_gender(gender) @@ -203,7 +211,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car eye_color = sanitize_hexcolor(eye_color, 3, 0) skin_tone = sanitize_inlist(skin_tone, skin_tones) backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag)) - mutant_race = sanitize_text(mutant_race, initial(mutant_race)) + mutant_color = sanitize_hexcolor(mutant_color, 3, 0) userandomjob = sanitize_integer(userandomjob, 0, 1, initial(userandomjob)) job_civilian_high = sanitize_integer(job_civilian_high, 0, 65535, initial(job_civilian_high)) @@ -240,7 +248,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["facial_style_name"] << facial_hair_style S["underwear"] << underwear S["backbag"] << backbag - S["mutant_race"] << mutant_race + S["species"] << pref_species + S["mutant_color"] << mutant_color //Jobs S["userandomjob"] << userandomjob diff --git a/code/modules/clothing/gloves/boxing.dm b/code/modules/clothing/gloves/boxing.dm index 0865c31e942..9467c63e34e 100644 --- a/code/modules/clothing/gloves/boxing.dm +++ b/code/modules/clothing/gloves/boxing.dm @@ -3,6 +3,7 @@ desc = "Because you really needed another excuse to punch your crewmates." icon_state = "boxing" item_state = "boxing" + species_exception = list(/datum/species/golem, /datum/species/golem/adamantine) // now you too can be a golem boxing champion /obj/item/clothing/gloves/boxing/green icon_state = "boxinggreen" diff --git a/code/modules/events/holiday/halloween.dm b/code/modules/events/holiday/halloween.dm index 67536e1dec7..9a7945d7719 100644 --- a/code/modules/events/holiday/halloween.dm +++ b/code/modules/events/holiday/halloween.dm @@ -9,9 +9,9 @@ /datum/round_event/spooky/start() for(var/mob/living/carbon/human/H in mob_list) if(H.dna) - hardset_dna(H, null, null, null, "skeleton") + hardset_dna(H, null, null, null, null, /datum/species/skeleton) for(var/mob/living/simple_animal/corgi/Ian/Ian in mob_list) Ian.place_on_head(new /obj/item/weapon/bedsheet(Ian)) /datum/round_event/spooky/announce() - priority_announce(pick("RATTLE ME BONES!","THE RIDE NEVER ENDS!", "A SKELETON POPS OUT!", "SPOOKY SCARY SKELETONS!", "CREWMEMBERS BEWARE, YOU'RE IN FOR A SCARE!") , "THE CALL IS COMING FROM INSIDE THE HOUSE") \ No newline at end of file + priority_announce(pick("RATTLE ME BONES!","THE RIDE NEVER ENDS!", "A SKELETON POPS OUT!", "SPOOKY SCARY SKELETONS!", "CREWMEMBERS BEWARE, YOU'RE IN FOR A SCARE!") , "THE CALL IS COMING FROM INSIDE THE HOUSE") diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index b88f5b482ad..12dfeb163be 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -144,15 +144,17 @@ /obj/item/weapon/reagent_containers/food/snacks/grown/potato/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() if(istype(W, /obj/item/stack/cable_coil)) - if(W:amount >= 5) - W:amount -= 5 - if(!W:amount) qdel(W) + var/obj/item/stack/cable_coil/C + if (C.use(5)) user << "You add some cable to the potato and slide it inside the battery encasing." var/obj/item/weapon/stock_parts/cell/potato/pocell = new /obj/item/weapon/stock_parts/cell/potato(user.loc) pocell.maxcharge = src.potency * 10 pocell.charge = pocell.maxcharge qdel(src) return + else + user << "You need five lengths of cable to make a potato battery." + return /obj/item/weapon/reagent_containers/food/snacks/grown/grapes seed = "/obj/item/seeds/grapeseed" diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 80642e3957b..10f10353b41 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -909,7 +909,7 @@ obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob) podman.gender = ghost.gender //dna stuff - hardset_dna(podman, ui, se, null, !prob(potency) ? "plant" : null) //makes sure podman has dna and sets the dna's ui/se/mutantrace/real_name etc variables + hardset_dna(podman, ui, se, null, null, null, !prob(potency) ? /datum/species/plant/pod : null, "#59CE00") //makes sure podman has dna and sets the dna's ui/se/mutantrace/real_name etc variables else //else, one packet of seeds. maybe two var/seed_count = 1 diff --git a/code/modules/mining/mint.dm b/code/modules/mining/mint.dm index 44cbb1da3cf..2f130f34d6e 100644 --- a/code/modules/mining/mint.dm +++ b/code/modules/mining/mint.dm @@ -25,28 +25,28 @@ var/turf/T = get_step(src,input_dir) if(T) for(var/obj/item/stack/sheet/O in T) - if (istype(O,/obj/item/stack/sheet/mineral/gold)) + if (istype(O, /obj/item/stack/sheet/mineral/gold)) amt_gold += 100 * O.amount O.loc = null - if (istype(O,/obj/item/stack/sheet/mineral/silver)) + if (istype(O, /obj/item/stack/sheet/mineral/silver)) amt_silver += 100 * O.amount O.loc = null - if (istype(O,/obj/item/stack/sheet/mineral/diamond)) + if (istype(O, /obj/item/stack/sheet/mineral/diamond)) amt_diamond += 100 * O.amount O.loc = null - if (istype(O,/obj/item/stack/sheet/mineral/plasma)) + if (istype(O, /obj/item/stack/sheet/mineral/plasma)) amt_plasma += 100 * O.amount O.loc = null - if (istype(O,/obj/item/stack/sheet/mineral/uranium)) + if (istype(O, /obj/item/stack/sheet/mineral/uranium)) amt_uranium += 100 * O.amount O.loc = null - if (istype(O,/obj/item/stack/sheet/metal)) + if (istype(O, /obj/item/stack/sheet/metal)) amt_iron += 100 * O.amount O.loc = null - if (istype(O,/obj/item/stack/sheet/mineral/clown)) + if (istype(O, /obj/item/stack/sheet/mineral/clown)) amt_clown += 100 * O.amount O.loc = null - if (istype(O,/obj/item/stack/sheet/mineral/adamantine)) + if (istype(O, /obj/item/stack/sheet/mineral/adamantine)) amt_adamantine += 100 * O.amount O.loc = null //Commented out for now. -Durandan return diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index 48c101d41be..88a115e20fb 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -224,21 +224,20 @@ /obj/item/weapon/coin/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W,/obj/item/stack/cable_coil) ) + if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/CC = W if(string_attached) - user << "\blue There already is a string attached to this coin." + user << "There already is a string attached to this coin." return - if(CC.amount <= 0) - user << "\blue This cable coil appears to be empty." - qdel(CC) + if (CC.use(1)) + overlays += image('icons/obj/economy.dmi',"coin_string_overlay") + string_attached = 1 + user << "You attach a string to the coin." + else + user << "You need one length of cable to attach a string to the coin." return - overlays += image('icons/obj/economy.dmi',"coin_string_overlay") - string_attached = 1 - user << "\blue You attach a string to the coin." - CC.use(1) else if(istype(W,/obj/item/weapon/wirecutters)) if(!string_attached) ..() diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index abda0ce43fa..eb89d6cf49b 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -94,7 +94,7 @@ if(shielded) damage /= 4 - show_message("\red The blob attacks!") + show_message("The blob attacks!") adjustFireLoss(damage) return @@ -120,9 +120,8 @@ return if (health > 0) playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[M.name] bites [src]!"), 1) + visible_message("[M.name] bites [src]!", \ + "[M.name] bites [src]!") adjustBruteLoss(rand(1, 3)) updatehealth() return @@ -137,10 +136,8 @@ if (health > -100) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red The [M.name] glomps []!", src), 1) - + visible_message("The [M.name] glomps [src]!", \ + "The [M.name] glomps [src]!") var/damage = rand(1, 3) if(M.is_adult) @@ -167,9 +164,8 @@ if(M.powerlevel < 0) M.powerlevel = 0 - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red The [M.name] has shocked []!", src), 1) + visible_message("The [M.name] has shocked [src]!", \ + "The [M.name] has shocked [src]!") Weaken(power) if (stuttering < power) @@ -194,8 +190,8 @@ else if(M.attack_sound) playsound(loc, M.attack_sound, 50, 1, 1) - for(var/mob/O in viewers(src, null)) - O.show_message("\red [M] [M.attacktext] [src]!", 1) + visible_message("[M] [M.attacktext] [src]!", \ + "[M] [M.attacktext] [src]!") var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) adjustBruteLoss(damage) updatehealth() @@ -229,9 +225,7 @@ LAssailant = M playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) + visible_message("[M] has grabbed [src] passively!") if ("harm") var/damage = rand(1, 9) @@ -244,42 +238,35 @@ sleep(3) step_away(src,M,15) playsound(loc, "punch", 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has punched []!", M, src), 1) + visible_message("[M] has punched [src]!", \ + "[M] has punched [src]!") if ((stat != DEAD) && (damage > 9||prob(5)))//Regular humans have a very small chance of weakening an alien. Weaken(1,5) - for(var/mob/O in viewers(M, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has weakened []!", M, src), 1, "\red You hear someone fall.", 2) + visible_message("[M] has weakened [src]!", \ + "[M] has weakened [src]!", \ + "You hear someone fall.") adjustBruteLoss(damage) updatehealth() else playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has attempted to punch []!", M, src), 1) + visible_message("[M] has attempted to punch [src]!") if ("disarm") if (!lying) if (prob(5))//Very small chance to push an alien down. Weaken(2) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has pushed down []!", M, src), 1) + visible_message("[M] has pushed down [src]!", \ + "[M] has pushed down [src]!") else if (prob(50)) drop_item() playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has disarmed []!", M, src), 1) + visible_message("[M] has disarmed [src]!", \ + "[M] has disarmed [src]!") else playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has attempted to disarm []!", M, src), 1) + visible_message("[M] has attempted to disarm [src]!") return /*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other. @@ -306,21 +293,19 @@ In all, this is a lot like the monkey code. /N AdjustParalysis(-3) AdjustStunned(-3) AdjustWeakened(-3) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M.name] nuzzles [] trying to wake it up!", src), 1) + visible_message("[M.name] nuzzles [src] trying to wake it up!") else if (health > 0) playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) var/damage = rand(1, 3) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[M.name] bites []!", src), 1) + visible_message("[M.name] bites [src]!!", \ + "[M.name] bites [src]!!") + adjustBruteLoss(damage) updatehealth() else - M << "\green [name] is too injured for that." + M << "[name] is too injured for that." return diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index 7503b0d0b35..4b6585412d1 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -101,7 +101,7 @@ //paralysis += 1 - show_message("\red The blob attacks you!") + show_message("The blob attacks you!") adjustFireLoss(damage) @@ -117,8 +117,8 @@ if(M.melee_damage_upper == 0) M.emote("[M.friendly] [src]") else - for(var/mob/O in viewers(src, null)) - O.show_message("\red [M] [M.attacktext] [src]!", 1) + visible_message("[M] [M.attacktext] [src]!", \ + "[M] [M.attacktext] [src]!") var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) adjustBruteLoss(damage) add_logs(M, src, "attacked", admin=0) @@ -146,9 +146,8 @@ return if (health > 0) playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[M.name] bites [src]!"), 1) + visible_message("[M.name] bites [src]!", \ + "[M.name] bites [src]!") adjustBruteLoss(rand(1, 3)) updatehealth() return @@ -163,9 +162,8 @@ if (health > -100) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red The [M.name] glomps []!", src), 1) + visible_message("The [M.name] glomps [src]!", \ + "The [M.name] glomps [src]!") var/damage = rand(1, 3) @@ -209,9 +207,7 @@ LAssailant = M playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) + visible_message("[M] has grabbed [src] passively!") else var/damage = rand(1, 9) @@ -224,21 +220,19 @@ sleep(3) step_away(src,M,15) playsound(loc, "punch", 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has kicked []!", M, src), 1) + visible_message("[M] has kicked [src]!", \ + "[M] has kicked [src]!") if ((stat != DEAD) && (damage > 4.9)) Weaken(rand(5,10)) - for(var/mob/O in viewers(M, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has weakened []!", M, src), 1, "\red You hear someone fall.", 2) + visible_message("[M] has weakened [src]!", \ + "[M] has weakened [src]!", \ + "You hear someone fall.") adjustBruteLoss(damage) updatehealth() else playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has attempted to kick []!", M, src), 1) + visible_message("[M] has attempted to kick [src]!", \ + "[M] has attempted to kick [src]!") return /mob/living/carbon/alien/larva/attack_alien(mob/living/carbon/alien/humanoid/M as mob) @@ -260,21 +254,18 @@ AdjustParalysis(-3) AdjustStunned(-3) AdjustWeakened(-3) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M.name] nuzzles [] trying to wake it up!", src), 1) + visible_message("[M.name] nuzzles [src] trying to wake it up!") else if (health > 0) playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) var/damage = rand(1, 3) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[M.name] bites []!", src), 1) + visible_message("[M.name] bites [src]!", \ + "[M.name] bites [src]!") adjustBruteLoss(damage) updatehealth() else - M << "\green [name] is too injured for that." + M << "[name] is too injured for that." return /mob/living/carbon/alien/larva/restrained() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 8cc66e2897b..f2dfb348f29 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -205,7 +205,7 @@ src << "You're completely exhausted." else src << "You feel fatigued." - if(dna && (dna.mutantrace == "skeleton") && !H.w_uniform && !H.wear_suit) + if(dna && (dna.species == /datum/species/skeleton) && !H.w_uniform && !H.wear_suit) H.play_xylophone() else if(ishuman(src)) @@ -452,13 +452,6 @@ ..() -/mob/living/carbon/proc/is_mutantrace(var/mrace) - if(mrace) - if(src.dna && src.dna.mutantrace == mrace) - return 1 - else - return src.dna && src.dna.mutantrace ? 1 : 0 - /mob/living/carbon/getTrail() if(getBruteLoss() < 300) if(prob(50)) diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 473707ff132..045ca305efa 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -8,7 +8,10 @@ ..() /mob/living/carbon/human/spawn_gibs() - hgibs(loc, viruses, dna) + if(dna) + hgibs(loc, viruses, dna) + else + hgibs(loc, viruses, null) /mob/living/carbon/human/spawn_dust() new /obj/effect/decal/remains/human(loc) @@ -31,6 +34,9 @@ update_canmove() if(client) blind.layer = 0 + if(dna) + dna.species.spec_death(gibbed,src) + tod = worldtime2text() //weasellos time of death patch if(mind) mind.store_memory("Time of death: [tod]", 0) if(ticker && ticker.mode) @@ -40,11 +46,9 @@ return ..(gibbed) /mob/living/carbon/human/proc/makeSkeleton() - if(!check_dna_integrity(src) || (dna.mutantrace == "skeleton")) return - dna.mutantrace = "skeleton" + if(!check_dna_integrity(src)) return status_flags |= DISFIGURED - update_hair() - update_body() + dna.species = new /datum/species/skeleton(src) return 1 /mob/living/carbon/proc/ChangeToHusk() diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index ea0cc16a2d5..f7db2f18267 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -253,7 +253,7 @@ msg += "[t_He] [t_has] a vacant, braindead stare...\n" if(digitalcamo) - msg += "[t_He] [t_is] repulsively uncanny!\n" + msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly inhuman manner.\n" if(istype(usr, /mob/living/carbon/human)) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 7030742e370..773c4bf2b23 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -51,12 +51,12 @@ for(var/mob/M in range(tmob, 1)) if( ((M.pulling == tmob && ( tmob.restrained() && !( M.restrained() ) && M.stat == 0)) || locate(/obj/item/weapon/grab, tmob.grabbed_by.len)) ) if ( !(world.time % 5) ) - src << "\red [tmob] is restrained, you cannot push past" + src << "[tmob] is restrained, you cannot push past." now_pushing = 0 return if( tmob.pulling == M && ( M.restrained() && !( tmob.restrained() ) && tmob.stat == 0) ) if ( !(world.time % 5) ) - src << "\red [tmob] is restraining [M], you cannot push past" + src << "[tmob] is restraining [M], you cannot push past." now_pushing = 0 return @@ -198,7 +198,7 @@ /mob/living/carbon/human/blob_act() if(stat == 2) return - show_message("\red The blob attacks you!") + show_message(" The blob attacks you!") var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") var/obj/item/organ/limb/affecting = get_organ(ran_zone(dam_zone)) apply_damage(rand(20,30), BRUTE, affecting, run_armor_check(affecting, "melee")) @@ -211,8 +211,8 @@ else if(M.attack_sound) playsound(loc, M.attack_sound, 50, 1, 1) - for(var/mob/O in viewers(src, null)) - O.show_message("\red [M] [M.attacktext] [src]!", 1) + visible_message("[M] [M.attacktext] [src]!", \ + "[M] [M.attacktext]!") add_logs(M, src, "attacked", admin=0) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") @@ -227,9 +227,8 @@ if (health > -100) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red The [M.name] glomps []!", src), 1) + visible_message("The [M.name] glomps [src]!", \ + "The [M.name] glomps [src]!") var/damage = rand(1, 3) @@ -262,10 +261,8 @@ M.powerlevel -= 3 if(M.powerlevel < 0) M.powerlevel = 0 - - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red The [M.name] has shocked []!", src), 1) + visible_message("The [M.name] has shocked [src]!", \ + "The [M.name] has shocked [src]!") Weaken(power) if (stuttering < power) @@ -344,7 +341,7 @@ dat += "
Uniform: Obscured by [wear_suit]" else dat += "
Uniform: [(w_uniform && !(w_uniform.flags&ABSTRACT)) ? w_uniform : "Empty"]" - if(w_uniform) + if(w_uniform || dna.species.nojumpsuit) dat += "
[TAB]↳Belt: [(belt && !(belt.flags&ABSTRACT)) ? belt : "Empty"]" if(has_breathable_mask && istype(belt, /obj/item/weapon/tank)) dat += "
[TAB][TAB]↳[internal ? "Disable Internals" : "Set Internals"]" @@ -352,12 +349,31 @@ dat += " [(r_store && !(r_store.flags&ABSTRACT)) ? "Right (Full)" : "Right (Empty)"]" dat += "
[TAB]↳ID: [(wear_id && !(wear_id.flags&ABSTRACT)) ? wear_id : "Empty"]" + if(dna) + if(dna.species.nojumpsuit) + dat += "
ID: [(wear_id && !(wear_id.flags&ABSTRACT)) ? wear_id : "Nothing"]" + else if(w_uniform) + dat += "
ID: [(wear_id && !(wear_id.flags&ABSTRACT)) ? wear_id : "Nothing"]" + else if(w_uniform) + dat += "
ID: [(wear_id && !(wear_id.flags&ABSTRACT)) ? wear_id : "Nothing"]" + dat += "
" if(handcuffed) dat += "
Handcuffed: Remove" if(legcuffed) - dat += "
Legcuffed: Remove" + dat += "
Legcuffed" + + if(dna) + if(dna.species.nojumpsuit) + dat += "

Left Pocket ([(l_store && !(l_store.flags&ABSTRACT)) ? "Full" : "Empty"])" + dat += " - Right Pocket ([(r_store && !(r_store.flags&ABSTRACT)) ? "Full" : "Empty"])" + else if(w_uniform) + dat += "

Left Pocket ([(l_store && !(l_store.flags&ABSTRACT)) ? "Full" : "Empty"])" + dat += " - Right Pocket ([(r_store && !(r_store.flags&ABSTRACT)) ? "Full" : "Empty"])" + else if(w_uniform) + dat += "

Left Pocket ([(l_store && !(l_store.flags&ABSTRACT)) ? "Full" : "Empty"])" + dat += " - Right Pocket ([(r_store && !(r_store.flags&ABSTRACT)) ? "Full" : "Empty"])" dat += {"
@@ -467,7 +483,7 @@ H.handle_regular_hud_updates() if(!modified) - usr << "\red Unable to locate a data core entry for this person." + usr << "Unable to locate a data core entry for this person." /mob/living/carbon/human/proc/play_xylophone() if(!src.xylophone) @@ -516,4 +532,4 @@ if(obscured.len > 0) return obscured else - return null + return null diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 0d1ef146670..d703a7ab610 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -2,163 +2,9 @@ if(..()) //to allow surgery to return properly. return - if((M != src) && check_shields(0, M.name)) - add_logs(M, src, "attempted to touch") - visible_message("[M] attempted to touch [src]!") - return 0 + if(dna) + dna.species.spec_attack_hand(M, src) - switch(M.a_intent) - if("help") - if(health >= 0) - help_shake_act(M) - if(src != M) - add_logs(M, src, "shaked") - return 1 - - //CPR - if((M.head && (M.head.flags & HEADCOVERSMOUTH)) || (M.wear_mask && (M.wear_mask.flags & MASKCOVERSMOUTH))) - M << "Remove your mask!" - return 0 - if((head && (head.flags & HEADCOVERSMOUTH)) || (wear_mask && (wear_mask.flags & MASKCOVERSMOUTH))) - M << "Remove their mask!" - return 0 - - if(cpr_time < world.time + 30) - add_logs(src, M, "CPRed") - visible_message("[M] is trying to perform CPR on [src]!") - if(!do_mob(M, src)) - return 0 - if((health >= -99 && health <= 0)) - cpr_time = world.time - var/suff = min(getOxyLoss(), 7) - adjustOxyLoss(-suff) - updatehealth() - M.visible_message("[M] performs CPR on [src]!") - src << "You feel a breath of fresh air enter your lungs. It feels good." - - if("grab") - if(M == src || anchored) - return 0 - - add_logs(M, src, "grabbed", addition="passively") - - if(w_uniform) - w_uniform.add_fingerprint(M) - - var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src) - if(buckled) - M << "You cannot grab [src], \he is buckled in!" - if(!G) //the grab will delete itself in New if affecting is anchored - return - M.put_in_active_hand(G) - G.synch() - LAssailant = M - - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("[M] has grabbed [src] passively!") - return 1 - - if("harm") - add_logs(M, src, "punched") - - var/attack_verb = "punch" - if(lying) - attack_verb = "kick" - else if(M.dna) - switch(M.dna.mutantrace) - if("lizard") - attack_verb = "scratch" - if("plant") - attack_verb = "slash" - - var/damage = rand(0, 9) - if(!damage) - switch(attack_verb) - if("slash") - playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - else - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - - visible_message("[M] has attempted to [attack_verb] [src]!") - return 0 - - - var/obj/item/organ/limb/affecting = get_organ(ran_zone(M.zone_sel.selecting)) - var/armor_block = run_armor_check(affecting, "melee") - - if(HULK in M.mutations) - damage += 5 - - switch(attack_verb) - if("slash") - playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) - else - playsound(loc, "punch", 25, 1, -1) - - visible_message("[M] has [attack_verb]ed [src]!", \ - "[M] has [attack_verb]ed [src]!") - - apply_damage(damage, BRUTE, affecting, armor_block) - if((stat != DEAD) && damage >= 9) - visible_message("[M] has weakened [src]!", \ - "[M] has weakened [src]!") - apply_effect(4, WEAKEN, armor_block) - forcesay(hit_appends) - else if(lying) - forcesay(hit_appends) - - if("disarm") - add_logs(M, src, "disarmed") - - if(w_uniform) - w_uniform.add_fingerprint(M) - var/obj/item/organ/limb/affecting = get_organ(ran_zone(M.zone_sel.selecting)) - var/randn = rand(1, 100) - if(randn <= 25) - apply_effect(2, WEAKEN, run_armor_check(affecting, "melee")) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - visible_message("[M] has pushed [src]!", - "[M] has pushed [src]!") - forcesay(hit_appends) - return - - var/talked = 0 // BubbleWrap - - if(randn <= 60) - //BubbleWrap: Disarming breaks a pull - if(pulling) - visible_message("[M] has broken [src]'s grip on [pulling]!") - talked = 1 - stop_pulling() - - //BubbleWrap: Disarming also breaks a grab - this will also stop someone being choked, won't it? - if(istype(l_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/lgrab = l_hand - if(lgrab.affecting) - visible_message("[M] has broken [src]'s grip on [lgrab.affecting]!") - talked = 1 - spawn(1) - qdel(lgrab) - if(istype(r_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/rgrab = r_hand - if(rgrab.affecting) - visible_message("[M] has broken [src]'s grip on [rgrab.affecting]!") - talked = 1 - spawn(1) - qdel(rgrab) - //End BubbleWrap - - if(!talked) //BubbleWrap - if(drop_item()) - visible_message("[M] has disarmed [src]!", \ - "[M] has disarmed [src]!") - playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - return - - - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[M] attempted to disarm [src]!", \ - "[M] attemped to disarm [src]!") return /mob/living/carbon/human/proc/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, inrange, params) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index c1c1e7240f1..633e72059db 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -102,6 +102,7 @@ mob/living/carbon/human/proc/hat_fall_prob() var/obj/item/organ/limb/picked = pick(parts) if(picked.take_damage(brute,burn)) update_damage_overlays(0) + updatehealth() @@ -128,6 +129,7 @@ mob/living/carbon/human/proc/hat_fall_prob() // damage MANY external organs, in random order /mob/living/carbon/human/take_overall_damage(var/brute, var/burn) if(status_flags & GODMODE) return //godmode + var/list/obj/item/organ/limb/parts = get_damageable_organs() var/update = 0 while(parts.len && (brute>0 || burn>0) ) @@ -143,7 +145,9 @@ mob/living/carbon/human/proc/hat_fall_prob() burn -= (picked.burn_dam - burn_was) parts -= picked + updatehealth() + if(update) update_damage_overlays(0) @@ -159,34 +163,38 @@ mob/living/carbon/human/proc/hat_fall_prob() /mob/living/carbon/human/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0) - if((damagetype != BRUTE) && (damagetype != BURN)) - ..(damage, damagetype, def_zone, blocked) - return 1 - - blocked = (100-blocked)/100 - if(blocked <= 0) return 0 - - var/obj/item/organ/limb/organ = null - if(isorgan(def_zone)) - organ = def_zone + if(dna) // if you have a species, it will run the apply_damage code there instead + dna.species.apply_damage(damage, damagetype, def_zone, blocked, src) else - if(!def_zone) def_zone = ran_zone(def_zone) - organ = get_organ(check_zone(def_zone)) - if(!organ) return 0 + if((damagetype != BRUTE) && (damagetype != BURN)) + ..(damage, damagetype, def_zone, blocked) + return 1 - damage = (damage * blocked) + else + blocked = (100-blocked)/100 + if(blocked <= 0) return 0 - switch(damagetype) - if(BRUTE) - damageoverlaytemp = 20 - if(organ.take_damage(damage, 0)) - update_damage_overlays(0) - if(BURN) - damageoverlaytemp = 20 - if(organ.take_damage(0, damage)) - update_damage_overlays(0) + var/obj/item/organ/limb/organ = null + if(isorgan(def_zone)) + organ = def_zone + else + if(!def_zone) def_zone = ran_zone(def_zone) + organ = get_organ(check_zone(def_zone)) + if(!organ) return 0 - // Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life(). + damage = (damage * blocked) - updatehealth() + switch(damagetype) + if(BRUTE) + damageoverlaytemp = 20 + if(organ.take_damage(damage, 0)) + update_damage_overlays(0) + if(BURN) + damageoverlaytemp = 20 + if(organ.take_damage(0, damage)) + update_damage_overlays(0) + + // Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life(). + + updatehealth() return 1 diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 76ef3e5583d..4048c7e762c 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -36,6 +36,11 @@ emp_act protection += C.armor[type] return protection +/mob/living/carbon/human/on_hit(proj_type) + if(dna) + dna.species.on_hit(proj_type, src) + return + /mob/living/carbon/human/bullet_act(var/obj/item/projectile/P, var/def_zone) if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) if(check_reflect(def_zone)) // Checks if you've passed a reflection% check @@ -118,94 +123,93 @@ emp_act /mob/living/carbon/human/attacked_by(var/obj/item/I, var/mob/living/user, var/def_zone) if(!I || !user) return 0 + var/obj/item/organ/limb/target_limb = get_organ(user.zone_sel.selecting) var/obj/item/organ/limb/affecting = get_organ(ran_zone(user.zone_sel.selecting)) - var/hit_area = parse_zone(affecting.name) + var/target_area = parse_zone(target_limb.name) - if((user != src) && check_shields(I.force, "the [I.name]")) - return 0 + if(dna) // allows your species to affect the attacked_by code + return dna.species.spec_attacked_by(I,user,def_zone,affecting,hit_area,src.a_intent,target_limb,target_area,src) - if(I.attack_verb && I.attack_verb.len) - visible_message("[src] has been [pick(I.attack_verb)] in the [hit_area] with [I] by [user]!", \ - "[src] has been [pick(I.attack_verb)] in the [hit_area] with [I] by [user]!") - else if(I.force) - visible_message("[src] has been attacked in the [hit_area] with [I] by [user]!", \ - "[src] has been attacked in the [hit_area] with [I] by [user]!") else - return 0 + if((user != src) && check_shields(I.force, "the [I.name]")) + return 0 - var/armor = run_armor_check(affecting, "melee", "Your armour has protected your [hit_area].", "Your armour has softened a hit to your [hit_area].") - if(armor >= 100) return 0 - var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords) + if(I.attack_verb && I.attack_verb.len) + visible_message("[src] has been [pick(I.attack_verb)] in the [hit_area] with [I] by [user]!", \ + "[src] has been [pick(I.attack_verb)] in the [hit_area] with [I] by [user]!") + else if(I.force) + visible_message("[src] has been attacked in the [hit_area] with [I] by [user]!", \ + "[src] has been attacked in the [hit_area] with [I] by [user]!") + else + return 0 - apply_damage(I.force, I.damtype, affecting, armor , I) + var/armor = run_armor_check(affecting, "melee", "Your armour has protected your [hit_area].", "Your armour has softened a hit to your [hit_area].") + if(armor >= 100) return 0 + var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords) - var/bloody = 0 - if(((I.damtype == BRUTE) && prob(25 + (I.force * 2)))) - if(affecting.status == ORGAN_ORGANIC) - I.add_blood(src) //Make the weapon bloody, not the person. - if(prob(I.force * 2)) //blood spatter! - bloody = 1 - var/turf/location = loc - if(istype(location, /turf/simulated)) - location.add_blood(src) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(get_dist(H, src) <= 1) //people with TK won't get smeared with blood - if(H.wear_suit) - H.wear_suit.add_blood(src) - H.update_inv_wear_suit(0) //updates mob overlays to show the new blood (no refresh) - else if(H.w_uniform) - H.w_uniform.add_blood(src) - H.update_inv_w_uniform(0) //updates mob overlays to show the new blood (no refresh) - if (H.gloves) - var/obj/item/clothing/gloves/G = H.gloves - G.add_blood(H) - else - H.add_blood(H) - H.update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves + apply_damage(I.force, I.damtype, affecting, armor , I) + var/bloody = 0 + if(((I.damtype == BRUTE) && prob(25 + (I.force * 2)))) + if(affecting.status == ORGAN_ORGANIC) + I.add_blood(src) //Make the weapon bloody, not the person. + if(prob(I.force * 2)) //blood spatter! + bloody = 1 + var/turf/location = loc + if(istype(location, /turf/simulated)) + location.add_blood(src) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(get_dist(H, src) <= 1) //people with TK won't get smeared with blood + if(H.wear_suit) + H.wear_suit.add_blood(src) + H.update_inv_wear_suit(0) //updates mob overlays to show the new blood (no refresh) + else if(H.w_uniform) + H.w_uniform.add_blood(src) + H.update_inv_w_uniform(0) //updates mob overlays to show the new blood (no refresh) + if (H.gloves) + var/obj/item/clothing/gloves/G = H.gloves + G.add_blood(H) + else + H.add_blood(H) + H.update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves - switch(hit_area) - if("head") //Harder to score a stun but if you do it lasts a bit longer - if(stat == CONSCIOUS && prob(I.force)) - if(Iforce >= 5) + switch(hit_area) + if("head") //Harder to score a stun but if you do it lasts a bit longer + if(stat == CONSCIOUS && prob(I.force)) visible_message("[src] has been knocked unconscious!", \ "[src] has been knocked unconscious!") apply_effect(20, PARALYZE, armor) if(src != user && I.damtype == BRUTE) ticker.mode.remove_revolutionary(mind) + if(bloody) //Apply blood + if(wear_mask) + wear_mask.add_blood(src) + update_inv_wear_mask(0) + if(head) + head.add_blood(src) + update_inv_head(0) + if(glasses && prob(33)) + glasses.add_blood(src) + update_inv_glasses(0) - if(bloody) //Apply blood - if(wear_mask) - wear_mask.add_blood(src) - update_inv_wear_mask(0) - if(head) - head.add_blood(src) - update_inv_head(0) - if(glasses && prob(33)) - glasses.add_blood(src) - update_inv_glasses(0) - - if("chest") //Easier to score a stun but lasts less time - if(stat == CONSCIOUS && prob(I.force + 10)) - if(Iforce >= 5) + if("chest") //Easier to score a stun but lasts less time + if(stat == CONSCIOUS && prob(I.force + 10)) visible_message("[src] has been knocked down!", \ "[src] has been knocked down!") apply_effect(5, WEAKEN, armor) - if(bloody) - if(wear_suit) - wear_suit.add_blood(src) - update_inv_wear_suit(0) - if(w_uniform) - w_uniform.add_blood(src) - update_inv_w_uniform(0) - - if(Iforce > 10 || Iforce >= 5 && prob(33)) - forcesay(hit_appends) //forcesay checks stat already. - + if(bloody) + if(wear_suit) + wear_suit.add_blood(src) + update_inv_wear_suit(0) + if(w_uniform) + w_uniform.add_blood(src) + update_inv_w_uniform(0) + if(Iforce > 10 || Iforce >= 5 && prob(33)) + forcesay(hit_appends) //forcesay checks stat already /mob/living/carbon/human/emp_act(severity) var/informed = 0 diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index ba27693b4c6..3fffa8a5958 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -34,7 +34,7 @@ var/obj/item/l_store = null var/obj/item/s_store = null - var/base_icon_state = "caucasian1_m" + var/icon/base_icon_state = "caucasian1_m" var/list/organs = list() //Gets filled up in the constructor (human.dm, New() proc, line 24. I'm sick and tired of missing comments. -Agouri diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 6b59a125648..3af3219a129 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -119,4 +119,11 @@ return 1//Humans can use guns and such /mob/living/carbon/human/InCritical() - return (health <= config.health_threshold_crit && stat == UNCONSCIOUS) \ No newline at end of file + return (health <= config.health_threshold_crit && stat == UNCONSCIOUS) + +/mob/living/carbon/human/reagent_check(datum/reagent/R) + if(dna) + var/bypass = dna.species.handle_chemicals(R,src) + return bypass // if it returns 0, it will run the usual on_mob_life for that reagent. otherwise, it will stop after running handle_chemicals for the species. + else + return 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 905c9adaf4d..438fb8c650b 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -1,29 +1,6 @@ /mob/living/carbon/human/movement_delay() - if(!has_gravity(src)) - return -1 //It's hard to be slowed down in space by... anything - else if(status_flags & GOTTAGOFAST) - return -1 - - . = 0 - var/health_deficiency = (100 - health + staminaloss) - if(health_deficiency >= 40) - . += (health_deficiency / 25) - - var/hungry = (500 - nutrition) / 5 //So overeat would be 100 and default level would be 80 - if(hungry >= 70) - . += hungry / 50 - - if(wear_suit) - . += wear_suit.slowdown - if(shoes) - . += shoes.slowdown - if(back) - . += back.slowdown - - if(FAT in mutations) - . += 1.5 - if(bodytemperature < 283.222) - . += (283.222 - bodytemperature) / 10 * 1.75 + if(dna) + . += dna.species.movement_delay(src) . += ..() . += config.human_delay diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index ac1cddac276..9e99030ba8d 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -1,153 +1,156 @@ /mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = 0) - switch(slot) - if(slot_l_hand) - if(l_hand) - return 0 - return 1 - if(slot_r_hand) - if(r_hand) - return 0 - return 1 - if(slot_wear_mask) - if(wear_mask) - return 0 - if( !(I.slot_flags & SLOT_MASK) ) - return 0 - return 1 - if(slot_back) - if(back) - return 0 - if( !(I.slot_flags & SLOT_BACK) ) - return 0 - return 1 - if(slot_wear_suit) - if(wear_suit) - return 0 - if( !(I.slot_flags & SLOT_OCLOTHING) ) - return 0 - return 1 - if(slot_gloves) - if(gloves) - return 0 - if( !(I.slot_flags & SLOT_GLOVES) ) - return 0 - return 1 - if(slot_shoes) - if(shoes) - return 0 - if( !(I.slot_flags & SLOT_FEET) ) - return 0 - return 1 - if(slot_belt) - if(belt) - return 0 - if(!w_uniform) - if(!disable_warning) - src << "\red You need a jumpsuit before you can attach this [I.name]." - return 0 - if( !(I.slot_flags & SLOT_BELT) ) - return - return 1 - if(slot_glasses) - if(glasses) - return 0 - if( !(I.slot_flags & SLOT_EYES) ) - return 0 - return 1 - if(slot_head) - if(head) - return 0 - if( !(I.slot_flags & SLOT_HEAD) ) - return 0 - return 1 - if(slot_ears) - if(ears) - return 0 - if( !(I.slot_flags & SLOT_EARS) ) - return 0 - return 1 - if(slot_w_uniform) - if(w_uniform) - return 0 - if( !(I.slot_flags & SLOT_ICLOTHING) ) - return 0 - return 1 - if(slot_wear_id) - if(wear_id) - return 0 - if(!w_uniform) - if(!disable_warning) - src << "\red You need a jumpsuit before you can attach this [I.name]." - return 0 - if( !(I.slot_flags & SLOT_ID) ) - return 0 - return 1 - if(slot_l_store) - if(I.flags & NODROP) //Pockets aren't visible, so you can't move NODROP items into them. - return 0 - if(l_store) - return 0 - if(!w_uniform) - if(!disable_warning) - src << "\red You need a jumpsuit before you can attach this [I.name]." - return 0 - if(I.slot_flags & SLOT_DENYPOCKET) - return - if( I.w_class <= 2 || (I.slot_flags & SLOT_POCKET) ) + if(dna) + return dna.species.can_equip(I, slot, disable_warning, src) + else + switch(slot) + if(slot_l_hand) + if(l_hand) + return 0 return 1 - if(slot_r_store) - if(I.flags & NODROP) - return 0 - if(r_store) - return 0 - if(!w_uniform) - if(!disable_warning) - src << "\red You need a jumpsuit before you can attach this [I.name]." - return 0 - if(I.slot_flags & SLOT_DENYPOCKET) - return 0 - if( I.w_class <= 2 || (I.slot_flags & SLOT_POCKET) ) + if(slot_r_hand) + if(r_hand) + return 0 return 1 - return 0 - if(slot_s_store) - if(I.flags & NODROP) //Suit storage NODROP items drop if you take a suit off, this is to prevent people exploiting this. - return 0 - if(s_store) - return 0 - if(!wear_suit) - if(!disable_warning) - src << "\red You need a suit before you can attach this [I.name]." - return 0 - if(!wear_suit.allowed) - if(!disable_warning) - usr << "You somehow have a suit with no defined allowed items for suit storage, stop that." //should be src? - return 0 - if(I.w_class > 4) - if(!disable_warning) - usr << "The [I.name] is too big to attach." //should be src? - return 0 - if( istype(I, /obj/item/device/pda) || istype(I, /obj/item/weapon/pen) || is_type_in_list(I, wear_suit.allowed) ) //ugly and un-polymorphic. + if(slot_wear_mask) + if(wear_mask) + return 0 + if( !(I.slot_flags & SLOT_MASK) ) + return 0 return 1 - return 0 - if(slot_handcuffed) - if(handcuffed) - return 0 - if(!istype(I, /obj/item/weapon/handcuffs)) - return 0 - return 1 - if(slot_legcuffed) - if(legcuffed) - return 0 - if(!istype(I, /obj/item/weapon/legcuffs)) - return 0 - return 1 - if(slot_in_backpack) - if (back && istype(back, /obj/item/weapon/storage/backpack)) - var/obj/item/weapon/storage/backpack/B = back - if(B.contents.len < B.storage_slots && I.w_class <= B.max_w_class) + if(slot_back) + if(back) + return 0 + if( !(I.slot_flags & SLOT_BACK) ) + return 0 + return 1 + if(slot_wear_suit) + if(wear_suit) + return 0 + if( !(I.slot_flags & SLOT_OCLOTHING) ) + return 0 + return 1 + if(slot_gloves) + if(gloves) + return 0 + if( !(I.slot_flags & SLOT_GLOVES) ) + return 0 + return 1 + if(slot_shoes) + if(shoes) + return 0 + if( !(I.slot_flags & SLOT_FEET) ) + return 0 + return 1 + if(slot_belt) + if(belt) + return 0 + if(!w_uniform) + if(!disable_warning) + src << "\red You need a jumpsuit before you can attach this [I.name]." + return 0 + if( !(I.slot_flags & SLOT_BELT) ) + return + return 1 + if(slot_glasses) + if(glasses) + return 0 + if( !(I.slot_flags & SLOT_EYES) ) + return 0 + return 1 + if(slot_head) + if(head) + return 0 + if( !(I.slot_flags & SLOT_HEAD) ) + return 0 + return 1 + if(slot_ears) + if(ears) + return 0 + if( !(I.slot_flags & SLOT_EARS) ) + return 0 + return 1 + if(slot_w_uniform) + if(w_uniform) + return 0 + if( !(I.slot_flags & SLOT_ICLOTHING) ) + return 0 + return 1 + if(slot_wear_id) + if(wear_id) + return 0 + if(!w_uniform) + if(!disable_warning) + src << "\red You need a jumpsuit before you can attach this [I.name]." + return 0 + if( !(I.slot_flags & SLOT_ID) ) + return 0 + return 1 + if(slot_l_store) + if(I.flags & NODROP) //Pockets aren't visible, so you can't move NODROP items into them. + return 0 + if(l_store) + return 0 + if(!w_uniform) + if(!disable_warning) + src << "\red You need a jumpsuit before you can attach this [I.name]." + return 0 + if(I.slot_flags & SLOT_DENYPOCKET) + return + if( I.w_class <= 2 || (I.slot_flags & SLOT_POCKET) ) return 1 - return 0 - return 0 //Unsupported slot + if(slot_r_store) + if(I.flags & NODROP) + return 0 + if(r_store) + return 0 + if(!w_uniform) + if(!disable_warning) + src << "\red You need a jumpsuit before you can attach this [I.name]." + return 0 + if(I.slot_flags & SLOT_DENYPOCKET) + return 0 + if( I.w_class <= 2 || (I.slot_flags & SLOT_POCKET) ) + return 1 + return 0 + if(slot_s_store) + if(I.flags & NODROP) //Suit storage NODROP items drop if you take a suit off, this is to prevent people exploiting this. + return 0 + if(s_store) + return 0 + if(!wear_suit) + if(!disable_warning) + src << "\red You need a suit before you can attach this [I.name]." + return 0 + if(!wear_suit.allowed) + if(!disable_warning) + usr << "You somehow have a suit with no defined allowed items for suit storage, stop that." //should be src? + return 0 + if(I.w_class > 4) + if(!disable_warning) + usr << "The [I.name] is too big to attach." //should be src? + return 0 + if( istype(I, /obj/item/device/pda) || istype(I, /obj/item/weapon/pen) || is_type_in_list(I, wear_suit.allowed) ) //ugly and un-polymorphic. + return 1 + return 0 + if(slot_handcuffed) + if(handcuffed) + return 0 + if(!istype(I, /obj/item/weapon/handcuffs)) + return 0 + return 1 + if(slot_legcuffed) + if(legcuffed) + return 0 + if(!istype(I, /obj/item/weapon/legcuffs)) + return 0 + return 1 + if(slot_in_backpack) + if (back && istype(back, /obj/item/weapon/storage/backpack)) + var/obj/item/weapon/storage/backpack/B = back + if(B.contents.len < B.storage_slots && I.w_class <= B.max_w_class) + return 1 + return 0 + return 0 //Unsupported slot @@ -383,5 +386,4 @@ return else src << "\red You are trying to equip this item to an unsupported inventory slot. Report this to a coder!" - return - + return \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 341bc28445e..65d0d00b9b0 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1,6 +1,11 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 //NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick! + + +#define TINT_IMPAIR 2 //Threshold of tint level to apply weld mask overlay +#define TINT_BLIND 3 //Threshold of tint level to obscure vision fully + #define HUMAN_MAX_OXYLOSS 3 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it. #define HUMAN_CRIT_MAX_OXYLOSS ( (last_tick_duration) /3) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 100HP to get through, so (1/3)*last_tick_duration per second. Breaths however only happen every 4 ticks. @@ -21,9 +26,6 @@ #define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point #define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point -#define TINT_IMPAIR 2 //Threshold of tint level to apply weld mask overlay -#define TINT_BLIND 3 //Threshold of tint level to obscure vision fully - /mob/living/carbon/human var/oxygen_alert = 0 var/toxins_alert = 0 @@ -51,7 +53,6 @@ fire_alert = 0 //Reset this here, because both breathe() and handle_environment() have a chance to set it. tinttotal = tintcheck() //here as both hud updates and status updates call it - //TODO: seperate this out var/datum/gas_mixture/environment = loc.return_air() @@ -98,6 +99,9 @@ handle_regular_hud_updates() + if(dna) + dna.species.spec_life(src) // for mutantraces + // Grabbing for(var/obj/item/weapon/grab/G in src) G.process() @@ -163,132 +167,14 @@ proc/handle_mutations_and_radiation() - if(getFireLoss()) - if((COLD_RESISTANCE in mutations) || (prob(1))) - heal_organ_damage(0,1) - - if ((HULK in mutations) && health <= 25) - mutations.Remove(HULK) - update_mutations() //update our mutation overlays - src << "\red You suddenly feel very weak." - Weaken(3) - emote("collapse") - - if (radiation) - if (radiation > 100) - radiation = 100 - Weaken(10) - src << "\red You feel weak." - emote("collapse") - - if (radiation < 0) - radiation = 0 - - else - switch(radiation) - if(1 to 49) - radiation-- - if(prob(25)) - adjustToxLoss(1) - updatehealth() - - if(50 to 74) - radiation -= 2 - adjustToxLoss(1) - if(prob(5)) - radiation -= 5 - Weaken(3) - src << "\red You feel weak." - emote("collapse") - if(prob(15)) - if(!( hair_style == "Shaved") || !(hair_style == "Bald")) - src << "Your hair starts to fall out in clumps..." - spawn(50) - facial_hair_style = "Shaved" - hair_style = "Bald" - update_hair() - updatehealth() - - if(75 to 100) - radiation -= 3 - adjustToxLoss(3) - if(prob(1)) - src << "\red You mutate!" - randmutb(src) - domutcheck(src,null) - emote("gasp") - updatehealth() - + if(dna) + dna.species.handle_mutations_and_radiation(src) proc/breathe() + if(dna) + dna.species.breathe(src) - if(reagents.has_reagent("lexorin")) return - if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return - - var/datum/gas_mixture/environment = loc.return_air() - var/datum/gas_mixture/breath - // HACK NEED CHANGING LATER - if(health <= config.health_threshold_crit) - losebreath++ - - if(losebreath>0) //Suffocating so do not take a breath - losebreath-- - if (prob(10)) //Gasp per 10 ticks? Sounds about right. - spawn emote("gasp") - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - else - //First, check for air from internal atmosphere (using an air tank and mask generally) - breath = get_breath_from_internal(BREATH_VOLUME) // Super hacky -- TLE - //breath = get_breath_from_internal(0.5) // Manually setting to old BREATH_VOLUME amount -- TLE - - //No breath from internal atmosphere so get breath from location - if(!breath) - if(isobj(loc)) - var/obj/location_as_object = loc - breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME) - else if(isturf(loc)) - var/breath_moles = 0 - /*if(environment.return_pressure() > ONE_ATMOSPHERE) - // Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT) - breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) - else*/ - // Not enough air around, take a percentage of what's there to model this properly - breath_moles = environment.total_moles()*BREATH_PERCENTAGE - - breath = loc.remove_air(breath_moles) - // Handle chem smoke effect -- Doohl - var/block = 0 - if(wear_mask) - if(wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT) - block = 1 - if(glasses) - if(glasses.flags & BLOCK_GAS_SMOKE_EFFECT) - block = 1 - if(head) - if(head.flags & BLOCK_GAS_SMOKE_EFFECT) - block = 1 - - if(!block) - - for(var/obj/effect/effect/chem_smoke/smoke in view(1, src)) - if(smoke.reagents.total_volume) - smoke.reagents.reaction(src, INGEST) - spawn(5) - if(smoke) - smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? - break // If they breathe in the nasty stuff once, no need to continue checking - - else //Still give containing object the chance to interact - if(istype(loc, /obj/)) - var/obj/location_as_object = loc - location_as_object.handle_internal_lifeform(src, 0) - - handle_breath(breath) - - if(breath) - loc.assume_air(breath) + return proc/get_breath_from_internal(volume_needed) @@ -304,229 +190,45 @@ return null - proc/handle_breath(datum/gas_mixture/breath) + /*proc/handle_breath(datum/gas_mixture/breath) if((status_flags & GODMODE)) return - if(!breath || (breath.total_moles() == 0) || suiciding) - if(reagents.has_reagent("inaprovaline")) - return - if(suiciding) - adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster - failed_last_breath = 1 - oxygen_alert = max(oxygen_alert, 1) - return 0 - if(health >= config.health_threshold_crit) - adjustOxyLoss(HUMAN_MAX_OXYLOSS) - failed_last_breath = 1 - else - adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS) - failed_last_breath = 1 + if(dna) + dna.species.handle_breath(breath) - oxygen_alert = max(oxygen_alert, 1) - - return 0 - - var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa - //var/safe_oxygen_max = 140 // Maximum safe partial pressure of O2, in kPa (Not used for now) - var/safe_co2_max = 10 // Yes it's an arbitrary value who cares? - var/safe_toxins_max = 0.005 - var/SA_para_min = 1 - var/SA_sleep_min = 5 - var/oxygen_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME - - //Partial pressure of the O2 in our breath - var/O2_pp = (breath.oxygen/breath.total_moles())*breath_pressure - // Same, but for the toxins - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure - // And CO2, lets say a PP of more than 10 will be bad (It's a little less really, but eh, being passed out all round aint no fun) - var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*breath_pressure // Tweaking to fit the hacky bullshit I've done with atmo -- TLE - //var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*0.5 // The default pressure value - - if(O2_pp < safe_oxygen_min) // Too little oxygen - if(prob(20)) - spawn(0) emote("gasp") - if(O2_pp > 0) - var/ratio = safe_oxygen_min/O2_pp - adjustOxyLoss(min(5*ratio, HUMAN_MAX_OXYLOSS)) // Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!) - failed_last_breath = 1 - oxygen_used = breath.oxygen*ratio/6 - else - adjustOxyLoss(HUMAN_MAX_OXYLOSS) - failed_last_breath = 1 - oxygen_alert = max(oxygen_alert, 1) - /*else if (O2_pp > safe_oxygen_max) // Too much oxygen (commented this out for now, I'll deal with pressure damage elsewhere I suppose) - spawn(0) emote("cough") - var/ratio = O2_pp/safe_oxygen_max - oxyloss += 5*ratio - oxygen_used = breath.oxygen*ratio/6 - oxygen_alert = max(oxygen_alert, 1)*/ - else // We're in safe limits - failed_last_breath = 0 - adjustOxyLoss(-5) - oxygen_used = breath.oxygen/6 - oxygen_alert = 0 - - breath.oxygen -= oxygen_used - breath.carbon_dioxide += oxygen_used - - //CO2 does not affect failed_last_breath. So if there was enough oxygen in the air but too much co2, this will hurt you, but only once per 4 ticks, instead of once per tick. - if(CO2_pp > safe_co2_max) - if(!co2overloadtime) // If it's the first breath with too much CO2 in it, lets start a counter, then have them pass out after 12s or so. - co2overloadtime = world.time - else if(world.time - co2overloadtime > 120) - Paralyse(3) - adjustOxyLoss(3) // Lets hurt em a little, let them know we mean business - if(world.time - co2overloadtime > 300) // They've been in here 30s now, lets start to kill them for their own good! - adjustOxyLoss(8) - if(prob(20)) // Lets give them some chance to know somethings not right though I guess. - spawn(0) emote("cough") - - else - co2overloadtime = 0 - - if(Toxins_pp > safe_toxins_max) // Too much toxins - var/ratio = (breath.toxins/safe_toxins_max) * 10 - //adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) //Limit amount of damage toxin exposure can do per second - if(reagents) - reagents.add_reagent("plasma", Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) - toxins_alert = max(toxins_alert, 1) - else - toxins_alert = 0 - - if(breath.trace_gases.len) // If there's some other shit in the air lets deal with it here. - for(var/datum/gas/sleeping_agent/SA in breath.trace_gases) - var/SA_pp = (SA.moles/breath.total_moles())*breath_pressure - if(SA_pp > SA_para_min) // Enough to make us paralysed for a bit - Paralyse(3) // 3 gives them one second to wake up and run away a bit! - if(SA_pp > SA_sleep_min) // Enough to make us sleep as well - sleeping = max(sleeping+2, 10) - else if(SA_pp > 0.01) // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning - if(prob(20)) - spawn(0) emote(pick("giggle", "laugh")) - - if( (abs(310.15 - breath.temperature) > 50) && !(COLD_RESISTANCE in mutations)) // Hot air hurts :( - if(breath.temperature < 260.15) - if(prob(20)) - src << "\red You feel your face freezing and an icicle forming in your lungs!" - else if(breath.temperature > 360.15) - if(prob(20)) - src << "\red You feel your face burning and a searing heat in your lungs!" - - switch(breath.temperature) - if(-INFINITY to 120) - apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, "head") - fire_alert = max(fire_alert, 1) - if(120 to 200) - apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, "head") - fire_alert = max(fire_alert, 1) - if(200 to 260) - apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, "head") - fire_alert = max(fire_alert, 1) - if(360 to 400) - apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, "head") - fire_alert = max(fire_alert, 2) - if(400 to 1000) - apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, "head") - fire_alert = max(fire_alert, 2) - if(1000 to INFINITY) - apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head") - fire_alert = max(fire_alert, 2) - - //Temporary fixes to the alerts. - - return 1 + return 1*/ proc/handle_environment(datum/gas_mixture/environment) - if(!environment) - return - - var/loc_temp = get_temperature(environment) - //world << "Loc temp: [loc_temp] - Body temp: [bodytemperature] - Fireloss: [getFireLoss()] - Thermal protection: [get_thermal_protection()] - Fire protection: [thermal_protection + add_fire_protection(loc_temp)] - Heat capacity: [environment_heat_capacity] - Location: [loc] - src: [src]" - - //Body temperature is adjusted in two steps. Firstly your body tries to stabilize itself a bit. - if(stat != 2) - stabilize_temperature_from_calories() - - //After then, it reacts to the surrounding atmosphere based on your thermal protection - if(!on_fire) //If you're on fire, you do not heat up or cool down based on surrounding gases - if(loc_temp < bodytemperature) - //Place is colder than we are - var/thermal_protection = get_cold_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to. - if(thermal_protection < 1) - bodytemperature += min((1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_COLD_DIVISOR), BODYTEMP_COOLING_MAX) - else - //Place is hotter than we are - var/thermal_protection = get_heat_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to. - if(thermal_protection < 1) - bodytemperature += min((1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR), BODYTEMP_HEATING_MAX) - - // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. - if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT) - //Body temperature is too hot. - fire_alert = max(fire_alert, 1) - switch(bodytemperature) - if(360 to 400) - apply_damage(HEAT_DAMAGE_LEVEL_1, BURN) - fire_alert = max(fire_alert, 2) - if(400 to 460) - apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) - fire_alert = max(fire_alert, 2) - if(460 to INFINITY) - if(on_fire) - apply_damage(HEAT_DAMAGE_LEVEL_3, BURN) - fire_alert = max(fire_alert, 2) - else - apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) - fire_alert = max(fire_alert, 2) - - else if(bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT) - fire_alert = max(fire_alert, 1) - if(!istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) - switch(bodytemperature) - if(200 to 260) - apply_damage(COLD_DAMAGE_LEVEL_1, BURN) - fire_alert = max(fire_alert, 1) - if(120 to 200) - apply_damage(COLD_DAMAGE_LEVEL_2, BURN) - fire_alert = max(fire_alert, 1) - if(-INFINITY to 120) - apply_damage(COLD_DAMAGE_LEVEL_3, BURN) - fire_alert = max(fire_alert, 1) - - // Account for massive pressure differences. Done by Polymorph - // Made it possible to actually have something that can protect against high pressure... Done by Errorage. Polymorph now has an axe sticking from his head for his previous hardcoded nonsense! - - var/pressure = environment.return_pressure() - var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob. - switch(adjusted_pressure) - if(HAZARD_HIGH_PRESSURE to INFINITY) - adjustBruteLoss( min( ( (adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) ) - pressure_alert = 2 - if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE) - pressure_alert = 1 - if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE) - pressure_alert = 0 - if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE) - pressure_alert = -1 - else - if( !(COLD_RESISTANCE in mutations) ) - adjustBruteLoss( LOW_PRESSURE_DAMAGE ) - pressure_alert = -2 - else - pressure_alert = -1 + if(dna) + dna.species.handle_environment(environment, src) return ///FIRE CODE handle_fire() + if(dna) + dna.species.handle_fire(src) + if(..()) return var/thermal_protection = get_heat_protection(30000) //If you don't have fire suit level protection, you get a temperature increase if((1 - thermal_protection) > 0.0001) bodytemperature += BODYTEMP_HEATING_MAX return + + IgniteMob() + if(dna) + dna.species.IgniteMob(src) + else + ..() + + ExtinguishMob() + if(dna) + dna.species.ExtinguishMob(src) + else + ..() + //END FIRE CODE /* @@ -650,6 +352,9 @@ if(COLD_RESISTANCE in mutations) return 1 //Fully protected from the cold. + if(dna && COLDRES in dna.species.specflags) + return 1 + temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K. var/thermal_protection_flags = get_cold_protection_flags(temperature) @@ -739,82 +444,8 @@ */ proc/handle_chemicals_in_body() - if(reagents) reagents.metabolize(src) - - if(dna && dna.mutantrace == "plant") //couldn't think of a better place to place it, since it handles nutrition -- Urist - var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing - if(isturf(loc)) //else, there's considered to be no light - var/turf/T = loc - var/area/A = T.loc - if(A) - if(A.lighting_use_dynamic) light_amount = min(10,T.lighting_lumcount) - 5 //hardcapped so it's not abused by having a ton of flashlights - else light_amount = 5 - nutrition += light_amount - if(nutrition > 500) - nutrition = 500 - if(light_amount > 2) //if there's enough light, heal - heal_overall_damage(1,1) - adjustToxLoss(-1) - adjustOxyLoss(-1) - if(dna && dna.mutantrace == "shadow") - var/light_amount = 0 - if(isturf(loc)) - var/turf/T = loc - var/area/A = T.loc - if(A) - if(A.lighting_use_dynamic) light_amount = T.lighting_lumcount - else light_amount = 10 - if(light_amount > 2) //if there's enough light, start dying - take_overall_damage(1,1) - else if (light_amount < 2) //heal in the dark - heal_overall_damage(1,1) - - //The fucking FAT mutation is the dumbest shit ever. It makes the code so difficult to work with - if(FAT in mutations) - if(overeatduration < 100) - src << "\blue You feel fit again!" - mutations -= FAT - update_inv_w_uniform(0) - update_inv_wear_suit() - else - if(overeatduration > 500) - src << "\red You suddenly feel blubbery!" - mutations |= FAT - update_inv_w_uniform(0) - update_inv_wear_suit() - - // nutrition decrease - if (nutrition > 0 && stat != 2) - nutrition = max (0, nutrition - HUNGER_FACTOR) - - if (nutrition > 450) - if(overeatduration < 600) //capped so people don't take forever to unfat - overeatduration++ - else - if(overeatduration > 1) - overeatduration -= 2 //doubled the unfat rate - - if(dna && dna.mutantrace == "plant") - if(nutrition < 200) - take_overall_damage(2,0) - - if (drowsyness) - drowsyness-- - eye_blurry = max(2, eye_blurry) - if (prob(5)) - sleeping += 1 - Paralyse(5) - - confused = max(0, confused - 1) - // decrement dizziness counter, clamped to 0 - if(resting) - dizziness = max(0, dizziness - 15) - jitteriness = max(0, jitteriness - 15) - else - dizziness = max(0, dizziness - 3) - jitteriness = max(0, jitteriness - 3) - - updatehealth() + if(dna) + dna.species.handle_chemicals_in_body(src) return //TODO: DEFERRED @@ -1048,155 +679,15 @@ damageoverlay.overlays += I damageoverlay.overlays += black - if( stat == DEAD ) - sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) - see_in_dark = 8 - if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO - if(healths) healths.icon_state = "health7" //DEAD healthmeter - else - sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS) - var/see_temp = see_invisible - see_invisible = SEE_INVISIBLE_LIVING - if(dna) - switch(dna.mutantrace) - if("slime") - see_in_dark = 3 - see_invisible = SEE_INVISIBLE_LEVEL_ONE - if("shadow") - see_in_dark = 8 - else - see_in_dark = 2 - - if(XRAY in mutations) - sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS - see_in_dark = 8 - see_invisible = SEE_INVISIBLE_LEVEL_TWO - - if(seer) - see_invisible = SEE_INVISIBLE_OBSERVER - - if(mind && mind.changeling) - hud_used.lingchemdisplay.invisibility = 0 - hud_used.lingchemdisplay.maptext = "
[src.mind.changeling.chem_charges]
" - else - hud_used.lingchemdisplay.invisibility = 101 - - if(istype(wear_mask, /obj/item/clothing/mask/gas/voice/space_ninja)) - var/obj/item/clothing/mask/gas/voice/space_ninja/O = wear_mask - switch(O.mode) - if(0) - var/target_list[] = list() - for(var/mob/living/target in oview(src)) - if( target.mind&&(target.mind.special_role||issilicon(target)) )//They need to have a mind. - target_list += target - if(target_list.len)//Everything else is handled by the ninja mask proc. - O.assess_targets(target_list, src) - see_invisible = SEE_INVISIBLE_LIVING - if(1) - see_in_dark = 5 - see_invisible = SEE_INVISIBLE_LIVING - if(2) - sight |= SEE_MOBS - see_invisible = SEE_INVISIBLE_LEVEL_TWO - if(3) - sight |= SEE_TURFS - see_invisible = SEE_INVISIBLE_LIVING - - if(glasses) - if(istype(glasses, /obj/item/clothing/glasses)) - var/obj/item/clothing/glasses/G = glasses - sight |= G.vision_flags - see_in_dark = G.darkness_view - see_invisible = G.invis_view - if(G.hud) - G.process_hud(src) - - if(druggy) //Override for druggy - see_invisible = see_temp - - if(see_override) //Override all - see_invisible = see_override - - if(healths) - switch(hal_screwyhud) - if(1) healths.icon_state = "health6" - if(2) healths.icon_state = "health7" - else - switch(health - staminaloss) - if(100 to INFINITY) healths.icon_state = "health0" - if(80 to 100) healths.icon_state = "health1" - if(60 to 80) healths.icon_state = "health2" - if(40 to 60) healths.icon_state = "health3" - if(20 to 40) healths.icon_state = "health4" - if(0 to 20) healths.icon_state = "health5" - else healths.icon_state = "health6" - - if(nutrition_icon) - switch(nutrition) - if(450 to INFINITY) nutrition_icon.icon_state = "nutrition0" - if(350 to 450) nutrition_icon.icon_state = "nutrition1" - if(250 to 350) nutrition_icon.icon_state = "nutrition2" - if(150 to 250) nutrition_icon.icon_state = "nutrition3" - else nutrition_icon.icon_state = "nutrition4" - - if(pressure) - pressure.icon_state = "pressure[pressure_alert]" - - if(pullin) - if(pulling) pullin.icon_state = "pull" - else pullin.icon_state = "pull0" -// if(rest) //Not used with new UI -// if(resting || lying || sleeping) rest.icon_state = "rest1" -// else rest.icon_state = "rest0" - if(toxin) - if(hal_screwyhud == 4 || toxins_alert) toxin.icon_state = "tox1" - else toxin.icon_state = "tox0" - if(oxygen) - if(hal_screwyhud == 3 || oxygen_alert) oxygen.icon_state = "oxy1" - else oxygen.icon_state = "oxy0" - if(fire) - if(fire_alert) fire.icon_state = "fire[fire_alert]" //fire_alert is either 0 if no alert, 1 for cold and 2 for heat. - else fire.icon_state = "fire0" - - if(bodytemp) - switch(bodytemperature) //310.055 optimal body temp - if(370 to INFINITY) bodytemp.icon_state = "temp4" - if(350 to 370) bodytemp.icon_state = "temp3" - if(335 to 350) bodytemp.icon_state = "temp2" - if(320 to 335) bodytemp.icon_state = "temp1" - if(300 to 320) bodytemp.icon_state = "temp0" - if(295 to 300) bodytemp.icon_state = "temp-1" - if(280 to 295) bodytemp.icon_state = "temp-2" - if(260 to 280) bodytemp.icon_state = "temp-3" - else bodytemp.icon_state = "temp-4" - -// This checks how much the mob's eyewear impairs their vision - if(tinttotal >= TINT_IMPAIR) - if(tinted_weldhelh) - if(tinttotal >= TINT_BLIND) - blinded = 1 // You get the sudden urge to learn to play keyboard - client.screen += global_hud.darkMask - else - client.screen += global_hud.darkMask - - if(blind) - if(blinded) blind.layer = 18 - else blind.layer = 0 - - if( disabilities & NEARSIGHTED && !istype(glasses, /obj/item/clothing/glasses/regular) ) - client.screen += global_hud.vimpaired - if(eye_blurry) client.screen += global_hud.blurry - if(druggy) client.screen += global_hud.druggy - - - if(eye_stat > 20) - if(eye_stat > 30) client.screen += global_hud.darkMask - else client.screen += global_hud.vimpaired - if(machine) if(!machine.check_eye(src)) reset_view(null) else if(!client.adminobs) reset_view(null) + + if(dna) + dna.species.handle_vision(src) + dna.species.handle_hud_icons(src) + return 1 proc/handle_random_events() diff --git a/code/modules/mob/living/carbon/human/mutantrace.dm b/code/modules/mob/living/carbon/human/mutantrace.dm new file mode 100644 index 00000000000..30615bb624c --- /dev/null +++ b/code/modules/mob/living/carbon/human/mutantrace.dm @@ -0,0 +1,22 @@ +var/global/list/colored_mutraces = list( // these mutantraces are affected by mutant color + "lizard", + "plant", + "pod", + "slime", + "jelly", + "golem" +) + +var/global/list/mutants_with_eyes = list( // these mutantraces have eyes + "lizard", + "plant", + "pod", + "jelly", +) + +/mob/living/carbon/human/proc/check_mutrace(var/mutneeded = "mut1", var/mutneededalt = "mut2") + if(dna) + if(dna.mutantrace == mutneeded || dna.mutantrace == mutneededalt) + return 1 + + return 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index cdd8b0cc80a..be98cf67ed9 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -22,24 +22,8 @@ return if(dna) - if(dna.mutantrace == "lizard") - if(copytext(message, 1, 2) != "*") - message = replacetext(message, "s", stutter("ss")) + message = dna.species.handle_speech(message,src) - if(dna.mutantrace == "fly") - if(copytext(message, 1, 2) != "*") - message = replacetext(message, "z", stutter("zz")) - - /*if(dna.mutantrace == "slime" && prob(5)) - if(copytext(message, 1, 2) != "*") - if(copytext(message, 1, 2) == ";") - message = ";" - else - message = "" - message += "SKR" - var/imax = rand(5,20) - for(var/i = 0,i= 60) + return "gibbers, \"[text]\""; + if (ending == "?") + return "asks, \"[text]\""; + if (ending == "!") + return "exclaims, \"[text]\""; + + if(dna) + return "[dna.species.say_mod], \"[text]\""; + + return "says, \"[text]\""; /mob/living/carbon/human/proc/forcesay(list/append) if(stat == CONSCIOUS) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm new file mode 100644 index 00000000000..97143b147b1 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species.dm @@ -0,0 +1,1330 @@ +// This code handles different species in the game. + +#define SPECIES_LAYER 23 +#define BODY_LAYER 22 +#define HAIR_LAYER 8 + +#define TINT_IMPAIR 2 +#define TINT_BLIND 3 + +#define HUMAN_MAX_OXYLOSS 3 +#define HUMAN_CRIT_MAX_OXYLOSS ( (last_tick_duration) /3) + +#define HEAT_DAMAGE_LEVEL_1 2 +#define HEAT_DAMAGE_LEVEL_2 3 +#define HEAT_DAMAGE_LEVEL_3 8 + +#define COLD_DAMAGE_LEVEL_1 0.5 +#define COLD_DAMAGE_LEVEL_2 1.5 +#define COLD_DAMAGE_LEVEL_3 3 + +#define HEAT_GAS_DAMAGE_LEVEL_1 2 +#define HEAT_GAS_DAMAGE_LEVEL_2 4 +#define HEAT_GAS_DAMAGE_LEVEL_3 8 + +#define COLD_GAS_DAMAGE_LEVEL_1 0.5 +#define COLD_GAS_DAMAGE_LEVEL_2 1.5 +#define COLD_GAS_DAMAGE_LEVEL_3 3 + +/datum/species + var/id = null // if the game needs to manually check your race to do something not included in a proc here, it will use this + var/name = null // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever + var/roundstart = 0 // can this mob be chosen at roundstart? (assuming the config option is checked?) + var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race + + var/eyes = "eyes" // which eyes the race uses. at the moment, the only types of eyes are "eyes" (regular eyes) and "jelleyes" (three eyes) + var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows + var/hair_color = null // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color + var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent. + var/use_skintones = 0 // does it use skintones or not? (spoiler alert this is only used by humans) + + var/list/no_equip = list() // slots the race can't equip stuff to + var/nojumpsuit = 0 // this is sorta... weird. it basically lets you equip stuff that usually needs jumpsuits without one, like belts and pockets and ids + + var/say_mod = "says" // affects the speech message + + var/speedmod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster + var/armor = 0 // overall defense for the race... or less defense, if it's negative. + var/brutemod = 1 // multiplier for brute damage + var/burnmod = 1 // multiplier for burn damage + var/coldmod = 1 // multiplier for cold damage + var/heatmod = 1 // multiplier for heat damage + var/punchmod = 0 // adds to the punch damage + + var/invis_sight = SEE_INVISIBLE_LIVING + var/darksight = 2 + + // species flags. these can be found in flags.dm + var/list/specflags = list() + + var/attack_verb = "punch" // punch-specific attack verb + var/sound/attack_sound = 'sound/weapons/punch1.ogg' + var/sound/miss_sound = 'sound/weapons/punchmiss.ogg' + + var/mob/living/list/ignored_by = list() // list of mobs that will ignore this species + + /////////// + // PROCS // + /////////// + + proc/update_base_icon_state(var/mob/living/carbon/human/H) + if(HUSK in H.mutations) + H.remove_overlay(SPECIES_LAYER) // races lose their color + return "husk" + else if(sexes) + if(use_skintones) + return "[H.skin_tone]_[(H.gender == FEMALE) ? "f" : "m"]" + else + return "[id]_[(H.gender == FEMALE) ? "f" : "m"]" + else + return "[id]" + + proc/update_color(var/mob/living/carbon/human/H) + H.remove_overlay(SPECIES_LAYER) + + var/image/standing + + var/g = (H.gender == FEMALE) ? "f" : "m" + + if(MUTCOLORS in specflags) + var/image/spec_base + if(sexes) + spec_base = image("icon" = 'icons/mob/human.dmi', "icon_state" = "[id]_[g]_s", "layer" = -SPECIES_LAYER) + else + spec_base = image("icon" = 'icons/mob/human.dmi', "icon_state" = "[id]_s", "layer" = -SPECIES_LAYER) + if(!config.mutant_colors) + H.dna.mutant_color = default_color + spec_base.color = "#[H.dna.mutant_color]" + standing = spec_base + + if(standing) + H.overlays_standing[SPECIES_LAYER] = standing + + H.apply_overlay(SPECIES_LAYER) + + proc/handle_hair(var/mob/living/carbon/human/H) + H.remove_overlay(HAIR_LAYER) + + var/datum/sprite_accessory/S + var/list/standing = list() + + if(H.facial_hair_style && FACEHAIR in specflags) + S = facial_hair_styles_list[H.facial_hair_style] + if(S) + var/image/img_facial_s + + img_facial_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER) + + if(hair_color) + if(hair_color == "mutcolor") + if(!config.mutant_colors) + img_facial_s.color = "#" + default_color + else + img_facial_s.color = "#" + H.dna.mutant_color + else + img_facial_s.color = "#" + hair_color + else + img_facial_s.color = "#" + H.facial_hair_color + img_facial_s.alpha = hair_alpha + + standing += img_facial_s + + //Applies the debrained overlay if there is no brain + if(!H.getorgan(/obj/item/organ/brain)) + standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s", "layer" = -HAIR_LAYER) + + else if(H.hair_style && HAIR in specflags) + S = hair_styles_list[H.hair_style] + if(S) + var/image/img_hair_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER) + + img_hair_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER) + + if(hair_color) + if(hair_color == "mutcolor") + if(!config.mutant_colors) + img_hair_s.color = "#" + default_color + else + img_hair_s.color = "#" + H.dna.mutant_color + else + img_hair_s.color = "#" + hair_color + else + img_hair_s.color = "#" + H.hair_color + img_hair_s.alpha = hair_alpha + + standing += img_hair_s + + if(standing.len) + H.overlays_standing[HAIR_LAYER] = standing + + H.apply_overlay(HAIR_LAYER) + + return + + proc/handle_body(var/mob/living/carbon/human/H) + H.remove_overlay(BODY_LAYER) + + var/list/standing = list() + + // lipstick + if(H.lip_style && LIPS in specflags) + standing += image("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[H.lip_style]_s", "layer" = -BODY_LAYER) + + // eyes + if(EYECOLOR in specflags) + var/image/img_eyes_s = image("icon" = 'icons/mob/human_face.dmi', "icon_state" = "[eyes]_s", "layer" = -BODY_LAYER) + img_eyes_s.color = "#" + H.eye_color + standing += img_eyes_s + + //Underwear + if(H.underwear) + var/datum/sprite_accessory/underwear/U = underwear_all[H.underwear] + if(U) + standing += image("icon"=U.icon, "icon_state"="[U.icon_state]_s", "layer"=-BODY_LAYER) + + if(standing.len) + H.overlays_standing[BODY_LAYER] = standing + + H.apply_overlay(BODY_LAYER) + + return + + proc/spec_life(var/mob/living/carbon/human/H) + return + + proc/spec_death(var/gibbed, var/mob/living/carbon/human/H) + return + + proc/auto_equip(var/mob/living/carbon/human/H) + // handles the equipping of species-specific gear + return + + proc/can_equip(var/obj/item/I, var/slot, var/disable_warning, var/mob/living/carbon/human/H) + if(slot in no_equip) + if(!(type in I.species_exception)) + return 0 + + switch(slot) + if(slot_l_hand) + if(H.l_hand) + return 0 + return 1 + if(slot_r_hand) + if(H.r_hand) + return 0 + return 1 + if(slot_wear_mask) + if(H.wear_mask) + return 0 + if( !(I.slot_flags & SLOT_MASK) ) + return 0 + return 1 + if(slot_back) + if(H.back) + return 0 + if( !(I.slot_flags & SLOT_BACK) ) + return 0 + return 1 + if(slot_wear_suit) + if(H.wear_suit) + return 0 + if( !(I.slot_flags & SLOT_OCLOTHING) ) + return 0 + return 1 + if(slot_gloves) + if(H.gloves) + return 0 + if( !(I.slot_flags & SLOT_GLOVES) ) + return 0 + return 1 + if(slot_shoes) + if(H.shoes) + return 0 + if( !(I.slot_flags & SLOT_FEET) ) + return 0 + return 1 + if(slot_belt) + if(H.belt) + return 0 + if(!H.w_uniform && !nojumpsuit) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [I.name]." + return 0 + if( !(I.slot_flags & SLOT_BELT) ) + return + return 1 + if(slot_glasses) + if(H.glasses) + return 0 + if( !(I.slot_flags & SLOT_EYES) ) + return 0 + return 1 + if(slot_head) + if(H.head) + return 0 + if( !(I.slot_flags & SLOT_HEAD) ) + return 0 + return 1 + if(slot_ears) + if(H.ears) + return 0 + if( !(I.slot_flags & SLOT_EARS) ) + return 0 + return 1 + if(slot_w_uniform) + if(H.w_uniform) + return 0 + if( !(I.slot_flags & SLOT_ICLOTHING) ) + return 0 + return 1 + if(slot_wear_id) + if(H.wear_id) + return 0 + if(!H.w_uniform && !nojumpsuit) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [I.name]." + return 0 + if( !(I.slot_flags & SLOT_ID) ) + return 0 + return 1 + if(slot_l_store) + if(I.flags & NODROP) //Pockets aren't visible, so you can't move NODROP items into them. + return 0 + if(H.l_store) + return 0 + if(!H.w_uniform && !nojumpsuit) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [I.name]." + return 0 + if(I.slot_flags & SLOT_DENYPOCKET) + return + if( I.w_class <= 2 || (I.slot_flags & SLOT_POCKET) ) + return 1 + if(slot_r_store) + if(I.flags & NODROP) + return 0 + if(H.r_store) + return 0 + if(!H.w_uniform && !nojumpsuit) + if(!disable_warning) + H << "You need a jumpsuit before you can attach this [I.name]." + return 0 + if(I.slot_flags & SLOT_DENYPOCKET) + return 0 + if( I.w_class <= 2 || (I.slot_flags & SLOT_POCKET) ) + return 1 + return 0 + if(slot_s_store) + if(I.flags & NODROP) + return 0 + if(H.s_store) + return 0 + if(!H.wear_suit) + if(!disable_warning) + H << "You need a suit before you can attach this [I.name]." + return 0 + if(!H.wear_suit.allowed) + if(!disable_warning) + H << "You somehow have a suit with no defined allowed items for suit storage, stop that." + return 0 + if(I.w_class > 4) + if(!disable_warning) + H << "The [I.name] is too big to attach." //should be src? + return 0 + if( istype(I, /obj/item/device/pda) || istype(I, /obj/item/weapon/pen) || is_type_in_list(I, H.wear_suit.allowed) ) + return 1 + return 0 + if(slot_handcuffed) + if(H.handcuffed) + return 0 + if(!istype(I, /obj/item/weapon/handcuffs)) + return 0 + return 1 + if(slot_legcuffed) + if(H.legcuffed) + return 0 + if(!istype(I, /obj/item/weapon/legcuffs)) + return 0 + return 1 + if(slot_in_backpack) + if (H.back && istype(H.back, /obj/item/weapon/storage/backpack)) + var/obj/item/weapon/storage/backpack/B = H.back + if(B.contents.len < B.storage_slots && I.w_class <= B.max_w_class) + return 1 + return 0 + return 0 //Unsupported slot + + proc/before_equip_job(var/datum/job/J, var/mob/living/carbon/human/H) + return + + proc/after_equip_job(var/datum/job/J, var/mob/living/carbon/human/H) + return + + proc/handle_chemicals(var/datum/reagent/chem, var/mob/living/carbon/human/H) + return 0 + + proc/handle_speech(var/message, var/mob/living/carbon/human/H) + return message + + //////// + //LIFE// + //////// + + proc/handle_chemicals_in_body(var/mob/living/carbon/human/H) + if(H.reagents) H.reagents.metabolize(H) + + //The fucking FAT mutation is the dumbest shit ever. It makes the code so difficult to work with + if(FAT in H.mutations) + if(H.overeatduration < 100) + H << "You feel fit again!" + H.mutations -= FAT + H.update_inv_w_uniform(0) + H.update_inv_wear_suit() + else + if(H.overeatduration > 500) + H << "You suddenly feel blubbery!" + H.mutations |= FAT + H.update_inv_w_uniform(0) + H.update_inv_wear_suit() + + // nutrition decrease + if (H.nutrition > 0 && H.stat != 2) + H.nutrition = max (0, H.nutrition - HUNGER_FACTOR) + + if (H.nutrition > 450) + if(H.overeatduration < 600) //capped so people don't take forever to unfat + H.overeatduration++ + else + if(H.overeatduration > 1) + H.overeatduration -= 2 //doubled the unfat rate + + if (H.drowsyness) + H.drowsyness-- + H.eye_blurry = max(2, H.eye_blurry) + if (prob(5)) + H.sleeping += 1 + H.Paralyse(5) + + H.confused = max(0, H.confused - 1) + // decrement dizziness counter, clamped to 0 + if(H.resting) + H.dizziness = max(0, H.dizziness - 15) + H.jitteriness = max(0, H.jitteriness - 15) + else + H.dizziness = max(0, H.dizziness - 3) + H.jitteriness = max(0, H.jitteriness - 3) + + H.updatehealth() + + return + + proc/handle_vision(var/mob/living/carbon/human/H) + if( H.stat == DEAD ) + H.sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS) + H.see_in_dark = 8 + if(!H.druggy) H.see_invisible = SEE_INVISIBLE_LEVEL_TWO + else + H.sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS) + var/see_temp = H.see_invisible + H.see_invisible = invis_sight + H.see_in_dark = darksight + + if(XRAY in H.mutations) + H.sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS + H.see_in_dark = 8 + H.see_invisible = SEE_INVISIBLE_LEVEL_TWO + + if(H.seer) + H.see_invisible = SEE_INVISIBLE_OBSERVER + + if(H.mind && H.mind.changeling) + H.hud_used.lingchemdisplay.invisibility = 0 + H.hud_used.lingchemdisplay.maptext = "
[H.mind.changeling.chem_charges]
" + else + H.hud_used.lingchemdisplay.invisibility = 101 + + if(istype(H.wear_mask, /obj/item/clothing/mask/gas/voice/space_ninja)) + var/obj/item/clothing/mask/gas/voice/space_ninja/O = H.wear_mask + switch(O.mode) + if(0) + var/target_list[] = list() + for(var/mob/living/target in oview(H)) + if( target.mind&&(target.mind.special_role||issilicon(target)) )//They need to have a mind. + target_list += target + if(target_list.len)//Everything else is handled by the ninja mask proc. + O.assess_targets(target_list, H) + H.see_invisible = SEE_INVISIBLE_LIVING + if(1) + H.see_in_dark = 5 + H.see_invisible = SEE_INVISIBLE_LIVING + if(2) + H.sight |= SEE_MOBS + H.see_invisible = SEE_INVISIBLE_LEVEL_TWO + if(3) + H.sight |= SEE_TURFS + H.see_invisible = SEE_INVISIBLE_LIVING + + if(H.glasses) + if(istype(H.glasses, /obj/item/clothing/glasses)) + var/obj/item/clothing/glasses/G = H.glasses + H.sight |= G.vision_flags + H.see_in_dark = G.darkness_view + H.see_invisible = G.invis_view + if(G.hud) + G.process_hud(H) + + if(H.druggy) //Override for druggy + H.see_invisible = see_temp + + if(H.see_override) //Override all + H.see_invisible = H.see_override + + // This checks how much the mob's eyewear impairs their vision + if(H.tinttotal >= TINT_IMPAIR) + if(tinted_weldhelh) + if(H.tinttotal >= TINT_BLIND) + H.blinded = 1 // You get the sudden urge to learn to play keyboard + H.client.screen += global_hud.darkMask + else + H.client.screen += global_hud.darkMask + + if(H.blind) + if(H.blinded) H.blind.layer = 18 + else H.blind.layer = 0 + + if( H.disabilities & NEARSIGHTED && !istype(H.glasses, /obj/item/clothing/glasses/regular) ) + H.client.screen += global_hud.vimpaired + if(H.eye_blurry) H.client.screen += global_hud.blurry + if(H.druggy) H.client.screen += global_hud.druggy + + + if(H.eye_stat > 20) + if(H.eye_stat > 30) H.client.screen += global_hud.darkMask + else H.client.screen += global_hud.vimpaired + + return 1 + + proc/handle_hud_icons(var/mob/living/carbon/human/H) + if(H.healths) + if(H.stat == DEAD) + H.healths.icon_state = "health7" + else + switch(H.hal_screwyhud) + if(1) H.healths.icon_state = "health6" + if(2) H.healths.icon_state = "health7" + else + switch(H.health - H.staminaloss) + if(100 to INFINITY) H.healths.icon_state = "health0" + if(80 to 100) H.healths.icon_state = "health1" + if(60 to 80) H.healths.icon_state = "health2" + if(40 to 60) H.healths.icon_state = "health3" + if(20 to 40) H.healths.icon_state = "health4" + if(0 to 20) H.healths.icon_state = "health5" + else H.healths.icon_state = "health6" + + if(H.nutrition_icon) + switch(H.nutrition) + if(450 to INFINITY) H.nutrition_icon.icon_state = "nutrition0" + if(350 to 450) H.nutrition_icon.icon_state = "nutrition1" + if(250 to 350) H.nutrition_icon.icon_state = "nutrition2" + if(150 to 250) H.nutrition_icon.icon_state = "nutrition3" + else H.nutrition_icon.icon_state = "nutrition4" + + if(H.pressure) + H.pressure.icon_state = "pressure[H.pressure_alert]" + + if(H.pullin) + if(H.pulling) H.pullin.icon_state = "pull" + else H.pullin.icon_state = "pull0" +// if(rest) //Not used with new UI +// if(resting || lying || sleeping) rest.icon_state = "rest1" +// else rest.icon_state = "rest0" + if(H.toxin) + if(H.hal_screwyhud == 4 || H.toxins_alert) H.toxin.icon_state = "tox1" + else H.toxin.icon_state = "tox0" + if(H.oxygen) + if(H.hal_screwyhud == 3 || H.oxygen_alert) H.oxygen.icon_state = "oxy1" + else H.oxygen.icon_state = "oxy0" + if(H.fire) + if(H.fire_alert) H.fire.icon_state = "fire[H.fire_alert]" //fire_alert is either 0 if no alert, 1 for cold and 2 for heat. + else H.fire.icon_state = "fire0" + + if(H.bodytemp) + if(!(HEATRES in specflags)) + switch(H.bodytemperature) //310.055 optimal body temp + if(370 to INFINITY) H.bodytemp.icon_state = "temp4" + if(350 to 370) H.bodytemp.icon_state = "temp3" + if(335 to 350) H.bodytemp.icon_state = "temp2" + switch(H.bodytemperature) + if(320 to 335) H.bodytemp.icon_state = "temp1" + if(300 to 320) H.bodytemp.icon_state = "temp0" + if(295 to 300) H.bodytemp.icon_state = "temp-1" + if(!(COLDRES in specflags)) + switch(H.bodytemperature) + if(280 to 295) H.bodytemp.icon_state = "temp-2" + if(260 to 280) H.bodytemp.icon_state = "temp-3" + if(-INFINITY to 260) H.bodytemp.icon_state = "temp-4" + + return 1 + + proc/handle_mutations_and_radiation(var/mob/living/carbon/human/H) + if(H.getFireLoss()) + if((COLD_RESISTANCE in H.mutations) || (prob(1))) + H.heal_organ_damage(0,1) + + if ((HULK in H.mutations) && H.health <= 25) + H.mutations.Remove(HULK) + H.update_mutations() //update our mutation overlays + H << "You suddenly feel very weak." + H.Weaken(3) + H.emote("collapse") + + if (H.radiation && !(RADIMMUNE in specflags)) + if (H.radiation > 100) + H.radiation = 100 + H.Weaken(10) + H << "You feel weak." + H.emote("collapse") + + if (H.radiation < 0) + H.radiation = 0 + + else + switch(H.radiation) + if(1 to 49) + H.radiation-- + if(prob(25)) + H.adjustToxLoss(1) + H.updatehealth() + + if(50 to 74) + H.radiation -= 2 + H.adjustToxLoss(1) + if(prob(5)) + H.radiation -= 5 + H.Weaken(3) + H << "You feel weak." + H.emote("collapse") + if(prob(15)) + if(!( H.hair_style == "Shaved") || !(H.hair_style == "Bald") || HAIR in specflags) + H << "Your hair starts to fall out in clumps..." + spawn(50) + H.facial_hair_style = "Shaved" + H.hair_style = "Bald" + H.update_hair() + H.updatehealth() + + if(75 to 100) + H.radiation -= 3 + H.adjustToxLoss(3) + if(prob(1)) + H << "You mutate!" + randmutb(H) + domutcheck(H,null) + H.emote("gasp") + H.updatehealth() + + //////////////// + // MOVE SPEED // + //////////////// + + proc/movement_delay(var/mob/living/carbon/human/H) + var/mspeed = 0 + + if(!has_gravity(H)) + return -1 //It's hard to be slowed down in space by... anything + else if(H.status_flags & GOTTAGOFAST) + return -1 + + mspeed = 0 + var/health_deficiency = (100 - H.health + H.staminaloss) + if(health_deficiency >= 40) + mspeed += (health_deficiency / 25) + + var/hungry = (500 - H.nutrition) / 5 //So overeat would be 100 and default level would be 80 + if(hungry >= 70) + mspeed += hungry / 50 + + if(H.wear_suit) + mspeed += H.wear_suit.slowdown + if(H.shoes) + mspeed += H.shoes.slowdown + if(H.back) + mspeed += H.back.slowdown + + if(FAT in H.mutations) + mspeed += 1.5 + if(H.bodytemperature < 283.222) + mspeed += (283.222 - H.bodytemperature) / 10 * 1.75 + + mspeed += speedmod + + return mspeed + + ////////////////// + // ATTACK PROCS // + ////////////////// + + proc/spec_attack_hand(var/mob/living/carbon/human/M, var/mob/living/carbon/human/H) + if((M != H) && H.check_shields(0, M.name)) + add_logs(M, H, "attempted to touch") + H.visible_message("[M] attempted to touch [H]!") + return 0 + + switch(M.a_intent) + if("help") + if(H.health >= 0) + H.help_shake_act(M) + if(H != M) + add_logs(M, H, "shaked") + return 1 + + //CPR + if((M.head && (M.head.flags & HEADCOVERSMOUTH)) || (M.wear_mask && (M.wear_mask.flags & MASKCOVERSMOUTH))) + M << "Remove your mask!" + return 0 + if((H.head && (H.head.flags & HEADCOVERSMOUTH)) || (H.wear_mask && (H.wear_mask.flags & MASKCOVERSMOUTH))) + M << "Remove their mask!" + return 0 + + if(H.cpr_time < world.time + 30) + add_logs(H, M, "CPRed") + H.visible_message("[M] is trying to perform CPR on [H]!") + if(!do_mob(M, H)) + return 0 + if((H.health >= -99 && H.health <= 0)) + H.cpr_time = world.time + var/suff = min(H.getOxyLoss(), 7) + H.adjustOxyLoss(-suff) + H.updatehealth() + M.visible_message("[M] performs CPR on [H]!") + H << "You feel a breath of fresh air enter your lungs. It feels good." + + if("grab") + if(M == H || H.anchored) + return 0 + + add_logs(M, H, "grabbed", addition="passively") + + if(H.w_uniform) + H.w_uniform.add_fingerprint(M) + + var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, H) + if(H.buckled) + M << "You cannot grab [H], \he is buckled in!" + if(!G) //the grab will delete itself in New if affecting is anchored + return + M.put_in_active_hand(G) + G.synch() + H.LAssailant = M + + playsound(H.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + H.visible_message("[M] has grabbed [H] passively!") + return 1 + + if("harm") + add_logs(M, H, "punched") + + var/atk_verb = "punch" + if(H.lying) + atk_verb = "kick" + else if(M.dna) + atk_verb = M.dna.species.attack_verb + + var/damage = rand(0, 9) + damage += punchmod + + if(!damage) + if(M.dna) + playsound(H.loc, M.dna.species.miss_sound, 25, 1, -1) + else + playsound(H.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + + H.visible_message("[M] has attempted to [atk_verb] [H]!") + return 0 + + + var/obj/item/organ/limb/affecting = H.get_organ(ran_zone(M.zone_sel.selecting)) + var/armor_block = H.run_armor_check(affecting, "melee") + + if(HULK in M.mutations) + damage += 5 + + if(M.dna) + playsound(H.loc, M.dna.species.attack_sound, 25, 1, -1) + else + playsound(H.loc, 'sound/weapons/punch1.ogg', 25, 1, -1) + + + H.visible_message("[M] has [atk_verb]ed [H]!", \ + "[M] has [atk_verb]ed [H]!") + + H.apply_damage(damage, BRUTE, affecting, armor_block) + if((H.stat != DEAD) && damage >= 9) + H.visible_message("[M] has weakened [H]!", \ + "[M] has weakened [H]!") + H.apply_effect(4, WEAKEN, armor_block) + H.forcesay(hit_appends) + else if(H.lying) + H.forcesay(hit_appends) + + if("disarm") + add_logs(M, H, "disarmed") + + if(H.w_uniform) + H.w_uniform.add_fingerprint(M) + var/obj/item/organ/limb/affecting = H.get_organ(ran_zone(M.zone_sel.selecting)) + var/randn = rand(1, 100) + if(randn <= 25) + H.apply_effect(2, WEAKEN, H.run_armor_check(affecting, "melee")) + playsound(H, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + H.visible_message("[M] has pushed [H]!", + "[M] has pushed [H]!") + H.forcesay(hit_appends) + return + + var/talked = 0 // BubbleWrap + + if(randn <= 60) + //BubbleWrap: Disarming breaks a pull + if(H.pulling) + H.visible_message("[M] has broken [H]'s grip on [H.pulling]!") + talked = 1 + H.stop_pulling() + + //BubbleWrap: Disarming also breaks a grab - this will also stop someone being choked, won't it? + if(istype(H.l_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/lgrab = H.l_hand + if(lgrab.affecting) + H.visible_message("[M] has broken [H]'s grip on [lgrab.affecting]!") + talked = 1 + spawn(1) + qdel(lgrab) + if(istype(H.r_hand, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/rgrab = H.r_hand + if(rgrab.affecting) + H.visible_message("[M] has broken [H]'s grip on [rgrab.affecting]!") + talked = 1 + spawn(1) + qdel(rgrab) + //End BubbleWrap + + if(!talked) //BubbleWrap + if(H.drop_item()) + H.visible_message("[M] has disarmed [H]!", \ + "[M] has disarmed [H]!") + playsound(H, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + return + + + playsound(H, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + H.visible_message("[M] attempted to disarm [H]!", \ + "[M] attemped to disarm [H]!") + return + + proc/spec_attacked_by(var/obj/item/I, var/mob/living/user, var/def_zone, var/obj/item/organ/limb/affecting, var/hit_area, var/intent, var/obj/item/organ/limb/target_limb, target_area, var/mob/living/carbon/human/H) + // Allows you to put in item-specific reactions based on species + if((user != H) && H.check_shields(I.force, "the [I.name]")) + return 0 + + if(I.attack_verb && I.attack_verb.len) + H.visible_message("[H] has been [pick(I.attack_verb)] in the [hit_area] with [I] by [user]!", \ + "[H] has been [pick(I.attack_verb)] in the [hit_area] with [I] by [user]!") + else if(I.force) + H.visible_message("[H] has been attacked in the [hit_area] with [I] by [user]!", \ + "[H] has been attacked in the [hit_area] with [I] by [user]!") + else + return 0 + + var/armor = H.run_armor_check(affecting, "melee", "Your armour has protected your [hit_area].", "Your armour has softened a hit to your [hit_area].") + if(armor >= 100) return 0 + var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords) + + apply_damage(I.force, I.damtype, affecting, armor, H) + + var/bloody = 0 + if(((I.damtype == BRUTE) && prob(25 + (I.force * 2)))) + if(affecting.status == ORGAN_ORGANIC) + I.add_blood(H) //Make the weapon bloody, not the person. + if(prob(I.force * 2)) //blood spatter! + bloody = 1 + var/turf/location = H.loc + if(istype(location, /turf/simulated)) + location.add_blood(H) + if(get_dist(H, H) <= 1) //people with TK won't get smeared with blood + if(H.wear_suit) + H.wear_suit.add_blood(H) + H.update_inv_wear_suit(0) //updates mob overlays to show the new blood (no refresh) + else if(H.w_uniform) + H.w_uniform.add_blood(H) + H.update_inv_w_uniform(0) //updates mob overlays to show the new blood (no refresh) + if (H.gloves) + var/obj/item/clothing/gloves/G = H.gloves + G.add_blood(H) + else + H.add_blood(H) + H.update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves + + + switch(hit_area) + if("head") //Harder to score a stun but if you do it lasts a bit longer + if(H.stat == CONSCIOUS && prob(I.force) && armor < 50) + H.visible_message("[H] has been knocked unconscious!", \ + "[H] has been knocked unconscious!") + H.apply_effect(20, PARALYZE, armor) + if(H != user && I.damtype == BRUTE) + ticker.mode.remove_revolutionary(H.mind) + + if(bloody) //Apply blood + if(H.wear_mask) + H.wear_mask.add_blood(H) + H.update_inv_wear_mask(0) + if(H.head) + H.head.add_blood(H) + H.update_inv_head(0) + if(H.glasses && prob(33)) + H.glasses.add_blood(H) + H.update_inv_glasses(0) + + if("chest") //Easier to score a stun but lasts less time + if(H.stat == CONSCIOUS && prob(I.force + 10)) + H.visible_message("[H] has been knocked down!", \ + "[H] has been knocked down!") + H.apply_effect(5, WEAKEN, armor) + + if(bloody) + if(H.wear_suit) + H.wear_suit.add_blood(H) + H.update_inv_wear_suit(0) + if(H.w_uniform) + H.w_uniform.add_blood(H) + H.update_inv_w_uniform(0) + + if(Iforce > 10 || Iforce >= 5 && prob(33)) + H.forcesay(hit_appends) //forcesay checks stat already. + return + + proc/attacked_by(var/obj/item/I, var/mob/living/user, var/def_zone, var/mob/living/carbon/human/H) + H.apply_damage(I.force, I.damtype) + if(I.damtype == "brute") + if(prob(33) && I.force && !(NOBLOOD in specflags)) + var/turf/location = H.loc + if(istype(location, /turf/simulated)) + location.add_blood_floor(H) + + var/showname = "." + if(user) + showname = " by [user]!" + if(!(user in viewers(I, null))) + showname = "." + + if(I.attack_verb && I.attack_verb.len) + H.visible_message("[H] has been [pick(I.attack_verb)] with [I][showname]", + "[H] has been [pick(I.attack_verb)] with [I][showname]") + else if(I.force) + H.visible_message("[H] has been attacked with [I][showname]", + "[H] has been attacked with [I][showname]") + if(!showname && user) + if(user.client) + user << "You attack [H] with [I]. " + + return + + proc/apply_damage(var/damage, var/damagetype = BRUTE, var/def_zone = null, var/blocked, var/mob/living/carbon/human/H) + blocked = (100-(blocked+armor))/100 + if(blocked <= 0) return 0 + + var/obj/item/organ/limb/organ = null + if(isorgan(def_zone)) + organ = def_zone + else + if(!def_zone) def_zone = ran_zone(def_zone) + organ = H.get_organ(check_zone(def_zone)) + if(!organ) return 0 + + damage = (damage * blocked) + + switch(damagetype) + if(BRUTE) + H.damageoverlaytemp = 20 + if(organ.take_damage(damage*brutemod, 0)) + H.update_damage_overlays(0) + if(BURN) + H.damageoverlaytemp = 20 + if(organ.take_damage(0, damage*burnmod)) + H.update_damage_overlays(0) + if(TOX) + H.adjustToxLoss(damage * blocked) + if(OXY) + H.adjustOxyLoss(damage * blocked) + if(CLONE) + H.adjustCloneLoss(damage * blocked) + if(STAMINA) + H.adjustStaminaLoss(damage * blocked) + + proc/on_hit(var/obj/item/projectile/proj_type, var/mob/living/carbon/human/H) + // called when hit by a projectile + switch(proj_type) + if(/obj/item/projectile/energy/floramut) // overwritten by plants/pods + H.show_message("The radiation beam dissipates harmlessly through your body.") + if(/obj/item/projectile/energy/florayield) + H.show_message("The radiation beam dissipates harmlessly through your body.") + return + + ///////////// + //BREATHING// + ///////////// + + proc/breathe(var/mob/living/carbon/human/H) + if(H.reagents.has_reagent("lexorin")) return + if(istype(H.loc, /obj/machinery/atmospherics/unary/cryo_cell)) return + + var/datum/gas_mixture/environment = H.loc.return_air() + var/datum/gas_mixture/breath + // HACK NEED CHANGING LATER + if(H.health <= config.health_threshold_crit) + H.losebreath++ + + if(H.losebreath>0) //Suffocating so do not take a breath + H.losebreath-- + if (prob(10)) //Gasp per 10 ticks? Sounds about right. + spawn H.emote("gasp") + if(istype(H.loc, /obj/)) + var/obj/location_as_object = H.loc + location_as_object.handle_internal_lifeform(H, 0) + else + //First, check for air from internal atmosphere (using an air tank and mask generally) + breath = H.get_breath_from_internal(BREATH_VOLUME) // Super hacky -- TLE + //breath = get_breath_from_internal(0.5) // Manually setting to old BREATH_VOLUME amount -- TLE + + //No breath from internal atmosphere so get breath from location + if(!breath) + if(isobj(H.loc)) + var/obj/location_as_object = H.loc + breath = location_as_object.handle_internal_lifeform(H, BREATH_VOLUME) + else if(isturf(H.loc)) + var/breath_moles = 0 + /*if(environment.return_pressure() > ONE_ATMOSPHERE) + // Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT) + breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature) + else*/ + // Not enough air around, take a percentage of what's there to model this properly + breath_moles = environment.total_moles()*BREATH_PERCENTAGE + + breath = H.loc.remove_air(breath_moles) + // Handle chem smoke effect -- Doohl + var/block = 0 + if(H.wear_mask) + if(H.wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT) + block = 1 + if(H.glasses) + if(H.glasses.flags & BLOCK_GAS_SMOKE_EFFECT) + block = 1 + if(H.head) + if(H.head.flags & BLOCK_GAS_SMOKE_EFFECT) + block = 1 + + if(!block) + + for(var/obj/effect/effect/chem_smoke/smoke in view(1, H)) + if(smoke.reagents.total_volume) + smoke.reagents.reaction(H, INGEST) + spawn(5) + if(smoke) + smoke.reagents.copy_to(H, 10) // I dunno, maybe the reagents enter the blood stream through the lungs? + break // If they breathe in the nasty stuff once, no need to continue checking + + else //Still give containing object the chance to interact + if(istype(H.loc, /obj/)) + var/obj/location_as_object = H.loc + location_as_object.handle_internal_lifeform(H, 0) + + handle_breath(breath, H) + + if(breath) + H.loc.assume_air(breath) + + proc/handle_breath(datum/gas_mixture/breath, var/mob/living/carbon/human/H) + if((H.status_flags & GODMODE)) + return + + if(!breath || (breath.total_moles() == 0) || H.suiciding) + if(H.reagents.has_reagent("inaprovaline")) + return + if(H.suiciding) + H.adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster + H.failed_last_breath = 1 + H.oxygen_alert = max(H.oxygen_alert, 1) + return 0 + if(H.health >= config.health_threshold_crit) + if(NOBREATH in specflags) return 1 + H.adjustOxyLoss(HUMAN_MAX_OXYLOSS) + H.failed_last_breath = 1 + else + H.adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS) + H.failed_last_breath = 1 + + H.oxygen_alert = max(H.oxygen_alert, 1) + + return 0 + + var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa + //var/safe_oxygen_max = 140 // Maximum safe partial pressure of O2, in kPa (Not used for now) + var/safe_co2_max = 10 // Yes it's an arbitrary value who cares? + var/safe_toxins_max = 0.005 + var/SA_para_min = 1 + var/SA_sleep_min = 5 + var/oxygen_used = 0 + var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + + //Partial pressure of the O2 in our breath + var/O2_pp = (breath.oxygen/breath.total_moles())*breath_pressure + // Same, but for the toxins + var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure + // And CO2, lets say a PP of more than 10 will be bad (It's a little less really, but eh, being passed out all round aint no fun) + var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*breath_pressure // Tweaking to fit the hacky bullshit I've done with atmo -- TLE + //var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*0.5 // The default pressure value + + if(O2_pp < safe_oxygen_min) // Too little oxygen + if(!(NOBREATH in specflags) || (H.health <= config.health_threshold_crit)) + if(prob(20)) + spawn(0) H.emote("gasp") + if(O2_pp > 0) + var/ratio = safe_oxygen_min/O2_pp + H.adjustOxyLoss(min(5*ratio, HUMAN_MAX_OXYLOSS)) // Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!) + H.failed_last_breath = 1 + oxygen_used = breath.oxygen*ratio/6 + else + H.adjustOxyLoss(HUMAN_MAX_OXYLOSS) + H.failed_last_breath = 1 + H.oxygen_alert = max(H.oxygen_alert, 1) + /*else if (O2_pp > safe_oxygen_max) // Too much oxygen (commented this out for now, I'll deal with pressure damage elsewhere I suppose) + spawn(0) emote("cough") + var/ratio = O2_pp/safe_oxygen_max + oxyloss += 5*ratio + oxygen_used = breath.oxygen*ratio/6 + oxygen_alert = max(oxygen_alert, 1)*/ + else // We're in safe limits + H.failed_last_breath = 0 + H.adjustOxyLoss(-5) + oxygen_used = breath.oxygen/6 + H.oxygen_alert = 0 + + breath.oxygen -= oxygen_used + breath.carbon_dioxide += oxygen_used + + //CO2 does not affect failed_last_breath. So if there was enough oxygen in the air but too much co2, this will hurt you, but only once per 4 ticks, instead of once per tick. + if(CO2_pp > safe_co2_max && !(NOBREATH in specflags)) + if(!H.co2overloadtime) // If it's the first breath with too much CO2 in it, lets start a counter, then have them pass out after 12s or so. + H.co2overloadtime = world.time + else if(world.time - H.co2overloadtime > 120) + H.Paralyse(3) + H.adjustOxyLoss(3) // Lets hurt em a little, let them know we mean business + if(world.time - H.co2overloadtime > 300) // They've been in here 30s now, lets start to kill them for their own good! + H.adjustOxyLoss(8) + if(prob(20)) // Lets give them some chance to know somethings not right though I guess. + spawn(0) H.emote("cough") + + else + H.co2overloadtime = 0 + + if(Toxins_pp > safe_toxins_max && !(NOBREATH in specflags)) // Too much toxins + var/ratio = (breath.toxins/safe_toxins_max) * 10 + //adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) //Limit amount of damage toxin exposure can do per second + if(H.reagents) + H.reagents.add_reagent("plasma", Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) + H.toxins_alert = max(H.toxins_alert, 1) + else + H.toxins_alert = 0 + + if(breath.trace_gases.len && !(NOBREATH in specflags)) // If there's some other shit in the air lets deal with it here. + for(var/datum/gas/sleeping_agent/SA in breath.trace_gases) + var/SA_pp = (SA.moles/breath.total_moles())*breath_pressure + if(SA_pp > SA_para_min) // Enough to make us paralysed for a bit + H.Paralyse(3) // 3 gives them one second to wake up and run away a bit! + if(SA_pp > SA_sleep_min) // Enough to make us sleep as well + H.sleeping = max(H.sleeping+2, 10) + else if(SA_pp > 0.01) // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning + if(prob(20)) + spawn(0) H.emote(pick("giggle", "laugh")) + + handle_temperature(breath) + + return 1 + + proc/handle_temperature(datum/gas_mixture/breath, var/mob/living/carbon/human/H) // called by human/life, handles temperatures + if( (abs(310.15 - breath.temperature) > 50) && !(COLD_RESISTANCE in H.mutations) && !(COLDRES in specflags)) // Hot air hurts :( + if(breath.temperature < 260.15) + if(prob(20)) + H << "You feel your face freezing and an icicle forming in your lungs!" + else if(breath.temperature > 360.15 && !(HEATRES in specflags)) + if(prob(20)) + H << "You feel your face burning and a searing heat in your lungs!" + + if(!(COLDRES in specflags)) // COLD DAMAGE + switch(breath.temperature) + if(-INFINITY to 120) + H.apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, "head") + H.fire_alert = max(H.fire_alert, 1) + if(120 to 200) + H.apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, "head") + H.fire_alert = max(H.fire_alert, 1) + if(200 to 260) + H.apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, "head") + H.fire_alert = max(H.fire_alert, 1) + + if(!(HEATRES in specflags)) // HEAT DAMAGE + switch(breath.temperature) + if(360 to 400) + H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, "head") + H.fire_alert = max(H.fire_alert, 2) + if(400 to 1000) + H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, "head") + H.fire_alert = max(H.fire_alert, 2) + if(1000 to INFINITY) + H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head") + H.fire_alert = max(H.fire_alert, 2) + + return + + proc/handle_environment(datum/gas_mixture/environment, var/mob/living/carbon/human/H) + if(!environment) + return + + var/loc_temp = H.get_temperature(environment) + //world << "Loc temp: [loc_temp] - Body temp: [bodytemperature] - Fireloss: [getFireLoss()] - Thermal protection: [get_thermal_protection()] - Fire protection: [thermal_protection + add_fire_protection(loc_temp)] - Heat capacity: [environment_heat_capacity] - Location: [loc] - src: [src]" + + //Body temperature is adjusted in two steps. Firstly your body tries to stabilize itself a bit. + if(H.stat != 2) + H.stabilize_temperature_from_calories() + + //After then, it reacts to the surrounding atmosphere based on your thermal protection + if(!H.on_fire) //If you're on fire, you do not heat up or cool down based on surrounding gases + if(loc_temp < H.bodytemperature) + //Place is colder than we are + var/thermal_protection = H.get_cold_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to. + if(thermal_protection < 1) + H.bodytemperature += min((1-thermal_protection) * ((loc_temp - H.bodytemperature) / BODYTEMP_COLD_DIVISOR), BODYTEMP_COOLING_MAX) + else + //Place is hotter than we are + var/thermal_protection = H.get_heat_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to. + if(thermal_protection < 1) + H.bodytemperature += min((1-thermal_protection) * ((loc_temp - H.bodytemperature) / BODYTEMP_HEAT_DIVISOR), BODYTEMP_HEATING_MAX) + + // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. + if(H.bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT && !(HEATRES in specflags)) + //Body temperature is too hot. + H.fire_alert = max(H.fire_alert, 1) + switch(H.bodytemperature) + if(360 to 400) + H.apply_damage(HEAT_DAMAGE_LEVEL_1*heatmod, BURN) + H.fire_alert = max(H.fire_alert, 2) + if(400 to 460) + H.apply_damage(HEAT_DAMAGE_LEVEL_2*heatmod, BURN) + H.fire_alert = max(H.fire_alert, 2) + if(460 to INFINITY) + if(H.on_fire) + H.apply_damage(HEAT_DAMAGE_LEVEL_3*heatmod, BURN) + H.fire_alert = max(H.fire_alert, 2) + else + H.apply_damage(HEAT_DAMAGE_LEVEL_2*heatmod, BURN) + H.fire_alert = max(H.fire_alert, 2) + + else if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !(COLDRES in specflags)) + H.fire_alert = max(H.fire_alert, 1) + if(!istype(H.loc, /obj/machinery/atmospherics/unary/cryo_cell)) + switch(H.bodytemperature) + if(200 to 260) + H.apply_damage(COLD_DAMAGE_LEVEL_1*coldmod, BURN) + H.fire_alert = max(H.fire_alert, 1) + if(120 to 200) + H.apply_damage(COLD_DAMAGE_LEVEL_2*coldmod, BURN) + H.fire_alert = max(H.fire_alert, 1) + if(-INFINITY to 120) + H.apply_damage(COLD_DAMAGE_LEVEL_3*coldmod, BURN) + H.fire_alert = max(H.fire_alert, 1) + + // Account for massive pressure differences. Done by Polymorph + // Made it possible to actually have something that can protect against high pressure... Done by Errorage. Polymorph now has an axe sticking from his head for his previous hardcoded nonsense! + + var/pressure = environment.return_pressure() + var/adjusted_pressure = H.calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob. + switch(adjusted_pressure) + if(HAZARD_HIGH_PRESSURE to INFINITY) + if(!(HEATRES in specflags)) + H.adjustBruteLoss( min( ( (adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) ) + H.pressure_alert = 2 + else + H.pressure_alert = 1 + if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE) + H.pressure_alert = 1 + if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE) + H.pressure_alert = 0 + if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE) + H.pressure_alert = -1 + else + if((COLD_RESISTANCE in H.mutations) || (COLDRES in specflags)) + H.pressure_alert = -1 + else + H.adjustBruteLoss( LOW_PRESSURE_DAMAGE ) + H.pressure_alert = -2 + + return + + ////////// + // FIRE // + ////////// + + proc/handle_fire(var/mob/living/carbon/human/H) + if((HEATRES in specflags) || (NOFIRE in specflags)) + return + if(H.fire_stacks < 0) + H.fire_stacks++ //If we've doused ourselves in water to avoid fire, dry off slowly + H.fire_stacks = min(0, H.fire_stacks)//So we dry ourselves back to default, nonflammable. + if(!H.on_fire) + return + var/datum/gas_mixture/G = H.loc.return_air() // Check if we're standing in an oxygenless environment + if(G.oxygen < 1) + ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire + return + var/turf/location = get_turf(H) + location.hotspot_expose(700, 50, 1) + + proc/IgniteMob(var/mob/living/carbon/human/H) + if(H.fire_stacks > 0 && !H.on_fire && !(HEATRES in specflags) && !(NOFIRE in specflags)) + H.on_fire = 1 + H.AddLuminosity(3) + H.update_fire() + + proc/ExtinguishMob(var/mob/living/carbon/human/H) + if(H.on_fire) + H.on_fire = 0 + H.fire_stacks = 0 + H.AddLuminosity(-3) + H.update_fire() + +#undef SPECIES_LAYER +#undef BODY_LAYER +#undef HAIR_LAYER + +#undef HUMAN_MAX_OXYLOSS +#undef HUMAN_CRIT_MAX_OXYLOSS + +#undef HEAT_DAMAGE_LEVEL_1 +#undef HEAT_DAMAGE_LEVEL_2 +#undef HEAT_DAMAGE_LEVEL_3 + +#undef COLD_DAMAGE_LEVEL_1 +#undef COLD_DAMAGE_LEVEL_2 +#undef COLD_DAMAGE_LEVEL_3 + +#undef HEAT_GAS_DAMAGE_LEVEL_1 +#undef HEAT_GAS_DAMAGE_LEVEL_2 +#undef HEAT_GAS_DAMAGE_LEVEL_3 + +#undef COLD_GAS_DAMAGE_LEVEL_1 +#undef COLD_GAS_DAMAGE_LEVEL_2 +#undef COLD_GAS_DAMAGE_LEVEL_3 + +#undef TINT_IMPAIR +#undef TINT_BLIND \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species_types.dm b/code/modules/mob/living/carbon/human/species_types.dm new file mode 100644 index 00000000000..7d159238fc5 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species_types.dm @@ -0,0 +1,221 @@ +/* + HUMANS +*/ + +/datum/species/human + name = "Human" + id = "human" + roundstart = 1 + specflags = list(EYECOLOR,HAIR,FACEHAIR,LIPS) + use_skintones = 1 + +/datum/species/human/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) + if(chem.id == "mutationtoxin") + H << "Your flesh rapidly mutates!" + H.dna.species = new /datum/species/slime() + H.regenerate_icons() + H.reagents.del_reagent(chem.type) + return 1 + +/* + LIZARDPEOPLE +*/ + +/datum/species/lizard + // Reptilian humanoids with scaled skin and tails. + name = "Lizardperson" + id = "lizard" + say_mod = "hisses" + default_color = "00FF00" + roundstart = 1 + specflags = list(MUTCOLORS,EYECOLOR,LIPS) + attack_verb = "slash" + attack_sound = 'sound/weapons/slash.ogg' + miss_sound = 'sound/weapons/slashmiss.ogg' + +/datum/species/lizard/handle_speech(message) + // jesus christ why + if(copytext(message, 1, 2) != "*") + message = replacetext(message, "s", stutter("ss")) + + return message + +/* + PLANTPEOPLE +*/ + +/datum/species/plant + // Creatures made of leaves and plant matter. + name = "Plant" + id = "plant" + default_color = "59CE00" + specflags = list(MUTCOLORS,EYECOLOR) + attack_verb = "slice" + attack_sound = 'sound/weapons/slice.ogg' + miss_sound = 'sound/weapons/slashmiss.ogg' + burnmod = 1.25 + heatmod = 1.5 + +/datum/species/plant/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) + if(chem.id == "plantbgone") + H.adjustToxLoss(3) + H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM) + return 1 + +/datum/species/plant/on_hit(proj_type, mob/living/carbon/human/H) + switch(proj_type) + if(/obj/item/projectile/energy/floramut) + if(prob(15)) + H.apply_effect((rand(30,80)),IRRADIATE) + H.Weaken(5) + for (var/mob/V in viewers(H)) + V.show_message("[H] writhes in pain as \his vacuoles boil.", 3, "You hear the crunching of leaves.", 2) + if(prob(80)) + randmutb(H) + domutcheck(H,null) + else + randmutg(H) + domutcheck(H,null) + else + H.adjustFireLoss(rand(5,15)) + H.show_message("The radiation beam singes you!") + if(/obj/item/projectile/energy/florayield) + H.nutrition = min(H.nutrition+30, 500) + return + +/* + PODPEOPLE +*/ + +/datum/species/plant/pod + // A mutation caused by a human being ressurected in a revival pod. These regain health in light, and begin to wither in darkness. + name = "Podperson" + id = "pod" + +/datum/species/plant/pod/spec_life(mob/living/carbon/human/H) + var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing + if(isturf(H.loc)) //else, there's considered to be no light + var/turf/T = H.loc + var/area/A = T.loc + if(A) + if(A.lighting_use_dynamic) light_amount = min(10,T.lighting_lumcount) - 5 + else light_amount = 5 + H.nutrition += light_amount + if(H.nutrition > 500) + H.nutrition = 500 + if(light_amount > 2) //if there's enough light, heal + H.heal_overall_damage(1,1) + H.adjustToxLoss(-1) + H.adjustOxyLoss(-1) + + if(H.nutrition < 200) + H.take_overall_damage(2,0) + +/* + SHADOWPEOPLE +*/ + +/datum/species/shadow + // Humans cursed to stay in the darkness, lest their life forces drain. They regain health in shadow and die in light. + name = "???" + id = "shadow" + darksight = 8 + sexes = 0 + ignored_by = list(/mob/living/simple_animal/hostile/faithless) + +/datum/species/shadow/spec_life(mob/living/carbon/human/H) + var/light_amount = 0 + if(isturf(H.loc)) + var/turf/T = H.loc + var/area/A = T.loc + if(A) + if(A.lighting_use_dynamic) light_amount = T.lighting_lumcount + else light_amount = 10 + if(light_amount > 2) //if there's enough light, start dying + H.take_overall_damage(1,1) + else if (light_amount < 2) //heal in the dark + H.heal_overall_damage(1,1) + +/* + SLIMEPEOPLE +*/ + +/datum/species/slime + // Humans mutated by slime mutagen, produced from green slimes. They are not targetted by slimes. + name = "Slimeperson" + id = "slime" + default_color = "00FFFF" + darksight = 3 + invis_sight = SEE_INVISIBLE_LEVEL_ONE + specflags = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR) + hair_color = "mutcolor" + hair_alpha = 150 + ignored_by = list(/mob/living/carbon/slime) + +/* + JELLYPEOPLE +*/ + +/datum/species/jelly + // Entirely alien beings that seem to be made entirely out of gel. They have three eyes and a skeleton visible within them. + name = "Xenobiological Jelly Entity" + id = "jelly" + default_color = "00FF90" + say_mod = "chirps" + eyes = "jelleyes" + specflags = list(MUTCOLORS,EYECOLOR) + +/* + GOLEMS +*/ + +/datum/species/golem + // Animated beings of stone. They have increased defenses, and do not need to breathe. They're also slow as fuuuck. + name = "Golem" + id = "golem" + specflags = list(NOBREATH,HEATRES,COLDRES,NOGUNS,NOBLOOD,RADIMMUNE) + speedmod = 3 + armor = 55 + punchmod = 5 + no_equip = list(slot_wear_mask, slot_wear_suit, slot_gloves, slot_shoes, slot_head, slot_w_uniform) + nojumpsuit = 1 + +/* + ADAMANTINE GOLEMS +*/ + +/datum/species/golem/adamantine + name = "Adamantine Golem" + id = "adamantine" + +/* + FLIES +*/ + +/datum/species/fly + // Humans turned into fly-like abominations in teleporter accidents. + name = "Human?" + id = "fly" + say_mod = "buzzes" + +/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) + if(chem.id == "pestkiller") + H.adjustToxLoss(3) + H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM) + return 1 + +/datum/species/fly/handle_speech(message) + if(copytext(message, 1, 2) != "*") + message = replacetext(message, "z", stutter("zz")) + + return message + +/* + SKELETONS +*/ + +/datum/species/skeleton + // 2spooky + name = "Spooky Scary Skeleton" + id = "skeleton" + sexes = 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index e09d39d53dd..c9edac17e1c 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -56,6 +56,7 @@ Please contact me on #coderbus IRC. ~Carnie x */ //Human Overlays Indexes///////// +#define SPECIES_LAYER 23 // mutantrace colors... these are on a seperate layer in order to prvent #define BODY_LAYER 22 //underwear, eyes, lips(makeup) #define MUTATIONS_LAYER 21 //Tk headglows etc. #define AUGMENTS_LAYER 20 @@ -78,28 +79,28 @@ Please contact me on #coderbus IRC. ~Carnie x #define L_HAND_LAYER 3 #define R_HAND_LAYER 2 //Having the two hands seperate seems rather silly, merge them together? It'll allow for code to be reused on mobs with arbitarily many hands #define FIRE_LAYER 1 //If you're on fire -#define TOTAL_LAYERS 22 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_; +#define TOTAL_LAYERS 23 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_; ////////////////////////////////// + /mob/living/carbon/human var/list/overlays_standing[TOTAL_LAYERS] /mob/living/carbon/human/proc/update_base_icon_state() - var/race = dna ? dna.mutantrace : null - switch(race) - if("lizard","golem","slime","shadow","adamantine","fly","plant") - base_icon_state = "[dna.mutantrace]_[(gender == FEMALE) ? "f" : "m"]" - if("skeleton") - base_icon_state = "skeleton" + //var/race = dna ? dna.mutantrace : null + if(dna) + base_icon_state = dna.species.update_base_icon_state(src) + else + if(HUSK in mutations) + base_icon_state = "husk" else - if(HUSK in mutations) - base_icon_state = "husk" - else - base_icon_state = "[skin_tone]_[(gender == FEMALE) ? "f" : "m"]" + base_icon_state = "[skin_tone]_[(gender == FEMALE) ? "f" : "m"]" + icon_state = "[base_icon_state]_s" /mob/living/carbon/human/proc/apply_overlay(cache_index) var/image/I = overlays_standing[cache_index] + if(I) overlays += I @@ -145,42 +146,11 @@ Please contact me on #coderbus IRC. ~Carnie x //Reset our hair remove_overlay(HAIR_LAYER) - //mutants don't have hair. masks and helmets can obscure our hair too. - if( (HUSK in mutations) || (dna && dna.mutantrace) || (head && (head.flags & BLOCKHAIR)) || (wear_mask && (wear_mask.flags & BLOCKHAIR)) ) + if( (HUSK in mutations) || (head && (head.flags & BLOCKHAIR)) || (wear_mask && (wear_mask.flags & BLOCKHAIR)) ) return - //base icons - var/datum/sprite_accessory/S - var/list/standing = list() - - if(facial_hair_style) - S = facial_hair_styles_list[facial_hair_style] - if(S) - var/image/img_facial_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER) - - var/new_color = "#" + facial_hair_color - img_facial_s.color = new_color - - standing += img_facial_s - - //Applies the debrained overlay if there is no brain - if(!getorgan(/obj/item/organ/brain)) - standing += image("icon"='icons/mob/human_face.dmi', "icon_state" = "debrained_s", "layer" = -HAIR_LAYER) - else if(hair_style) - S = hair_styles_list[hair_style] - if(S) - var/image/img_hair_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER) - - var/new_color = "#" + hair_color - img_hair_s.color = new_color - - standing += img_hair_s - - if(standing.len) - overlays_standing[HAIR_LAYER] = standing - - apply_overlay(HAIR_LAYER) - + if(dna) + dna.species.handle_hair(src) /mob/living/carbon/human/update_mutations() remove_overlay(MUTATIONS_LAYER) @@ -188,6 +158,7 @@ Please contact me on #coderbus IRC. ~Carnie x var/list/standing = list() var/g = (gender == FEMALE) ? "f" : "m" + for(var/mut in mutations) switch(mut) if(HULK) @@ -203,41 +174,22 @@ Please contact me on #coderbus IRC. ~Carnie x apply_overlay(MUTATIONS_LAYER) +/mob/living/carbon/human/proc/update_mutcolor() + if(dna && !(HUSK in mutations)) + dna.species.update_color(src) /mob/living/carbon/human/proc/update_body() remove_overlay(BODY_LAYER) - update_base_icon_state() + if(dna) + base_icon_state = dna.species.update_base_icon_state(src) + else + update_base_icon_state() + icon_state = "[base_icon_state]_s" - var/list/standing = list() - - //Mouth (lipstick!) - if(lip_style) - standing += image("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[lip_style]_s", "layer" = -BODY_LAYER) - - //Eyes - if(!dna || dna.mutantrace != "skeleton") - var/image/img_eyes_s = image("icon" = 'icons/mob/human_face.dmi', "icon_state" = "eyes_s", "layer" = -BODY_LAYER) - - var/new_color = "#" + eye_color - - img_eyes_s.color = new_color - - standing += img_eyes_s - - //Underwear - if(underwear) - var/datum/sprite_accessory/underwear/U = underwear_all[underwear] - if(U) - standing += image("icon"=U.icon, "icon_state"="[U.icon_state]_s", "layer"=-BODY_LAYER) - - - if(standing.len) - overlays_standing[BODY_LAYER] = standing - - apply_overlay(BODY_LAYER) - + if(dna) // didn't want to have a duplicate if(dna) here, but due to the ordering of the code this was the only way + dna.species.handle_body(src) /mob/living/carbon/human/update_fire() @@ -274,8 +226,6 @@ Please contact me on #coderbus IRC. ~Carnie x apply_overlay(AUGMENTS_LAYER) - - /* --------------------------------------- */ //For legacy support. /mob/living/carbon/human/regenerate_icons() @@ -305,6 +255,8 @@ Please contact me on #coderbus IRC. ~Carnie x update_transform() //Hud Stuff update_hud() + // Mutantrace colors + update_mutcolor() /* --------------------------------------- */ //vvvvvv UPDATE_INV PROCS vvvvvv @@ -322,16 +274,18 @@ Please contact me on #coderbus IRC. ~Carnie x var/t_color = w_uniform.item_color if(!t_color) t_color = icon_state var/image/standing = image("icon"='icons/mob/uniform.dmi', "icon_state"="[t_color]_s", "layer"=-UNIFORM_LAYER) + overlays_standing[UNIFORM_LAYER] = standing - var/G = (gender == FEMALE) ? "f" : "m" - if(G == "f" && U.fitted == 1) - var/index = "[t_color]_s" - var/icon/female_uniform_icon = female_uniform_icons[index] - if(!female_uniform_icon ) //Create standing/laying icons if they don't exist - generate_uniform(index,t_color) - standing = image("icon"=female_uniform_icons["[t_color]_s"], "layer"=-UNIFORM_LAYER) - overlays_standing[UNIFORM_LAYER] = standing + if(dna && dna.species.sexes) + var/G = (gender == FEMALE) ? "f" : "m" + if(G == "f" && U.fitted == 1) + var/index = "[t_color]_s" + var/icon/female_uniform_icon = female_uniform_icons[index] + if(!female_uniform_icon ) //Create standing/laying icons if they don't exist + generate_uniform(index,t_color) + standing = image("icon"=female_uniform_icons["[t_color]_s"], "layer"=-UNIFORM_LAYER) + overlays_standing[UNIFORM_LAYER] = standing if(w_uniform.blood_DNA) standing.overlays += image("icon"='icons/effects/blood.dmi', "icon_state"="uniformblood") @@ -375,6 +329,7 @@ Please contact me on #coderbus IRC. ~Carnie x if(gloves.blood_DNA) standing.overlays += image("icon"='icons/effects/blood.dmi', "icon_state"="bloodyhands") + else if(blood_DNA) overlays_standing[GLOVES_LAYER] = image("icon"='icons/effects/blood.dmi', "icon_state"="bloodyhands") @@ -532,7 +487,6 @@ Please contact me on #coderbus IRC. ~Carnie x if(wear_mask.blood_DNA && !istype(wear_mask, /obj/item/clothing/mask/cigarette)) standing.overlays += image("icon"='icons/effects/blood.dmi', "icon_state"="maskblood") - apply_overlay(FACEMASK_LAYER) @@ -628,7 +582,9 @@ Please contact me on #coderbus IRC. ~Carnie x apply_overlay(L_HAND_LAYER) + //Human Overlays Indexes///////// +#undef SPECIES_LAYER #undef BODY_LAYER #undef MUTATIONS_LAYER #undef DAMAGE_LAYER diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm index 3cfb35adffc..c045f843831 100644 --- a/code/modules/mob/living/carbon/metroid/life.dm +++ b/code/modules/mob/living/carbon/metroid/life.dm @@ -331,13 +331,10 @@ if(issilicon(L) && (rabid || attacked)) // They can't eat silicons, but they can glomp them in defence targets += L // Possible target found! - if(isanimal(L) && (rabid || attacked || hungry >= 2)) //Simple_Animals only get retaliated against. - targets += L - - if(istype(L, /mob/living/carbon/human)) // Ignore slime(wo)men + if(istype(L, /mob/living/carbon/human) && dna) //Ignore slime(wo)men var/mob/living/carbon/human/H = L if(H.dna) - if(H.dna.mutantrace == "slime") + if(/mob/living/carbon/slime in H.dna.species.ignored_by) continue if(!L.canmove) // Only one slime can latch on at a time. @@ -568,4 +565,4 @@ if (hunger == 2 || rabid || attacked) return 1 if (Leader) return 0 if (holding_still) return 0 - return 1 \ No newline at end of file + return 1 diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm index ef4a1102c17..529d105a617 100644 --- a/code/modules/mob/living/carbon/metroid/metroid.dm +++ b/code/modules/mob/living/carbon/metroid/metroid.dm @@ -225,7 +225,7 @@ //paralysis += 1 - show_message(" The blob attacks you!") + show_message(" The blob attacks you!") adjustFireLoss(damage) @@ -237,7 +237,7 @@ return /mob/living/carbon/slime/attack_ui(slot) - return + return /mob/living/carbon/slime/attack_slime(mob/living/carbon/slime/M as mob) if (!ticker) @@ -248,10 +248,8 @@ if (health > -100) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text(" The [M.name] has glomped []!", src), 1) - + visible_message(" The [M.name] has glomped [src]!", \ + " The [M.name] has glomped [src]!") var/damage = rand(1, 3) attacked += 5 @@ -271,8 +269,8 @@ else if(M.attack_sound) playsound(loc, M.attack_sound, 50, 1, 1) - for(var/mob/O in viewers(src, null)) - O.show_message(" [M] [M.attacktext] [src]!", 1) + visible_message("[M] [M.attacktext] [src]!", \ + "[M] [M.attacktext] [src]!") add_logs(M, src, "attacked", admin=0) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) attacked += 10 @@ -303,9 +301,8 @@ if (health > 0) attacked += 10 //playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text(" [M.name] has attacked [src]!"), 1) + visible_message("[M.name] has attacked [src]!", \ + "[M.name] has attacked [src]!") adjustBruteLoss(rand(1, 3)) updatehealth() return @@ -325,15 +322,11 @@ if(Victim) if(Victim == M) if(prob(60)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(" [M] attempts to wrestle \the [name] off!", 1) + visible_message("[M] attempts to wrestle \the [name] off!") playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) else - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(" [M] manages to wrestle \the [name] off!", 1) + visible_message(" [M] manages to wrestle \the [name] off!") playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) if(prob(90) && !client) @@ -353,15 +346,11 @@ else if(prob(30)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(" [M] attempts to wrestle \the [name] off of [Victim]!", 1) + visible_message("[M] attempts to wrestle \the [name] off of [Victim]!") playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) else - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(" [M] manages to wrestle \the [name] off of [Victim]!", 1) + visible_message(" [M] manages to wrestle \the [name] off of [Victim]!") playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) if(prob(80) && !client) @@ -400,9 +389,7 @@ LAssailant = M playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text(" [] has grabbed [] passively!", M, src), 1) + visible_message("[M] has grabbed [src] passively!") else @@ -426,17 +413,14 @@ playsound(loc, "punch", 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text(" [] has punched []!", M, src), 1) + visible_message("[M] has punched [src]!", \ + "[M] has punched [src]!") adjustBruteLoss(damage) updatehealth() else playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text(" [] has attempted to punch []!", M, src), 1) + visible_message("[M] has attempted to punch [src]!") return @@ -452,9 +436,7 @@ switch(M.a_intent) if ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) + visible_message("[M] caresses [src] with its scythe like arm.") if ("harm") @@ -464,20 +446,17 @@ var/damage = rand(15, 30) if (damage >= 25) damage = rand(20, 40) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text(" [] has attacked [name]!", M), 1) + visible_message("[M] has attacked [name]!", \ + "[M] has attacked [name]!") else - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text(" [] has wounded [name]!", M), 1) + visible_message("[M] has wounded [name]!", \ + ")[M] has wounded [name]!") adjustBruteLoss(damage) updatehealth() else playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text(" [] has attempted to lunge at [name]!", M), 1) + visible_message("[M] has attempted to lunge at [name]!", \ + "[M] has attempted to lunge at [name]!") if ("grab") if (M == src || anchored) @@ -491,8 +470,7 @@ LAssailant = M playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message(text(" [] has grabbed [name] passively!", M), 1) + visible_message(" [M] has grabbed [name] passively!") if ("disarm") playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) @@ -500,9 +478,8 @@ attacked += 10 if(prob(95)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text(" [] has tackled [name]!", M), 1) + visible_message("[M] has tackled [name]!", \ + "[M] has tackled [name]!") if(Victim || Target) Victim = null @@ -527,9 +504,8 @@ else drop_item() - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text(" [] has disarmed [name]!", M), 1) + visible_message("[M] has disarmed [name]!", + "[M] has disarmed [name]!") adjustBruteLoss(damage) updatehealth() return @@ -538,7 +514,7 @@ if(W.force > 0) attacked += 10 if(prob(25)) - user << "\red [W] passes right through [src]!" + user << "[W] passes right through [src]!" return if(Discipline && prob(50)) // wow, buddy, why am I getting attacked?? Discipline = 0 @@ -847,6 +823,8 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 ////////Adamantine Golem stuff I dunno where else to put it +// This will eventually be removed. + /obj/item/clothing/under/golem name = "adamantine skin" desc = "a golem's skin" @@ -855,7 +833,6 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 item_color = "golem" flags = ABSTRACT | NODROP has_sensor = 0 - armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) /obj/item/clothing/suit/golem name = "adamantine shell" @@ -866,14 +843,8 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 gas_transfer_coefficient = 0.90 permeability_coefficient = 0.50 body_parts_covered = FULL_BODY - slowdown = 1.0 flags_inv = HIDEGLOVES | HIDESHOES | HIDEJUMPSUIT - flags = STOPSPRESSUREDMAGE | ABSTRACT | NODROP - heat_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS | HEAD - max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT - cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS | HEAD - min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT - armor = list(melee = 80, bullet = 20, laser = 20, energy = 10, bomb = 0, bio = 0, rad = 0) + flags = ABSTRACT | NODROP /obj/item/clothing/shoes/golem name = "golem's feet" @@ -881,7 +852,6 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 icon_state = "golem" item_state = null flags = NOSLIP | ABSTRACT | NODROP - slowdown = SHOES_SLOWDOWN+1 /obj/item/clothing/mask/breath/golem @@ -891,7 +861,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 item_state = "golem" siemens_coefficient = 0 unacidable = 1 - flags = ABSTRACT | NODROP | MASKINTERNALS | MASKCOVERSMOUTH + flags = ABSTRACT | NODROP /obj/item/clothing/gloves/golem @@ -910,10 +880,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 name = "golem's head" desc = "a golem's head" unacidable = 1 - flags = STOPSPRESSUREDMAGE | ABSTRACT | NODROP - heat_protection = HEAD - max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT - armor = list(melee = 80, bullet = 20, laser = 20, energy = 10, bomb = 0, bio = 0, rad = 0) + flags = ABSTRACT | NODROP /obj/effect/golemrune anchored = 1 @@ -952,14 +919,9 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 return var/mob/living/carbon/human/G = new /mob/living/carbon/human if(prob(50)) G.gender = "female" - hardset_dna(G, null, null, null, "adamantine") + hardset_dna(G, null, null, null, null, /datum/species/golem/adamantine) G.real_name = text("Adamantine Golem ([rand(1, 1000)])") - G.equip_to_slot_or_del(new /obj/item/clothing/under/golem(G), slot_w_uniform) - G.equip_to_slot_or_del(new /obj/item/clothing/suit/golem(G), slot_wear_suit) - G.equip_to_slot_or_del(new /obj/item/clothing/shoes/golem(G), slot_shoes) - G.equip_to_slot_or_del(new /obj/item/clothing/mask/breath/golem(G), slot_wear_mask) - G.equip_to_slot_or_del(new /obj/item/clothing/gloves/golem(G), slot_gloves) - //G.equip_to_slot_or_del(new /obj/item/clothing/head/space/golem(G), slot_head) + G.dna.species.auto_equip(G) G.loc = src.loc G.key = ghost.key G << "You are an adamantine golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. Serve [user], and assist them in completing their goals at any cost." @@ -1047,9 +1009,9 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 /obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Hatch() processing_objects.Remove(src) var/turf/T = get_turf(src) - src.visible_message("\blue The [name] pulsates and quivers!") + src.visible_message(" The [name] pulsates and quivers!") spawn(rand(50,100)) - src.visible_message("\blue The [name] bursts open!") + src.visible_message(" The [name] bursts open!") new/mob/living/carbon/slime(T) qdel(src) @@ -1065,4 +1027,4 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 return else ..() -*/ \ No newline at end of file +*/ diff --git a/code/modules/mob/living/carbon/monkey/examine.dm b/code/modules/mob/living/carbon/monkey/examine.dm index fa16619e4d2..6fc0a1d4772 100644 --- a/code/modules/mob/living/carbon/monkey/examine.dm +++ b/code/modules/mob/living/carbon/monkey/examine.dm @@ -43,7 +43,7 @@ msg += "" if (src.digitalcamo) - msg += "It is repulsively uncanny!\n" + msg += "It is moving its body in an unnatural and blatantly unsimian manner.\n" msg += "*---------*" diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 233e9501ea3..7938cea3365 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -77,8 +77,8 @@ if (M.a_intent == "harm" && !is_muzzled()) if ((prob(75) && health > 0)) playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message("[M.name] bites [name]!", 1) + visible_message("[M.name] bites [name]!", \ + "[M.name] bites [name]!") var/damage = rand(1, 5) adjustBruteLoss(damage) health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() @@ -86,8 +86,8 @@ if(istype(D, /datum/disease/jungle_fever)) contract_disease(D,1,0) else - for(var/mob/O in viewers(src, null)) - O.show_message("[M.name] has attempted to bite [name]!", 1) + visible_message("[M.name] has attempted to bite [name]!", \ + "[M.name] has attempted to bite [name]!") return /mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M as mob) @@ -108,9 +108,8 @@ else if (M.a_intent == "harm") if (prob(75)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has punched [name]!", M), 1) + visible_message("[M] has punched [name]!", \ + "[M] has punched [name]!") playsound(loc, "punch", 25, 1, -1) var/damage = rand(5, 10) @@ -119,17 +118,15 @@ if ( (paralysis < 5) && (health > 0) ) Paralyse(rand(10, 15)) spawn( 0 ) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has knocked out [name]!", M), 1) + visible_message("[M] has knocked out [name]!", \ + "[M] has knocked out [name]!") return adjustBruteLoss(damage) updatehealth() else playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has attempted to punch [name]!", M), 1) + visible_message("[M] has attempted to punch [name]!", \ + "[M] has attempted to punch [name]!") else if (M.a_intent == "grab") if (M == src || anchored) @@ -144,22 +141,19 @@ LAssailant = M playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message(text("\red [] has grabbed [name] passively!", M), 1) + visible_message("[M] has grabbed [name] passively!") else if (!( paralysis )) if (prob(25)) Paralyse(2) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has pushed down [name]!", M), 1) + visible_message("[M] has pushed down [src]!", \ + "[M] has pushed down [src]!") else if(drop_item()) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has disarmed [name]!", M), 1) + visible_message("[M] has disarmed [src]!", \ + "[M] has disarmed [src]!") return /mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M as mob) @@ -173,9 +167,7 @@ switch(M.a_intent) if ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) + visible_message(" [M] caresses [src] with its scythe like arm.") if ("harm") if ((prob(95) && health > 0)) @@ -185,20 +177,17 @@ damage = rand(20, 40) if (paralysis < 15) Paralyse(rand(10, 15)) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has wounded [name]!", M), 1) + visible_message("[M] has wounded [name]!", \ + "[M] has wounded [name]!") else - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has slashed [name]!", M), 1) + visible_message("[M] has slashed [name]!", \ + "[M] has slashed [name]!") adjustBruteLoss(damage) updatehealth() else playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has attempted to lunge at [name]!", M), 1) + visible_message("[M] has attempted to lunge at [name]!", \ + "[M] has attempted to lunge at [name]!") if ("grab") if (M == src || anchored) @@ -212,22 +201,19 @@ LAssailant = M playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - O.show_message(text("\red [] has grabbed [name] passively!", M), 1) + visible_message("[M] has grabbed [name] passively!") if ("disarm") playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) var/damage = 5 if(prob(95)) Weaken(10) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has tackled down [name]!", M), 1) + visible_message("[M] has tackled down [name]!", \ + "[M] has tackled down [name]!") else if(drop_item()) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[] has disarmed [name]!", M), 1) + visible_message("[M] has disarmed [name]!", \ + "[M] has disarmed [name]!") adjustBruteLoss(damage) updatehealth() return @@ -238,8 +224,8 @@ else if(M.attack_sound) playsound(loc, M.attack_sound, 50, 1, 1) - for(var/mob/O in viewers(src, null)) - O.show_message("[M] [M.attacktext] [src]!", 1) + visible_message("[M] [M.attacktext] [src]!", \ + "[M] [M.attacktext] [src]!") add_logs(M, src, "attacked", admin=0) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) adjustBruteLoss(damage) @@ -255,9 +241,8 @@ if (health > -100) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("The [M.name] glomps []!", src), 1) + visible_message("The [M.name] glomps [src]!", \ + "The [M.name] glomps [src]!") var/damage = rand(1, 3) @@ -285,7 +270,8 @@ if(M.powerlevel < 0) M.powerlevel = 0 - visible_message("[M] shocked [src]!", "[M] shocked [src]!") + visible_message("[M] shocked [src]!", \ + "[M] shocked [src]!") Weaken(power) if (stuttering < power) @@ -343,6 +329,7 @@ /mob/living/carbon/monkey/blob_act() if (stat != 2) + show_message("The blob attacks you!") adjustFireLoss(60) health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() if (prob(50)) @@ -360,4 +347,4 @@ return 0 /mob/living/carbon/monkey/canBeHandcuffed() - return 1 + return 1 diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index e492bb5d2fb..e903b7cef30 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -16,6 +16,8 @@ /mob/living/proc/getarmor(var/def_zone, var/type) return 0 +/mob/living/proc/on_hit(var/obj/item/projectile/proj_type) + return /mob/living/bullet_act(obj/item/projectile/P, def_zone) var/armor = run_armor_check(def_zone, P.flag) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 9354918ac99..23019c83f9e 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -317,6 +317,8 @@ if(internal) stat("Internal Atmosphere Info", internal.name) stat("Tank Pressure", internal.air_contents.return_pressure()) + for (var/datum/robot_energy_storage/st in module.storages) + stat("[st.name]: [st.energy]/[st.max_energy]") /mob/living/silicon/robot/restrained() return 0 @@ -413,11 +415,13 @@ else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed) var/obj/item/stack/cable_coil/coil = W - adjustFireLoss(-30) - updatehealth() - for(var/mob/O in viewers(user, null)) - O.show_message(text("\red [user] has fixed some of the burnt wires on [src]!"), 1) - coil.use(1) + if (coil.use(1)) + adjustFireLoss(-30) + updatehealth() + for(var/mob/O in viewers(user, null)) + O.show_message(text("\red [user] has fixed some of the burnt wires on [src]!"), 1) + else + user << "You need one length of cable to repair [src]." else if (istype(W, /obj/item/weapon/crowbar)) // crowbar means open or close the cover if(opened) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 277bacfe30b..3fedce48ffb 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -9,7 +9,7 @@ var/list/modules = list() var/obj/item/emag = null var/obj/item/borg/upgrade/jetpack = null - + var/list/storages = list() /obj/item/weapon/robot_module/emp_act(severity) if(modules) @@ -108,42 +108,38 @@ modules += new /obj/item/device/t_scanner(src) modules += new /obj/item/device/analyzer(src) + var/datum/robot_energy_storage/metal/metstore = new /datum/robot_energy_storage/metal(src) + var/datum/robot_energy_storage/glass/glastore = new /datum/robot_energy_storage/glass(src) + var/datum/robot_energy_storage/wire/wirestore = new /datum/robot_energy_storage/wire(src) + var/obj/item/stack/sheet/metal/cyborg/M = new /obj/item/stack/sheet/metal/cyborg(src) - M.amount = 50 + M.source = metstore modules += M + var/obj/item/stack/sheet/glass/cyborg/Q = new /obj/item/stack/sheet/glass/cyborg(src) + Q.source = glastore + modules += Q + var/obj/item/stack/sheet/rglass/cyborg/G = new /obj/item/stack/sheet/rglass/cyborg(src) - G.amount = 50 + G.metsource = metstore + G.glasource = glastore modules += G var/obj/item/stack/rods/cyborg/R = new /obj/item/stack/rods/cyborg(src) - R.amount = 50 + R.source = metstore modules += R - var/obj/item/stack/cable_coil/W = new /obj/item/stack/cable_coil(src) - W.amount = 50 + var/obj/item/stack/cable_coil/cyborg/W = new /obj/item/stack/cable_coil/cyborg(src) + W.source = wirestore modules += W var/obj/item/stack/tile/plasteel/cyborg/F = new /obj/item/stack/tile/plasteel/cyborg(src) //"Plasteel" is the normal metal floor tile, Don't be confused - RR - F.amount = 50 - modules += F //'F' for floor tile - RR - - - respawn_consumable(var/mob/living/silicon/robot/R) - var/list/what = list ( - /obj/item/stack/sheet/metal, - /obj/item/stack/sheet/rglass, - /obj/item/stack/rods, - /obj/item/stack/cable_coil, - /obj/item/stack/tile/plasteel/cyborg, - ) - for(var/T in what) - if(!(locate(T) in modules)) - modules -= null - var/O = new T(src) - modules += O - O:amount = 1 + F.source = metstore + modules += F //'F' for floor tile - RR(src) + storages += metstore + storages += glastore + storages += wirestore /obj/item/weapon/robot_module/security name = "security robot module" @@ -239,4 +235,37 @@ modules += new /obj/item/weapon/gun/energy/laser/cyborg(src) modules += new /obj/item/weapon/tank/jetpack/carbondioxide(src) modules += new /obj/item/weapon/crowbar(src) - emag = null \ No newline at end of file + emag = null + +/datum/robot_energy_storage + var/name = "Generic energy storage" + var/max_energy = 30000 + var/recharge_rate = 1000 + var/energy + +/datum/robot_energy_storage/New() + energy = max_energy + return + +/datum/robot_energy_storage/proc/use_charge(var/amount) + if (energy >= amount) + energy -= amount + if (energy == 0) + return 1 + return 2 + else + return 0 + +/datum/robot_energy_storage/proc/add_charge(var/amount) + energy = min(energy + amount, max_energy) + +/datum/robot_energy_storage/metal + name = "Metal Synthesizer" + +/datum/robot_energy_storage/glass + name = "Glass Synthesizer" + +/datum/robot_energy_storage/wire + max_energy = 50 + recharge_rate = 2 + name = "Wire Synthesizer" diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 2ab4636438a..9506df68555 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -9,6 +9,7 @@ response_disarm = "flails at" response_harm = "punches" icon_dead = "shade_dead" + icon = 'icons/mob/mob.dmi' speed = 0 a_intent = "harm" stop_automated_movement = 1 @@ -25,6 +26,7 @@ minbodytemp = 0 faction = "cult" var/list/construct_spells = list() + var/playstyle_string = "You are a generic construct! Your job is to not exist." /mob/living/simple_animal/construct/New() ..() @@ -118,8 +120,7 @@ /mob/living/simple_animal/construct/armoured name = "Juggernaut" real_name = "Juggernaut" - desc = "A possessed suit of armour driven by the will of the restless dead" - icon = 'icons/mob/mob.dmi' + desc = "A possessed suit of armour driven by the will of the restless dead." icon_state = "behemoth" icon_living = "behemoth" maxHealth = 250 @@ -135,7 +136,8 @@ status_flags = 0 force_threshold = 11 construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall) - + playstyle_string = "You are a Juggernaut. Though slow, your shell can withstand extreme punishment, \ + create shield walls and even deflect energy weapons, and rip apart enemies and walls alike." /mob/living/simple_animal/construct/armoured/bullet_act(var/obj/item/projectile/P) if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) @@ -174,7 +176,6 @@ name = "Wraith" real_name = "Wraith" desc = "A wicked bladed shell contraption piloted by a bound spirit" - icon = 'icons/mob/mob.dmi' icon_state = "floating" icon_living = "floating" maxHealth = 75 @@ -186,18 +187,16 @@ see_in_dark = 7 attack_sound = 'sound/weapons/bladeslice.ogg' construct_spells = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift) + playstyle_string = "You are a Wraith. Though relatively fragile, you are fast, deadly, and even able to phase through walls." /////////////////////////////Artificer///////////////////////// - - /mob/living/simple_animal/construct/builder name = "Artificer" real_name = "Artificer" desc = "A bulbous construct dedicated to building and maintaining The Cult of Nar-Sie's armies" - icon = 'icons/mob/mob.dmi' icon_state = "artificer" icon_living = "artificer" maxHealth = 50 @@ -215,60 +214,31 @@ /obj/effect/proc_holder/spell/aoe_turf/conjure/floor, /obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone, /obj/effect/proc_holder/spell/targeted/projectile/magic_missile/lesser) + playstyle_string = "You are an Artificer. You are incredibly weak and fragile, but you are able to construct fortifications, \ + use magic missile, repair allied constructs (by clicking on them), \ + and most important of all create new constructs \ + (Use your Artificer spell to summon a new construct shell and Summon Soulstone to create a new soulstone)." +/////////////////////////////Harvester///////////////////////// -/////////////////////////////Behemoth///////////////////////// +/mob/living/simple_animal/construct/harvester + name = "Harvester" + real_name = "Harvester" + desc = "A harbinger of Nar-Sie's enlightenment. It'll be all over soon." + icon_state = "harvester" + icon_living = "harvester" + maxHealth = 60 + health = 60 + melee_damage_lower = 1 + melee_damage_upper = 5 + attacktext = "prods" + speed = 0 + environment_smash = 1 + see_in_dark = 7 + attack_sound = 'sound/weapons/tap.ogg' + construct_spells = list(/obj/effect/proc_holder/spell/targeted/smoke/disable) + playstyle_string = "You are a Harvester. You are not strong, but your powers of domination will assist you in your role: \ + Bring those who still cling to this world of illusion back to the Geometer so they may know Truth." - -/mob/living/simple_animal/construct/behemoth - name = "Behemoth" - real_name = "Behemoth" - desc = "The pinnacle of occult technology, Behemoths are the ultimate weapon in the Cult of Nar-Sie's arsenal." - icon = 'icons/mob/mob.dmi' - icon_state = "behemoth" - icon_living = "behemoth" - maxHealth = 750 - health = 750 - speak_emote = list("rumbles") - response_harm = "harmlessly punches" - harm_intent_damage = 0 - melee_damage_lower = 50 - melee_damage_upper = 50 - attacktext = "brutally crushes" - speed = 5 - environment_smash = 2 - attack_sound = 'sound/weapons/punch4.ogg' - force_threshold = 11 - var/energy = 0 - var/max_energy = 1000 - - -////////////////Powers////////////////// - - -/* -/client/proc/summon_cultist() - set category = "Behemoth" - set name = "Summon Cultist (300)" - set desc = "Teleport a cultist to your location" - if (istype(usr,/mob/living/simple_animal/constructbehemoth)) - - if(usr.energy<300) - usr << "\red You do not have enough power stored!" - return - - if(usr.stat) - return - - usr.energy -= 300 - var/list/mob/living/cultists = new - for(var/datum/mind/H in ticker.mode.cult) - if (istype(H.current,/mob/living)) - cultists+=H.current - var/mob/cultist = input("Choose the one who you want to summon", "Followers of Geometer") as null|anything in (cultists - usr) - if(!cultist) - return - if (cultist == usr) //just to be sure. - return - cultist.loc = usr.loc - usr.visible_message("/red [cultist] appears in a flash of red light as [usr] glows with power")*/ +/mob/living/simple_animal/construct/harvester/Process_Spacemove(var/check_drift = 0) + return 1 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 522122633b8..c65884dfc63 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -111,6 +111,11 @@ return 0 if(L in friends) return 0 + if(ishuman(L)) + var/mob/living/carbon/human/H = L + if(H.dna) + if(src.type in H.dna.species.ignored_by) + return 0 return 1 if(isobj(the_target)) if(the_target.type in wanted_objects) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index bf2a8a17afd..38916358259 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -245,8 +245,7 @@ return if(act) if(act == "scream") act = "makes a loud and pained whimper" //ugly hack to stop animals screaming when crushed :P - for (var/mob/O in viewers(src, null)) - O.show_message("[src] [act].") + visible_message("[src] [act].") /mob/living/simple_animal/attack_animal(mob/living/simple_animal/M as mob) @@ -255,8 +254,8 @@ else if(M.attack_sound) playsound(loc, M.attack_sound, 50, 1, 1) - for(var/mob/O in viewers(src, null)) - O.show_message("\red \The [M] [M.attacktext] [src]!", 1) + visible_message("\The [M] [M.attacktext] [src]!", \ + "\The [M] [M.attacktext] [src]!") add_logs(M, src, "attacked", admin=0) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) adjustBruteLoss(damage) @@ -276,9 +275,7 @@ if("help") if (health > 0) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\blue [M] [response_help] [src].") + visible_message(" [M] [response_help] [src].") if("grab") if (M == src || anchored) @@ -294,15 +291,11 @@ LAssailant = M - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) + visible_message("[M] has grabbed [src] passively!") if("harm", "disarm") adjustBruteLoss(harm_intent_damage) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message("\red [M] [response_harm] [src]!") + visible_message("[M] [response_harm] [src]!") return @@ -312,9 +305,7 @@ if ("help") - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1) + visible_message("[M] caresses [src] with its scythe like arm.") if ("grab") if(M == src || anchored) return @@ -329,13 +320,12 @@ LAssailant = M playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - for(var/mob/O in viewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("\red [] has grabbed [] passively!", M, src), 1) + visible_message("[M] has grabbed [src] passively!") if("harm", "disarm") var/damage = rand(15, 30) - visible_message("\red [M] has slashed at [src]!") + visible_message("[M] has slashed at [src]!", \ + "[M] has slashed at [src]!") adjustBruteLoss(damage) return @@ -344,13 +334,14 @@ switch(L.a_intent) if("help") - visible_message("\blue [L] rubs it's head against [src]") + visible_message("[L] rubs its head against [src].") else var/damage = rand(5, 10) - visible_message("\red [L] bites [src]!") + visible_message("[L] bites [src]!", \ + "[L] bites [src]!") if(stat != DEAD) L.amount_grown = min(L.amount_grown + damage, L.max_grown) @@ -364,7 +355,8 @@ if(M.Victim) return // can't attack while eating! - visible_message("\red [M.name] glomps [src]!") + visible_message("[M.name] glomps [src]!", \ + "[M.name] glomps [src]!") var/damage = rand(1, 3) @@ -391,18 +383,16 @@ MED.amount -= 1 if(MED.amount <= 0) qdel(MED) - for(var/mob/M in viewers(src, null)) - if ((M.client && !( M.blinded ))) - M.show_message("\blue [user] applies [MED] on [src]") + visible_message(" [user] applies [MED] on [src].") return else - user << "\blue [MED] won't help at all." + user << " [MED] won't help at all." return else - user << "\blue [src] is at full health." + user << " [src] is at full health." return else - user << "\blue [src] is dead, medical items won't bring it back to life." + user << " [src] is dead, medical items won't bring it back to life." return else if(meat_type && (stat == DEAD)) //if the animal has a meat, and if it is dead. if(istype(O, /obj/item/weapon/kitchenknife) || istype(O, /obj/item/weapon/butch)) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index e295e0b6553..25d81d559cb 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -420,6 +420,9 @@ proc/is_special_character(mob/M) // returns 1 for special characters and 2 for h var/list/hands = list(M.l_hand, M.r_hand) return hands +/mob/proc/reagent_check(var/datum/reagent/R) // utilized in the species code + return 1 + /proc/item_heal_robotic(var/mob/living/carbon/human/H, var/mob/user, var/brute, var/burn) var/obj/item/organ/limb/affecting = H.get_organ(check_zone(user.zone_sel.selecting)) @@ -442,4 +445,4 @@ proc/is_special_character(mob/M) // returns 1 for special characters and 2 for h user << "[H]'s [affecting.getDisplayName()] is already in good condition" return else - return \ No newline at end of file + return diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index 6badea404f5..17df645d3aa 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -12,6 +12,7 @@ datum/preferences hair_color = random_short_color() facial_hair_color = hair_color eye_color = random_eye_color() + pref_species = new /datum/species/human() backbag = 2 age = rand(AGE_MIN,AGE_MAX) @@ -23,7 +24,11 @@ datum/preferences var/g = "m" if(gender == FEMALE) g = "f" - preview_icon = new /icon('icons/mob/human.dmi', "[skin_tone]_[g]_s") + if(pref_species.id == "human" || !config.mutant_races) + preview_icon = new /icon('icons/mob/human.dmi', "[skin_tone]_[g]_s") + else + preview_icon = new /icon('icons/mob/human.dmi', "[pref_species.id]_[g]_s") + preview_icon.Blend("#[mutant_color]", ICON_MULTIPLY) var/datum/sprite_accessory/S if(underwear) @@ -31,17 +36,19 @@ datum/preferences if(S) preview_icon.Blend(new /icon(S.icon, "[S.icon_state]_s"), ICON_OVERLAY) - var/icon/eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = "eyes_s") - eyes_s.Blend("#[eye_color]", ICON_MULTIPLY) + var/icon/eyes_s = new/icon() + if(EYECOLOR in pref_species.specflags) + eyes_s = new/icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = "[pref_species.eyes]_s") + eyes_s.Blend("#[eye_color]", ICON_MULTIPLY) S = hair_styles_list[hair_style] - if(S) + if(S && (HAIR in pref_species.specflags)) var/icon/hair_s = new/icon("icon" = S.icon, "icon_state" = "[S.icon_state]_s") hair_s.Blend("#[hair_color]", ICON_MULTIPLY) eyes_s.Blend(hair_s, ICON_OVERLAY) S = facial_hair_styles_list[facial_hair_style] - if(S) + if(S && (FACEHAIR in pref_species.specflags)) var/icon/facial_s = new/icon("icon" = S.icon, "icon_state" = "[S.icon_state]_s") facial_s.Blend("#[facial_hair_color]", ICON_MULTIPLY) eyes_s.Blend(facial_s, ICON_OVERLAY) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 7b69731d0cd..0258e2f08a8 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -133,6 +133,12 @@ O.gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE O.dna = dna + + if(!dna.species) + O.dna.species = new /datum/species/human() + else + O.dna.species = new dna.species.type() + dna = null if (newname) //if there's a name as an argument, always take that one over the current name O.real_name = newname @@ -475,20 +481,8 @@ if(!MP) return 0 //Sanity, this should never happen. -// if(ispath(MP, /mob/living/simple_animal/space_worm)) //Goodbye Space Worms 2014 -// return 0 //Unfinished. Very buggy, they seem to just spawn additional space worms everywhere and eating your own tail results in new worms spawning. - - if(ispath(MP, /mob/living/simple_animal/construct/behemoth)) - return 0 //I think this may have been an unfinished WiP or something. These constructs should really have their own class simple_animal/construct/subtype - - if(ispath(MP, /mob/living/simple_animal/construct/armoured)) - return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype - - if(ispath(MP, /mob/living/simple_animal/construct/wraith)) - return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype - - if(ispath(MP, /mob/living/simple_animal/construct/builder)) - return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype + if(ispath(MP, /mob/living/simple_animal/construct)) + return 0 //Verbs do not appear for players. //Good mobs! if(ispath(MP, /mob/living/simple_animal/cat)) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index e296c3123fd..dd23b2ed520 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -488,28 +488,29 @@ user << "You fail to [ locked ? "unlock" : "lock"] the APC interface." else if (istype(W, /obj/item/stack/cable_coil) && !terminal && opened && has_electronics!=2) if (src.loc:intact) - user << "\red You must remove the floor plating in front of the APC first." + user << "You must remove the floor plating in front of the APC first." return var/obj/item/stack/cable_coil/C = W - if(C.amount < 10) - user << "\red You need more wires." + if(C.get_amount() < 10) + user << "You need ten lengths of cable for APC." return user << "You start adding cables to the APC frame..." playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - if(do_after(user, 20) && C.amount >= 10) - var/turf/T = get_turf(src) - var/obj/structure/cable/N = T.get_cable_node() - if (prob(50) && electrocute_mob(usr, N, N)) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - return - C.use(10) - user.visible_message(\ - "\red [user.name] has added cables to the APC frame!",\ - "You add cables to the APC frame.") - make_terminal() - terminal.connect_to_network() + if(do_after(user, 20)) + if (C.amount >= 10 && !terminal && opened && has_electronics != 2) + var/turf/T = get_turf(src) + var/obj/structure/cable/N = T.get_cable_node() + if (prob(50) && electrocute_mob(usr, N, N)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + return + C.use(10) + user.visible_message(\ + "\red [user.name] has added cables to the APC frame!",\ + "You add cables to the APC frame.") + make_terminal() + terminal.connect_to_network() else if (istype(W, /obj/item/weapon/wirecutters) && terminal && opened && has_electronics!=2) if (src.loc:intact) user << "\red You must remove the floor plating in front of the APC first." diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 3aa64529fc7..19ebe4a5600 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -146,6 +146,9 @@ By design, d1 is the smallest direction and d2 is the highest else if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/coil = W + if (coil.get_amount() < 1) + user << "Not enough cable" + return coil.cable_join(src, user) else if(istype(W, /obj/item/device/multitool)) @@ -464,6 +467,12 @@ obj/structure/cable/proc/avail() slot_flags = SLOT_BELT attack_verb = list("whipped", "lashed", "disciplined", "flogged") +/obj/item/stack/cable_coil/cyborg + is_cyborg = 1 + m_amt = 0 + g_amt = 0 + cost = 1 + /obj/item/stack/cable_coil/suicide_act(mob/user) if(locate(/obj/structure/stool) in user.loc) user.visible_message("[user] is making a noose with the [src.name]! It looks like \he's trying to commit suicide.") @@ -515,12 +524,15 @@ obj/structure/cable/proc/avail() /obj/item/stack/cable_coil/examine() set src in view(1) - if(amount == 1) - usr << "A short piece of power cable." - else if(amount == 2) - usr << "A piece of power cable." + if (is_cyborg) + usr << "A cable synthesizer. Currently has energy for [get_amount()] lengths of cable." else - usr << "A coil of power cable. There are [amount] lengths of cable in the coil." + if(get_amount() == 1) + usr << "A short piece of power cable." + else if(get_amount() == 2) + usr << "A piece of power cable." + else + usr << "A coil of power cable. There are [get_amount()] lengths of cable in the coil." /obj/item/stack/cable_coil/verb/make_restraint() @@ -553,7 +565,12 @@ obj/structure/cable/proc/avail() src.update_icon() return - else if( istype(W, /obj/item/stack/cable_coil) ) + else if(istype(W, /obj/item/stack/cable_coil/cyborg)) + var/obj/item/stack/cable_coil/cyborg/C = W + var/to_transfer = min(src.amount, round((C.source.max_energy - C.source.energy) / C.cost)) + C.add(to_transfer) + src.use(to_transfer) + else if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = W if(C.amount >= MAXCOIL) user << "The coil is too long, you cannot add any more cable to it." @@ -573,6 +590,7 @@ obj/structure/cable/proc/avail() return //remove cables from the stack +/* This is probably reduntant /obj/item/stack/cable_coil/use(var/used) if(src.amount < used) return 0 @@ -586,6 +604,11 @@ obj/structure/cable/proc/avail() amount -= used update_icon() return 1 +*/ +/obj/item/stack/cable_coil/use(var/used) + . = ..() + update_icon() + return //add cables to the stack /obj/item/stack/cable_coil/proc/give(var/extra) @@ -604,11 +627,15 @@ obj/structure/cable/proc/avail() if(!isturf(user.loc)) return - if(get_dist(F,user) > 1) //too far + if(get_amount() < 1) // Out of cable + user << "There is no cable left." + return + + if(get_dist(F,user) > 1) // Too far user << "You can't lay cable at a place that far away." return - if(F.intact) // if floor is intact, complain + if(F.intact) // Ff floor is intact, complain user << "You can't lay cable there unless the floor tiles are removed." return diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 7158a28f907..8261e9fc7dc 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -137,15 +137,17 @@ if(istype(W, /obj/item/stack/cable_coil)) if (src.stage != 1) return var/obj/item/stack/cable_coil/coil = W - coil.use(1) - switch(fixture_type) - if ("tube") - src.icon_state = "tube-construct-stage2" - if("bulb") - src.icon_state = "bulb-construct-stage2" - src.stage = 2 - user.visible_message("[user.name] adds wires to [src].", \ - "You add wires to [src].") + if (coil.use(1)) + switch(fixture_type) + if ("tube") + src.icon_state = "tube-construct-stage2" + if("bulb") + src.icon_state = "bulb-construct-stage2" + src.stage = 2 + user.visible_message("[user.name] adds wires to [src].", \ + "You add wires to [src].") + else + user << "You need one length of cable to wire [src]." return if(istype(W, /obj/item/weapon/screwdriver)) diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm index f4751450a1d..85684c8e756 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm @@ -226,10 +226,14 @@ So, hopefully this is helpful if any more icons are to be added/changed/wonderin "You remove the external bolts.") temp_state-- else if(istype(O, /obj/item/stack/cable_coil)) - if(O:use(1,user)) + var/obj/item/stack/cable_coil/C = O + if(C.use(1)) user.visible_message("[user.name] adds wires to the [src.name].", \ "You add some wires.") temp_state++ + else + user << "You need one length of cable to wire the [src.name]." + return if(2) if(istype(O, /obj/item/weapon/wirecutters))//TODO:Shock user if its on? user.visible_message("[user.name] removes some wires from the [src.name].", \ diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index a0725f79ee5..ffe2e10a903 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -1,10 +1,5 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33 -var/global/list/uneatable = list( - /turf/space, - /obj/effect/overlay - ) - /obj/machinery/singularity name = "gravitational singularity" desc = "A gravitational singularity." @@ -31,7 +26,9 @@ var/global/list/uneatable = list( var/target = null //its target. moves towards the target if it has one var/last_failed_movement = 0//Will not move in the same dir if it couldnt before, will help with the getting stuck on fields thing var/teleport_del = 0 + var/sizes_to_number = list("1" = 0, "3" = 1, "5" = 2, "7" = 3, "9" = 4) //so i dont have to mess around with weirdass formulas to get this done. var/last_warning + var/list/uneatable = list(/turf/space, /obj/effect/overlay) /obj/machinery/singularity/New(loc, var/starting_energy = 50, var/temp = 0) //CARN: admin-alert for chuckle-fuckery. @@ -233,7 +230,7 @@ var/global/list/uneatable = list( if(current_size >= 5) var/list/handlist = list(H.l_hand, H.r_hand) for(var/obj/item/hand in handlist) - if(prob(current_size * 5) && hand.w_class <= 2 && H.unEquip(hand)) + if(prob(current_size * 5) && hand.w_class >= 5 - sizes_to_number["[current_size]"] && H.unEquip(hand)) step_towards(hand, src) H << "\The [src] pulls \the [hand] from your grip!" @@ -477,6 +474,7 @@ var/global/list/uneatable = list( move_self = 1 //Do we move on our own? grav_pull = 5 //How many tiles out do we pull? consume_range = 6 //How many tiles out do we eat + uneatable = list(/turf/space, /obj/effect/overlay, /mob/living/simple_animal/construct) /obj/machinery/singularity/narsie/large name = "Nar-Sie" @@ -496,6 +494,12 @@ var/global/list/uneatable = list( if(emergency_shuttle) emergency_shuttle.incall(0.3) // Cannot recall + +/obj/machinery/singularity/narsie/large/attack_ghost(mob/dead/observer/user as mob) + makeNewConstruct(/mob/living/simple_animal/construct/harvester, user, null, 1) + new /obj/effect/effect/sleep_smoke(user.loc) + + /obj/machinery/singularity/narsie/process() eat() if(!target || prob(5)) @@ -538,8 +542,11 @@ var/global/list/uneatable = list( if(istype(A,/mob/living/)) var/mob/living/C = A + if(C.client) + makeNewConstruct(/mob/living/simple_animal/construct/harvester, C, null, 1) C.spawn_dust() C.gib() + return if(isturf(A)) var/turf/T = A @@ -550,35 +557,33 @@ var/global/list/uneatable = list( if(prob(20)) T.ChangeTurf(/turf/simulated/wall/cult) return + /obj/machinery/singularity/narsie/ex_act() //No throwing bombs at it either. --NEO return + /obj/machinery/singularity/narsie/proc/pickcultist() //Narsie rewards his cultists with being devoured first, then picks a ghost to follow. --NEO var/list/cultists = list() - for(var/datum/mind/cult_nh_mind in ticker.mode.cult) - if(!cult_nh_mind.current) - continue - if(cult_nh_mind.current.stat) - continue - var/turf/pos = get_turf(cult_nh_mind.current) - if(pos.z != src.z) - continue - cultists += cult_nh_mind.current - if(cultists.len) - acquire(pick(cultists)) - return - //If there was living cultists, it picks one to follow. - for(var/mob/living/carbon/human/food in living_mob_list) - if(food.stat) - continue + var/list/noncultists = list() + for(var/mob/living/carbon/food in living_mob_list) //we don't care about constructs or cult-Ians or whatever. cult-monkeys are fair game i guess var/turf/pos = get_turf(food) if(pos.z != src.z) continue - cultists += food - if(cultists.len) - acquire(pick(cultists)) - return - //no living cultists, pick a living human instead. + + if(iscultist(food)) + cultists += food + else + noncultists += food + + if(cultists.len) //cultists get higher priority + acquire(pick(cultists)) + return + + if(noncultists.len) + acquire(pick(noncultists)) + return + + //no living humans, follow a ghost instead. for(var/mob/dead/observer/ghost in player_list) if(!ghost.client) continue @@ -589,7 +594,7 @@ var/global/list/uneatable = list( if(cultists.len) acquire(pick(cultists)) return - //no living humans, follow a ghost instead. + /obj/machinery/singularity/narsie/proc/acquire(var/mob/food) target << "\blue NAR-SIE HAS LOST INTEREST IN YOU" diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index 7c3e16ed5a4..8b394c28d73 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -219,15 +219,17 @@ var/list/solars_list = list() if(istype(W, /obj/item/stack/sheet/glass) || istype(W, /obj/item/stack/sheet/rglass)) var/obj/item/stack/sheet/S = W - if(S.amount >= 2) + if(S.use(2)) glass_type = W.type - S.use(2) playsound(src.loc, 'sound/machines/click.ogg', 50, 1) user.visible_message("[user] places the glass on the solar assembly.") if(tracker) new /obj/machinery/power/tracker(get_turf(src), src) else new /obj/machinery/power/solar(get_turf(src), src) + else + user << "You need two sheets of glass to put them into a solar panel." + return return 1 if(!tracker) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 7d79eaeb7de..ea2a9a8c73e 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -80,8 +80,8 @@ return if(ishuman(user)) var/mob/living/carbon/human/H = user - if(H.dna && H.dna.mutantrace == "adamantine") - user << "Your metal fingers don't fit in the trigger guard!" + if(H.dna && NOGUNS in H.dna.species.specflags) + user << "Your fingers don't fit in the trigger guard!" return add_fingerprint(user) diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 988d947a13e..f1ee2f12a74 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -33,20 +33,24 @@ /obj/item/weapon/gun/energy/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, params) - newshot() + newshot() //prepare a new shot ..() /obj/item/weapon/gun/energy/proc/newshot() - if (!ammo_type || !power_supply) return + if (!ammo_type || !power_supply) + return var/obj/item/ammo_casing/energy/shot = ammo_type[select] - if (!power_supply.use(shot.e_cost)) return - chambered = shot - chambered.newshot() + if(power_supply.charge >= shot.e_cost) //if there's enough power in the power_supply cell... + chambered = shot //...prepare a new shot based on the current ammo type selected + chambered.newshot() return /obj/item/weapon/gun/energy/process_chamber() - chambered = null + if(chambered && !chambered.BB) //if BB is null, i.e the shot has been fired... + var/obj/item/ammo_casing/energy/shot = chambered + power_supply.use(shot.e_cost)//... drain the power_supply cell + chambered = null //either way, released the prepared shot return /obj/item/weapon/gun/energy/proc/select_fire(mob/living/user as mob) @@ -56,7 +60,7 @@ var/obj/item/ammo_casing/energy/shot = ammo_type[select] fire_sound = shot.fire_sound if (shot.select_name) - user << "\red [src] is now set to [shot.select_name]." + user << "[src] is now set to [shot.select_name]." update_icon() return diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 6fc8094d59f..afd7bf263ab 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -58,6 +58,7 @@ if(!isliving(target)) return 0 if(isanimal(target)) return 0 var/mob/living/L = target + L.on_hit(type) return L.apply_effects(stun, weaken, paralyze, irradiate, stutter, eyeblur, drowsy, blocked) proc/vol_by_damage() diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index e65431d7ad7..2efdbab093b 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -199,8 +199,12 @@ proc/wabbajack(mob/living/M) var/mob/living/carbon/human/H = new_mob ready_dna(H) if(H.dna) - H.dna.mutantrace = pick("lizard","golem","slime","plant","fly","shadow","adamantine","skeleton",8;"") - H.update_body() + var/list/randspecies = list() + for(var/t in typesof(/datum/species)) // returns a bunch of types + var/datum/species/temp = new t() + randspecies += "[temp.type]" + var/datum/species/new_species = pick(randspecies) + H.dna.species = new new_species() else return diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index afe46c110e3..e067b00b949 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -82,32 +82,8 @@ flag = "energy" on_hit(var/atom/target, var/blocked = 0) - if(iscarbon(target)) - var/mob/living/carbon/M = target - if(check_dna_integrity(M) && M.dna.mutantrace == "plant") //Plantmen possibly get mutated and damaged by the rays. - if(prob(15)) - M.apply_effect((rand(30,80)),IRRADIATE) - M.Weaken(5) - for (var/mob/V in viewers(src)) - V.show_message("\red [M] writhes in pain as \his vacuoles boil.", 3, "\red You hear the crunching of leaves.", 2) - if(prob(35)) - // for (var/mob/V in viewers(src)) //Public messages commented out to prevent possible metaish genetics experimentation and stuff. - Cheridan - // V.show_message("\red [M] is mutated by the radiation beam.", 3, "\red You hear the snapping of twigs.", 2) - if(prob(80)) - randmutb(M) - domutcheck(M,null) - else - randmutg(M) - domutcheck(M,null) - else - M.adjustFireLoss(rand(5,15)) - M.show_message("\red The radiation beam singes you!") - // for (var/mob/V in viewers(src)) - // V.show_message("\red [M] is singed by the radiation beam.", 3, "\red You hear the crackle of burning leaves.", 2) - else - // for (var/mob/V in viewers(src)) - // V.show_message("The radiation beam dissipates harmlessly through [M]", 3) - M.show_message("\blue The radiation beam dissipates harmlessly through your body.") + ..() + return /obj/item/projectile/energy/florayield name = "beta somatoray" @@ -117,14 +93,9 @@ nodamage = 1 flag = "energy" - on_hit(mob/living/carbon/target, var/blocked = 0) - if(iscarbon(target)) - if(ishuman(target) && target.dna && target.dna.mutantrace == "plant") //These rays make plantmen fat. - target.nutrition = min(target.nutrition+30, 500) - else - target.show_message("\blue The radiation beam dissipates harmlessly through your body.") - else - return 1 + on_hit(mob/living/carbon/human/target, var/blocked = 0) + ..() + return /obj/item/projectile/beam/mindflayer diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index a675580369a..4eec5cad53a 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -200,7 +200,9 @@ datum for(var/A in reagent_list) var/datum/reagent/R = A if(M && R) - R.on_mob_life(M) + if(M.reagent_check(R) != 1) + R.on_mob_life(M) + update_total() conditional_update_move(var/atom/A, var/Running = 0) diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index e7a8c57b042..ef9f736fa34 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -342,18 +342,6 @@ datum reagent_state = LIQUID color = "#13BC5E" // rgb: 19, 188, 94 - on_mob_life(var/mob/living/M as mob) - if(!M) M = holder.my_atom - if(ishuman(M)) - var/mob/living/carbon/human/human = M - if(human.dna && !human.dna.mutantrace) - M << "Your flesh rapidly mutates!" - human.dna.mutantrace = "slime" - human.update_body() - human.update_hair() - ..() - return - aslimetoxin name = "Advanced Mutation Toxin" id = "amutationtoxin" @@ -1507,11 +1495,6 @@ datum var/mob/living/carbon/C = M if(!C.wear_mask) // If not wearing a mask C.adjustToxLoss(2) // 4 toxic damage per application, doubled for some reason - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.dna) - if(H.dna.mutantrace == "plant") //plantmen take a LOT of damage - H.adjustToxLoss(10) toxin/plantbgone/weedkiller name = "Weed Killer" @@ -1534,11 +1517,6 @@ datum var/mob/living/carbon/C = M if(!C.wear_mask) // If not wearing a mask C.adjustToxLoss(2) // 4 toxic damage per application, doubled for some reason - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.dna) - if(H.dna.mutantrace == "fly") //Botanists can now genocide plant and fly people alike. - H.adjustToxLoss(10) toxin/stoxin name = "Sleep Toxin" diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index e23270bafc3..0f630190c1a 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -62,9 +62,9 @@ var/who = (isnull(user) || eater == user) ? "your" : "their" if(istype(cover, /obj/item/clothing/mask/)) - user << "You have to remove [who] mask first!" + user << "You have to remove [who] mask first!" else - user << "You have to remove [who] helmet first!" + user << "You have to remove [who] helmet first!" return 0 - return 1 \ No newline at end of file + return 1 diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 7d8ae71c443..697a96fc5bd 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -59,6 +59,12 @@ return if(ismob(target)) //Blood! + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(H.dna) + if(NOBLOOD in H.dna.species.specflags) + user << "You are unable to locate any blood." + return if(reagents.has_reagent("blood")) user << "There is already a blood sample in this syringe." return diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index e5588ca946f..6c960e0d5c8 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -75,15 +75,15 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). if(istype(O, /obj/item/weapon/crowbar)) for(var/obj/item/weapon/reagent_containers/glass/G in component_parts) reagents.trans_to(G, G.reagents.maximum_volume) - if(g_amount >= 3750) + if(g_amount >= MINERAL_MATERIAL_AMOUNT) var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(src.loc) - G.amount = round(g_amount / 3750) - if(gold_amount >= 2000) + G.amount = round(g_amount / MINERAL_MATERIAL_AMOUNT) + if(gold_amount >= MINERAL_MATERIAL_AMOUNT) var/obj/item/stack/sheet/mineral/gold/G = new /obj/item/stack/sheet/mineral/gold(src.loc) - G.amount = round(gold_amount / 2000) - if(diamond_amount >= 2000) + G.amount = round(gold_amount / MINERAL_MATERIAL_AMOUNT) + if(diamond_amount >= MINERAL_MATERIAL_AMOUNT) var/obj/item/stack/sheet/mineral/diamond/G = new /obj/item/stack/sheet/mineral/diamond(src.loc) - G.amount = round(diamond_amount / 2000) + G.amount = round(diamond_amount / MINERAL_MATERIAL_AMOUNT) default_deconstruction_crowbar(O) return else @@ -116,14 +116,14 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). amount = min(stack.amount, round((max_material_amount-TotalMaterials())/stack.perunit)) busy = 1 - use_power(max(1000, (3750*amount/10))) + use_power(max(1000, (MINERAL_MATERIAL_AMOUNT*amount/10))) user << "You add [amount] sheets to the [src.name]." if(istype(stack, /obj/item/stack/sheet/glass)) - g_amount += amount * 3750 + g_amount += amount * MINERAL_MATERIAL_AMOUNT else if(istype(stack, /obj/item/stack/sheet/mineral/gold)) - gold_amount += amount * 2000 + gold_amount += amount * MINERAL_MATERIAL_AMOUNT else if(istype(stack, /obj/item/stack/sheet/mineral/diamond)) - diamond_amount += amount * 2000 + diamond_amount += amount * MINERAL_MATERIAL_AMOUNT stack.use(amount) busy = 0 src.updateUsrDialog() diff --git a/config/game_options.txt b/config/game_options.txt index b9ca7e763ca..d250d80c56d 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -114,6 +114,10 @@ SHUTTLE_REFUEL_DELAY 12000 TRAITOR_SCALING_COEFF 6 CHANGELING_SCALING_COEFF 7 +# The number of objectives traitors get. +# Not including escaping/hijacking. +TRAITOR_OBJECTIVES_AMOUNT 2 + ## Uncomment to prohibit jobs that start with loyalty ## implants from being most antagonists. #PROTECT_ROLES_FROM_ANTAGONIST @@ -187,5 +191,9 @@ SEC_START_BRIG ## Set to 2 for "random", silicons will start with a random lawset picked from (at the time of writing): P.A.L.A.D.I.N., Corporate, Asimov. More can be added by changing the law datum paths in ai_laws.dm. DEFAULT_LAWS 1 -## Uncoment to give players the choice of their mutantrace before they join the game -#JOIN_WITH_MUTANT_RACE \ No newline at end of file +## Uncoment to give players the choice of their species before they join the game +#JOIN_WITH_MUTANT_RACE + +## Uncomment to allow certain species to have custom colors + +#MUTANT_COLORS diff --git a/html/changelog.html b/html/changelog.html index 245a2c28a3c..7fb97f47b88 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,14 @@ should be listed in the changelog upon commit tho. Thanks. --> +
+

20 June 2014

+

Ikarrus updated:

+
    +
  • The 'Enter Exosuit' button was removed, and you have to click + drag yourself to enter a mech now; like you would to enter a disposal unit.
  • +
+
+

12 June 2014

diff --git a/icons/mob/human.dmi b/icons/mob/human.dmi index efbb59c0fd7..8b586b4fab9 100644 Binary files a/icons/mob/human.dmi and b/icons/mob/human.dmi differ diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index 9e2059cafbe..7b9629e0de8 100644 Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ diff --git a/icons/obj/cigarettes.dmi b/icons/obj/cigarettes.dmi index d254c6c843d..2ce3ce877fa 100644 Binary files a/icons/obj/cigarettes.dmi and b/icons/obj/cigarettes.dmi differ diff --git a/sound/machines/airlockforced.ogg b/sound/machines/airlockforced.ogg new file mode 100644 index 00000000000..8f46a89fe32 Binary files /dev/null and b/sound/machines/airlockforced.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 86fb4497c89..c01bdc15e3a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -963,6 +963,8 @@ #include "code\modules\mob\living\carbon\human\life.dm" #include "code\modules\mob\living\carbon\human\login.dm" #include "code\modules\mob\living\carbon\human\say.dm" +#include "code\modules\mob\living\carbon\human\species.dm" +#include "code\modules\mob\living\carbon\human\species_types.dm" #include "code\modules\mob\living\carbon\human\update_icons.dm" #include "code\modules\mob\living\carbon\human\whisper.dm" #include "code\modules\mob\living\carbon\metroid\death.dm"