Attack chain migration: /mob (#28211)

* Attack chain migration: /mob

* always target zone on attack for tests

* thread corgi item interactions through to parent

* put away razor

* standardize test names

* fix harmbaton not beating + stunning

* fix ID cards not unlocking bots

* fix fulton

* fix fulton shenanigans

* fix tumor shards
This commit is contained in:
warriorstar-orion
2025-03-11 23:37:11 +00:00
committed by GitHub
parent 179dfe6280
commit e69c572b19
46 changed files with 284 additions and 235 deletions
@@ -21,12 +21,13 @@
if(volume > 10) // Anything over 10 volume will make the mob wetter.
wetlevel = min(wetlevel + 1,5)
/mob/living/carbon/attackby__legacy__attackchain(obj/item/I, mob/user, params)
/mob/living/carbon/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(length(surgeries))
if(user.a_intent == INTENT_HELP)
for(var/datum/surgery/S in surgeries)
if(S.next_step(user, src))
return TRUE
return ITEM_INTERACT_COMPLETE
return ..()
/mob/living/carbon/attack_hand(mob/living/carbon/human/user)
@@ -461,10 +461,9 @@ emp_act
w_uniform.add_fingerprint(user)
return ..()
//Returns TRUE if the attack hit, FALSE if it missed.
/mob/living/carbon/human/attacked_by__legacy__attackchain(obj/item/I, mob/living/user, def_zone)
/mob/living/carbon/human/attacked_by(obj/item/I, mob/living/user, def_zone)
if(!I || !user)
return FALSE
return
if(HAS_TRAIT(I, TRAIT_BUTCHERS_HUMANS) && stat == DEAD && user.a_intent == INTENT_HARM)
var/obj/item/food/meat/human/newmeat = new /obj/item/food/meat/human(get_turf(loc))
@@ -479,7 +478,7 @@ emp_act
if(!meatleft)
add_attack_logs(user, src, "Chopped up into meat")
qdel(src)
return FALSE
return
var/obj/item/organ/external/affecting = get_organ(ran_zone(user.zone_selected))
@@ -492,16 +491,16 @@ emp_act
if(user != src)
user.do_attack_animation(src)
if(check_shields(I, I.force, "the [I.name]", MELEE_ATTACK, I.armour_penetration_flat, I.armour_penetration_percentage))
return FALSE
return
send_item_attack_message(I, user, hit_area)
if(!I.force)
return FALSE //item force is zero
return //item force is zero
var/armor = run_armor_check(affecting, MELEE, "<span class='warning'>Your armour has protected your [hit_area].</span>", "<span class='warning'>Your armour has softened hit to your [hit_area].</span>", armour_penetration_flat = I.armour_penetration_flat, armour_penetration_percentage = I.armour_penetration_percentage)
if(armor == INFINITY)
return FALSE
return
var/weapon_sharp = I.sharp
// do not roll for random blunt if the target mob is dead for the ease of decaps
@@ -809,10 +808,10 @@ emp_act
O.water_act(volume, temperature, source, method)
/mob/living/carbon/human/attackby__legacy__attackchain(obj/item/I, mob/user, params)
/mob/living/carbon/human/attack_by(obj/item/I, mob/living/user, params)
if(SEND_SIGNAL(src, COMSIG_HUMAN_ATTACKED, user) & COMPONENT_CANCEL_ATTACK_CHAIN)
return TRUE
return FINISH_ATTACK
return ..()
/mob/living/carbon/human/is_eyes_covered(check_glasses = TRUE, check_head = TRUE, check_mask = TRUE)
@@ -6,10 +6,10 @@
mobility_flags = 0
a_intent = INTENT_HARM // This is apparently the only thing that stops other mobs walking through them as if they were thin air.
/mob/living/silicon/decoy/attackby__legacy__attackchain(obj/item/W, mob/user, params)
/mob/living/silicon/decoy/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/aicard))
to_chat(user, "<span class='warning'>You cannot find an intellicard slot on [src].</span>")
return TRUE
return ITEM_INTERACT_COMPLETE
else
return ..()
+8 -4
View File
@@ -289,7 +289,7 @@
update_icons()
//Overriding this will stop a number of headaches down the track.
/mob/living/silicon/pai/attackby__legacy__attackchain(obj/item/W as obj, mob/user as mob, params)
/mob/living/silicon/pai/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/stack/nanopaste))
var/obj/item/stack/nanopaste/N = W
if(stat == DEAD)
@@ -302,8 +302,13 @@
else
to_chat(user, "<span class='notice'>All [name]'s systems are nominal.</span>")
return
else if(W.force)
return ITEM_INTERACT_COMPLETE
/mob/living/silicon/pai/attack_by(obj/item/W, mob/living/user, params)
if(..())
return FINISH_ATTACK
if(W.force)
visible_message("<span class='danger'>[user.name] attacks [src] with [W]!</span>")
adjustBruteLoss(W.force)
else
@@ -311,7 +316,6 @@
spawn(1)
if(stat != 2)
close_up()
return
/mob/living/silicon/pai/welder_act()
return
@@ -155,10 +155,10 @@
. += "<span class='notice'><i>The ever-loyal workers of Nanotrasen facilities. Known for their small and cute look, these drones seek only to repair damaged parts of the station, being lawed against hurting even a spiderling. These fine drones are programmed against interfering with any business of anyone, so they won't do anything you don't want them to.</i></span>"
//Drones cannot be upgraded with borg modules so we need to catch some items before they get used in ..().
/mob/living/silicon/robot/drone/attackby__legacy__attackchain(obj/item/I, mob/user, params)
/mob/living/silicon/robot/drone/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/borg/upgrade))
to_chat(user, "<span class='warning'>The maintenance drone chassis is not compatible with [I].</span>")
return
return ITEM_INTERACT_COMPLETE
else if(istype(I, /obj/item/card/id) || istype(I, /obj/item/pda))
if(stat == DEAD)
@@ -186,7 +186,7 @@
drones++
if(drones < config.max_maint_drones)
request_player()*/
return
return ITEM_INTERACT_COMPLETE
else
var/confirm = tgui_alert(user, "Using your ID on a Maintenance Drone will shut it down, are you sure you want to do this?", "Disable Drone", list("Yes", "No"))
@@ -201,9 +201,9 @@
else
to_chat(user, "<span class='warning'>Access denied.</span>")
return
return ITEM_INTERACT_COMPLETE
..()
return ..()
/mob/living/silicon/robot/drone/crowbar_act(mob/user, obj/item/I)
. = TRUE
@@ -921,7 +921,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return 2
/mob/living/silicon/robot/attackby__legacy__attackchain(obj/item/W, mob/user, params)
/mob/living/silicon/robot/item_interaction(mob/living/user, obj/item/W, list/modifiers)
// Check if the user is trying to insert another component like a radio, actuator, armor etc.
if(istype(W, /obj/item/robot_parts/robot_component) && opened)
for(var/V in components)
@@ -930,22 +930,22 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
continue
if(!user.drop_item())
to_chat(user, "<span class='warning'>[W] seems to be stuck in your hand!</span>")
return
return ITEM_INTERACT_COMPLETE
var/obj/item/robot_parts/robot_component/WC = W
C.brute_damage = WC.brute
C.electronics_damage = WC.burn
C.install(WC)
to_chat(usr, "<span class='notice'>You install [W].</span>")
return
return ITEM_INTERACT_COMPLETE
if(istype(W, /obj/item/stack/cable_coil) && user.a_intent == INTENT_HELP && (wiresexposed || isdrone(src)))
user.changeNext_move(CLICK_CD_MELEE)
if(!getFireLoss())
to_chat(user, "<span class='notice'>Nothing to fix!</span>")
return
return ITEM_INTERACT_COMPLETE
else if(!getFireLoss(TRUE))
to_chat(user, "<span class='warning'>The damaged components are beyond saving!</span>")
return
return ITEM_INTERACT_COMPLETE
var/obj/item/stack/cable_coil/coil = W
adjustFireLoss(-30)
updatehealth()
@@ -976,13 +976,13 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
module?.update_cells()
diag_hud_set_borgcell()
return ITEM_INTERACT_COMPLETE
else if(istype(W, /obj/item/encryptionkey/) && opened)
if(radio)//sanityyyyyy
radio.attackby__legacy__attackchain(W,user)//GTFO, you have your own procs
else
to_chat(user, "Unable to locate a radio.")
return ITEM_INTERACT_COMPLETE
else if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda)) // trying to unlock the interface with an ID card
if(emagged)//still allow them to open the cover
to_chat(user, "The interface seems slightly damaged.")
@@ -996,7 +996,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
update_icons()
else
to_chat(user, "<span class='warning'>Access denied.</span>")
return ITEM_INTERACT_COMPLETE
else if(istype(W, /obj/item/borg/upgrade/))
var/obj/item/borg/upgrade/U = W
if(!opened)
@@ -1006,18 +1006,18 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
else
if(U.action(user, src))
user.visible_message("<span class='notice'>[user] applied [U] to [src].</span>", "<span class='notice'>You apply [U] to [src].</span>")
return ITEM_INTERACT_COMPLETE
else if(istype(W, /obj/item/mmi_radio_upgrade))
if(!opened)
to_chat(user, "<span class='warning'>You must access the borg's internals!</span>")
return
return ITEM_INTERACT_COMPLETE
else if(!mmi)
to_chat(user, "<span class='warning'>This cyborg does not have an MMI to augment!</span>")
return
return ITEM_INTERACT_COMPLETE
else if(mmi.radio)
to_chat(user, "<span class='warning'>A radio upgrade is already installed in the MMI!</span>")
return
return ITEM_INTERACT_COMPLETE
else if(user.drop_item())
to_chat(user, "<span class='notice'>You apply the upgrade to [src].</span>")
to_chat(src, "<span class='notice'>MMI radio capability installed.</span>")
@@ -1133,7 +1133,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
/mob/living/silicon/robot/attacked_by__legacy__attackchain(obj/item/I, mob/living/user, def_zone)
/mob/living/silicon/robot/attacked_by(obj/item/I, mob/living/user, def_zone)
if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt.
spark_system.start()
..()
@@ -118,10 +118,10 @@
return
cham_proj.attack_self__legacy__attackchain(src)
/mob/living/silicon/robot/syndicate/saboteur/attackby__legacy__attackchain()
/mob/living/silicon/robot/syndicate/saboteur/attack_by(obj/item/attacking, mob/living/user, params)
. = ..()
if(cham_proj)
cham_proj.disrupt(src)
..()
/mob/living/silicon/robot/syndicate/saboteur/attack_hand()
if(cham_proj)
@@ -286,10 +286,14 @@
return 2
/mob/living/silicon/attacked_by__legacy__attackchain(obj/item/I, mob/living/user, def_zone)
/mob/living/silicon/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/clothing/head) && user.a_intent == INTENT_HELP)
place_on_head(user.get_active_hand(), user)
return TRUE
return ITEM_INTERACT_COMPLETE
return ..()
/mob/living/silicon/attacked_by(obj/item/I, mob/living/user, def_zone)
send_item_attack_message(I, user)
if(I.force)
var/bonus_damage = 0
@@ -1,9 +1,7 @@
/mob/living/simple_animal/attackby__legacy__attackchain(obj/item/O, mob/living/user)
/mob/living/simple_animal/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(can_collar && istype(O, /obj/item/petcollar) && !pcollar)
add_collar(O, user)
return
else
return ..()
return ITEM_INTERACT_COMPLETE
/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M)
..()
@@ -423,44 +423,44 @@
/mob/living/simple_animal/bot/proc/interact(mob/user)
show_controls(user)
/mob/living/simple_animal/bot/attackby__legacy__attackchain(obj/item/W, mob/user, params)
/mob/living/simple_animal/bot/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda))
if(allowed(user) && !open && !emagged)
locked = !locked
to_chat(user, "Controls are now [locked ? "locked." : "unlocked."]")
return
return ITEM_INTERACT_COMPLETE
if(emagged)
to_chat(user, "<span class='danger'>ERROR</span>")
if(open)
to_chat(user, "<span class='warning'>Please close the access panel before locking it.</span>")
else
to_chat(user, "<span class='warning'>Access denied.</span>")
return
return ITEM_INTERACT_COMPLETE
if(istype(W, /obj/item/paicard))
if(paicard)
to_chat(user, "<span class='warning'>A [paicard] is already inserted!</span>")
return
return ITEM_INTERACT_COMPLETE
if(!allow_pai || key)
to_chat(user, "<span class='warning'>[src] is not compatible with [W].</span>")
return
return ITEM_INTERACT_COMPLETE
if(locked || open || hijacked)
to_chat(user, "<span class='warning'>The personality slot is locked.</span>")
return
return ITEM_INTERACT_COMPLETE
var/obj/item/paicard/card = W
if(!card.pai?.mind)
to_chat(user, "<span class='warning'>[W] is inactive.</span>")
return
return ITEM_INTERACT_COMPLETE
if(!card.pai.ckey || jobban_isbanned(card.pai, ROLE_SENTIENT))
to_chat(user, "<span class='warning'>[W] is unable to establish a connection to [src].</span>")
return
return ITEM_INTERACT_COMPLETE
if(!user.drop_item())
return
return ITEM_INTERACT_COMPLETE
W.forceMove(src)
paicard = card
@@ -471,20 +471,19 @@
name = paicard.pai.name
faction = user.faction
add_attack_logs(user, paicard.pai, "Uploaded to [src.bot_name]")
return
return ITEM_INTERACT_COMPLETE
if(istype(W, /obj/item/hemostat) && paicard)
if(open)
to_chat(user, "<span class='warning'>Close the access panel before manipulating the personality slot!</span>")
return
return ITEM_INTERACT_COMPLETE
to_chat(user, "<span class='notice'>You attempt to pull [paicard] free...</span>")
if(do_after(user, 30 * W.toolspeed, target = src))
if(paicard)
user.visible_message("<span class='notice'>[user] uses [W] to pull [paicard] out of [bot_name]!</span>","<span class='notice'>You pull [paicard] out of [bot_name] with [W].</span>")
ejectpai(user)
return
return ..()
return ITEM_INTERACT_COMPLETE
/mob/living/simple_animal/bot/screwdriver_act(mob/living/user, obj/item/I)
if(user.a_intent == INTENT_HARM)
@@ -88,7 +88,7 @@
text_dehack = "[name]'s software has been reset!"
text_dehack_fail = "[name] does not seem to respond to your repair code!"
/mob/living/simple_animal/bot/cleanbot/attackby__legacy__attackchain(obj/item/W, mob/user, params)
/mob/living/simple_animal/bot/cleanbot/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/card/id)||istype(W, /obj/item/pda))
if(allowed(user) && !open && !emagged)
locked = !locked
@@ -100,8 +100,10 @@
to_chat(user, "<span class='warning'>Please close the access panel before locking it.</span>")
else
to_chat(user, "<span class='notice'>\The [src] doesn't seem to respect your authority.</span>")
else
return ..()
return ITEM_INTERACT_COMPLETE
return ..()
/mob/living/simple_animal/bot/cleanbot/emag_act(mob/user)
..()
@@ -184,8 +184,10 @@
retaliate(H)
return ..()
/mob/living/simple_animal/bot/ed209/attackby__legacy__attackchain(obj/item/W, mob/user, params)
..()
/mob/living/simple_animal/bot/ed209/attack_by(obj/item/W, mob/living/user, params)
if(..())
return FINISH_ATTACK
if(W.force && !target && W.damtype != STAMINA)
retaliate(user)
if(lasercolor)//To make up for the fact that lasertag bots don't hunt
@@ -133,11 +133,11 @@
if("ejectpai")
ejectpai()
/mob/living/simple_animal/bot/floorbot/attackby__legacy__attackchain(obj/item/W , mob/user, params)
/mob/living/simple_animal/bot/floorbot/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/stack/tile/plasteel))
var/obj/item/stack/tile/plasteel/T = W
if(amount >= MAX_AMOUNT)
return
return ITEM_INTERACT_COMPLETE
var/loaded = min(MAX_AMOUNT - amount, T.amount)
T.use(loaded)
amount += loaded
@@ -147,8 +147,10 @@
update_icon()
else
to_chat(user, "<span class='warning'>You need at least one floor tile to put into [src]!</span>")
else
..()
return ITEM_INTERACT_COMPLETE
return ..()
/mob/living/simple_animal/bot/floorbot/emag_act(mob/user)
..()
@@ -221,14 +221,15 @@
return
return ..()
/mob/living/simple_animal/bot/secbot/griefsky/attackby__legacy__attackchain(obj/item/W, mob/user, params) //cant touch or attack him while spinning
// cant touch or attack him while spinning
/mob/living/simple_animal/bot/secbot/griefsky/attack_by(obj/item/W, mob/living/user, params)
if(..())
return FINISH_ATTACK
if(src.icon_state == spin_icon)
if(prob(block_chance_melee))
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
visible_message("[src] deflects [user]'s move with his energy swords!")
playsound(loc, 'sound/weapons/blade1.ogg', 50, TRUE, -1)
else
return ..()
else
return ..()
return FINISH_ATTACK
@@ -116,13 +116,14 @@
addtimer(CALLBACK(src, PROC_REF(react_buzz)), 5)
return ..()
/mob/living/simple_animal/bot/honkbot/attackby__legacy__attackchain(obj/item/W, mob/user, params)
..()
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) // Any intent but harm will heal, so we shouldn't get angry.
return
if(!isscrewdriver(W) && !locked && (W.force) && (!target) && (W.damtype != STAMINA))//If the target is locked, they are recieving damage from the screwdriver
/mob/living/simple_animal/bot/honkbot/item_interaction(mob/living/user, obj/item/W, list/modifiers)
// If the target is locked, they are recieving damage from the screwdriver
if(!isscrewdriver(W) && !locked && (W.force) && (!target) && (W.damtype != STAMINA))
retaliate(user)
addtimer(CALLBACK(src, PROC_REF(react_buzz)), 5)
return ITEM_INTERACT_COMPLETE
return ..()
/mob/living/simple_animal/bot/honkbot/emag_act(mob/user)
..()
@@ -275,28 +275,31 @@
reagent_glass.forceMove(get_turf(src))
reagent_glass = null
/mob/living/simple_animal/bot/medbot/attackby__legacy__attackchain(obj/item/W, mob/user, params)
/mob/living/simple_animal/bot/medbot/item_interaction(mob/living/user, obj/item/W, list/modifiers)
if(istype(W, /obj/item/reagent_containers/glass))
. = TRUE //no afterattack
if(locked)
to_chat(user, "<span class='warning'>You cannot insert a beaker because the panel is locked!</span>")
return
return ITEM_INTERACT_COMPLETE
if(!isnull(reagent_glass))
to_chat(user, "<span class='warning'>There is already a beaker loaded!</span>")
return
return ITEM_INTERACT_COMPLETE
if(!user.drop_item())
return
return ITEM_INTERACT_COMPLETE
W.forceMove(src)
reagent_glass = W
to_chat(user, "<span class='notice'>You insert [W].</span>")
ui_interact(user)
else
var/current_health = health
..()
if(health < current_health) //if medbot took some damage
step_to(src, (get_step_away(src,user)))
return ITEM_INTERACT_COMPLETE
return ..()
/mob/living/simple_animal/bot/medbot/attacked_by(obj/item/attacker, mob/living/user)
var/current_health = health
. = ..()
if(health < current_health) //if medbot took some damage
step_to(src, (get_step_away(src,user)))
/mob/living/simple_animal/bot/medbot/emag_act(mob/user)
..()
@@ -100,16 +100,18 @@
..()
reached_target = 0
/mob/living/simple_animal/bot/mulebot/attackby__legacy__attackchain(obj/item/I, mob/user, params)
/mob/living/simple_animal/bot/mulebot/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I,/obj/item/stock_parts/cell) && open && !cell)
if(!user.drop_item())
return
return ITEM_INTERACT_COMPLETE
var/obj/item/stock_parts/cell/C = I
C.forceMove(src)
cell = C
visible_message("[user] inserts a cell into [src].",
"<span class='notice'>You insert the new cell into [src].</span>")
update_controls()
update_icon()
return ITEM_INTERACT_COMPLETE
else if(load && ismob(load)) // chance to knock off rider
if(prob(1 + I.force * 2))
unload(0)
@@ -117,11 +119,10 @@
"<span class='danger'>You knock [load] off [src] with \the [I]!</span>")
else
to_chat(user, "<span class='warning'>You hit [src] with \the [I] but to no effect!</span>")
..()
else
..()
update_icon()
return
update_icon()
return ITEM_INTERACT_COMPLETE
return ..()
/mob/living/simple_animal/bot/mulebot/crowbar_act(mob/living/user, obj/item/I)
if(!open || !cell)
@@ -196,8 +196,10 @@
retaliate(H)
return ..()
/mob/living/simple_animal/bot/secbot/attackby__legacy__attackchain(obj/item/W, mob/user, params)
..()
/mob/living/simple_animal/bot/secbot/attacked_by(obj/item/W, mob/living/user)
if(..())
return FINISH_ATTACK
if(W.force && !target && W.damtype != STAMINA)
retaliate(user)
@@ -51,18 +51,16 @@
playsound(src, 'sound/effects/pylon_shatter.ogg', 40, TRUE)
return ..()
/mob/living/simple_animal/hostile/clockwork_construct/clockwork_marauder/attacked_by__legacy__attackchain(obj/item/I, mob/living/user)
/mob/living/simple_animal/hostile/clockwork_construct/clockwork_marauder/attacked_by(obj/item/I, mob/living/user)
if(..())
return FINISH_ATTACK
if(istype(I, /obj/item/nullrod))
adjustFireLoss(15)
if(shield_health > 0)
damage_shield()
playsound(src,'sound/hallucinations/veryfar_noise.ogg', 40, 1)
if((I.tool_behaviour == TOOL_WELDER) && (user.a_intent == INTENT_HELP))
welder_act(user, I)
return
. = ..()
/mob/living/simple_animal/hostile/clockwork_construct/clockwork_marauder/bullet_act(obj/item/projectile/Proj)
if(shield_health > 0)
damage_shield()
@@ -22,7 +22,6 @@
var/last_eaten = 0
footstep_type = FOOTSTEP_MOB_CLAW
var/next_spin_message = 0
var/razor_shave_delay = 5 SECONDS
/mob/living/simple_animal/pet/dog/npc_safe(mob/user)
return TRUE
@@ -84,6 +83,7 @@
var/list/strippable_inventory_slots = list()
var/shaved = FALSE
var/nofur = FALSE //Corgis that have risen past the material plane of existence.
var/razor_shave_delay = 5 SECONDS
/mob/living/simple_animal/pet/dog/corgi/Initialize(mapload)
. = ..()
@@ -185,14 +185,14 @@
armorval += inventory_back.armor.getRating(type)
return armorval * 0.5
/mob/living/simple_animal/pet/dog/corgi/attackby__legacy__attackchain(obj/item/O, mob/user, params)
/mob/living/simple_animal/pet/dog/corgi/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(istype(O, /obj/item/razor))
if(shaved)
to_chat(user, "<span class='warning'>You can't shave this corgi, it's already been shaved!</span>")
return
return ITEM_INTERACT_COMPLETE
if(nofur)
to_chat(user, "<span class='warning'>You can't shave this corgi, it doesn't have a fur coat!</span>")
return
return ITEM_INTERACT_COMPLETE
user.visible_message("<span class='notice'>[user] starts to shave [src] using \the [O].", "<span class='notice'>You start to shave [src] using \the [O]...</span>")
if(do_after(user, razor_shave_delay, target = src))
user.visible_message("<span class='notice'>[user] shaves [src]'s hair using \the [O].</span>")
@@ -204,9 +204,10 @@
icon_state = icon_living
else
icon_state = icon_dead
return
..()
update_corgi_fluff()
update_corgi_fluff()
return ITEM_INTERACT_COMPLETE
return ..()
//Corgis are supposed to be simpler, so only a select few objects can actually be put
//to be compatible with them. The objects are below.
@@ -73,11 +73,10 @@
if(stat == CONSCIOUS)
eat_plants()
/mob/living/simple_animal/hostile/retaliate/goat/attackby__legacy__attackchain(obj/item/O as obj, mob/user as mob, params)
/mob/living/simple_animal/hostile/retaliate/goat/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(stat == CONSCIOUS && istype(O, /obj/item/reagent_containers/glass))
udder.milkAnimal(O, user)
else
return ..()
return ITEM_INTERACT_COMPLETE
/mob/living/simple_animal/hostile/retaliate/goat/proc/eat_plants()
var/eaten = FALSE
@@ -146,12 +145,10 @@
QDEL_NULL(udder)
return ..()
/mob/living/simple_animal/cow/attackby__legacy__attackchain(obj/item/O, mob/user, params)
/mob/living/simple_animal/cow/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(stat == CONSCIOUS && istype(O, /obj/item/reagent_containers/glass))
udder.milkAnimal(O, user)
return TRUE
else
return ..()
return ITEM_INTERACT_COMPLETE
/mob/living/simple_animal/cow/Life(seconds, times_fired)
. = ..()
@@ -319,7 +316,7 @@ GLOBAL_VAR_INIT(chicken_count, 0)
return
GLOB.chicken_count -= 1
/mob/living/simple_animal/chicken/attackby__legacy__attackchain(obj/item/O, mob/user, params)
/mob/living/simple_animal/chicken/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(istype(O, food_type)) //feedin' dem chickens
if(stat == CONSCIOUS && eggsleft < 8)
var/feedmsg = "[user] feeds [O] to [name]! [pick(feedMessages)]"
@@ -330,8 +327,8 @@ GLOBAL_VAR_INIT(chicken_count, 0)
//world << eggsleft
else
to_chat(user, "<span class='warning'>[name] doesn't seem hungry!</span>")
else
..()
return ITEM_INTERACT_COMPLETE
/mob/living/simple_animal/chicken/attack_hand(mob/living/carbon/human/M)
if(M.a_intent == INTENT_HELP)
@@ -124,11 +124,11 @@
else
get_scooped(M)
/mob/living/simple_animal/nian_caterpillar/attacked_by__legacy__attackchain(obj/item/I, mob/living/user, def_zone)
/mob/living/simple_animal/nian_caterpillar/attacked_by(obj/item/I, mob/living/user)
if(..())
return FINISH_ATTACK
if(istype(I, /obj/item/melee/flyswatter) && I.force)
gib() // Commit die.
else
..()
/datum/action/innate/nian_caterpillar_emerge
name = "Evolve"
@@ -7,11 +7,12 @@
speed = 0 // same speed as a person.
hud_type = /datum/hud/corgi
/mob/living/simple_animal/pet/attackby__legacy__attackchain(obj/item/O, mob/user, params)
/mob/living/simple_animal/pet/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(!istype(O, /obj/item/newspaper))
return ..()
var/obj/item/newspaper/paper = O
if(stat != CONSCIOUS || !paper.rolled)
return
return ..()
user.visible_message("<span class='notice'>[user] baps [name] on the nose with the rolled up [O].</span>")
INVOKE_ASYNC(src, PROC_REF(spin), 7 DECISECONDS, 1)
return ITEM_INTERACT_COMPLETE
@@ -46,15 +46,15 @@
eject_brain()
return ..()
/mob/living/simple_animal/spiderbot/attackby__legacy__attackchain(obj/item/O, mob/living/user, params)
/mob/living/simple_animal/spiderbot/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(istype(O, /obj/item/mmi))
var/obj/item/mmi/B = O
if(mmi) //There's already a brain in it.
to_chat(user, "<span class='warning'>There's already a brain in [src]!</span>")
return
return ITEM_INTERACT_COMPLETE
if(!B.brainmob)
to_chat(user, "<span class='warning'>Sticking an empty MMI into the frame would sort of defeat the purpose.</span>")
return
return ITEM_INTERACT_COMPLETE
if(!B.brainmob.key)
var/ghost_can_reenter = 0
if(B.brainmob.mind)
@@ -68,15 +68,15 @@
break
if(!ghost_can_reenter)
to_chat(user, "<span class='notice'>[B] is completely unresponsive; there's no point.</span>")
return
return ITEM_INTERACT_COMPLETE
if(B.brainmob.stat == DEAD)
to_chat(user, "<span class='warning'>[B] is dead. Sticking it into the frame would sort of defeat the purpose.</span>")
return
return ITEM_INTERACT_COMPLETE
if(jobban_isbanned(B.brainmob, "Cyborg") || jobban_isbanned(B.brainmob, "nonhumandept"))
to_chat(user, "<span class='warning'>[B] does not seem to fit.</span>")
return
return ITEM_INTERACT_COMPLETE
to_chat(user, "<span class='notice'>You install [B] in [src]!</span>")
@@ -86,16 +86,16 @@
transfer_personality(B)
update_icon()
return 1
return ITEM_INTERACT_COMPLETE
else if(istype(O, /obj/item/card/id) || istype(O, /obj/item/pda))
if(!mmi)
to_chat(user, "<span class='warning'>There's no reason to swipe your ID - the spiderbot has no brain to remove.</span>")
return 0
return ITEM_INTERACT_COMPLETE
if(emagged)
to_chat(user, "<span class='warning'>[src] doesn't seem to respond.</span>")
return 0
return ITEM_INTERACT_COMPLETE
var/obj/item/card/id/id_card
@@ -108,13 +108,10 @@
if(ACCESS_ROBOTICS in id_card.access)
to_chat(user, "<span class='notice'>You swipe your access card and pop the brain out of [src].</span>")
eject_brain()
return 1
return ITEM_INTERACT_COMPLETE
else
to_chat(user, "<span class='warning'>You swipe your card, with no effect.</span>")
return 0
else
..()
return ITEM_INTERACT_COMPLETE
/mob/living/simple_animal/spiderbot/welder_act(mob/user, obj/item/I)
if(user.a_intent != INTENT_HELP)
@@ -92,8 +92,10 @@
return TRUE
return FALSE
/mob/living/simple_animal/hostile/hellhound/attackby__legacy__attackchain(obj/item/C, mob/user, params)
. = ..()
/mob/living/simple_animal/hostile/hellhound/attacked_by(obj/item/attacker, mob/living/user)
if(..())
return FINISH_ATTACK
if(target && isliving(target))
var/mob/living/L = target
if(L.stat != CONSCIOUS)
@@ -115,10 +115,12 @@
Move(get_step(src, chosen_dir))
face_atom(target) //Looks better if they keep looking at you when dodging
/mob/living/simple_animal/hostile/attacked_by__legacy__attackchain(obj/item/I, mob/living/user)
/mob/living/simple_animal/hostile/attacked_by(obj/item/attacker, mob/living/user)
if(..())
return FINISH_ATTACK
if(stat == CONSCIOUS && !target && AIStatus != AI_OFF && !client && user)
FindTarget(list(user), 1)
return ..()
/mob/living/simple_animal/hostile/bullet_act(obj/item/projectile/P)
if(stat == CONSCIOUS && !target && AIStatus != AI_OFF && !client)
@@ -344,9 +344,12 @@ Difficulty: Hard
if(P.damage)
disable_shield()
/mob/living/simple_animal/hostile/megafauna/ancient_robot/attacked_by__legacy__attackchain(obj/item/I, mob/living/user)
/mob/living/simple_animal/hostile/megafauna/ancient_robot/attacked_by(obj/item/I, mob/living/user)
if(..())
return FINISH_ATTACK
if(!body_shield_enabled)
return ..()
return
do_sparks(2, 1, src)
visible_message("<span class='danger'>[src]'s shield deflects [I] in a shower of sparks!</span>", "<span class='userdanger'>You deflect the attack!</span>")
if(I.force)
@@ -425,14 +425,17 @@ While using this makes the system rely on OnFire, it still gives options for tim
w_class = WEIGHT_CLASS_SMALL
throw_speed = 3
throw_range = 5
new_attack_chain = TRUE
/obj/item/tumor_shard/afterattack__legacy__attackchain(atom/target, mob/user, proximity_flag)
. = ..()
if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite) && proximity_flag)
/obj/item/tumor_shard/interact_with_atom(atom/target, mob/living/user, list/modifiers)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(target)
if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite))
var/mob/living/simple_animal/hostile/asteroid/elite/E = target
if(E.stat != DEAD || E.sentience_type != SENTIENCE_BOSS || !E.key)
user.visible_message("It appears [E] is unable to be revived right now. Perhaps try again later.")
return
return ITEM_INTERACT_COMPLETE
E.faction = list("\ref[user]")
E.friends += user
E.revive()
@@ -453,6 +456,8 @@ While using this makes the system rely on OnFire, it still gives options for tim
else
to_chat(user, "<span class='notice'>[src] only works on the corpse of a sentient lavaland elite.</span>")
return ITEM_INTERACT_COMPLETE
/obj/effect/temp_visual/elite_tumor_wall
name = "magic wall"
icon = 'icons/turf/walls/hierophant_wall_temp.dmi'
@@ -58,12 +58,11 @@
if(udder.reagents.total_volume == udder.reagents.maximum_volume)
add_overlay("gl_full")
/mob/living/simple_animal/hostile/asteroid/gutlunch/attackby__legacy__attackchain(obj/item/O, mob/user, params)
/mob/living/simple_animal/hostile/asteroid/gutlunch/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(stat == CONSCIOUS && istype(O, /obj/item/reagent_containers/glass))
udder.milkAnimal(O, user)
regenerate_icons()
else
return ..()
return ITEM_INTERACT_COMPLETE
/mob/living/simple_animal/hostile/asteroid/gutlunch/CanAttack(atom/the_target) // Gutlunch-specific version of CanAttack to handle stupid stat_exclusive = true crap so we don't have to do it for literally every single simple_animal/hostile except the two that spawn in lavaland
if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids
@@ -151,17 +151,21 @@
src.visible_message("<span class='notice'>[src] was bruised!</span>")
bruised = 1
/mob/living/simple_animal/hostile/mushroom/attackby__legacy__attackchain(obj/item/I as obj, mob/user as mob, params)
/mob/living/simple_animal/hostile/mushroom/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(istype(I, /obj/item/food/grown/mushroom))
if(stat == DEAD && !recovery_cooldown)
Recover()
qdel(I)
else
to_chat(user, "<span class='notice'>[src] won't eat it!</span>")
return
if(I.force)
return ITEM_INTERACT_COMPLETE
/mob/living/simple_animal/hostile/mushroom/attacked_by(obj/item/attacker, mob/living/user)
if(..())
return FINISH_ATTACK
if(attacker.force)
Bruise()
..()
/mob/living/simple_animal/hostile/mushroom/attack_hand(mob/living/carbon/human/M as mob)
..()
@@ -61,7 +61,10 @@
var/melee_block_chance = 20
var/ranged_block_chance = 35
/mob/living/simple_animal/hostile/syndicate/melee/attackby__legacy__attackchain(obj/item/O as obj, mob/user as mob, params)
/mob/living/simple_animal/hostile/syndicate/melee/attack_by(obj/item/O, mob/living/user, params)
if(..())
return FINISH_ATTACK
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
if(O.force)
@@ -81,6 +84,7 @@
to_chat(usr, "<span class='warning'>This weapon is ineffective, it does no damage.</span>")
visible_message("<span class='warning'>[user] gently taps [src] with [O].</span>")
return FINISH_ATTACK
/mob/living/simple_animal/hostile/syndicate/melee/bullet_act(obj/item/projectile/Proj)
if(!Proj)
+12 -12
View File
@@ -177,19 +177,19 @@
return
//Mobs with objects
/mob/living/simple_animal/parrot/attackby__legacy__attackchain(obj/item/O, mob/user, params)
..()
if(stat == CONSCIOUS && !client && !istype(O, /obj/item/stack/medical))
if(O.force)
if(parrot_state == PARROT_PERCH)
parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched
/mob/living/simple_animal/parrot/attacked_by(obj/item/O, mob/living/user)
if(..())
return FINISH_ATTACK
parrot_interest = user
parrot_state = PARROT_SWOOP|PARROT_FLEE
icon_state = "parrot_fly"
ADD_TRAIT(src, TRAIT_FLYING, INNATE_TRAIT)
drop_held_item(FALSE)
return
if(O.force)
if(parrot_state == PARROT_PERCH)
parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched
parrot_interest = user
parrot_state = PARROT_SWOOP|PARROT_FLEE
icon_state = "parrot_fly"
ADD_TRAIT(src, TRAIT_FLYING, INNATE_TRAIT)
drop_held_item(FALSE)
//Bullets
/mob/living/simple_animal/parrot/bullet_act(obj/item/projectile/P)
@@ -173,12 +173,13 @@
set_opacity(possessed_item.opacity)
return ..(NONE)
/mob/living/simple_animal/possessed_object/attackby__legacy__attackchain(obj/item/O, mob/living/user)
. = ..()
/mob/living/simple_animal/possessed_object/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(istype(O, /obj/item/nullrod))
visible_message("<span type='notice'>[O] dispels the spooky aura!</span>")
death()
return ITEM_INTERACT_COMPLETE
/mob/living/simple_animal/possessed_object/throw_impact(atom/hit_atom, throwingdatum)
//Don't call parent here as the mob isn't doing the hitting, technically
return possessed_item.throw_impact(hit_atom, throwingdatum)
@@ -33,12 +33,11 @@
initial_traits = list(TRAIT_FLYING, TRAIT_SHOCKIMMUNE)
var/holy = FALSE
/mob/living/simple_animal/shade/attackby__legacy__attackchain(obj/item/O, mob/user) //Marker -Agouri
/mob/living/simple_animal/shade/item_interaction(mob/living/user, obj/item/O, list/modifiers)
if(istype(O, /obj/item/soulstone))
var/obj/item/soulstone/SS = O
SS.transfer_soul("SHADE", src, user)
else
..()
return ITEM_INTERACT_COMPLETE
/mob/living/simple_animal/shade/Process_Spacemove(movement_dir = 0, continuous_move = FALSE)
return TRUE
@@ -356,35 +356,39 @@
discipline_slime(M)
/mob/living/simple_animal/slime/attackby__legacy__attackchain(obj/item/I, mob/living/user, params)
/mob/living/simple_animal/slime/item_interaction(mob/living/user, obj/item/I, list/modifiers)
if(stat == DEAD && length(surgeries))
if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM)
for(var/datum/surgery/S in surgeries)
if(S.next_step(user, src))
return 1
return ITEM_INTERACT_COMPLETE
if(istype(I, /obj/item/stack/sheet/mineral/plasma) && stat == CONSCIOUS) //Let's you feed slimes plasma.
to_chat(user, "<span class='notice'>You feed the slime the plasma. It chirps happily.</span>")
var/obj/item/stack/sheet/mineral/plasma/S = I
S.use(1)
discipline_slime(user)
return
return ITEM_INTERACT_COMPLETE
if(I.force > 0)
attacked += 10
if(prob(25))
user.do_attack_animation(src)
user.changeNext_move(CLICK_CD_MELEE)
to_chat(user, "<span class='danger'>[I] passes right through [src]!</span>")
return
return ITEM_INTERACT_COMPLETE
if(Discipline && prob(50)) // wow, buddy, why am I getting attacked??
Discipline = 0
return ITEM_INTERACT_COMPLETE
/mob/living/simple_animal/slime/attacked_by(obj/item/I, mob/living/user)
if(..())
return FINISH_ATTACK
if(I.force >= 3)
var/force_effect = 2 * I.force
if(is_adult)
force_effect = round(I.force / 2)
if(prob(10 + force_effect))
discipline_slime(user)
..()
/mob/living/simple_animal/slime/water_act(volume, temperature, source, method = REAGENT_TOUCH)
. = ..()
+1 -1
View File
@@ -27,7 +27,7 @@
/obj/item/holder/attackby__legacy__attackchain(obj/item/W as obj, mob/user as mob, params)
for(var/mob/M in src.contents)
M.attackby__legacy__attackchain(W,user, params)
M.attack_by(W, user, params)
/obj/item/holder/proc/show_message(message, m_type, chat_message_type)
for(var/mob/living/M in contents)
+2
View File
@@ -256,3 +256,5 @@
/// Does this mob speak OOC?
/// Controls whether they can say some symbols.
var/speaks_ooc = FALSE
new_attack_chain = TRUE