This commit is contained in:
kevinz000
2020-06-13 09:24:22 -07:00
parent b3b67a6a4f
commit 180b7d31d9
10 changed files with 88 additions and 45 deletions
-7
View File
@@ -275,13 +275,6 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
*/
#define INEFFICIENT_ATTACK_MSG_THRESHOLD 0.7
//bullet_act() return values
#define BULLET_ACT_HIT "HIT" //It's a successful hit, whatever that means in the context of the thing it's hitting.
#define BULLET_ACT_BLOCK "BLOCK" //It's a blocked hit, whatever that means in the context of the thing it's hitting.
#define BULLET_ACT_FORCE_PIERCE "PIERCE" //It pierces through the object regardless of the bullet being piercing by default.
#define BULLET_ACT_TURF "TURF" //It hit us but it should hit something on the same turf too. Usually used for turfs.
/// Check whether or not we can block, without "triggering" a block. Basically run checks without effects like depleting shields.
/// Wrapper for do_run_block(). The arguments on that means the same as for this.
#define mob_check_block(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)\
+2 -2
View File
@@ -22,8 +22,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
//FLAGS BITMASK
///This flag is what recursive_hear_check() uses to determine wether to add an item to the hearer list or not.
#define HEAR_1 (1<<3)
///Projectiels will check ricochet on things impacted that have this.
#define CHECK_RICOCHET_1 (1<<4)
///Projectiles will use default chance-based ricochet handling on things with this.
#define DEFAULT_RICOCHET_1 (1<<4)
///Conducts electricity (metal etc.).
#define CONDUCT_1 (1<<5)
///For machines and structures that should not break into parts, eg, holodeck stuff.
+14
View File
@@ -0,0 +1,14 @@
/// This atom should be ricocheted off of from its inherent properties using standard % chance handling.
#define PROJECTILE_RICOCHET_YES 1
/// This atom should not be ricocheted off of from its inherent properties.
#define PROJECTILE_RICOCHET_NO 2
/// This atom should prevent any kind of projectile ricochet from its inherent properties.
#define PROJECTILE_RICOCHET_PREVENT 3
/// This atom should force a projectile ricochet from its inherent properties.
#define PROJECTILE_RICOCHET_FORCE 4
//bullet_act() return values
#define BULLET_ACT_HIT "HIT" //It's a successful hit, whatever that means in the context of the thing it's hitting.
#define BULLET_ACT_BLOCK "BLOCK" //It's a blocked hit, whatever that means in the context of the thing it's hitting.
#define BULLET_ACT_FORCE_PIERCE "PIERCE" //It pierces through the object regardless of the bullet being piercing by default.
#define BULLET_ACT_TURF "TURF" //It hit us but it should hit something on the same turf too. Usually used for turfs.
+1 -1
View File
@@ -123,7 +123,7 @@ GLOBAL_LIST_INIT(bitfields, list(
"UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1,
"CAN_BE_DIRTY_1" = CAN_BE_DIRTY_1,
"HEAR_1" = HEAR_1,
"CHECK_RICOCHET_1" = CHECK_RICOCHET_1,
"DEFAULT_RICOCHET_1" = DEFAULT_RICOCHET_1,
"CONDUCT_1" = CONDUCT_1,
"NO_LAVA_GEN_1" = NO_LAVA_GEN_1,
"NODECONSTRUCT_1" = NODECONSTRUCT_1,
+12 -2
View File
@@ -141,8 +141,18 @@
return ..()
/atom/proc/handle_ricochet(obj/item/projectile/P)
return
/**
* Checks if a projectile should ricochet off of us. Projectiles get final say.
* [__DEFINES/projectiles.dm] for return values.
*/
/atom/proc/check_projectile_ricochet(obj/item/projectile/P)
return (flags_1 & CHECK_RICOCHET_1)? PROJECTILE_RICOCHET_YES : PROJECTILE_RICOCHET_NO
/**
* Handle a projectile ricochet. Return TRUE if we did something to the projectile like reflecting it/whatnot.
*/
/atom/proc/handle_projectile_ricochet(obj/item/projectile/P)
return FALSE
/atom/proc/CanPass(atom/movable/mover, turf/target)
return !density
@@ -191,7 +191,7 @@
icon = 'icons/turf/walls/shuttle_wall.dmi'
icon_state = "map-shuttle"
explosion_block = 3
flags_1 = CAN_BE_DIRTY_1 | CHECK_RICOCHET_1
flags_1 = CAN_BE_DIRTY_1 | DEFAULT_RICOCHET_1
sheet_type = /obj/item/stack/sheet/mineral/titanium
smooth = SMOOTH_MORE|SMOOTH_DIAGONAL
canSmoothWith = list(/turf/closed/wall/mineral/titanium, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock, /obj/structure/window/shuttle, /obj/structure/shuttle/engine/heater, /obj/structure/falsewall/titanium)
@@ -302,4 +302,4 @@
/turf/closed/wall/mineral/plastitanium/copyTurf(turf/T)
. = ..()
T.transform = transform
T.transform = transform
+1 -1
View File
@@ -41,7 +41,7 @@
/turf/closed/wall/attack_tk()
return
/turf/closed/wall/handle_ricochet(obj/item/projectile/P) //A huge pile of shitcode!
/turf/closed/wall/handle_projectile_ricochet(obj/item/projectile/P) //A huge pile of shitcode!
var/turf/p_turf = get_turf(P)
var/face_direction = get_dir(src, p_turf)
var/face_angle = dir2angle(face_direction)
@@ -45,13 +45,15 @@
desc = "A solid wall of slightly twitching tendrils with a reflective glow."
damaged_desc = "A wall of twitching tendrils with a reflective glow."
icon_state = "blob_glow"
flags_1 = CHECK_RICOCHET_1
point_return = 8
max_integrity = 100
brute_resist = 1
explosion_block = 2
/obj/structure/blob/shield/reflective/handle_ricochet(obj/item/projectile/P)
/obj/structure/blob/shield/reflective/check_projectile_ricochet(obj/item/projectile/P)
return PROJECTILE_RICOCHET_FORCE
/obj/structure/blob/shield/reflective/handle_projectile_ricochet(obj/item/projectile/P)
var/turf/p_turf = get_turf(P)
var/face_direction = get_dir(src, p_turf)
var/face_angle = dir2angle(face_direction)
@@ -61,4 +63,4 @@
var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s)
P.setAngle(new_angle_s)
visible_message("<span class='warning'>[P] reflects off [src]!</span>")
return TRUE
return TRUE
+50 -27
View File
@@ -45,6 +45,8 @@
var/pixels_range_leftover = 0
/// "leftover" tick pixels and stuff yeah, so we don't round off things and introducing tracing inaccuracy.
var/pixels_tick_leftover = 0
/// Used to detect jumps in the middle of a pixel_move. Yes, this is ugly as sin code-wise but it works.
var/pixel_move_interrupted = FALSE
/// Pixels moved per second.
var/pixels_per_second = TILES_TO_PIXELS(12.5)
@@ -249,27 +251,54 @@
else
return 50 //if the projectile doesn't do damage, play its hitsound at 50% volume
/obj/item/projectile/proc/on_ricochet(atom/A)
return
/obj/item/projectile/proc/store_hitscan_collision(datum/point/pcache)
beam_segments[beam_index] = pcache
beam_index = pcache
beam_segments[beam_index] = null
/obj/item/projectile/Bump(atom/A)
var/turf/T = get_turf(A)
if(trajectory && check_ricochet(A) && check_ricochet_flag(A) && ricochets < ricochets_max)
var/datum/point/pcache = trajectory.copy_to()
ricochets++
if(A.handle_ricochet(src))
on_ricochet(A)
ignore_source_check = TRUE
decayedRange = max(0, decayedRange - reflect_range_decrease)
range = decayedRange
if(hitscan)
store_hitscan_collision(pcache)
/**
* Determines if we should ricochet off of something.
* By default, asks the thing if we should ricochet off it, but because we're called first, we get final say.
* Returns TRUE or FALSE.
*/
/obj/item/projectile/proc/check_ricochet(atom/A)
if(ricochets > ricochets_max) //safety thing, we don't care about what the other thing says about this.
return FALSE
var/them = A.check_projectile_ricochet(src)
switch(them)
if(PROJECTILE_RICOCHET_PREVENT)
return FALSE
if(PROJECTILE_RICOCHET_FORCE)
return TRUE
if(PROJECTILE_RICOCHET_NO)
return FALSE
if(PROJECTILE_RICOCHET_YES)
return prob(ricochet_chance)
else
CRASH("Invalid return value for projectile ricochet check from [A].")
/**
* Handles ricocheting off of something.
* By default, also asks the thing to handle it, but because we're called first, we get final say.
*/
/obj/item/projectile/proc/handle_ricochet(atom/A)
ricochets++
ignore_source_check = TRUE
decayedRange = max(0, decayedRange - reflect_range_decrease)
pixel_move_interrupted = TRUE
range = decayedRange
return A.handle_projectile_ricochet(src)
/obj/item/projectile/Bump(atom/A)
if(!trajectory)
return
var/turf/T = get_turf(A)
if(check_ricochet(A))
var/datum/point/pcache = trajectory.copy_to()
if(hitscan)
store_hitscan_collision(pcache)
handle_ricochet(A)
return TRUE
var/distance = get_dist(T, starting) // Get the distance between the turf shot from and the mob we hit and use that for the calculations.
if(def_zone && check_zone(def_zone) != BODY_ZONE_CHEST)
@@ -344,16 +373,6 @@
return T
//Returns null if nothing at all was found.
/obj/item/projectile/proc/check_ricochet()
if(prob(ricochet_chance))
return TRUE
return FALSE
/obj/item/projectile/proc/check_ricochet_flag(atom/A)
if(A.flags_1 & CHECK_RICOCHET_1)
return TRUE
return FALSE
/// one move is a tile.
/obj/item/projectile/proc/return_predicted_turf_after_moves(moves, forced_angle) //I say predicted because there's no telling that the projectile won't change direction/location in flight.
if(!trajectory && isnull(forced_angle) && isnull(Angle))
@@ -457,6 +476,7 @@
trajectory.initialize_location(target.x, target.y, target.z, 0, 0)
if(hitscan)
record_hitscan_start(RETURN_PRECISE_POINT(src))
pixel_move_interrupted = TRUE
if(zc)
after_z_change(old, target)
@@ -505,7 +525,7 @@
* The proc to make the projectile go, using a simulated pixel movement line trace.
* Note: deciseconds_equivalent is currently only used for homing, times is the number of times to move pixel_increment_amount.
* Trajectory multiplier directly modifies the factor of pixel_increment_amount to go per time.
* It's complicated, so probably just don'ot mess with this unless you know what you're doing.
* It's complicated, so probably just don't mess with this unless you know what you're doing.
*/
/obj/item/projectile/proc/pixel_move(times, hitscanning = FALSE, deciseconds_equivalent = world.tick_lag, trajectory_multiplier = 1, allow_animation = TRUE)
if(!loc || !trajectory)
@@ -515,6 +535,7 @@
M.Turn(Angle)
transform = M
var/forcemoved = FALSE
pixel_move_interrupted = FALSE // reset that
var/turf/oldloc = loc
var/old_px = pixel_x
var/old_py = pixel_y
@@ -550,7 +571,9 @@
if(!--safety)
CRASH("[type] took too long (allowed: [CEILING(pixel_increment_amount/world.icon_size,1)*2] moves) to get to its location.")
step_towards(src, T)
if(QDELETED(src))
if(QDELETED(src) || pixel_move_interrupted) // this doesn't take into account with pixel_move_interrupted the portion of the move cut off by any forcemoves, but we're opting to ignore that for now
// the reason is the entire point of moving to pixel speed rather than tile speed is smoothness, which will be crucial when pixel movement is done in the future
// reverting back to tile is more or less the only way of fixing this issue.
return
pixels_range_leftover += pixel_increment_amount
if(pixels_range_leftover > world.icon_size)
+1
View File
@@ -85,6 +85,7 @@
#include "code\__DEFINES\preferences.dm"
#include "code\__DEFINES\procpath.dm"
#include "code\__DEFINES\profile.dm"
#include "code\__DEFINES\projectiles.dm"
#include "code\__DEFINES\qdel.dm"
#include "code\__DEFINES\radiation.dm"
#include "code\__DEFINES\radio.dm"