From 14779ba8d67dadcca5efc807d04fcee85b48d6a1 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Sun, 18 Aug 2024 16:00:26 -0400 Subject: [PATCH] slip refactor (#6665) --- citadel.dme | 9 ++- code/__DEFINES/_flags/atom_flags.dm | 2 +- code/__DEFINES/dcs/components/slippery.dm | 29 +++++++ .../signals_atom/signals_atom_movement.dm | 4 +- code/__DEFINES/traits/atoms.dm | 14 ---- code/__DEFINES/traits/movables.dm | 38 +++++++++ code/datums/components/objects/slippery.dm | 74 ++++++++++++++++++ code/game/atoms/movable/movement.dm | 39 +++------- code/game/objects/effects/chem/foam.dm | 2 +- code/game/objects/items/README.md | 5 ++ code/game/objects/items/devices/PDA/PDA.dm | 2 +- .../clown_items.dm => janitorial/soap.dm} | 72 ++++++++--------- .../objects/items/theatrical/bike_horn.dm | 58 ++++++++++++++ code/game/objects/items/weapons/other.dm | 77 ------------------- code/game/turfs/simulated.dm | 8 +- code/modules/food/food/snacks.dm | 10 +-- code/modules/hydroponics/grown_inedible.dm | 9 +++ .../mob/living/carbon/carbon-defense.dm | 14 ++++ code/modules/mob/living/carbon/carbon.dm | 9 --- .../mob/living/carbon/human/human-defense.dm | 15 ++++ code/modules/mob/living/carbon/human/human.dm | 12 --- code/modules/mob/living/living-defense.dm | 22 ++++++ code/modules/mob/living/living.dm | 3 - code/modules/mob/living/mobility.dm | 2 + code/modules/mob/living/resist.dm | 25 +++--- .../subtypes/animal/borer/borer_captive.dm | 2 +- 26 files changed, 347 insertions(+), 209 deletions(-) create mode 100644 code/__DEFINES/dcs/components/slippery.dm create mode 100644 code/__DEFINES/traits/movables.dm create mode 100644 code/datums/components/objects/slippery.dm create mode 100644 code/game/objects/items/README.md rename code/game/objects/items/{weapons/clown_items.dm => janitorial/soap.dm} (66%) create mode 100644 code/game/objects/items/theatrical/bike_horn.dm create mode 100644 code/modules/mob/living/carbon/carbon-defense.dm create mode 100644 code/modules/mob/living/carbon/human/human-defense.dm create mode 100644 code/modules/mob/living/living-defense.dm diff --git a/citadel.dme b/citadel.dme index 5e16bb43a7c..08e8d2528d4 100644 --- a/citadel.dme +++ b/citadel.dme @@ -165,6 +165,7 @@ #include "code\__DEFINES\dcs\flags.dm" #include "code\__DEFINES\dcs\helpers.dm" #include "code\__DEFINES\dcs\components\riding.dm" +#include "code\__DEFINES\dcs\components\slippery.dm" #include "code\__DEFINES\dcs\signals\global_signals.dm" #include "code\__DEFINES\dcs\signals\signals_area.dm" #include "code\__DEFINES\dcs\signals\signals_datum.dm" @@ -329,6 +330,7 @@ #include "code\__DEFINES\traits\atoms.dm" #include "code\__DEFINES\traits\items.dm" #include "code\__DEFINES\traits\mob.dm" +#include "code\__DEFINES\traits\movables.dm" #include "code\__DEFINES\traits\sources.dm" #include "code\__DEFINES\traits\unsorted.dm" #include "code\__DEFINES\turfs\change_turf.dm" @@ -765,6 +767,7 @@ #include "code\datums\components\items\wielding.dm" #include "code\datums\components\movable\aquarium.dm" #include "code\datums\components\movable\spatial_grid.dm" +#include "code\datums\components\objects\slippery.dm" #include "code\datums\components\riding\riding_filter.dm" #include "code\datums\components\riding\riding_handler.dm" #include "code\datums\components\riding\mob\_mob.dm" @@ -1634,6 +1637,7 @@ #include "code\game\objects\items\id_cards\sprite_stacks_cit.dm" #include "code\game\objects\items\id_cards\station_ids.dm" #include "code\game\objects\items\id_cards\syndicate_ids.dm" +#include "code\game\objects\items\janitorial\soap.dm" #include "code\game\objects\items\robot\gripper.dm" #include "code\game\objects\items\robot\robot_items.dm" #include "code\game\objects\items\robot\robot_parts.dm" @@ -1691,6 +1695,7 @@ #include "code\game\objects\items\storage\single_use\mre.dm" #include "code\game\objects\items\stream_projector\medichine.dm" #include "code\game\objects\items\stream_projector\stream_projector.dm" +#include "code\game\objects\items\theatrical\bike_horn.dm" #include "code\game\objects\items\tools\_tool.dm" #include "code\game\objects\items\tools\crowbar.dm" #include "code\game\objects\items\tools\screwdriver.dm" @@ -1704,7 +1709,6 @@ #include "code\game\objects\items\weapons\bones.dm" #include "code\game\objects\items\weapons\candle.dm" #include "code\game\objects\items\weapons\cigs_lighters.dm" -#include "code\game\objects\items\weapons\clown_items.dm" #include "code\game\objects\items\weapons\cosmetics.dm" #include "code\game\objects\items\weapons\dna_injector.dm" #include "code\game\objects\items\weapons\duct_tape.dm" @@ -3494,6 +3498,7 @@ #include "code\modules\mob\living\health.dm" #include "code\modules\mob\living\inventory.dm" #include "code\modules\mob\living\life.dm" +#include "code\modules\mob\living\living-defense.dm" #include "code\modules\mob\living\living.dm" #include "code\modules\mob\living\living_defines.dm" #include "code\modules\mob\living\living_powers.dm" @@ -3523,6 +3528,7 @@ #include "code\modules\mob\living\bot\secbot.dm" #include "code\modules\mob\living\bot\SLed209bot.dm" #include "code\modules\mob\living\carbon\breathe.dm" +#include "code\modules\mob\living\carbon\carbon-defense.dm" #include "code\modules\mob\living\carbon\carbon.dm" #include "code\modules\mob\living\carbon\carbon_defense.dm" #include "code\modules\mob\living\carbon\carbon_defines.dm" @@ -3577,6 +3583,7 @@ #include "code\modules\mob\living\carbon\human\emote.dm" #include "code\modules\mob\living\carbon\human\examine.dm" #include "code\modules\mob\living\carbon\human\health.dm" +#include "code\modules\mob\living\carbon\human\human-defense.dm" #include "code\modules\mob\living\carbon\human\human.dm" #include "code\modules\mob\living\carbon\human\human_attackhand.dm" #include "code\modules\mob\living\carbon\human\human_damage.dm" diff --git a/code/__DEFINES/_flags/atom_flags.dm b/code/__DEFINES/_flags/atom_flags.dm index 23dfa78116f..8b10246acf6 100644 --- a/code/__DEFINES/_flags/atom_flags.dm +++ b/code/__DEFINES/_flags/atom_flags.dm @@ -115,7 +115,7 @@ DEFINE_BITFIELD(pass_flags_self, list( BITFIELD(ATOM_PASS_BUCKLED), )) -//? /atom/movable movement_type - only one should be on the atom at a time, but these are flags for quick checks. +//? /atom/movable movement_type - only one primary type should be on the atom at a time, but these are flags for quick checks. /// Can not be stopped from moving from Cross(), CanPass(), or Uncross() failing. Still bumps everything it passes through, though. #define MOVEMENT_UNSTOPPABLE (1<<0) /// Ground movement. diff --git a/code/__DEFINES/dcs/components/slippery.dm b/code/__DEFINES/dcs/components/slippery.dm new file mode 100644 index 00000000000..d750d65e9b5 --- /dev/null +++ b/code/__DEFINES/dcs/components/slippery.dm @@ -0,0 +1,29 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station developers. *// + +/** + * Slip classes + * + * Despite being defined in the component file, this may be used basically everywhere. + */ + +/// water slip +#define SLIP_CLASS_WATER (1<<0) +/// lube slip +#define SLIP_CLASS_LUBRICANT (1<<1) +/// oil slip +/// +/// * sensically this is just weaker [SLIP_CLASS_LUBRICANT] +#define SLIP_CLASS_OIL (1<<2) +/// no-grav / no-friction slips +/// +/// * used for very futuristic slips +#define SLIP_CLASS_KINESIS (1<<3) +/// ice-like surfaces +#define SLIP_CLASS_ICE (1<<4) +/// foam surfaces +/// +/// * not necessarily as bad as [SLIP_CLASS_OIL] but also specialized +#define SLIP_CLASS_FOAM (1<<5) + +// todo: DEFINE_BITFIELD_NEW diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm index 8f4a720905d..96e078ed6c8 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm @@ -4,11 +4,13 @@ * * All signals send the source datum of the signal as the first argument */ -/// From base of atom/Entered(): (atom/movable/arrived, atom/old_loc, list/atom/old_locs) +/// From base of atom/Entered(): (atom/movable/arrived, atom/old_loc) /// If you hook this and need to intercept movement, always check if the atom is still in us. If something else is intercepting movement, bad things will happen as the component signal will not stop propagating. +// todo: this does not support multi-tile objects well #define COMSIG_ATOM_ENTERED "atom_entered" /// From base of atom/Exited(): (atom/movable/gone, atom/new_loc) /// If you hook this and need to intercept movement, always check if the atom is still in us. If something else is intercepting movement, bad things will happen as the component signal will not stop propagating. +// todo: this does not support multi-tile objects well #define COMSIG_ATOM_EXITED "atom_exited" /// From base of atom/Bumped(): (/atom/movable) #define COMSIG_ATOM_BUMPED "atom_bumped" diff --git a/code/__DEFINES/traits/atoms.dm b/code/__DEFINES/traits/atoms.dm index 0ee8aaab559..87b019d6aec 100644 --- a/code/__DEFINES/traits/atoms.dm +++ b/code/__DEFINES/traits/atoms.dm @@ -1,17 +1,3 @@ -//? movement -/// flying -/// use add/remove_atom_flying() to modify -#define TRAIT_ATOM_FLYING "atom_flying" -DATUM_TRAIT(/atom, TRAIT_ATOM_FLYING) -/// phsaing -/// use add/remove_atom_phasing() to modify -#define TRAIT_ATOM_PHASING "atom_phasing" -DATUM_TRAIT(/atom, TRAIT_ATOM_PHASING) -/// floating -/// use add/remove_atom_floating() to modify -#define TRAIT_ATOM_FLOATING "atom_floating" -DATUM_TRAIT(/atom, TRAIT_ATOM_FLOATING) - //? radiation /// block contents radiation diff --git a/code/__DEFINES/traits/movables.dm b/code/__DEFINES/traits/movables.dm new file mode 100644 index 00000000000..5329eddd63b --- /dev/null +++ b/code/__DEFINES/traits/movables.dm @@ -0,0 +1,38 @@ +//* Movement, including getters / setters *// + +/// flying +/// use add/remove_atom_flying() to modify +#define TRAIT_MOVABLE_FLYING "atom_flying" +DATUM_TRAIT(/atom, TRAIT_MOVABLE_FLYING) +/// phsaing +/// use add/remove_atom_phasing() to modify +#define TRAIT_MOVABLE_PHASING "atom_phasing" +DATUM_TRAIT(/atom, TRAIT_MOVABLE_PHASING) +/// floating +/// use add/remove_atom_floating() to modify +#define TRAIT_MOVABLE_FLOATING "atom_floating" +DATUM_TRAIT(/atom, TRAIT_MOVABLE_FLOATING) + +/atom/movable/proc/add_atom_flying(source) + ADD_TRAIT(src, TRAIT_MOVABLE_FLYING, source) + update_movement_type() + +/atom/movable/proc/add_atom_phasing(source) + ADD_TRAIT(src, TRAIT_MOVABLE_PHASING, source) + update_movement_type() + +/atom/movable/proc/add_atom_floating(source) + ADD_TRAIT(src, TRAIT_MOVABLE_FLOATING, source) + update_movement_type() + +/atom/movable/proc/remove_atom_flying(source) + REMOVE_TRAIT(src, TRAIT_MOVABLE_FLYING, source) + update_movement_type() + +/atom/movable/proc/remove_atom_phasing(source) + REMOVE_TRAIT(src, TRAIT_MOVABLE_PHASING, source) + update_movement_type() + +/atom/movable/proc/remove_atom_floating(source) + REMOVE_TRAIT(src, TRAIT_MOVABLE_FLOATING, source) + update_movement_type() diff --git a/code/datums/components/objects/slippery.dm b/code/datums/components/objects/slippery.dm new file mode 100644 index 00000000000..4d289083cdf --- /dev/null +++ b/code/datums/components/objects/slippery.dm @@ -0,0 +1,74 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station developers. *// + +/** + * /obj only + * + * * too inefficient for /turf + * * not complex enough for /mob + * + * todo: multi-tile object support + */ +/datum/component/slippery + registered_type = /datum/component/slippery + + var/slip_class = SLIP_CLASS_WATER + var/hard_strength = 5 + var/soft_strength = 10 + +/datum/component/slippery/Initialize(slip_class, hard_strength, soft_strength) + if(!isobj(parent)) + return COMPONENT_INCOMPATIBLE + . = ..() + if(. == COMPONENT_INCOMPATIBLE) + return + + if(!isnull(slip_class)) + src.slip_class = slip_class + if(!isnull(hard_strength)) + src.hard_strength = hard_strength + if(!isnull(soft_strength)) + src.soft_strength = soft_strength + +/datum/component/slippery/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) + if(isturf(parent:loc)) + RegisterSignal(parent:loc, COMSIG_ATOM_ENTERED, PROC_REF(on_enter)) + +/datum/component/slippery/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_MOVABLE_MOVED) + if(isturf(parent:loc)) + UnregisterSignal(parent:loc, COMSIG_ATOM_ENTERED) + +/datum/component/slippery/proc/on_move(atom/movable/source, atom/old_loc) + var/atom/new_loc = source.loc + if(old_loc == new_loc) + return + if(isturf(old_loc)) + UnregisterSignal(old_loc, COMSIG_ATOM_ENTERED) + if(isturf(new_loc)) + RegisterSignal(new_loc, COMSIG_ATOM_ENTERED, PROC_REF(on_enter)) + +/datum/component/slippery/proc/on_enter(turf/source, atom/movable/entering, atom/old_loc) + if(source == parent) + return + // no more locker exploit + // basically, don't slip if they're exiting onto the tile we're on + if(old_loc?.loc == parent:loc) + return + if(!isliving(entering)) + return + var/mob/living/living_entering = entering + // todo: refactor these + if(living_entering.is_incorporeal()) + return + if(living_entering.resting) + return + if(!(living_entering.movement_type & MOVEMENT_GROUND)) + return + // end + + // check for yanks + spawn(0) + if(living_entering.loc == source) + living_entering.slip_act(slip_class, parent, hard_strength, soft_strength) diff --git a/code/game/atoms/movable/movement.dm b/code/game/atoms/movable/movement.dm index 5fdcfdc4271..64c2e193c2b 100644 --- a/code/game/atoms/movable/movement.dm +++ b/code/game/atoms/movable/movement.dm @@ -365,6 +365,9 @@ * Do not do anything that will re-move the atom, or bad things happen. * Use spawn(0) to yield behavior until after the movement call stack is done if you want to do that. * + * todo: old_locs is not actually real used right now + * todo: momentum_change is not actually used right now + * * @params * * old_loc is the location prior to the move. Can be null to indicate nullspace. * * movement_dir is the direction the movement took place. Can be NONE if it was some sort of teleport. @@ -422,8 +425,10 @@ * * Do not do anything that will re-move the atom, or bad things happen. * Use spawn(0) to yield behavior until after the movement call stack is done if you want to do that. + * + * todo: audit all child calls, they should all have the same proc signature as this one. */ -/atom/movable/Crossed(atom/movable/AM, oldloc) +/atom/movable/Crossed(atom/movable/AM) SHOULD_CALL_PARENT(TRUE) . = ..() SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM) @@ -631,7 +636,7 @@ for(var/atom/movable/AM in destination) if(AM == src) continue - AM.Crossed(src, oldloc) + AM.Crossed(src) // moved Moved(oldloc, NONE, TRUE) @@ -786,11 +791,11 @@ var/old_type = movement_type & MOVEMENT_TYPES #define RESET_MOVE_TYPE(type) movement_type = (movement_type & ~(movement_type & MOVEMENT_TYPES)) | type - if(HAS_TRAIT(src, TRAIT_ATOM_PHASING)) + if(HAS_TRAIT(src, TRAIT_MOVABLE_PHASING)) RESET_MOVE_TYPE(MOVEMENT_PHASING) - else if(HAS_TRAIT(src, TRAIT_ATOM_FLYING)) + else if(HAS_TRAIT(src, TRAIT_MOVABLE_FLYING)) RESET_MOVE_TYPE(MOVEMENT_FLYING) - else if(HAS_TRAIT(src, TRAIT_ATOM_FLOATING)) + else if(HAS_TRAIT(src, TRAIT_MOVABLE_FLOATING)) RESET_MOVE_TYPE(MOVEMENT_FLOATING) else RESET_MOVE_TYPE(MOVEMENT_GROUND) @@ -805,30 +810,6 @@ /atom/movable/proc/on_update_movement_type(old_type, new_type) -/atom/movable/proc/add_atom_flying(source) - ADD_TRAIT(src, TRAIT_ATOM_FLYING, source) - update_movement_type() - -/atom/movable/proc/add_atom_phasing(source) - ADD_TRAIT(src, TRAIT_ATOM_PHASING, source) - update_movement_type() - -/atom/movable/proc/add_atom_floating(source) - ADD_TRAIT(src, TRAIT_ATOM_FLOATING, source) - update_movement_type() - -/atom/movable/proc/remove_atom_flying(source) - REMOVE_TRAIT(src, TRAIT_ATOM_FLYING, source) - update_movement_type() - -/atom/movable/proc/remove_atom_phasing(source) - REMOVE_TRAIT(src, TRAIT_ATOM_PHASING, source) - update_movement_type() - -/atom/movable/proc/remove_atom_floating(source) - REMOVE_TRAIT(src, TRAIT_ATOM_FLOATING, source) - update_movement_type() - //? Glide Size /** diff --git a/code/game/objects/effects/chem/foam.dm b/code/game/objects/effects/chem/foam.dm index 9084ec4f48b..85c16ec469a 100644 --- a/code/game/objects/effects/chem/foam.dm +++ b/code/game/objects/effects/chem/foam.dm @@ -87,7 +87,7 @@ return if(slips && istype(AM, /mob/living)) var/mob/living/M = AM - M.slip("the foam", 6) + M.slip_act(SLIP_CLASS_FOAM, src, 5, 7.5) /datum/effect_system/foam_spread /// The size of the foam spread. diff --git a/code/game/objects/items/README.md b/code/game/objects/items/README.md new file mode 100644 index 00000000000..f64d1480e60 --- /dev/null +++ b/code/game/objects/items/README.md @@ -0,0 +1,5 @@ +# Items + +Items should be categorized if possible, because /items is getting uh. Massive. + +Later on, all uncategorized items will go in /misc. diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 7faba817a15..ca79da65190 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -1502,7 +1502,7 @@ GLOBAL_LIST_EMPTY(PDAs) if (istype(AM, /mob/living)) var/mob/living/M = AM - if(M.slip("the PDA",8) && M.real_name != src.owner && istype(src.cartridge, /obj/item/cartridge/clown)) + if(M.slip_act(SLIP_CLASS_LUBRICANT, src, 5, 5) > 0 && M.real_name != src.owner && istype(src.cartridge, /obj/item/cartridge/clown)) if(src.cartridge.charges < 5) src.cartridge.charges++ diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/janitorial/soap.dm similarity index 66% rename from code/game/objects/items/weapons/clown_items.dm rename to code/game/objects/items/janitorial/soap.dm index a2f72b9f9f9..3f71ef89c69 100644 --- a/code/game/objects/items/weapons/clown_items.dm +++ b/code/game/objects/items/janitorial/soap.dm @@ -1,39 +1,27 @@ -/* Clown Items - * Contains: - * Banana Peels - * Soap - * Bike Horns - */ +/datum/component/slippery/soap + +/obj/item/soap + name = "soap" + desc = "A cheap bar of soap. Doesn't smell." + gender = PLURAL + icon = 'icons/obj/items.dmi' + icon_state = "soap" + atom_flags = NOCONDUCT + w_class = WEIGHT_CLASS_SMALL + slot_flags = SLOT_HOLSTER + throw_force = 0 + throw_speed = 4 + throw_range = 20 -/* - * Banana Peals - */ -/obj/item/bananapeel/Crossed(atom/movable/AM as mob|obj) - . = ..() - if(AM.is_incorporeal()) - return - if (istype(AM, /mob/living)) - var/mob/living/M = AM - M.slip("the [src.name]",4) -/* - * Soap - */ /obj/item/soap/Initialize(mapload) . = ..() + AddComponent(/datum/component/slippery/soap) create_reagents(5) wet() /obj/item/soap/proc/wet() reagents.add_reagent("cleaner", 5) -/obj/item/soap/Crossed(atom/movable/AM as mob|obj) - . = ..() - if(AM.is_incorporeal()) - return - if(istype(AM, /mob/living)) - var/mob/living/M = AM - M.slip("the [src.name]",3) - /obj/item/soap/pre_attack(atom/target, mob/user, clickchain_flags, list/params) //I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing. //So this is a workaround. This also makes more sense from an IC standpoint. ~Carn @@ -66,17 +54,21 @@ return CLICKCHAIN_DO_NOT_PROPAGATE return ..() -/* - * Bike Horns - */ -/obj/item/bikehorn/attack_self(mob/user) +/obj/item/soap/nanotrasen + desc = "A Nanotrasen-brand bar of soap. Smells of phoron." + icon_state = "soapnt" + +/obj/item/soap/deluxe + icon_state = "soapdeluxe" + +/obj/item/soap/deluxe/Initialize(mapload) . = ..() - if(.) - return - if (spam_flag == 0) - spam_flag = 1 - playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1) - src.add_fingerprint(user) - spawn(20) - spam_flag = 0 - return + desc = "A deluxe Waffle Co. brand bar of soap. Smells of [pick("lavender", "vanilla", "strawberry", "chocolate" ,"space")]." + +/obj/item/soap/syndie + desc = "An untrustworthy bar of soap. Smells of fear." + icon_state = "soapsyndie" + +/obj/item/soap/primitive + desc = "Lye and fat processed into a solid state. This hand crafted bar is unscented and uneven." + icon_state = "soapprim" diff --git a/code/game/objects/items/theatrical/bike_horn.dm b/code/game/objects/items/theatrical/bike_horn.dm new file mode 100644 index 00000000000..1a893d4a12a --- /dev/null +++ b/code/game/objects/items/theatrical/bike_horn.dm @@ -0,0 +1,58 @@ +// todo: /bike_horn +/obj/item/bikehorn + name = "bike horn" + desc = "A horn off of a bicycle." + icon = 'icons/obj/items.dmi' + icon_state = "bike_horn" + item_state = "bike_horn" + throw_force = 3 + w_class = WEIGHT_CLASS_SMALL + slot_flags = SLOT_HOLSTER + throw_speed = 3 + throw_range = 15 + attack_verb = list("HONKED") + var/spam_flag = 0 + +/obj/item/bikehorn/attack_self(mob/user) + . = ..() + if(.) + return + if (spam_flag == 0) + spam_flag = 1 + playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1) + src.add_fingerprint(user) + spawn(20) + spam_flag = 0 + return + +/obj/item/bikehorn/golden + name = "golden bike horn" + desc = "Golden? Clearly, it's made with bananium! Honk!" + icon_state = "gold_horn" + item_state = "gold_horn" + var/flip_cooldown = 0 + +/* +/obj/item/bikehorn/golden/attack() + if(flip_cooldown < world.time) + flip_mobs() + return ..() + +/obj/item/bikehorn/golden/attack_self(mob/user) + . = ..() + if(.) + return + if(flip_cooldown < world.time) + flip_mobs() + ..() + +/obj/item/bikehorn/golden/proc/flip_mobs(mob/living/carbon/M, mob/user) + var/turf/T = get_turf(src) + for(M in ohearers(7, T)) + if(ishuman(M) && M.can_hear()) + var/mob/living/carbon/human/H = M + if(istype(H.ears, /obj/item/clothing/ears/earmuffs)) + continue + M.emote("flip") + flip_cooldown = world.time + 7 +*/ diff --git a/code/game/objects/items/weapons/other.dm b/code/game/objects/items/weapons/other.dm index 09706596c7e..9b5c907b0eb 100644 --- a/code/game/objects/items/weapons/other.dm +++ b/code/game/objects/items/weapons/other.dm @@ -25,83 +25,6 @@ var/mode = 1 w_class = WEIGHT_CLASS_NORMAL -/obj/item/soap - name = "soap" - desc = "A cheap bar of soap. Doesn't smell." - gender = PLURAL - icon = 'icons/obj/items.dmi' - icon_state = "soap" - atom_flags = NOCONDUCT - w_class = WEIGHT_CLASS_SMALL - slot_flags = SLOT_HOLSTER - throw_force = 0 - throw_speed = 4 - throw_range = 20 - -/obj/item/soap/nanotrasen - desc = "A Nanotrasen-brand bar of soap. Smells of phoron." - icon_state = "soapnt" - -/obj/item/soap/deluxe - icon_state = "soapdeluxe" - -/obj/item/soap/deluxe/Initialize(mapload) - . = ..() - desc = "A deluxe Waffle Co. brand bar of soap. Smells of [pick("lavender", "vanilla", "strawberry", "chocolate" ,"space")]." - -/obj/item/soap/syndie - desc = "An untrustworthy bar of soap. Smells of fear." - icon_state = "soapsyndie" - -/obj/item/soap/primitive - desc = "Lye and fat processed into a solid state. This hand crafted bar is unscented and uneven." - icon_state = "soapprim" - -/obj/item/bikehorn - name = "bike horn" - desc = "A horn off of a bicycle." - icon = 'icons/obj/items.dmi' - icon_state = "bike_horn" - item_state = "bike_horn" - throw_force = 3 - w_class = WEIGHT_CLASS_SMALL - slot_flags = SLOT_HOLSTER - throw_speed = 3 - throw_range = 15 - attack_verb = list("HONKED") - var/spam_flag = 0 - -/obj/item/bikehorn/golden - name = "golden bike horn" - desc = "Golden? Clearly, it's made with bananium! Honk!" - icon_state = "gold_horn" - item_state = "gold_horn" - var/flip_cooldown = 0 - -/* -/obj/item/bikehorn/golden/attack() - if(flip_cooldown < world.time) - flip_mobs() - return ..() - -/obj/item/bikehorn/golden/attack_self(mob/user) - . = ..() - if(.) - return - if(flip_cooldown < world.time) - flip_mobs() - ..() - -/obj/item/bikehorn/golden/proc/flip_mobs(mob/living/carbon/M, mob/user) - var/turf/T = get_turf(src) - for(M in ohearers(7, T)) - if(ishuman(M) && M.can_hear()) - var/mob/living/carbon/human/H = M - if(istype(H.ears, /obj/item/clothing/ears/earmuffs)) - continue - M.emote("flip") - flip_cooldown = world.time + 7 -*/ /obj/item/c_tube name = "cardboard tube" diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 5f79e14e22c..23d5f179ce7 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -139,19 +139,19 @@ var/slip_dist = 1 var/slip_stun = 6 - var/floor_type = "wet" + var/class = SLIP_CLASS_WATER switch(src.wet) if(2) // Lube - floor_type = "slippery" slip_dist = 4 slip_stun = 10 + class = SLIP_CLASS_LUBRICANT if(3) // Ice - floor_type = "icy" slip_stun = 4 slip_dist = 2 + class = SLIP_CLASS_ICE - if(M.slip("the [floor_type] floor", slip_stun)) + if(M.slip_act(class, src, slip_stun, slip_stun) > 0) for(var/i = 1 to slip_dist) step(M, M.dir) sleep(1) diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm index 7d842764f77..f0b26d35619 100644 --- a/code/modules/food/food/snacks.dm +++ b/code/modules/food/food/snacks.dm @@ -4286,6 +4286,8 @@ END CITADEL CHANGE */ nutriment_desc = list("margarine" = 1) nutriment_amt = 20 +/datum/component/slippery/butter + /obj/item/reagent_containers/food/snacks/spreads/butter name = "butter" desc = "A stick of pure butterfat made from milk products." @@ -4294,13 +4296,9 @@ END CITADEL CHANGE */ nutriment_desc = list("butter" = 1) nutriment_amt = 0 -/obj/item/reagent_containers/food/snacks/spreads/butter/Crossed(atom/movable/AM as mob|obj) +/obj/item/reagent_containers/food/snacks/spreads/butter/Initialize(mapload) . = ..() - if(AM.is_incorporeal()) - return - if (istype(AM, /mob/living)) - var/mob/living/M = AM - M.slip("the [src.name]",4) + AddComponent(/datum/component/slippery/butter) /obj/item/reagent_containers/food/snacks/spreads/Initialize(mapload) . = ..() diff --git a/code/modules/hydroponics/grown_inedible.dm b/code/modules/hydroponics/grown_inedible.dm index b9408c95c6b..4e762a248e0 100644 --- a/code/modules/hydroponics/grown_inedible.dm +++ b/code/modules/hydroponics/grown_inedible.dm @@ -49,6 +49,11 @@ qdel(src) return +//* Banana Peels *// + +/datum/component/slippery/banana_peel + +// todo: /banana_peel /obj/item/bananapeel name = "banana peel" desc = "A peel from a banana." @@ -59,3 +64,7 @@ throw_force = 0 throw_speed = 4 throw_range = 20 + +/obj/item/bananapeel/Initialize(mapload) + . = ..() + AddComponent(/datum/component/slippery/banana_peel) diff --git a/code/modules/mob/living/carbon/carbon-defense.dm b/code/modules/mob/living/carbon/carbon-defense.dm new file mode 100644 index 00000000000..63a455454c0 --- /dev/null +++ b/code/modules/mob/living/carbon/carbon-defense.dm @@ -0,0 +1,14 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station developers. *// + +//* Misc Effects *// + +/mob/living/carbon/slip_act(slip_class, source, hard_strength, soft_strength, suppressed) + . = ..() + if(buckled) + return 0 + tactile_feedback(SPAN_WARNING("You slipped on \the [source]!")) + // todo: sound should be on component / tile? + playsound(src, 'sound/misc/slip.ogg', 50, TRUE, -3) + afflict_paralyze(hard_strength) + afflict_knockdown(soft_strength) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 26127f22300..366bba48529 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -252,15 +252,6 @@ /mob/living/carbon/cannot_use_vents() return -/mob/living/carbon/slip(var/slipped_on,stun_duration=8) - if(buckled) - return 0 - stop_pulling() - to_chat(src, "You slipped on [slipped_on]!") - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) - afflict_paralyze(20 * FLOOR(stun_duration/2, 1)) - return 1 - /mob/living/carbon/proc/add_chemical_effect(var/effect, var/magnitude = 1) if(effect in chem_effects) chem_effects[effect] += magnitude diff --git a/code/modules/mob/living/carbon/human/human-defense.dm b/code/modules/mob/living/carbon/human/human-defense.dm new file mode 100644 index 00000000000..09f8eb24c17 --- /dev/null +++ b/code/modules/mob/living/carbon/human/human-defense.dm @@ -0,0 +1,15 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station developers. *// + +//* Misc Effects *// + +/mob/living/carbon/human/slip_act(slip_class, source, hard_strength, soft_strength, suppressed) + var/list/equipment = list(src.w_uniform,src.wear_suit,src.shoes) + var/footcoverage_check = FALSE + for(var/obj/item/clothing/C in equipment) + if(C.body_cover_flags & FEET) + footcoverage_check = TRUE + break + if((species.species_flags & NO_SLIP && !footcoverage_check) || (shoes && (shoes.clothing_flags & NOSLIP))) //Footwear negates a species' natural traction. + return 0 + return ..() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index c267cb56b42..c2005c49631 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1407,18 +1407,6 @@ return 1 return 0 -/mob/living/carbon/human/slip(var/slipped_on, stun_duration=8) - var/list/equipment = list(src.w_uniform,src.wear_suit,src.shoes) - var/footcoverage_check = FALSE - for(var/obj/item/clothing/C in equipment) - if(C.body_cover_flags & FEET) - footcoverage_check = TRUE - break - if((species.species_flags & NO_SLIP && !footcoverage_check) || (shoes && (shoes.clothing_flags & NOSLIP))) //Footwear negates a species' natural traction. - return 0 - if(..(slipped_on,stun_duration)) - return 1 - /mob/living/carbon/human/proc/relocate() set category = VERB_CATEGORY_OBJECT set name = "Relocate Joint" diff --git a/code/modules/mob/living/living-defense.dm b/code/modules/mob/living/living-defense.dm new file mode 100644 index 00000000000..3bdb111c5bc --- /dev/null +++ b/code/modules/mob/living/living-defense.dm @@ -0,0 +1,22 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station developers. *// + +//* Misc Effects *// + +/** + * Processes a slip. + * + * * hard / soft strength are not necessarily directly mapped to stuns + * * hard / soft strength can do a lot more than stun so don't go overboard + * + * @params + * * slip_class - SLIP_CLASS_* flags of what the slip is + * * source - a text string, or an atom, of what the source is + * * hard_strength - nominally the amount of time it'll hardstun someone for; this should be very, very low + * * soft_strength - nominally how strong the slip should be in terms of stun power. this is, optimally, 0 to 100, with the assumption most people go down at 100 + * * suppressed - suppress outgoing sound and text. + * + * @return 0 to 1 for effectiveness, with 0 being 'entirely resisted' and 1 being 'entirely hit' + */ +/mob/living/proc/slip_act(slip_class, source, hard_strength, soft_strength, suppressed) + return 1 diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 4029c9941df..18322f70ef4 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -462,9 +462,6 @@ default behaviour is: return FALSE -/mob/living/proc/slip(var/slipped_on,stun_duration=8) - return 0 - //damage/heal the mob ears and adjust the deaf amount /mob/living/adjustEarDamage(var/damage, var/deaf) ear_damage = max(0, ear_damage + damage) diff --git a/code/modules/mob/living/mobility.dm b/code/modules/mob/living/mobility.dm index 9f0697f8561..64edf2557f2 100644 --- a/code/modules/mob/living/mobility.dm +++ b/code/modules/mob/living/mobility.dm @@ -22,6 +22,8 @@ stop_pulling() if(!(mobility_flags & MOBILITY_CAN_STAND)) set_resting(TRUE) + else if(resting) + auto_resist_rest() /** * immediately sets whether or not we're prone. diff --git a/code/modules/mob/living/resist.dm b/code/modules/mob/living/resist.dm index 6b01f7b4836..80177bf2a5a 100644 --- a/code/modules/mob/living/resist.dm +++ b/code/modules/mob/living/resist.dm @@ -3,17 +3,23 @@ set category = VERB_CATEGORY_IC if(!incapacitated(INCAPACITATION_KNOCKOUT) && canClick()) - setClickCooldown(20) - resist_grab() if(CHECK_MOBILITY(src, MOBILITY_CAN_RESIST)) - process_resist() + // this means execute both and get as boolean + // this is done so resist doesn't always invoke clickcd + if(resist_grab() | process_resist()) + setClickCooldown(20) +// todo: refactor +// todo: resist doing normal clickcd is kinda weird +/** + * @return TRUE if we should apply resist delay + */ /mob/living/proc/process_resist() if(!CHECK_MOBILITY(src, MOBILITY_CAN_RESIST)) - return + return FALSE if(SEND_SIGNAL(src, COMSIG_MOB_PROCESS_RESIST) & COMPONENT_MOB_RESIST_INTERRUPT) - return + return TRUE //unbuckling yourself if(buckled) @@ -27,24 +33,25 @@ return TRUE if(resist_fire()) - return + return TRUE if(resist_restraints()) - return + return TRUE if(isbelly(loc)) var/obj/belly/B = loc B.relay_resist(src) - return + return TRUE if(resist_a_rest()) - return + return FALSE /mob/living/proc/resist_grab() var/resisting = 0 for(var/obj/item/grab/G in grabbed_by) resisting++ G.handle_resist() + . = TRUE if(resisting) visible_message("[src] resists!") diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_captive.dm b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_captive.dm index e65d580f316..ffbbf0d713f 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_captive.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/borer/borer_captive.dm @@ -54,6 +54,6 @@ remove_verb(src, /mob/living/carbon/proc/punish_host) remove_verb(src, /mob/living/carbon/proc/spawn_larvae) - return + return TRUE ..()