Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Monster Hunters can now see rabbits through walls (+ silver bullets are now a status effect) #3522

Merged
merged 1 commit into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
///how many rabbits have we found
var/rabbits_spotted = 0
///the list of white rabbits
var/list/obj/effect/client_image_holder/white_rabbit/rabbits = list()
var/list/obj/effect/bnnuy/rabbits = list()
///the red card tied to this trauma if any
var/obj/item/rabbit_locator/locator
///have we triggered the apocalypse
Expand Down Expand Up @@ -44,13 +44,16 @@
current_mob.add_traits(granted_traits, HUNTER_TRAIT)
current_mob.update_sight()
current_mob.faction |= FACTION_RABBITS
RegisterSignal(current_mob, COMSIG_MOB_LOGIN, PROC_REF(setup_bnuuy_images))
RegisterSignal(current_mob, COMSIG_MOVABLE_MOVED, PROC_REF(update_bnnuy_visibility))

/datum/antagonist/monsterhunter/remove_innate_effects(mob/living/mob_override)
. = ..()
var/mob/living/current_mob = mob_override || owner.current
REMOVE_TRAITS_IN(current_mob, HUNTER_TRAIT)
current_mob.remove_traits(granted_traits, HUNTER_TRAIT)
current_mob.faction -= FACTION_RABBITS
current_mob.update_sight()
UnregisterSignal(current_mob, list(COMSIG_MOB_LOGIN, COMSIG_MOVABLE_MOVED))

/datum/antagonist/monsterhunter/on_gain()
//Give Hunter Objective
Expand Down Expand Up @@ -80,16 +83,28 @@
RegisterSignal(src, COMSIG_BEASTIFY, PROC_REF(turn_beast))
for(var/i in 1 to 5)
var/turf/rabbit_hole = get_safe_random_station_turf()
var/obj/effect/client_image_holder/white_rabbit/cretin = new(rabbit_hole, owner.current)
cretin.hunter = src
rabbits += cretin
var/obj/effect/client_image_holder/white_rabbit/gun_holder = pick(rabbits)
rabbits += new /obj/effect/bnnuy(rabbit_hole, src)
var/obj/effect/bnnuy/gun_holder = pick(rabbits)
gun_holder.drop_gun = TRUE
var/datum/action/cooldown/spell/track_monster/track = new
track.Grant(owner.current)

return ..()

/datum/antagonist/monsterhunter/proc/setup_bnuuy_images()
SIGNAL_HANDLER
for(var/obj/effect/bnnuy/bnnuy as anything in rabbits)
if(QDELETED(bnnuy))
continue
owner.current?.client?.images |= bnnuy.hunter_image

/datum/antagonist/monsterhunter/proc/update_bnnuy_visibility(mob/living/source, atom/old_loc, dir, forced, list/old_locs)
SIGNAL_HANDLER
for(var/obj/effect/bnnuy/bnnuy as anything in rabbits)
if(QDELETED(bnnuy))
continue
bnnuy.update_mouse_opacity(source)

/datum/antagonist/monsterhunter/proc/grant_drop_ability(obj/item/tool)
var/datum/action/droppod_item/summon_contract = new(tool)
if(istype(tool, /obj/item/rabbit_locator))
Expand All @@ -101,14 +116,10 @@
summon_contract.Grant(owner.current)

/datum/antagonist/monsterhunter/on_removal()
UnregisterSignal(src, COMSIG_GAIN_INSIGHT)
UnregisterSignal(src, COMSIG_BEASTIFY)
REMOVE_TRAITS_IN(owner, HUNTER_TRAIT)
for(var/obj/effect/client_image_holder/white_rabbit/white as anything in rabbits)
rabbits -= white
qdel(white)
if(locator)
locator.hunter = null
UnregisterSignal(src, list(COMSIG_GAIN_INSIGHT, COMSIG_BEASTIFY))
owner.remove_traits(mind_traits, HUNTER_TRAIT)
QDEL_LIST(rabbits)
locator?.hunter = null
locator = null
to_chat(owner.current, span_userdanger("Your hunt has ended: You enter retirement once again, and are no longer a Monster Hunter."))
return ..()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,53 +1,98 @@
/obj/effect/client_image_holder/white_rabbit
/obj/effect/bnnuy
name = "white rabbit"
desc = "FEED YOUR HEAD."
image_icon = 'monkestation/icons/bloodsuckers/rabbit.dmi'
image_state = "white_rabbit"
image_layer = ABOVE_LIGHTING_PLANE
image_layer = ABOVE_MOB_LAYER
image_plane = GAME_PLANE_UPPER
///the rabbit's whisper
var/description
///has the rabbit already whispered?
desc = span_big(span_hypnophrase("FEED YOUR HEAD."))
icon = 'monkestation/icons/bloodsuckers/512x512.dmi'
anchored = TRUE
interaction_flags_atom = INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND | INTERACT_ATOM_NO_FINGERPRINT_INTERACT
resistance_flags = parent_type::resistance_flags | SHUTTLE_CRUSH_PROOF
invisibility = INVISIBILITY_OBSERVER
appearance_flags = PIXEL_SCALE | KEEP_TOGETHER
pixel_x = -240
pixel_y = -240
/// The icon state applied to the image created for this rabbit.
var/real_icon_state = "bnnuy"
/// The antag datum of the monster hunter that can see us.
var/datum/antagonist/monsterhunter/hunter_antag
/// The mind of the monster hunter that can see us.
var/datum/mind/hunter_mind
/// The image shown to the hunter.
var/image/hunter_image
/// Has the rabbit already whispered?
var/being_used = FALSE
///the hunter this rabbit is tied to
var/datum/antagonist/monsterhunter/hunter
///is this rabbit selected to drop the gun?
/// Is this rabbit selected to drop the gun?
var/drop_gun = FALSE

/obj/effect/client_image_holder/white_rabbit/Initialize(mapload)
/obj/effect/bnnuy/Initialize(mapload, datum/antagonist/monsterhunter/hunter)
. = ..()
RegisterSignal(src, COMSIG_RABBIT_FOUND, PROC_REF(spotted))
if(!istype(hunter) || QDELING(hunter) || QDELETED(hunter.owner) || !isopenturf(loc) || QDELING(loc))
return INITIALIZE_HINT_QDEL
hunter_image = create_bnnuy_image()
hunter_antag = hunter
hunter_mind = hunter.owner
update_mouse_opacity(hunter_mind.current)
hunter_mind.current?.client?.images |= hunter_image
AddComponent(/datum/component/redirect_attack_hand_from_turf, interact_check = CALLBACK(src, PROC_REF(verify_user_can_see)))

/obj/effect/client_image_holder/white_rabbit/attack_hand(mob/user, list/modifiers)
/obj/effect/bnnuy/Destroy(force)
hunter_antag?.rabbits -= src
hunter_antag = null
hunter_mind?.current?.client?.images -= hunter_image
hunter_mind = null
hunter_image = null
return ..()

/obj/effect/bnnuy/examine(mob/user)
. = ..()
if(.)
return
if(!(user in who_sees_us))
return
if(hunter_antag)
. += span_info("You have found [hunter_antag.rabbits_spotted] out of 5 rabbits.")

/obj/effect/bnnuy/attack_hand(mob/living/user, list/modifiers)
if(user?.mind != hunter_mind)
return SECONDARY_ATTACK_CALL_NORMAL
. = SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
if(being_used)
return
being_used = TRUE
SEND_SIGNAL(src, COMSIG_RABBIT_FOUND, user)
if(!hunter)
return
SEND_SIGNAL(hunter, COMSIG_GAIN_INSIGHT)
image_state = "rabbit_hole"
update_appearance()
spotted(user)
SEND_SIGNAL(hunter_antag, COMSIG_GAIN_INSIGHT)
icon = 'monkestation/icons/bloodsuckers/rabbit.dmi'
real_icon_state = "rabbit_hole"
pixel_x = 0
pixel_y = 0
update_bnnuy_image()
QDEL_IN(src, 8 SECONDS)

/obj/effect/bnnuy/proc/create_bnnuy_image() as /image
RETURN_TYPE(/image)
var/image/new_image = image(icon, src, real_icon_state, BELOW_MOB_LAYER)
SET_PLANE_EXPLICIT(new_image, ABOVE_LIGHTING_PLANE, src)
return new_image

/obj/effect/bnnuy/proc/update_bnnuy_image()
hunter_mind?.current?.client?.images -= hunter_image
hunter_image = create_bnnuy_image()
hunter_mind?.current?.client?.images |= hunter_image

/obj/effect/client_image_holder/white_rabbit/proc/spotted(datum/source, mob/user)
SIGNAL_HANDLER
/obj/effect/bnnuy/proc/verify_user_can_see(mob/user)
return (user?.mind == hunter_mind)

new /obj/item/rabbit_eye(drop_location())
if(hunter?.rabbits_spotted == 0) //our first bunny
new /obj/item/clothing/mask/cursed_rabbit(drop_location())
/obj/effect/bnnuy/proc/spotted(mob/living/user)
if(hunter_antag?.rabbits_spotted == 0) //our first bunny
user.put_in_hands(new /obj/item/clothing/mask/cursed_rabbit(drop_location()))
user.put_in_hands(new /obj/item/rabbit_eye(drop_location()))
if(drop_gun)
new /obj/item/gun/ballistic/revolver/hunter_revolver(drop_location())
var/datum/action/cooldown/spell/conjure_item/blood_silver/silverblood = new(user)
silverblood.StartCooldown()
silverblood.Grant(user)
if(hunter)
hunter.rabbits -= src
UnregisterSignal(src, COMSIG_RABBIT_FOUND)
give_gun(user)
hunter_antag?.rabbits -= src

/obj/effect/bnnuy/proc/give_gun(mob/living/user)
user.put_in_hands(new /obj/item/gun/ballistic/revolver/hunter_revolver(drop_location()))
var/datum/action/cooldown/spell/conjure_item/blood_silver/silverblood = new(user)
silverblood.StartCooldown()
silverblood.Grant(user)

/// Janky workaround to avoid the 512x512 sprite always occuping the user's right click menu
/obj/effect/bnnuy/proc/update_mouse_opacity(mob/living/user)
if(in_view_range(user, src, TRUE) && can_see(user, src))
mouse_opacity = MOUSE_OPACITY_ICON
else
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
if(!length(hunter?.rabbits))
return
var/obj/effect/selected_bunny
for(var/obj/effect/located as anything in hunter.rabbits)
for(var/obj/effect/bnnuy/located as anything in hunter.rabbits)
if(get_dist(user, located) < dist)
dist = get_dist(user, located)
selected_bunny = located
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/obj/item/gun/ballistic/revolver/hunter_revolver
name = "\improper Hunter's Revolver"
desc = "Does minimal damage but slows down the enemy."
desc = "While doing minimal physical damage, the bullets will force a monster to carry the weight of their impure sins for a short while, greatly slowing them down."
icon_state = "revolver"
icon = 'monkestation/icons/bloodsuckers/weapons.dmi'
accepted_magazine_type = /obj/item/ammo_box/magazine/internal/cylinder/bloodsilver
Expand All @@ -26,15 +26,33 @@
caliber = CALIBER_BLOODSILVER

/obj/projectile/bullet/bloodsilver
name = "Bloodsilver bullet"
name = "bloodsilver bullet"
damage = 3
ricochets_max = 4

/obj/projectile/bullet/bloodsilver/on_hit(mob/living/carbon/target, blocked = 0, pierce_hit)
/obj/projectile/bullet/bloodsilver/on_hit(mob/living/target, blocked = 0, pierce_hit)
. = ..()
if(!iscarbon(target) || QDELING(target) || target.has_movespeed_modifier(/datum/movespeed_modifier/silver_bullet) || !is_monster_hunter_prey(target))
if(!isliving(target) || QDELING(target) || !is_monster_hunter_prey(target))
return
target.add_movespeed_modifier(/datum/movespeed_modifier/silver_bullet)
if(!(target.has_movespeed_modifier(/datum/movespeed_modifier/silver_bullet)))
return
addtimer(CALLBACK(target, TYPE_PROC_REF(/mob, remove_movespeed_modifier), /datum/movespeed_modifier/silver_bullet), 8 SECONDS)
target.apply_status_effect(/datum/status_effect/silver_bullet)

/datum/status_effect/silver_bullet
id = "silver_bullet"
duration = 8 SECONDS
tick_interval = -1
status_type = STATUS_EFFECT_REFRESH
alert_type = /atom/movable/screen/alert/status_effect/silver_bullet

/datum/status_effect/silver_bullet/on_apply()
owner.add_movespeed_modifier(/datum/movespeed_modifier/silver_bullet)
to_chat(owner, span_userdanger("Your body suddenly feels impossibly heavy, you can barely move!"), type = MESSAGE_TYPE_COMBAT)
return TRUE

/datum/status_effect/silver_bullet/on_remove()
owner.remove_movespeed_modifier(/datum/movespeed_modifier/silver_bullet)
to_chat(owner, span_notice("The impossible weight fades away, allowing you to move normally once more."), type = MESSAGE_TYPE_COMBAT)

/atom/movable/screen/alert/status_effect/silver_bullet
name = "Bloodsilver Curse"
desc = "You can feel your sins crawling on your back, weighing you down immensely."
icon_state = "weaken"
Binary file added monkestation/icons/bloodsuckers/512x512.dmi
Binary file not shown.
Loading