Attack chain, initial setup. (pull *immediately* for *any* TM issues) (#26834)

* refactor: Attack chain, initial setup.

* migrate curtain to make dreamchecker happy

* update thurible

* don't call attacked_by separately for legacy attack chain

* remove duplicate proc

* condense similar code, put allowances for legacy code in new procs

* update docs, include diagram source

* add comment on how to update diagram

* fix admonition

* mindflayer updates

* remove commented out code

* clarify all steps

* after_attack should be overridable

* whoops

* retrofit recent changes

* duh, can't restrict this yet because of tool_acts

* i hate ore bags with the fire of a thousand suns

* return correct value for object attack logic

* Various cleanups.

We don't want to attempt to pull stuff out of `/obj/item/attackby`,
because those pieces are part of the related objects' migrations, not
`/obj/item` itself. Attempting to do this causes knockon effects where
things expected to call e.g. `/obj/item/storage/attackby` in the call
chain were not ferried over to the new item interaction code, because
the related objects hadn't actually been migrated over yet.

I've used refactoring /obj/vehicle as the example for migrating
`attackby` methods instead.

* simplify some argument names

* fuck it

* make it do the thing

* Rename CI module call

* Prove that CI works

* improve test output

* aaand fix it again

* fix curtain tool interactions

* fix compile error

* fix compile error

* Better docs, introduce migration plan tool.
This commit is contained in:
warriorstar-orion
2024-12-02 23:36:36 +00:00
committed by GitHub
parent e9e16645e1
commit 525c68d617
724 changed files with 4266 additions and 1862 deletions
@@ -234,7 +234,7 @@
add_fingerprint(usr)
/obj/machinery/chem_dispenser/attackby(obj/item/I, mob/user, params)
/obj/machinery/chem_dispenser/attackby__legacy__attackchain(obj/item/I, mob/user, params)
if(istype(I, /obj/item/storage/part_replacer))
. = ..()
SStgui.update_uis(src)
@@ -446,7 +446,7 @@
/obj/item/handheld_chem_dispenser/get_cell()
return cell
/obj/item/handheld_chem_dispenser/afterattack(obj/target, mob/user, proximity)
/obj/item/handheld_chem_dispenser/afterattack__legacy__attackchain(obj/target, mob/user, proximity)
if(!proximity || !current_reagent || !amount)
return
@@ -470,7 +470,7 @@
if(!target.reagents.isolate_reagent(current_reagent))
to_chat(user, "<span class='notice'>You remove all but [current_reagent] from [target].</span>")
/obj/item/handheld_chem_dispenser/attack_self(mob/user)
/obj/item/handheld_chem_dispenser/attack_self__legacy__attackchain(mob/user)
if(cell)
ui_interact(user)
else
@@ -570,7 +570,7 @@
update_icon(UPDATE_OVERLAYS)
return TRUE
/obj/item/handheld_chem_dispenser/attackby(obj/item/W, mob/user, params)
/obj/item/handheld_chem_dispenser/attackby__legacy__attackchain(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stock_parts/cell))
var/obj/item/stock_parts/cell/C = W
if(cell)
@@ -62,7 +62,7 @@
else
stat |= NOPOWER
/obj/machinery/chem_heater/attackby(obj/item/I, mob/user)
/obj/machinery/chem_heater/attackby__legacy__attackchain(obj/item/I, mob/user)
if(istype(I, /obj/item/reagent_containers/glass) && user.a_intent != INTENT_HARM)
if(beaker)
to_chat(user, "<span class='notice'>A beaker is already loaded into the machine.</span>")
@@ -114,7 +114,7 @@
return
update_icon()
/obj/machinery/chem_master/attackby(obj/item/I, mob/user, params)
/obj/machinery/chem_master/attackby__legacy__attackchain(obj/item/I, mob/user, params)
if(istype(I, /obj/item/storage/part_replacer))
return ..()
@@ -384,7 +384,7 @@
/obj/machinery/computer/pandemic/attack_ghost(mob/user)
ui_interact(user)
/obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params)
/obj/machinery/computer/pandemic/attackby__legacy__attackchain(obj/item/I, mob/user, params)
if(default_unfasten_wrench(user, I, time = 4 SECONDS))
power_change()
return
@@ -157,7 +157,7 @@
return
default_unfasten_wrench(user, I)
/obj/machinery/reagentgrinder/attackby(obj/item/I, mob/user, params)
/obj/machinery/reagentgrinder/attackby__legacy__attackchain(obj/item/I, mob/user, params)
if(istype(I, /obj/item/storage/part_replacer))
..()
SStgui.update_uis(src)
+2 -2
View File
@@ -88,7 +88,7 @@
container_type |= REFILLABLE | DRAINABLE
update_icon(UPDATE_OVERLAYS)
/obj/item/reagent_containers/attack_self(mob/user)
/obj/item/reagent_containers/attack_self__legacy__attackchain(mob/user)
if(has_lid)
if(is_open_container())
to_chat(usr, "<span class='notice'>You put the lid on [src].</span>")
@@ -97,7 +97,7 @@
to_chat(usr, "<span class='notice'>You take the lid off [src].</span>")
remove_lid()
/obj/item/reagent_containers/attack(mob/M, mob/user, def_zone)
/obj/item/reagent_containers/attack__legacy__attackchain(mob/M, mob/user, def_zone)
if(user.a_intent == INTENT_HARM)
return ..()
@@ -96,10 +96,10 @@
update_icon()
user.changeNext_move(CLICK_CD_MELEE)
/obj/item/reagent_containers/applicator/attack(mob/living/M, mob/user)
/obj/item/reagent_containers/applicator/attack__legacy__attackchain(mob/living/M, mob/user)
return apply(M, user)
/obj/item/reagent_containers/applicator/attack_self(mob/user)
/obj/item/reagent_containers/applicator/attack_self__legacy__attackchain(mob/user)
return apply(user, user)
/obj/item/reagent_containers/applicator/proc/apply_to(mob/living/carbon/M, mob/user, multiplier = 1, show_message = TRUE)
@@ -88,7 +88,7 @@
robot.cell.use(charge_cost)
total_reagents = min((total_reagents + BORGHYPO_REFILL_VALUE), maximum_reagents)
/obj/item/reagent_containers/borghypo/attack(mob/living/carbon/human/M, mob/user)
/obj/item/reagent_containers/borghypo/attack__legacy__attackchain(mob/living/carbon/human/M, mob/user)
if(!total_reagents)
to_chat(user, "<span class='warning'>The injector is empty.</span>")
return
@@ -109,7 +109,7 @@
/obj/item/reagent_containers/borghypo/proc/get_radial_contents()
return reagent_icons & reagent_ids
/obj/item/reagent_containers/borghypo/attack_self(mob/user)
/obj/item/reagent_containers/borghypo/attack_self__legacy__attackchain(mob/user)
playsound(loc, 'sound/effects/pop.ogg', 50, 0)
var/selected_reagent = show_radial_menu(user, src, get_radial_contents(), radius = 48)
if(!selected_reagent)
@@ -18,10 +18,10 @@
else
icon_state = "[initial(icon_state)]1"
/obj/item/reagent_containers/dropper/attack(mob/living/M, mob/living/user, def_zone)
/obj/item/reagent_containers/dropper/attack__legacy__attackchain(mob/living/M, mob/living/user, def_zone)
return
/obj/item/reagent_containers/dropper/afterattack(atom/target, mob/user, proximity)
/obj/item/reagent_containers/dropper/afterattack__legacy__attackchain(atom/target, mob/user, proximity)
if(!proximity)
return
var/to_transfer = 0
@@ -113,7 +113,7 @@
//Syndicate item. Virus transmitting mini hypospray
/obj/item/reagent_containers/dropper/precision/viral_injector
/obj/item/reagent_containers/dropper/precision/viral_injector/attack(mob/living/M, mob/living/user, def_zone)
/obj/item/reagent_containers/dropper/precision/viral_injector/attack__legacy__attackchain(mob/living/M, mob/living/user, def_zone)
if(M.can_inject(user, TRUE))
to_chat(user, "<span class='warning'>You stealthily stab [M] with [src].</span>")
if(reagents.total_volume && M.reagents)
@@ -27,7 +27,7 @@
. += "<span class='notice'>[src] can hold up to [reagents.maximum_volume] units.</span>"
/obj/item/reagent_containers/glass/attack(mob/M, mob/user, def_zone)
/obj/item/reagent_containers/glass/attack__legacy__attackchain(mob/M, mob/user, def_zone)
if(!is_open_container())
return ..()
@@ -69,7 +69,7 @@
addtimer(CALLBACK(reagents, TYPE_PROC_REF(/datum/reagents, trans_to), M, 5), 5)
playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1)
/obj/item/reagent_containers/glass/afterattack(obj/target, mob/user, proximity)
/obj/item/reagent_containers/glass/afterattack__legacy__attackchain(obj/target, mob/user, proximity)
if((!proximity) || !check_allowed_items(target, target_self = TRUE))
return
@@ -110,7 +110,7 @@
reagents.reaction(target, REAGENT_TOUCH)
reagents.clear_reagents()
/obj/item/reagent_containers/glass/attackby(obj/item/I, mob/user, params)
/obj/item/reagent_containers/glass/attackby__legacy__attackchain(obj/item/I, mob/user, params)
if(is_pen(I))
var/t = rename_interactive(user, I)
if(!isnull(t))
@@ -171,7 +171,7 @@
if(reagents)
reagents.temperature_reagents(4000)
/obj/item/reagent_containers/glass/beaker/attackby(obj/item/W, mob/user, params)
/obj/item/reagent_containers/glass/beaker/attackby__legacy__attackchain(obj/item/W, mob/user, params)
if(istype(W, /obj/item/assembly_holder) && can_assembly)
if(assembly)
to_chat(usr, "<span class='warning'>[src] already has an assembly.</span>")
@@ -324,7 +324,7 @@
reagents.reaction(user, REAGENT_TOUCH)
reagents.clear_reagents()
/obj/item/reagent_containers/glass/bucket/attackby(obj/D, mob/user, params)
/obj/item/reagent_containers/glass/bucket/attackby__legacy__attackchain(obj/D, mob/user, params)
if(istype(D, /obj/item/mop))
var/obj/item/mop/m = D
m.wet_mop(src, user)
@@ -69,13 +69,13 @@
reagents.reaction(M, REAGENT_INGEST, 0.1)
return TRUE
/obj/item/reagent_containers/hypospray/attack(mob/living/M, mob/user)
/obj/item/reagent_containers/hypospray/attack__legacy__attackchain(mob/living/M, mob/user)
return apply(M, user)
/obj/item/reagent_containers/hypospray/attack_self(mob/user)
/obj/item/reagent_containers/hypospray/attack_self__legacy__attackchain(mob/user)
return apply(user, user)
/obj/item/reagent_containers/hypospray/attackby(obj/item/I, mob/user, params)
/obj/item/reagent_containers/hypospray/attackby__legacy__attackchain(obj/item/I, mob/user, params)
if(is_pen(I))
rename_interactive(user, I, use_prefix = TRUE, prompt = "Give [src] a title.")
return TRUE
@@ -189,7 +189,7 @@
container_type = DRAWABLE
flags = null
/obj/item/reagent_containers/hypospray/autoinjector/attack(mob/M, mob/user)
/obj/item/reagent_containers/hypospray/autoinjector/attack__legacy__attackchain(mob/M, mob/user)
if(!reagents.total_volume)
to_chat(user, "<span class='warning'>[src] is empty!</span>")
return
@@ -197,7 +197,7 @@
update_icon(UPDATE_ICON_STATE)
return TRUE
/obj/item/reagent_containers/hypospray/autoinjector/attack_self(mob/user)
/obj/item/reagent_containers/hypospray/autoinjector/attack_self__legacy__attackchain(mob/user)
..()
update_icon(UPDATE_ICON_STATE)
return TRUE
@@ -268,7 +268,7 @@
volume = 40
list_reagents = list("nanocalcium" = 30, "epinephrine" = 10)
/obj/item/reagent_containers/hypospray/autoinjector/nanocalcium/attack(mob/living/M, mob/user)
/obj/item/reagent_containers/hypospray/autoinjector/nanocalcium/attack__legacy__attackchain(mob/living/M, mob/user)
if(..())
playsound(loc, 'sound/weapons/smg_empty_alarm.ogg', 20, 1)
@@ -281,7 +281,7 @@
container_type = null //No sucking out the reagent
list_reagents = list("zombiecure1" = 15)
/obj/item/reagent_containers/hypospray/autoinjector/zombiecure/attack(mob/living/M, mob/user)
/obj/item/reagent_containers/hypospray/autoinjector/zombiecure/attack__legacy__attackchain(mob/living/M, mob/user)
if(..())
playsound(loc, 'sound/weapons/smg_empty_alarm.ogg', 20, TRUE) //Sucker for sounds, also gets zombies attention.
@@ -32,7 +32,7 @@
..()
update_icon(UPDATE_OVERLAYS)
/obj/item/reagent_containers/iv_bag/attack_self(mob/user)
/obj/item/reagent_containers/iv_bag/attack_self__legacy__attackchain(mob/user)
..()
mode = !mode
update_icon(UPDATE_OVERLAYS)
@@ -87,10 +87,10 @@
injection_target.reagents.trans_id_to(src, reagent.id, amount_per_transfer_from_this / 10)
update_icon(UPDATE_OVERLAYS)
/obj/item/reagent_containers/iv_bag/attack(mob/living/M, mob/living/user, def_zone)
/obj/item/reagent_containers/iv_bag/attack__legacy__attackchain(mob/living/M, mob/living/user, def_zone)
return
/obj/item/reagent_containers/iv_bag/afterattack(atom/target, mob/user, proximity)
/obj/item/reagent_containers/iv_bag/afterattack__legacy__attackchain(atom/target, mob/user, proximity)
if(!proximity)
return
if(!target.reagents)
@@ -157,7 +157,7 @@
if(IV_INJECT)
. += "inject"
/obj/item/reagent_containers/iv_bag/attackby(obj/item/I, mob/user, params)
/obj/item/reagent_containers/iv_bag/attackby__legacy__attackchain(obj/item/I, mob/user, params)
if(is_pen(I))
rename_interactive(user, I)
@@ -12,10 +12,10 @@
var/instant_application = FALSE
var/needs_to_apply_reagents = TRUE
/obj/item/reagent_containers/patch/attack(mob/living/carbon/C, mob/user)
/obj/item/reagent_containers/patch/attack__legacy__attackchain(mob/living/carbon/C, mob/user)
return apply(C, user)
/obj/item/reagent_containers/patch/attack_self(mob/user)
/obj/item/reagent_containers/patch/attack_self__legacy__attackchain(mob/user)
return apply(user, user)
/obj/item/reagent_containers/patch/proc/apply(mob/living/carbon/C, mob/user)
@@ -47,13 +47,13 @@
qdel(src)
return TRUE
/obj/item/reagent_containers/pill/attack(mob/living/carbon/C, mob/user)
/obj/item/reagent_containers/pill/attack__legacy__attackchain(mob/living/carbon/C, mob/user)
return apply(C, user)
/obj/item/reagent_containers/pill/attack_self(mob/user)
/obj/item/reagent_containers/pill/attack_self__legacy__attackchain(mob/user)
return apply(user, user)
/obj/item/reagent_containers/pill/afterattack(obj/target, mob/user, proximity)
/obj/item/reagent_containers/pill/afterattack__legacy__attackchain(obj/target, mob/user, proximity)
if(!proximity || !target.is_refillable())
return
if(target.reagents.holder_full())
@@ -23,7 +23,7 @@
. = ..()
ADD_TRAIT(src, TRAIT_CAN_POINT_WITH, ROUNDSTART_TRAIT)
/obj/item/reagent_containers/spray/afterattack(atom/A, mob/user)
/obj/item/reagent_containers/spray/afterattack__legacy__attackchain(atom/A, mob/user)
if(isstorage(A) || ismodcontrol(A) || istype(A, /obj/structure/table) || istype(A, /obj/structure/rack) || istype(A, /obj/structure/closet) \
|| istype(A, /obj/item/reagent_containers) || istype(A, /obj/structure/sink) || istype(A, /obj/structure/janitorialcart) || istype(A, /obj/machinery/hydroponics))
return
@@ -95,7 +95,7 @@
qdel(D)
/obj/item/reagent_containers/spray/attack_self(mob/user)
/obj/item/reagent_containers/spray/attack_self__legacy__attackchain(mob/user)
amount_per_transfer_from_this = (amount_per_transfer_from_this == 10 ? 5 : 10)
spray_currentrange = (spray_currentrange == 1 ? spray_maxrange : 1)
@@ -135,7 +135,7 @@
amount_per_transfer_from_this = 10
list_reagents = list("cleaner" = 250)
/obj/item/reagent_containers/spray/cleaner/attack_self(mob/user)
/obj/item/reagent_containers/spray/cleaner/attack_self__legacy__attackchain(mob/user)
amount_per_transfer_from_this = (amount_per_transfer_from_this == 5 ? 10 : 5)
spray_currentrange = (spray_currentrange == 1 ? spray_maxrange : 1)
to_chat(user, "<span class='notice'>You [amount_per_transfer_from_this == 5 ? "remove" : "fix"] the nozzle. You'll now use [amount_per_transfer_from_this] units per spray.</span>")
@@ -215,7 +215,7 @@
volume = 10
list_reagents = list("water" = 10)
/obj/item/reagent_containers/spray/waterflower/attack_self(mob/user) //Don't allow changing how much the flower sprays
/obj/item/reagent_containers/spray/waterflower/attack_self__legacy__attackchain(mob/user) //Don't allow changing how much the flower sprays
return
//chemsprayer
@@ -271,7 +271,7 @@
/obj/item/reagent_containers/spray/chemsprayer/attack_self(mob/user)
/obj/item/reagent_containers/spray/chemsprayer/attack_self__legacy__attackchain(mob/user)
amount_per_transfer_from_this = (amount_per_transfer_from_this == 10 ? 5 : 10)
to_chat(user, "<span class='notice'>You adjust the output switch. You'll now use [amount_per_transfer_from_this] units per spray.</span>")
@@ -33,7 +33,7 @@
..()
update_icon()
/obj/item/reagent_containers/syringe/attack_self(mob/user)
/obj/item/reagent_containers/syringe/attack_self__legacy__attackchain(mob/user)
mode = !mode
update_icon()
@@ -41,14 +41,14 @@
..()
update_icon()
/obj/item/reagent_containers/syringe/attack(mob/living/M, mob/living/user, def_zone)
/obj/item/reagent_containers/syringe/attack__legacy__attackchain(mob/living/M, mob/living/user, def_zone)
return
/obj/item/reagent_containers/syringe/attackby(obj/item/I, mob/user, params)
/obj/item/reagent_containers/syringe/attackby__legacy__attackchain(obj/item/I, mob/user, params)
if(istype(I, /obj/item/storage/bag))
..()
/obj/item/reagent_containers/syringe/afterattack(atom/target, mob/user , proximity)
/obj/item/reagent_containers/syringe/afterattack__legacy__attackchain(atom/target, mob/user , proximity)
if(!proximity)
return
if(!target.reagents)
+3 -3
View File
@@ -24,7 +24,7 @@
if(tank_volume && (damage_flag == BULLET || damage_flag == LASER))
boom(FALSE, TRUE)
/obj/structure/reagent_dispensers/attackby(obj/item/I, mob/user, params)
/obj/structure/reagent_dispensers/attackby__legacy__attackchain(obj/item/I, mob/user, params)
if(I.is_refillable())
return FALSE //so we can refill them via their afterattack.
return ..()
@@ -158,7 +158,7 @@
lastrigger = null
overlays.Cut()
/obj/structure/reagent_dispensers/fueltank/attackby(obj/item/I, mob/user, params)
/obj/structure/reagent_dispensers/fueltank/attackby__legacy__attackchain(obj/item/I, mob/user, params)
if(istype(I, /obj/item/assembly_holder) && accepts_rig)
if(rig)
to_chat(user, "<span class='warning'>There is another device in the way.</span>")
@@ -282,7 +282,7 @@
/// If TRUE, prevents the player from inserting the disk again while it is currently exploding.
var/exploding = FALSE
/obj/structure/reagent_dispensers/beerkeg/nuke/attackby(obj/item/O, mob/user, params)
/obj/structure/reagent_dispensers/beerkeg/nuke/attackby__legacy__attackchain(obj/item/O, mob/user, params)
. = ..()
if(exploding)
return