mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-18 19:44:58 +01:00
cf14dcfc1a
## About The Pull Request `adjust_fishing_difficulty` is a good one to make into a bespoke element since a number of the same clothing item are created in the wardrobe system. climb_walkable is also good due to how prevalent it is, and it is a bit of a two for one since it also removes the need for the `/component/connect_loc_behalf` Also stops adding the on_climbable trait to literally everything in the turf, it now only applies it to atoms with density. So no more pipes and stuff getting trait lists created for no reason. <details><summary> Tested + things still work as before </summary> <img width="422" height="122" alt="image" src="https://github.com/user-attachments/assets/b23696f5-cd16-4150-aeb3-14ea6bd256fc" /> </details> ## Why It's Good For The Game Lessens overhead, fixes a bug as well. ## Changelog 🆑 fix: fixes a pushed crate not removing on_climbable trait properly off the mob standing atop it /🆑
196 lines
6.8 KiB
Plaintext
196 lines
6.8 KiB
Plaintext
#define PICKUP_RESTRICTION_TIME 3 SECONDS // so other players can pickup the ball after someone scores
|
|
|
|
/datum/crafting_recipe/basketball_hoop
|
|
name = "Basketball Hoop"
|
|
result = /obj/structure/hoop
|
|
reqs = list(/obj/item/stack/sheet/durathread = 5,
|
|
/obj/item/stack/sheet/iron = 1, // the backboard
|
|
/obj/item/stack/rods = 5)
|
|
time = 10 SECONDS
|
|
category = CAT_STRUCTURE
|
|
|
|
/obj/structure/hoop
|
|
name = "basketball hoop"
|
|
desc = "Boom, shakalaka!"
|
|
icon = 'icons/obj/fluff/basketball_hoop.dmi'
|
|
icon_state = "hoop"
|
|
anchored = TRUE
|
|
density = TRUE
|
|
layer = ABOVE_MOB_LAYER
|
|
interaction_flags_click = NEED_DEXTERITY | NEED_HANDS | FORBID_TELEKINESIS_REACH
|
|
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 3.5)
|
|
/// Keeps track of the total points scored
|
|
var/total_score = 0
|
|
/// The chance to score a ball into the hoop based on distance
|
|
var/static/list/throw_range_success = list(95, 80, 65, 50, 35, 20)
|
|
|
|
/obj/structure/hoop/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/simple_rotation, ROTATION_REQUIRE_WRENCH|ROTATION_IGNORE_ANCHORED, post_rotation_proccall = PROC_REF(post_rotation))
|
|
update_appearance()
|
|
register_context()
|
|
|
|
/obj/structure/hoop/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
|
|
context[SCREENTIP_CONTEXT_CTRL_LMB] = "Reset score"
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
/obj/structure/hoop/proc/post_rotation(mob/user, degrees)
|
|
update_appearance()
|
|
|
|
/obj/structure/hoop/proc/score(obj/item/toy/basketball/ball, mob/living/baller, points)
|
|
// we still play buzzer sound regardless of the object
|
|
playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 100, FALSE)
|
|
|
|
if(!istype(ball))
|
|
return
|
|
|
|
total_score += points
|
|
update_appearance()
|
|
// whoever scored doesn't get to pickup the ball instantly
|
|
COOLDOWN_START(ball, pickup_cooldown, PICKUP_RESTRICTION_TIME)
|
|
|
|
ball.pickup_restriction_ckeys |= baller.ckey
|
|
return TRUE
|
|
|
|
/obj/structure/hoop/update_overlays()
|
|
. = ..()
|
|
|
|
var/dir_offset_w = 0
|
|
var/dir_offset_z = 0
|
|
|
|
switch(dir)
|
|
if(NORTH)
|
|
dir_offset_z = -32
|
|
if(SOUTH)
|
|
dir_offset_z = 32
|
|
if(EAST)
|
|
dir_offset_w = -32
|
|
if(WEST)
|
|
dir_offset_w = 32
|
|
|
|
var/mutable_appearance/scoreboard = mutable_appearance('icons/obj/signs.dmi', "basketball_scorecard")
|
|
scoreboard.pixel_w = dir_offset_w
|
|
scoreboard.pixel_z = dir_offset_z
|
|
. += scoreboard
|
|
|
|
var/ones = total_score % 10
|
|
var/mutable_appearance/ones_overlay = mutable_appearance('icons/obj/signs.dmi', "days_[ones]", layer + 0.01)
|
|
ones_overlay.pixel_w = 4
|
|
var/mutable_appearance/emissive_ones_overlay = emissive_appearance('icons/obj/signs.dmi', "days_[ones]", src, alpha = src.alpha)
|
|
emissive_ones_overlay.pixel_w = 4
|
|
scoreboard.add_overlay(ones_overlay)
|
|
scoreboard.add_overlay(emissive_ones_overlay)
|
|
|
|
var/tens = (total_score / 10) % 10
|
|
var/mutable_appearance/tens_overlay = mutable_appearance('icons/obj/signs.dmi', "days_[tens]", layer + 0.01)
|
|
tens_overlay.pixel_w = -5
|
|
|
|
var/mutable_appearance/emissive_tens_overlay = emissive_appearance('icons/obj/signs.dmi', "days_[tens]", src, alpha = src.alpha)
|
|
emissive_tens_overlay.pixel_w = -5
|
|
scoreboard.add_overlay(tens_overlay)
|
|
scoreboard.add_overlay(emissive_tens_overlay)
|
|
|
|
/obj/structure/hoop/attackby(obj/item/ball, mob/living/baller, list/modifiers, list/attack_modifiers)
|
|
if(!baller.can_perform_action(src, NEED_HANDS|FORBID_TELEKINESIS_REACH))
|
|
return // TK users aren't allowed to dunk
|
|
|
|
if(!baller.transfer_item_to_turf(ball, drop_location()))
|
|
return
|
|
|
|
var/dunk_dir = get_dir(baller, src)
|
|
|
|
var/dunk_pixel_z = (dunk_dir & SOUTH) ? -16 : 16
|
|
var/dunk_pixel_w = ((dunk_dir & EAST) && 16) || ((dunk_dir & WEST) && -16) || 0
|
|
|
|
animate(baller, pixel_w = dunk_pixel_w, pixel_z = dunk_pixel_z, time = 0.5 SECONDS, easing = BOUNCE_EASING|EASE_IN|EASE_OUT, flags = ANIMATION_PARALLEL|ANIMATION_RELATIVE)
|
|
animate(pixel_w = -dunk_pixel_w, pixel_z = -dunk_pixel_z, time = 0.5 SECONDS, flags = ANIMATION_RELATIVE)
|
|
|
|
visible_message(span_warning("[baller] dunks [ball] into \the [src]!"))
|
|
baller.add_mood_event("basketball", /datum/mood_event/basketball_dunk)
|
|
score(ball, baller, 2)
|
|
|
|
if(istype(ball, /obj/item/toy/basketball))
|
|
baller.adjust_stamina_loss(STAMINA_COST_DUNKING)
|
|
|
|
/obj/structure/hoop/attack_hand(mob/living/baller, list/modifiers)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
|
|
if(!(baller.pulling && isliving(baller.pulling)))
|
|
return ..()
|
|
|
|
var/mob/living/loser = baller.pulling
|
|
if(baller.grab_state < GRAB_AGGRESSIVE)
|
|
to_chat(baller, span_warning("You need a better grip to do that!"))
|
|
return
|
|
loser.forceMove(loc)
|
|
loser.Paralyze(100)
|
|
visible_message(span_danger("[baller] dunks [loser] into \the [src]!"))
|
|
playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 100, FALSE)
|
|
baller.adjust_stamina_loss(STAMINA_COST_DUNKING_MOB)
|
|
baller.stop_pulling()
|
|
|
|
/obj/structure/hoop/click_ctrl(mob/user)
|
|
user.balloon_alert_to_viewers("resetting score...")
|
|
playsound(src, 'sound/machines/locktoggle.ogg', 50, TRUE)
|
|
if(do_after(user, 5 SECONDS, target = src))
|
|
total_score = 0
|
|
update_appearance()
|
|
return CLICK_ACTION_SUCCESS
|
|
|
|
/obj/structure/hoop/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
|
if(!isitem(AM))
|
|
return ..()
|
|
|
|
var/distance = clamp(throwingdatum.dist_travelled + 1, 1, throw_range_success.len)
|
|
var/score_chance = throw_range_success[distance]
|
|
var/obj/structure/hoop/backboard = throwingdatum.initial_target?.resolve()
|
|
var/click_on_hoop = TRUE
|
|
var/mob/living/thrower = throwingdatum?.get_thrower()
|
|
|
|
if(!istype(thrower))
|
|
return
|
|
|
|
// aim penalty for not clicking directly on the hoop when shooting
|
|
if(!istype(backboard) || backboard != src)
|
|
click_on_hoop = FALSE
|
|
score_chance *= 0.5
|
|
|
|
// aim penalty for spinning while shooting
|
|
if(HAS_TRAIT(thrower, TRAIT_SPINNING))
|
|
score_chance *= 0.5
|
|
|
|
if(prob(score_chance))
|
|
AM.forceMove(get_turf(src))
|
|
// is it a 3 pointer shot
|
|
var/points = (distance > 2) ? 3 : 2
|
|
thrower.add_mood_event("basketball", /datum/mood_event/basketball_score)
|
|
score(AM, thrower, points)
|
|
visible_message(span_warning("[click_on_hoop ? "Swish!" : ""] [AM] lands in [src]."))
|
|
else
|
|
visible_message(span_danger("[AM] bounces off of [src]'s [click_on_hoop ? "rim" : "backboard"]!"))
|
|
|
|
// Special hoops for the minigame
|
|
/obj/structure/hoop/minigame
|
|
/// This is a list of ckeys for the minigame to prevent scoring on their own hoops
|
|
var/list/team_ckeys = list()
|
|
|
|
/obj/structure/hoop/minigame/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
|
|
return NONE
|
|
|
|
// No resetting the score for minigame hoops
|
|
/obj/structure/hoop/minigame/click_ctrl(mob/user)
|
|
return CLICK_ACTION_BLOCKING
|
|
|
|
/obj/structure/hoop/minigame/score(obj/item/toy/basketball/ball, mob/living/baller, points)
|
|
var/is_team_hoop = !(baller.ckey in team_ckeys)
|
|
if(is_team_hoop)
|
|
baller.balloon_alert_to_viewers("cant score own hoop!")
|
|
return
|
|
|
|
if(..())
|
|
ball.pickup_restriction_ckeys |= team_ckeys
|
|
|
|
#undef PICKUP_RESTRICTION_TIME
|