From bfe122dd26a74fc955bbbb02d1c326af1e119e06 Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Fri, 27 Jan 2023 19:19:54 +1100 Subject: [PATCH] Mashing trained drake logic down to base drake level. Harness are now removable. --- .../subtypes/animal/_animal_harness.dm | 147 ++++++++++++++++-- .../animal/sif/grafadreka/grafadreka.dm | 86 ++++++++-- .../sif/grafadreka/grafadreka_harness.dm | 31 ++-- .../animal/sif/grafadreka/grafadreka_misc.dm | 2 + .../sif/grafadreka/grafadreka_trained.dm | 73 +-------- icons/mob/drake_harness.dmi | Bin 1674 -> 1930 bytes maps/cynosure/cynosure_jobs.dm | 11 +- 7 files changed, 224 insertions(+), 126 deletions(-) diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/_animal_harness.dm b/code/modules/mob/living/simple_mob/subtypes/animal/_animal_harness.dm index 2833c3caf9..f60f8ed04f 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/_animal_harness.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/_animal_harness.dm @@ -1,11 +1,22 @@ -/obj/item/storage/internal/animal_harness - abstract_type = /obj/item/storage/internal/animal_harness +/obj/item/storage/animal_harness + abstract_type = /obj/item/storage/animal_harness name = "animal harness" color = COLOR_BEASTY_BROWN max_w_class = ITEMSIZE_LARGE max_storage_space = INVENTORY_STANDARD_SPACE icon_state = "harness" icon = 'icons/mob/drake_harness.dmi' + preserve_item = TRUE + + // keys for animal_harness/attachable_type + var/const/ATTACHED_GPS = "gps" + var/const/ATTACHED_RADIO = "radio" + var/const/ATTACHED_ARMOR = "armor plate" + var/const/ATTACHED_LIGHT = "light" + var/const/ATTACHED_ID = "access card" + + /// Contains valid types that the harness will attach to. + var/list/harnessable_types /// Null, or a list of (/obj/item/foo = "item key"), or (/path = ("item key", proc/handler)). var/list/attachable_types @@ -20,10 +31,10 @@ var/other_attach_delay = 3 SECONDS -/obj/item/storage/internal/animal_harness/Destroy() +/obj/item/storage/animal_harness/Destroy() var/mob/living/simple_mob/animal/wearer = loc if (istype(wearer) && wearer.harness == src) - wearer.harness = null + wearer.clear_harness() for (var/key in attached_items) var/obj/item/item = attached_items[key] qdel(item) @@ -32,7 +43,7 @@ return ..() -/obj/item/storage/internal/animal_harness/Initialize() +/obj/item/storage/animal_harness/Initialize() . = ..() if (!attachable_types) return @@ -43,11 +54,15 @@ CreateAttachments() -/obj/item/storage/internal/animal_harness/LateInitializeName() +/obj/item/storage/animal_harness/GetIdCard() + return attached_items[ATTACHED_ID] + + +/obj/item/storage/animal_harness/LateInitializeName() return -/obj/item/storage/internal/animal_harness/attackby(obj/item/item, mob/living/user, silent) +/obj/item/storage/animal_harness/attackby(obj/item/item, mob/living/user, silent) . = TRUE if (user == loc) // Animals can only shove stuff in their storage. return ..() @@ -78,7 +93,7 @@ return ..() -/obj/item/storage/internal/animal_harness/proc/GetAttachedKeys() +/obj/item/storage/animal_harness/proc/GetAttachedKeys() var/list/obj/item/result = list() for (var/key in attached_items) if (attached_items[key]) @@ -86,7 +101,7 @@ return result -/obj/item/storage/internal/animal_harness/proc/GetAttachedItems() +/obj/item/storage/animal_harness/proc/GetAttachedItems() var/list/obj/item/result = list() for (var/key in attached_items) var/obj/item/item = attached_items[key] @@ -95,7 +110,7 @@ return result -/obj/item/storage/internal/animal_harness/proc/RemoveAttachment(obj/item/attachment) +/obj/item/storage/animal_harness/proc/RemoveAttachment(obj/item/attachment) if (istext(attachment)) var/obj/item/item = attached_items[attachment] if (!item) @@ -110,12 +125,29 @@ return attachment -/obj/item/storage/internal/animal_harness/proc/CreateAttachments() +/obj/item/storage/animal_harness/proc/CreateAttachments() return /mob/living/simple_mob/animal - var/obj/item/storage/internal/animal_harness/harness + var/obj/item/storage/animal_harness/harness + + +/mob/living/simple_mob/animal/attackby(obj/item/O, mob/user) + if(istype(O, /obj/item/storage/animal_harness)) + if(harness) + to_chat(user, SPAN_WARNING("\The [src] is already wearing \the [harness].")) + return TRUE + var/obj/item/storage/animal_harness/new_harness = O + if(!is_type_in_list(src, new_harness.harnessable_types)) + to_chat(user, SPAN_WARNING("\The [new_harness] does not fit on \the [src].")) + return TRUE + if(user.unEquip(new_harness, src)) + set_harness(new_harness) + user.visible_message(SPAN_NOTICE("\The [user] slips \the [harness] over \the [src] and buckles it securely.")) + update_icon() + return TRUE + return ..() /mob/living/simple_mob/animal/Destroy() @@ -126,10 +158,44 @@ /mob/living/simple_mob/animal/Initialize() . = ..() - if (ispath(harness)) - harness = new harness (src) - verbs += /mob/living/simple_mob/animal/proc/RemoveAttachmentVerb + if(harness) + if(ispath(harness)) + set_harness(new harness(src)) + else if(!istype(harness)) + clear_harness() +/mob/living/simple_mob/animal/proc/clear_harness() + if(!harness) + return FALSE + if(istype(harness)) + var/turf/drop_loc = get_turf(src) + for (var/key in harness.attached_items) + var/obj/item/item = harness.attached_items[key] + if(item) + harness.RemoveAttachment(item) + item.dropInto(drop_loc) + harness.dropInto(drop_loc) + harness = null + verbs -= /mob/living/simple_mob/animal/proc/RemoveAttachmentVerb + verbs -= /mob/living/simple_mob/animal/proc/RemoveHarnessVerb + update_icon() + return TRUE + +/mob/living/simple_mob/animal/proc/set_harness(var/obj/item/storage/animal_harness/new_harness) + if(!istype(new_harness) || new_harness == harness) + return FALSE + if(istype(harness)) + QDEL_NULL(harness) + harness = new_harness + if(istype(harness)) + harness.forceMove(src) + verbs |= /mob/living/simple_mob/animal/proc/RemoveAttachmentVerb + verbs |= /mob/living/simple_mob/animal/proc/RemoveHarnessVerb + else + verbs -= /mob/living/simple_mob/animal/proc/RemoveAttachmentVerb + verbs -= /mob/living/simple_mob/animal/proc/RemoveHarnessVerb + update_icon() + return TRUE /mob/living/simple_mob/animal/examine(mob/living/user) . = ..() @@ -138,6 +204,31 @@ for (var/obj/item/item in harness.GetAttachedItems()) . += "There is \a [item] attached." +/mob/living/simple_mob/animal/proc/RemoveHarnessVerb() + set name = "Remove Harness" + set category = "IC" + set src in view(1) + + var/mob/living/user = usr + if (!istype(user)) + return + if (!Adjacent(user) || user.incapacitated()) + to_chat(user, SPAN_WARNING("You are in no condition to do that.")) + return + if (!user.check_dexterity(MOB_DEXTERITY_SIMPLE_MACHINES)) + return + if(user == src) + to_chat(usr, SPAN_WARNING("You cannot remove your own harness!")) + return + + var/removing_harness = harness + user.visible_message(SPAN_NOTICE("\The [user] begins unbuckling \the [harness] from \the [src].")) + if(!do_after(user, 3 SECONDS, src) || removing_harness != harness || !Adjacent(user) || user.incapacitated()) + return + user.visible_message(SPAN_NOTICE("\The [user] unbuckles and removes \the [harness] from \the [src].")) + harness.forceMove(get_turf(src)) + clear_harness() + /mob/living/simple_mob/animal/proc/RemoveAttachmentVerb() set name = "Remove Harness Attachment" set category = "IC" @@ -178,3 +269,29 @@ return var/obj/item/removed = harness.RemoveAttachment(response) user.put_in_hands(removed) + +// The below logic is adapted from /obj/item/storage/internal. +/obj/item/storage/animal_harness/attack_hand(mob/user) + if(isanimal(loc)) + var/mob/living/simple_mob/animal/critter = loc + if(critter.harness == src) + if(loc == user) + add_fingerprint(user) + open(user) + return FALSE + if(user.Adjacent(loc)) + add_fingerprint(user) + open(user) + return FALSE + for(var/mob/M in range(1, get_turf(loc))) + if (M.s_active == src) + src.close(M) + return TRUE + return ..() + +/obj/item/storage/animal_harness/Adjacent(var/atom/neighbor) + if(isanimal(loc)) + var/mob/living/simple_mob/animal/critter = loc + if(critter.harness == src) + return critter.Adjacent(neighbor) + return ..() diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka.dm index 2eab15c14b..87f8f7a184 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka.dm @@ -97,12 +97,20 @@ You can eat glowing tree fruit to fuel your ranged spitting attack and ranged spitting attack and ranged spitting attack and ranged spitting attack and ranged spitting attack and ranged spitting attack and ranged spitting attack and = 10 - -/mob/living/simple_mob/animal/sif/grafadreka/proc/add_glow() - var/image/I = image(icon, "[icon_state]-glow") - I.color = glow_colour - I.plane = PLANE_LIGHTING_ABOVE - I.alpha = 35 + round(220 * clamp(stored_sap/max_stored_sap, 0, 1)) - return I - - /mob/living/simple_mob/animal/sif/grafadreka/proc/has_sap(amount) return stored_sap >= amount @@ -550,3 +587,24 @@ var/global/list/wounds_being_tended_by_drakes = list() to_chat(drake, SPAN_NOTICE("The pack leader wishes for you to follow them.")) else if (drake.ai_holder) drake.ai_holder.set_follow(src) + + +/mob/living/simple_mob/animal/sif/grafadreka/GetIdCard() + return harness?.GetIdCard() + + +/mob/living/simple_mob/animal/sif/grafadreka/attack_hand(mob/living/user) + // Permit headpats/smacks + if (!harness || user.a_intent == I_HURT || (user.a_intent == I_HELP && user.zone_sel?.selecting == BP_HEAD)) + return ..() + return harness.attack_hand(user) + + +/mob/living/simple_mob/animal/sif/grafadreka/attackby(obj/item/item, mob/user) + if (user.a_intent == I_HURT) + return ..() + if (user.a_intent == I_HELP && is_type_in_list(item, allow_type_to_pass)) + return ..() + if (harness?.attackby(item, user)) + return TRUE + return ..() diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka_harness.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka_harness.dm index 039e29964a..b8a953fbd8 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka_harness.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka_harness.dm @@ -1,46 +1,39 @@ -/obj/item/storage/internal/animal_harness/grafadreka - abstract_type = /obj/item/storage/internal/animal_harness/grafadreka +/obj/item/storage/animal_harness/grafadreka + abstract_type = /obj/item/storage/animal_harness/grafadreka name = "grafadreka harness" self_attach_delay = 3 SECONDS - - // keys for animal_harness/attachable_type - var/const/ATTACHED_GPS = "gps" - var/const/ATTACHED_RADIO = "radio" - var/const/ATTACHED_ARMOR = "armor plate" - var/const/ATTACHED_LIGHT = "light" - var/const/ATTACHED_ID = "access card" - + harnessable_types = list( + /mob/living/simple_mob/animal/sif/grafadreka, + /mob/living/simple_mob/animal/sif/grafadreka/trained + ) /// An attachable_types list shared between drake harness instances. var/static/list/grafadreka_attachable_types = list( /obj/item/gps = ATTACHED_GPS, /obj/item/radio = ATTACHED_RADIO, /obj/item/clothing/accessory/armor = list( ATTACHED_ARMOR, - /obj/item/storage/internal/animal_harness/grafadreka/proc/UpdateArmor + /obj/item/storage/animal_harness/grafadreka/proc/UpdateArmor ), /obj/item/clothing/accessory/material/makeshift = list( ATTACHED_ARMOR, - /obj/item/storage/internal/animal_harness/grafadreka/proc/UpdateArmor + /obj/item/storage/animal_harness/grafadreka/proc/UpdateArmor ), /obj/item/card/id = ATTACHED_ID, /obj/item/flashlight = ATTACHED_LIGHT ) -/obj/item/storage/internal/animal_harness/grafadreka/GetIdCard() - return attached_items[ATTACHED_ID] - -/obj/item/storage/internal/animal_harness/grafadreka/Destroy() +/obj/item/storage/animal_harness/grafadreka/Destroy() attachable_types = null return ..() -/obj/item/storage/internal/animal_harness/grafadreka/Initialize(mapload) +/obj/item/storage/animal_harness/grafadreka/Initialize(mapload) attachable_types = grafadreka_attachable_types . = ..() -/obj/item/storage/internal/animal_harness/grafadreka/proc/UpdateArmor() +/obj/item/storage/animal_harness/grafadreka/proc/UpdateArmor() var/mob/living/simple_mob/animal/sif/grafadreka/drake = loc if (!istype(drake)) return @@ -53,7 +46,7 @@ // Basic trained drake harness contents on spawn -/obj/item/storage/internal/animal_harness/grafadreka/trained/CreateAttachments() +/obj/item/storage/animal_harness/grafadreka/trained/CreateAttachments() var/mob/living/owner = loc if (!istype(owner)) return diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka_misc.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka_misc.dm index c22a60583e..db1881acb5 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka_misc.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka_misc.dm @@ -63,6 +63,7 @@ Field studies suggest analytical abilities on par with some species of cepholapo ) + /obj/item/projectile/drake_spit name = "drake spittle" icon_state = "ice_1" @@ -77,6 +78,7 @@ Field studies suggest analytical abilities on par with some species of cepholapo eyeblur = 5 fire_sound = 'sound/voice/drakes/drake_spit.ogg' + /obj/item/projectile/drake_spit/on_hit(atom/target, blocked, def_zone) // Stun is needed to effectively hunt simplemobs, but it's OP against humans. if(ishuman(target)) diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka_trained.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka_trained.dm index f8e5a4c8a7..434b3d7355 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka_trained.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka/grafadreka_trained.dm @@ -9,84 +9,13 @@ Using grab intent you can pick up and drop items by gender = PLURAL // Will take gender from prefs = set to non-NEUTER here to avoid randomizing in Initialize(). movement_cooldown = 1.5 // ~~Red~~ trained ones go faster. dexterity = MOB_DEXTERITY_SIMPLE_MACHINES - harness = /obj/item/storage/internal/animal_harness/grafadreka/trained + harness = /obj/item/storage/animal_harness/grafadreka/trained trained_drake = TRUE understands_languages = list( LANGUAGE_GALCOM, LANGUAGE_SIVIAN ) - /// On clicking with an item, stuff that should use behaviors instead of being placed in storage. - var/static/list/allow_type_to_pass = list( - /obj/item/healthanalyzer, - /obj/item/stack/medical, - /obj/item/reagent_containers/syringe, - /obj/item/shockpaddles - ) - -/mob/living/simple_mob/animal/sif/grafadreka/trained/Destroy() - if (istype(harness)) - QDEL_NULL(harness) - return ..() - - -/mob/living/simple_mob/animal/sif/grafadreka/trained/GetIdCard() - return harness?.GetIdCard() - - -/mob/living/simple_mob/animal/sif/grafadreka/trained/add_glow() - . = ..() - if (. && harness) - var/image/I = . - I.icon_state = "[I.icon_state]-[harness.icon_state]" - - -/mob/living/simple_mob/animal/sif/grafadreka/trained/Logout() - ..() - if (stat != DEAD) - lying = TRUE - resting = TRUE - sitting = FALSE - Sleeping(2) - update_icon() - - -/mob/living/simple_mob/animal/sif/grafadreka/trained/Login() - ..() - SetSleeping(0) - update_icon() - - -/mob/living/simple_mob/animal/sif/grafadreka/trained/attack_hand(mob/living/user) - // Permit headpats/smacks - if (!harness || user.a_intent == I_HURT || (user.a_intent == I_HELP && user.zone_sel?.selecting == BP_HEAD)) - return ..() - return harness.handle_attack_hand(user) - - -/mob/living/simple_mob/animal/sif/grafadreka/trained/update_icon() - . = ..() - if (harness) - var/image/I = image(harness.icon, "[current_icon_state]-[harness.icon_state]") - I.color = harness.color - I.appearance_flags |= (RESET_COLOR|PIXEL_SCALE|KEEP_APART) - if (offset_compiled_icon) - I.pixel_x = offset_compiled_icon - add_overlay(I) - - -/mob/living/simple_mob/animal/sif/grafadreka/trained/attackby(obj/item/item, mob/user) - if (user.a_intent == I_HURT) - return ..() - if (user.a_intent == I_HELP) - for (var/pass_type in allow_type_to_pass) - if (istype(item, pass_type)) - return ..() - if (harness?.attackby(item, user)) - return TRUE - return ..() - - /mob/living/simple_mob/animal/sif/grafadreka/trained/proc/DropItem() if (!length(harness?.contents)) to_chat(src, SPAN_WARNING("You have nothing to drop.")) diff --git a/icons/mob/drake_harness.dmi b/icons/mob/drake_harness.dmi index a9de55e0c7b4502065c0cfade185d01fe22f4521..1ceb8653b83a3e33034bf7087072407ae85a9a21 100644 GIT binary patch delta 1855 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 by the Xenobiology department to assist with expeditions and field work, and are an official part of the Exploration staff." You can eat glowing tree fruit to fuel your ranged spitting attack and poisonous bite (on harm intent), as well as healing saliva (on help intent). Using grab intent you can pick up and drop items by clicking them or yourself, and can interact with some simple machines like buttons and levers."} - harness = /obj/item/storage/internal/animal_harness/grafadreka/expedition + harness = /obj/item/storage/animal_harness/grafadreka/expedition /obj/item/book/manual/drake_handling name = "Care And Handling Of The Sivian Snow Drake v0.1.12b"