Merge remote-tracking branch 'origin/master' into luciee

This commit is contained in:
Katherine Kiefer
2022-05-22 20:04:32 +10:00
91 changed files with 1165 additions and 398 deletions

View File

@@ -1,13 +1,28 @@
Any time you make a change to the schema files, remember to increment the database schema version. Generally increment the minor number, major should be reserved for significant changes to the schema. Both values go up to 255.
The latest database version is 5.6; The query to update the schema revision table is:
The latest database version is 5.10; The query to update the schema revision table is:
INSERT INTO `schema_revision` (`major`, `minor`) VALUES (5, 9);
INSERT INTO `schema_revision` (`major`, `minor`) VALUES (5, 10);
or
INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (5, 9);
INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (5, 10);
In any query remember to add a prefix to the table names if you use one.
version 5.10 2022-05-18, alexkar598
Adds credentials binding
CREATE TABLE `bound_credentials` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ckey` varchar(32) NOT NULL,
`computerid` varchar(32) DEFAULT NULL,
`ip` int(10) unsigned DEFAULT NULL,
`flags` set('bypass_bans') DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_ckey_lookup` (`ckey`),
KEY `idx_cid_lookup` (`computerid`),
KEY `idx_ip_lookup` (`ip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
version 5.9 23 November 2021, by adamsogm
Adds the datetime column to the primary key for the MFA table

View File

@@ -116,6 +116,19 @@ CREATE TABLE IF NOT EXISTS `ban` (
) ENGINE=InnoDB AUTO_INCREMENT=39587 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `bound_credentials`;
CREATE TABLE `bound_credentials` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ckey` varchar(32) NOT NULL,
`computerid` varchar(32) DEFAULT NULL,
`ip` int(10) unsigned DEFAULT NULL,
`flags` set('bypass_bans') DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_ckey_lookup` (`ckey`),
KEY `idx_cid_lookup` (`computerid`),
KEY `idx_ip_lookup` (`ip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `connection_log`;
CREATE TABLE IF NOT EXISTS `connection_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,

View File

@@ -116,6 +116,18 @@ CREATE TABLE IF NOT EXISTS `SS13_ban` (
KEY `idx_ban_count` (`bantime`,`a_ckey`,`applies_to_admins`,`unbanned_datetime`,`expiration_time`)
) ENGINE=InnoDB AUTO_INCREMENT=39587 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_bound_credentials`;
CREATE TABLE `SS13_bound_credentials` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ckey` varchar(32) NOT NULL,
`computerid` varchar(32) DEFAULT NULL,
`ip` int(10) unsigned DEFAULT NULL,
`flags` set('bypass_bans') DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_ckey_lookup` (`ckey`),
KEY `idx_cid_lookup` (`computerid`),
KEY `idx_ip_lookup` (`ip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `SS13_connection_log`;
CREATE TABLE IF NOT EXISTS `SS13_connection_log` (

View File

@@ -25012,6 +25012,13 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/central)
"cCz" = (
/obj/machinery/light{
dir = 8
},
/obj/machinery/suit_storage_unit/captain,
/turf/open/floor/wood,
/area/crew_quarters/heads/captain)
"cCF" = (
/obj/machinery/air_sensor{
id_tag = "n2o_sensor"
@@ -29005,6 +29012,16 @@
/obj/structure/disposalpipe/segment,
/turf/open/floor/plasteel/white,
/area/medical/virology)
"eGj" = (
/obj/item/radio/intercom{
dir = 8;
freerange = 1;
name = "Station Intercom (Command)";
pixel_x = -28
},
/obj/structure/filingcabinet,
/turf/open/floor/wood,
/area/crew_quarters/heads/captain)
"eGz" = (
/obj/item/radio/intercom{
name = "Station Intercom (General)";
@@ -31087,16 +31104,6 @@
},
/turf/open/floor/plasteel,
/area/crew_quarters/dorms)
"fNu" = (
/obj/item/radio/intercom{
dir = 8;
freerange = 1;
name = "Station Intercom (Command)";
pixel_x = -28
},
/obj/machinery/suit_storage_unit/captain,
/turf/open/floor/wood,
/area/crew_quarters/heads/captain)
"fNw" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{
dir = 10
@@ -39967,6 +39974,14 @@
},
/turf/open/floor/plasteel/freezer,
/area/crew_quarters/toilet/locker)
"kgY" = (
/obj/machinery/recharger/wallrecharger{
pixel_x = -21;
pixel_y = -3
},
/obj/machinery/papershredder,
/turf/open/floor/wood,
/area/crew_quarters/heads/captain)
"khm" = (
/obj/effect/turf_decal/stripes,
/obj/structure/railing/corner,
@@ -60467,14 +60482,6 @@
/obj/item/book/manual/wiki/surgery,
/turf/open/floor/plasteel/white,
/area/medical/surgery)
"urw" = (
/obj/structure/filingcabinet,
/obj/machinery/recharger/wallrecharger{
pixel_x = -21;
pixel_y = -3
},
/turf/open/floor/wood,
/area/crew_quarters/heads/captain)
"urG" = (
/obj/structure/closet/emcloset,
/obj/machinery/atmospherics/components/unary/vent_pump/layer2{
@@ -62673,13 +62680,6 @@
/obj/effect/turf_decal/trimline/blue/filled/corner,
/turf/open/floor/plasteel/white,
/area/medical/storage)
"vCQ" = (
/obj/machinery/light{
dir = 8
},
/obj/machinery/papershredder,
/turf/open/floor/wood,
/area/crew_quarters/heads/captain)
"vCX" = (
/obj/structure/janitorialcart,
/obj/effect/turf_decal/delivery,
@@ -98907,10 +98907,10 @@ aZV
fqv
ruZ
nCL
vCQ
cCz
wxL
urw
fNu
kgY
eGj
aZV
aZV
aZV

View File

@@ -32,10 +32,17 @@
/// blob gets a free reroll every X time
#define BLOB_REROLL_TIME 2400
#define BLOB_SPREAD_COST 4
#define OVERMIND_STARTING_AUTO_PLACE_TIME 6 MINUTES
/// blob refunds this much if it attacks and doesn't spread
#define BLOB_ATTACK_REFUND 2
#define BLOB_REFLECTOR_COST 15
/// Forces the blob to place the core where they currently are, ignoring any checks.
#define BLOB_FORCE_PLACEMENT -1
/// Normal blob placement, does the regular checks to make sure the blob isn't placing itself in an invalid location
#define BLOB_NORMAL_PLACEMENT 0
/// Selects a random location for the blob to be placed.
#define BLOB_RANDOM_PLACEMENT 1
//ERT Types
#define ERT_BLUE "Blue"

View File

@@ -60,6 +60,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
/// Blocks ruins spawning on the turf
#define NO_RUINS_1 (1<<10)
/// If blobs can spawn there and if it counts towards their score.
#define BLOBS_ALLOWED (1<<1)
/*
These defines are used specifically with the atom/pass_flags bitmask
the atom/checkpass() proc uses them (tables will call movable atom checkpass(PASSTABLE) for example)

View File

@@ -21,7 +21,7 @@
* make sure you add an update to the schema_version stable in the db changelog
*/
#define DB_MINOR_VERSION 9
#define DB_MINOR_VERSION 10
//! ## Timing subsystem
/**

View File

@@ -18,4 +18,6 @@
#define DARKSPAWN_BRIGHT_LIGHT 0.3 //light of this intensity causes rapid burn damage
#define DARKSPAWN_DARK_HEAL 5 //how much damage of each type (with fire damage half rate) is healed in the dark
#define DARKSPAWN_LIGHT_BURN 7 //how much damage the darkspawn receives per tick in lit areas
#define DARKSPAWN_LIGHT_BURN 7 //how much damage the darkspawn receives per tick in lit areas
#define MONKIFY_BLOOD_COEFFICIENT (BLOOD_VOLUME_MONKEY/BLOOD_VOLUME_GENERIC) //the ratio of monkey to human blood volume so a 100% blood volume monkey will not instantly die when you turn it into a human with ~58% blood volume

View File

@@ -241,9 +241,9 @@ If you're feeling frisky, examine yourself and click the underlined item to pull
icon_state = "embeddedobject"
/obj/screen/alert/embeddedobject/Click()
if(isliving(usr))
var/mob/living/carbon/human/M = usr
return M.help_shake_act(M)
if(iscarbon(usr))
var/mob/living/carbon/C = usr
return C.try_remove_embedded_object(C)
/obj/screen/alert/weightless
name = "Weightless"

View File

@@ -48,7 +48,7 @@
if(isovermind(usr))
var/mob/camera/blob/B = usr
if(!B.placed)
B.place_blob_core(0)
B.place_blob_core(BLOB_NORMAL_PLACEMENT)
B.transport_core()
/obj/screen/blob/Blobbernaut

View File

@@ -371,7 +371,7 @@
name = "Depleted Uranium Slug Shell"
result = /obj/item/ammo_casing/shotgun/uraniumpenetrator
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1,
/datum/material/uranium = 3,
/obj/item/stack/sheet/mineral/uranium = 3,
/obj/item/stack/rods = 2,
/datum/reagent/thermite = 5)
tools = list(TOOL_SCREWDRIVER)

View File

@@ -0,0 +1,54 @@
/datum/disease/plague
form = "Disease"
name = "Plague"
max_stages = 5
spread_text = "Airborne"
cure_text = "Spaceacillin"
cures = list(/datum/reagent/medicine/spaceacillin)
agent = "Plague rats"
viable_mobtypes = list(/mob/living/carbon/human)
cure_chance = 20
desc = "A deadly disease, spread by infected animals and insects. It causes fever, weakness, headache and choking."
required_organs = list(/obj/item/organ/lungs)
severity = DISEASE_SEVERITY_BIOHAZARD
bypasses_immunity = TRUE
/datum/disease/tuberculosis/stage_act()
..()
switch(stage)
if(2)
if(prob(2))
affected_mob.emote("cough")
to_chat(affected_mob, span_danger("Your chest hurts."))
if(prob(2))
to_chat(affected_mob, span_danger("Your head pounds."))
if(4)
if(prob(2))
to_chat(affected_mob, span_userdanger("You can't keep steady!"))
affected_mob.Dizzy(5)
if(prob(2))
to_chat(affected_mob, span_danger("You can barely breathe!"))
affected_mob.adjustOxyLoss(5)
affected_mob.emote("gasp")
if(prob(10))
to_chat(affected_mob, span_danger("You can't breathe!"))
affected_mob.adjustOxyLoss(20)
affected_mob.emote("gasp")
if(prob(2))
to_chat(affected_mob, span_danger("You feel weak!"))
affected_mob.adjustStaminaLoss(40)
if(5)
if(prob(10))
affected_mob.vomit(20)
if(prob(15))
affected_mob.adjust_bodytemperature(30)
to_chat(affected_mob, span_danger("You feel hot!"))
if(prob(2))
to_chat(affected_mob, span_danger("You feel very weak!"))
affected_mob.adjustStaminaLoss(100)
if(prob(6))
to_chat(affected_mob, span_danger("Your lungs feel full of fluid! You're unable to breathe!"))
affected_mob.adjustOxyLoss(35)
affected_mob.emote("gasp")
return

View File

@@ -92,14 +92,18 @@
/datum/mutation/human/dwarfism/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
owner.transform = owner.transform.Scale(1, 0.8)
var/matrix/new_transform = matrix()
new_transform.Scale(1, 0.8)
owner.transform = new_transform.Multiply(owner.transform)
passtable_on(owner, GENETIC_MUTATION)
owner.visible_message(span_danger("[owner] suddenly shrinks!"), span_notice("Everything around you seems to grow.."))
/datum/mutation/human/dwarfism/on_losing(mob/living/carbon/human/owner)
if(..())
return
owner.transform = owner.transform.Scale(1, 1.25)
var/matrix/new_transform = matrix()
new_transform.Scale(1, 1.25)
owner.transform = new_transform.Multiply(owner.transform)
passtable_off(owner, GENETIC_MUTATION)
owner.visible_message(span_danger("[owner] suddenly grows!"), span_notice("Everything around you seems to shrink.."))

View File

@@ -493,7 +493,7 @@
. = FALSE
if(destination)
var/turf/new_turf = get_turf(destination)
if(ismob(src))
if(new_turf && ismob(src))
var/mob/M = src
if(is_secret_level(new_turf.z) && !M.client?.holder)
return

View File

@@ -361,7 +361,7 @@
enemy_roles = list("Security Officer", "Detective", "Head of Security", "Captain")
required_enemies = list(2,2,1,1,1,1,1,0,0,0)
required_candidates = 1
weight = 4
weight = 2
cost = 10
requirements = list(100,100,100,80,60,50,45,30,20,20)
repeatable = TRUE
@@ -370,6 +370,41 @@
var/body = applicant.become_overmind()
return body
// Infects a random player, making them explode into a blob.
/datum/dynamic_ruleset/midround/blob_infection
name = "Blob Infection"
antag_datum = /datum/antagonist/blob
antag_flag = ROLE_BLOB
protected_roles = list("Prisoner", "Security Officer", "Warden", "Detective", "Head of Security", "Captain")
restricted_roles = list("Cyborg", "AI", "Positronic Brain")
enemy_roles = list("Security Officer", "Detective", "Head of Security", "Captain")
required_enemies = list(2,2,1,1,1,1,1,0,0,0)
required_candidates = 1
weight = 2
cost = 10
requirements = list(101,101,101,80,60,50,30,20,10,10)
repeatable = TRUE
/datum/dynamic_ruleset/midround/blob_infection/trim_candidates()
..()
candidates = living_players
for(var/mob/living/player as anything in candidates)
var/turf/player_turf = get_turf(player)
if(!player_turf || !is_station_level(player_turf.z))
candidates -= player
continue
if(player.mind && (player.mind.special_role || length(player.mind.antag_datums) > 0))
candidates -= player
/datum/dynamic_ruleset/midround/blob_infection/execute()
if(!candidates || !candidates.len)
return FALSE
var/mob/living/carbon/human/blob_antag = pick_n_take(candidates)
assigned += blob_antag.mind
blob_antag.mind.special_role = antag_flag
return ..()
//////////////////////////////////////////////
// //
// XENOMORPH (GHOST) //
@@ -653,3 +688,109 @@
message_admins("[ADMIN_LOOKUPFLW(selected_mobs)] was selected by the [name] ruleset and has been made into a midround Bloodsucker.")
log_game("DYNAMIC: [key_name(selected_mobs)] was selected by the [name] ruleset and has been made into a midround Bloodsucker.")
return TRUE
/// Revenant ruleset
/datum/dynamic_ruleset/midround/from_ghosts/revenant
name = "Revenant"
antag_datum = /datum/antagonist/revenant
antag_flag = "Revenant"
antag_flag_override = ROLE_REVENANT
enemy_roles = list("Security Officer", "Detective", "Head of Security", "Captain")
required_enemies = list(2,2,1,1,1,1,1,0,0,0)
required_candidates = 1
weight = 4
cost = 10
requirements = list(101,101,101,70,50,40,20,15,10,10)
repeatable = TRUE
var/dead_mobs_required = 20
var/need_extra_spawns_value = 15
var/list/spawn_locs = list()
/datum/dynamic_ruleset/midround/from_ghosts/revenant/acceptable(population=0, threat=0)
if(GLOB.dead_mob_list.len < dead_mobs_required)
return FALSE
return ..()
/datum/dynamic_ruleset/midround/from_ghosts/revenant/execute()
for(var/mob/living/corpse in GLOB.dead_mob_list) //look for any dead bodies
var/turf/corpse_turf = get_turf(corpse)
if(corpse_turf && is_station_level(corpse_turf.z))
spawn_locs += corpse_turf
if(!spawn_locs.len || spawn_locs.len < need_extra_spawns_value) //look for any morgue trays, crematoriums, ect if there weren't alot of dead bodies on the station to pick from
for(var/obj/structure/bodycontainer/corpse_container in GLOB.bodycontainers)
var/turf/container_turf = get_turf(corpse_container)
if(container_turf && is_station_level(container_turf.z))
spawn_locs += container_turf
if(!spawn_locs.len) //If we can't find any valid spawnpoints, try the carp spawns
for(var/obj/effect/landmark/carpspawn/carp_spawnpoint in GLOB.landmarks_list)
if(isturf(carp_spawnpoint.loc))
spawn_locs += carp_spawnpoint.loc
if(!spawn_locs.len) //If we can't find THAT, then just give up and cry
return FALSE
. = ..()
/datum/dynamic_ruleset/midround/from_ghosts/revenant/generate_ruleset_body(mob/applicant)
var/mob/living/simple_animal/revenant/revenant = new(pick(spawn_locs))
revenant.key = applicant.key
message_admins("[ADMIN_LOOKUPFLW(revenant)] has been made into a revenant by the midround ruleset.")
log_game("[key_name(revenant)] was spawned as a revenant by the midround ruleset.")
return revenant
/// Sentient Disease ruleset
/datum/dynamic_ruleset/midround/from_ghosts/sentient_disease
name = "Sentient Disease"
antag_datum = /datum/antagonist/disease
antag_flag = "Sentient Disease"
antag_flag_override = ROLE_ALIEN
required_candidates = 1
weight = 4
cost = 10
requirements = list(101,101,101,80,60,50,30,20,10,10)
repeatable = TRUE
/datum/dynamic_ruleset/midround/from_ghosts/sentient_disease/generate_ruleset_body(mob/applicant)
var/mob/camera/disease/virus = new /mob/camera/disease(SSmapping.get_station_center())
virus.key = applicant.key
INVOKE_ASYNC(virus, /mob/camera/disease/proc/pick_name)
message_admins("[ADMIN_LOOKUPFLW(virus)] has been made into a sentient disease by the midround ruleset.")
log_game("[key_name(virus)] was spawned as a sentient disease by the midround ruleset.")
return virus
/// Obsessed ruleset
/datum/dynamic_ruleset/midround/obsessed
name = "Obsessed"
antag_datum = /datum/antagonist/obsessed
antag_flag = ROLE_OBSESSED
restricted_roles = list("Cyborg", "AI", "Positronic Brain")
enemy_roles = list("Security Officer", "Detective", "Head of Security", "Captain")
required_enemies = list(2,2,1,1,1,1,1,0,0,0)
required_candidates = 1
weight = 4
cost = 10
requirements = list(101,101,101,80,60,50,30,20,10,10)
repeatable = TRUE
/datum/dynamic_ruleset/midround/obsessed/trim_candidates()
..()
candidates = living_players
for(var/mob/living/carbon/human/candidate in candidates)
if( \
!candidate.getorgan(/obj/item/organ/brain) \
|| candidate.mind.has_antag_datum(/datum/antagonist/obsessed) \
|| candidate.stat == DEAD \
|| !(ROLE_OBSESSED in candidate.client?.prefs?.be_special) \
|| !SSjob.GetJob(candidate.mind.assigned_role) \
|| (candidate.mind.assigned_role in GLOB.nonhuman_positions) \
)
candidates -= candidate
/datum/dynamic_ruleset/midround/obsessed/execute()
if(!candidates || !candidates.len)
return FALSE
var/mob/living/carbon/human/obsessed = pick_n_take(candidates)
obsessed.gain_trauma(/datum/brain_trauma/special/obsessed)
message_admins("[ADMIN_LOOKUPFLW(obsessed)] has been made Obsessed by the midround ruleset.")
log_game("[key_name(obsessed)] was made Obsessed by the midround ruleset.")
return ..()

View File

@@ -153,7 +153,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
item_flags |= FORCE_STRING_OVERRIDE
if(!hitsound)
if(damtype == FIRE)
if(damtype == BURN)
hitsound = 'sound/items/welder.ogg'
if(damtype == "brute")
hitsound = "swing_hit"
@@ -878,3 +878,20 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
if(ismob(loc))
var/mob/mob_loc = loc
mob_loc.regenerate_icons()
/**
* Called when this object is first embedded into a carbon
*/
/obj/item/proc/on_embed(mob/living/carbon/human/embedde, obj/item/bodypart/part)
return TRUE
/**
* Called when this object is no longer embedded into a carbon
*/
/obj/item/proc/on_embed_removal(mob/living/carbon/human/embedde)
return TRUE
/**
* Called every life tick when the object is embedded in a carbon
*/
/obj/item/proc/embed_tick(mob/living/carbon/human/embedde, obj/item/bodypart/part)
return

View File

@@ -42,7 +42,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
playsound(src, "sound/items/match_strike.ogg", 15, TRUE)
lit = TRUE
icon_state = "match_lit"
damtype = FIRE
damtype = BURN
force = 3
hitsound = 'sound/items/welder.ogg'
item_state = "cigon"
@@ -183,7 +183,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
name = "lit [name]"
attack_verb = list("burnt", "singed")
hitsound = 'sound/items/welder.ogg'
damtype = FIRE
damtype = BURN
force = 4
if(reagents.get_reagent_amount(/datum/reagent/toxin/plasma)) // the plasma explodes when exposed to fire
var/datum/effect_system/reagents_explosion/e = new()
@@ -588,7 +588,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
lit = new_lit
if(lit)
force = 5
damtype = FIRE
damtype = BURN
hitsound = 'sound/items/welder.ogg'
attack_verb = list("burnt", "singed")
set_light(1)

View File

@@ -339,7 +339,7 @@
force = on_damage
name = "lit [initial(src.name)]"
desc = "[initial(src.desc)] This one is lit."
damtype = FIRE
damtype = BURN
attack_verb = list("burnt","scorched","scalded")
hitsound = 'sound/items/welder.ogg'
START_PROCESSING(SSobj, src)

View File

@@ -153,7 +153,7 @@
icon = 'icons/obj/supermatter_delaminator.dmi'
icon_state = "antinoblium_tongs"
toolspeed = 0.75
damtype = FIRE
damtype = BURN
var/obj/item/supermatter_delaminator/antinoblium_shard/shard
/obj/item/hemostat/antinoblium/Destroy()

View File

@@ -201,7 +201,7 @@
icon = 'icons/obj/nuke_tools.dmi'
icon_state = "supermatter_scalpel"
toolspeed = 0.5
damtype = FIRE
damtype = BURN
usesound = 'sound/weapons/bladeslice.ogg'
var/usesLeft
@@ -215,7 +215,7 @@
icon = 'icons/obj/nuke_tools.dmi'
icon_state = "supermatter_tongs"
toolspeed = 0.75
damtype = FIRE
damtype = BURN
var/obj/item/nuke_core/supermatter_sliver/sliver
/obj/item/hemostat/supermatter/Destroy()

View File

@@ -75,7 +75,7 @@
//Welders left on now use up fuel, but lets not have them run out quite that fast
if(1)
force = 15
damtype = FIRE
damtype = BURN
++burned_fuel_for
if(burned_fuel_for >= WELDER_FUEL_BURN_INTERVAL)
use(1)
@@ -172,7 +172,7 @@
to_chat(user, span_notice("You switch [src] on."))
playsound(loc, acti_sound, 50, 1)
force = 15
damtype = FIRE
damtype = BURN
hitsound = 'sound/items/welder.ogg'
update_icon()
START_PROCESSING(SSobj, src)

View File

@@ -22,7 +22,7 @@
var/scan_state = "" //Holder for the image we display when we're pinged by a mining scanner
var/defer_change = FALSE
var/hardness = 1 //how hard the material is, we'll have to have more powerful stuff if we want to blast harder materials.
/turf/closed/mineral/Initialize()
if (!canSmoothWith)
canSmoothWith = list(/turf/closed/mineral, /turf/closed/indestructible)
@@ -695,9 +695,12 @@
. = ..()
/turf/closed/mineral/gibtonite/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/t_scanner/adv_mining_scanner/goat_scanner) && stage == 1)
user.visible_message(span_notice("[user] holds [I] to [src]..."), span_notice("[I] locates where to cut off the chain reaction and stops it."))
defuse(force_perfect = TRUE)
if(istype(I, /obj/item/mining_scanner) || istype(I, /obj/item/t_scanner/adv_mining_scanner) && stage == 1)
user.visible_message(span_notice("[user] holds [I] to [src]..."), span_notice("You use [I] to locate where to cut off the chain reaction and attempt to stop it..."))
defuse()
defuse(force_perfect = FALSE)
..()
/turf/closed/mineral/gibtonite/proc/explosive_reaction(mob/user = null, triggered_by_explosion = 0)
@@ -732,13 +735,17 @@
stage = GIBTONITE_DETONATE
explosion(bombturf,1,3,5, adminlog = notify_admins)
/turf/closed/mineral/gibtonite/proc/defuse()
/turf/closed/mineral/gibtonite/proc/defuse(force_perfect = FALSE)
if(stage == GIBTONITE_ACTIVE)
cut_overlay(activated_overlay)
activated_overlay.icon_state = "rock_Gibtonite_inactive"
add_overlay(activated_overlay)
desc = "An inactive gibtonite reserve. The ore can be extracted."
stage = GIBTONITE_STABLE
if(force_perfect)
det_time = 0
visible_message(span_notice("The chain reaction was stopped at its highest potency!"))
return
if(det_time < 0)
det_time = 0
visible_message(span_notice("The chain reaction was stopped! The gibtonite had [det_time] reactions left till the explosion!"))
@@ -814,4 +821,3 @@
/turf/closed/mineral/magmite/volcanic/hard
smooth_icon = 'icons/turf/smoothrocks_hard.dmi'
hardness = 2

View File

@@ -94,6 +94,49 @@ Yogs End*/
if (message)
message_admins(msg)
else
if(!real_bans_only)
var/datum/DBQuery/query_get_bound_creds = SSdbcore.NewQuery({"
SELECT
ckey,
ip,
computerid
FROM [format_table_name("bound_credentials")]
WHERE
(ip = INET_ATON(:ip) OR computerid = :computerid)
"}, list("ckey" = ckey, "ip" = address, "computerid" = computer_id))
if(!query_get_bound_creds.warn_execute())
qdel(query_get_bound_creds)
return
//Null = unchecked, false = verified, true = reject
var/reject_bound_cid
var/reject_bound_ip
while(query_get_bound_creds.NextRow())
var/bound_ckey = query_get_bound_creds.item[1]
var/bound_ip = query_get_bound_creds.item[2]
var/bound_cid = query_get_bound_creds.item[3]
//We have yet to confirm the ip and this entry specifies one
if(bound_ip && (reject_bound_ip != FALSE))
//If it matches, we set it to false and we stop checking bound ips
// Otherwise, we set it to true and it will reject the login if no bound ip is found
reject_bound_ip = (bound_ckey != ckey)
//Same logic but for cids
if(bound_cid && (reject_bound_cid != FALSE))
reject_bound_cid = (bound_ckey != ckey)
if(reject_bound_cid || reject_bound_ip)
var/cause = reject_bound_cid ? "computer ID" : "IP address"
var/msg = {"This [cause] has been bound to another account.
Please visit [CONFIG_GET(string/banappeals) || "the forums"] if this was done in error or if you have recently changed BYOND accounts."}
log_access("Failed Login: [key] [computer_id] [address] - Bound [cause]")
key_cache[key] = 0
return list("reason" = "bound [cause]", "desc" = msg)
qdel(query_get_bound_creds)
var/list/ban_details = is_banned_from_with_details(ckey, address, computer_id, "Server")
for(var/i in ban_details)
if(admin)

View File

@@ -52,8 +52,33 @@
//checks DB ban table if a ckey, ip and/or cid is banned from a specific role
//returns an associative nested list of each matching row's ban id, bantime, ban round id, expiration time, ban duration, applies to admins, reason, key, ip, cid and banning admin's key in that order
/proc/is_banned_from_with_details(player_ckey, player_ip, player_cid, role)
var/datum/DBQuery/query_get_bypass_creds = SSdbcore.NewQuery({"
SELECT
computerid,
INET_NTOA(ip)
FROM [format_table_name("bound_credentials")]
WHERE
ckey = :ckey AND
FIND_IN_SET('bypass_bans', [format_table_name("bound_credentials")].flags)
"}, list("ckey" = player_ckey));
if(!query_get_bypass_creds.warn_execute())
qdel(query_get_bypass_creds)
return
while(query_get_bypass_creds.NextRow())
var/bound_cid = query_get_bypass_creds.item[1]
var/bound_ip = query_get_bypass_creds.item[2]
//If we bypass, set the thing to null so that we can not check it
if(bound_cid == player_cid)
player_cid = null
if(bound_ip == player_ip)
player_ip = null
qdel(query_get_bypass_creds)
if(!player_ckey && !player_ip && !player_cid)
return
var/datum/DBQuery/query_check_ban = SSdbcore.NewQuery({"
SELECT
id,

View File

@@ -22,13 +22,25 @@
return basic_report
/datum/antagonist/blob/greet()
to_chat(owner.current, span_notice("<font color=\"#EE4000\">You are the Blob!</font>"))
owner.announce_objectives()
if(!isovermind(owner.current))
to_chat(owner,span_userdanger("You feel bloated."))
to_chat(owner.current, span_notice("Use the pop ability to place your blob core! It is recommended you do this away from anyone else, as you'll be taking on the entire crew!"))
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/blobalert.ogg', 100, FALSE, pressure_affected = FALSE)
/datum/antagonist/blob/on_gain()
create_objectives()
. = ..()
/datum/antagonist/blob/remove_innate_effects()
QDEL_NULL(pop_action)
return ..()
/datum/antagonist/blob/farewell()
to_chat(owner.current, "<span class='alertsyndie'><font color=\"#EE4000\">You are no longer the Blob!</font></span>")
return ..()
/datum/antagonist/blob/proc/create_objectives()
var/datum/objective/blob_takeover/main = new
main.owner = owner
@@ -49,21 +61,49 @@
desc = "Unleash the blob"
icon_icon = 'icons/mob/blob.dmi'
button_icon_state = "blob"
var/autoplace_time = OVERMIND_STARTING_AUTO_PLACE_TIME
/datum/action/innate/blobpop/Activate()
/datum/action/innate/blobpop/Grant(Target)
. = ..()
if(owner)
addtimer(CALLBACK(src, .proc/Activate, TRUE), autoplace_time, TIMER_UNIQUE|TIMER_OVERRIDE)
to_chat(owner, "<span class='big'><font color=\"#EE4000\">You will automatically pop and place your blob core in [DisplayTimeText(autoplace_time)].</font></span>")
/datum/action/innate/blobpop/Activate(timer_activated = FALSE)
var/mob/old_body = owner
if(!owner)
return
var/datum/antagonist/blob/blobtag = owner.mind.has_antag_datum(/datum/antagonist/blob)
if(!blobtag)
Remove()
Remove(owner)
return
var/mob/camera/blob/B = new /mob/camera/blob(get_turf(old_body), blobtag.starting_points_human_blob)
owner.mind.transfer_to(B)
. = TRUE
var/turf/target_turf = get_turf(owner)
if(target_turf.density)
to_chat(owner, "<span class='warning'>This spot is too dense to place a blob core on!</span>")
. = FALSE
if(isspaceturf(target_turf) || !is_station_level(target_turf.z))
to_chat(owner, "<span class='warning'>You cannot place your core here!</span>")
. = FALSE
var/placement_override = BLOB_FORCE_PLACEMENT
if(!.)
if(!timer_activated)
return
placement_override = BLOB_RANDOM_PLACEMENT
to_chat(owner, "<span class='boldwarning'>Because your current location is an invalid starting spot and you need to pop, you've been moved to a random location!</span>")
var/mob/camera/blob/blob_cam = new /mob/camera/blob(get_turf(old_body), blobtag.starting_points_human_blob)
owner.mind.transfer_to(blob_cam)
old_body.gib()
B.place_blob_core(blobtag.point_rate_human_blob, pop_override = TRUE)
blob_cam.place_blob_core(placement_override, pop_override = TRUE)
playsound(get_turf(blob_cam), 'sound/ambience/antag/blobalert.ogg', 50, FALSE)
/datum/antagonist/blob/antag_listing_status()
. = ..()
if(owner && owner.current)
var/mob/camera/blob/B = owner.current
if(istype(B))
. += "(Progress: [B.blobs_legit.len]/[B.blobwincount])"
var/mob/camera/blob/blob_cam = owner.current
if(istype(blob_cam))
. += "(Progress: [length(blob_cam.blobs_legit)]/[blob_cam.blobwincount])"

View File

@@ -86,6 +86,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
//Quirk list
var/list/all_quirks = list()
var/mood_tail_wagging = TRUE
//Job preferences 2.0 - indexed by job title , no key or value implies never
var/list/job_preferences = list()
@@ -753,6 +755,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
//yogs start -- Mood preference toggling
if(CONFIG_GET(flag/disable_human_mood))
dat += "<b>Mood:</b> <a href='?_src_=prefs;preference=mood'>[yogtoggles & PREF_MOOD ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>Mood Tail Wagging:</b> <a href='?_src_=prefs;preference=moodtailwagging'>[mood_tail_wagging ? "Enabled" : "Disabled"] </a><br>"
//yogs end
dat += "</td><td width='300px' height='300px' valign='top'>"
@@ -2084,6 +2087,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("mood")
yogtoggles ^= PREF_MOOD
if("moodtailwagging")
mood_tail_wagging = !mood_tail_wagging
// yogs end
ShowChoices(user)

View File

@@ -232,6 +232,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
READ_FILE(S["yogtoggles"], yogtoggles)
READ_FILE(S["accent"], accent) // Accents, too!
READ_FILE(S["mood_tail_wagging"], mood_tail_wagging)
// yogs end
//try to fix any outdated data if necessary
@@ -368,6 +370,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["purrbation"], purrbation)
WRITE_FILE(S["accent"], accent) // Accents, too!
WRITE_FILE(S["mood_tail_wagging"], mood_tail_wagging)
// yogs end
save_keybindings(S) // yogs - Custom keybindings

View File

@@ -354,3 +354,10 @@
desc = "A relic from the past. Its effectiveness as a stylish hat was never debated."
icon_state = "unberet"
item_state = "unberet"
/obj/item/clothing/head/halo
name = "Transdimensional halo"
desc = "An aetherial halo that magically hovers above the head."
icon_state = "halo"
item_state = "halo"
layer = EARS_LAYER

View File

@@ -124,7 +124,7 @@
return 1
/datum/spacevine_mutation/fire_proof/on_hit(obj/structure/spacevine/holder, mob/hitter, obj/item/I, expected_damage)
if(I && I.damtype == FIRE)
if(I && I.damtype == BURN)
. = 0
else
. = expected_damage

View File

@@ -340,6 +340,19 @@
icon_state = "shadowmeat"
desc = "It is covered in a strange darkness. This slab's magical properties appear to be drastically weakened due to the synthetic nature of the meat."
/obj/item/reagent_containers/food/snacks/meat/slab/plagued
name = "meat"
desc = "A slab of disease-ridden meat. Eating it is a questionable idea."
icon_state = "meat"
dried_type = /obj/item/reagent_containers/food/snacks/sosjerky/
bitesize = 3
list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/cooking_oil = 2, /datum/reagent/plaguebacteria = 3) //It is infected by plague
slice_path = /obj/item/reagent_containers/food/snacks/meat/raw_cutlet/plain
slices_num = 3
filling_color = "#FF0000"
tastes = list("meat" = 2, "decay" = 1)
foodtype = MEAT | RAW
////////////////////////////////////// MEAT STEAKS ///////////////////////////////////////////////////////////
@@ -435,7 +448,7 @@
/obj/item/reagent_containers/food/snacks/meat/raw_cutlet/initialize_cooked_food(obj/item/reagent_containers/food/snacks/S, cooking_efficiency)
..()
S.name = "[meat_type] cutlet"
/obj/item/reagent_containers/food/snacks/meat/raw_cutlet/plain

View File

@@ -151,7 +151,7 @@
icon_state = "sunflower"
lefthand_file = 'icons/mob/inhands/weapons/plants_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/plants_righthand.dmi'
damtype = FIRE
damtype = BURN
force = 0
slot_flags = ITEM_SLOT_HEAD
throwforce = 0

View File

@@ -36,7 +36,7 @@
icon_state = "nettle"
lefthand_file = 'icons/mob/inhands/weapons/plants_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/plants_righthand.dmi'
damtype = FIRE
damtype = BURN
force = 15
wound_bonus = CANT_WOUND
hitsound = 'sound/weapons/bladeslice.ogg'

View File

@@ -54,6 +54,12 @@
range = 4
cooldown = 50
/obj/item/t_scanner/adv_mining_scanner/goat_scanner
desc = "An advanced scanner used by the goat king to sate his appetite for explosions; It allows the user to always receive high potency gibtonite after defusing them."
name = "goat king's scanner"
icon_state = "goat_mining0"
cooldown = 20
/obj/item/t_scanner/adv_mining_scanner/scan()
if(current_cooldown <= world.time)
current_cooldown = world.time + cooldown
@@ -85,3 +91,4 @@
/obj/effect/temp_visual/mining_overlay/Initialize()
. = ..()
animate(src, alpha = 0, time = duration, easing = EASE_IN)

View File

@@ -226,11 +226,19 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
GibtoniteReaction(user)
return
if(primed)
if(istype(I, /obj/item/t_scanner/adv_mining_scanner/goat_scanner))
primed = FALSE
if(det_timer)
deltimer(det_timer)
user.visible_message("The chain reaction was stopped... the ore's quality seems to have improved!", span_notice("You stopped the chain reaction... the ore's quality seems to have improved!"))
icon_state = "Gibtonite ore 3"
quality = GIBTONITE_QUALITY_HIGH
return
if(istype(I, /obj/item/mining_scanner) || istype(I, /obj/item/t_scanner/adv_mining_scanner) || I.tool_behaviour == TOOL_MULTITOOL)
primed = FALSE
if(det_timer)
deltimer(det_timer)
user.visible_message("The chain reaction was stopped! ...The ore's quality looks diminished.", span_notice("You stopped the chain reaction. ...The ore's quality looks diminished."))
user.visible_message("The chain reaction was stopped! ...The ore's quality looks diminished.", span_notice("You stopped the chain reaction... the ore's quality looks diminished."))
icon_state = "Gibtonite ore"
quality = GIBTONITE_QUALITY_LOW
return

View File

@@ -77,6 +77,7 @@
var/obj/item/bodypart/affecting = get_bodypart(check_zone(user.zone_selected))
if(user.a_intent != INTENT_HARM && I.tool_behaviour == TOOL_WELDER && affecting?.status == BODYPART_ROBOTIC)
user.changeNext_move(CLICK_CD_MELEE)
if(I.use_tool(src, user, 0, volume=50, amount=1))
if(user == src)
user.visible_message(span_notice("[user] starts to fix some of the dents on [src]'s [affecting.name]."),
@@ -273,6 +274,26 @@
visible_message(span_danger("[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name]."), \
span_userdanger("[usr] [internal ? "opens" : "closes"] the valve on [src]'s [ITEM.name]."))
// Embed Stuff
if(href_list["embedded_object"] && usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts
if(!L)
return
var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects
if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore
return
var/time_taken = I.embedding.embedded_unsafe_removal_time*I.w_class
usr.visible_message(span_warning("[usr] attempts to remove [I] from [usr.p_their()] [L.name]."),span_notice("You attempt to remove [I] from your [L.name]... (It will take [DisplayTimeText(time_taken)].)"))
if(do_after(usr, time_taken, needhand = 1, target = src))
if(!I || !L || I.loc != src)
return
var/damage_amount = I.embedding.embedded_unsafe_removal_pain_multiplier * I.w_class
L.receive_damage(damage_amount, sharpness = SHARP_EDGED)//It hurts to rip it out, get surgery you dingus.
if(remove_embedded_object(I, get_turf(src), damage_amount))
usr.put_in_hands(I)
usr.visible_message("[usr] successfully rips [I] out of [usr.p_their()] [L.name]!", span_notice("You successfully remove [I] from your [L.name]."))
return
/mob/living/carbon/fall(forced)
if(loc)
loc.handle_fall(src, forced)//it's loc so it doesn't call the mob's handle_fall which does nothing

View File

@@ -50,10 +50,15 @@
return TRUE
/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
if(!skipcatch) //ugly, but easy
if(can_catch_item())
if(istype(AM, /obj/item))
var/obj/item/I = AM
var/obj/item/I = AM
if(istype(I, /obj/item))
if(((throwingdatum ? throwingdatum.speed : I.throw_speed) >= EMBED_THROWSPEED_THRESHOLD) || I.embedding.embedded_ignore_throwspeed_threshold)
var/obj/item/bodypart/body_part = pick(bodyparts)
if(prob(clamp(I.embedding.embed_chance - run_armor_check(body_part, MELEE), 0, 100)) && embed_object(I, deal_damage = TRUE))
hitpush = FALSE
skipcatch = TRUE //can't catch the now embedded item
if(!skipcatch) //ugly, but easy
if(can_catch_item())
if(I.item_flags & UNCATCHABLE)
return FALSE
if(isturf(I.loc))
@@ -68,6 +73,83 @@
return TRUE
..()
/**
* Embeds an object into this carbon
*/
/mob/living/carbon/proc/embed_object(obj/item/embedding, part, deal_damage, silent, forced)
if(!(forced || (can_embed(embedding) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE))))
return FALSE
var/obj/item/bodypart/body_part = part
// In case its a zone
if(!istype(body_part) && body_part)
body_part = get_bodypart(body_part)
// Otherwise pick one
if(!istype(body_part))
body_part = pick(bodyparts)
// Thats probably not good
if(!istype(body_part))
return FALSE
if(!embedding.on_embed(src, body_part))
return
body_part.embedded_objects |= embedding
embedding.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
embedding.forceMove(src)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
if(deal_damage)
body_part.receive_damage(embedding.w_class*embedding.embedding.embedded_impact_pain_multiplier, wound_bonus=-30, sharpness = TRUE)
if(!silent)
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
visible_message(span_danger("[embedding] embeds itself in [src]'s [body_part.name]!"), span_userdanger("[embedding] embeds itself in your [body_part.name]!"))
return TRUE
/**
* Removes the given embedded object from this carbon
*/
/mob/living/carbon/proc/remove_embedded_object(obj/item/embedded, new_loc, silent, forced)
var/obj/item/bodypart/body_part
for(var/obj/item/bodypart/part in bodyparts)
if(embedded in part.embedded_objects)
body_part = part
if(!body_part)
return
if(!embedded.on_embed_removal(src))
return
body_part.embedded_objects -= embedded
if(!silent)
emote("scream")
if(!has_embedded_objects())
clear_alert("embeddedobject")
SEND_SIGNAL(usr, COMSIG_CLEAR_MOOD_EVENT, "embedded")
if(new_loc)
embedded.forceMove(new_loc)
return TRUE
/**
* Called when a mob tries to remove an embedded object from this carbon
*/
/mob/living/carbon/proc/try_remove_embedded_object(mob/user)
var/list/choice_list = list()
var/obj/item/bodypart/body_part
for(var/obj/item/bodypart/part in bodyparts)
for(var/obj/item/embedded in part.embedded_objects)
choice_list[embedded] = image(embedded)
var/obj/item/choice = show_radial_menu(user, src, choice_list, tooltips = TRUE)
for(var/obj/item/bodypart/part in bodyparts)
if(choice in part.embedded_objects)
body_part = part
if(!istype(choice) || !(choice in choice_list))
return
var/time_taken = choice.embedding.embedded_unsafe_removal_time * choice.w_class
user.visible_message(span_warning("[user] attempts to remove [choice] from [usr.p_their()] [body_part.name]."),span_notice("You attempt to remove [choice] from your [body_part.name]... (It will take [DisplayTimeText(time_taken)].)"))
if(!do_after(user, time_taken, needhand = 1, target = src) && !(choice in body_part.embedded_objects))
return
var/damage_amount = choice.embedding.embedded_unsafe_removal_pain_multiplier * choice.w_class
body_part.receive_damage(damage_amount > 0, sharpness = SHARP_EDGED)//It hurts to rip it out, get surgery you dingus.
if(remove_embedded_object(choice, get_turf(src), damage_amount))
user.put_in_hands(choice)
user.visible_message("[user] successfully rips [choice] out of [user == src? p_their() : "[src]'s"] [body_part.name]!", span_notice("You successfully remove [choice] from your [body_part.name]."))
return TRUE
/mob/living/carbon/proc/get_interaction_efficiency(zone)
var/obj/item/bodypart/limb = get_bodypart(zone)
if(!limb)

View File

@@ -32,6 +32,17 @@
else if(get_bodypart(BODY_ZONE_HEAD))
. += span_deadsay("It appears that [t_his] brain is missing...")
var/list/disabled = list()
for(var/X in bodyparts)
var/obj/item/bodypart/body_part = X
if(body_part.bodypart_disabled)
disabled += body_part
for(var/obj/item/I in body_part.embedded_objects)
. += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [body_part.name]!</B>\n"
for(var/i in body_part.wounds)
var/datum/wound/iter_wound = i
. += "[iter_wound.get_examine_description(user)]\n"
var/list/missing = get_missing_limbs()
for(var/t in missing)
if(t==BODY_ZONE_HEAD)
@@ -68,12 +79,6 @@
else
msg += "<b>[t_He] [t_is] severely deformed!</b>\n"
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
for(var/i in BP.wounds)
var/datum/wound/W = i
msg += "[W.get_examine_description(user)]\n"
if(HAS_TRAIT(src, TRAIT_DUMB))
msg += "[t_He] seem[p_s()] to be clumsy and unable to think.\n"

View File

@@ -231,29 +231,6 @@
spreadFire(AM)
/mob/living/carbon/human/Topic(href, href_list)
if(href_list["embedded_object"] && usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts
if(!L)
return
var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects
if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore
return
var/time_taken = I.embedding.embedded_unsafe_removal_time*I.w_class
usr.visible_message(span_warning("[usr] attempts to remove [I] from [usr.p_their()] [L.name]."),span_notice("You attempt to remove [I] from your [L.name]... (It will take [DisplayTimeText(time_taken)].)"))
if(do_after(usr, time_taken, needhand = 1, target = src))
if(!I || !L || I.loc != src || !(I in L.embedded_objects))
return
L.embedded_objects -= I
L.receive_damage(I.embedding.embedded_unsafe_removal_pain_multiplier*I.w_class, sharpness=SHARP_EDGED)//It hurts to rip it out, get surgery you dingus.
I.forceMove(get_turf(src))
usr.put_in_hands(I)
usr.emote("scream")
usr.visible_message("[usr] successfully rips [I] out of [usr.p_their()] [L.name]!",span_notice("You successfully remove [I] from your [L.name]."))
if(!has_embedded_objects())
clear_alert("embeddedobject")
SEND_SIGNAL(usr, COMSIG_CLEAR_MOOD_EVENT, "embedded")
return
if(href_list["item"]) //canUseTopic check for this is handled by mob/Topic()
var/slot = text2num(href_list["item"])
if(slot in check_obscured_slots(TRUE))
@@ -1235,6 +1212,9 @@
/mob/living/carbon/human/species/lizard/ashwalker
race = /datum/species/lizard/ashwalker
/mob/living/carbon/human/species/lizard/draconid
race = /datum/species/lizard/draconid
/mob/living/carbon/human/species/moth
race = /datum/species/moth

View File

@@ -169,21 +169,6 @@
hitpush = FALSE
skipcatch = TRUE
blocked = TRUE
else if(I)
if(((throwingdatum ? throwingdatum.speed : I.throw_speed) >= EMBED_THROWSPEED_THRESHOLD) || I.embedding.embedded_ignore_throwspeed_threshold)
if(can_embed(I))
if(prob(I.embedding.embed_chance) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE))
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
var/obj/item/bodypart/L = pick(bodyparts)
L.embedded_objects |= I
I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
I.forceMove(src)
L.receive_damage(I.w_class*I.embedding.embedded_impact_pain_multiplier, wound_bonus=-30, sharpness = TRUE)
visible_message(span_danger("[I] embeds itself in [src]'s [L.name]!"),span_userdanger("[I] embeds itself in your [L.name]!"))
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
hitpush = FALSE
skipcatch = TRUE //can't catch the now embedded item
return ..()
/mob/living/carbon/human/grippedby(mob/living/user, instant = FALSE)

View File

@@ -38,10 +38,6 @@
//heart attack stuff
handle_heart()
if(stat != DEAD)
//Stuff jammed in your limbs hurts
handle_embedded_objects()
dna.species.spec_life(src) // for mutantraces
else
for(var/i in all_wounds)
@@ -307,31 +303,6 @@
return TRUE
return ..()
/mob/living/carbon/human/proc/handle_embedded_objects()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
for(var/obj/item/I in BP.embedded_objects)
var/pain_chance_current = I.embedding.embedded_pain_chance
if(!(mobility_flags & MOBILITY_STAND))
pain_chance_current *= 0.2
if(prob(pain_chance_current))
BP.receive_damage(I.w_class*I.embedding.embedded_pain_multiplier, wound_bonus = CANT_WOUND)
to_chat(src, span_userdanger("[I] embedded in your [BP.name] hurts!"))
var/fall_chance_current = I.embedding.embedded_fall_chance
if(!(mobility_flags & MOBILITY_STAND))
fall_chance_current *= 0.2
if(prob(fall_chance_current))
BP.receive_damage(I.w_class*I.embedding.embedded_fall_pain_multiplier, wound_bonus = CANT_WOUND) // can wound
BP.embedded_objects -= I
I.forceMove(drop_location())
visible_message(span_danger("[I] falls out of [name]'s [BP.name]!"),span_userdanger("[I] falls out of your [BP.name]!"))
if(!has_embedded_objects())
clear_alert("embeddedobject")
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "embedded")
/mob/living/carbon/human/proc/handle_heart()
var/we_breath = !HAS_TRAIT_FROM(src, TRAIT_NOBREATH, SPECIES_TRAIT)

View File

@@ -1219,7 +1219,7 @@ GLOBAL_LIST_EMPTY(mentor_races)
/datum/species/proc/check_species_weakness(obj/item, mob/living/attacker)
return 0 //This is not a boolean, it's the multiplier for the damage that the user takes from the item.It is added onto the check_weakness value of the mob, and then the force of the item is multiplied by this value
////////
////////
//LIFE//
////////

View File

@@ -166,3 +166,28 @@
/datum/species/human/felinid/get_scream_sound(mob/living/carbon/human/H)
return pick(screamsound)
/datum/species/human/felinid/spec_life(mob/living/carbon/human/H)
. = ..()
if((H.client && H.client.prefs.mood_tail_wagging) && !is_wagging_tail() && H.mood_enabled)
var/datum/component/mood/mood = H.GetComponent(/datum/component/mood)
if(!istype(mood) || !(mood.shown_mood >= MOOD_LEVEL_HAPPY2))
return
var/chance = 0
switch(mood.shown_mood)
if(0 to MOOD_LEVEL_SAD4)
chance = -0.1
if(MOOD_LEVEL_SAD4 to MOOD_LEVEL_SAD3)
chance = -0.01
if(MOOD_LEVEL_HAPPY2 to MOOD_LEVEL_HAPPY3)
chance = 0.001
if(MOOD_LEVEL_HAPPY3 to MOOD_LEVEL_HAPPY4)
chance = 0.1
if(MOOD_LEVEL_HAPPY4 to INFINITY)
chance = 1
if(prob(abs(chance)))
switch(SIGN(chance))
if(1)
H.emote("wag")
if(-1)
stop_wagging_tail(H)

View File

@@ -62,6 +62,32 @@
stunmod *= heat_stun_mult //however many times, and if it goes down we multiply by 1.1
//This gets us an effective stunmod of 0.91, 1, 1.1, 1.21, 1.33, based on temp
/datum/species/lizard/spec_life(mob/living/carbon/human/H)
. = ..()
if((H.client && H.client.prefs.mood_tail_wagging) && !is_wagging_tail() && H.mood_enabled)
var/datum/component/mood/mood = H.GetComponent(/datum/component/mood)
if(!istype(mood) || !(mood.shown_mood >= MOOD_LEVEL_HAPPY2))
return
var/chance = 0
switch(mood.shown_mood)
if(0 to MOOD_LEVEL_SAD4)
chance = -0.1
if(MOOD_LEVEL_SAD4 to MOOD_LEVEL_SAD3)
chance = -0.01
if(MOOD_LEVEL_HAPPY2 to MOOD_LEVEL_HAPPY3)
chance = 0.001
if(MOOD_LEVEL_HAPPY3 to MOOD_LEVEL_HAPPY4)
chance = 0.1
if(MOOD_LEVEL_HAPPY4 to INFINITY)
chance = 1
if(prob(abs(chance)))
switch(SIGN(chance))
if(1)
H.emote("wag")
if(-1)
stop_wagging_tail(H)
/*
Lizard subspecies: ASHWALKERS
*/

View File

@@ -37,6 +37,10 @@
if(stat != DEAD)
handle_liver()
if(stat != DEAD)
//Stuff jammed in your limbs hurts
handle_embedded_objects()
else
. = ..()
@@ -654,6 +658,35 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
var/datum/brain_trauma/BT = T
BT.on_life()
////////////
// EMBEDS //
////////////
/mob/living/carbon/proc/handle_embedded_objects()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
for(var/obj/item/I in BP.embedded_objects)
I.embed_tick(src, BP)
var/pain_chance_current = I.embedding.embedded_pain_chance
if(!(mobility_flags & MOBILITY_STAND))
pain_chance_current *= 0.2
if(prob(pain_chance_current))
BP.receive_damage(I.w_class*I.embedding.embedded_pain_multiplier, wound_bonus = CANT_WOUND)
to_chat(src, span_userdanger("[I] embedded in your [BP.name] hurts!"))
var/fall_chance_current = I.embedding.embedded_fall_chance
if(!(mobility_flags & MOBILITY_STAND))
fall_chance_current *= 0.2
if(prob(fall_chance_current))
BP.receive_damage(I.w_class*I.embedding.embedded_fall_pain_multiplier, wound_bonus = CANT_WOUND) // can wound
remove_embedded_object(I, drop_location(), FALSE)
visible_message(span_danger("[I] falls out of [name]'s [BP.name]!"), span_userdanger("[I] falls out of your [BP.name]!"))
if(!has_embedded_objects())
clear_alert("embeddedobject")
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "embedded")
/////////////////////////////////////
//MONKEYS WITH TOO MUCH CHOLOESTROL//
/////////////////////////////////////

View File

@@ -0,0 +1,89 @@
/mob/living/simple_animal/hostile/plaguerat
name = "rat"
desc = "It's a large rodent, afflicted with both anger issues and a terrible disease."
icon_state = "mouse_gray"
icon_living = "mouse_gray"
icon_dead = "mouse_gray_dead"
speak = list("Skree!","SKREEE!","Squeak?")
speak_emote = list("squeaks")
emote_hear = list("Hisses.")
emote_see = list("runs in a circle.", "stands on its hind legs.")
melee_damage_lower = 5 //stronk
melee_damage_upper = 5
obj_damage = 5
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
maxHealth = 20
health = 20
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/plagued = 1)
density = FALSE
ventcrawler = VENTCRAWLER_ALWAYS
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_TINY
mob_biotypes = list(MOB_ORGANIC,MOB_BEAST)
faction = list("rat")
var/playstyle_string = "<span class='big bold'>You are a Plague Rat,</span></b> \
Your goal is to spread The Plague as much as possible, by infecting anyone you can. \
You can do this by licking their food, or by directly biting them. \
You can also nibble on dead bodies to slightly heal yourself! \
However, you are still very fragile! You're just are a small rat, after all.</b>"
/mob/living/simple_animal/hostile/plaguerat/AttackingTarget()
..()
var/mob/living/carbon/C = target
if(isliving(C) && (C.stat != DEAD)) //It is for injecting plague reagent into people via biting them.
if(C.reagents)
var/obj/item/I = C.get_item_by_slot(ITEM_SLOT_OCLOTHING)
if(!istype(I, /obj/item/clothing/suit/space/hardsuit) && !istype(I, /obj/item/clothing/suit/armor))
C.reagents.add_reagent(/datum/reagent/plaguebacteria, 3)
if(C.stat == DEAD) //It is for biting dead bodies to heal.
src.visible_message(span_warning("[src] starts biting into [C]!"),span_notice("You start eating [C]..."))
if(do_mob(src, target, 3 SECONDS))
to_chat(src, span_notice ("You finish eating [C]."))
heal_bodypart_damage(5)
C.adjustBruteLoss(15)
return
if (!isliving(target) && target.reagents && target.is_injectable(src, allowmobs = TRUE)) //It is for injecting plague reagent into food and reagent containers by licking them. Not to be confused with biting people.
src.visible_message(span_warning("[src] starts licking [target]!"),span_notice("You start licking [target]..."))
if (do_mob(src, target, 2 SECONDS))
target.reagents.add_reagent(/datum/reagent/plaguebacteria,rand(1,2),no_react = TRUE)
to_chat(src, span_notice("You finish licking [target]."))
return
//Spawn Event
/datum/round_event_control/plaguerat
name = "Spawn a Plague Rat"
typepath = /datum/round_event/ghost_role/plaguerat
weight = 6
max_occurrences = 1
earliest_start = 30 MINUTES
/datum/round_event/ghost_role/plaguerat
minimum_required = 1
role_name = "plaguerat"
/datum/round_event/ghost_role/plaguerat/spawn_role()
var/list/candidates = get_candidates(ROLE_SENTIENCE, null, ROLE_SENTIENCE)
if(!candidates.len)
return NOT_ENOUGH_PLAYERS
var/mob/dead/selected = pick_n_take(candidates)
var/datum/mind/player_mind = new /datum/mind(selected.key)
player_mind.active = 1
if(!GLOB.xeno_spawn)
return MAP_ERROR
var/mob/living/simple_animal/hostile/plaguerat/S = new /mob/living/simple_animal/hostile/plaguerat/(pick(GLOB.xeno_spawn))
player_mind.transfer_to(S)
player_mind.assigned_role = "Plague rat"
player_mind.special_role = "Plague rat"
to_chat(S, S.playstyle_string)
SEND_SOUND(S, sound('sound/magic/mutate.ogg'))
message_admins("[ADMIN_LOOKUPFLW(S)] has been made into a plague rat by an event.")
log_game("[key_name(S)] was spawned as a plague rat by an event.")
spawned_mobs += S
return SUCCESSFUL_SPAWN

View File

@@ -89,6 +89,7 @@
O.setOrganLoss(ORGAN_SLOT_BRAIN, getOrganLoss(ORGAN_SLOT_BRAIN))
O.updatehealth()
O.radiation = radiation
O.blood_volume = blood_volume * MONKIFY_BLOOD_COEFFICIENT
//re-add implants to new mob
if (tr_flags & TR_KEEPIMPLANTS)
@@ -265,6 +266,7 @@
O.adjustOrganLoss(ORGAN_SLOT_BRAIN, getOrganLoss(ORGAN_SLOT_BRAIN))
O.updatehealth()
O.radiation = radiation
O.blood_volume = blood_volume / MONKIFY_BLOOD_COEFFICIENT
//re-add implants to new mob
if (tr_flags & TR_KEEPIMPLANTS)

View File

@@ -283,8 +283,8 @@
if(13 to INFINITY)
M.visible_message("<span class='danger'>[M] suddenly ignites in a brilliant flash of white!<span>", span_userdanger("You suddenly ignite in a holy fire!"))
M.adjust_fire_stacks(3)
M.IgniteMob()
M.adjustFireLoss(4)
M.IgniteMob()
M.adjustFireLoss(4)
holder.remove_reagent(type, 0.4) //fixed consumption to prevent balancing going out of whack
/datum/reagent/water/holywater/reaction_turf(turf/T, reac_volume)
@@ -2043,3 +2043,14 @@
wounded_part.heal_damage(0.25, 0.25)
M.adjustStaminaLoss(-0.25*REM) // the more wounds, the more stamina regen
..()
/datum/reagent/plaguebacteria
name = "Yersinia pestis"
description = "A horrible plague, in a container. It is a TERRIBLE idea to drink this."
color = "#7CFC00"
taste_description = "death"
can_synth = FALSE
/datum/reagent/plaguebacteria/reaction_mob(mob/living/L, method=TOUCH, reac_volume, show_message = 1, touch_protection = 0)
L.ForceContractDisease(new /datum/disease/plague(), FALSE, TRUE)

View File

@@ -86,11 +86,8 @@
for(var/X in C.bodyparts)
var/obj/item/bodypart/part = X
if(item_to_retrieve in part.embedded_objects)
part.embedded_objects -= item_to_retrieve
C.remove_embedded_object(item_to_retrieve, silent = TRUE, forced = TRUE)
to_chat(C, span_warning("The [item_to_retrieve] that was embedded in your [L] has mysteriously vanished. How fortunate!"))
if(!C.has_embedded_objects())
C.clear_alert("embeddedobject")
SEND_SIGNAL(C, COMSIG_CLEAR_MOOD_EVENT, "embedded")
break
else

View File

@@ -104,8 +104,7 @@
break
for(var/obj/item/I in embedded_objects)
embedded_objects -= I
I.forceMove(src)
phantom_owner.remove_embedded_object(I, src, TRUE, TRUE)
if(!phantom_owner.has_embedded_objects())
phantom_owner.clear_alert("embeddedobject")
SEND_SIGNAL(phantom_owner, COMSIG_CLEAR_MOOD_EVENT, "embedded")

View File

@@ -161,6 +161,7 @@
for(var/X in bodyparts)
var/obj/item/bodypart/L = X
for(var/obj/item/I in L.embedded_objects)
remove_embedded_object(I, T, TRUE, TRUE)
L.embedded_objects -= I
I.forceMove(T)
@@ -168,11 +169,11 @@
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "embedded")
/mob/living/carbon/proc/has_embedded_objects()
. = 0
. = FALSE
for(var/X in bodyparts)
var/obj/item/bodypart/L = X
for(var/obj/item/I in L.embedded_objects)
return 1
return TRUE
//Helper for quickly creating a new limb - used by augment code in species.dm spec_attacked_by

View File

@@ -1,14 +1,16 @@
/datum/surgery/embedded_removal
name = "Removal of embedded objects"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/remove_object)
steps = list(/datum/surgery_step/incise, /datum/surgery_step/remove_object, /datum/surgery_step/close)
possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
/datum/surgery_step/remove_object
name = "remove embedded objects"
time = 32
accept_hand = 1
time = 1.5 SECONDS
accept_hand = TRUE
fuckup_damage = 0
repeatable = TRUE
var/obj/item/target_item = null
var/obj/item/bodypart/L = null
@@ -25,25 +27,20 @@
/datum/surgery_step/remove_object/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(L)
if(ishuman(target))
var/mob/living/carbon/human/H = target
var/objects = 0
for(var/obj/item/I in L.embedded_objects)
objects++
I.forceMove(get_turf(H))
L.embedded_objects -= I
if(!H.has_embedded_objects())
H.clear_alert("embeddedobject")
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "embedded")
if(objects > 0)
display_results(user, target, span_notice("You successfully remove [objects] objects from [H]'s [L.name]."),
"[user] successfully removes [objects] objects from [H]'s [L]!",
"[user] successfully removes [objects] objects from [H]'s [L]!")
if(iscarbon(target))
if(L.embedded_objects)
var/mob/living/carbon/C = target
var/obj/item/I = pick(L.embedded_objects)
if(C.remove_embedded_object(I, C.drop_location(), TRUE))
display_results(user, target, span_notice("You successfully remove \the [I] from [C]'s [L.name]."),
"[user] successfully removes \the [I] from [C]'s [L]!",
"[user] successfully removes \the [I] from [C]'s [L]!")
else
to_chat(user, span_warning("You fail to remove \the [I] from [C]'s [L.name]!"))
else
to_chat(user, span_warning("You find no objects embedded in [H]'s [L]!"))
to_chat(user, span_warning("You find no objects embedded in [target]'s [L]!"))
else
to_chat(user, span_warning("You can't find [target]'s [parse_zone(user.zone_selected)], let alone any objects embedded in it!"))
return 1
return FALSE

View File

@@ -399,10 +399,10 @@ BASE_MC_TICK_RATE 1
HIGH_POP_MC_TICK_RATE 1.1
##Engage high pop mode if player count raises above this (Player in this context means any connected user. Lobby, ghost or in-game all count)
HIGH_POP_MC_MODE_AMOUNT 60
HIGH_POP_MC_MODE_AMOUNT 65
##Disengage high pop mode if player count drops below this
DISABLE_HIGH_POP_MC_MODE_AMOUNT 50
DISABLE_HIGH_POP_MC_MODE_AMOUNT 60
## Uncomment to prevent the world from sleeping while no players are connected after initializations
#RESUME_AFTER_INITIALIZATIONS

View File

@@ -58,6 +58,186 @@
-->
<div class="commit sansserif">
<h2 class="date">22 May 2022</h2>
<h3 class="author">ToasterBiome updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">fixes runtime in forceMove if you move to some place without a turf</li>
</ul>
<h3 class="author">nmajask updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">Carbons can now be embedded with objects.</li>
<li class="tweak">Removing embedded objects now uses a radial menu.</li>
<li class="tweak">Embeds now respect armor.</li>
</ul>
<h2 class="date">21 May 2022</h2>
<h3 class="author"> @cuackles updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Added goat king loot</li>
<li class="imageadd">added sprite for scanner</li>
</ul>
<h3 class="author"> [IndieanaJones](https://github.com/IndieanaJones) and [Watermelon914](https://github.com/Watermelon914), ported to Yogstation by SuperSlayer updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Ports some PR's from TG that add some midround rulesets for dynamic</li>
</ul>
<h3 class="author">MajManatee updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">Swaps the position of the filing cabinet, paper shredder, and armor storage on YogBox</li>
</ul>
<h3 class="author">Mqiib updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">Dying in bat form now actually hurts</li>
</ul>
<h3 class="author">SomeguyManperson updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">welders now respect attack cooldowns when repairing limbs</li>
</ul>
<h3 class="author">ToasterBiome updated:</h3>
<ul class="changes bgimages16">
<li class="experiment">Fixes lag when server is above 60 population</li>
</ul>
<h3 class="author">TymurShatillo updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Adds plague rat - VERY MINOR midround antagonist</li>
<li class="rscadd">Adds plague disease</li>
</ul>
<h3 class="author">UselessTheremin updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">no more becoming a spaghetti creature with dwarfism</li>
</ul>
<h3 class="author">cuackles updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Added new ckey donor exclusive item</li>
<li class="imageadd">added some icons and images for said donor item</li>
</ul>
<h2 class="date">20 May 2022</h2>
<h3 class="author">SomeguyManperson updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">TONS of stuff that is supposed to deal burn damage no longer does literally fucking nothing because it's trying to deal "fire" damage</li>
</ul>
<h2 class="date">18 May 2022</h2>
<h3 class="author">Chubbygummibear updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">blood level is persistent through monkey transforming</li>
<li class="bugfix">proper blood scaling between monkey and human</li>
</ul>
<h3 class="author">MajManatee updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">The crafting recipe for the Uranium Slugs actually works now</li>
</ul>
<h2 class="date">17 May 2022</h2>
<h3 class="author"> @cuackles, MajesticManateee updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Adds new donor beret for myself</li>
<li class="imageadd">added sprites for said beret</li>
</ul>
<h3 class="author"> Cakey, Cajoes, Ghommie updated:</h3>
<ul class="changes bgimages16">
<li class="imageadd">added 3/4 sprites for paper bins, paper shredders, fax machines, and towel bins</li>
</ul>
<h3 class="author"> Mqiib, Nmajask updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">The hivemind has found DNA blueprints for a devastating new weapon: the flesh maul!</li>
<li class="imageadd">Fixes the changeling tentacle arm sprites being backwards</li>
<li class="imageadd">Sprites for new ling item</li>
<li class="wip">Balance decisions pending</li>
</ul>
<h3 class="author"> TemporalOroboros updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">Added defines for the damage flags. Please use them!</li>
</ul>
<h3 class="author"> [tralezab](https://github.com/tralezab), ported to Yogstation by SuperSlayer updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">Simplemobs now have healthdolls</li>
</ul>
<h3 class="author">ArcaneMusic, MrDoomBringer, ynot01 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Added Medical Kiosk</li>
</ul>
<h3 class="author">Chubbygummibear updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Inducers can be used to charge Preternis but this process burns them</li>
</ul>
<h3 class="author">Fikou, ported by TheGamerDK updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Secret Gateways can now be a thing enabled by config. They are not on the repository, instead, loaded from a config folder.</li>
<li class="rscadd">Adds the secret and anti-phasing z level traits used by Secret Gateways, secret prevents observers from looking at the z level in any way other than observing through another player's eyes</li>
<li class="experiment">admin loaded away missions can be secret as well</li>
</ul>
<h3 class="author">JohnFulpWillard, Tatax, ToastyBiome updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">bloodsucker bugfixes</li>
</ul>
<h3 class="author">MajManatee updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Adds Depleted Uranium Slugs</li>
<li class="rscadd">Adds Cryoshot buckshot shells</li>
<li class="imageadd">adds unique shells and projectiles for both ammo types</li>
<li class="rscadd">Adds cool new electrical buckshot ammo</li>
<li class="imageadd">adds a new yellow, electrically charged shell</li>
</ul>
<h3 class="author">Marmio64 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Monster hunter gets interactions with demons of sin</li>
</ul>
<h3 class="author">SomeguyManperson updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">non-combat mechs can no longer throw people</li>
<li class="tweak">Both advanced stack healing items (adv mesh + medicated suture) have had their stack size increased by 10</li>
<li class="tweak">Advanced sutures are applied to wounds twice as fast as normal sutures</li>
<li class="tweak">sutures now have 15 items in each stack isntead of 10 because why 10 when mesh has 15</li>
<li class="tweak">touch healing chems (silver sulf/styptic) now heal 75% less damage passively (no change to on touch healing), and can only heal on touch for up to 45 points of damage/chemical</li>
<li class="tweak">touch healing chems (silver sulf/styptic) now apply their reagent to the bloodstream when splashed</li>
<li class="tweak">lesser form now costs 1 dna and 5 chemicals, cannot be used if stunned or cuffed</li>
<li class="rscadd">new emote pointdown</li>
<li class="bugfix">embeds will act more often when standing instead of acting more often when lying down</li>
<li class="bugfix">sandbag icon should be back</li>
</ul>
<h3 class="author">TheGamerdk updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">An area with an AI data core can no longer experience power failure from random events</li>
<li class="rscadd">The Sig Tech has been renamed to Network Admin and is now in charge of general AI upgrades</li>
<li class="rscadd">The Network Admin can combine CPUs and RAM to create racks to upgrade the AI, instead of using individual cards.</li>
<li class="rscadd">This is done using the new rack creator machine. You insert printed CPUs and then add RAM sticks. Then you finalize and it will print the full rack.</li>
<li class="rscadd">The AI is now upgraded by inserting server racks into expansion card holders (Now called server cabinets)</li>
<li class="rscadd">The Network Admin can now overclock CPUs in their workshop. Increase the speed as much as possible while minimizing the power draw!</li>
<li class="rscadd">Adds up to tier 3/4 AI hardware, unlockable through Research.</li>
<li class="tweak">AI cpu now works off of percentage, adds support for fractional CPU speeds (Overclocking)</li>
<li class="bugfix">Fixes off-station hijacking and downloading of the AI</li>
</ul>
<h3 class="author">ToasterBiome updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">marrow weaver drop uranium</li>
</ul>
<h3 class="author">adamsong updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Added more notification methods for tickets with no present admins</li>
</ul>
<h3 class="author">cuackles updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">new snack, vermin bites</li>
<li class="imageadd">new snack sprites, vermin bites</li>
<li class="rscadd">Added new makeshift item: makeshift ID</li>
<li class="imageadd">added some icons for the makeshift ID</li>
</ul>
<h3 class="author">maxion12345 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Added new airlock to secondary datacore and added secondary datacore to event blacklist for APC failure and anomalies.</li>
</ul>
<h3 class="author">nmajask updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Added chance for felinids and lizards to wag their tail when they are happy and if they aren't doing so already</li>
<li class="rscadd">Added human subtypes for some species that were missing them, making it posable to spawn them in with spawn</li>
</ul>
<h3 class="author">ynot01 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Fixed being able to interact with cryo cells from within</li>
<li class="tweak">Throwing a body at the wall is no longer silent</li>
</ul>
<h2 class="date">16 May 2022</h2>
<h3 class="author"> ToasterBiome, tatax updated:</h3>
<ul class="changes bgimages16">
@@ -1977,88 +2157,6 @@
<li class="rscadd">Added a second set of weights to make ion lawsets independent from roundstart lawsets</li>
<li class="tweak">Adds a separate probability for adding an ion law, allowing it to be tweaked separate from other ion effects</li>
</ul>
<h2 class="date">20 February 2022</h2>
<h3 class="author"> Imaginos16 updated:</h3>
<ul class="changes bgimages16">
<li class="imageadd">Removes soul from the Security TV, Smartfridge, and Booze-o-Mat</li>
</ul>
<h3 class="author"> Xoxeyos updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">AI Core Tutorial disk can now be found in the RD's office and AI sat on YogsBox.</li>
</ul>
<h3 class="author">tattax updated:</h3>
<ul class="changes bgimages16">
<li class="imageadd">hammer now looks epic</li>
<li class="imagedel">blue hamoroo is gone</li>
</ul>
<h2 class="date">19 February 2022</h2>
<h3 class="author">TheGamerdk updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">The AI core on Boxstation has been properly fortified. No more avoiding turrets or spacing the room to kill the AI.</li>
</ul>
<h2 class="date">18 February 2022</h2>
<h3 class="author">TheGamerdk updated:</h3>
<ul class="changes bgimages16">
<li class="spellcheck">Swimming pool -> swimming pool</li>
</ul>
<h3 class="author">tattax updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">mice now cheese up on cheesie honkers</li>
</ul>
<h3 class="author">wejengin2 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">fixes an airlock to space on meta</li>
</ul>
<h2 class="date">17 February 2022</h2>
<h3 class="author">ToasterBiome updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">fixes anomaly cores dropping on every blob tile destruction</li>
<li class="tweak">no bible antimagic if you are a powergamer</li>
</ul>
<h3 class="author">nmajask updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">fixed mining medic's PDA not being assigned to them round start</li>
</ul>
<h2 class="date">16 February 2022</h2>
<h3 class="author">JamieD1 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Blob now drops anomaly core on death</li>
</ul>
<h3 class="author">wejengin2 updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">fixed a typo in topkake description</li>
</ul>
<h2 class="date">15 February 2022</h2>
<h3 class="author"> Xoxeyos updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Eclipse now has a secondary AI datacore south of the RD's office.</li>
<li class="rscadd">New tutorial holodisk for creation of AI cores, you will find these within your local RD's office, or within the AI data core storage, depending on the station.</li>
<li class="rscadd">OmegaStation now has a proper AI core.</li>
<li class="bugfix">Fixed a fucked up door in front of a table.</li>
<li class="bugfix">Removed a stray wire on Omega.</li>
</ul>
<h3 class="author">Anvilman6 updated:</h3>
<ul class="changes bgimages16">
<li class="spellcheck">Updated syntax and wording on the "AI Changes" roundstart informational announcement</li>
</ul>
<h3 class="author">TheGamerdk updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">AI Projects have the ability to give active abilities</li>
<li class="rscadd">New project allows AI to charge a borg remotely</li>
<li class="rscadd">New project allows AI to keep APC operational even without power for a short duration</li>
<li class="rscadd">New project that notifies the AI when a tagged individual re-enters camera view.</li>
<li class="rscadd">Adds AI abilities that can be recharged by using CPU power</li>
</ul>
<h3 class="author">UselessTheremin updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">wheelchairs can now use turnstiles</li>
</ul>
</div>
<b>GoonStation 13 Development Team</b>

View File

@@ -31517,3 +31517,137 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
ToasterBiome:
- tweak: makes tape recursively check contents to make sure theres no grenades or
explosives in the taped item
2022-05-17:
' @cuackles, MajesticManateee':
- rscadd: Adds new donor beret for myself
- imageadd: added sprites for said beret
' Cakey, Cajoes, Ghommie':
- imageadd: added 3/4 sprites for paper bins, paper shredders, fax machines, and
towel bins
' Mqiib, Nmajask':
- rscadd: 'The hivemind has found DNA blueprints for a devastating new weapon: the
flesh maul!'
- imageadd: Fixes the changeling tentacle arm sprites being backwards
- imageadd: Sprites for new ling item
- wip: Balance decisions pending
' TemporalOroboros':
- tweak: Added defines for the damage flags. Please use them!
' [tralezab](https://github.com/tralezab), ported to Yogstation by SuperSlayer':
- tweak: Simplemobs now have healthdolls
ArcaneMusic, MrDoomBringer, ynot01:
- rscadd: Added Medical Kiosk
Chubbygummibear:
- rscadd: Inducers can be used to charge Preternis but this process burns them
Fikou, ported by TheGamerDK:
- rscadd: Secret Gateways can now be a thing enabled by config. They are not on
the repository, instead, loaded from a config folder.
- rscadd: Adds the secret and anti-phasing z level traits used by Secret Gateways,
secret prevents observers from looking at the z level in any way other than
observing through another player's eyes
- experiment: admin loaded away missions can be secret as well
JohnFulpWillard, Tatax, ToastyBiome:
- bugfix: bloodsucker bugfixes
MajManatee:
- rscadd: Adds Depleted Uranium Slugs
- rscadd: Adds Cryoshot buckshot shells
- imageadd: adds unique shells and projectiles for both ammo types
- rscadd: Adds cool new electrical buckshot ammo
- imageadd: adds a new yellow, electrically charged shell
Marmio64:
- rscadd: Monster hunter gets interactions with demons of sin
SomeguyManperson:
- bugfix: non-combat mechs can no longer throw people
- tweak: Both advanced stack healing items (adv mesh + medicated suture) have had
their stack size increased by 10
- tweak: Advanced sutures are applied to wounds twice as fast as normal sutures
- tweak: sutures now have 15 items in each stack isntead of 10 because why 10 when
mesh has 15
- tweak: touch healing chems (silver sulf/styptic) now heal 75% less damage passively
(no change to on touch healing), and can only heal on touch for up to 45 points
of damage/chemical
- tweak: touch healing chems (silver sulf/styptic) now apply their reagent to the
bloodstream when splashed
- tweak: lesser form now costs 1 dna and 5 chemicals, cannot be used if stunned
or cuffed
- rscadd: new emote pointdown
- bugfix: embeds will act more often when standing instead of acting more often
when lying down
- bugfix: sandbag icon should be back
TheGamerdk:
- tweak: An area with an AI data core can no longer experience power failure from
random events
- rscadd: The Sig Tech has been renamed to Network Admin and is now in charge of
general AI upgrades
- rscadd: The Network Admin can combine CPUs and RAM to create racks to upgrade
the AI, instead of using individual cards.
- rscadd: This is done using the new rack creator machine. You insert printed CPUs
and then add RAM sticks. Then you finalize and it will print the full rack.
- rscadd: The AI is now upgraded by inserting server racks into expansion card holders
(Now called server cabinets)
- rscadd: The Network Admin can now overclock CPUs in their workshop. Increase the
speed as much as possible while minimizing the power draw!
- rscadd: Adds up to tier 3/4 AI hardware, unlockable through Research.
- tweak: AI cpu now works off of percentage, adds support for fractional CPU speeds
(Overclocking)
- bugfix: Fixes off-station hijacking and downloading of the AI
ToasterBiome:
- rscadd: marrow weaver drop uranium
adamsong:
- rscadd: Added more notification methods for tickets with no present admins
cuackles:
- rscadd: new snack, vermin bites
- imageadd: new snack sprites, vermin bites
- rscadd: 'Added new makeshift item: makeshift ID'
- imageadd: added some icons for the makeshift ID
maxion12345:
- rscadd: Added new airlock to secondary datacore and added secondary datacore to
event blacklist for APC failure and anomalies.
nmajask:
- rscadd: Added chance for felinids and lizards to wag their tail when they are
happy and if they aren't doing so already
- rscadd: Added human subtypes for some species that were missing them, making it
posable to spawn them in with spawn
ynot01:
- bugfix: Fixed being able to interact with cryo cells from within
- tweak: Throwing a body at the wall is no longer silent
2022-05-18:
Chubbygummibear:
- bugfix: blood level is persistent through monkey transforming
- bugfix: proper blood scaling between monkey and human
MajManatee:
- bugfix: The crafting recipe for the Uranium Slugs actually works now
2022-05-20:
SomeguyManperson:
- bugfix: TONS of stuff that is supposed to deal burn damage no longer does literally
fucking nothing because it's trying to deal "fire" damage
2022-05-21:
' @cuackles':
- rscadd: Added goat king loot
- imageadd: added sprite for scanner
? ' [IndieanaJones](https://github.com/IndieanaJones) and [Watermelon914](https://github.com/Watermelon914),
ported to Yogstation by SuperSlayer'
: - rscadd: Ports some PR's from TG that add some midround rulesets for dynamic
MajManatee:
- tweak: Swaps the position of the filing cabinet, paper shredder, and armor storage
on YogBox
Mqiib:
- tweak: Dying in bat form now actually hurts
SomeguyManperson:
- bugfix: welders now respect attack cooldowns when repairing limbs
ToasterBiome:
- experiment: Fixes lag when server is above 60 population
TymurShatillo:
- rscadd: Adds plague rat - VERY MINOR midround antagonist
- rscadd: Adds plague disease
UselessTheremin:
- bugfix: no more becoming a spaghetti creature with dwarfism
cuackles:
- rscadd: Added new ckey donor exclusive item
- imageadd: added some icons and images for said donor item
2022-05-22:
ToasterBiome:
- bugfix: fixes runtime in forceMove if you move to some place without a turf
nmajask:
- tweak: Carbons can now be embedded with objects.
- tweak: Removing embedded objects now uses a radial menu.
- tweak: Embeds now respect armor.

View File

@@ -1,11 +0,0 @@
author: "TheGamerdk"
delete-after: true
changes:
- rscadd: "The Sig Tech has been renamed to Network Admin and is now in charge of general AI upgrades"
- rscadd: "The Network Admin can combine CPUs and RAM to create racks to upgrade the AI, instead of using individual cards."
- rscadd: "This is done using the new rack creator machine. You insert printed CPUs and then add RAM sticks. Then you finalize and it will print the full rack."
- rscadd: "The AI is now upgraded by inserting server racks into expansion card holders (Now called server cabinets)"
- rscadd: "The Network Admin can now overclock CPUs in their workshop. Increase the speed as much as possible while minimizing the power draw!"
- rscadd: "Adds up to tier 3/4 AI hardware, unlockable through Research."
- tweak: "AI cpu now works off of percentage, adds support for fractional CPU speeds (Overclocking)"
- bugfix: "Fixes off-station hijacking and downloading of the AI"

View File

@@ -1,6 +0,0 @@
author: "Fikou, ported by TheGamerDK"
delete-after: true
changes:
- rscadd: "Secret Gateways can now be a thing enabled by config. They are not on the repository, instead, loaded from a config folder."
- rscadd: "Adds the secret and anti-phasing z level traits used by Secret Gateways, secret prevents observers from looking at the z level in any way other than observing through another player's eyes"
- experiment: "admin loaded away missions can be secret as well"

View File

@@ -1,4 +0,0 @@
author: "adamsong"
delete-after: true
changes:
- rscadd: "Added more notification methods for tickets with no present admins"

View File

@@ -1,4 +0,0 @@
author: " TemporalOroboros"
delete-after: true
changes:
- tweak: "Added defines for the damage flags. Please use them!"

View File

@@ -1,5 +0,0 @@
author: "cuackles"
delete-after: true
changes:
- rscadd: "Added new makeshift item: makeshift ID"
- imageadd: "added some icons for the makeshift ID"

View File

@@ -1,5 +0,0 @@
author: "MajManatee"
delete-after: true
changes:
- rscadd: "Adds cool new electrical buckshot ammo"
- imageadd: "adds a new yellow, electrically charged shell"

View File

@@ -1,5 +0,0 @@
author: "cuackles"
delete-after: true
changes:
- rscadd: "new snack, vermin bites"
- imageadd: "new snack sprites, vermin bites"

View File

@@ -1,4 +0,0 @@
author: " [tralezab](https://github.com/tralezab), ported to Yogstation by SuperSlayer"
delete-after: true
changes:
- tweak: "Simplemobs now have healthdolls"

View File

@@ -1,4 +0,0 @@
author: "ArcaneMusic, MrDoomBringer, ynot01"
delete-after: true
changes:
- rscadd: "Added Medical Kiosk"

View File

@@ -1,4 +0,0 @@
author: "ynot01"
delete-after: true
changes:
- tweak: "Throwing a body at the wall is no longer silent"

View File

@@ -1,4 +0,0 @@
author: "SomeguyManperson"
delete-after: true
changes:
- bugfix: "sandbag icon should be back"

View File

@@ -1,6 +0,0 @@
author: "MajManatee"
delete-after: true
changes:
- rscadd: "Adds Depleted Uranium Slugs"
- rscadd: "Adds Cryoshot buckshot shells"
- imageadd: "adds unique shells and projectiles for both ammo types"

View File

@@ -1,5 +0,0 @@
author: " @cuackles, MajesticManateee"
delete-after: true
changes:
- rscadd: "Adds new donor beret for myself"
- imageadd: "added sprites for said beret"

View File

@@ -1,4 +0,0 @@
author: "SomeguyManperson"
delete-after: true
changes:
- tweak: "lesser form now costs 1 dna and 5 chemicals, cannot be used if stunned or cuffed"

View File

@@ -1,4 +0,0 @@
author: "SomeguyManperson"
delete-after: true
changes:
- bugfix: "non-combat mechs can no longer throw people"

View File

@@ -1,4 +0,0 @@
author: "ynot01"
delete-after: true
changes:
- bugfix: "Fixed being able to interact with cryo cells from within"

View File

@@ -1,7 +0,0 @@
author: " Mqiib, Nmajask"
delete-after: true
changes:
- rscadd: "The hivemind has found DNA blueprints for a devastating new weapon: the flesh maul!"
- imageadd: "Fixes the changeling tentacle arm sprites being backwards"
- imageadd: "Sprites for new ling item"
- wip: "Balance decisions pending"

View File

@@ -1,4 +0,0 @@
author: "JohnFulpWillard, Tatax, ToastyBiome"
delete-after: true
changes:
- bugfix: "bloodsucker bugfixes"

View File

@@ -1,4 +0,0 @@
author: "Marmio64"
delete-after: true
changes:
- rscadd: "Monster hunter gets interactions with demons of sin"

View File

@@ -1,5 +0,0 @@
author: "SomeguyManperson"
delete-after: true
changes:
- tweak: "touch healing chems (silver sulf/styptic) now heal 75% less damage passively (no change to on touch healing), and can only heal on touch for up to 45 points of damage/chemical"
- tweak: "touch healing chems (silver sulf/styptic) now apply their reagent to the bloodstream when splashed"

View File

@@ -1,4 +0,0 @@
author: "ToasterBiome"
delete-after: true
changes:
- rscadd: "marrow weaver drop uranium"

View File

@@ -1,4 +0,0 @@
author: " Cakey, Cajoes, Ghommie"
delete-after: true
changes:
- imageadd: "added 3/4 sprites for paper bins, paper shredders, fax machines, and towel bins"

View File

@@ -1,6 +0,0 @@
author: "SomeguyManperson"
delete-after: true
changes:
- tweak: "Both advanced stack healing items (adv mesh + medicated suture) have had their stack size increased by 10"
- tweak: "Advanced sutures are applied to wounds twice as fast as normal sutures"
- tweak: "sutures now have 15 items in each stack isntead of 10 because why 10 when mesh has 15"

View File

@@ -1,4 +0,0 @@
author: "SomeguyManperson"
delete-after: true
changes:
- rscadd: "new emote pointdown"

View File

@@ -1,4 +0,0 @@
author: "maxion12345"
delete-after: true
changes:
- rscadd: "Added new airlock to secondary datacore and added secondary datacore to event blacklist for APC failure and anomalies."

View File

@@ -1,4 +0,0 @@
author: "TheGamerdk"
delete-after: true
changes:
- tweak: "An area with an AI data core can no longer experience power failure from random events"

View File

@@ -1,4 +0,0 @@
author: "Chubbygummibear"
delete-after: true
changes:
- rscadd: "Inducers can be used to charge Preternis but this process burns them"

View File

@@ -1,4 +0,0 @@
author: "SomeguyManperson"
delete-after: true
changes:
- bugfix: "embeds will act more often when standing instead of acting more often when lying down"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

View File

@@ -509,6 +509,7 @@
#include "code\datums\diseases\magnitis.dm"
#include "code\datums\diseases\parrotpossession.dm"
#include "code\datums\diseases\pierrot_throat.dm"
#include "code\datums\diseases\plague.dm"
#include "code\datums\diseases\retrovirus.dm"
#include "code\datums\diseases\rhumba_beat.dm"
#include "code\datums\diseases\sleepy.dm"
@@ -2537,6 +2538,7 @@
#include "code\modules\mob\living\simple_animal\hostile\nanotrasen.dm"
#include "code\modules\mob\living\simple_animal\hostile\netherworld.dm"
#include "code\modules\mob\living\simple_animal\hostile\pirate.dm"
#include "code\modules\mob\living\simple_animal\hostile\plague_rat.dm"
#include "code\modules\mob\living\simple_animal\hostile\rat.dm"
#include "code\modules\mob\living\simple_animal\hostile\regalrat.dm"
#include "code\modules\mob\living\simple_animal\hostile\russian.dm"

View File

@@ -49,6 +49,7 @@
mind.transfer_to(controller)
controller.status_flags &= ~GODMODE
controller.Knockdown(120)
to_chat(controller, span_userdanger("The force of being exiled from your bat form knocks you down!"))
controller.adjustBruteLoss(20)
to_chat(controller, span_userdanger("The force of being exiled from your bat form painfully throws you to the ground!"))
qdel()
. = ..()

View File

@@ -140,6 +140,11 @@ Uncomment this and use atomproccall as necessary, then copypaste the output into
ckey = "Majesticmanateee"
unlock_path = /obj/item/clothing/head/peacekeeperberet
/datum/donator_gear/Hisakaki
name = "Transdimensional halo"
ckey = "Hisakaki"
unlock_path = /obj/item/clothing/head/halo
///Generic donator hats, ckey agnostic.
/datum/donator_gear/beanie
name = "Beanie"

View File

@@ -4,7 +4,16 @@
/mob/living/carbon/human/species/egg
race = /datum/species/egg
/mob/living/carbon/human/species/preternis
race = /datum/species/preternis
/mob/living/carbon/human/species/lizard/ashwalker/cosmic
race = /datum/species/lizard/ashwalker/cosmic
/mob/living/carbon/human/species/szlachta
race = /datum/species/szlachta
/mob/living/carbon/human/get_blood_state()
if(NOBLOOD in dna.species.species_traits) //Can't have blood problems if your species doesn't have any blood, innit?
return BLOOD_SAFE
. = ..()
. = ..()

View File

@@ -289,7 +289,8 @@ Difficulty: Insanely Hard
visible_message(span_cult("\The [src] shrieks as the seal on his power breaks and he starts to break apart!"))
new /obj/structure/ladder/unbreakable/goat(loc)
new /obj/item/toy/plush/goatplushie/angry/kinggoat(loc) //If someone dies from this after beating the king goat im going to laugh
new /obj/item/t_scanner/adv_mining_scanner/goat_scanner(loc)
/mob/living/simple_animal/hostile/retaliate/goat/king/death()
..()
OnDeath()