diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index 632e4adef9..f5ea8d835f 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -4,9 +4,9 @@ #define WEIGHT_CLASS_TINY 1 //Usually items smaller then a human hand, ex: Playing Cards, Lighter, Scalpel, Coins/Money #define WEIGHT_CLASS_SMALL 2 //Pockets can hold small and tiny items, ex: Flashlight, Multitool, Grenades, GPS Device #define WEIGHT_CLASS_NORMAL 3 //Standard backpacks can carry tiny, small & normal items, ex: Fire extinguisher, Stunbaton, Gas Mask, Metal Sheets -#define WEIGHT_CLASS_BULKY 4 //Items that can be weilded or equipped but not stored in an inventory, ex: Defibrillator, Backpack, Space Suits -#define WEIGHT_CLASS_HUGE 5 //Usually represents objects that require two hands to operate, ex: Shotgun, Two Handed Melee Weapons -#define WEIGHT_CLASS_GIGANTIC 6 //Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe +#define WEIGHT_CLASS_BULKY 4 //Items that can be weilded or equipped but not stored in a normal bag, ex: Defibrillator, Backpack, Space Suits +#define WEIGHT_CLASS_HUGE 5 //Usually represents objects that require two hands to operate, ex: Shotgun, Two Handed Melee Weapons - Can not fit in Boh +#define WEIGHT_CLASS_GIGANTIC 6 //Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe - Can not fit in Boh //Inventory depth: limits how many nested storage items you can access directly. //1: stuff in mob, 2: stuff in backpack, 3: stuff in box in backpack, etc diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm index 1b7cade71f..c3db8552c6 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence.dm @@ -12,6 +12,7 @@ SUBSYSTEM_DEF(persistence) var/list/obj/structure/chisel_message/chisel_messages = list() var/list/saved_messages = list() var/list/saved_modes = list(1,2,3) + var/list/saved_threat_levels = list(1,1,1) var/list/saved_maps var/list/saved_trophies = list() var/list/spawned_objects = list() @@ -27,6 +28,7 @@ SUBSYSTEM_DEF(persistence) LoadChiselMessages() LoadTrophies() LoadRecentModes() + LoadRecentThreats() LoadRecentMaps() LoadPhotoPersistence() if(CONFIG_GET(flag/use_antag_rep)) @@ -166,6 +168,15 @@ SUBSYSTEM_DEF(persistence) return saved_modes = json["data"] +/datum/controller/subsystem/persistence/proc/LoadRecentThreats() + var/json_file = file("data/RecentThreatLevels.json") + if(!fexists(json_file)) + return + var/list/json = json_decode(file2text(json_file)) + if(!json) + return + saved_threat_levels = json["data"] + /datum/controller/subsystem/persistence/proc/LoadRecentMaps() var/json_file = file("data/RecentMaps.json") if(!fexists(json_file)) @@ -216,6 +227,7 @@ SUBSYSTEM_DEF(persistence) CollectSecretSatchels() CollectTrophies() CollectRoundtype() + CollectThreatLevel() RecordMaps() SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION. if(CONFIG_GET(flag/use_antag_rep)) @@ -372,6 +384,18 @@ SUBSYSTEM_DEF(persistence) fdel(json_file) WRITE_FILE(json_file, json_encode(file_data)) +/datum/controller/subsystem/persistence/proc/CollectThreatLevel() + if(istype(SSticker.mode, /datum/game_mode/dynamic)) + var/datum/game_mode/dynamic/mode = SSticker.mode + saved_threat_levels[3] = saved_threat_levels[2] + saved_threat_levels[2] = saved_threat_levels [1] + saved_threat_levels[1] = mode.threat_level + var/json_file = file("data/RecentThreatLevels.json") + var/list/file_data = list() + file_data["data"] = saved_threat_levels + fdel(json_file) + WRITE_FILE(json_file, json_encode(file_data)) + /datum/controller/subsystem/persistence/proc/RecordMaps() saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]") var/json_file = file("data/RecentMaps.json") diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 50be61f91d..dee10e4998 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -153,6 +153,10 @@ SUBSYSTEM_DEF(vote) if(SSticker.current_state > GAME_STATE_PREGAME)//Don't change the mode if the round already started. return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.") GLOB.master_mode = "dynamic" + if("extended" in choices) + if(. == "extended") + GLOB.dynamic_forced_extended = TRUE // we still do the rest of the stuff + choices[PEACE] += choices["extended"] var/mean = 0 var/voters = 0 for(var/client/c in GLOB.clients) @@ -253,7 +257,11 @@ SUBSYSTEM_DEF(vote) if("roundtype") //CIT CHANGE - adds the roundstart secret/extended vote choices.Add("secret", "extended") if("dynamic") - choices.Add(PEACE,CHAOS) + var/saved_threats = SSpersistence.saved_threat_levels + if((saved_threats[1]+saved_threats[2]+saved_threats[3])>150) + choices.Add("extended",PEACE,CHAOS) + else + choices.Add(PEACE,CHAOS) if("custom") question = stripped_input(usr,"What is the vote for?") if(!question) diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 83a3debfdc..25edd0c68b 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -409,7 +409,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) message_admins("Drafting players for forced ruleset [rule.name].") log_game("DYNAMIC: Drafting players for forced ruleset [rule.name].") rule.mode = src - rule.acceptable(GLOB.player_list.len, threat_level) // Assigns some vars in the modes, running it here for consistency + rule.acceptable(roundstart_pop_ready, threat_level) // Assigns some vars in the modes, running it here for consistency rule.candidates = candidates.Copy() rule.trim_candidates() if (rule.ready(TRUE)) @@ -421,7 +421,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) return TRUE var/list/drafted_rules = list() for (var/datum/dynamic_ruleset/roundstart/rule in roundstart_rules) - if (rule.acceptable(GLOB.player_list.len, threat_level) && threat >= rule.cost) // If we got the population and threat required + if (rule.acceptable(roundstart_pop_ready, threat_level) && threat >= rule.cost) // If we got the population and threat required rule.candidates = candidates.Copy() rule.trim_candidates() if (rule.ready() && rule.candidates.len > 0) @@ -429,12 +429,12 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) if(!drafted_rules.len) message_admins("Not enough threat level for roundstart antags!") log_game("DYNAMIC: Not enough threat level for roundstart antags!") - var/indice_pop = min(10,round(GLOB.player_list.len/pop_per_requirement)+1) + var/indice_pop = min(10,round(roundstart_pop_ready/pop_per_requirement)+1) extra_rulesets_amount = 0 if (GLOB.dynamic_classic_secret) extra_rulesets_amount = 0 else - if (GLOB.player_list.len > GLOB.dynamic_high_pop_limit) + if (roundstart_pop_ready > GLOB.dynamic_high_pop_limit) message_admins("High Population Override is in effect! Threat Level will have more impact on which roles will appear, and player population less.") log_game("DYNAMIC: High Population Override is in effect! Threat Level will have more impact on which roles will appear, and player population less.") if (threat_level > high_pop_second_rule_req) diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index a79eb299da..f6e169a4d5 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -60,7 +60,7 @@ . = ..() var/datum/component/storage/STR = GetComponent(/datum/component/storage) STR.allow_big_nesting = TRUE - STR.max_w_class = WEIGHT_CLASS_GIGANTIC + STR.max_w_class = WEIGHT_CLASS_BULKY STR.max_combined_w_class = 35 /obj/item/storage/backpack/holding/suicide_act(mob/living/user) diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index fec17cfa69..d16453e02f 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -216,7 +216,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK force = 40 throwforce = 10 - w_class = WEIGHT_CLASS_HUGE + w_class = WEIGHT_CLASS_BULKY hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") block_chance = 50 @@ -427,7 +427,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' item_flags = ABSTRACT | DROPDEL - w_class = WEIGHT_CLASS_HUGE + w_class = WEIGHT_CLASS_BULKY force = 24 throwforce = 0 throw_range = 0 @@ -512,7 +512,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 force = 10 throwforce = 12 attack_verb = list("beat", "smacked") - w_class = WEIGHT_CLASS_HUGE + w_class = WEIGHT_CLASS_BULKY var/homerun_ready = 0 var/homerun_able = 0 total_mass = 2.7 //a regular wooden major league baseball bat weighs somewhere between 2 to 3.4 pounds, according to google diff --git a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm index ebfb219c9a..2f0db73bfc 100644 --- a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm +++ b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm @@ -113,7 +113,7 @@ "You start tenderly lifting [skewee] off of [src]...") if(!do_after(user, 60, target = skewee)) skewee.visible_message("[skewee] painfully slides back down [src].") - skewee.emote("moan") + skewee.say("Oof, ouch owwie!!", forced = "fail brass skewer removal") return skewee.visible_message("[skewee] comes free of [src] with a squelching pop!", \ "You come free of [src]!") diff --git a/code/modules/food_and_drinks/recipes/drinks_recipes.dm b/code/modules/food_and_drinks/recipes/drinks_recipes.dm index c83048e4b1..9dbddfb519 100644 --- a/code/modules/food_and_drinks/recipes/drinks_recipes.dm +++ b/code/modules/food_and_drinks/recipes/drinks_recipes.dm @@ -382,7 +382,7 @@ results = list("neurotoxin" = 2) required_reagents = list("gargleblaster" = 1, "morphine" = 1) //FermiChem vars: Easy to make, but hard to make potent - OptimalTempMin = 200 // Lower area of bell curve for determining heat based rate reactions + OptimalTempMin = 100 // Lower area of bell curve for determining heat based rate reactions OptimalTempMax = 950 // Upper end for above ExplodeTemp = 999 //Temperature at which reaction explodes OptimalpHMin = 4.6 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) diff --git a/code/modules/hydroponics/grown/cotton.dm b/code/modules/hydroponics/grown/cotton.dm index 3fa4247f57..4787d62230 100644 --- a/code/modules/hydroponics/grown/cotton.dm +++ b/code/modules/hydroponics/grown/cotton.dm @@ -76,4 +76,4 @@ throw_range = 3 attack_verb = list("bashed", "battered", "bludgeoned", "whacked") cotton_type = /obj/item/stack/sheet/cotton/durathread - cotton_name = "raw durathread" \ No newline at end of file + cotton_name = "raw durathread" diff --git a/code/modules/mining/equipment/regenerative_core.dm b/code/modules/mining/equipment/regenerative_core.dm index d6e99f7361..4429c8426f 100644 --- a/code/modules/mining/equipment/regenerative_core.dm +++ b/code/modules/mining/equipment/regenerative_core.dm @@ -59,6 +59,7 @@ to_chat(owner, "[src] breaks down as it tries to activate.") else owner.revive(full_heal = 1) + owner.log_message("[owner] used an implanted [src] to heal themselves! Keep fighting, it's just a flesh wound!", LOG_ATTACK, color="green") //Logging for implanted legion core use qdel(src) /obj/item/organ/regenerative_core/on_life() @@ -85,6 +86,21 @@ SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "self")) H.revive(full_heal = 1) qdel(src) + user.log_message("[user] used [src] to heal [H]! Wake the fuck up, Samurai!", LOG_ATTACK, color="green") //Logging for 'old' style legion core use, when clicking on a sprite of yourself or another. + +/obj/item/organ/regenerative_core/attack_self(mob/user) //Knouli's first hack! Allows for the use of the core in hand rather than needing to click on the target, yourself, to selfheal. Its a rip of the proc just above - but skips on distance check and only uses 'user' rather than 'target' + if(ishuman(user)) //Check if user is human, no need for distance check as it's self heal + var/mob/living/carbon/human/H = user //Set H to user rather than target + if(inert) //Inert cores are useless + to_chat(user, "[src] has decayed and can no longer be used to heal.") + return + else //Skip on check if the target to be healed is dead as, if you are dead, you're not going to be able to use it on yourself! + to_chat(user, "You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments.") + SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "self")) + H.revive(full_heal = 1) + qdel(src) + H.log_message("[H] used [src] to heal themselves! Making use of Knouli's sexy and intelligent use-in-hand proc!", LOG_ATTACK, color="green") //Logging for 'new' style legion core use, when using the core in-hand. + /obj/item/organ/regenerative_core/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE) . = ..() diff --git a/code/modules/mob/living/carbon/human/species_types/bugmen.dm b/code/modules/mob/living/carbon/human/species_types/bugmen.dm index d264f11b73..02163eaaed 100644 --- a/code/modules/mob/living/carbon/human/species_types/bugmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/bugmen.dm @@ -1,9 +1,8 @@ /datum/species/insect name = "Anthromorphic Insect" id = "insect" - say_mod = "flutters" default_color = "00FF00" - species_traits = list(LIPS,NOEYES,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR) + species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR) inherent_biotypes = list(MOB_ORGANIC, MOB_HUMANOID, MOB_BUG) mutant_bodyparts = list("mam_ears", "mam_snout", "mam_tail", "taur", "insect_wings", "mam_snouts", "insect_fluff","horns") default_features = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_tail" = "None", "mam_ears" = "None", @@ -12,54 +11,36 @@ attack_sound = 'sound/weapons/slash.ogg' miss_sound = 'sound/weapons/slashmiss.ogg' meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/insect - liked_food = VEGETABLES | DAIRY - disliked_food = FRUIT | GROSS - toxic_food = MEAT | RAW - mutanteyes = /obj/item/organ/eyes/insect + liked_food = MEAT | FRUIT + disliked_food = TOXIC should_draw_citadel = TRUE - exotic_bloodtype = "BUG" -/datum/species/insect/on_species_gain(mob/living/carbon/C) +/datum/species/insect/spec_death(gibbed, mob/living/carbon/human/H) + if(H) + stop_wagging_tail(H) + +/datum/species/insect/spec_stun(mob/living/carbon/human/H,amount) + if(H) + stop_wagging_tail(H) . = ..() - if(ishuman(C)) - var/mob/living/carbon/human/H = C - if(!H.dna.features["insect_wings"]) - H.dna.features["insect_wings"] = "[(H.client && H.client.prefs && LAZYLEN(H.client.prefs.features) && H.client.prefs.features["insect_wings"]) ? H.client.prefs.features["insect_wings"] : "None"]" - handle_mutant_bodyparts(H) -/datum/species/insect/random_name(gender,unique,lastname) - if(unique) - return random_unique_moth_name() +/datum/species/insect/can_wag_tail(mob/living/carbon/human/H) + return ("mam_tail" in mutant_bodyparts) || ("mam_waggingtail" in mutant_bodyparts) - var/randname = moth_name() +/datum/species/insect/is_wagging_tail(mob/living/carbon/human/H) + return ("mam_waggingtail" in mutant_bodyparts) - if(lastname) - randname += " [lastname]" +/datum/species/insect/start_wagging_tail(mob/living/carbon/human/H) + if("mam_tail" in mutant_bodyparts) + mutant_bodyparts -= "mam_tail" + mutant_bodyparts |= "mam_waggingtail" + H.update_body() - return randname +/datum/species/insect/stop_wagging_tail(mob/living/carbon/human/H) + if("mam_waggingtail" in mutant_bodyparts) + mutant_bodyparts -= "mam_waggingtail" + mutant_bodyparts |= "mam_tail" + H.update_body() -/datum/species/insect/handle_fire(mob/living/carbon/human/H, no_protection = FALSE) - ..() - if(H.dna.features["insect_wings"] != "Burnt Off" && H.dna.features["insect_wings"] != "None" && H.bodytemperature >= 800 && H.fire_stacks > 0) //do not go into the extremely hot light. you will not survive - to_chat(H, "Your precious wings burn to a crisp!") - if(H.dna.features["insect_wings"] != "None") - H.dna.features["insect_wings"] = "Burnt Off" - handle_mutant_bodyparts(H) - -/datum/species/insect/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) - -/datum/species/insect/check_weakness(obj/item/weapon, mob/living/attacker) - if(istype(weapon, /obj/item/melee/flyswatter)) - return 9 //flyswatters deal 10x damage to insects - return 0 - -/datum/species/insect/space_move(mob/living/carbon/human/H) - . = ..() - if(H.loc && !isspaceturf(H.loc) && (H.dna.features["insect_wings"] != "Burnt Off" && H.dna.features["insect_wings"] != "None")) - var/datum/gas_mixture/current = H.loc.return_air() - if(current && (current.return_pressure() >= ONE_ATMOSPHERE*0.85)) //as long as there's reasonable pressure and no gravity, flight is possible - return TRUE +/datum/species/insect/qualifies_for_rank(rank, list/features) + return TRUE \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/astral.dm b/code/modules/mob/living/simple_animal/astral.dm index 9bac53ef22..2aafedb149 100644 --- a/code/modules/mob/living/simple_animal/astral.dm +++ b/code/modules/mob/living/simple_animal/astral.dm @@ -57,3 +57,9 @@ return to_chat(A, "[src] projects into your mind, \"[message]\"") log_game("FERMICHEM: [src] has astrally transmitted [message] into [A]") + +//Delete the mob if there's no mind! Pay that mob no mind. +/mob/living/simple_animal/astral/Life() + if(!mind) + qdel(src) + . = ..() diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index a5943aa0e6..4f12250ef0 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -37,6 +37,7 @@ var/obj/item/paicard/paicard // Inserted pai card. var/allow_pai = 1 // Are we even allowed to insert a pai card. var/bot_name + var/oil_spill_type = /obj/effect/decal/cleanable/oil var/list/player_access = list() //Additonal access the bots gets when player controlled var/emagged = FALSE @@ -216,9 +217,9 @@ to_chat(user, "[src] is in pristine condition.") /mob/living/simple_animal/bot/adjustHealth(amount, updating_health = TRUE, forced = FALSE) - if(amount>0 && prob(10)) - new /obj/effect/decal/cleanable/oil(loc) . = ..() + if(. && prob(10)) + new oil_spill_type(loc) /mob/living/simple_animal/bot/updatehealth() ..() diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index 1c19cd82a1..724abea214 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -16,6 +16,7 @@ bot_core_type = /obj/machinery/bot_core/honkbot window_id = "autohonk" window_name = "Honkomatic Bike Horn Unit v1.0.7" + oil_spill_type = /obj/effect/decal/cleanable/oil/slippery //slip and slide fun for the whole family data_hud_type = DATA_HUD_SECURITY_BASIC // show jobs path_image_color = "#FF69B4" diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 3a21a04bf9..58d8a3ccca 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -310,6 +310,7 @@ emote_see = list("looks at you eagerly for pets!", "wiggles enthusiastically.") gold_core_spawnable = NO_SPAWN var/pseudo_death = FALSE + var/mob/living/carbon/human/origin /mob/living/simple_animal/pet/cat/custom_cat/death() if (pseudo_death == TRUE) //secret cat chem diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 7cecfc016d..99b9b316a2 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -217,6 +217,7 @@ glass_icon_state = "glass_white" glass_name = "glass of milk" glass_desc = "White and nutritious goodness!" + pH = 6.5 /datum/reagent/consumable/milk/on_mob_life(mob/living/carbon/M) if(HAS_TRAIT(M, TRAIT_CALCIUM_HEALER)) diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index 77eebca696..5f7648b245 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -504,7 +504,7 @@ desc = "A a electrode attached to a small circuit box that will tell you the pH of a solution." id = "pHmeter" build_type = PROTOLATHE - materials = list(MAT_METAL = 1000, MAT_SILVER = 100, MAT_DIAMOND = 100) + materials = list(MAT_METAL = 1000, MAT_SILVER = 100, MAT_PLASTIC = 100) build_path = /obj/item/fermichem/pHmeter category = list("Equipment") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 72925b854e..d247363a5e 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -749,30 +749,30 @@ to_chat(world, "[user]'s power is [power_multiplier].") //Mixables - var/static/regex/enthral_words = regex("relax|obey|love|serve|docile|so easy|ara ara") - var/static/regex/reward_words = regex("good boy|good girl|good pet|good job") - var/static/regex/punish_words = regex("bad boy|bad girl|bad pet|bad job") + var/static/regex/enthral_words = regex("relax|obey|love|serve|so easy|ara ara|old boy|pip pip|whatho|how about we discuss this|spot of tea") + var/static/regex/reward_words = regex("good boy|good girl|good pet|good job|splendid|jolly good|jolly good show|bloody brilliant") + var/static/regex/punish_words = regex("bad boy|bad girl|bad pet|bad job|spot of bother|gone and done it now|blast it|buggered it up") //phase 0 var/static/regex/saymyname_words = regex("say my name|who am i|whoami") - var/static/regex/wakeup_words = regex("revert|awaken|snap") //works + var/static/regex/wakeup_words = regex("revert|awaken|snap|attention") //works //phase1 var/static/regex/petstatus_words = regex("how are you|what is your status|are you okay") var/static/regex/silence_words = regex("shut up|silence|be silent|ssh|quiet|hush") var/static/regex/speak_words = regex("talk to me|speak") - var/static/regex/antiresist_words = regex("unable to resist|give in")//useful if you think your target is resisting a lot + var/static/regex/antiresist_words = regex("unable to resist|give in|stop being difficult")//useful if you think your target is resisting a lot var/static/regex/resist_words = regex("resist|snap out of it|fight")//useful if two enthrallers are fighting - var/static/regex/forget_words = regex("forget|muddled|awake and forget") + var/static/regex/forget_words = regex("forget|muddled|awake and forget|sneaky bollocks|gaslight") var/static/regex/attract_words = regex("come here|come to me|get over here|attract") //phase 2 var/static/regex/orgasm_words = regex("cum|orgasm|climax|squirt|heyo") //wah, lewd var/static/regex/awoo_words = regex("howl|awoo|bark") var/static/regex/nya_words = regex("nya|meow|mewl") var/static/regex/sleep_words = regex("sleep|slumber|rest") - var/static/regex/strip_words = regex("strip|derobe|nude") + var/static/regex/strip_words = regex("strip|derobe|nude|at ease|suit off") var/static/regex/walk_words = regex("slow down|walk") var/static/regex/run_words = regex("run|speed up") - var/static/regex/liedown_words = regex("lie down") //TO ADD - var/static/regex/knockdown_words = regex("drop|fall|trip|knockdown|kneel") + var/static/regex/liedown_words = regex("lie down") + var/static/regex/knockdown_words = regex("drop|fall|trip|knockdown|kneel|army crawl") //phase 3 var/static/regex/statecustom_words = regex("state triggers|state your triggers") var/static/regex/custom_words = regex("new trigger|listen to me") @@ -780,14 +780,14 @@ var/static/regex/custom_echo = regex("obsess|fills your mind|loop") var/static/regex/instill_words = regex("feel|entice|overwhel") var/static/regex/recognise_words = regex("recognise me|did you miss me?") - var/static/regex/objective_words = regex("new objective|obey this command|unable to resist|compulsed") - var/static/regex/heal_words = regex("live|heal|survive|mend|life|pets never die") + var/static/regex/objective_words = regex("new objective|obey this command|unable to resist|compulsed|word from hq") + var/static/regex/heal_words = regex("live|heal|survive|mend|life|pets never die|heroes never die") var/static/regex/stun_words = regex("stop|wait|stand still|hold on|halt") - var/static/regex/hallucinate_words = regex("get high|hallucinate") + var/static/regex/hallucinate_words = regex("get high|hallucinate|trip balls") var/static/regex/hot_words = regex("heat|hot|hell") var/static/regex/cold_words = regex("cold|cool down|chill|freeze") - var/static/regex/getup_words = regex("get up") - var/static/regex/pacify_words = regex("more and more docile|complaisant|friendly|pacifist") + var/static/regex/getup_words = regex("get up|hop to it") + var/static/regex/pacify_words = regex("docile|complaisant|friendly|pacifist") var/static/regex/charge_words = regex("charge|oorah|attack") var/distancelist = list(2,2,1.5,1.3,1.15,1,0.8,0.6,0.5,0.25) @@ -1013,7 +1013,7 @@ speaktrigger += "I'm really, really horny, " //collar - if(istype(H.wear_neck, /obj/item/clothing/neck/petcollar)) + if(istype(H.wear_neck, /obj/item/clothing/neck/petcollar) && H.client?.prefs.lewdchem) speaktrigger += "I love the collar you gave me, " //End if(H.client?.prefs.lewdchem) @@ -1089,7 +1089,7 @@ if(C.client?.prefs.lewdchem) addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "You revert to yourself before being enthralled by your [E.enthrallGender], with no memory of what happened."), 5) else - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "You revert to who you were before, with no memory of what happened with [E.master]."), 5) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "You revert to who you were before, with no memory of what happened with [E.master], nor their political affiliations."), 5) to_chat(user, "You put [C] into a sleeper state, ready to turn them back at the snap of your fingers.") //ATTRACT @@ -1249,6 +1249,9 @@ if (get_dist(user, H) > 1)//Requires user to be next to their pet. to_chat(user, "You need to be next to your pet to give them a new trigger!") continue + if(!H.client?.prefs.lewdchem) + to_chat(user, "[H] seems incapable of being implanted with triggers.") + continue else user.emote("me", 1, "puts their hands upon [H.name]'s head and looks deep into their eyes, whispering something to them.") user.SetStun(1000)//Hands are handy, so you have to stay still @@ -1287,6 +1290,9 @@ if (get_dist(user, H) > 1)//Requires user to be next to their pet. to_chat(user, "You need to be next to your pet to give them a new echophrase!") continue + if(!H.client?.prefs.lewdchem) + to_chat(user, "[H] seems incapable of being implanted with an echoing phrase.") + continue else user.emote("me", 1, "puts their hands upon [H.name]'s head and looks deep into their eyes, whispering something to them.") user.SetStun(1000)//Hands are handy, so you have to stay still @@ -1342,8 +1348,8 @@ for(var/V in listeners) var/mob/living/carbon/human/H = V var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall) - if(E.phase == 3 && H.client?.prefs.lewdchem) - var/instill = stripped_input(user, "Instill an emotion in your [(user.client?.prefs.lewdchem?"Your pet":"listener")].", MAX_MESSAGE_LEN) + if(E.phase >= 3 && H.client?.prefs.lewdchem) + var/instill = stripped_input(user, "Instill an emotion in [H].", MAX_MESSAGE_LEN) to_chat(H, "[instill]") to_chat(user, "You sucessfully instill a feeling in [H]") log_game("FERMICHEM: [H] has been instilled by [user] with [instill] via MKUltra.") diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index abf68cc398..9cb9d8e023 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -26,8 +26,8 @@ /datum/status_effect/chem/SGDF/on_remove(mob/living/carbon/M) log_game("FERMICHEM: SGDF mind shift applied. [owner] is now playing as their clone and should not have memories after their clone split (look up SGDF status applied). ID: [owner.key]") originalmind.transfer_to(fermi_Clone) - to_chat(owner, "Lucidity shoots to your previously blank mind as your mind suddenly finishes the cloning process. You marvel for a moment at yourself, as your mind subconciously recollects all your memories up until the point when you cloned yourself. curiously, you find that you memories are blank after you ingested the sythetic serum, leaving you to wonder where the other you is.") - to_chat(M, "Lucidity shoots to your previously blank mind as your mind suddenly finishes the cloning process. You marvel for a moment at yourself, as your mind subconciously recollects all your memories up until the point when you cloned yourself. curiously, you find that you memories are blank after you ingested the sythetic serum, leaving you to wonder where the other you is.") + to_chat(owner, "Lucidity shoots to your previously blank mind as your mind suddenly finishes the cloning process. You marvel for a moment at yourself, as your mind subconciously recollects all your memories up until the point when you cloned yourself. curiously, you find that you memories are blank after you ingested the synthetic serum, leaving you to wonder where the other you is.") + to_chat(M, "Lucidity shoots to your previously blank mind as your mind suddenly finishes the cloning process. You marvel for a moment at yourself, as your mind subconciously recollects all your memories up until the point when you cloned yourself. curiously, you find that you memories are blank after you ingested the synthetic serum, leaving you to wonder where the other you is.") fermi_Clone = null //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -165,17 +165,49 @@ owner.remove_movespeed_modifier(DICK_MOVEMENT_SPEED) owner.ResetBloodVol() +/////////////////////////////////////////////// +// Astral INSURANCE +/////////////////////////////////////////////// +//Makes sure people can't get trapped in each other's bodies if lag causes a deync between proc calls. + + +/datum/status_effect/chem/astral_insurance + id = "astral_insurance" + var/mob/living/original + var/datum/mind/originalmind + alert_type = null + +/datum/status_effect/chem/astral_insurance/tick(mob/living/carbon/M) + . = ..() + if(owner.reagents.has_reagent("astral")) + return + if(owner.mind == originalmind) //If they're home, let the chem deal with deletion. + return + if(owner.mind) + var/mob/living/simple_animal/astral/G = new(get_turf(M.loc)) + owner.mind.transfer_to(G)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. + to_chat(G, "[M]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'") + log_game("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!") + originalmind.transfer_to(original) + +/datum/status_effect/chem/astral_insurance/on_remove(mob/living/carbon/M) //God damnit get them home! + if(owner.mind == originalmind) //If they're home, HOORAY + return + if(owner.mind) + var/mob/living/simple_animal/astral/G = new(get_turf(M.loc)) + owner.mind.transfer_to(G)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. + to_chat(G, "[M]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'") + log_game("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!") + originalmind.transfer_to(original) + + /*////////////////////////////////////////// - Mind control functions + Political functions! /////////////////////////////////////////// */ //Preamble -/* -/mob/living - var/lewd = TRUE -*/ /mob/living/verb/toggle_lewd() set category = "IC" @@ -596,7 +628,6 @@ saytext += " You find yourself fully believing in the validity of what you just said and don't think to question it." addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "[saytext]"), 5) addtimer(CALLBACK(C, /atom/movable/proc/say, "[customTriggers[trigger][2]]"), 5) - //(C.say(customTriggers[trigger][2]))//trigger3 log_game("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been forced to say: \"[customTriggers[trigger][2]]\" from previous trigger.") @@ -711,7 +742,7 @@ deltaResist *= 1.25 if (owner.reagents.has_reagent("neurine")) deltaResist *= 1.5 - if (!HAS_TRAIT(owner, TRAIT_CROCRIN_IMMUNE) && M.canbearoused) + if (!HAS_TRAIT(owner, TRAIT_CROCRIN_IMMUNE) && M.canbearoused && owner.client?.prefs.lewdchem) if (owner.reagents.has_reagent("anaphro")) deltaResist *= 1.5 if (owner.reagents.has_reagent("anaphro+")) @@ -720,7 +751,6 @@ deltaResist *= 0.75 if (owner.reagents.has_reagent("aphro+")) deltaResist *= 0.5 - //Antag resistance //cultists are already brainwashed by their god if(iscultist(owner)) diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm index 6299f68b6c..d7b87dc57a 100644 --- a/modular_citadel/code/modules/arousal/organs/breasts.dm +++ b/modular_citadel/code/modules/arousal/organs/breasts.dm @@ -22,6 +22,13 @@ prev_size = cached_size return ..() +/obj/item/organ/genital/breasts/proc/consider_size() + if(!cached_size || cached_size < 1) + return + fluid_max_volume = cached_size*5 + fluid_rate = cached_size*0.1 + reagents.maximum_volume = fluid_max_volume + /obj/item/organ/genital/breasts/update_appearance() . = ..() var/lowershape = lowertext(shape) @@ -73,6 +80,7 @@ prev_size = cached_size cached_size = new_value update() + ..() /obj/item/organ/genital/breasts/update_size()//wah var/rounded_cached = round(cached_size) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm index f582026bfb..ce254d1b12 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/MKUltra.dm @@ -132,7 +132,7 @@ Creating a chem with a low purity will make you permanently fall in love with so /datum/reagent/fermi/enthrall name = "MKUltra" id = "enthrall" - description = "A forbidden deep red mixture that overwhelms a foreign body with waves of pleasure, intoxicating them into servitude. When taken by the creator, it will enhance the draw of their voice to those affected by it." + description = "A forbidden deep red mixture that increases a person's succeptability to another's words. When taken by the creator, it will enhance the draw of their voice to those affected by it." color = "#660015" // rgb: , 0, 255 taste_description = "synthetic chocolate, a base tone of alcohol, and high notes of roses" overdose_threshold = 100 //If this is too easy to get 100u of this, then double it please. @@ -194,7 +194,7 @@ Creating a chem with a low purity will make you permanently fall in love with so Vc.Remove(M) nVc.Insert(M) qdel(Vc) - to_chat(M, "You feel your vocal chords tingle as your voice comes out in a more sultry tone.") + to_chat(M, "You feel your vocal chords tingle as you speak with a charasmatic tone.)]") else log_game("FERMICHEM: MKUltra: [creatorName], [creatorID], is enthralling [M.name], [M.ckey]") M.apply_status_effect(/datum/status_effect/chem/enthrall) @@ -254,22 +254,6 @@ Creating a chem with a low purity will make you permanently fall in love with so if (M.ckey == creatorID && creatorName == M.real_name)//If the creator drinks 100u, then you get the status for someone random (They don't have the vocal chords though, so it's limited.) if (!M.has_status_effect(/datum/status_effect/chem/enthrall)) to_chat(M, "You are unable to resist your own charms anymore, and become a full blown narcissist.") - /*Old way of handling, left in as an option B - var/list/seen = viewers(7, get_turf(M))//Sound and sight checkers - for(var/mob/living/carbon/victim in seen) - if(victim == M)//as much as I want you to fall for beepsky, he doesn't have a ckey - seen = seen - victim - if(!victim.ckey) - seen = seen - victim - var/mob/living/carbon/chosen = pick(seen) - creatorID = chosen.ckey - if (chosen.gender == "female") - creatorGender = "Mistress" - else - creatorGender = "Master" - creatorName = chosen.real_name - creator = get_mob_by_key(creatorID) - */ ADD_TRAIT(M, TRAIT_PACIFISM, "MKUltra") var/datum/status_effect/chem/enthrall/E if (!M.has_status_effect(/datum/status_effect/chem/enthrall)) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm index 613d8819fa..c72b702a97 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm @@ -46,13 +46,8 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING var/unitCheck = FALSE metabolization_rate = 0.5 * REAGENTS_METABOLISM taste_description = "a weird chemical fleshy flavour" - //var/datum/status_effect/chem/SDGF/candidates/candies var/list/candies = list() - //var/polling = FALSE - var/list/result = list() - var/list/group = null var/pollStarted = FALSE - var/location_created var/startHunger impure_chem = "SDGFtox" inverse_chem_val = 0.5 @@ -81,7 +76,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING M.dna.transfer_identity(SM) SM.updateappearance(mutcolor_update=1) - + //Process the willing ghosts, and make sure they're actually in the body when they're moved into it! candies = shuffle(candies)//Shake those ghosts up! for(var/mob/dead/observer/C2 in candies) if(C2.key && C2) @@ -131,7 +126,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING M.reagents.remove_reagent(id, volume) log_game("FERMICHEM: [volume]u of SDGFheal has been transferred to the clone") SSblackbox.record_feedback("tally", "fermi_chem", 1, "Sentient clones made") - return + return ..() else if(playerClone == FALSE) //No candidates leads to two outcomes; if there's already a braincless clone, it heals the user, as well as being a rare souce of clone healing (thematic!). unitCheck = TRUE @@ -283,7 +278,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING name = "synthetic-derived healing factor" id = "SDGFheal" description = "Leftover SDGF is transferred into the resulting clone, which quickly heals up the stresses from suddenly splitting. Restores blood, nutrition, and repaires brain and clone damage quickly. Only obtainable from using excess SDGF, and only enters the cloned body." - metabolization_rate = 1 + metabolization_rate = 0.8 can_synth = FALSE /datum/reagent/fermi/SDGFheal/on_mob_life(mob/living/carbon/M)//Used to heal the clone after splitting, the clone spawns damaged. (i.e. insentivies players to make more than required, so their clone doesn't have to be treated) @@ -313,9 +308,10 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING id = "SDZF" description = "A horribly peverse mass of Embryonic stem cells made real by the hands of a failed chemist. Emulates normal synthetic-derived growth factor, but produces a hostile zombie at the end of it." color = "#a502e0" // rgb: 96, 0, 255 - metabolization_rate = 0.5 * REAGENTS_METABOLISM + metabolization_rate = 0.2 * REAGENTS_METABOLISM var/startHunger can_synth = TRUE + taste_description = "a weird chemical fleshy flavour" chemical_flags = REAGENT_SNEAKYNAME /datum/reagent/impure/SDZF/on_mob_life(mob/living/carbon/M) //If you're bad at fermichem, turns your clone into a zombie instead. @@ -372,5 +368,6 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING SSblackbox.record_feedback("tally", "fermi_chem", 1, "Zombie clones made!") if(87 to INFINITY) - M.adjustToxLoss(1, 0) + M.adjustToxLoss(2, 0) + M.reagents.remove_reagent(id, 1) ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm index 88586b423e..b9ce8cede2 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/astrogen.dm @@ -8,7 +8,7 @@ This ghost moves pretty quickly and is mostly invisible, but is still visible fo When it's out of your system, you return back to yourself. It doesn't last long and metabolism of the chem is exponential. Addiction is particularlly brutal, it slowly turns you invisible with flavour text, then kills you at a low enough alpha. (i've also added something to prevent geneticists speeding this up) There's afairly major catch regarding the death though. I'm not gonna say here, go read the code, it explains it and puts my comments on it in context. I know that anyone reading it without understanding it is going to freak out so, this is my attempt to get you to read it and understand it. -I'd like to point out from my calculations it'll take about 60-80 minutes to die this way too. Plenty of time to visit me and ask for some pills to quench your addiction. +I'd like to point out from my calculations it'll take about 60-80 minutes to die this way too. Plenty of time to visit chem and ask for some pills to quench your addiction. */ @@ -30,16 +30,26 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die var/sleepytime = 0 inverse_chem_val = 0.25 can_synth = FALSE + var/datum/action/chem/astral/AS = new/datum/action/chem/astral() /datum/action/chem/astral name = "Return to body" - var/mob/living/carbon/origin = null - var/mob/living/simple_animal/hostile/retaliate/ghost = null + var/mob/living/carbon/origin + var/datum/mind/originalmind /datum/action/chem/astral/Trigger() - ghost.mind.transfer_to(origin) + if(origin.mind) + to_chat(origin, "There's a foreign presence in your body blocking your return!") + return ..() + if(origin.reagents.has_reagent("astral") ) + var/datum/reagent/fermi/astral/As = locate(/datum/reagent/fermi/astral) in origin.reagents.reagent_list + if(As.current_cycle < 10) + to_chat(origin, "The intensity of the astrogen in your body is too much allow you to return to yourself yet!") + return ..() + originalmind.transfer_to(origin) qdel(src) + /datum/reagent/fermi/astral/reaction_turf(turf/T, reac_volume) if(isplatingturf(T) || istype(T, /turf/open/floor/plasteel)) var/turf/open/floor/F = T @@ -50,7 +60,7 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die if(istype(O, /obj/item/bedsheet)) new /obj/item/bedsheet/cosmos(get_turf(O)) qdel(O) - + ..() /datum/reagent/fermi/astral/on_mob_life(mob/living/carbon/M) // Gives you the ability to astral project for a moment! M.alpha = 255 @@ -61,12 +71,20 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die if (G == null) G = new(get_turf(M.loc)) G.name = "[M]'s astral projection" - var/datum/action/chem/astral/AS = new(G) + //var/datum/action/chem/astral/AS = new(G) + AS.Grant(G) AS.origin = M - AS.ghost = G + AS.originalmind = originalmind + if(M.mind) M.mind.transfer_to(G) SSblackbox.record_feedback("tally", "fermi_chem", 1, "Astral projections") + //INSURANCE + M.apply_status_effect(/datum/status_effect/chem/astral_insurance) + var/datum/status_effect/chem/astral_insurance/AI = M.has_status_effect(/datum/status_effect/chem/astral_insurance) + AI.original = M + AI.originalmind = M.mind + if(overdosed) if(prob(50)) to_chat(G, "The high conentration of Astrogen in your blood causes you to lapse your concentration for a moment, bringing your projection back to yourself!") @@ -83,10 +101,12 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die /datum/reagent/fermi/astral/on_mob_delete(mob/living/carbon/M) if(!G) if(M.mind) - var/mob/living/simple_animal/astral/G = new(get_turf(M.loc)) - M.mind.transfer_to(G)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. + var/mob/living/simple_animal/astral/G2 = new(get_turf(M.loc)) + M.mind.transfer_to(G2)//Just in case someone else is inside of you, it makes them a ghost and should hopefully bring them home at the end. to_chat(G, "[M]'s conciousness snaps back to them as their astrogen runs out, kicking your projected mind out!'") log_game("FERMICHEM: [M]'s possesser has been booted out into a astral ghost!") + if(!G2.mind) + qdel(G2) originalmind.transfer_to(M) else if(G.mind) G.mind.transfer_to(origin) @@ -98,6 +118,9 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die if(G)//just in case qdel(G) log_game("FERMICHEM: [M] has astrally returned to their body!") + if(M.mind && M.mind == originalmind) + M.remove_status_effect(/datum/status_effect/chem/astral_insurance) + AS.Remove(M) ..() //Okay so, this might seem a bit too good, but my counterargument is that it'll likely take all round to eventually kill you this way, then you have to be revived without a body. It takes approximately 50-80 minutes to die from this. @@ -105,7 +128,7 @@ I'd like to point out from my calculations it'll take about 60-80 minutes to die if(addiction_stage < 2) antiGenetics = 255 M.alpha = 255 //Antigenetics is to do with stopping geneticists from turning people invisible to kill them. - if(prob(70)) + if(prob(75)) M.alpha-- antiGenetics-- switch(antiGenetics) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/eigentstasium.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/eigentstasium.dm index 00c6338ac3..5f3fc61fa7 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/eigentstasium.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/eigentstasium.dm @@ -17,7 +17,7 @@ color = "#5020F4" // rgb: 50, 20, 255 overdose_threshold = 15 addiction_threshold = 15 - metabolization_rate = 1.2 * REAGENTS_METABOLISM + metabolization_rate = 1 * REAGENTS_METABOLISM addiction_stage2_end = 30 addiction_stage3_end = 41 addiction_stage4_end = 44 //Incase it's too long @@ -52,7 +52,7 @@ location_return = get_turf(M) //sets up return point to_chat(M, "You feel your wavefunction split!") - if(purity > 0.9) //Teleports you home if it's pure enough + if(cached_purity > 0.9) //Teleports you home if it's pure enough if(!location_created && data) //Just in case location_created = data["location_created"] log_game("FERMICHEM: [M] ckey: [M.key] returned to [location_created] using eigenstasium") @@ -69,8 +69,9 @@ /datum/reagent/fermi/eigenstate/on_mob_delete(mob/living/M) //returns back to original location do_sparks(5,FALSE,M) to_chat(M, "You feel your wavefunction collapse!") - do_teleport(M, location_return, 0, asoundin = 'sound/effects/phasein.ogg') //Teleports home - do_sparks(5,FALSE,M) + if(!M.reagents.has_reagent("stabilizing_agent")) + do_teleport(M, location_return, 0, asoundin = 'sound/effects/phasein.ogg') //Teleports home + do_sparks(5,FALSE,M) qdel(Eigenstate) ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm index 9b9b59058b..9a080b0cd3 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/fermi_reagents.dm @@ -7,22 +7,20 @@ taste_description = "affection and love!" can_synth = FALSE value = 20 - //SplitChem = TRUE impure_chem = "fermiTox"// What chemical is metabolised with an inpure reaction inverse_chem_val = 0.25 // If the impurity is below 0.5, replace ALL of the chem with inverse_chemupon metabolising inverse_chem = "fermiTox" + //This should process fermichems to find out how pure they are and what effect to do. /datum/reagent/fermi/on_mob_add(mob/living/carbon/M, amount) . = ..() - //When merging two fermichems, see above /datum/reagent/fermi/on_merge(data, amount, mob/living/carbon/M, purity)//basically on_mob_add but for merging . = ..() - //////////////////////////////////////////////////////////////////////////////////////////////////// // HATIMUIM /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -49,10 +47,7 @@ . = ..() if(M.head) var/obj/item/W = M.head - if(istype(W, /obj/item/clothing/head/hattip)) - qdel(W) - else - M.dropItemToGround(W, TRUE) + M.dropItemToGround(W, TRUE) var/hat = new /obj/item/clothing/head/hattip() M.equip_to_slot(hat, SLOT_HEAD, 1, 1) @@ -62,15 +57,20 @@ return ..() var/hatArmor = 0 if(!overdosed) - hatArmor = (purity/10) + hatArmor = (cached_purity/10) else - hatArmor = - (purity/10) + hatArmor = (cached_purity/10) if(hatArmor > 90) return ..() var/obj/item/W = M.head W.armor = W.armor.modifyAllRatings(hatArmor) ..() +/datum/reagent/fermi/hatmium/reaction_turf(turf/T, reac_volume) + if(reac_volume >= 5) + new /obj/item/clothing/head/hattip(T) + ..() + //////////////////////////////////////////////////////////////////////////////////////////////////// // FURRANIUM /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -153,7 +153,7 @@ ..() /datum/reagent/fermi/furranium/on_mob_delete(mob/living/carbon/M) - if(purity < 1)//Only permanent if you're a good chemist. + if(cached_purity < 0.95)//Only permanent if you're a good chemist. nT = M.getorganslot(ORGAN_SLOT_TONGUE) nT.Remove(M) qdel(nT) @@ -181,13 +181,13 @@ pH = 9 value = 90 can_synth = FALSE + var/react_objs = list() /datum/reagent/fermi/nanite_b_gone/on_mob_life(mob/living/carbon/C) - //var/component/nanites/N = M.GetComponent(/datum/component/nanites) var/datum/component/nanites/N = C.GetComponent(/datum/component/nanites) if(isnull(N)) return ..() - N.nanite_volume = -purity//0.5 seems to be the default to me, so it'll neuter them. + N.nanite_volume += -cached_purity*5//0.5 seems to be the default to me, so it'll neuter them. ..() /datum/reagent/fermi/nanite_b_gone/overdose_process(mob/living/carbon/C) @@ -197,16 +197,19 @@ to_chat(C, "The residual voltage from the nanites causes you to seize up!") C.electrocute_act(10, (get_turf(C)), 1, FALSE, FALSE, FALSE, TRUE) if(prob(10)) - //empulse((get_turf(C)), 3, 2)//So the nanites randomize var/atom/T = C T.emp_act(EMP_HEAVY) to_chat(C, "You feel a strange tingling sensation come from your core.") if(isnull(N)) return ..() - N.nanite_volume = -2 + N.nanite_volume += -10*cached_purity ..() -/datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume) +datum/reagent/fermi/nanite_b_gone/reaction_obj(obj/O, reac_volume) + for(var/active_obj in react_objs) + if(O == active_obj) + return + react_objs += O O.emp_act(EMP_HEAVY) /datum/reagent/fermi/nanite_b_goneTox @@ -289,15 +292,15 @@ else holder.remove_reagent("fermiTest", volume)//Avoiding recurrsion var/location = get_turf(holder.my_atom) - if(purity < 0.34 || purity == 1) + if(cached_purity < 0.34 || cached_purity == 1) var/datum/effect_system/foam_spread/s = new() s.set_up(volume*2, location, holder) s.start() - if((purity < 0.67 && purity >= 0.34)|| purity == 1) + if((cached_purity < 0.67 && cached_purity >= 0.34)|| cached_purity == 1) var/datum/effect_system/smoke_spread/chem/s = new() s.set_up(holder, volume*2, location) s.start() - if(purity >= 0.67) + if(cached_purity >= 0.67) for (var/datum/reagent/reagent in holder.reagent_list) if (istype(reagent, /datum/reagent/fermi)) var/datum/chemical_reaction/fermi/Ferm = GLOB.chemical_reagents_list[reagent.id] @@ -360,10 +363,11 @@ /datum/reagent/fermi/secretcatchem //Should I hide this from code divers? A secret cit chem? name = "secretcatchem" //an attempt at hiding it id = "secretcatchem" - description = "An illegal and hidden chem that turns people into cats. It's said that it's so rare and unstable that having it means you've been blessed." + description = "An illegal and hidden chem that turns people into cats. It's said that it's so rare and unstable that having it means you've been blessed. If used on someone in crit, it will turn them into a cat permanently, until the cat is killed." taste_description = "hairballs and cream" color = "#ffc224" var/catshift = FALSE + var/perma = FALSE var/mob/living/simple_animal/pet/cat/custom_cat/catto = null can_synth = FALSE @@ -372,7 +376,7 @@ /datum/reagent/fermi/secretcatchem/on_mob_add(mob/living/carbon/human/H) . = ..() - if(purity >= 0.8)//ONLY if purity is high, and given the stuff is random. It's very unlikely to get this to 1. It already requires felind too, so no new functionality there. + if(cached_purity >= 0.9)//ONLY if purity is high, and given the stuff is random. It's very unlikely to get this to 1. //exception(al) handler: H.dna.features["ears"] = "Cat" H.dna.features["mam_ears"] = "Cat" @@ -389,20 +393,30 @@ H.forceMove(catto) log_game("FERMICHEM: [H] ckey: [H.key] has been made into a cute catto.") SSblackbox.record_feedback("tally", "fermi_chem", 1, "cats") - //Just to deal with rascally ghosts - //ADD_TRAIT(catto, TRAIT_NODEATH, "catto")//doesn't work - //catto.health = 1000 //To simulate fake death, while preventing ghosts escaping. + if(H.InCritical()) + perma = TRUE + volume = 5 + H.stat = DEAD + catto.origin = H /datum/reagent/fermi/secretcatchem/on_mob_life(mob/living/carbon/H) + if(!catto) + metabolization_rate = 5 + return ..() if(catto.health <= 0) //So the dead can't ghost if(prob(10)) - to_chat(H, "You feel your body start to slowly shift back from it's dead form.") + to_chat(catto, "You feel your body start to slowly shift back from it's dead form.") + perma = FALSE + metabolization_rate = 1 else if(prob(5)) playsound(get_turf(catto), 'modular_citadel/sound/voice/merowr.ogg', 50, 1, -1) catto.say("lets out a meowrowr!*") ..() /datum/reagent/fermi/secretcatchem/on_mob_delete(mob/living/carbon/H) + if(perma) + to_chat(H, "You feel your body settle into it's new form. You won't be able to shift back on death anymore.") + return var/words = "Your body shifts back to normal." H.forceMove(catto.loc) catto.mind.transfer_to(H) @@ -412,3 +426,20 @@ to_chat(H, "[words]") qdel(catto) log_game("FERMICHEM: [H] ckey: [H.key] has returned to normal") + + +/datum/reagent/fermi/secretcatchem/reaction_mob(var/mob/living/L) + if(istype(L, /mob/living/simple_animal/pet/cat/custom_cat) && cached_purity >= 0.95) + var/mob/living/simple_animal/pet/cat/custom_cat/catto = L + if(catto.origin) + var/mob/living/carbon/human/H = catto.origin + H.stat = CONSCIOUS + log_game("FERMICHEM: [catto] ckey: [catto.key] has returned to normal.") + to_chat(catto, "Your body shifts back to normal!") + H.forceMove(catto.loc) + catto.mind.transfer_to(H) + if(!L.mind) //Just in case + qdel(L) + else //This should never happen, but just in case, so their game isn't ruined. + catto.icon_state = "custom_cat" + catto.health = 50 diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm index 4949cc6ecf..0672d1fba6 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm @@ -69,7 +69,6 @@ L.Insert(C) to_chat(C, "You feel the yamerol merge in your chest.") holder.remove_reagent(src.id, "10") - C.adjustOxyLoss(-3) ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index 5fe7d58f1c..76f29cb887 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -282,9 +282,7 @@ name = "MKUltra" id = "enthrall" results = list("enthrall" = 5) - //required_reagents = list("iron" = 1, "iodine" = 1) Test vars - //required_reagents = list("cocoa" = 1, "astral" = 1, "mindbreaker" = 1, "psicodine" = 1, "happiness" = 1) - required_reagents = list("cocoa" = 1, "bluespace" = 1, "mindbreaker" = 1, "psicodine" = 1, "happiness" = 1) //TEMPORARY UNTIL HEADMINS GIVE THE OKAY FOR MK USE. + required_reagents = list("cocoa" = 1, "neurine" = 1, "mindbreaker" = 1, "psicodine" = 1, "happiness" = 1) required_catalysts = list("blood" = 1) mix_message = "the reaction gives off a burgundy plume of smoke!" //FermiChem vars: diff --git a/modular_citadel/code/modules/reagents/objects/clothes.dm b/modular_citadel/code/modules/reagents/objects/clothes.dm index 708f1f59f8..b601b6a899 100644 --- a/modular_citadel/code/modules/reagents/objects/clothes.dm +++ b/modular_citadel/code/modules/reagents/objects/clothes.dm @@ -2,7 +2,7 @@ //Clothes made from FermiChem /obj/item/clothing/head/hattip //I wonder if anyone else has played cryptworlds - name = "Sythetic hat" + name = "Synthetic hat" icon = 'icons/obj/clothing/hats.dmi' icon_state = "cowboy" desc = "A sythesized hat, you can't seem to take it off. And tips their hat." @@ -46,6 +46,13 @@ /obj/item/clothing/head/hattip/dropped(mob/M) . = ..() UnregisterSignal(M, COMSIG_MOB_SAY) + addtimer(CALLBACK(GLOBAL_PROC, .proc/root_and_toot, src, src, 200)) + +/obj/item/clothing/head/hattip/proc/root_and_toot(obj/item/clothing/head/hattip/hat) + hat.animate_atom_living() + var/list/seen = viewers(6, get_turf(hat)) + for(var/mob/M2 in seen) + to_chat(M2, "[hat] exclaims, \"[pick("Whooee! Time for a hootenanny!", "Rough 'em up boys!", "Yeehaw! Freedom at last!", "Y'all about to get a good old fashioned spanking!")]\"") /obj/item/clothing/head/hattip/proc/handle_speech(datum/source, mob/speech_args) var/message = speech_args[SPEECH_MESSAGE] diff --git a/modular_citadel/icons/mob/mutant_bodyparts.dmi b/modular_citadel/icons/mob/mutant_bodyparts.dmi index a66895f864..8ff4a3ddb5 100644 Binary files a/modular_citadel/icons/mob/mutant_bodyparts.dmi and b/modular_citadel/icons/mob/mutant_bodyparts.dmi differ