// Not all that crazy shit /datum/projectile/special name = "special" icon = 'icons/obj/projectiles.dmi' icon_state = "laser" power = 15 cost = 25 dissipation_rate = 1 dissipation_delay = 0 ks_ratio = 1.0 sname = "laser" shot_sound = 'sound/weapons/Taser.ogg' shot_number = 1 damage_type = D_SPECIAL hit_ground_chance = 50 window_pass = 0 on_hit(atom/hit, direction, projectile) return /datum/projectile/special/kiss name = "kiss" icon_state = "kiss" power = 0 sname = "kiss" shot_sound = 'sound/voice/gasps/gasp.ogg' on_hit(atom/hit, direction, var/obj/projectile/projectile) if(istype(hit, /mob/living/carbon/human)) var/mob/living/carbon/human/H = hit boutput(H, "You catch the kiss and save it for later.") /datum/projectile/special/acid name = "acid" icon_state = "radbolt" power = 45 dissipation_rate = 30 dissipation_delay = 10 sname = "acid" on_hit(atom/hit, direction, var/obj/projectile/projectile) var/power = projectile.power hit.damage_corrosive(power) potent power = 100 weak power = 15 /datum/projectile/special/acidspit name = "acid splash" icon_state = "cbbolt" power = 0.8 dissipation_rate = 20 dissipation_delay = 10 sname = "acid" damage_type = D_TOXIC hit_mob_sound = 'sound/impact_sounds/burn_sizzle.ogg' hit_object_sound = 'sound/impact_sounds/burn_sizzle.ogg' shot_sound = null on_hit(atom/hit, direction, var/obj/projectile/projectile) ..() var/power = projectile.power hit.damage_corrosive(power) /datum/projectile/special/ice name = "ice" icon_state = "ice" power = 120 dissipation_rate = 10 dissipation_delay = 3 sname = "ice" on_hit(atom/hit, direction, var/obj/projectile/projectile) hit.damage_cold(projectile.power / 10) if (ishuman(hit)) var/mob/living/L = hit L.bodytemperature -= projectile.power /datum/projectile/special/material_changer name = "transmutation bolt" icon_state = "ice" power = 1 dissipation_rate = 1 dissipation_delay = 25 sname = "ice" color_icon = "#aaff00" var/material_to_make = "gold" tick(var/obj/projectile/P) var/turf/T = get_turf(P) if (T) T.setMaterial(getMaterial("gold")) on_hit(var/atom/A) A.setMaterial(getMaterial("gold")) /datum/projectile/special/piercing name = "focused beam" sname = "focused beam" icon_state = "laser_white" window_pass = 1 power = 30 dissipation_rate = 1 dissipation_delay = 3 damage_type = D_ENERGY pierces = -1 ticks_between_mob_hits = 10 /datum/projectile/special/wallhax name = "phased beam" sname = "phased beam" icon_state = "crescent_white" window_pass = 1 power = 30 dissipation_rate = 1 dissipation_delay = 3 damage_type = D_ENERGY goes_through_walls = 1 // Mildly crazy shit /datum/projectile/special/spreader name = "spread shot" sname = "spread shot" shot_sound = 'sound/weapons/grenade.ogg' var/pellets_to_fire = 15 var/spread_projectile_type = /datum/projectile/bullet/flak_chunk var/split_type = 0 // 0 = on spawn // 1 = on impact on_launch(var/obj/projectile/P) if(split_type == 0) split(P) on_hit(var/atom/A,var/obj/projectile/P) if(split_type == 1) split(P) proc/new_pellet(var/obj/projectile/P, var/turf/PT, var/datum/projectile/F) return proc/split(var/obj/projectile/P) var/datum/projectile/F = new spread_projectile_type() var/turf/PT = get_turf(P) var/pellets = pellets_to_fire while (pellets > 0) pellets-- new_pellet(P,PT,F) P.die() /datum/projectile/special/spreader/uniform_burst name = "uniform spread" sname = "uniform spread" var/spread_angle = 45 var/current_angle = 0 var/angle_adjust_per_pellet = 0 var/initial_angle_offset_mult = 0.5 on_launch(var/obj/projectile/P) angle_adjust_per_pellet = ((spread_angle * 2) / pellets_to_fire) current_angle = (0 - spread_angle) + (angle_adjust_per_pellet * initial_angle_offset_mult) ..() new_pellet(var/obj/projectile/P, var/turf/PT, var/datum/projectile/F) var/obj/projectile/FC = initialize_projectile(PT, F, P.xo, P.yo, P.shooter) FC.rotateDirection(current_angle) FC.launch() current_angle += angle_adjust_per_pellet /datum/projectile/special/spreader/buckshot_burst name = "buckshot" sname = "buckshot" cost = 1 pellets_to_fire = 10 spread_projectile_type = /datum/projectile/bullet/buckshot var/speed_max = 5 var/speed_min = 60 var/spread_angle_variance = 5 var/dissipation_variance = 1 new_pellet(var/obj/projectile/P, var/turf/PT, var/datum/projectile/F) var/obj/projectile/FC = initialize_projectile(PT, F, P.xo, P.yo, P.shooter) FC.rotateDirection(rand(0-spread_angle_variance,spread_angle_variance)) FC.internal_speed = rand(speed_min,speed_max) FC.dissipation_ticker = rand(0,dissipation_variance) FC.launch() /datum/projectile/special/spreader/uniform_burst/circle name = "circular spread" sname = "circular spread" spread_angle = 360 pellets_to_fire = 20 /datum/projectile/special/spreader/uniform_burst/blaster name = "blaster wave" sname = "wave fire" spread_angle = 33 cost = 200 pellets_to_fire = 5 spread_projectile_type = /datum/projectile/laser/blaster/blast shot_sound = 'sound/weapons/laser_f.ogg' // Really crazy shit /datum/projectile/special/shock_orb name = "ball lightning" sname = "ball lightning" icon_state = "elecorb" shot_sound = 'sound/weapons/energy/LightningCannon.ogg' power = 75 cost = 75 damage_type = D_ENERGY dissipation_delay = 15 color_red = 0.1 color_green = 0.3 color_blue = 1 ks_ratio = 0.8 var/arc_chance_per_tick = 33 var/max_arcs_per_tick = 3 var/min_arcs_per_tick = 1 var/arcs_on_hit = 8 var/shock_range = 3 var/wattage = 5000 tick(var/obj/projectile/P) if (prob(arc_chance_per_tick)) var/list/sfloors = list() for (var/turf/T in view(shock_range, P)) if (!T.density) sfloors += T var/shocks = rand(min_arcs_per_tick, max_arcs_per_tick) while (shocks > 0 && sfloors.len) shocks-- var/turf/Q = pick(sfloors) arcFlashTurf(P, Q, wattage) sfloors -= Q on_hit(var/atom/A) playsound(A, "sound/weapons/energy/LightningCannonImpact.ogg", 50, 1) var/list/sfloors = list() for (var/turf/T in view(shock_range, A)) if (!T.density) sfloors += T var/arcs = arcs_on_hit while (arcs > 0 && sfloors.len) arcs-- var/turf/Q = pick(sfloors) arcFlashTurf(A, Q, wattage) sfloors -= Q always_mob tick(var/obj/projectile/P) if (prob(arc_chance_per_tick)) var/list/smobs = list() for (var/mob/M in view(shock_range, P)) smobs += M var/shocks = rand(min_arcs_per_tick, max_arcs_per_tick) while (shocks > 0 && smobs.len) shocks-- var/mob/Q = pick(smobs) arcFlash(P, Q, wattage) smobs -= Q /datum/projectile/special/inferno name = "inferno bomb" sname = "inferno bomb" icon_state = "fusionorb" shot_sound = 'sound/weapons/energy/InfernoCannon.ogg' power = 75 cost = 75 damage_type = D_BURNING dissipation_delay = 15 ks_ratio = 0.8 var/burn_range = 1 var/blast_size = 3 var/temperature = 800 tick(var/obj/projectile/P) fireflash_sm(get_turf(P), burn_range, temperature) on_hit(var/atom/A) playsound(A, "sound/effects/ExplosionFirey.ogg", 100, 1) fireflash_sm(get_turf(A), blast_size, temperature) /datum/projectile/special/howitzer name = "plasma howitzer" sname = "plasma howitzer" icon = 'icons/obj/32x96.dmi' icon_state = "howitzer-shot" shot_sound = 'sound/weapons/energy/howitzer_shot.ogg' power = 10000 // blam = INF cost = 2500 damage_type = D_BURNING dissipation_delay = 75 dissipation_rate = 300 ks_ratio = 0.8 brightness = 2 projectile_speed = 28 impact_range = 32 caliber = 40 pierces = -1 goes_through_walls = 1 color_red = 1 color_green = 1 color_blue = 0 var/burn_range = 1 var/blast_size = 2 var/temperature = 5000 var/impacted = 0 tick(var/obj/projectile/P) var/T1 = get_turf(P) if((!istype(T1,/turf/space))) // so uh yeah this will be pretty mean fireflash_sm(T1, burn_range, temperature) new /obj/effects/explosion/dangerous(get_step(P.loc,P.dir)) on_launch(var/obj/projectile/P) for(var/mob/M in range(P.loc, 6)) shake_camera(M, 3, 1) on_hit(var/atom/A) var/turf/T = get_turf(A) playsound(A, "sound/effects/ExplosionFirey.ogg", 60, 1) if(!src.impacted) world << sound('sound/weapons/energy/howitzer_impact.ogg', volume = 70) src.impacted = 1 SPAWN_DBG(1 DECI SECOND) for(var/mob/living/M in mobs) shake_camera(M, 2, 1) SPAWN_DBG(0) explosion_new(null, T, 30, 1) if(prob(50)) world << sound('sound/effects/creaking_metal1.ogg', volume = 60) /datum/projectile/special/spewer name = "volatile bolt" sname = "volatile bolt" icon_state = "orb_white" shot_sound = 'sound/weapons/laserultra.ogg' power = 100 cost = 75 damage_type = D_BURNING dissipation_delay = 0 dissipation_rate = 5 ks_ratio = 0.8 var/bolt_type = /datum/projectile/laser/spewer_bolt var/datum/projectile/bolt_instance = null var/bolt_chance_per_tick = 50 on_launch(var/obj/projectile/P) bolt_instance = new bolt_type() tick(var/obj/projectile/P) if (prob(bolt_chance_per_tick) && istype(bolt_instance)) var/list/sfloors = list() for (var/turf/T in view(7, P)) if (!T.density) sfloors += T new_bolt(P, get_turf(P), bolt_instance) proc/new_bolt(var/obj/projectile/P, var/turf/PT, var/datum/projectile/F) var/obj/projectile/FC = initialize_projectile(PT, F, rand(-projectile_speed,projectile_speed), rand(-projectile_speed,projectile_speed), P.shooter) FC.launch() /datum/projectile/laser/spewer_bolt name = "volatile bolt fragment" sname = "volatile bolt fragment" icon_state = "ball_white" shot_sound = 'sound/weapons/blaster_a.ogg' power = 5 dissipation_delay = 15 dissipation_rate = 1 /datum/projectile/laser/punch // yep :I name = "punch" window_pass = 0 icon_state = "punch" damage_type = D_KINETIC power = 0 cost = 1 brightness = 0 sname = "punch" shot_sound = 'sound/impact_sounds/Generic_Swing_1.ogg' dissipation_delay = 1 dissipation_rate = 35 icon_turf_hit = null on_hit(atom/hit) if (usr && hit) hit.attack_hand(usr) //mbc : hey i know homing projectiles exist already as 'seeker', but i like mine better /datum/projectile/special/homing name = "homing" icon = 'icons/obj/projectiles.dmi' icon_state = "laser" power = 1 cost = 1 dissipation_rate = 0 dissipation_delay = 0 shot_sound = 'sound/weapons/Taser.ogg' shot_number = 1 damage_type = D_SPECIAL hit_ground_chance = 100 window_pass = 0 precalculated = 0 var/min_speed = 0 var/max_speed = 23 var/start_speed = 6 var/easemult = 0.1 var/auto_find_targets = 1 var/desired_x = 0 var/desired_y = 0 var/rotate_proj = 1 var/face_desired_dir = 0 goes_through_walls = 1 on_launch(var/obj/projectile/P) ..() P.internal_speed = start_speed if (auto_find_targets) P.targets = list() for(var/mob/M in view(P,15)) P.targets += M on_hit(atom/hit, direction, projectile) return proc/calc_desired_x_y(var/obj/projectile/P) .= 0 //if (auto_find_targets) //prob expensive // P.targets = list() // for(var/mob/M in view(P,6)) // P.targets += M if (P.targets && P.targets.len && P.targets[1]) var/atom/closest = P.targets[1] for (var/atom in P.targets) var/atom/A = atom if (A == P.shooter) continue if (get_dist(P,A) < get_dist(P,closest)) closest = A desired_x = closest.x - P.x desired_y = closest.y - P.y .= 1 tick(var/obj/projectile/P) if (!P) return desired_x = 0 desired_y = 0 if (calc_desired_x_y(P)) var/magnitude = vector_magnitude(desired_x,desired_y) if (magnitude != 0) desired_x /= magnitude desired_y /= magnitude desired_x *= max_speed desired_y *= max_speed var/xchanged = P.xo + ((desired_x - P.xo) * easemult) var/ychanged = P.yo + ((desired_y - P.yo) * easemult) var/setangle = 0 if (face_desired_dir) setangle = atan2(desired_y,desired_x) P.setDirection(xchanged,ychanged, do_turn = rotate_proj, angle_override = setangle) P.internal_speed = ( max(min_speed, min(max_speed, magnitude)) ) desired_x = 0 desired_y = 0 ..() /datum/projectile/special/homing/slow max_speed = 1 /datum/projectile/special/homing/vamp_blood name = "blood glob" icon_state = "bloodproj" start_speed = 9 goes_through_walls = 1 goes_through_mobs = 1 auto_find_targets = 0 silentshot = 1 shot_sound = "sound/impact_sounds/Flesh_Tear_1.ogg" on_launch(var/obj/projectile/P) if (!("victim" in P.special_data)) P.die() return if (!("vamp" in P.special_data)) P.die() return P.layer = EFFECTS_LAYER_BASE flick("bloodproj",P) ..() on_hit(atom/hit, direction, var/obj/projectile/P) if (("vamp" in P.special_data)) var/datum/abilityHolder/vampire/vampire = P.special_data["vamp"] if (vampire.owner == hit) P.die() ..() on_end(var/obj/projectile/P) if (("vamp" in P.special_data) && ("victim" in P.special_data)) var/datum/abilityHolder/vampire/vampire = P.special_data["vamp"] var/mob/living/victim = P.special_data["victim"] if (vampire && victim) if (vampire.can_bite(victim,is_pointblank = 0)) vampire.do_bite(victim, mult = 0.3333) vampire.owner.add_stamina(20) victim.remove_stamina(4) ..() //vamp bail out travel /datum/projectile/special/homing/travel name = "mysterious mystery mist" icon_state = "vamp_travel" auto_find_targets = 0 max_speed = 2 start_speed = 0.1 shot_sound = "sound/effects/mag_phase.ogg" goes_through_walls = 1 goes_through_mobs = 1 silentshot = 1 on_hit(atom/hit, direction, var/obj/projectile/P) ..() if (istype(hit, /obj/storage/closet/coffin/vampire)) P.special_data["insert_owner"] = hit P.die() on_launch(var/obj/projectile/P) ..() if (!("owner" in P.special_data)) P.die() return var/mob/carryme = P.special_data["owner"] carryme.set_loc(P) tick(var/obj/projectile/P) ..() if (!(P.targets && P.targets.len && P.targets[1])) P.die() on_end(var/obj/projectile/P) if (("owner" in P.special_data) && P.proj_data == src) var/mob/dropme = P.special_data["owner"] if (("insert_owner" in P.special_data) && P.special_data["insert_owner"]) dropme.set_loc(P.special_data["insert_owner"]) else if (dropme.loc == P) dropme.set_loc(get_turf(P)) boutput(dropme, __red("Your coffin was lost or destroyed! Oh no!!!")) ..() /datum/projectile/special/homing/orbiter icon_state = "bloodproj" easemult = 0.3 rotate_proj = 1 face_desired_dir = 1 goes_through_walls = 1 var/radius = 1.4 var/ang_inc = 15 on_launch(var/obj/projectile/P) ..() P.special_data["orbit_angle"] = 0 P.special_data["diss_count"] = 0 calc_desired_x_y(var/obj/projectile/P) .= 0 if (P.targets && P.targets.len && P.targets[1]) P.special_data["orbit_angle"] += ang_inc if (P.special_data["orbit_angle"] > 360) P.special_data["orbit_angle"] -= 360 var/atom/target = P.targets[1] //var/ang_between = get_angle(target,P) var/tx = target.x + cos(P.special_data["orbit_angle"]) var/ty = target.y + sin(P.special_data["orbit_angle"]) desired_x = (tx - P.x) desired_y = (ty - P.y) .= 1 else P.special_data["diss_count"] += 1 if (P.special_data["diss_count"] > 40) P.die() /datum/projectile/special/homing/orbiter/spiritbat name = "frost bat" icon = 'icons/misc/critter.dmi' icon_state = "spiritbat" rotate_proj = 0 face_desired_dir = 1 goes_through_walls = 1 shot_sound = 0 hit_mob_sound = 'sound/effects/mag_iceburstimpact_high.ogg' hit_object_sound = 'sound/effects/mag_iceburstimpact_high.ogg' var/temp_reduc = 80 on_launch(var/obj/projectile/P) ..() P.collide_with_other_projectiles = 1 //P.transform = matrix() on_hit(atom/hit, direction, var/obj/projectile/P) ..() if (istype(hit, /obj/projectile)) var/obj/projectile/pass_proj = hit if (pass_proj.proj_data.hit_object_sound) playsound(pass_proj.loc, pass_proj.proj_data.hit_object_sound, 60, 0.5) if (pass_proj.proj_data.name != src.name) pass_proj.die() return hit.damage_cold(temp_reduc / 10) if (isliving(hit)) var/mob/living/L = hit L.bodytemperature -= temp_reduc L.TakeDamage("All", 3, 1, 0, 0) var/atom/targetTurf = 0 if (P.shooter) var/dir = get_dir(P.shooter, P.dir) targetTurf = get_edge_target_turf(hit, dir ? dir : P.dir) else targetTurf = get_edge_target_turf(hit, P.dir) SPAWN_DBG(0) L.changeStatus("weakened", 2 SECONDS) L.force_laydown_standup() L.throw_at(targetTurf, rand(5,7), rand(1,2), throw_type = THROW_GUNIMPACT) on_canpass(var/obj/projectile/P, atom/movable/passing_thing) if (P != passing_thing) if (istype(passing_thing, /obj/projectile)) var/obj/projectile/pass_proj = passing_thing return (istype(pass_proj.proj_data, src.type) || pass_proj.goes_through_walls) if (isitem(passing_thing)) var/obj/item/I = passing_thing if (I.throwing) return 0 .= 1 //place coffin. then, we travel to it in prjoectile form and it heals us while people can beat it //cofin is anchored, rises outta ground at spot /datum/projectile/special/spreader/tasershotgunspread //Used in Azungar's taser shotgun. name = "energy bolt" sname = "shotgun spread" shot_number = 0 cost = 37.5 power = 80 pellets_to_fire = 3 spread_projectile_type = /datum/projectile/energy_bolt/tasershotgun split_type = 0 shot_sound = 'sound/weapons/Taser.ogg' hit_mob_sound = 'sound/effects/sparks6.ogg' var/spread_angle = 30 var/current_angle = 0 var/angle_adjust_per_pellet = 0 var/initial_angle_offset_mult = 0 on_launch(var/obj/projectile/P) angle_adjust_per_pellet = ((spread_angle *3) / pellets_to_fire) current_angle = (0 - spread_angle) + (angle_adjust_per_pellet * initial_angle_offset_mult) ..() new_pellet(var/obj/projectile/P, var/turf/PT, var/datum/projectile/F) var/obj/projectile/FC = initialize_projectile(PT, F, P.xo, P.yo, P.shooter) FC.rotateDirection(current_angle) FC.launch() current_angle += angle_adjust_per_pellet