diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 6ae5692a..4080c325 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -157,6 +157,8 @@ var/list/contact_levels = list(1, 5) // Defines which Z-levels which, for example, a Code Red announcement may affect var/list/player_levels = list(1, 3, 4, 5, 6) // Defines all Z-levels a character can typically reach + var/list/age_restrictions = list() // Holds all of the age restrictions for jobs and antag roles in a single associated list + /datum/configuration/New() var/list/L = typesof(/datum/game_mode) - /datum/game_mode for (var/T in L) @@ -576,6 +578,11 @@ else log_misc("Unknown setting in configuration: '[name]'") + else if (type == "age_restrictions") + name = replacetext(name, "_", " ") + age_restrictions += name + age_restrictions[name] = text2num(value) + /datum/configuration/proc/loadsql(filename) // -- TLE var/list/Lines = file2list(filename) for(var/t in Lines) diff --git a/code/datums/spells/horsemask.dm b/code/datums/spells/horsemask.dm index 1319f620..066a6317 100644 --- a/code/datums/spells/horsemask.dm +++ b/code/datums/spells/horsemask.dm @@ -35,6 +35,51 @@ flick("e_flash", target.flash) +//A spell for reversing the curse. +/obj/effect/proc_holder/spell/targeted/remove_horsemask + name = "Free the Horseman" + desc = "This spell lifts the Curse of the Horseman from the target. This spell does not require robes." + school = "transmutation" + charge_type = "recharge" + charge_max = 150 + charge_counter = 0 + clothes_req = 0 + stat_allowed = 0 + invocation = "KN'A EUTH, PUCK 'BTHIK!" + invocation_type = "shout" + range = 7 + selection_type = "range" + var/list/compatible_mobs = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + +/obj/effect/proc_holder/spell/targeted/remove_horsemask/cast(list/targets, mob/user = usr) + if (!targets.len) + user << "No target found in range." + return + + var/mob/living/carbon/target = targets[1] + + if (!(target.type in compatible_mobs)) + user << "It'd be stupid to curse [target] with a horse's head!" + return + + if (!(target in oview(range)))//If they are not in overview after selection. + user << "They are too far away!" + return + + if (istype(target.wear_mask, /obj/item/clothing/mask/horsehead/magic)) + var/obj/item/clothing/mask/horsehead/magic/to_be_removed = target.wear_mask + target.visible_message( "The [to_be_removed] on [target]'s face lights up and burns away, revealing \his face.", \ + "Your face burns up once more, but you suddenly realize that you are no longer wearing a silly horsemask!") + target.u_equip(to_be_removed) + + if (prob(40)) + del(to_be_removed) + else + user << "They aren't cursed, as such, there is nothing to reverse!" + return + + flick("e_flash", target.flash) + //item used by the horsehead spell /obj/item/clothing/mask/horsehead/magic //flags_inv = null //so you can still see their face... no. How can you recognize someone when their face is completely different? @@ -43,7 +88,7 @@ dropped(mob/user as mob) canremove = 1 ..() - + equipped(var/mob/user, var/slot) if (slot == slot_wear_mask) canremove = 0 //curses! diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index ef201cd0..9a12fed6 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -139,7 +139,7 @@ /area/proc/firealert() - if(name == "Space") //no fire alarms in space + if(name == "\improper Space") //no fire alarms in space return if( !fire ) fire = 1 @@ -370,4 +370,4 @@ else if(T && gravity_field_generators["[T.z]"] && length(gravity_field_generators["[T.z]"])) return 1 - return 0 \ No newline at end of file + return 0 diff --git a/code/game/gamemodes/events/power_failure.dm b/code/game/gamemodes/events/power_failure.dm index 3f0ae3c0..a388ce4c 100644 --- a/code/game/gamemodes/events/power_failure.dm +++ b/code/game/gamemodes/events/power_failure.dm @@ -69,7 +69,7 @@ S.updateicon() S.power_change() for(var/area/A in world) - if(A.name != "Space" && A.name != "Engine Walls" && A.name != "Chemical Lab Test Chamber" && A.name != "space" && A.name != "Escape Shuttle" && A.name != "Arrival Area" && A.name != "Arrival Shuttle" && A.name != "start area" && A.name != "Engine Combustion Chamber") + if(A.name != "\improper Space" && A.name != "Engine Walls" && A.name != "Chemical Lab Test Chamber" && A.name != "space" && A.name != "Escape Shuttle" && A.name != "Arrival Area" && A.name != "Arrival Shuttle" && A.name != "start area" && A.name != "Engine Combustion Chamber") A.power_light = 1 A.power_equip = 1 A.power_environ = 1 diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index f4d98d1d..60fb8187 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -38,6 +38,20 @@ dat += "Ethereal Jaunt (60)
" dat += "Knock (10)
" dat += "Curse of the Horseman (15)
" + dat += "A reversal spell offered for free, upon purchase.
" + + var/need_remove_horse = 0 + for (var/obj/effect/proc_holder/spell/targeted/horsemask/Add in user.spell_list) + if (need_remove_horse == 1) + break + need_remove_horse++ + for (var/obj/effect/proc_holder/spell/targeted/remove_horsemask/Remove in user.spell_list) + if (need_remove_horse == 2) + break + need_remove_horse++ + if (need_remove_horse == 1) + dat += "Free the Horseman (15)
" + // if(op) // dat += "Summon Guns (One time use, global spell)
" dat += "
" @@ -153,7 +167,15 @@ if("horseman") feedback_add_details("wizard_spell_learned","HH") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells H.spell_list += new /obj/effect/proc_holder/spell/targeted/horsemask(H) + if (alert("Do you want a spell that can lift this curse, too? (Does not cost a spellpoint.)",,"Yes","No") == "Yes") + feedback_add_details("wizard_spell_learned","RH") + H.spell_list += new /obj/effect/proc_holder/spell/targeted/remove_horsemask(H) temp = "This spell will curse a person to wear an unremovable horse mask (it has glue on the inside) and speak like a horse. It does not require a wizard garb. Do note the curse will disintegrate the target's current mask if they are wearing one." + if ("remove_horseman") + feedback_add_details("wizard_spell_learned","RH") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells + H.spell_list += new /obj/effect/proc_holder/spell/targeted/remove_horsemask(H) + temp = "This spell lifts the Curse of the Horseman from the target. This spell does not require robes." + uses++ //since it's a really trivial spell, purchasing it won't deduct points if("summonguns") feedback_add_details("wizard_spell_learned","SG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells H.rightandwrong() diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index b0de91e9..7ed5b7d0 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -70,4 +70,8 @@ if(!isnum(minimal_player_age)) return 0 - return max(0, minimal_player_age - C.player_age) \ No newline at end of file + return max(0, minimal_player_age - C.player_age) + +/datum/job/proc/fetch_age_restriction() + if (config.age_restrictions[lowertext(title)]) + minimal_player_age = config.age_restrictions[lowertext(title)] diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index f4acb6bd..c7da1724 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -24,6 +24,8 @@ var/global/datum/controller/occupations/job_master if(!job) continue if(job.faction != faction) continue occupations += job + if (config && config.use_age_restriction_for_jobs) + job.fetch_age_restriction() return 1 diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index b5e92042..0e10c5dc 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -1224,7 +1224,7 @@ Code shamelessly copied from apc_frame if (!istype(loc, /turf/simulated/floor)) usr << "\red Air Alarm cannot be placed on this spot." return - if (A.requires_power == 0 || A.name == "Space") + if (A.requires_power == 0 || A.name == "\improper Space") usr << "\red Air Alarm cannot be placed in this area." return @@ -1547,7 +1547,7 @@ Code shamelessly copied from apc_frame if (!istype(loc, /turf/simulated/floor)) usr << "\red Fire Alarm cannot be placed on this spot." return - if (A.requires_power == 0 || A.name == "Space") + if (A.requires_power == 0 || A.name == "\improper Space") usr << "\red Fire Alarm cannot be placed in this area." return diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index a1199642..bb3641de 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -52,7 +52,9 @@ /obj/item/robot_parts/robot_component/diagnosis_unit, /obj/item/robot_parts/robot_component/camera, /obj/item/robot_parts/robot_component/law_computer, - /obj/item/robot_parts/robot_component/armour + /obj/item/robot_parts/robot_component/armour, + /obj/item/robot_parts/robot_component/radiator, + /obj/item/robot_parts/robot_component/bladder ), "Ripley"=list( /obj/item/mecha_parts/chassis/ripley, @@ -127,7 +129,9 @@ /obj/item/borg/upgrade/tasercooler, /obj/item/borg/upgrade/jetpack), - "Synthetic Coverings" = list( /obj/item/weapon/synth_skin_spray, + "Synthetic Shell Components" = list( + /obj/item/organ/eyes/robot, + /obj/item/weapon/synth_skin_spray, /obj/item/weapon/synth_skin_cartridge/paint, /obj/item/weapon/synth_skin_cartridge/skin, /obj/item/weapon/synth_skin_cartridge/fur, @@ -887,4 +891,4 @@ target.apply_damage(10, HALLOSS) target.say("*scream") spawn(10) - user.visible_message("\red [user] stops the [src] and leaves [target] resting as they are.", "\red You turn the [src] off and let go of [target].") \ No newline at end of file + user.visible_message("\red [user] stops the [src] and leaves [target] resting as they are.", "\red You turn the [src] off and let go of [target].") diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm index ff1a1fb1..7919762a 100644 --- a/code/game/objects/items/blueprints.dm +++ b/code/game/objects/items/blueprints.dm @@ -80,7 +80,7 @@ move an amendment to the drawing.

return A /obj/item/blueprints/proc/get_area_type(var/area/A = get_area()) - if (A.name == "Space") + if (A.name == "\improper Space") return AREA_SPACE var/list/SPECIALS = list( /area/shuttle, @@ -247,4 +247,4 @@ move an amendment to the drawing.

if(BORDER_SPACE) return ROOM_ERR_SPACE found+=T - return found \ No newline at end of file + return found diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 8af5727d..ef95abdb 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -916,6 +916,21 @@ var/global/list/obj/item/device/pda/PDAs = list() message = "\red" + message M.show_message(message, 1) +/obj/item/device/pda/verb/verb_reset_pda() + set category = "Object" + set name = "Reset PDA" + set src in usr + + if(issilicon(usr)) + return + + if(can_use(usr)) + mode = 0 + nanomanager.update_uis(src) + usr << "You press the reset button on \the [src]." + else + usr << "You cannot do this while restrained." + /obj/item/device/pda/proc/remove_id() if (id) if (ismob(loc)) diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index df251ef6..0c5f8e90 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -26,6 +26,10 @@ var/jobban_keylist[0] //to store the keys & ranks if(config.usewhitelist && !check_whitelist(M)) return "Whitelisted Job" + if (config.use_age_restriction_for_jobs) + if (config.age_restrictions[rank] && M.client.player_age < config.age_restrictions[rank]) + return "Age Restricted" + for (var/s in jobban_keylist) if( findtext(s,"[M.ckey] - [rank]") == 1 ) var/startpos = findtext(s, "## ")+3 diff --git a/code/modules/admin/player_notes_sql.dm b/code/modules/admin/player_notes_sql.dm index b80d2b83..0eac3ee8 100644 --- a/code/modules/admin/player_notes_sql.dm +++ b/code/modules/admin/player_notes_sql.dm @@ -8,6 +8,8 @@ var/ckey = sanitizeSQL(key) var/content = sanitizeSQL(note) + note = sql_sanitize_text(note) + var/a_ckey if(usr) a_ckey = sanitizeSQL(usr.key) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index dfb14c9e..d985f847 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1366,6 +1366,7 @@ var/special_role_description = "" var/health_description = "" var/gender_description = "" + var/species_description = "" var/turf/T = get_turf(M) //Location @@ -1399,8 +1400,18 @@ if(MALE,FEMALE) gender_description = "[M.gender]" else gender_description = "[M.gender]" + //Species + if(ishuman(M)) + var/mob/living/carbon/human/K = M + if(K.species) + species_description = "[K.species.name]" + else + species_description = "Unknown" + else + species_description = "N/A" + src.owner << "Info about [M.name]: " - src.owner << "Mob type = [M.type]; Gender = [gender_description] Damage = [health_description]" + src.owner << "Mob type = [M.type]; Species = [species_description]; Gender = [gender_description]; Damage = [health_description]" src.owner << "Name = [M.name]; Real_name = [M.real_name]; Mind_name = [M.mind?"[M.mind.name]":""]; Key = [M.key];" src.owner << "Location = [location_description];" src.owner << "[special_role_description]" diff --git a/code/modules/admin/verbs/warning.dm b/code/modules/admin/verbs/warning.dm index a9288213..d222bb5e 100644 --- a/code/modules/admin/verbs/warning.dm +++ b/code/modules/admin/verbs/warning.dm @@ -88,8 +88,12 @@ if(!reason) return + reason = sql_sanitize_text(reason) + var/notes = input("Add Additional Information. This is visible to staff only.") as null|text + notes = sql_sanitize_text(notes) + var/severity switch(alert("Set Warning Severity",,"Standard","Severe")) if("Standard") diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 2f7ec095..cea406ad 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -429,13 +429,18 @@ datum/preferences src.be_special = 0 else var/n = 0 + var/banned = null for (var/i in special_roles) if(special_roles[i]) //if mode is available on the server - if(jobban_isbanned(user, i)) - dat += "Be [i]: \[BANNED]
" - else if(i == "pai candidate") - if(jobban_isbanned(user, "pAI")) - dat += "Be [i]: \[BANNED]
" + banned = jobban_isbanned(user, i) + if (i == "pai candidate") + banned = jobban_isbanned(user, "pAI") + + if (banned == "Age Restricted") + var/time = config.age_restrictions[i] - user.client.player_age + dat += "Be [i]: \[IN [time] DAYS]
" + else if (banned) + dat += "Be [i]: \[BANNED]
" else dat += "Be [i]: [src.be_special&(1<
" n++ @@ -1680,4 +1685,4 @@ var/list/limb_connection_data /datum/preferences/proc/make_sure_we_have_a_brain_type_for_machines() if (species=="Machine") if(!machine_brain_type) - machine_brain_type="Posibrain" \ No newline at end of file + machine_brain_type="Posibrain" diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index 8044f6a0..79f2863b 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -25,7 +25,8 @@ "/obj/item/weapon/airlock_electronics", "/obj/item/weapon/module/power_control", "/obj/item/weapon/cell", - "/obj/item/weapon/hand_tele") + "/obj/item/weapon/hand_tele", + "/obj/item/weapon/soap/fluff/jace_toothbrush") storage_slots = 14 max_combined_w_class = 42 max_w_class = 3 @@ -1323,4 +1324,38 @@ END R I P HAZERI slot_flags = SLOT_MASK /obj/item/clothing/tie/fluff/fortune_shieldpendant/New() - inv_overlay = image("icon" = 'icons/obj/custom_items/fortune_shieldpendant.dmi', "icon_state" = "fortune_shieldpendant_w") \ No newline at end of file + inv_overlay = image("icon" = 'icons/obj/custom_items/fortune_shieldpendant.dmi', "icon_state" = "fortune_shieldpendant_w") + + +// Jace Evan's toothbrush - Wittly +/obj/item/weapon/soap/fluff/jace_toothbrush + name = "toothbrush" + desc = "An old toothbrush. It looks well used." + icon = 'icons/obj/custom_items/jace_toothbrush.dmi' + icon_state = "jace_toothbrush" + var/cleanspeed = 20 + +/obj/item/weapon/soap/fluff/jace_toothbrush/Crossed(AM as mob|obj) + return + +/obj/item/weapon/soap/fluff/jace_toothbrush/afterattack(atom/target, mob/user as mob, proximity) + if(!proximity) return + + if(user.client && (target in user.client.screen)) + return + if (istype(target,/obj/effect/decal/cleanable)) + user.visible_message("[user] begins to scrub \the [target.name] out with [src].") + if(do_after(user, src.cleanspeed) && target) + user << "You scrub \the [target.name] out." + del(target) + else + user.visible_message("[user] begins to clean \the [target.name] with [src].") + if(do_after(user, src.cleanspeed)) + user << "You clean \the [target.name]." + var/obj/effect/decal/cleanable/C = locate() in target + del(C) + target.clean_blood() + return + +/obj/item/weapon/soap/fluff/jace_toothbrush/attack(mob/target as mob, mob/user as mob) + return \ No newline at end of file diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index 618dba58..82e0175c 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -116,9 +116,6 @@ /obj/item/seeds/cornseed seed_type = "corn" -/obj/item/seeds/poppyseed - seed_type = "poppies" - /obj/item/seeds/potatoseed seed_type = "potato" diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 1a0399fa..5e14402c 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -801,7 +801,19 @@ proc/stabilize_body_temperature() if (species.flags & IS_SYNTHETIC) - bodytemperature += species.synth_temp_gain //just keep putting out heat. + var/temperatureModifier = 0 + if(species.has_organ["radiator"]) + if(internal_organs_by_name["radiator"]) + var/datum/organ/internal/Radiator = internal_organs_by_name["radiator"] + if(Radiator.is_broken()) + temperatureModifier = 25 + if(bodytemperature > 450 && prob(10)) + apply_damage(rand(1, 5), BURN) + else if(Radiator.is_bruised()) + temperatureModifier = 18 + else + temperatureModifier = 25 + bodytemperature += species.synth_temp_gain + temperatureModifier //just keep putting out heat. return var/body_temperature_difference = species.body_temperature - bodytemperature @@ -1432,15 +1444,29 @@ if(1) healths.icon_state = "health6" if(2) healths.icon_state = "health7" else - //switch(health - halloss) - switch(100 - ((species && species.flags & NO_PAIN & !IS_SYNTHETIC) ? 0 : traumatic_shock)) - 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" + var/numb = 0 + if (species.has_organ["diagnosis unit"]) + if (internal_organs_by_name["diagnosis unit"]) + var/datum/organ/internal/machine/Diagnosis_unit = internal_organs_by_name["diagnosis unit"] + if (Diagnosis_unit.is_broken()) + numb = 1 + else if (Diagnosis_unit.is_bruised() && prob(35)) + numb = 1 + else + numb = 1 + + if (numb) + healths.icon_state = "health_numb" + else + //switch(health - halloss) + switch(100 - ((species && species.flags & NO_PAIN & !IS_SYNTHETIC) ? 0 : traumatic_shock)) + 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) @@ -1483,7 +1509,20 @@ else bodytemp.icon_state = "temp-4" else var/temp_step - if (bodytemperature >= species.body_temperature) + var/numb = 0 + if (species.has_organ["diagnosis unit"]) + if(internal_organs_by_name["diagnosis unit"]) + var/datum/organ/internal/machine/Diagnosis_unit = internal_organs_by_name["diagnosis unit"] + if (Diagnosis_unit.is_broken()) + numb = 1 + else if (Diagnosis_unit.is_bruised() && prob(35)) + numb = 1 + else numb = 1 + + if (numb) + bodytemp.icon_state = "temp_numb" + + else if (bodytemperature >= species.body_temperature) temp_step = (species.heat_level_1 - species.body_temperature)/4 if (bodytemperature >= species.heat_level_1) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index ddfb8577..6fc004aa 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -201,17 +201,17 @@ // Grabs the window recieved when you click-drag someone onto you. /datum/species/proc/get_inventory_dialogue(var/mob/living/carbon/human/H) return - + //Used by xenos understanding larvae and dionaea understanding nymphs. /datum/species/proc/can_understand(var/mob/other) return - - + + /datum/species/proc/blend_preview_icon(var/icon/main_icon,var/datum/preferences/preferences,var/paint_colour) if(paint_colour) main_icon.Blend(paint_colour, ICON_ADD) - return + return if(flags & HAS_SKIN_COLOR) main_icon.Blend(rgb(preferences.r_skin, preferences.g_skin, preferences.b_skin), ICON_ADD) return @@ -220,8 +220,8 @@ main_icon.Blend(rgb(preferences.s_tone, preferences.s_tone, preferences.s_tone), ICON_ADD) else main_icon.Blend(rgb(-preferences.s_tone, -preferences.s_tone, -preferences.s_tone), ICON_SUBTRACT) - - + + /datum/species/proc/get_organ_preview_icon(var/name, var/robot, var/gendered, var/gender_string, var/datum/preferences/preferences, var/datum/synthetic_limb_cover/covering, var/paint_colour) var/icon_name = icobase if (robot) @@ -236,7 +236,7 @@ var/icon/result = new /icon(icon_name,state_name) blend_preview_icon(result,preferences,paint_colour) return result - + /datum/species/proc/get_is_preview_organ_robotic(var/name,var/datum/preferences/preferences) if (flags & IS_SYNTHETIC) @@ -245,7 +245,7 @@ var/list/organ_robotic_info=preferences.organ_data[name] if (istype(organ_robotic_info)) return TRUE - + /datum/species/proc/get_preview_organ_covering(var/name,var/datum/preferences/preferences) if (name in preferences.organ_data) var/list/organ_robotic_info=preferences.organ_data[name] @@ -254,8 +254,8 @@ if (preferences.species=="Machine") if (preferences.covering_type) return list(preferences.covering_type,rgb(preferences.r_skin,preferences.g_skin,preferences.b_skin)) - - + + /datum/species/proc/get_tail_preview_icon(var/list/preview_coverings,var/datum/preferences/preferences) var/tail_state=null if (!(isnull(preview_coverings["groin"]))) @@ -268,8 +268,8 @@ var/icon/result = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = tail_state) result.Blend(rgb(preferences.r_hair,preferences.g_hair,preferences.b_hair),ICON_ADD) return result - - + + /datum/species/proc/get_eyes_preview_icon(var/list/preview_coverings,var/datum/preferences/preferences) var/eye_state=null if (!(isnull(preview_coverings["head"]))) @@ -280,13 +280,13 @@ var/icon/result = new/icon('icons/mob/human_face.dmi',eye_state) result.Blend(rgb(preferences.r_eyes,preferences.g_eyes,preferences.b_eyes),ICON_ADD) return result - + /* This function takes a preferences object and generates a complete body and hair icon for that set of preferences. It's needlessly complicated and duplicates a lot of what's going on in update_icons. The two systems should be combined somehow, possibly by using a 'visual identity' object -that could be created from either a living human or a preferences object and then passing that to a single render function, but I'll leave that +that could be created from either a living human or a preferences object and then passing that to a single render function, but I'll leave that exercise for another day. -See code\modules\mob\new_player\preferences_setup.dm for where it's used. +See code\modules\mob\new_player\preferences_setup.dm for where it's used. - jack_fractal*/ /datum/species/proc/create_body_preview_icon(var/datum/preferences/preferences) var/gender_string = (preferences.gender==FEMALE) ? "f" : "m" @@ -578,7 +578,7 @@ See code\modules\mob\new_player\preferences_setup.dm for where it's used. rarity_value = 2 eyes = "blank_eyes" - brute_mod = 0.5 + brute_mod = 1 //Fuck yo brute mod. burn_mod = 1 warning_low_pressure = 50 @@ -602,6 +602,10 @@ See code\modules\mob\new_player\preferences_setup.dm for where it's used. has_organ = list( "heart" = /datum/organ/internal/heart, "brain" = /datum/organ/internal/brain/robot, + "eyes" = /datum/organ/internal/eyes/robot, + "radiator" = /datum/organ/internal/machine/radiator, + "chemical containment" = /datum/organ/internal/machine/bladder, + "diagnosis unit" = /datum/organ/internal/machine/diagnosis_unit, ) /datum/species/machine/create_organs(var/mob/living/carbon/human/H) ..() @@ -609,8 +613,8 @@ See code\modules\mob\new_player\preferences_setup.dm for where it's used. if (istype(brain_datum)) if (isnull(brain_datum.machine_brain_type)) brain_datum.machine_brain_type="Posibrain" - - + + /datum/species/bug name = "Vaurca" name_plural = "varucae" @@ -778,4 +782,4 @@ See code\modules\mob\new_player\preferences_setup.dm for where it's used. if(slot_back in equip_slots) equip_slots |= slot_in_backpack - equip_slots |= slot_legcuffed \ No newline at end of file + equip_slots |= slot_legcuffed diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm deleted file mode 100644 index b5043fd2..00000000 --- a/code/modules/mob/living/carbon/species.dm +++ /dev/null @@ -1,388 +0,0 @@ -/* - Datum-based species. Should make for much cleaner and easier to maintain mutantrace code. -*/ - -/datum/species - var/name // Species name. - - var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set. - var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set. - var/eyes = "eyes_s" // Icon for eyes. - - var/primitive // Lesser form, if any (ie. monkey for humans) - var/tail // Name of tail image in species effects icon file. - var/language // Default racial language, if any. - var/unarmed //For empty hand harm-intent attack - var/unarmed_type = /datum/unarmed_attack - var/secondary_langs = list() // The names of secondary languages that are available to this species. - var/mutantrace // Safeguard due to old code. - - var/breath_type = "oxygen" // Non-oxygen gas breathed, if any. - var/poison_type = "phoron" // Poisonous air. - var/exhale_type = "carbon_dioxide" // Exhaled gas type. - - var/cold_level_1 = 260 // Cold damage level 1 below this point. - var/cold_level_2 = 200 // Cold damage level 2 below this point. - var/cold_level_3 = 120 // Cold damage level 3 below this point. - - var/heat_level_1 = 360 // Heat damage level 1 above this point. - var/heat_level_2 = 400 // Heat damage level 2 above this point. - var/heat_level_3 = 1000 // Heat damage level 2 above this point. - - var/body_temperature = 310.15 //non-IS_SYNTHETIC species will try to stabilize at this temperature. (also affects temperature processing) - var/synth_temp_gain = 0 //IS_SYNTHETIC species will gain this much temperature every second - var/reagent_tag //Used for metabolizing reagents. - - var/darksight = 2 - var/hazard_high_pressure = HAZARD_HIGH_PRESSURE // Dangerously high pressure. - var/warning_high_pressure = WARNING_HIGH_PRESSURE // High pressure warning. - var/warning_low_pressure = WARNING_LOW_PRESSURE // Low pressure warning. - var/hazard_low_pressure = HAZARD_LOW_PRESSURE // Dangerously low pressure. - - var/brute_mod = null // Physical damage reduction/malus. - var/burn_mod = null // Burn damage reduction/malus. - - var/flags = 0 // Various specific features. - - var/list/abilities = list() // For species-derived or admin-given powers - - var/blood_color = "#A10808" //Red. - var/flesh_color = "#FFC896" //Pink. - var/base_color //Used when setting species. - - //Used in icon caching. - var/race_key = 0 - var/icon/icon_template - -/datum/species/New() - unarmed = new unarmed_type() - -/datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs. - //This is a basic humanoid limb setup. - H.organs = list() - H.organs_by_name["chest"] = new/datum/organ/external/chest() - H.organs_by_name["groin"] = new/datum/organ/external/groin(H.organs_by_name["chest"]) - H.organs_by_name["head"] = new/datum/organ/external/head(H.organs_by_name["chest"]) - H.organs_by_name["l_arm"] = new/datum/organ/external/l_arm(H.organs_by_name["chest"]) - H.organs_by_name["r_arm"] = new/datum/organ/external/r_arm(H.organs_by_name["chest"]) - H.organs_by_name["r_leg"] = new/datum/organ/external/r_leg(H.organs_by_name["groin"]) - H.organs_by_name["l_leg"] = new/datum/organ/external/l_leg(H.organs_by_name["groin"]) - H.organs_by_name["l_hand"] = new/datum/organ/external/l_hand(H.organs_by_name["l_arm"]) - H.organs_by_name["r_hand"] = new/datum/organ/external/r_hand(H.organs_by_name["r_arm"]) - H.organs_by_name["l_foot"] = new/datum/organ/external/l_foot(H.organs_by_name["l_leg"]) - H.organs_by_name["r_foot"] = new/datum/organ/external/r_foot(H.organs_by_name["r_leg"]) - - H.internal_organs = list() - H.internal_organs_by_name["heart"] = new/datum/organ/internal/heart(H) - H.internal_organs_by_name["lungs"] = new/datum/organ/internal/lungs(H) - H.internal_organs_by_name["liver"] = new/datum/organ/internal/liver(H) - H.internal_organs_by_name["kidney"] = new/datum/organ/internal/kidney(H) - H.internal_organs_by_name["brain"] = new/datum/organ/internal/brain(H) - H.internal_organs_by_name["eyes"] = new/datum/organ/internal/eyes(H) - - for(var/name in H.organs_by_name) - H.organs += H.organs_by_name[name] - - for(var/datum/organ/external/O in H.organs) - O.owner = H - - if(flags & IS_SYNTHETIC) - for(var/datum/organ/external/E in H.organs) - if(E.status & ORGAN_CUT_AWAY || E.status & ORGAN_DESTROYED) continue - E.status |= ORGAN_ROBOT - for(var/datum/organ/internal/I in H.internal_organs) - I.mechanize() - -/datum/species/proc/handle_post_spawn(var/mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment. - return - -/datum/species/proc/handle_death(var/mob/living/carbon/human/H) //Handles any species-specific death events (such as dionaea nymph spawns). - if(flags & IS_SYNTHETIC) - //H.make_jittery(200) //S-s-s-s-sytem f-f-ai-i-i-i-i-lure-ure-ure-ure - H.h_style = "" - spawn(100) - //H.is_jittery = 0 - //H.jitteriness = 0 - H.update_hair() - return - - -/datum/species/proc/get_eye_icon() - return eyes - - -/datum/species/human - name = "Human" - language = "Sol Common" - primitive = /mob/living/carbon/monkey - unarmed_type = /datum/unarmed_attack/punch - - flags = HAS_SKIN_TONE | HAS_LIPS | HAS_UNDERWEAR - - //If you wanted to add a species-level ability: - /*abilities = list(/client/proc/test_ability)*/ - -/datum/species/unathi - name = "Unathi" - icobase = 'icons/mob/human_races/r_lizard.dmi' - deform = 'icons/mob/human_races/r_def_lizard.dmi' - language = "Sinta'unathi" - tail = "sogtail" - unarmed_type = /datum/unarmed_attack/claws - primitive = /mob/living/carbon/monkey/unathi - darksight = 3 - - cold_level_1 = 280 //Default 260 - Lower is better - cold_level_2 = 220 //Default 200 - cold_level_3 = 130 //Default 120 - - heat_level_1 = 420 //Default 360 - Higher is better - heat_level_2 = 480 //Default 400 - heat_level_3 = 1100 //Default 1000 - - flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SKIN_COLOR - - flesh_color = "#34AF10" - - reagent_tag = IS_UNATHI - base_color = "#066000" - -/datum/species/tajaran - name = "Tajaran" - icobase = 'icons/mob/human_races/r_tajaran.dmi' - deform = 'icons/mob/human_races/r_def_tajaran.dmi' - language = "Siik'Maas" - tail = "tajtail" - unarmed_type = /datum/unarmed_attack/claws - darksight = 8 - - cold_level_1 = 200 //Default 260 - cold_level_2 = 140 //Default 200 - cold_level_3 = 80 //Default 120 - - heat_level_1 = 330 //Default 360 - heat_level_2 = 380 //Default 400 - heat_level_3 = 800 //Default 1000 - - primitive = /mob/living/carbon/monkey/tajara - - flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SKIN_COLOR - - flesh_color = "#AFA59E" - base_color = "#333333" - -/datum/species/skrell - name = "Skrell" - icobase = 'icons/mob/human_races/r_skrell.dmi' - deform = 'icons/mob/human_races/r_def_skrell.dmi' - language = "Skrellian" - primitive = /mob/living/carbon/monkey/skrell - unarmed_type = /datum/unarmed_attack/punch - - flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR - - flesh_color = "#8CD7A3" - - reagent_tag = IS_SKRELL - -/datum/species/vox - name = "Vox" - icobase = 'icons/mob/human_races/r_vox.dmi' - deform = 'icons/mob/human_races/r_def_vox.dmi' - language = "Vox-pidgin" - unarmed_type = /datum/unarmed_attack/claws //I dont think it will hurt to give vox claws too. - - warning_low_pressure = 50 - hazard_low_pressure = 0 - - cold_level_1 = 80 - cold_level_2 = 50 - cold_level_3 = 0 - - eyes = "vox_eyes_s" - - breath_type = "nitrogen" - poison_type = "oxygen" - - flags = NO_SCAN - - blood_color = "#2299FC" - flesh_color = "#808D11" - - reagent_tag = IS_VOX - -/datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H) - - H.verbs += /mob/living/carbon/human/proc/leap - ..() - -/datum/species/vox/armalis/handle_post_spawn(var/mob/living/carbon/human/H) - - H.verbs += /mob/living/carbon/human/proc/gut - H.verbs += /mob/living/carbon/human/proc/commune - ..() - -/datum/species/vox/armalis - name = "Vox Armalis" - icobase = 'icons/mob/human_races/r_armalis.dmi' - deform = 'icons/mob/human_races/r_armalis.dmi' - language = "Vox-pidgin" - unarmed_type = /datum/unarmed_attack/claws/armalis - - warning_low_pressure = 50 - hazard_low_pressure = 0 - - cold_level_1 = 80 - cold_level_2 = 50 - cold_level_3 = 0 - - heat_level_1 = 2000 - heat_level_2 = 3000 - heat_level_3 = 4000 - - brute_mod = 0.2 - burn_mod = 0.2 - - eyes = "blank_eyes" - breath_type = "nitrogen" - poison_type = "oxygen" - - flags = NO_SCAN | NO_BLOOD | HAS_TAIL | NO_PAIN | IS_WHITELISTED - - blood_color = "#2299FC" - flesh_color = "#808D11" - - tail = "armalis_tail" - icon_template = 'icons/mob/human_races/r_armalis.dmi' - - reagent_tag = IS_VOX - -/datum/species/diona - name = "Diona" - icobase = 'icons/mob/human_races/r_diona.dmi' - deform = 'icons/mob/human_races/r_def_plant.dmi' - language = "Rootspeak" - unarmed_type = /datum/unarmed_attack/diona - primitive = /mob/living/carbon/monkey/diona - - warning_low_pressure = 50 - hazard_low_pressure = -1 - - cold_level_1 = 50 - cold_level_2 = -1 - cold_level_3 = -1 - - heat_level_1 = 2000 - heat_level_2 = 3000 - heat_level_3 = 4000 - - body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not - - flags = IS_WHITELISTED | NO_BREATHE | REQUIRE_LIGHT | NO_SCAN | IS_PLANT | RAD_ABSORB | NO_BLOOD | IS_SLOW | NO_PAIN - - blood_color = "#004400" - flesh_color = "#907E4A" - - reagent_tag = IS_DIONA - -/datum/species/diona/handle_post_spawn(var/mob/living/carbon/human/H) - H.gender = NEUTER - - return ..() - -/datum/species/diona/handle_death(var/mob/living/carbon/human/H) - - var/mob/living/carbon/monkey/diona/S = new(get_turf(H)) - - if(H.mind) - H.mind.transfer_to(S) - - for(var/mob/living/carbon/monkey/diona/D in H.contents) - if(D.client) - D.loc = H.loc - else - del(D) - - H.visible_message("\red[H] splits apart with a wet slithering noise!") - -/datum/species/machine - name = "Machine" - icobase = 'icons/mob/human_races/r_machine.dmi' - deform = 'icons/mob/human_races/r_machine.dmi' - language = "Tradeband" - unarmed_type = /datum/unarmed_attack/punch - - eyes = "blank_eyes" - brute_mod = 0.5 - burn_mod = 1 - - warning_low_pressure = 50 - hazard_low_pressure = 0 - - cold_level_1 = 50 - cold_level_2 = -1 - cold_level_3 = -1 - - heat_level_1 = 500 //gives them about 25 seconds in space before taking damage - heat_level_2 = 1000 - heat_level_3 = 2000 - - synth_temp_gain = 10 //this should cause IPCs to stabilize at ~80 C in a 20 C environment. - - flags = IS_WHITELISTED | NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | IS_SYNTHETIC | NO_POISON - - blood_color = "#1F181F" - flesh_color = "#575757" - - var/brain_type = 'posibrain' // default is robots - - -//Species unarmed attacks - -/datum/unarmed_attack - var/attack_verb = list("attack") // Empty hand hurt intent verb. - var/damage = 0 // Extra empty hand attack damage. - var/attack_sound = "punch" - var/miss_sound = 'sound/weapons/punchmiss.ogg' - var/sharp = 0 - var/edge = 0 - -/datum/unarmed_attack/punch - attack_verb = list("punch") - -/datum/unarmed_attack/diona - attack_verb = list("lash", "bludgeon") - damage = 5 - -/datum/unarmed_attack/claws - attack_verb = list("scratch", "claw") - attack_sound = 'sound/weapons/slice.ogg' - miss_sound = 'sound/weapons/slashmiss.ogg' - damage = 5 - sharp = 1 - edge = 1 - -/datum/unarmed_attack/claws/armalis - attack_verb = list("slash", "claw") - damage = 10 //they're huge! they should do a little more damage, i'd even go for 15-20 maybe... - -/datum/species/kocasslani - name = "Kocasslani" - icobase = 'icons/mob/human_races/r_kocasslani.dmi' - deform = 'icons/mob/human_races/r_def_kocasslani.dmi' - language = "Sini" - darksight = 8 - - cold_level_1 = 160 //Default 260 - cold_level_2 = 100 //Default 200 - cold_level_3 = 60 //Default 120 - - heat_level_1 = 300 //Default 360 - heat_level_2 = 360 //Default 400 - heat_level_3 = 800 //Default 1000 - - flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR - -/* blood_color = "#659CEF" - flesh_color = "#D3AA8E" -*/ \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm index bb03edb4..8f836208 100644 --- a/code/modules/mob/living/silicon/robot/component.dm +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -147,6 +147,14 @@ var/brute = 0 var/burn = 0 var/icon_state_broken = "broken" + var/obj/item/organ/organ_type = null // for shells. Only define if this can be placed inside an IPC during organ replacement surgery. + +// In case the robot_component has a child organ, it is updated to have the proper datums and so on. +/obj/item/robot_parts/robot_component/New() + ..() + spawn(5) + if(organ_type) + organ_type.update() // TODO: actual icons ;) /obj/item/robot_parts/robot_component/binary_communication_device @@ -168,7 +176,8 @@ name = "camera" icon_state = "camera" icon_state_broken = "camera_broken" - + organ_type = new /obj/item/organ/eyes/robot() + /obj/item/robot_parts/robot_component/law_computer name = "law computer" icon_state = "radio" @@ -178,12 +187,25 @@ name = "diagnosis unit" icon_state = "analyser" icon_state_broken = "analyser_broken" + organ_type = new /obj/item/organ/machine/diagnosis_unit() /obj/item/robot_parts/robot_component/radio name = "radio" icon_state = "radio" icon_state_broken = "radio_broken" +/obj/item/robot_parts/robot_component/radiator + name = "radiator" + icon_state = "radiator" + icon_state_broken = "radiator_broken" + organ_type = new /obj/item/organ/machine/radiator() + +/obj/item/robot_parts/robot_component/bladder + name = "chemical containment" + icon_state = "bladder" + icon_state_broken = "bladder_broken" + organ_type = new /obj/item/organ/machine/bladder() + // //Robotic Component Analyser, basically a health analyser for robots // @@ -227,7 +249,7 @@ user.show_message("\t Damage Specifics: [BU] - [BR]") if(M.tod && M.stat == DEAD) user.show_message("\blue Time of Disable: [M.tod]") - + if (istype(M, /mob/living/silicon/robot)) var/mob/living/silicon/robot/H = M var/list/damaged = H.get_damaged_components(1,1,1) @@ -245,7 +267,7 @@ user.show_message("\blue \t Components are OK.",1) if(H.emagged && prob(5)) user.show_message("\red \t ERROR: INTERNAL SYSTEMS COMPROMISED",1) - + if (ishuman(M) && (M:species.flags & IS_SYNTHETIC)) var/mob/living/carbon/human/H = M var/list/damaged = H.get_damaged_organs(1,1) @@ -258,8 +280,8 @@ (org.burn_dam > 0) ? "[org.burn_dam]" :0),1) else user.show_message("\blue \t Components are OK.",1) - + user.show_message("\blue Operating Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1) - + src.add_fingerprint(user) return diff --git a/code/modules/organs/organ_alien.dm b/code/modules/organs/organ_alien.dm index 9d4bfa0b..c473d377 100644 --- a/code/modules/organs/organ_alien.dm +++ b/code/modules/organs/organ_alien.dm @@ -224,4 +224,117 @@ robotic = 2 /obj/item/organ/stack/vox - name = "vox cortical stack" \ No newline at end of file + name = "vox cortical stack" + +//IPC/SHELL ORGANS. +//TODO: Make the robot_components required for these +//TODO: Make said components printable +//TODO: sprites +/datum/organ/internal/machine + removed_type = /obj/item/organ/machine + +/datum/organ/internal/machine/process() + return + +/datum/organ/internal/machine/radiator + name = "internal cooling unit" + parent_organ = "chest" + robotic = 2 + min_bruised_damage = 15 + min_broken_damage = 40 + removed_type = /obj/item/organ/machine/radiator + +/obj/item/organ/machine/radiator + name = "internal cooling unit" + icon_state = "radiator" + organ_tag = "radiator" + organ_type = /datum/organ/internal/machine/radiator + robotic = 2 + +/obj/item/organ/machine/radiator/exposed_to_the_world() + var/obj/item/robot_parts/robot_component/radiator/Radiator = new(src.loc) + if(organ_data.damage) + Radiator.brute = organ_data.damage + del(src) + return Radiator + +/datum/organ/internal/machine/bladder + name = "chemical containment" + parent_organ = "groin" + robotic = 2 + removed_type = /obj/item/organ/machine/bladder + +/datum/organ/internal/machine/bladder/process() + if(status & ORGAN_CUT_AWAY) + return + + if(is_bruised()) + var/leakSmall = rand(1,5) + if(owner.reagents.total_volume > 0) + owner.reagents.remove_any(leakSmall) + if(owner.reagents.maximum_volume > 500) + owner.reagents.maximum_volume -= leakSmall + + if(is_broken()) + var/leakLarge = rand(25,50) + if(owner.reagents.total_volume > 0) + owner.reagents.remove_any(leakLarge) + if(owner.reagents.maximum_volume > 0) + if(owner.reagents.maximum_volume < leakLarge) + owner.reagents.maximum_volume = 0 + else + owner.reagents.maximum_volume -= leakLarge + + if(owner.reagents.reagent_list.len) + if(owner.reagents.has_reagent("sacid") || owner.reagents.has_reagent("pacid")) + take_damage(rand(0,2.5), 1) + +/obj/item/organ/machine/bladder + name = "chemical containment" + icon_state = "bladder" + organ_tag = "chemical containment" + organ_type = /datum/organ/internal/machine/bladder + robotic = 2 + +/obj/item/organ/machine/bladder/replaced(var/mob/living/carbon/human/target) + if(istype(target) && (target.species.flags & IS_SYNTHETIC)) + if(target.reagents.maximum_volume < 1000) + target.reagents.maximum_volume = 1000 + + ..() + +/obj/item/organ/machine/bladder/removed(var/mob/living/target, var/mob/living/user) + ..() + + if(istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/Machine = target + if(Machine.species.flags & IS_SYNTHETIC) + Machine.reagents.clear_reagents() + Machine.reagents.maximum_volume = 0 + +/obj/item/organ/machine/bladder/exposed_to_the_world() + var/obj/item/robot_parts/robot_component/bladder/Bladder = new(src.loc) + if(organ_data.damage) + Bladder.brute = organ_data.damage + del(src) + return Bladder + +/datum/organ/internal/machine/diagnosis_unit + name = "diagnosis unit" + parent_organ = "head" + robotic = 2 + removed_type = /obj/item/organ/machine/diagnosis_unit + +/obj/item/organ/machine/diagnosis_unit + name = "diagnosis unit" + icon_state = "diagnosis_unit" + organ_tag = "diagnosis unit" + organ_type = /datum/organ/internal/machine/diagnosis_unit + robotic = 2 + +/obj/item/organ/machine/diagnosis_unit/exposed_to_the_world() + var/obj/item/robot_parts/robot_component/diagnosis_unit/Diagnosis_unit = new(src.loc) + if(organ_data.damage) + Diagnosis_unit.brute = organ_data.damage + del(src) + return Diagnosis_unit diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm index 3ee262b7..53f28e83 100644 --- a/code/modules/organs/organ_internal.dm +++ b/code/modules/organs/organ_internal.dm @@ -249,12 +249,12 @@ parent_organ = "head" removed_type = /obj/item/organ/brain vital = 1 - - + + /datum/organ/internal/brain/robot // brains for shells - var/machine_brain_type=null - - + var/machine_brain_type=null + + /datum/organ/internal/brain/robot/proc/create_robot_brain_replacement(var/target,var/new_location) var/obj/item/device/mmi/new_mmi if (machine_brain_type=="Posibrain") @@ -267,7 +267,7 @@ new_mmi.transfer_identity(target) new_mmi.loc = new_location return new_mmi - + /datum/organ/internal/brain/xeno removed_type = /obj/item/organ/brain/xeno @@ -284,6 +284,11 @@ if(is_broken()) owner.eye_blind = 20 +/datum/organ/internal/eyes/robot // eyes for shells + name = "charge-coupled device" + parent_organ = "head" + removed_type = /obj/item/organ/eyes/robot + /datum/organ/internal/appendix name = "appendix" parent_organ = "groin" @@ -306,4 +311,4 @@ removed_organ.update() organ_holder = removed_organ - return removed_organ \ No newline at end of file + return removed_organ diff --git a/code/modules/organs/organ_objects.dm b/code/modules/organs/organ_objects.dm index c375cbb4..2340a34e 100644 --- a/code/modules/organs/organ_objects.dm +++ b/code/modules/organs/organ_objects.dm @@ -150,6 +150,19 @@ /obj/item/organ/eyes/prosthetic robotic = 2 +/obj/item/organ/eyes/robot + name = "charge-coupled device" + icon_state = "" + organ_type = /datum/organ/internal/eyes/robot + robotic = 2 + + exposed_to_the_world() + var/obj/item/robot_parts/robot_component/camera/Camera = new() + if(organ_data.damage) + Camera.brute = organ_data.damage + del(src) + return Camera + /obj/item/organ/liver/prosthetic robotic = 2 @@ -180,11 +193,11 @@ msg_admin_attack("[user.name] ([user.ckey]) removed a vital organ ([src]) from [target.name] ([target.ckey]) (INTENT: [uppertext(user.a_intent)]) (JMP)") target.death() - + /obj/item/organ/proc/exposed_to_the_world() // this is only useful for organs that change when actually removed from the body - return - - + return + + /obj/item/organ/appendix/removed(var/mob/living/target,var/mob/living/user) ..() @@ -277,4 +290,4 @@ if(fingerprintslast) O.fingerprintslast = fingerprintslast user.put_in_active_hand(O) - del(src) \ No newline at end of file + del(src) diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index 0cf7dfef..b9a234aa 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -17,10 +17,11 @@ return 0 if (affected.status & ORGAN_DESTROYED) return 0 - if (target_zone == "head" && target.species && (target.species.flags & IS_SYNTHETIC)) - return 1 if (affected.status & ORGAN_ROBOT) - return 0 + if (target.species && (target.species.flags & IS_SYNTHETIC) && affected.internal_organs.len) + return 1 + else + return 0 return 1 /datum/surgery_step/generic/cut_with_laser diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 3ea958bb..71189a51 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -320,7 +320,8 @@ /datum/surgery_step/internal/replace_organ allowed_tools = list( - /obj/item/organ = 100 + /obj/item/organ = 100, + /obj/item/robot_parts/robot_component = 100 ) min_duration = 60 @@ -334,7 +335,13 @@ var/organ_compatible var/organ_missing - if(!istype(O)) + if(!istype(O) && istype(O, /obj/item/robot_parts/robot_component)) + var/obj/item/robot_parts/robot_component/A = tool + if(A.organ_type) + O = A.organ_type + else + return 0 + else return 0 if(!target.species) @@ -383,6 +390,11 @@ var/obj/item/organ/O = tool if(istype(O)) O.replaced(target,affected) + else if(istype(tool, /obj/item/robot_parts/robot_component)) + var/obj/item/robot_parts/robot_component/A = tool + if(A.organ_type) + O = A.organ_type + O.replaced(target,affected) fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) user.visible_message("\red [user]'s hand slips, damaging \the [tool]!", \ @@ -455,4 +467,4 @@ // max_duration = 40 // can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) -// return ..() && target.op_stage.ribcage == 2 \ No newline at end of file +// return ..() && target.op_stage.ribcage == 2 diff --git a/code/world.dm b/code/world.dm index f5b526c3..790f6774 100644 --- a/code/world.dm +++ b/code/world.dm @@ -285,6 +285,8 @@ var/master_server_password // apply some settings from config.. abandon_allowed = config.respawn + if (config.use_age_restriction_for_jobs) + config.load("config/age_restrictions.txt","age_restrictions") /hook/startup/proc/loadMods() world.load_mods() diff --git a/config/example/age_restrictions.txt b/config/example/age_restrictions.txt new file mode 100644 index 00000000..a0d3d3cf --- /dev/null +++ b/config/example/age_restrictions.txt @@ -0,0 +1,71 @@ +#Try to keep up to date. +#Replace all spaces in the job titles with underscores, otherwise the config will not load properly + +#These are all the titles (var/title) of the different job datums +#Station jobs +#Command +Captain 0 +Head_of_Personnel 0 +Head_of_Security 0 +Chief_Engineer 0 +Research_Director 0 +Chief_Medical_Officer 0 + +#Engineering +Station_Engineer 0 +Atmospheric_Technician 0 +Engineering_Apprentice 0 + +#Medical +Medical_Doctor 0 +Psychiatrist 0 +Chemist 0 +Emergency_Medical_Tech 0 +Nursing_Intern 0 + +#Science +Scientist 0 +Geneticist 0 +Roboticist 0 +Xenobiologist 0 +Lab_Assistant 0 + +#Security +Warden 0 +Detective 0 +Forensic_Technician 0 +Security_Officer 0 +Security_Cadet 0 + +#Civilian +Bartender 0 +Botanist 0 +Chef 0 +Janitor 0 +Librarian 0 +Quartermaster 0 +Cargo_Technician 0 +Shaft_Miner 0 +Lawyer 0 +Chaplain 0 +Assistant 0 +Internal_Affairs_Agent 0 + +#Synth +AI 0 +Cyborg 0 +pAI 0 + +#This is fetched from the special_roles global list. +#Antags +traitor 0 +operative 0 +changeling 0 +wizard 0 +malf_AI 0 +revolutionary 0 +cultist 0 +ninja 0 +vox_raider 0 +vampire 0 +mutineer 0 diff --git a/icons/obj/custom_items/jace_toothbrush.dmi b/icons/obj/custom_items/jace_toothbrush.dmi new file mode 100644 index 00000000..63359516 Binary files /dev/null and b/icons/obj/custom_items/jace_toothbrush.dmi differ diff --git a/icons/obj/robot_component.dmi b/icons/obj/robot_component.dmi index 1129f25a..bb53a0ab 100644 Binary files a/icons/obj/robot_component.dmi and b/icons/obj/robot_component.dmi differ diff --git a/icons/obj/seeds.dmi b/icons/obj/seeds.dmi index 9f61275f..069f770c 100644 Binary files a/icons/obj/seeds.dmi and b/icons/obj/seeds.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 202ec39b..694752e1 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ