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

Thrown Thing Improvments #2950

Merged
merged 7 commits into from
Jun 2, 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
1 change: 1 addition & 0 deletions code/__DEFINES/flags.dm
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define FLOATING (1<<3)
/// When moving, will Cross()/Uncross() everything, but won't stop or Bump() anything.
#define PHASING (1<<4)
#define THROWN (1<<5)

//Fire and Acid stuff, for resistance_flags
#define LAVA_PROOF (1<<0)
Expand Down
1 change: 1 addition & 0 deletions code/_globalvars/bitfields.dm
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ DEFINE_BITFIELD(movement_type, list(
"GROUND" = GROUND,
"PHASING" = PHASING,
"VENTCRAWLING" = VENTCRAWLING,
"THROWN" = THROWN,
))

DEFINE_BITFIELD(obj_flags, list(
Expand Down
61 changes: 32 additions & 29 deletions code/controllers/subsystem/throwing.dm
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ SUBSYSTEM_DEF(throwing)

/datum/thrownthing
var/atom/movable/thrownthing
var/atom/target
var/datum/weakref/initial_target
var/turf/target_turf
var/target_zone
var/init_dir
Expand All @@ -71,12 +71,13 @@ SUBSYSTEM_DEF(throwing)
var/last_move = 0


/datum/thrownthing/New(thrownthing, target, target_turf, init_dir, maxrange, speed, thrower, diagonals_first, force, gentle, callback, target_zone)
/datum/thrownthing/New(thrownthing, target, init_dir, maxrange, speed, thrower, diagonals_first, force, gentle, callback, target_zone)
. = ..()
src.thrownthing = thrownthing
RegisterSignal(thrownthing, COMSIG_PARENT_QDELETING, PROC_REF(on_thrownthing_qdel))
src.target = target
src.target_turf = target_turf
src.target_turf = get_turf(target)
if(target_turf != target)
src.initial_target = WEAKREF(target)
src.init_dir = init_dir
src.maxrange = maxrange
src.speed = speed
Expand All @@ -87,14 +88,13 @@ SUBSYSTEM_DEF(throwing)
src.callback = callback
src.target_zone = target_zone


/datum/thrownthing/Destroy()
SSthrowing.processing -= thrownthing
SSthrowing.currentrun -= thrownthing
thrownthing.throwing = null
thrownthing = null
target = null
thrower = null
initial_target = null
if(callback)
QDEL_NULL(callback) //It stores a reference to the thrownthing, its source. Let's clean that.
return ..()
Expand All @@ -109,6 +109,7 @@ SUBSYSTEM_DEF(throwing)

/datum/thrownthing/proc/tick()
var/atom/movable/AM = thrownthing
AM.setMovetype(AM.movement_type | THROWN)
if (!isturf(AM.loc) || !AM.throwing)
finalize()
return
Expand All @@ -117,9 +118,17 @@ SUBSYSTEM_DEF(throwing)
delayed_time += world.time - last_move
return

if (dist_travelled && hitcheck()) //to catch sneaky things moving on our tile while we slept
finalize()
return
var/atom/movable/actual_target = initial_target?.resolve()

if(dist_travelled) //to catch sneaky things moving on our tile while we slept
for(var/atom/movable/obstacle as anything in get_turf(thrownthing))
if (obstacle == thrownthing || (obstacle == thrower && !ismob(thrownthing)))
continue
if(obstacle.pass_flags_self & LETPASSTHROW)
continue
if (obstacle == actual_target || (obstacle.density && !(obstacle.flags_1 & ON_BORDER_1)))
finalize(TRUE, obstacle)
return

var/atom/step

Expand All @@ -146,10 +155,15 @@ SUBSYSTEM_DEF(throwing)
finalize()
return

AM.Move(step, get_dir(AM, step), DELAY_TO_GLIDE_SIZE(1 / speed))
if(!AM.Move(step, get_dir(AM, step), DELAY_TO_GLIDE_SIZE(1 / speed))) // we hit something during our move...
if(AM.throwing) // ...but finalize() wasn't called on Bump() because of a higher level definition that doesn't always call parent.
finalize()
return

if (!AM.throwing) // we hit something during our move
finalize(hit = TRUE)
dist_travelled++

if(actual_target && !(actual_target.pass_flags_self & LETPASSTHROW) && actual_target.loc == AM.loc) // we crossed a movable with no density (e.g. a mouse or APC) we intend to hit anyway.
finalize(TRUE, actual_target)
return

dist_travelled++
Expand All @@ -158,18 +172,19 @@ SUBSYSTEM_DEF(throwing)
finalize()
return

/datum/thrownthing/proc/finalize(hit = FALSE, target=null)
//If the target hasent been hit search for it in the turf we landed on.
/datum/thrownthing/proc/finalize(hit = FALSE, target = null)
set waitfor = FALSE
//done throwing, either because it hit something or it finished moving
if(!thrownthing)
return
thrownthing.throwing = null
thrownthing.setMovetype(thrownthing.movement_type & ~THROWN)
if (!hit)
for (var/thing in get_turf(thrownthing)) //looking for our target on the turf we land on.
var/atom/A = thing
if (A == target)
for (var/atom/movable/obstacle as anything in get_turf(thrownthing)) //looking for our target on the turf we land on.
if (obstacle == target)
hit = TRUE
thrownthing.throw_impact(A, src)
thrownthing.throw_impact(obstacle, src)
if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing
return //deletion should already be handled by on_thrownthing_qdel()
break
Expand All @@ -195,15 +210,3 @@ SUBSYSTEM_DEF(throwing)
T.zFall(thrownthing)

qdel(src)

/datum/thrownthing/proc/hit_atom(atom/A)
finalize(hit=TRUE, target=A)

/datum/thrownthing/proc/hitcheck()
for (var/thing in get_turf(thrownthing))
var/atom/movable/AM = thing
if (AM == thrownthing || (AM == thrower && !ismob(thrownthing)))
continue
if (AM.density && !(AM.pass_flags_self & LETPASSTHROW) && !(AM.flags_1 & ON_BORDER_1))
finalize(hit=TRUE, target=AM)
return TRUE
8 changes: 5 additions & 3 deletions code/game/atoms_movable.dm
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@
SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A)
. = ..()
if(!QDELETED(throwing))
throwing.hit_atom(A)
throwing.finalize(hit = TRUE, target = A)
. = TRUE
if(QDELETED(A))
return
Expand Down Expand Up @@ -821,7 +821,9 @@
var/impact_signal = SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
if(impact_signal & COMPONENT_MOVABLE_IMPACT_FLIP_HITPUSH)
hitpush = FALSE // hacky, tie this to something else or a proper workaround later

if(isturf(loc))
var/turf/T = loc
T.Entered(src)
if(impact_signal & ~COMPONENT_MOVABLE_IMPACT_NEVERMIND) // in case a signal interceptor broke or deleted the thing before we could process our hit
return hit_atom.hitby(src, throwingdatum=throwingdatum, hitpush=hitpush)

Expand Down Expand Up @@ -883,7 +885,7 @@
else
target_zone = thrower.zone_selected

var/datum/thrownthing/TT = new(src, target, get_turf(target), get_dir(src, target), range, speed, thrower, diagonals_first, force, gentle, callback, target_zone)
var/datum/thrownthing/TT = new(src, target, get_dir(src, target), range, speed, thrower, diagonals_first, force, gentle, callback, target_zone)

var/dist_x = abs(target.x - src.x)
var/dist_y = abs(target.y - src.y)
Expand Down
11 changes: 6 additions & 5 deletions code/game/objects/items/devices/mines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,8 @@
SIGNAL_HANDLER
if(!can_trigger(arrived))
return
// Flying = can't step on a mine
if(arrived.movement_type & FLYING)
return
//no cheap disarming
if(arrived.throwing && isitem(arrived))
// All other movment types rn can easily avoid it
if(!(arrived.movement_type == GROUND))
return
// Someone already on it
if(foot_on_mine?.resolve())
Expand Down Expand Up @@ -257,6 +254,10 @@
clicked = FALSE
. = ..()

/obj/item/mine/pressure/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
trigger_mine(AM)
..()

//handles disarming(and failing to disarm)
/obj/item/mine/pressure/attackby(obj/item/I, mob/user)
if(I.tool_behaviour == TOOL_SCREWDRIVER)
Expand Down
5 changes: 5 additions & 0 deletions code/game/objects/items/handcuffs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@
update_appearance()
playsound(src, 'sound/effects/snap.ogg', 50, TRUE)

/obj/item/restraints/legcuffs/beartrap/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
if(armed)
close_trap()
..()

/obj/item/restraints/legcuffs/beartrap/proc/on_entered(datum/source, AM as mob|obj)
SIGNAL_HANDLER
if(armed && isturf(loc))
Expand Down
4 changes: 2 additions & 2 deletions code/game/objects/items/puzzle_pieces.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//**************
//*****Keys*******************
//************** ** **
//*****Keys*****
//**************
/obj/item/keycard
name = "security keycard"
desc = "This feels like it belongs to a door."
Expand Down
39 changes: 24 additions & 15 deletions code/modules/food_and_drinks/drinks/drinks.dm
Original file line number Diff line number Diff line change
Expand Up @@ -120,27 +120,36 @@
if(!.) //if the bottle wasn't caught
smash(hit_atom, throwingdatum?.thrower, TRUE)

/obj/item/reagent_containers/food/drinks/proc/smash(atom/target, mob/thrower, ranged = FALSE)
/obj/item/reagent_containers/food/drinks/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
smash()
..()

/obj/item/reagent_containers/food/drinks/proc/smash(atom/target = FALSE, mob/thrower = FALSE, ranged = FALSE)
if(!isGlass)
return
if(QDELING(src) || !target || !(flags_1 & INITIALIZED_1)) //Invalid loc
return
if(bartender_check(target) && ranged)
if(QDELING(src) || !(flags_1 & INITIALIZED_1)) //Invalid loc
return
var/obj/item/broken_bottle/B = new (loc)
B.icon_state = icon_state
var/icon/I = new(icon, icon_state)
I.Blend(B.broken_outline, ICON_OVERLAY, rand(5), 1)
I.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0))
B.icon = I
B.name = "broken [name]"
if(target)
if(bartender_check(target) && ranged)
return
var/obj/item/broken_bottle/smashed_bottle = new (loc)
if(!ranged && thrower)
thrower.put_in_hands(smashed_bottle)
smashed_bottle.icon_state = icon_state
var/icon/new_icon = new(icon, icon_state)
new_icon.Blend(smashed_bottle.broken_outline, ICON_OVERLAY, rand(5), 1)
new_icon.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0))
smashed_bottle.icon = new_icon
smashed_bottle.name = "broken [name]"
if(prob(33))
var/obj/item/shard/S = new(drop_location())
target.Bumped(S)
var/obj/item/shard/new_shard = new(drop_location())
if(target)
target.Bumped(new_shard)
playsound(src, "shatter", 70, TRUE)
transfer_fingerprints_to(B)
transfer_fingerprints_to(smashed_bottle)
qdel(src)
target.Bumped(B)
if(target)
target.Bumped(smashed_bottle)

/obj/item/reagent_containers/food/drinks/bullet_act(obj/projectile/P)
. = ..()
Expand Down
32 changes: 0 additions & 32 deletions code/modules/food_and_drinks/drinks/drinks/bottle.dm
Original file line number Diff line number Diff line change
Expand Up @@ -34,39 +34,7 @@
volume = 50
custom_price = 55

/obj/item/reagent_containers/food/drinks/bottle/smash(mob/living/target, mob/thrower, ranged = FALSE)
if(QDELING(src) || !target || !(flags_1 & INITIALIZED_1)) //Invalid loc
return
//Creates a shattering noise and replaces the bottle with a broken_bottle
if(bartender_check(target) && ranged)
return
var/obj/item/broken_bottle/B = new (loc)
if(!ranged && thrower)
thrower.put_in_hands(B)
B.icon_state = icon_state

var/icon/I = new('icons/obj/drinks/drinks.dmi', src.icon_state)
I.Blend(B.broken_outline, ICON_OVERLAY, rand(5), 1)
I.SwapColor(rgb(255, 0, 220, 255), rgb(0, 0, 0, 0))
B.icon = I

if(isGlass)
if(prob(33))
var/obj/item/shard/S = new(drop_location())
target.Bumped(S)
playsound(src, "shatter", 70, TRUE)
else
B.force = 0
B.throwforce = 0
B.desc = "A carton with the bottom half burst open. Might give you a papercut."
B.name = "broken [name]"
transfer_fingerprints_to(B)

qdel(src)
target.Bumped(B)

/obj/item/reagent_containers/food/drinks/bottle/attack(mob/living/target, mob/living/user)

if(!target)
return

Expand Down
3 changes: 3 additions & 0 deletions code/modules/mob/living/living_defense.dm
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@
return 1
else
playsound(loc, 'sound/weapons/genhit.ogg', 50, TRUE, -1) //Item sounds are handled in the item itself

if(body_position == LYING_DOWN) // physics says it's significantly harder to push someone by constantly chucking random furniture at them if they are down on the floor.
hitpush = FALSE
..()


Expand Down
5 changes: 4 additions & 1 deletion code/modules/power/lighting.dm
Original file line number Diff line number Diff line change
Expand Up @@ -859,8 +859,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/light/small/built, 28)
if(!..()) //not caught by a mob
shatter()

// update the icon state and description of the light
/obj/item/light/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
shatter()
..()

// update the icon state and description of the light
/obj/item/light/proc/update()
switch(status)
if(LIGHT_OK)
Expand Down
Loading