diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index a5e69bdc7b..e443e57b14 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -14,6 +14,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define NOBLUDGEON 4 // when an item has this it produces no "X has been hit by Y with Z" message in the default attackby() #define MASKINTERNALS 8 // mask allows internals #define HEAR 16 // This flag is what recursive_hear_check() uses to determine wether to add an item to the hearer list or not. +#define CHECK_RICOCHET 32 // Projectiels will check ricochet on things impacted that have this. #define CONDUCT 64 // conducts electricity (metal etc.) #define ABSTRACT 128 // for all things that are technically items but used for various different stuff, made it 128 because it could conflict with other flags other way #define NODECONSTRUCT 128 // For machines and structures that should not break into parts, eg, holodeck stuff @@ -57,6 +58,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define UNUSED_TRANSIT_TURF 2 #define CAN_BE_DIRTY 4 //If a turf can be made dirty at roundstart. This is also used in areas. #define NO_DEATHRATTLE 16 // Do not notify deadchat about any deaths that occur on this turf. +//#define CHECK_RICOCHET 32 //Same thing as atom flag. /* These defines are used specifically with the atom/pass_flags bitmask diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm index 7e892e8dd4..7e0fd531eb 100644 --- a/code/__HELPERS/maths.dm +++ b/code/__HELPERS/maths.dm @@ -130,6 +130,22 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, var/t = round((val - min) / d) return val - (t * d) +#define NORM_ROT(rot) ((((rot % 360) + (rot - round(rot, 1))) > 0) ? ((rot % 360) + (rot - round(rot, 1))) : (((rot % 360) + (rot - round(rot, 1))) + 360)) + +/proc/get_angle_of_incidence(face_angle, angle_in, auto_normalize = TRUE) + + var/angle_in_s = NORM_ROT(angle_in) + var/face_angle_s = NORM_ROT(face_angle) + var/incidence = face_angle_s - angle_in_s + var/incidence_s = incidence + while(incidence_s < -90) + incidence_s += 180 + while(incidence_s > 90) + incidence_s -= 180 + if(auto_normalize) + return incidence_s + else + return incidence //A logarithm that converts an integer to a number scaled between 0 and 1 (can be tweaked to be higher). //Currently, this is used for hydroponics-produce sprite transforming, but could be useful for other transform functions. @@ -141,8 +157,6 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, return size_factor + scaling_modifier //scale mod of 0 results in a number from 0 to 1. A scale modifier of +0.5 returns 0.5 to 1.5 //to_chat(world, "Transform multiplier of [src] is [size_factor + scaling_modifer]") - - //converts a uniform distributed random number into a normal distributed one //since this method produces two random numbers, one is saved for subsequent calls //(making the cost negligble for every second call) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 4a0f05602b..65d4cf1449 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -104,6 +104,9 @@ return ..() +/atom/proc/handle_ricochet(obj/item/projectile/P) + return + /atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5) return (!density || !height) diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm index 741d4f2958..2c3e60694d 100644 --- a/code/game/turfs/closed.dm +++ b/code/game/turfs/closed.dm @@ -24,9 +24,6 @@ /turf/closed/indestructible/oldshuttle/corner icon_state = "corner" - - - /turf/closed/indestructible/splashscreen name = "Space Station 13" icon = 'config/title_screens/images/blank.png' diff --git a/code/game/turfs/simulated/wall/mineral_walls.dm b/code/game/turfs/simulated/wall/mineral_walls.dm index b78099c6bb..2cfb32f6dc 100644 --- a/code/game/turfs/simulated/wall/mineral_walls.dm +++ b/code/game/turfs/simulated/wall/mineral_walls.dm @@ -175,6 +175,7 @@ desc = "A light-weight titanium wall used in shuttles." icon = 'icons/turf/walls/shuttle_wall.dmi' icon_state = "map-shuttle" + flags = CAN_BE_DIRTY | CHECK_RICOCHET 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/, /turf/closed/wall/shuttle, /obj/structure/window/shuttle, /obj/structure/shuttle/engine/heater, /obj/structure/falsewall/titanium) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 068dd0f218..44dc1afee7 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -28,6 +28,20 @@ /turf/closed/wall/attack_tk() return +/turf/closed/wall/handle_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) + var/incidence_s = get_angle_of_incidence(face_angle, P.Angle) + var/new_angle = face_angle + incidence_s + var/new_angle_s = new_angle + while(new_angle_s > 180) // Translate to regular projectile degrees + new_angle_s -= 360 + while(new_angle_s < -180) + new_angle_s += 360 + P.Angle = new_angle_s + return TRUE + /turf/closed/wall/proc/dismantle_wall(devastated=0, explode=0) if(devastated) devastate_wall() diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 3dbadc85c5..8c810155db 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -28,6 +28,9 @@ var/spread = 0 //amount (in degrees) of projectile spread var/legacy = 0 //legacy projectile system animate_movement = 0 //Use SLIDE_STEPS in conjunction with legacy + var/ricochets = 0 + var/ricochets_max = 2 + var/ricochet_chance = 30 var/damage = 10 var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here @@ -132,7 +135,11 @@ /obj/item/projectile/Bump(atom/A, yes) if(!yes) //prevents double bumps. return - if(firer) + if(check_ricochet() && check_ricochet_flag(A) && ricochets < ricochets_max) + ricochets++ + if(A.handle_ricochet(src)) + return FALSE + if(firer && !ricochets) if(A == firer || (A == firer.loc && istype(A, /obj/mecha))) //cannot shoot yourself or your mech loc = A.loc return 0 @@ -166,6 +173,16 @@ picked_mob.bullet_act(src, def_zone) qdel(src) +/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 & CHECK_RICOCHET) + return TRUE + return FALSE + /obj/item/projectile/Process_Spacemove(var/movement_dir = 0) return 1 //Bullets don't drift in space diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 766d8b5e39..427f590ba5 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -11,7 +11,9 @@ eyeblur = 2 impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser light_color = LIGHT_COLOR_RED - + ricochets_max = 50 //Honk! + ricochet_chance = 80 + /obj/item/projectile/beam/laser /obj/item/projectile/beam/laser/heavylaser