diff --git a/code/modules/projectiles/ammunition/ammo_casings.dm b/code/modules/projectiles/ammunition/ammo_casings.dm index 50b5aa6ad6c..5ceb6aa386b 100644 --- a/code/modules/projectiles/ammunition/ammo_casings.dm +++ b/code/modules/projectiles/ammunition/ammo_casings.dm @@ -47,7 +47,6 @@ icon_state = "gshell" projectile_type = "/obj/item/projectile/bullet/pellet" pellets = 5 - deviation = 0.8 deviation = 30 @@ -76,7 +75,7 @@ projectile_type = /obj/item/projectile/bullet/pellet/random m_amt = 250 pellets = 5 - deviation = 1.0 + deviation = 30 /obj/item/ammo_casing/shotgun/improvised/overload/New() ..() diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index f086b38988b..4efee86bb44 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -114,11 +114,6 @@ add_fingerprint(user) - var/turf/curloc = get_turf(user) - var/turf/targloc = get_turf(target) - if (!istype(targloc) || !istype(curloc)) - return - if(!special_check(user)) return @@ -130,23 +125,40 @@ if(!process_chambered()) //CHECK return click_empty(user) - if(!in_chamber) - return - if(heavy_weapon) if(user.get_inactive_hand()) recoil = 4 //one-handed kick else recoil = initial(recoil) - in_chamber.firer = user - in_chamber.def_zone = user.zone_sel.selecting - if(targloc == curloc) - user.bullet_act(in_chamber) - qdel(in_chamber) - update_icon() + if (istype(in_chamber, /obj/item/projectile/bullet/blank)) // A hacky way of making blank shotgun shells work again. Honk. + in_chamber.delete() + in_chamber = null return + user.changeNext_move(CLICK_CD_RANGE) + + var/spread = 0 + var/turf/targloc = get_turf(target) + if(chambered) + for (var/i = max(1, chambered.pellets), i > 0, i--) //Previous way of doing it fucked up math for spreading. This way, even the first projectile is part of the spread code. + if(i != max(1, chambered.pellets)) //Have we fired the initial chambered bullet yet? + in_chamber = new chambered.projectile_type() + ready_projectile(target, user) + prepare_shot(in_chamber) + if(chambered.deviation) + if(randomspread) //Random spread + spread = (rand() - 0.5) * chambered.deviation + else //Smart spread + spread = (i / chambered.pellets - 0.5) * chambered.deviation + if(!process_projectile(targloc, user, params, spread)) + return 0 + else + ready_projectile(target, user) + prepare_shot(in_chamber) + if(!process_projectile(targloc, user, params, spread)) + return 0 + if(recoil) spawn() shake_camera(user, recoil + 1, recoil) @@ -165,31 +177,33 @@ user.visible_message("[src] flies out of [user]'s hands!", "[src] kicks out of your grip!") user.drop_item() - if (istype(in_chamber, /obj/item/projectile/bullet/blank)) // A hacky way of making blank shotgun shells work again. Honk. - in_chamber.delete() - in_chamber = null - return - + update_icon() + if(user.hand) + user.update_inv_l_hand() + else + user.update_inv_r_hand() +/obj/item/weapon/gun/proc/ready_projectile(atom/target as mob|obj|turf, mob/living/user) + in_chamber.firer = user + in_chamber.def_zone = user.zone_sel.selecting in_chamber.original = target + return + +/obj/item/weapon/gun/proc/process_projectile(var/turf/targloc, mob/living/user as mob|obj, params, spread) + var/turf/curloc = user.loc + if (!istype(targloc) || !istype(curloc) || !in_chamber) + return 0 + if(targloc == curloc) //Fire the projectile + user.bullet_act(in_chamber) + qdel(in_chamber) + update_icon() + return 1 + in_chamber.loc = get_turf(user) in_chamber.starting = get_turf(user) - in_chamber.shot_from = src - user.changeNext_move(CLICK_CD_RANGE) - in_chamber.silenced = silenced in_chamber.current = curloc in_chamber.yo = targloc.y - curloc.y in_chamber.xo = targloc.x - curloc.x - - - var/spread = 0 - if(istype(user, /mob/living/carbon)) //Instead of modifying projectile's originl pixels, we can increase spread. - var/mob/living/carbon/mob = user - if(mob.shock_stage > 120) - spread += rand(-2,2) - else if(mob.shock_stage > 70) - spread += rand(-1,1) - if(params) var/list/mouse_control = params2list(params) if(mouse_control["icon-x"]) @@ -215,38 +229,19 @@ in_chamber.Angle = angle - if(chambered) - for (var/i = max(1, chambered.pellets), i > 0, i--) //Previous way of doing it fucked up math for spreading. This way, even the first projectile is part of the spread code. - if(randomspread) //Random spread - spread = (rand() - 0.5) * chambered.deviation - else //Smart spread - spread = (i / chambered.pellets - 0.5) * chambered.deviation + if(istype(user, /mob/living/carbon)) //Increase spread based on shock + var/mob/living/carbon/mob = user + if(mob.shock_stage > 120) + spread += rand(-5,5) + else if(mob.shock_stage > 70) + spread += rand(-2,2) - in_chamber = new chambered.projectile_type() - prepare_shot(in_chamber) - in_chamber.original = target - in_chamber.loc = get_turf(user) - in_chamber.starting = get_turf(user) - in_chamber.current = curloc - in_chamber.yo = targloc.y - curloc.y - in_chamber.xo = targloc.x - curloc.x - if(spread) - in_chamber.Angle += chambered.spread - if(in_chamber) - in_chamber.process() - else - if(spread) - in_chamber.Angle += chambered.spread - if(in_chamber) - in_chamber.process() - sleep(1) - in_chamber = null - - update_icon() - if(user.hand) - user.update_inv_l_hand() - else - user.update_inv_r_hand() + if(spread) + in_chamber.Angle += spread + if(in_chamber) + in_chamber.process() + in_chamber = null + return 1 /obj/item/weapon/gun/proc/can_fire() return process_chambered() diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 251b9b568ea..a4ce8cdeac2 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -64,6 +64,7 @@ var/speed = 1 //Amount of deciseconds it takes for projectile to travel. Animation is adjusted accordingly. var/Angle = 0 //For new projectiles var/spread = 0 //Amount of degrees by which the projectiles will be spread DURING MOVEMENT. It exists for chaotic types of projectiles, like bees or something. + var/legacy = 0 //Use the legacy projectile system or new pixel movement? proc/delete() // Garbage collect the projectiles @@ -179,43 +180,108 @@ return 1 - process() - spawn while(src) - if(kill_count < 1) - del(src) - return - kill_count-- - if((!( current ) || loc == current)) - current = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z) - if((x == 1 || x == world.maxx || y == 1 || y == world.maxy)) - del(src) - return - step_towards(src, current) - sleep(1) - if(!bumped && !isturf(original)) - if(loc == get_turf(original)) - if(!(original in permutated)) - Bump(original) - sleep(1) - Range() - return - proc/dumbfire(var/dir) // for spacepods, go snowflake go - if(!dir) - del(src) - if(kill_count < 1) - del(src) - kill_count-- - spawn while(src) - var/turf/T = get_step(src, dir) - step_towards(src, T) - sleep(1) - if(!bumped && !isturf(original)) - if(loc == get_turf(original)) - if(!(original in permutated)) - Bump(original) - sleep(1) - return + process(var/setAngle) + if(setAngle) Angle = setAngle + if(!legacy) + spawn() //New projectile system + while(loc) + if(kill_count < 1) + qdel(src) + return + kill_count-- + if((!( current ) || loc == current)) + current = locate(Clamp(x+xo,1,world.maxx),Clamp(y+yo,1,world.maxy),z) + if(!Angle) + Angle=round(Get_Angle(src,current)) + //world << "[Angle] angle" + //overlays.Cut() + //var/icon/I=new(initial(icon),icon_state) //using initial(icon) makes sure that the angle for that is reset as well + //I.Turn(Angle) + //I.DrawBox(rgb(255,0,0,50),1,1,32,32) + //icon = I + if(spread) //Chaotic spread + Angle += (rand() - 0.5) * spread + var/matrix/M = new//matrix(transform) + M.Turn(Angle) + transform = M + + var/Pixel_x=round(sin(Angle)+16*sin(Angle)*2) + var/Pixel_y=round(cos(Angle)+16*cos(Angle)*2) + var/pixel_x_offset = pixel_x + Pixel_x + var/pixel_y_offset = pixel_y + Pixel_y + var/new_x = x + var/new_y = y + //Not sure if using whiles for this is good + while(pixel_x_offset > 16) + //world << "Pre-adjust coords (x++): xy [pixel_x] xy offset [pixel_x_offset]" + pixel_x_offset -= 32 + pixel_x -= 32 + new_x++// x++ + while(pixel_x_offset < -16) + //world << "Pre-adjust coords (x--): xy [pixel_x] xy offset [pixel_x_offset]" + pixel_x_offset += 32 + pixel_x += 32 + new_x-- + + while(pixel_y_offset > 16) + //world << "Pre-adjust coords (y++): py [pixel_y] py offset [pixel_y_offset]" + pixel_y_offset -= 32 + pixel_y -= 32 + new_y++ + while(pixel_y_offset < -16) + //world << "Pre-adjust coords (y--): py [pixel_y] py offset [pixel_y_offset]" + pixel_y_offset += 32 + pixel_y += 32 + new_y-- + + speed = round(speed) //Just in case. + step_towards(src, locate(new_x, new_y, z)) //Original projectiles stepped towards 'current' + if(speed <= 1) //We should really only animate at speed 2 + pixel_x = pixel_x_offset + pixel_y = pixel_y_offset + else + animate(src, pixel_x = pixel_x_offset, pixel_y = pixel_y_offset, time = max(1, (speed <= 3 ? speed - 1 : speed))) + +/* + var/turf/T = get_turf(src) + if(T) + T.color = "#6666FF" + spawn(10) + T.color = initial(T.color) +*/ + + if(!bumped && ((original && original.layer>=2.75) || ismob(original))) + if(loc == get_turf(original)) + if(!(original in permutated)) + Bump(original) + Range() + sleep(max(1, speed)) + else + spawn() //Old projectile system + while(loc) + if(kill_count < 1) + qdel(src) + return + kill_count-- + if((!( current ) || loc == current)) + current = locate(Clamp(x+xo,1,world.maxx),Clamp(y+yo,1,world.maxy),z) + if(!Angle) + Angle=round(Get_Angle(src,current)) + var/matrix/M = new//matrix(transform) + M.Turn(Angle) + transform = M //So there's no need to give icons directions again + step_towards(src, current) + if(!bumped && ((original && original.layer>=2.75) || ismob(original))) + if(loc == get_turf(original)) + if(!(original in permutated)) + Bump(original) + Range() + sleep(1) + + proc/dumbfire(var/dir) + current = get_ranged_target_turf(src, dir, world.maxx) //world.maxx is the range. Not sure how to handle this better. + process() /obj/item/projectile/test //Used to see if you can hit them. invisibility = 101 //Nope! Can't see me! diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi index 57f75b0f54e..73177afd0bd 100644 Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ