Skip to content

Commit

Permalink
Fixes moths not being able to eat clothes (BeeStation#10699)
Browse files Browse the repository at this point in the history
* tgstation/tgstation#55356

* tgstation/tgstation#61082

* final touchups

* bad vars oopsies

* fix bad armor var

* dumb span
  • Loading branch information
Tsar-Salat authored Mar 5, 2024
1 parent 2c9146f commit f4fe24f
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 64 deletions.
109 changes: 56 additions & 53 deletions code/datums/armor.dm
Original file line number Diff line number Diff line change
@@ -1,73 +1,76 @@
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]-[stamina]"
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]-[stamina]-[consume]"

/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, stamina = 0)
. = locate(ARMORID)
if (!.)
. = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, stamina)
/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, stamina = 0, consume = 0)
. = locate(ARMORID)
if (!.)
. = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, stamina, consume)

/datum/armor
datum_flags = DF_USE_TAG
var/melee
var/bullet
var/laser
var/energy
var/bomb
var/bio
var/rad
var/fire
var/acid
var/magic
var/stamina
datum_flags = DF_USE_TAG
var/melee
var/bullet
var/laser
var/energy
var/bomb
var/bio
var/rad
var/fire
var/acid
var/magic
var/stamina
var/consume

/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, stamina = 0)
src.melee = melee
src.bullet = bullet
src.laser = laser
src.energy = energy
src.bomb = bomb
src.bio = bio
src.rad = rad
src.fire = fire
src.acid = acid
src.magic = magic
src.stamina = stamina
tag = ARMORID
/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, stamina = 0, consume = 0)
src.melee = melee
src.bullet = bullet
src.laser = laser
src.energy = energy
src.bomb = bomb
src.bio = bio
src.rad = rad
src.fire = fire
src.acid = acid
src.magic = magic
src.stamina = stamina
src.consume = consume
tag = ARMORID

/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, stamina = 0)
return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic, src.stamina+stamina)
/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, stamina = 0, consume = 0)
return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic, src.stamina+stamina, src.consume+consume)

/datum/armor/proc/modifyAllRatings(modifier = 0)
return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier, stamina+modifier)
return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier, stamina+modifier, consume+modifier)

/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
return getArmor((isnull(melee) ? src.melee : melee),\
(isnull(bullet) ? src.bullet : bullet),\
(isnull(laser) ? src.laser : laser),\
(isnull(energy) ? src.energy : energy),\
(isnull(bomb) ? src.bomb : bomb),\
(isnull(bio) ? src.bio : bio),\
(isnull(rad) ? src.rad : rad),\
(isnull(fire) ? src.fire : fire),\
(isnull(acid) ? src.acid : acid),\
(isnull(magic) ? src.magic : magic),\
(isnull(stamina) ? src.stamina : stamina))
/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, consume)
return getArmor((isnull(melee) ? src.melee : melee),\
(isnull(bullet) ? src.bullet : bullet),\
(isnull(laser) ? src.laser : laser),\
(isnull(energy) ? src.energy : energy),\
(isnull(bomb) ? src.bomb : bomb),\
(isnull(bio) ? src.bio : bio),\
(isnull(rad) ? src.rad : rad),\
(isnull(fire) ? src.fire : fire),\
(isnull(acid) ? src.acid : acid),\
(isnull(magic) ? src.magic : magic),\
(isnull(stamina) ? src.stamina : stamina),\
(isnull(consume) ? src.consume : consume))

/datum/armor/proc/getRating(rating)
return vars[rating]
return vars[rating]

/datum/armor/proc/getList()
return list(MELEE = melee, BULLET = bullet, LASER = laser, ENERGY = energy, BOMB = bomb, BIO = bio, RAD = rad, FIRE = fire, ACID = acid, MAGIC = magic, STAMINA = stamina)
return list(MELEE = melee, BULLET = bullet, LASER = laser, ENERGY = energy, BOMB = bomb, BIO = bio, RAD = rad, FIRE = fire, ACID = acid, MAGIC = magic, STAMINA = stamina, CONSUME = consume)

/datum/armor/proc/attachArmor(datum/armor/AA)
return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic, stamina+AA.stamina)
return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic, stamina+AA.stamina, consume+AA.consume)

/datum/armor/proc/detachArmor(datum/armor/AA)
return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic, stamina-AA.stamina)
return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic, stamina-AA.stamina, consume+AA.consume)

/datum/armor/vv_edit_var(var_name, var_value)
if (var_name == NAMEOF(src, tag))
return FALSE
. = ..()
tag = ARMORID // update tag in case armor values were edited
if (var_name == NAMEOF(src, tag))
return FALSE
. = ..()
tag = ARMORID // update tag in case armor values were edited

#undef ARMORID
60 changes: 51 additions & 9 deletions code/modules/clothing/clothing.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#define SENSORS_TRACKING 3
#define SENSOR_CHANGE_DELAY 1.5 SECONDS

#define MOTH_EATING_CLOTHING_DAMAGE 15

/obj/item/clothing
name = "clothing"
resistance_flags = FLAMMABLE
Expand Down Expand Up @@ -52,6 +54,9 @@
var/high_pressure_multiplier = 1
var/static/list/high_pressure_multiplier_types = list(MELEE, BULLET, LASER, ENERGY, BOMB)

/// A lazily initiated "food" version of the clothing for moths
var/obj/item/food/clothing/moth_snack

/obj/item/clothing/Initialize(mapload)
if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE))
actions_types += /datum/action/item_action/toggle_voice_box
Expand All @@ -76,17 +81,45 @@
/obj/item/food/clothing // fuck you
name = "temporary moth clothing snack item"
desc = "If you're reading this it means I messed up. This is related to moths eating clothes and I didn't know a better way to do it than making a new food object." // die
food_reagents = list(/datum/reagent/consumable/nutriment = 1)
bite_consumption = 1
// sigh, ok, so it's not ACTUALLY infinite nutrition. this is so you can eat clothes more than...once.
// bite_consumption limits how much you actually get, and the take_damage in after eat makes sure you can't abuse this.
// ...maybe this was a mistake after all.
food_reagents = list(/datum/reagent/consumable/nutriment = INFINITY)
tastes = list("dust" = 1, "lint" = 1)
foodtypes = CLOTH

/obj/item/clothing/attack(mob/M, mob/user, def_zone)
if(user.a_intent != INTENT_HARM && (ismoth(M) || ispsyphoza(M)) && !(clothing_flags & NOTCONSUMABLE) && !(resistance_flags & INDESTRUCTIBLE) && (armor.getRating(MELEE) == 0))
var/obj/item/food/clothing/clothing_as_food = new // I shall send you to hell in the next PR
clothing_as_food.name = name
if(clothing_as_food.attack(M, user, def_zone))
take_damage(15, sound_effect=FALSE)
qdel(clothing_as_food)
/// A weak reference to the clothing that created us
var/datum/weakref/clothing

/obj/item/food/clothing/make_edible()
AddComponent(/datum/component/edible,\
initial_reagents = food_reagents,\
food_flags = food_flags,\
foodtypes = foodtypes,\
volume = max_volume,\
eat_time = eat_time,\
tastes = tastes,\
eatverbs = eatverbs,\
bite_consumption = bite_consumption,\
microwaved_type = microwaved_type,\
junkiness = junkiness,\
after_eat = CALLBACK(src, PROC_REF(after_eat)))

/obj/item/food/clothing/proc/after_eat(mob/eater)
var/obj/item/clothing/resolved_clothing = clothing.resolve()
if (resolved_clothing)
resolved_clothing.take_damage(MOTH_EATING_CLOTHING_DAMAGE, sound_effect = FALSE, damage_flag = CONSUME)
else
qdel(src)

/obj/item/clothing/attack(mob/attacker, mob/user, def_zone)
if(user.a_intent != INTENT_HARM && (ismoth(attacker) || ispsyphoza(attacker)) && !(clothing_flags & NOTCONSUMABLE) && !(resistance_flags & INDESTRUCTIBLE) && (armor.getRating(MELEE) == 0))
if (isnull(moth_snack))
moth_snack = new
moth_snack.name = name
moth_snack.clothing = WEAKREF(src)
moth_snack.attack(attacker, user, def_zone)
else
return ..()

Expand All @@ -102,6 +135,7 @@

/obj/item/clothing/Destroy()
user_vars_remembered = null //Oh god somebody put REFERENCES in here? not to worry, we'll clean it up
QDEL_NULL(moth_snack)
return ..()

/obj/item/clothing/dropped(mob/user)
Expand Down Expand Up @@ -449,14 +483,20 @@ BLIND // can't see anything
return 1
return 0


/obj/item/clothing/obj_destruction(damage_flag)
if(damage_flag == BOMB || damage_flag == MELEE)
var/turf/T = get_turf(src)
spawn(1) //so the shred survives potential turf change from the explosion.
var/obj/effect/decal/cleanable/shreds/Shreds = new(T)
Shreds.desc = "The sad remains of what used to be [name]."
deconstruct(FALSE)
if(damage_flag == CONSUME) //This allows for moths to fully consume clothing, rather than damaging it like other sources like brute
var/turf/current_position = get_turf(src)
new /obj/effect/decal/cleanable/shreds(current_position, name)
if(isliving(loc))
var/mob/living/possessing_mob = loc
possessing_mob.visible_message("<span class='danger'>[src] is consumed until naught but shreds remains!</span>", "<span class='boldwarning'>[src] falls apart into little bits!</span>")
deconstruct(FALSE)
else
..()

Expand All @@ -475,3 +515,5 @@ BLIND // can't see anything
#undef SENSORS_VITALS
#undef SENSORS_TRACKING
#undef SENSOR_CHANGE_DELAY

#undef MOTH_EATING_CLOTHING_DAMAGE
4 changes: 2 additions & 2 deletions code/modules/unit_tests/food_edibility_check.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
/obj/item/food/grown/mushroom,
/obj/item/food/donkpocket/random,
/obj/item/food/deepfryholder,
//obj/item/food/clothing,
//obj/item/food/meat/slab/human/mutant,
/obj/item/food/clothing,
/obj/item/food/meat/slab/human/mutant,
/obj/item/food/grown/shell)

var/list/food_paths = subtypesof(/obj/item/food) - not_food
Expand Down

0 comments on commit f4fe24f

Please sign in to comment.