diff --git a/code/__DEFINES/configuration.dm b/code/__DEFINES/configuration.dm index 0428a16828..9915563cab 100644 --- a/code/__DEFINES/configuration.dm +++ b/code/__DEFINES/configuration.dm @@ -22,3 +22,5 @@ #define POLICYCONFIG_ON_DEFIB_LATE "ON_DEFIB_LATE" /// Displayed to pyroclastic slimes on spawn #define POLICYCONFIG_ON_PYROCLASTIC_SENTIENT "PYROCLASTIC_SLIME" +/// Displayed to pAIs on spawn +#define POLICYCONFIG_PAI "PAI_SPAWN" diff --git a/code/game/machinery/colormate.dm b/code/game/machinery/colormate.dm index 1f1c16248c..d059d492ae 100644 --- a/code/game/machinery/colormate.dm +++ b/code/game/machinery/colormate.dm @@ -44,7 +44,8 @@ icon_state = "colormate" /obj/machinery/gear_painter/Destroy() - inserted.forceMove(drop_location()) + if(inserted) //please i beg you do not drop nulls + inserted.forceMove(drop_location()) return ..() /obj/machinery/gear_painter/attackby(obj/item/I, mob/living/user) diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index 9a722feb6a..e7a9d51ebe 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -122,7 +122,10 @@ /obj/item/paicard/proc/setPersonality(mob/living/silicon/pai/personality) src.pai = personality src.add_overlay("pai-null") - + var/list/policies = CONFIG_GET(keyed_list/policyconfig) + var/policy = policies[POLICYCONFIG_PAI] + if(policy) + to_chat(personality, policy) playsound(loc, 'sound/effects/pai_boot.ogg', 50, 1, -1) audible_message("\The [src] plays a cheerful startup noise!") diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index 7f073567c5..743931fbdd 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -256,6 +256,8 @@ /datum/gas_reaction/fusion/react(datum/gas_mixture/air, datum/holder) var/turf/open/location + if (isopenturf(holder)) + return if (istype(holder,/datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet. var/datum/pipeline/fusion_pipenet = holder location = get_turf(pick(fusion_pipenet.members)) diff --git a/code/modules/client/verbs/aooc.dm b/code/modules/client/verbs/aooc.dm index 1a019bba80..182975d192 100644 --- a/code/modules/client/verbs/aooc.dm +++ b/code/modules/client/verbs/aooc.dm @@ -13,7 +13,7 @@ GLOBAL_VAR_INIT(normal_aooc_colour, "#ce254f") if(!mob) return - if(!(prefs.toggles & CHAT_OOC)) + if(!(prefs.chat_toggles & CHAT_OOC)) to_chat(src, " You have OOC muted.") return if(jobban_isbanned(mob, "OOC")) diff --git a/code/modules/clothing/under/suits.dm b/code/modules/clothing/under/suits.dm index b9f55e695a..7f0ecf3d70 100644 --- a/code/modules/clothing/under/suits.dm +++ b/code/modules/clothing/under/suits.dm @@ -138,3 +138,27 @@ icon_state = "greyturtle" item_state = "greyturtle" can_adjust = FALSE + +/obj/item/clothing/under/suit/turtle/purple + name = "purple turtleneck" + icon_state = "turtle_sci" + item_state = "turtle_sci" + can_adjust = FALSE + +/obj/item/clothing/under/suit/turtle/orange + name = "orange turtleneck" + icon_state = "turtle_eng" + item_state = "turtle_eng" + can_adjust = FALSE + +/obj/item/clothing/under/suit/turtle/red + name = "red turtleneck" + icon_state = "turtle_sec" + item_state = "turtle_sec" + can_adjust = FALSE + +/obj/item/clothing/under/suit/turtle/blue + name = "blue turtleneck" + icon_state = "turtle_med" + item_state = "turtle_med" + can_adjust = FALSE diff --git a/code/modules/events/holiday/vday.dm b/code/modules/events/holiday/vday.dm index 1da03623e6..df00f873b5 100644 --- a/code/modules/events/holiday/vday.dm +++ b/code/modules/events/holiday/vday.dm @@ -21,27 +21,6 @@ new /obj/item/reagent_containers/food/snacks/candyheart(B) new /obj/item/storage/fancy/heart_box(B) - var/list/valentines = list() - for(var/mob/living/M in GLOB.player_list) - if(!M.stat && M.client && M.mind && !HAS_TRAIT(M, TRAIT_NO_MIDROUND_ANTAG)) - valentines |= M - - - while(valentines.len) - var/mob/living/L = pick_n_take(valentines) - if(valentines.len) - var/mob/living/date = pick_n_take(valentines) - - - forge_valentines_objective(L, date) - forge_valentines_objective(date, L) - - if(valentines.len && prob(4)) - var/mob/living/notgoodenough = pick_n_take(valentines) - forge_valentines_objective(notgoodenough, date) - else - L.mind.add_antag_datum(/datum/antagonist/heartbreaker) - /proc/forge_valentines_objective(mob/living/lover,mob/living/date,var/chemLove = FALSE) lover.mind.special_role = "valentine" if (chemLove == TRUE) diff --git a/code/modules/events/supermatter_surge.dm b/code/modules/events/supermatter_surge.dm new file mode 100644 index 0000000000..d54fc4dcd2 --- /dev/null +++ b/code/modules/events/supermatter_surge.dm @@ -0,0 +1,23 @@ +/datum/round_event_control/supermatter_surge + name = "Supermatter Surge" + typepath = /datum/round_event/supermatter_surge + weight = 20 + max_occurrences = 4 + earliest_start = 10 MINUTES + +/datum/round_event_control/supermatter_surge/canSpawnEvent() + if(GLOB.main_supermatter_engine?.has_been_powered) + return ..() + +/datum/round_event/supermatter_surge + var/power = 2000 + +/datum/round_event/supermatter_surge/setup() + power = rand(200,4000) + +/datum/round_event/supermatter_surge/announce() + if(power > 800 || prob(round(power/8))) + priority_announce("Class [round(power/500) + 1] supermatter surge detected. Intervention may be required.", "Anomaly Alert") + +/datum/round_event/supermatter_surge/start() + GLOB.main_supermatter_engine.matter_power += power diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index e186364cff..aca727ad8d 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -97,6 +97,7 @@ if(myseed.mutatelist.len > 0) myseed.instability = (myseed.instability/2) mutatespecie() + return BULLET_ACT_HIT else return ..() diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index a7e305201d..600045e9c5 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -80,6 +80,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/list/inherent_traits = list() var/inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID + var/list/blacklisted_quirks = list() // Quirks that will be removed upon gaining this species, to be defined by species + var/list/removed_quirks = list() // Quirks that got removed due to being blacklisted, and will be restored when on_species_loss() is called + var/attack_verb = "punch" // punch-specific attack verb var/sound/attack_sound = 'sound/weapons/punch1.ogg' var/sound/miss_sound = 'sound/weapons/punchmiss.ogg' @@ -342,6 +345,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) for(var/X in inherent_traits) ADD_TRAIT(C, X, SPECIES_TRAIT) + //lets remove those conflicting quirks + remove_blacklisted_quirks(C) + if(TRAIT_VIRUSIMMUNE in inherent_traits) for(var/datum/disease/A in C.diseases) A.cure(FALSE) @@ -395,6 +401,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) for(var/X in inherent_traits) REMOVE_TRAIT(C, X, SPECIES_TRAIT) + // lets restore the quirks that got removed when gaining this species + restore_quirks(C) + C.remove_movespeed_modifier(/datum/movespeed_modifier/species) if(mutant_bodyparts["meat_type"]) @@ -424,6 +433,26 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src) +// shamelessly inspired by antag_datum.remove_blacklisted_quirks() +/datum/species/proc/remove_blacklisted_quirks(mob/living/carbon/C) + var/mob/living/L = C.mind?.current + if(istype(L)) + var/list/my_quirks = L.client?.prefs.all_quirks.Copy() + SSquirks.filter_quirks(my_quirks, blacklisted_quirks) + for(var/q in L.roundstart_quirks) + var/datum/quirk/Q = q + if(!(SSquirks.quirk_name_by_path(Q.type) in my_quirks)) + L.remove_quirk(Q.type) + removed_quirks += Q.type + +// restore any quirks that we removed +/datum/species/proc/restore_quirks(mob/living/carbon/C) + var/mob/living/L = C.mind?.current + if(istype(L)) + for(var/q in removed_quirks) + L.add_quirk(q) + + /datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour) H.remove_overlay(HAIR_LAYER) var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index 385dd94f04..57a11481d7 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -37,6 +37,7 @@ armor = 20 // 120 damage to KO a zombie, which kills it speedmod = 1.6 // they're very slow mutanteyes = /obj/item/organ/eyes/night_vision/zombie + blacklisted_quirks = list(/datum/quirk/nonviolent) var/heal_rate = 1 var/regen_cooldown = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index a584d34995..d087d9399a 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -424,7 +424,7 @@ Difficulty: Very Hard /obj/machinery/anomalous_crystal/honk //Strips and equips you as a clown. I apologize for nothing observer_desc = "This crystal strips and equips its targets as clowns." - possible_methods = list(ACTIVATE_MOB_BUMP, ACTIVATE_SPEECH) + possible_methods = list(ACTIVATE_TOUCH) //Because We love AOE transformations! activation_sound = 'sound/items/bikehorn.ogg' /obj/machinery/anomalous_crystal/honk/ActivationReaction(mob/user) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index 477483862b..cd7f2fe328 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -398,6 +398,14 @@ Difficulty: Medium crusher_loot = list() butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30) +/mob/living/simple_animal/hostile/megafauna/dragon/lesser/transformed //ash drake balanced around player control + name = "transformed ash drake" + desc = "A sentient being transformed into an ash drake" + mob_size = MOB_SIZE_HUMAN //prevents crusher vulnerability + move_force = MOVE_FORCE_NORMAL //stops them from destroying and unanchoring shit by walking into it + environment_smash = ENVIRONMENT_SMASH_STRUCTURES //no we dont want sentient megafauna be able to delete the entire station in a minute flat + damage_coeff = list(BRUTE = 0.7, BURN = 0.5, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) //200 health but not locked to standard movespeed, needs armor befitting of a dragon + /mob/living/simple_animal/hostile/megafauna/dragon/lesser/grant_achievement(medaltype,scoretype) return @@ -413,7 +421,8 @@ Difficulty: Medium if(L in hit_list || L == source) continue hit_list += L - L.adjustFireLoss(20) + L.adjustFireLoss(5) + L.adjust_fire_stacks(6) to_chat(L, "You're hit by [source]'s fire breath!") // deals damage to mechs diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm index ae0f5ea3ca..446fe80c7d 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm @@ -42,6 +42,8 @@ A.GiveTarget(target) A.friends = friends A.faction = faction.Copy() + if(!A == /mob/living/simple_animal/hostile/poison/bees/toxin) + A.my_creator = type ranged_cooldown = world.time + ranged_cooldown_time /mob/living/simple_animal/hostile/asteroid/hivelord/AttackingTarget() @@ -88,6 +90,7 @@ density = FALSE del_on_death = 1 var/swarming = FALSE + var/my_creator = null /mob/living/simple_animal/hostile/asteroid/hivelordbrood/Initialize() . = ..() @@ -205,11 +208,7 @@ /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/proc/infest(mob/living/carbon/human/H) visible_message("[name] burrows into the flesh of [H]!") - var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/L - if(HAS_TRAIT(H, TRAIT_DWARF)) //dwarf legions aren't just fluff! - L = new /mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf(H.loc) - else - L = new(H.loc) + var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/L = check_infest_type(H) visible_message("[L] staggers to [L.p_their()] feet!") H.death() H.adjustBruteLoss(1000) @@ -217,6 +216,20 @@ H.forceMove(L) qdel(src) +/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/proc/check_infest_type(mob/living/carbon/human/human) + var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/L + var/list/blacklisted_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf) + if(HAS_TRAIT(human, TRAIT_DWARF)) //dwarf legions aren't just fluff! + L = new /mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf(human.loc) + else if(my_creator) + if(my_creator in blacklisted_types) + L = new(human.loc) + else + L = new my_creator(human.loc) + else + L = new(human.loc) + return L + //Advanced Legion is slightly tougher to kill and can raise corpses (revive other legions) /mob/living/simple_animal/hostile/asteroid/hivelord/legion/advanced stat_attack = DEAD diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index e49bd5162b..fcaa77cac4 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -178,10 +178,7 @@ new /obj/effect/temp_visual/monkeyify/humanify(loc) - transformation_timer = addtimer(CALLBACK(src, .proc/finish_humanize, tr_flags), TRANSFORMATION_DURATION, TIMER_UNIQUE) - -/mob/living/carbon/proc/finish_humanize(tr_flags) - transformation_timer = null + sleep(TRANSFORMATION_DURATION) //This entire proc CANNOT be split into two var/list/stored_implants = list() var/list/int_organs = list() diff --git a/code/modules/spells/spell_types/shapeshift.dm b/code/modules/spells/spell_types/shapeshift.dm index e513865246..67c2e3e941 100644 --- a/code/modules/spells/spell_types/shapeshift.dm +++ b/code/modules/spells/spell_types/shapeshift.dm @@ -78,7 +78,7 @@ desc = "Take on the shape a lesser ash drake." invocation = "RAAAAAAAAWR!" - shapeshift_type = /mob/living/simple_animal/hostile/megafauna/dragon/lesser + shapeshift_type = /mob/living/simple_animal/hostile/megafauna/dragon/lesser/transformed /obj/shapeshift_holder diff --git a/config/policy.txt b/config/policy.txt index 610acd2be8..502b525ad0 100644 --- a/config/policy.txt +++ b/config/policy.txt @@ -3,7 +3,10 @@ ## ON_CLONE - displayed after a successful cloning operation to the cloned person ## ON_DEFIB_INTACT - displayed after defibbing before memory loss time threshold ## ON_DEFIB_LATE - displayed after defibbing post memory loss time threshold -## +## SDGF - displayed on SDGF clone spawning +## SDGF_GOOD - displayed on SDGF clone spawning, if the clone is loyal +## SDGF_BAD - displayed on SDGF clone spawning, if the clone is not loyal +## PAI - displayed on PAI personality being loaded ## EXAMPLE: ## POLICYCONFIG ON_CLONE insert text here span classes are fully supported diff --git a/html/changelog.html b/html/changelog.html index 65e2d571a2..c387dc4058 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -50,6 +50,28 @@ -->