diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 8fc61252ab..e8e74c738e 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -78463,6 +78463,7 @@ /turf/open/floor/engine, /area/science/xenobiology) "dbq" = ( +/mob/living/simple_animal/hostile/retaliate/goose, /turf/open/floor/wood{ icon_state = "wood-broken6" }, diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index c30e0bba80..4edcc47806 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -54391,6 +54391,10 @@ }, /turf/open/floor/plating, /area/maintenance/department/cargo) +"ggg" = ( +/mob/living/simple_animal/hostile/retaliate/goose, +/turf/open/floor/wood, +/area/maintenance/department/crew_quarters/dorms) "gih" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 @@ -99284,7 +99288,7 @@ cBk jhD cBo alQ -alb +ggg cBw noC aiS diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index fed2987a89..a4ae6590bf 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -233,11 +233,15 @@ #define OFFSET_S_STORE "s_store" #define OFFSET_FACEMASK "mask" #define OFFSET_HEAD "head" -#define OFFSET_FACE "face" +#define OFFSET_EYES "eyes" +#define OFFSET_LIPS "lips" #define OFFSET_BELT "belt" #define OFFSET_BACK "back" #define OFFSET_SUIT "suit" #define OFFSET_NECK "neck" +#define OFFSET_HAIR "hair" +#define OFFSET_FHAIR "fhair" +#define OFFSET_MUTPARTS "mutantparts" //MINOR TWEAKS/MISC #define AGE_MIN 18 //youngest a character can be //CITADEL EDIT - 17 --> 18 diff --git a/code/__DEFINES/tools.dm b/code/__DEFINES/tools.dm index 878d35608d..00e08129ae 100644 --- a/code/__DEFINES/tools.dm +++ b/code/__DEFINES/tools.dm @@ -8,6 +8,12 @@ #define TOOL_ANALYZER "analyzer" #define TOOL_MINING "mining" #define TOOL_SHOVEL "shovel" +#define TOOL_RETRACTOR "retractor" +#define TOOL_HEMOSTAT "hemostat" +#define TOOL_CAUTERY "cautery" +#define TOOL_DRILL "drill" +#define TOOL_SCALPEL "scalpel" +#define TOOL_SAW "saw" // If delay between the start and the end of tool operation is less than MIN_TOOL_SOUND_DELAY, diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 4c666d708c..f796f75407 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -157,7 +157,7 @@ var/image/item_overlay = image(holding) item_overlay.alpha = 92 - if(!user.can_equip(holding, slot_id, disable_warning = TRUE)) + if(!user.can_equip(holding, slot_id, TRUE)) item_overlay.color = "#FF0000" else item_overlay.color = "#00ff00" diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm index 6fc58b9f5d..0af90f694c 100644 --- a/code/datums/components/riding.dm +++ b/code/datums/components/riding.dm @@ -162,12 +162,12 @@ if(!Process_Spacemove(direction) || !isturf(AM.loc)) return step(AM, direction) - + if((direction & (direction - 1)) && (AM.loc == next)) //moved diagonally last_move_diagonal = TRUE else last_move_diagonal = FALSE - + handle_vehicle_layer() handle_vehicle_offsets() else @@ -234,7 +234,7 @@ return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(0, 6), TEXT_WEST = list(0, 6)) else return list(TEXT_NORTH = list(0, 6), TEXT_SOUTH = list(0, 6), TEXT_EAST = list(-6, 4), TEXT_WEST = list( 6, 4)) - + /datum/component/riding/human/force_dismount(mob/living/user) var/atom/movable/AM = parent diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index d27357d654..d308d180d0 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -245,6 +245,7 @@ visible_message("[src]'s door slides open. The glowing yellow lights dim to a gentle green.") else visible_message("[src]'s door slides open, barraging you with the nauseating smell of charred flesh.") + mob_occupant.radiation = 0 playsound(src, 'sound/machines/airlockclose.ogg', 25, 1) var/list/things_to_clear = list() //Done this way since using GetAllContents on the SSU itself would include circuitry and such. if(suit) diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm index d539e0a9d5..eb3261bb27 100644 --- a/code/game/mecha/equipment/tools/mining_tools.dm +++ b/code/game/mecha/equipment/tools/mining_tools.dm @@ -13,6 +13,8 @@ energy_drain = 10 force = 15 harmful = TRUE + tool_behaviour = TOOL_DRILL + toolspeed = 0.9 var/drill_delay = 7 var/drill_level = DRILL_BASIC @@ -141,6 +143,7 @@ drill_delay = 4 drill_level = DRILL_HARDENED force = 15 + toolspeed = 0.7 /obj/item/mecha_parts/mecha_equipment/mining_scanner diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm index ea9465184a..36708fcf90 100644 --- a/code/game/mecha/equipment/tools/work_tools.dm +++ b/code/game/mecha/equipment/tools/work_tools.dm @@ -11,6 +11,8 @@ var/dam_force = 20 var/obj/mecha/working/ripley/cargo_holder harmful = TRUE + tool_behaviour = TOOL_RETRACTOR + toolspeed = 0.8 /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj) if(..()) diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index 9c3df5395f..693d32e545 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -89,6 +89,7 @@ buckled_mob.clear_alert("buckled") buckled_mobs -= buckled_mob SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force) + SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, src, force) post_unbuckle_mob(.) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index b1e5505fa8..6a706fede9 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -421,10 +421,10 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) //the mob M is attempting to equip this item into the slot passed through as 'slot'. Return 1 if it can do this and 0 if it can't. //if this is being done by a mob other than M, it will include the mob equipper, who is trying to equip the item to mob M. equipper will be null otherwise. //If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen. -//Set disable_warning to 1 if you wish it to not give you outputs. +//Set disable_warning to TRUE if you wish it to not give you outputs. /obj/item/proc/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE) if(!M) - return 0 + return FALSE return M.can_equip(src, slot, disable_warning, bypass_equip_delay_self) diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index 5e8250ea00..ccb82f7029 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -358,6 +358,8 @@ slot_flags = ITEM_SLOT_BELT attack_verb = list("sawed", "torn", "cut", "chopped", "diced") hitsound = 'sound/weapons/chainsawhit.ogg' + tool_behaviour = TOOL_SAW + toolspeed = 1.5 //slower than a real saw /obj/item/nullrod/claymore/glowing icon_state = "swordon" @@ -513,7 +515,8 @@ slot_flags = ITEM_SLOT_BELT attack_verb = list("sawed", "torn", "cut", "chopped", "diced") hitsound = 'sound/weapons/chainsawhit.ogg' - + tool_behaviour = TOOL_SAW + toolspeed = 0.5 /obj/item/nullrod/hammmer icon_state = "hammeron" @@ -539,6 +542,8 @@ attack_verb = list("sawed", "torn", "cut", "chopped", "diced") hitsound = 'sound/weapons/chainsawhit.ogg' total_mass = TOTAL_MASS_HAND_REPLACEMENT + tool_behaviour = TOOL_SAW + toolspeed = 2 /obj/item/nullrod/chainsaw/Initialize() . = ..() diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm index d854ab9f5a..57b9973aa3 100644 --- a/code/game/objects/items/melee/energy.dm +++ b/code/game/objects/items/melee/energy.dm @@ -142,6 +142,8 @@ w_class = WEIGHT_CLASS_NORMAL sharpness = IS_SHARP light_color = "#40ceff" + tool_behaviour = TOOL_SAW + toolspeed = 0.7 /obj/item/melee/transforming/energy/sword/cyborg/saw/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) return 0 diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index fcadbf4270..c9fc59a3fe 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -89,6 +89,7 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \ resistance_flags = ACID_PROOF merge_type = /obj/item/stack/sheet/plasmaglass grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/toxin/plasma = 10) + tableVariant = /obj/structure/table/plasmaglass /obj/item/stack/sheet/plasmaglass/fifty amount = 50 diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 6532e9f7a5..ad8c4306a5 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -493,12 +493,9 @@ desc = "A large duffel bag for holding surgical tools. Bears the logo of an advanced med-tech firm." /obj/item/storage/backpack/duffelbag/syndie/surgery_adv/PopulateContents() - new /obj/item/hemostat/adv(src) - new /obj/item/circular_saw/adv(src) - new /obj/item/scalpel/adv(src) - new /obj/item/retractor/adv(src) - new /obj/item/cautery/adv(src) - new /obj/item/surgicaldrill/adv(src) + new /obj/item/scalpel/advanced(src) + new /obj/item/retractor/advanced(src) + new /obj/item/surgicaldrill/advanced(src) new /obj/item/surgical_drapes(src) new /obj/item/storage/firstaid/tactical(src) new /obj/item/clothing/suit/straight_jacket(src) diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index 3fe4abeeec..a2b497cc07 100755 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -185,12 +185,9 @@ content_overlays = FALSE /obj/item/storage/belt/medical/surgery_belt_adv/PopulateContents() - new /obj/item/hemostat/adv(src) - new /obj/item/circular_saw/adv(src) - new /obj/item/scalpel/adv(src) - new /obj/item/retractor/adv(src) - new /obj/item/cautery/adv(src) - new /obj/item/surgicaldrill/adv(src) + new /obj/item/scalpel/advanced(src) + new /obj/item/retractor/advanced(src) + new /obj/item/surgicaldrill/advanced(src) new /obj/item/surgical_drapes(src) /obj/item/storage/belt/security diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm index 0c74f610df..b99be7e988 100644 --- a/code/game/objects/items/theft_tools.dm +++ b/code/game/objects/items/theft_tools.dm @@ -232,7 +232,7 @@ . = ..() if(!sliver) return - if(ismovableatom(O) && O != sliver) + if(proximity && ismovableatom(O) && O != sliver) Consume(O, user) /obj/item/hemostat/supermatter/throw_impact(atom/hit_atom) // no instakill supermatter javelins diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm index 49190cdb6c..b1c2c36585 100644 --- a/code/game/objects/items/twohanded.dm +++ b/code/game/objects/items/twohanded.dm @@ -599,6 +599,8 @@ sharpness = IS_SHARP actions_types = list(/datum/action/item_action/startchainsaw) var/on = FALSE + tool_behaviour = TOOL_SAW + toolspeed = 0.5 /obj/item/twohanded/required/chainsaw/Initialize() . = ..() diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 4cb6fc74c0..4552e846ad 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -436,6 +436,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 attack_verb = list("sawed", "torn", "cut", "chopped", "diced") hitsound = 'sound/weapons/chainsawhit.ogg' total_mass = TOTAL_MASS_HAND_REPLACEMENT + tool_behaviour = TOOL_SAW + toolspeed = 1 /obj/item/mounted_chainsaw/Initialize() . = ..() diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index 4a56272ac1..b820e93c7b 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -45,7 +45,7 @@ death = FALSE anchored = FALSE density = FALSE - flavour_text = "You are an ash walker. Your tribe worships the Necropolis. The wastes are sacred ground, its monsters a blessed bounty. \ + flavour_text = "You are an ash walker. Your tribe worships the Necropolis. The wastes are sacred ground, its monsters a blessed bounty. You would never leave its beautiful expanse. \ You have seen lights in the distance... they foreshadow the arrival of outsiders that seek to tear apart the Necropolis and its domain. Fresh sacrifices for your nest." assignedrole = "Ash Walker" diff --git a/code/game/sound.dm b/code/game/sound.dm index 5503c6103d..e7562476a8 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -182,6 +182,8 @@ soundin = pick('sound/voice/beepsky/god.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/beepsky/secureday.ogg', 'sound/voice/beepsky/radio.ogg', 'sound/voice/beepsky/insult.ogg', 'sound/voice/beepsky/creep.ogg') if("honkbot_e") soundin = pick('sound/items/bikehorn.ogg', 'sound/items/AirHorn2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/items/AirHorn.ogg', 'sound/effects/reee.ogg', 'sound/items/WEEOO1.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/beepsky/creep.ogg','sound/magic/Fireball.ogg' ,'sound/effects/pray.ogg', 'sound/voice/hiss1.ogg','sound/machines/buzz-sigh.ogg', 'sound/machines/ping.ogg', 'sound/weapons/flashbang.ogg', 'sound/weapons/bladeslice.ogg') + if("goose") + soundin = pick('sound/creatures/goose1.ogg', 'sound/creatures/goose2.ogg', 'sound/creatures/goose3.ogg', 'sound/creatures/goose4.ogg') //START OF CIT CHANGES - adds random vore sounds if ("struggle_sound") soundin = pick( 'sound/vore/pred/struggle_01.ogg','sound/vore/pred/struggle_02.ogg','sound/vore/pred/struggle_03.ogg', diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 181b72e4a2..ebf6f6626c 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -465,16 +465,21 @@ /turf/AllowDrop() return TRUE -/turf/proc/add_vomit_floor(mob/living/carbon/M, toxvomit = NONE) +/turf/proc/add_vomit_floor(mob/living/M, toxvomit = NONE) + var/obj/effect/decal/cleanable/vomit/V = new /obj/effect/decal/cleanable/vomit(src, M.get_static_viruses()) - // If the vomit combined, apply toxicity and reagents to the old vomit + //if the vomit combined, apply toxicity and reagents to the old vomit if (QDELETED(V)) V = locate() in src // Make toxins and blazaam vomit look different if(toxvomit == VOMIT_PURPLE) V.icon_state = "vomitpurp_[pick(1,4)]" - else if(toxvomit == VOMIT_TOXIC) + else if (toxvomit == VOMIT_TOXIC) V.icon_state = "vomittox_[pick(1,4)]" + if (iscarbon(M)) + var/mob/living/carbon/C = M + if(C.reagents) + clear_reagents_to_vomit_pool(C,V) /proc/clear_reagents_to_vomit_pool(mob/living/carbon/M, obj/effect/decal/cleanable/vomit/V) M.reagents.trans_to(V, M.reagents.total_volume / 10) @@ -487,4 +492,4 @@ //Whatever happens after high temperature fire dies out or thermite reaction works. //Should return new turf /turf/proc/Melt() - return ScrapeAway() \ No newline at end of file + return ScrapeAway() diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm index fa28da74d0..8d845badd4 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -2246,6 +2246,13 @@ contains = list(/mob/living/simple_animal/hostile/retaliate/goat) crate_name = "goat crate" +/datum/supply_pack/critter/goose + name = "Goose Crate" + desc = "Angry and violent birds. Evil, evil creatures." + cost = 2500 + contains = list(/mob/living/simple_animal/hostile/retaliate/goose) + crate_name = "goose crate" + /datum/supply_pack/critter/monkey name = "Monkey Cube Crate" desc = "Stop monkeying around! Contains seven monkey cubes. Just add water!" diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index ed3e9f9b89..20a8c518f4 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -41,6 +41,13 @@ var/dynamic_hair_suffix = ""//head > mask for head hair var/dynamic_fhair_suffix = ""//mask > head for facial hair + //basically a restriction list. + var/list/species_restricted = null + //Basically syntax is species_restricted = list("Species Name","Species Name") + //Add a "exclude" string to do the opposite, making it only only species listed that can't wear it. + //You append this to clothing objects. + + /obj/item/clothing/Initialize() . = ..() if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE)) @@ -338,3 +345,38 @@ BLIND // can't see anything deconstruct(FALSE) else ..() + + +//Species-restricted clothing check. - Thanks Oraclestation, BS13, /vg/station etc. +/obj/item/clothing/mob_can_equip(mob/M, slot, disable_warning = TRUE) + + //if we can't equip the item anyway, don't bother with species_restricted (also cuts down on spam) + if(!..()) + return FALSE + + // Skip species restriction checks on non-equipment slots + if(slot in list(SLOT_IN_BACKPACK, SLOT_L_STORE, SLOT_R_STORE)) + return TRUE + + if(species_restricted && ishuman(M)) + + var/wearable = null + var/exclusive = null + var/mob/living/carbon/human/H = M + + if("exclude" in species_restricted) //TURNS IT INTO A BLACKLIST - AKA ALL MINUS SPECIES LISTED. + exclusive = TRUE + + if(H.dna.species) + if(exclusive) + if(!(H.dna.species.name in species_restricted)) + wearable = TRUE + else + if(H.dna.species.name in species_restricted) + wearable = TRUE + + if(!wearable) + to_chat(M, "Your species cannot wear [src].") + return FALSE + + return TRUE diff --git a/code/modules/goonchat/browserOutput.dm b/code/modules/goonchat/browserOutput.dm index ae49e2cb45..109f6e78e6 100644 --- a/code/modules/goonchat/browserOutput.dm +++ b/code/modules/goonchat/browserOutput.dm @@ -162,7 +162,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico var/list/row = src.connectionHistory[i] if (!row || row.len < 3 || (!row["ckey"] || !row["compid"] || !row["ip"])) //Passed malformed history object return - if (world.IsBanned(row["ckey"], row["compid"], row["ip"], real_bans_only=TRUE)) + if (world.IsBanned(row["ckey"], row["ip"], row["compid"], real_bans_only=TRUE)) found = row break diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 9569d4826c..760fb7a29f 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -158,7 +158,7 @@ //Returns if a certain item can be equipped to a certain slot. // Currently invalid for two-handed items - call obj/item/mob_can_equip() instead. -/mob/proc/can_equip(obj/item/I, slot, disable_warning = 0) +/mob/proc/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE) return FALSE /mob/proc/can_put_in_hand(I, hand_index) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 85dfe66725..02e6043462 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -865,7 +865,7 @@ piggyback(target) return //If you dragged them to you and you're aggressively grabbing try to fireman carry them - else if(user != target && can_be_firemanned(target)) + else if(user != target) fireman_carry(target) return . = ..() diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index b6346bead8..97f5a9f30b 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -9,9 +9,29 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/name // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race - var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows + var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows - var/list/offset_features = list(OFFSET_UNIFORM = list(0,0), OFFSET_ID = list(0,0), OFFSET_GLOVES = list(0,0), OFFSET_GLASSES = list(0,0), OFFSET_EARS = list(0,0), OFFSET_SHOES = list(0,0), OFFSET_S_STORE = list(0,0), OFFSET_FACEMASK = list(0,0), OFFSET_HEAD = list(0,0), OFFSET_FACE = list(0,0), OFFSET_BELT = list(0,0), OFFSET_BACK = list(0,0), OFFSET_SUIT = list(0,0), OFFSET_NECK = list(0,0)) + //Species Icon Drawing Offsets - Pixel X, Pixel Y, Aka X = Horizontal and Y = Vertical, from bottom left corner + var/list/offset_features = list( + OFFSET_UNIFORM = list(0,0), + OFFSET_ID = list(0,0), + OFFSET_GLOVES = list(0,0), + OFFSET_GLASSES = list(0,0), + OFFSET_EARS = list(0,0), + OFFSET_SHOES = list(0,0), + OFFSET_S_STORE = list(0,0), + OFFSET_FACEMASK = list(0,0), + OFFSET_HEAD = list(0,0), + OFFSET_EYES = list(0,0), + OFFSET_LIPS = list(0,0), + OFFSET_BELT = list(0,0), + OFFSET_BACK = list(0,0), + OFFSET_HAIR = list(0,0), + OFFSET_FHAIR = list(0,0), + OFFSET_SUIT = list(0,0), + OFFSET_NECK = list(0,0), + OFFSET_MUTPARTS = list(0,0) + ) var/hair_color // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent. @@ -401,6 +421,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) facial_overlay.alpha = hair_alpha + if(OFFSET_FHAIR in H.dna.species.offset_features) + facial_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FHAIR][1] + facial_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FHAIR][2] + standing += facial_overlay if(H.head) @@ -458,9 +482,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) else hair_overlay.color = forced_colour hair_overlay.alpha = hair_alpha - if(OFFSET_FACE in H.dna.species.offset_features) - hair_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1] - hair_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2] + + if(OFFSET_HAIR in H.dna.species.offset_features) + hair_overlay.pixel_x += H.dna.species.offset_features[OFFSET_HAIR][1] + hair_overlay.pixel_y += H.dna.species.offset_features[OFFSET_HAIR][2] + if(hair_overlay.icon) standing += hair_overlay @@ -481,9 +507,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(H.lip_style && (LIPS in species_traits)) var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[H.lip_style]", -BODY_LAYER) lip_overlay.color = H.lip_color - if(OFFSET_FACE in H.dna.species.offset_features) - lip_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1] - lip_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2] + + if(OFFSET_LIPS in H.dna.species.offset_features) + lip_overlay.pixel_x += H.dna.species.offset_features[OFFSET_LIPS][1] + lip_overlay.pixel_y += H.dna.species.offset_features[OFFSET_LIPS][2] + standing += lip_overlay // eyes @@ -496,9 +524,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER) if((EYECOLOR in species_traits) && has_eyes) eye_overlay.color = "#" + H.eye_color - if(OFFSET_FACE in H.dna.species.offset_features) - eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1] - eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2] + + if(OFFSET_EYES in H.dna.species.offset_features) + eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_EYES][1] + eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_EYES][2] + standing += eye_overlay //Underwear, Undershirts & Socks @@ -851,6 +881,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) for(var/index=1, index<=husklist.len, index++) husklist[index] = husklist[index]/255 accessory_overlay.color = husklist + + if(OFFSET_MUTPARTS in H.dna.species.offset_features) + accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1] + accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2] + standing += accessory_overlay if(S.hasinner) @@ -863,6 +898,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(S.center) inner_accessory_overlay = center_image(inner_accessory_overlay, S.dimension_x, S.dimension_y) + if(OFFSET_MUTPARTS in H.dna.species.offset_features) + inner_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1] + inner_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2] + standing += inner_accessory_overlay if(S.extra) //apply the extra overlay, if there is one @@ -903,6 +942,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(HORNCOLOR) extra_accessory_overlay.color = "#[H.horn_color]" + + if(OFFSET_MUTPARTS in H.dna.species.offset_features) + extra_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1] + extra_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2] + standing += extra_accessory_overlay if(S.extra2) //apply the extra overlay, if there is one @@ -937,6 +981,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) extra2_accessory_overlay.color = "#[H.hair_color]" if(HORNCOLOR) extra2_accessory_overlay.color = "#[H.horn_color]" + + if(OFFSET_MUTPARTS in H.dna.species.offset_features) + extra2_accessory_overlay.pixel_x += H.dna.species.offset_features[OFFSET_MUTPARTS][1] + extra2_accessory_overlay.pixel_y += H.dna.species.offset_features[OFFSET_MUTPARTS][2] + standing += extra2_accessory_overlay @@ -1343,9 +1392,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/obj/item/organ/cyberimp/chest/thrusters/T = H.getorganslot(ORGAN_SLOT_THRUSTERS) if(!istype(J) && istype(C)) J = C.jetpack - if(istype(J) && J.full_speed && J.allow_thrust(0.005, H)) //Prevents stacking + if(istype(J) && J.full_speed && J.allow_thrust(0.01, H)) //Prevents stacking . -= 0.4 - else if(istype(T) && T.allow_thrust(0.005, H)) + else if(istype(T) && T.allow_thrust(0.01, H)) . -= 0.4 if(!ignoreslow && gravity) diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 03c7209152..91ff5a3066 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -709,9 +709,9 @@ generate/load female uniform sprites matching all previously decided variables if(lip_style && (LIPS in dna.species.species_traits)) var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[lip_style]", -BODY_LAYER) lip_overlay.color = lip_color - if(OFFSET_FACE in dna.species.offset_features) - lip_overlay.pixel_x += dna.species.offset_features[OFFSET_FACE][1] - lip_overlay.pixel_y += dna.species.offset_features[OFFSET_FACE][2] + if(OFFSET_LIPS in dna.species.offset_features) + lip_overlay.pixel_x += dna.species.offset_features[OFFSET_LIPS][1] + lip_overlay.pixel_y += dna.species.offset_features[OFFSET_LIPS][2] add_overlay(lip_overlay) // eyes @@ -724,9 +724,9 @@ generate/load female uniform sprites matching all previously decided variables eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER) if((EYECOLOR in dna.species.species_traits) && has_eyes) eye_overlay.color = "#" + eye_color - if(OFFSET_FACE in dna.species.offset_features) - eye_overlay.pixel_x += dna.species.offset_features[OFFSET_FACE][1] - eye_overlay.pixel_y += dna.species.offset_features[OFFSET_FACE][2] + if(OFFSET_EYES in dna.species.offset_features) + eye_overlay.pixel_x += dna.species.offset_features[OFFSET_EYES][1] + eye_overlay.pixel_y += dna.species.offset_features[OFFSET_EYES][2] add_overlay(eye_overlay) dna.species.handle_hair(src) diff --git a/code/modules/mob/living/carbon/monkey/inventory.dm b/code/modules/mob/living/carbon/monkey/inventory.dm index fdc28d13a0..d5fffc70a2 100644 --- a/code/modules/mob/living/carbon/monkey/inventory.dm +++ b/code/modules/mob/living/carbon/monkey/inventory.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/monkey/can_equip(obj/item/I, slot, disable_warning = 0) +/mob/living/carbon/monkey/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE) switch(slot) if(SLOT_HANDS) if(get_empty_held_indexes()) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 46d9525046..d99900187b 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -290,7 +290,7 @@ to_chat(user, "Access denied.") else if(istype(W, /obj/item/paicard)) insertpai(user, W) - else if(istype(W, /obj/item/hemostat) && paicard) + else if(W.tool_behaviour == TOOL_HEMOSTAT && paicard) if(open) to_chat(user, "Close the access panel before manipulating the personality slot!") else diff --git a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm index 3f344c2936..6e89f045da 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm @@ -19,7 +19,7 @@ return 0 -/mob/living/simple_animal/drone/can_equip(obj/item/I, slot) +/mob/living/simple_animal/drone/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE) switch(slot) if(SLOT_HEAD) if(head) diff --git a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm index a43d4b6d5c..52a007e24c 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm @@ -52,7 +52,7 @@ return 1 return 0 -/mob/living/simple_animal/hostile/guardian/dextrous/can_equip(obj/item/I, slot) +/mob/living/simple_animal/hostile/guardian/dextrous/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE) switch(slot) if(SLOT_GENERC_DEXTROUS_STORAGE) if(internal_storage) diff --git a/code/modules/mob/living/simple_animal/hostile/goose.dm b/code/modules/mob/living/simple_animal/hostile/goose.dm new file mode 100644 index 0000000000..b67770fb4b --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/goose.dm @@ -0,0 +1,35 @@ +#define GOOSE_SATIATED 50 + +/mob/living/simple_animal/hostile/retaliate/goose + name = "goose" + desc = "It's loose" + icon_state = "goose" // sprites by cogwerks from goonstation, used with permission + icon_living = "goose" + icon_dead = "goose_dead" + mob_biotypes = list(MOB_ORGANIC, MOB_BEAST) + speak_chance = 0 + turns_per_move = 5 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = 2) + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "kicks" + emote_taunt = list("hisses") + taunt_chance = 30 + speed = 0 + maxHealth = 25 + health = 25 + harm_intent_damage = 5 + melee_damage_lower = 5 + melee_damage_upper = 5 + attacktext = "pecks" + attack_sound = "goose" + speak_emote = list("honks") + faction = list("neutral") + attack_same = TRUE + gold_core_spawnable = HOSTILE_SPAWN + var/random_retaliate = TRUE + +/mob/living/simple_animal/hostile/retaliate/goose/handle_automated_movement() + . = ..() + if(prob(5) && random_retaliate == TRUE) + Retaliate() diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 3e93d9f42b..1759f31344 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -191,7 +191,7 @@ /obj/item/stock_parts/cell/secborg name = "security borg rechargeable D battery" - maxcharge = 1750 //35/17/8 disabler/laser/taser shots. + maxcharge = 1250 //25/12/6 disabler/laser/taser shots. materials = list(MAT_GLASS=40) /obj/item/stock_parts/cell/secborg/empty/Initialize() diff --git a/code/modules/projectiles/ammunition/energy/stun.dm b/code/modules/projectiles/ammunition/energy/stun.dm index c9e60ddc1d..36d6e16496 100644 --- a/code/modules/projectiles/ammunition/energy/stun.dm +++ b/code/modules/projectiles/ammunition/energy/stun.dm @@ -25,3 +25,6 @@ fire_sound = 'sound/weapons/taser2.ogg' harmful = FALSE click_cooldown_override = 3.5 + +/obj/item/ammo_casing/energy/disabler/secborg + e_cost = 50 \ No newline at end of file diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index f455e0f138..a5fb8a85aa 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -277,12 +277,12 @@ ..() if(istype(A, /obj/item/ammo_box) || istype(A, /obj/item/ammo_casing)) chamber_round() + if(A.tool_behaviour == TOOL_SAW || istype(A, /obj/item/gun/energy/plasmacutter)) + sawoff(user) if(istype(A, /obj/item/melee/transforming/energy)) var/obj/item/melee/transforming/energy/W = A if(W.active) sawoff(user) - if(istype(A, /obj/item/circular_saw) || istype(A, /obj/item/gun/energy/plasmacutter)) - sawoff(user) /obj/item/gun/ballistic/revolver/doublebarrel/attack_self(mob/living/user) var/num_unloaded = 0 diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index d1b99c0e3c..47ccb6076f 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -95,7 +95,7 @@ /obj/item/gun/ballistic/shotgun/riot/attackby(obj/item/A, mob/user, params) ..() - if(istype(A, /obj/item/circular_saw) || istype(A, /obj/item/gun/energy/plasmacutter)) + if(A.tool_behaviour == TOOL_SAW || istype(A, /obj/item/gun/energy/plasmacutter)) sawoff(user) if(istype(A, /obj/item/melee/transforming/energy)) var/obj/item/melee/transforming/energy/W = A diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index 3733dad9a3..44c7894467 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -49,6 +49,7 @@ name = "cyborg disabler" desc = "An integrated disabler that draws from a cyborg's power cell. This one contains a limiter to prevent the cyborg's power cell from overheating." can_charge = FALSE + ammo_type = list(/obj/item/ammo_casing/energy/disabler/secborg) selfcharge = EGUN_SELFCHARGE_BORG cell_type = /obj/item/stock_parts/cell/secborg charge_delay = 5 diff --git a/code/modules/reagents/chem_wiki_render.dm b/code/modules/reagents/chem_wiki_render.dm index d4a629c508..efb6bdecfd 100644 --- a/code/modules/reagents/chem_wiki_render.dm +++ b/code/modules/reagents/chem_wiki_render.dm @@ -1,14 +1,46 @@ //Generates a markdown txt file for use with the wiki +/proc/find_reagent(input) + . = FALSE + if(GLOB.chemical_reagents_list[input]) //prefer IDs! + var/datum/reagent/R = GLOB.chemical_reagents_list[input] + return R + else + for(var/X in GLOB.chemical_reagents_list) + var/datum/reagent/R = GLOB.chemical_reagents_list[X] + if(input == replacetext(lowertext(R.name), " ", "")) + return R + if(input == replacetext(lowertext(R.id), " ", "")) + return R + + + + /client/proc/generate_wikichem_list() set name = "Generate Wikichems" set category = "Debug" set desc = "Generate a huge loglist of all the chems. Do not click unless you want lag." - message_admins("Someone pressed the lag button. (Generate Wikichems)") - to_chat(usr, "Generating list") - var/prefix = "|Name | Reagents | Reaction vars | Description | Chem properties |\n|---|---|---|-----------|---|\n" + + var/prefix = "|Name | Reagents | Reaction vars | Description | Chem properties |\n|---|---|---|-----------|---|\n" + var/input_reagent = replacetext(lowertext(input("Input the name/id of a reagent to get it's description on it's own, or leave blank to parse every chem.", "Input") as text), " ", "") //95% of the time, the reagent id is a lowercase/no spaces version of the name + if(input_reagent) + var/input_reagent2 = find_reagent(input_reagent) + if(!input_reagent2) + to_chat(usr, "Unable to find reagent, stopping proc.") + var/single_parse = generate_chemwiki_line(input_reagent2, input_reagent, FALSE) + text2file(single_parse, "[GLOB.log_directory]/chem_parse.md") + to_chat(usr, "[single_parse].") + + single_parse = generate_chemwiki_line(input_reagent2, input_reagent, FALSE) + text2file(single_parse, "[GLOB.log_directory]/chem_parse.md") + to_chat(usr, "[single_parse].") + to_chat(usr, "Saved line to (wherever your root folder is, i.e. where the DME is)/[GLOB.log_directory]/chem_parse.md OR use the Get Current Logs verb under the Admin tab. (if you click Open, and it does nothing, that's because you've not set a .md default program! Try downloading it instead, and use that file to set a default program! Also have a cute day.)") + //Do things here + return + to_chat(usr, "Generating big list") + message_admins("Someone pressed the lag button. (Generate Wikichems)") ///datum/reagent/medicine, /datum/reagent/toxin, /datum/reagent/consumable, /datum/reagent/plantnutriment, /datum/reagent/uranium, ///datum/reagent/colorful_reagent, /datum/reagent/mutationtoxin, /datum/reagent/fermi, /datum/reagent/drug, /datum/reagent/impure @@ -33,7 +65,7 @@ var/alco = "" var/grinded = "" var/blob = "" - //var/impure + var/impure = "" //Chem_dispencer var/list/dispensable_reagents = list( @@ -129,36 +161,46 @@ "applejack" ) - + var/breakout = FALSE for(var/i = 1, i <= 2, i+=1) for(var/X in GLOB.chemical_reagents_list) R = GLOB.chemical_reagents_list[X] + if(!R.description) //No description? It's not worth my time. + continue for(var/Y in dispensable_reagents) //Why do you have to do this if(R.id == Y) basic += generate_chemwiki_line(R, X, processCR) + breakout = TRUE continue for(var/Y in components) if(R.id == Y) upgraded += generate_chemwiki_line(R, X, processCR) + breakout = TRUE continue for(var/Y in dispence_drinks) if(R.id == Y) drinks += generate_chemwiki_line(R, X, processCR) + breakout = TRUE continue for(var/Y in dispence_alco) if(R.id == Y) alco += generate_chemwiki_line(R, X, processCR) + breakout = TRUE continue for(var/Y in grind) if(R.id == Y) grinded += generate_chemwiki_line(R, X, processCR) + breakout = TRUE continue + if(breakout) + breakout = FALSE + continue if(istype(R, /datum/reagent/medicine)) medicine += generate_chemwiki_line(R, X, processCR) @@ -190,10 +232,8 @@ else if(istype(R, /datum/reagent/blob)) blob += generate_chemwiki_line(R, X, processCR) - /* else if(istype(R, /datum/reagent/impure)) impure += generate_chemwiki_line(R, X, processCR) - */ else remainder += generate_chemwiki_line(R, X, processCR) @@ -206,8 +246,8 @@ to_chat(usr, "finished chems") - var/wholeString = ("\n# DISPENCEABLE REAGENTS\n\n[prefix][basic]\n\n# COMPONENT REAGENTS\n\n[prefix][upgraded]\n\n# GRINDABLE REAGENTS\n\n[prefix][grinded]\n") - wholeString += ("\n# MEDICINE:\n\n[prefix][medicine]\n\n# TOXIN:\n\n[prefix][toxin]\n\n# DRUGS\n\n[prefix][drug]\n\n# FERMI\n\nThese chems lie on the cutting edge of chemical technology, and as such are not recommended for beginners!\n\n[prefix][fermi]\n\n# GENERAL REAGENTS\n\n[prefix][remainder]\n\n# DISPENCEABLE SOFT DRINKS\n\n[prefix][drinks]\n\n# DISPENCEABLE HARD DRINKS\n\n[prefix][alco]\n\n# CONSUMABLE\n\n[prefix][consumable]\n\n# PLANTS\n\n[prefix][plant]\n\n# URANIUM\n\n[prefix][uranium]\n\n# COLOURS\n\n[prefix][colours]\n\n# RACE MUTATIONS\n\n[prefix][muta]\n\n\n# BLOB REAGENTS\n\n[prefix][blob]\n") + var/wholeString = ("\n# DISPENCEABLE REAGENTS\n\n[prefix][basic]\n\n# COMPONENT REAGENTS\n\n[prefix][upgraded]\n\n# GROUND REAGENTS\n\n[prefix][grinded]\n") + wholeString += ("\n# MEDICINE:\n\n[prefix][medicine]\n\n# TOXIN:\n\n[prefix][toxin]\n\n# DRUGS\n\n[prefix][drug]\n\n# FERMI\n\nThese chems lie on the cutting edge of chemical technology, and as such are not recommended for beginners!\n\n[prefix][fermi]\n\n# IMPURE REAGENTS\n\n[prefix][impure]\n\n# GENERAL REAGENTS\n\n[prefix][remainder]\n\n# DISPENCEABLE SOFT DRINKS\n\n[prefix][drinks]\n\n# DISPENCEABLE HARD DRINKS\n\n[prefix][alco]\n\n# CONSUMABLE\n\n[prefix][consumable]\n\n# PLANTS\n\n[prefix][plant]\n\n# URANIUM\n\n[prefix][uranium]\n\n# COLOURS\n\n[prefix][colours]\n\n# RACE MUTATIONS\n\n[prefix][muta]\n\n\n# BLOB REAGENTS\n\n[prefix][blob]\n") prefix = "|Name | Reagents | Reaction vars | Description |\n|---|---|---|----------|\n" var/CRparse = "" @@ -257,6 +297,8 @@ //Temp, Explosions and pH if(CR) outstring += "