putting some order in my guns

This commit is contained in:
DeityLink
2015-08-24 14:58:47 +02:00
parent 58bf419dbd
commit 0d550338d4
50 changed files with 3080 additions and 2750 deletions

View File

@@ -61,7 +61,6 @@
ammo_to_load = max_ammo
for(var/i = 1, i <= ammo_to_load, i++)
stored_ammo += new ammo_type(src)
update_icon()
/obj/item/ammo_storage/attackby(var/atom/A, var/mob/user) //now with loading
..()

View File

@@ -49,6 +49,14 @@
ammo_type = "/obj/item/ammo_casing/c45"
max_ammo = 30
/obj/item/ammo_storage/box/BMG50
name = "ammo box (.50 BMG)"
icon_state = "50BMG"
origin_tech = "combat=4"
ammo_type = "/obj/item/ammo_casing/BMG50"
max_ammo = 8
multiple_sprites = 1
/obj/item/ammo_storage/box/flare
name = "ammo box (flare shells)"
icon_state = "flarebox"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
/obj/item/weapon/gun/gravitywell
name = "\improper Gravity Well Gun"
desc = "Whoever created that gun had a taste for organized chaos..."
icon = 'icons/obj/gun_experimental.dmi'
icon_state = "gravitywell"
item_state = "gravitywell"
slot_flags = SLOT_BELT
origin_tech = "materials=7;bluespace=5;magnets=5"
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi')
recoil = 0
flags = FPRINT
w_class = 3.0
fire_delay = 0
fire_sound = 'sound/weapons/wave.ogg'
var/charge = 100
var/maxcharge = 100//admins can varedit this var to 0 to allow the gun to fire non-stop. I decline all responsibilities for lag-induced server crashes caused by gravity wells spam.
/obj/item/weapon/gun/gravitywell/examine(mob/user)
..()
user << "<span class='info'>Charge = [charge]%</span>"
/obj/item/weapon/gun/gravitywell/Destroy()
if(charge < maxcharge)
processing_objects.Remove(src)
..()
/obj/item/weapon/gun/gravitywell/process_chambered()
if(in_chamber) return 1
if(charge >= maxcharge)
charge = 0
update_icon()
in_chamber = new/obj/item/projectile/gravitywell()
processing_objects.Add(src)
return 1
return 0
/obj/item/weapon/gun/gravitywell/process()
charge = min(maxcharge,charge+1)
if(charge >= maxcharge)
update_icon()
if(istype(loc,/mob))
var/mob/M = loc
M.regenerate_icons()
processing_objects.Remove(src)
return 1
/obj/item/weapon/gun/gravitywell/update_icon()
if(charge == maxcharge)
icon_state = "gravitywell"
item_state = "gravitywell"
else
icon_state = "gravitywell0"
item_state = "gravitywell0"

View File

@@ -330,3 +330,179 @@ obj/item/weapon/gun/energy/staff/focus/attack_self(mob/living/user as mob)
power_supply.give(100)
update_icon()
return 1
/obj/item/weapon/gun/energy/ricochet
name = "ricochet rifle"
desc = "They say that these were originally designed for duck games. Not that there's any duck in this part of space."
icon = 'icons/obj/gun_experimental.dmi'
icon_state = "ricochet"
item_state = null
origin_tech = "materials=3;powerstorage=3;combat=3"
slot_flags = SLOT_BELT
projectile_type = "/obj/item/projectile/ricochet"
charge_cost = 100
cell_type = "/obj/item/weapon/cell"
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi')
/obj/item/weapon/gun/energy/bison
name = "\improper Righteous Bison"
desc = "A replica of Lord Cockswain's very own personnal ray gun."
icon = 'icons/obj/gun_experimental.dmi'
icon_state = "bison"
item_state = null
origin_tech = "materials=3;powerstorage=3;combat=3"
slot_flags = SLOT_BELT
projectile_type = "/obj/item/projectile/beam/bison"
charge_cost = 100
cell_type = "/obj/item/weapon/cell"
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi')
fire_delay = 8
fire_sound = 'sound/weapons/bison_fire.ogg'
var/pumping = 0
/obj/item/weapon/gun/energy/bison/New()
..()
power_supply.charge = 0
/obj/item/weapon/gun/energy/bison/attack_self(mob/user as mob)
if(pumping || !power_supply) return
pumping = 1
power_supply.charge = min(power_supply.charge + 200,power_supply.maxcharge)
if(power_supply.charge >= power_supply.maxcharge)
playsound(get_turf(src), 'sound/machines/click.ogg', 25, 1)
user << "<span class='rose'>You pull the pump at the back of the gun.Looks like the Inner battery is fully charged now.</span>"
else
playsound(get_turf(src), 'sound/weapons/bison_reload.ogg', 25, 1)
user << "<span class='rose'>You pull the pump at the back of the gun.</span>"
sleep(5)
pumping = 0
update_icon()
/obj/item/weapon/gun/energy/bison/update_icon()
if(power_supply.charge >= power_supply.maxcharge)
icon_state = "bison100"
else if (power_supply.charge > 0)
icon_state = "bison50"
else
icon_state = "bison0"
return
#define SPUR_FULL_POWER 4
#define SPUR_HIGH_POWER 3
#define SPUR_MEDIUM_POWER 2
#define SPUR_LOW_POWER 1
#define SPUR_NO_POWER 0
/obj/item/weapon/gun/energy/polarstar
name = "\improper Polar Star"
desc = "Despite being incomplete, the severe wear on this gun shows to which extent it's been used already."
icon = 'icons/obj/gun_experimental.dmi'
icon_state = "polarstar"
item_state = null
slot_flags = SLOT_BELT
fire_delay = 1
origin_tech = "materials=4;powerstorage=3;combat=3"
projectile_type = "/obj/item/projectile/spur/polarstar"
charge_cost = 100
cell_type = "/obj/item/weapon/cell"
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi')
recoil = 1
var/firelevel = SPUR_FULL_POWER
/obj/item/weapon/gun/energy/polarstar/New()
..()
playsound(get_turf(src), 'sound/weapons/spur_spawn.ogg', 50, 0, null, FALLOFF_SOUNDS, 0)
/obj/item/weapon/gun/energy/polarstar/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params, struggle = 0)
levelChange()
..()
/obj/item/weapon/gun/energy/polarstar/proc/levelChange()
var/maxlevel = power_supply.maxcharge
var/level = power_supply.charge
var/newlevel = 0
if(level == maxlevel)
newlevel = SPUR_FULL_POWER
else if(level >= ((maxlevel/3)*2))
newlevel = SPUR_HIGH_POWER
else if(level >= (maxlevel/3))
newlevel = SPUR_MEDIUM_POWER
else if(level >= charge_cost)
newlevel = SPUR_LOW_POWER
else
newlevel = SPUR_NO_POWER
if(firelevel >= newlevel)
firelevel = newlevel
set_firesound()
return
firelevel = newlevel
set_firesound()
var/levelupsound = null
switch(firelevel)
if(SPUR_LOW_POWER)
levelupsound = 'sound/weapons/spur_chargelow.ogg'
if(SPUR_MEDIUM_POWER)
levelupsound = 'sound/weapons/spur_chargemed.ogg'
if(SPUR_HIGH_POWER)
levelupsound = 'sound/weapons/spur_chargehigh.ogg'
if(SPUR_FULL_POWER)
levelupsound = 'sound/weapons/spur_chargefull.ogg'
if(levelupsound)
for(var/mob/M in get_turf(src))
M.playsound_local(M, levelupsound, 100, 0, null, FALLOFF_SOUNDS, 0)
spawn(1)
M.playsound_local(M, levelupsound, 75, 0, null, FALLOFF_SOUNDS, 0)
/obj/item/weapon/gun/energy/polarstar/proc/set_firesound()
switch(firelevel)
if(SPUR_HIGH_POWER,SPUR_FULL_POWER)
fire_sound = 'sound/weapons/spur_high.ogg'
recoil = 1
if(SPUR_MEDIUM_POWER)
fire_sound = 'sound/weapons/spur_medium.ogg'
recoil = 0
if(SPUR_LOW_POWER,SPUR_NO_POWER)
fire_sound = 'sound/weapons/spur_low.ogg'
recoil = 0
return
/obj/item/weapon/gun/energy/polarstar/update_icon()
return
/obj/item/weapon/gun/energy/polarstar/spur
name = "\improper Spur"
desc = "A masterpiece crafted by the legendary gunsmith of a far-away planet."
icon_state = "spur"
item_state = null
origin_tech = "materials=5;powerstorage=4;combat=5"
fire_delay = 0
projectile_type = "/obj/item/projectile/spur"
var/charge_tick = 0
/obj/item/weapon/gun/energy/polarstar/spur/New()
..()
processing_objects.Add(src)
/obj/item/weapon/gun/energy/polarstar/spur/Destroy()
processing_objects.Remove(src)
..()
/obj/item/weapon/gun/energy/polarstar/spur/process()
charge_tick++
if(charge_tick < 2) return 0
charge_tick = 0
if(!power_supply) return 0
power_supply.give(100)
levelChange()
return 1
#undef SPUR_FULL_POWER
#undef SPUR_HIGH_POWER
#undef SPUR_MEDIUM_POWER
#undef SPUR_LOW_POWER
#undef SPUR_NO_POWER

View File

@@ -0,0 +1,384 @@
/obj/item/weapon/gun/hookshot
name = "hookshot"
desc = "Used to create tethers! It's a very experimental device, recently developped by Nanotrasen."
icon = 'icons/obj/gun_experimental.dmi'
icon_state = "hookshot"
item_state = "hookshot"
slot_flags = SLOT_BELT
origin_tech = "materials=2;engineering=3;magnets=2"
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi')
recoil = 0
flags = FPRINT
w_class = 3.0
fire_delay = 0
fire_sound = 'sound/weapons/hookshot_fire.ogg'
var/maxlength = 14
var/obj/item/projectile/hookshot/hook = null
var/list/links = list()
var/datum/chain/chain_datum = null
var/rewinding = 0 //rewinding just means dragging the chain back into the gun.
var/clockwerk = 0 //clockwerk means "pulling yourself to the target".
var/mob/living/carbon/firer = null
var/atom/movable/extremity = null
/obj/item/weapon/gun/hookshot/update_icon()
if(hook || chain_datum)
icon_state = "hookshot0"
item_state = "hookshot0"
else
icon_state = "hookshot"
item_state = "hookshot"
if(istype(loc,/mob))
var/mob/M = loc
M.regenerate_icons()
/obj/item/weapon/gun/hookshot/New()
..()
for(var/i = 0;i <= maxlength; i++)
var/obj/effect/overlay/hookchain/HC = new(src)
links["[i]"] = HC
/obj/item/weapon/gun/hookshot/Destroy()
if(chain_datum)
chain_datum.Delete_Chain()
..()
/obj/item/weapon/gun/hookshot/attack_self(mob/user)
if(check_tether())
var/atom/movable/AM = chain_datum.extremity_B
if(AM)
AM.tether = null
chain_datum.extremity_B = null
chain_datum.rewind_chain()
/obj/item/weapon/gun/hookshot/process_chambered()
if(in_chamber)
return 1
if(!hook && !rewinding && !clockwerk && !check_tether())
hook = new/obj/item/projectile/hookshot(src)
in_chamber = hook
firer = loc
update_icon()
return 1
return 0
/obj/item/weapon/gun/hookshot/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params, struggle = 0)
if(flag) return //we're placing gun on a table or in backpack
if(check_tether())
if(istype(chain_datum.extremity_B,/mob/living/carbon))
var/mob/living/carbon/C = chain_datum.extremity_B
if(!(C.flags & INVULNERABLE) && (C.a_intent == I_HELP)) //players who don't see it coming (ie: are on Help intent) get briefly stunned and drop the items in their hands.
C.Weaken(1) //I guess that players on other intents than Help assume a more stable pose.
C.Stun(1)
C << "<span class='warning'>\The [src]'s pull makes you lose your balance and you fall as it drags you.</span>"
else
C << "<span class='warning'>\The [src] reels you in but you hold your balance.</span>"
chain_datum.rewind_chain()
return
..()
/obj/item/weapon/gun/hookshot/dropped(mob/user as mob)
if(user.tether)
var/datum/chain/tether_datum = user.tether.chain_datum
if(tether_datum == chain_datum)
spawn(1) //so we give time for the gun to be moved on the table or inside a container
if(isturf(loc)) //if we place the gun on the floor or a table, it becomes the new extremity of the chain
user.tether = null
chain_datum.extremity_A = src
var/obj/effect/overlay/chain/C = chain_datum.links["1"]
C.extremity_A = src
C.follow(src,get_step(loc,get_dir(loc,C)))
src.tether = C
else //else we simply rewind the chain
var/atom/movable/AM = chain_datum.extremity_B
if(AM)
AM.tether = null
chain_datum.extremity_B = null
chain_datum.rewind_chain()
..()
/obj/item/weapon/gun/hookshot/attack_hand(mob/user)
if(chain_datum && (chain_datum.extremity_A == src))
if(user.tether)
else
var/obj/effect/overlay/chain/C = src.tether
C.extremity_A = user
user.tether = C
chain_datum.extremity_A = user
C.follow(user,get_step(user,get_dir(user,C)))
src.tether = null
..()
/obj/item/weapon/gun/hookshot/proc/check_tether()
if(chain_datum && istype(loc,/mob/living))
var/mob/living/L = loc
if(L.tether)
var/datum/chain/tether_datum = L.tether.chain_datum
if(tether_datum == chain_datum)
return 1
return 0
/obj/item/weapon/gun/hookshot/proc/rewind_chain()
if(rewinding)
return
rewinding = 1
for(var/j = 1; j <= maxlength; j++)
for(var/i = maxlength; i > 0; i--)
var/obj/effect/overlay/hookchain/HC = links["[i]"]
if(HC.loc == src)
continue
var/obj/effect/overlay/hookchain/HC0 = links["[i-1]"]
HC.loc = HC0.loc
HC.pixel_x = HC0.pixel_x
HC.pixel_y = HC0.pixel_y
sleep(1)
rewinding = 0
update_icon()
/obj/item/weapon/gun/hookshot/proc/cancel_chain()
for(var/j = 1; j <= maxlength; j++)
var/obj/effect/overlay/hookchain/HC = links["[j]"]
HC.loc = src
rewinding = 0
clockwerk = 0
update_icon()
/obj/item/weapon/gun/hookshot/proc/clockwerk_chain(var/length)
if(clockwerk)
return
clockwerk = 1
for(var/i = 1;i <= length;i++)
var/obj/effect/overlay/hookchain/HC = links["[i]"]
if(!isturf(HC.loc) || (loc != firer))
cancel_chain()
break
var/bckp = firer.pass_flags
firer.pass_flags = PASSTABLE
firer.Move(HC.loc,get_dir(firer,HC.loc))
firer.pass_flags = bckp
HC.loc = src
sleep(1)
clockwerk = 0
update_icon()
/datum/chain
var/list/links = list()
var/atom/movable/extremity_A = null
var/atom/movable/extremity_B = null
var/obj/item/weapon/gun/hookshot/hookshot = null
var/undergoing_deletion = 0
var/snap = 0
var/rewinding = 0
/datum/chain/New()
spawn(20)
process()
/datum/chain/proc/process()
while(!undergoing_deletion)
if(!Check_Integrity())
snap = 1
Delete_Chain()
sleep(20)
/datum/chain/proc/Check_Integrity()
for(var/i = 1; i<= links.len ;i++)
var/obj/effect/overlay/chain/C = links["[i]"]
if(!C.rewinding && ((get_dist(C,C.extremity_A) > 1) || (get_dist(C,C.extremity_B) > 1)))
return 0
return 1
/datum/chain/proc/Delete_Chain()
if(undergoing_deletion)
return
undergoing_deletion = 1
if(extremity_A)
if(snap)
extremity_A.visible_message("The chain snaps and let go of \the [extremity_A]")
extremity_A.tether = null
if(extremity_B)
if(snap)
extremity_B.visible_message("The chain snaps and let go of \the [extremity_B]")
extremity_B.tether = null
for(var/i = 1; i<= links.len ;i++)
var/obj/effect/overlay/chain/C = links["[i]"]
qdel(C)
if(hookshot)
hookshot.chain_datum = null
hookshot.update_icon()
/datum/chain/proc/rewind_chain()
rewinding = 1
if(!extremity_A.tether)
Delete_Chain()
return
for(var/i = 1; i<= links.len ;i++)
var/obj/effect/overlay/chain/C1 = extremity_A.tether
if(!C1)
break
var/obj/effect/overlay/chain/C2 = C1.extremity_B
if(!C2)
break
if(istype(C2))
var/turf/T = C1.loc
C1.loc = extremity_A.loc
C2.follow(C1,T)
C2.extremity_A = extremity_A
C2.update_overlays(C1)
extremity_A.tether = C2
else if(extremity_B)
if(extremity_B.anchored)
extremity_B.tether = null
C1.extremity_B = null
extremity_B = null
else
var/turf/U = C1.loc
if(U && U.Enter(C2,C2.loc))
C2.loc = C1.loc
else
extremity_B.tether = null
extremity_B = null
C1.extremity_B = null
if(istype(extremity_A,/mob/living))
var/mob/living/L = extremity_A
C2.CtrlClick(L)
C1.rewinding = 1
qdel(C1)
sleep(1)
Delete_Chain()
/obj/effect/overlay/chain
name = "chain"
icon = 'icons/obj/chain.dmi'
icon_state = ""
animate_movement = 0
var/atom/movable/extremity_A = null
var/atom/movable/extremity_B = null
var/datum/chain/chain_datum = null
var/rewinding = 0
/obj/effect/overlay/chain/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
return 1
/obj/effect/overlay/chain/update_icon()
overlays.len = 0
if(extremity_A && (loc != extremity_A.loc))
overlays += image(icon,src,"chain",MOB_LAYER-0.1,get_dir(src,extremity_A))
if(extremity_B && (loc != extremity_B.loc))
overlays += image(icon,src,"chain",MOB_LAYER-0.1,get_dir(src,extremity_B))
/obj/effect/overlay/chain/proc/update_overlays(var/obj/effect/overlay/chain/C)
var/obj/effect/overlay/chain/C1 = extremity_A
var/obj/effect/overlay/chain/C2 = extremity_B
update_icon()
if(istype(C2) && ((!C && !istype(C1)) || ((C == C1) && istype(C1))))
C2.update_overlays(src)
else if(istype(C1) && ((!C && !istype(C2)) || ((C == C2) && istype(C2))))
C1.update_overlays(src)
/obj/effect/overlay/chain/attempt_to_follow(var/atom/movable/A,var/turf/T)
if(get_dist(T,loc) <= 1)
return 1
else
if(A == extremity_A)
return extremity_B.attempt_to_follow(src, A.loc)
else if(A == extremity_B)
return extremity_A.attempt_to_follow(src, A.loc)
/obj/effect/overlay/chain/Move(newLoc,Dir=0,step_x=0,step_y=0)//if someone pulls the chain
var/turf/T = loc
if(..())
var/obj/effect/overlay/chain/CA = extremity_A
var/obj/effect/overlay/chain/CB = extremity_B
if(istype(CA))
CA.follow(src,T)
CA.update_overlays(src)
else if(get_dist(loc,CA.loc) > 1)
CA.tether_pull = 1
CA.Move(T, get_dir(CA, T))
CA.tether_pull = 0
if(istype(CB))
CB.follow(src,T)
CB.update_overlays(src)
else if(get_dist(loc,CB.loc) > 1)
CB.tether_pull = 1
CB.Move(T, get_dir(CB, T))
CB.tether_pull = 0
if(!chain_datum.Check_Integrity())
chain_datum.snap = 1
chain_datum.Delete_Chain()
/obj/effect/overlay/chain/proc/follow(var/atom/movable/A,var/turf/T)
var/turf/U = get_turf(A)
if(!T || !loc || (T.z != loc.z))
chain_datum.Delete_Chain()
return
var/turf/R = loc
if(get_dist(U,loc) <= 1)
if(A == extremity_A)
var/obj/effect/overlay/chain/C = extremity_A
if(istype(C))
C.update_overlays(src)
else if(A == extremity_B)
var/obj/effect/overlay/chain/C = extremity_B
if(istype(C))
C.update_overlays(src)
update_icon()
return
forceMove(T, get_dir(src, T))
if(A == extremity_A)
var/obj/effect/overlay/chain/CH = extremity_B
if(istype(CH))
CH.follow(src,R)
else
if(!chain_datum.extremity_B)//for when we pull back the chain into the hookshot without pulling the other extremity
CH = null
extremity_B = null
var/obj/effect/overlay/chain/C = extremity_A
if(istype(C))
C.update_overlays(src)
if(CH && (get_dist(loc,CH.loc) > 1))
var/turf/oldLoc = CH.loc
CH.tether_pull = 1
var/pass_backup = CH.pass_flags
if(chain_datum.rewinding && (istype(CH,/mob/living) || istype(CH,/obj/item)))
CH.pass_flags = PASSTABLE//mobs can be pulled above tables
CH.Move(R, get_dir(CH, R))
CH.pass_flags = pass_backup
CH.tether_pull = 0
if(CH.loc == oldLoc)
CH.tether = null
extremity_B = null
chain_datum.extremity_B = null
update_icon()
else if(A == extremity_B)
var/obj/effect/overlay/chain/CH = extremity_A
if(istype(CH))
CH.follow(src,R)
else
var/obj/effect/overlay/chain/C = extremity_B
if(istype(C))
C.update_overlays(src)
if(CH && (get_dist(loc,CH.loc) > 1))
CH.tether_pull = 1
CH.Move(R, get_dir(CH, R))
CH.tether_pull = 0
update_icon()
/obj/effect/overlay/chain/Destroy()
if(chain_datum)
chain_datum.links -= src
if(!rewinding)
chain_datum.snap = 1
chain_datum.Delete_Chain()
..()

View File

@@ -0,0 +1,94 @@
/obj/item/weapon/gun/gatling
name = "gatling gun"
desc = "Ya-ta-ta-ta-ta-ta-ta-ta ya-ta-ta-ta-ta-ta-ta-ta do-de-da-va-da-da-dada! Kaboom-Kaboom!"
icon = 'icons/obj/gun_experimental.dmi'
icon_state = "minigun"
item_state = "minigun0"
origin_tech = "materials=4;combat=6"
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi')
recoil = 1
slot_flags = null
flags = FPRINT | TWOHANDABLE
w_class = 5.0//we be fuckin huge maaan
fire_delay = 0
fire_sound = 'sound/weapons/gatling_fire.ogg'
var/max_shells = 200
var/current_shells = 200
/obj/item/weapon/gun/gatling/examine(mob/user)
..()
user << "<span class='info'>Has [current_shells] round\s remaining.</span>"
/obj/item/weapon/gun/gatling/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params, struggle = 0)
if(flag) return //we're placing gun on a table or in backpack
if(harm_labeled >= min_harm_label)
user << "<span class='warning'>A label sticks the trigger to the trigger guard!</span>" //Such a new feature, the player might not know what's wrong if it doesn't tell them.
return
if(wielded)
Fire(A,user,params, "struggle" = struggle)
else
user << "<span class='warning'>You must dual-wield \the [src] before you can fire it!</span>"
/obj/item/weapon/gun/gatling/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0, struggle = 0)
..()
var/list/turf/possible_turfs = list()
for(var/turf/T in orange(target,1))
possible_turfs += T
spawn()
for(var/i = 1; i <= 3; i++)
sleep(1)
var/newturf = pick(possible_turfs)
..(newturf,user,params,reflex,struggle)
/obj/item/weapon/gun/gatling/update_wield(mob/user)
item_state = "minigun[wielded ? 1 : 0]"
if(wielded)
slowdown = 10
else
slowdown = 0
/obj/item/weapon/gun/gatling/process_chambered()
if(in_chamber) return 1
if(current_shells)
current_shells--
update_icon()
in_chamber = new/obj/item/projectile/bullet/gatling()//We create bullets as we are about to fire them. No other way to remove them from the gatling.
new/obj/item/ammo_casing_gatling(get_turf(src))
return 1
return 0
/obj/item/weapon/gun/gatling/update_icon()
switch(current_shells)
if(150 to INFINITY)
icon_state = "minigun100"
if(100 to 149)
icon_state = "minigun75"
if(50 to 99)
icon_state = "minigun50"
if(1 to 49)
icon_state = "minigun25"
else
icon_state = "minigun0"
/obj/item/weapon/gun/gatling/attack_self(mob/user)
if(wielded)
unwield(user)
else
wield(user)
/obj/item/ammo_casing_gatling
name = "large bullet casing"
desc = "An oversized bullet casing."
icon = 'icons/obj/ammo.dmi'
icon_state = "gatling-casing"
flags = FPRINT
siemens_coefficient = 1
throwforce = 1
w_class = 1.0
w_type = RECYK_METAL
/obj/item/ammo_casing_gatling/New()
..()
pixel_x = rand(-10.0, 10)
pixel_y = rand(-10.0, 10)
dir = pick(cardinal)

View File

@@ -0,0 +1,170 @@
#define OSIPR_MAX_CORES 3
#define OSIPR_PRIMARY_FIRE 1
#define OSIPR_SECONDARY_FIRE 2
/obj/item/weapon/gun/osipr
name = "\improper Overwatch Standard Issue Pulse Rifle"
desc = "Centuries ago those weapons striked fear in all of humanity when the Combine attacked the Earth. Nowadays these are just the best guns that the Syndicate can provide to its Elite Troops with its tight budget."
icon = 'icons/obj/gun_experimental.dmi'
icon_state = "osipr"
item_state = "osipr"
slot_flags = SLOT_BELT
origin_tech = "materials=5;combat=5;magnets=4;powerstorage=3"
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi')
recoil = 1
fire_delay = 0
w_class = 3.0
fire_sound = 'sound/weapons/osipr_fire.ogg'
var/obj/item/energy_magazine/osipr/magazine = null
var/energy_balls = 2
var/mode = OSIPR_PRIMARY_FIRE
/obj/item/weapon/gun/osipr/New()
..()
magazine = new(src)
/obj/item/weapon/gun/osipr/Destroy()
if(magazine)
qdel(magazine)
..()
/obj/item/weapon/gun/osipr/examine(mob/user)
..()
if(magazine)
user << "<span class='info'>Has [magazine.bullets] pulse bullet\s remaining.</span>"
else
user << "<span class='info'>It has no pulse magazine inserted!</span>"
user << "<span class='info'>Has [energy_balls] dark energy core\s remaining.</span>"
/obj/item/weapon/gun/osipr/process_chambered()
if(in_chamber) return 1
switch(mode)
if(OSIPR_PRIMARY_FIRE)
if(!magazine || !magazine.bullets) return 0
magazine.bullets--
update_icon()
in_chamber = new magazine.bullet_type()
return 1
if(OSIPR_SECONDARY_FIRE)
if(!energy_balls) return 0
energy_balls--
in_chamber = new/obj/item/projectile/energy/osipr()
return 1
return 0
/obj/item/weapon/gun/osipr/attackby(var/obj/item/A as obj, mob/user as mob)
if(istype(A, /obj/item/energy_magazine/osipr))
if(magazine)
user << "There is another magazine already inserted. Remove it first."
else
user.u_equip(A,1)
A.loc = src
magazine = A
update_icon()
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1)
user << "<span class='info'>You insert a new magazine.</span>"
user.regenerate_icons()
else if(istype(A, /obj/item/osipr_core))
if(energy_balls >= OSIPR_MAX_CORES)
user << "The OSIPR cannot receive any additional dark energy core."
else
user.u_equip(A,1)
qdel(A)
energy_balls++
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1)
user << "<span class='info'>You insert \the [A].</span>"
else
..()
/obj/item/weapon/gun/osipr/attack_hand(mob/user)
if(((src == user.r_hand) || (src == user.l_hand)) && magazine)
magazine.update_icon()
user.put_in_hands(magazine)
magazine = null
update_icon()
playsound(get_turf(src), 'sound/machines/click.ogg', 25, 1)
user << "<span class='info'>You remove the magazine.</span>"
user.regenerate_icons()
else
..()
/obj/item/weapon/gun/osipr/attack_self(mob/user)
switch(mode)
if(OSIPR_PRIMARY_FIRE)
mode = OSIPR_SECONDARY_FIRE
fire_sound = 'sound/weapons/osipr_altfire.ogg'
fire_delay = 20
user << "<span class='warning'>Now set to fire dark energy orbs.</span>"
if(OSIPR_SECONDARY_FIRE)
mode = OSIPR_PRIMARY_FIRE
fire_sound = 'sound/weapons/osipr_fire.ogg'
fire_delay = 0
user << "<span class='warning'>Now set to fire pulse bullets.</span>"
/obj/item/weapon/gun/osipr/update_icon()
if(!magazine)
icon_state = "osipr-empty"
item_state = "osipr-empty"
else
item_state = "osipr"
var/bullets = round(magazine.bullets/(magazine.max_bullets/10))
icon_state = "osipr[bullets]0"
/obj/item/energy_magazine
name = "energy magazine"
desc = "Can be replenished by a recharger"
icon = 'icons/obj/ammo.dmi'
icon_state = "osipr-magfull"
flags = FPRINT
force = 1
throwforce = 1
w_class = 3.0
var/bullets = 10
var/max_bullets = 10
var/caliber = "osipr" //base icon name
var/bullet_type = /obj/item/projectile/bullet/osipr
/obj/item/energy_magazine/New()
..()
pixel_x = rand(-10.0, 10)
pixel_y = rand(-10.0, 10)
update_icon()
/obj/item/energy_magazine/examine(mob/user)
..()
user << "<span class='info'>Has [bullets] bullet\s remaining.</span>"
/obj/item/energy_magazine/update_icon()
if(bullets == max_bullets)
icon_state = "[caliber]-magfull"
else
icon_state = "[caliber]-mag"
/obj/item/energy_magazine/osipr
name = "pulse magazine"
desc = "Primary ammo for OSIPR. Can be replenished by a recharger."
icon_state = "osipr-magfull"
w_class = 3.0
bullets = 30
max_bullets = 30
caliber = "osipr"
bullet_type = /obj/item/projectile/bullet/osipr
#undef OSIPR_PRIMARY_FIRE
#undef OSIPR_SECONDARY_FIRE
/obj/item/osipr_core
name = "dark energy core"
desc = "Secondary ammo for OSIPR."
icon = 'icons/obj/ammo.dmi'
icon_state = "osipr-core"
flags = FPRINT
force = 1
throwforce = 1
w_class = 3.0
/obj/item/osipr_core/New()
..()
pixel_x = rand(-10.0, 10)
pixel_y = rand(-10.0, 10)

View File

@@ -53,3 +53,68 @@
return(BRUTELOSS)
return
/obj/item/weapon/gun/projectile/rocketlauncher/nikita
name = "\improper Nikita"
desc = "A miniature cruise missile launcher. Using a pulsed rocket engine and sophisticated TV guidance system."
icon = 'icons/obj/gun_experimental.dmi'
icon_state = "nikita"
item_state = null
origin_tech = "materials=5;combat=6;programming=4"
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi')
recoil = 1
flags = FPRINT
slot_flags = SLOT_BACK
w_class = 4.0
fire_delay = 2
caliber = list("nikita" = 1)
origin_tech = null
fire_sound = 'sound/weapons/rocket.ogg'
ammo_type = "/obj/item/ammo_casing/rocket_rpg/nikita"
var/obj/item/projectile/nikita/fired = null
var/emagged = 0
/obj/item/weapon/gun/projectile/rocketlauncher/nikita/update_icon()
return
/obj/item/weapon/gun/projectile/rocketlauncher/nikita/attack_self(mob/user)
if(fired)
playsound(get_turf(src), 'sound/weapons/stickybomb_det.ogg', 30, 1)
fired.detonate()
/obj/item/weapon/gun/projectile/rocketlauncher/nikita/suicide_act(var/mob/user)
if(!loaded)
user.visible_message("<span class='danger'>[user] jams down \the [src]'s trigger before noticing it isn't loaded and starts bashing \his head in with it! It looks like \he's trying to commit suicide.</span>")
return(BRUTELOSS)
else
user.visible_message("<span class='danger'>[user] fiddles with \the [src]'s safeties and suddenly aims it at \his feet! It looks like \he's trying to commit suicide.</span>")
spawn(10) //RUN YOU IDIOT, RUN
explosion(src.loc, -1, 1, 4, 8)
return(BRUTELOSS)
return
/obj/item/weapon/gun/projectile/rocketlauncher/nikita/attackby(var/obj/item/A as obj, mob/user as mob)
if(istype(A, /obj/item/weapon/card/emag) && !emagged)
emagged = 1
user << "<span class='warning'>You disable \the [src]'s idiot security!</span>"
else
..()
/obj/item/weapon/gun/projectile/rocketlauncher/nikita/process_chambered()
if(..())
if(!emagged)
fired = in_chamber
return 1
return 0
/obj/item/ammo_casing/rocket_rpg/nikita
name = "\improper Nikita missile"
desc = "A miniature cruise missile"
icon = 'icons/obj/ammo.dmi'
icon_state = "nikita"
caliber = "nikita"
projectile_type = "/obj/item/projectile/nikita"
/obj/item/ammo_casing/rocket_rpg/nikita/New()
..()
pixel_x = rand(-10.0, 10)
pixel_y = rand(-10.0, 10)

View File

@@ -0,0 +1,51 @@
/obj/item/weapon/gun/projectile/hecate
name = "\improper PGM H<>cate II"
desc = "An Anti-Materiel Rifle. You can read \"Fabriqu<71> en Haute-Savoie\" on the receiver. Whatever that means..."
icon = 'icons/obj/gun_experimental.dmi'
icon_state = "hecate"
item_state = null
origin_tech = "materials=5;combat=6"
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi')
recoil = 2
slot_flags = SLOT_BACK
fire_delay = 30
w_class = 4.0
fire_sound = 'sound/weapons/hecate_fire.ogg'
caliber = list(".50BMG" = 1)
ammo_type = "/obj/item/ammo_casing/BMG50"
max_shells = 1
load_method = 0
var/backup_view = 7
/obj/item/weapon/gun/projectile/hecate/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params, struggle = 0)
if(flag) return //we're placing gun on a table or in backpack
if(harm_labeled >= min_harm_label)
user << "<span class='warning'>A label sticks the trigger to the trigger guard!</span>" //Such a new feature, the player might not know what's wrong if it doesn't tell them.
return
if(wielded)
Fire(A,user,params, "struggle" = struggle)
else
user << "<span class='warning'>You must dual-wield \the [src] before you can fire it!</span>"
/obj/item/weapon/gun/projectile/hecate/update_wield(mob/user)
if(wielded)
slowdown = 10
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_64x64.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_64x64.dmi')
if(user && user.client)
user.regenerate_icons()
var/client/C = user.client
backup_view = C.view
C.view = C.view * 2
else
slowdown = 0
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi')
if(user && user.client)
user.regenerate_icons()
var/client/C = user.client
C.view = backup_view
/obj/item/weapon/gun/projectile/hecate/attack_self(mob/user)
if(wielded)
unwield(user)
else
wield(user)

View File

@@ -0,0 +1,251 @@
#define MAX_STICKYBOMBS 4
/obj/item/weapon/gun/stickybomb
name = "stickybomb launcher"
desc = "Fired stickybombs take 5 seconds to become live. After which they'll progressively merge with their surroundings."
icon = 'icons/obj/gun_experimental.dmi'
icon_state = "stickybomb"
item_state = null
slot_flags = SLOT_BELT
origin_tech = "materials=3;combat=4;programming=3"
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns_experimental.dmi', "right_hand" = 'icons/mob/in-hand/right/guns_experimental.dmi')
recoil = 1
flags = FPRINT
w_class = 3.0
fire_delay = 2
fire_sound = 'sound/weapons/grenadelauncher.ogg'
var/list/loaded = list()
var/list/fired = list()
var/current_shells = 200
/obj/item/weapon/gun/stickybomb/New()
..()
loaded = list(
new /obj/item/stickybomb(src),
new /obj/item/stickybomb(src),
new /obj/item/stickybomb(src),
new /obj/item/stickybomb(src),
new /obj/item/stickybomb(src),
new /obj/item/stickybomb(src),
)
/obj/item/weapon/gun/stickybomb/Destroy()
for(var/obj/item/stickybomb/S in loaded)
qdel(S)
loaded = null
for(var/obj/item/stickybomb/B in fired)
B.deactivate()
B.unstick()
..()
/obj/item/weapon/gun/stickybomb/examine(mob/user)
..()
user << "<span class='info'>Has [loaded.len] stickybomb\s loaded, and [fired.len] stickybomb\s placed.</span>"
/obj/item/weapon/gun/stickybomb/update_icon()
return
/obj/item/weapon/gun/stickybomb/attack_self(mob/user)
if(fired.len)
playsound(get_turf(src), 'sound/weapons/stickybomb_det.ogg', 30, 1)
for(var/obj/item/stickybomb/B in fired)
spawn()
if(B.live)
B.detonate()
/obj/item/weapon/gun/stickybomb/attackby(var/obj/item/A as obj, mob/user as mob)
if(istype(A, /obj/item/stickybomb))
var/obj/item/stickybomb/B = A
if(B.live)
user << "<span class='warning'>You cannot load a live stickybomb!</span>"
else
if(loaded.len >= 6)
user << "<span class='warning'>You cannot fit any more stickybombs in there!</span>"
else
user.drop_item(A, src)
user << "<span class='notice'>You load \the [A] into \the [src].</span>"
loaded += A
else
..()
/obj/item/weapon/gun/stickybomb/process_chambered()
if(in_chamber) return 1
if(loaded.len)
var/obj/item/stickybomb/B = pick(loaded)
loaded -= B
if(fired.len >= MAX_STICKYBOMBS)
var/obj/item/stickybomb/SB = pick(fired)
spawn()
SB.detonate()
if(ismob(loc))
loc << "<span class='warning'>One of the stickybombs detonates to leave room for the next one.</span>"
fired += B
var/obj/item/projectile/stickybomb/SB = new()
SB.sticky = B
B.fired_from = src
B.loc = SB
in_chamber = SB
return 1
return 0
/obj/item/stickybomb
name = "anti-personnel stickybomb"
desc = "Ammo for a stickybomb launcher. Only affects living beings, produces a decent amount of knockback."
icon = 'icons/obj/ammo.dmi'
icon_state = "stickybomb"
flags = FPRINT
force = 1
throwforce = 1
w_class = 1.0
var/obj/item/weapon/gun/stickybomb/fired_from = null
var/live = 0
var/atom/stuck_to = null
var/image/self_overlay = null
var/signal = 0
/obj/item/stickybomb/New()
..()
pixel_x = rand(-10.0, 10)
pixel_y = rand(-10.0, 10)
/obj/item/stickybomb/Destroy()
if(fired_from)
fired_from.fired -= src
fired_from = null
stuck_to = null
self_overlay = null
..()
/obj/item/stickybomb/update_icon()
icon_state = "[initial(icon_state)][live ? "-live" : ""]"
if(live)
desc = "It appears to be live."
else
desc = "Ammo for a stickybomb launcher."
/obj/item/stickybomb/pickup(mob/user)
if(stuck_to)
user << "<span class='warning'>You reach for \the [src] stuck on \the [stuck_to] and start pulling.</span>"
if(do_after(user, src, 30))
user << "<span class='warning'>It came off!</span>"
unstick()
..()
else
..()
/obj/item/stickybomb/proc/stick_to(var/atom/A as mob|obj|turf, var/side = null)
stuck_to = A
loc = A
pixel_x = rand(-10, 10)
pixel_y = rand(-10, 10)
playsound(A, 'sound/items/metal_impact.ogg', 30, 1)
if(isturf(A))
anchored = 1
switch(side)
if(NORTH)
pixel_y = 16
if(SOUTH)
pixel_y = -16
if(EAST)
pixel_x = 16
if(WEST)
pixel_x = -16
sleep(50)
if(stuck_to == A)
flick("stickybomb_flick",src)
live = 1
update_icon()
animate(src, alpha=50, time=300)
else if(isliving(A))
visible_message("<span class='warning'>\the [src] sticks itself on \the [A].</span>")
src.loc = A
self_overlay = new(icon,src,icon_state,10,dir)
self_overlay.pixel_x = pixel_x
self_overlay.pixel_y = pixel_y
A.overlays += self_overlay
sleep(50)
if(stuck_to == A)
live = 1
A.overlays -= self_overlay
self_overlay.icon_state = "stickybomb-live"
A.overlays += self_overlay
/obj/item/stickybomb/proc/unstick(var/fall_to_floor = 1)
if(ismob(stuck_to))
stuck_to.overlays -= self_overlay
icon_state = self_overlay.icon_state
if(fall_to_floor)
src.loc = get_turf(src)
stuck_to = null
anchored = 0
alpha = 255
pixel_x = 0
pixel_y = 0
/obj/item/stickybomb/proc/detonate()
icon_state = "stickybomb_flick"
if(!self_overlay)
self_overlay = new(icon,src,icon_state,13,dir)
overlays += self_overlay//a bit awkward but the sprite wouldn't properly animate otherwise
if(signal)
return
signal = 1
mouse_opacity = 0
var/turf/T = get_turf(src)
playsound(T, 'sound/machines/twobeep.ogg', 30, 1)
if(ismob(stuck_to))
stuck_to.overlays -= self_overlay
self_overlay.icon_state = "stickybomb_flick"
self_overlay.layer = 13
stuck_to.overlays += self_overlay
alpha = 255
spawn(3)
if(ismob(stuck_to))
stuck_to.overlays -= self_overlay
T.turf_animation('icons/effects/96x96.dmi',"explosion_sticky",pixel_x-32, pixel_y-32, 13)
playsound(T, "explosion_small", 75, 1)
for(var/mob/living/L in range(T,3))
var/turf/TL = get_turf(L)
var/dist = get_dist(T,L)
var/atom/throw_target = T
if(T!=TL)
throw_target = get_edge_target_turf(T, get_dir(T,TL))
switch(dist)
if(0 to 1)
L.ex_act(3)//ex_act(2) would deal too much damage
L.ex_act(3)
spawn(1)//to give time for the other bombs to calculate their damage.
L.throw_at(throw_target, 2, 3)
if(1 to 2)
L.ex_act(3,TRUE)
spawn(1)
L.throw_at(throw_target, 1, 1)
if(2 to 3)
L.ex_act(3,TRUE)
qdel(src)
/obj/item/stickybomb/proc/deactivate()
live = 0
if(fired_from)
fired_from.fired -= src
fired_from = null
update_icon()
alpha = 255
unstick()
/obj/item/stickybomb/emp_act(severity)
deactivate()
unstick()
/obj/item/stickybomb/bullet_act(var/obj/item/projectile/Proj)
if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet)||istype(Proj,/obj/item/projectile/ricochet))
if(!istype(Proj ,/obj/item/projectile/beam/lastertag) && !istype(Proj ,/obj/item/projectile/beam/practice) )
detonate()
#undef MAX_STICKYBOMBS

View File

@@ -529,3 +529,247 @@ var/list/beam_master = list()
if((istype(M.wear_suit, /obj/item/clothing/suit/bluetag))||(istype(M.wear_suit, /obj/item/clothing/suit/redtag)))
M.Weaken(5)
return 1
/obj/item/projectile/beam/bison
name = "heat ray"
damage_type = BURN
flag = "laser"
kill_count = 100
layer = 13
damage = 15
icon = 'icons/obj/lightning.dmi'
icon_state = "heatray"
animate_movement = 0
linear_movement = 0
pass_flags = PASSTABLE
var/drawn = 0
var/tang = 0
var/turf/last = null
/obj/item/projectile/beam/bison/proc/adjustAngle(angle)
angle = round(angle) + 45
if(angle > 180)
angle -= 180
else
angle += 180
if(!angle)
angle = 1
/*if(angle < 0)
//angle = (round(abs(get_angle(A, user))) + 45) - 90
angle = round(angle) + 45 + 180
else
angle = round(angle) + 45*/
return angle
/obj/item/projectile/beam/bison/process()
//calculating the turfs that we go through
var/lastposition = loc
target = get_turf(original)
dist_x = abs(target.x - src.x)
dist_y = abs(target.y - src.y)
if (target.x > src.x)
dx = EAST
else
dx = WEST
if (target.y > src.y)
dy = NORTH
else
dy = SOUTH
if(dist_x > dist_y)
error = dist_x/2 - dist_y
spawn while(src && src.loc)
// only stop when we've hit something, or hit the end of the map
if(error < 0)
var/atom/step = get_step(src, dy)
if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
break
src.Move(step)
error += dist_x
else
var/atom/step = get_step(src, dx)
if(!step)
break
src.Move(step)
error -= dist_y
if(isnull(loc))
draw_ray(lastposition)
return
if(lastposition == loc)
kill_count = 0
lastposition = loc
if(kill_count < 1)
//del(src)
draw_ray(lastposition)
returnToPool(src)
return
kill_count--
if(!bumped && !isturf(original))
if(loc == target)
if(!(original in permutated))
draw_ray(target)
Bump(original)
else
error = dist_y/2 - dist_x
spawn while(src && src.loc)
// only stop when we've hit something, or hit the end of the map
if(error < 0)
var/atom/step = get_step(src, dx)
if(!step)
break
src.Move(step)
error += dist_y
else
var/atom/step = get_step(src, dy)
if(!step)
break
src.Move(step)
error -= dist_x
if(isnull(loc))
draw_ray(lastposition)
return
if(lastposition == loc)
kill_count = 0
lastposition = loc
if(kill_count < 1)
//del(src)
draw_ray(lastposition)
returnToPool(src)
return
kill_count--
if(!bumped && !isturf(original))
if(loc == get_turf(original))
if(!(original in permutated))
draw_ray(target)
Bump(original)
return
/obj/item/projectile/beam/bison/bullet_die()
draw_ray(loc)
..()
/obj/item/projectile/beam/bison/proc/draw_ray(var/turf/lastloc)
if(drawn) return
drawn = 1
var/atom/curr = lastloc
var/Angle=round(Get_Angle(firer,curr))
var/icon/I=new('icons/obj/lightning.dmi',icon_state)
var/icon/Istart=new('icons/obj/lightning.dmi',"[icon_state]start")
var/icon/Iend=new('icons/obj/lightning.dmi',"[icon_state]end")
I.Turn(Angle+45)
Istart.Turn(Angle+45)
Iend.Turn(Angle+45)
var/DX=(32*curr.x+curr.pixel_x)-(32*firer.x+firer.pixel_x)
var/DY=(32*curr.y+curr.pixel_y)-(32*firer.y+firer.pixel_y)
var/N=0
var/length=round(sqrt((DX)**2+(DY)**2))
var/count = 0
var/turf/T = get_turf(firer)
var/timer_total = 16
var/increment = timer_total/round(length/32)
var/current_timer = 5
for(N,N<(length+16),N+=32)
if(count >= kill_count)
break
count++
var/obj/effect/overlay/beam/X=getFromPool(/obj/effect/overlay/beam,T,current_timer,1)
X.BeamSource=src
current_timer += increment
if((N+64>(length+16)) && (N+32<=(length+16)))
X.icon=Iend
else if(N==0)
X.icon=Istart
else if(N+32>(length+16))
X.icon=null
else
X.icon=I
var/Pixel_x=round(sin(Angle)+32*sin(Angle)*(N+16)/32)
var/Pixel_y=round(cos(Angle)+32*cos(Angle)*(N+16)/32)
if(DX==0) Pixel_x=0
if(DY==0) Pixel_y=0
if(Pixel_x>32)
for(var/a=0, a<=Pixel_x,a+=32)
X.x++
Pixel_x-=32
if(Pixel_x<-32)
for(var/a=0, a>=Pixel_x,a-=32)
X.x--
Pixel_x+=32
if(Pixel_y>32)
for(var/a=0, a<=Pixel_y,a+=32)
X.y++
Pixel_y-=32
if(Pixel_y<-32)
for(var/a=0, a>=Pixel_y,a-=32)
X.y--
Pixel_y+=32
//Now that we've calculated the total offset in pixels, we move each beam parts to their closest corresponding turfs
var/x_increm = 0
var/y_increm = 0
while(Pixel_x >= 32 || Pixel_x <= -32)
if(Pixel_x > 0)
Pixel_x -= 32
x_increm++
else
Pixel_x += 32
x_increm--
while(Pixel_y >= 32 || Pixel_y <= -32)
if(Pixel_y > 0)
Pixel_y -= 32
y_increm++
else
Pixel_y += 32
y_increm--
X.x += x_increm
X.y += y_increm
X.pixel_x=Pixel_x
X.pixel_y=Pixel_y
var/turf/TT = get_turf(X.loc)
if(TT == firer.loc)
continue
return
/obj/item/projectile/beam/bison/Bump(atom/A as mob|obj|turf|area)
//Heat Rays go through mobs
if(A == firer)
loc = A.loc
return 0 //cannot shoot yourself
if(firer && istype(A, /mob/living))
var/mob/living/M = A
A.bullet_act(src, def_zone)
loc = A.loc
permutated.Add(A)
visible_message("<span class='warning'>[A.name] is hit by the [src.name] in the [parse_zone(def_zone)]!</span>")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter
if(istype(firer, /mob))
log_attack("<font color='red'>[key_name(firer)] shot [key_name(M)] with a [type]</font>")
M.attack_log += "\[[time_stamp()]\] <b>[key_name(firer)]</b> shot <b>[key_name(M)]</b> with a <b>[type]</b>"
firer.attack_log += "\[[time_stamp()]\] <b>[key_name(firer)]</b> shot <b>[key_name(M)]</b> with a <b>[type]</b>"
msg_admin_attack("[key_name(firer)] shot [key_name(M)] with a [type] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)") //BS12 EDIT ALG
if(!iscarbon(firer))
M.LAssailant = null
else
M.LAssailant = firer
else
M.attack_log += "\[[time_stamp()]\] <b>UNKNOWN/(no longer exists)</b> shot <b>[key_name(M)]</b> with a <b>[type]</b>"
msg_admin_attack("UNKNOWN/(no longer exists) shot [key_name(M)] with a [type] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)") //BS12 EDIT ALG
log_attack("<font color='red'>UNKNOWN/(no longer exists) shot [key_name(M)] with a [type]</font>")
return 1
else
return ..()

View File

@@ -86,4 +86,176 @@
stutter = 10
/obj/item/projectile/bullet/a762
damage = 25
damage = 25
#define SPUR_FULL_POWER 4
#define SPUR_HIGH_POWER 3
#define SPUR_MEDIUM_POWER 2
#define SPUR_LOW_POWER 1
#define SPUR_NO_POWER 0
/obj/item/projectile/spur
name = "spur bullet"
damage_type = BRUTE
flag = "bullet"
kill_count = 100
layer = 13
damage = 40
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "spur_high"
animate_movement = 2
custom_impact = 1
linear_movement = 0
/obj/item/projectile/spur/OnFired()
..()
var/obj/item/weapon/gun/energy/polarstar/quote = shot_from
switch(quote.firelevel)
if(SPUR_FULL_POWER,SPUR_HIGH_POWER)
icon_state = "spur_high"
damage = 40
kill_count = 20
if(SPUR_MEDIUM_POWER)
icon_state = "spur_medium"
damage = 30
kill_count = 13
if(SPUR_LOW_POWER,SPUR_NO_POWER)
icon_state = "spur_low"
damage = 20
kill_count = 7
/obj/item/projectile/spur/polarstar
name = "polar star bullet"
damage = 20
/obj/item/projectile/spur/polarstar/OnFired()
..()
var/obj/item/weapon/gun/energy/polarstar/quote = shot_from
switch(quote.firelevel)
if(SPUR_FULL_POWER,SPUR_HIGH_POWER)
icon_state = "spur_high"
damage = 20
kill_count = 20
if(SPUR_MEDIUM_POWER)
icon_state = "spur_medium"
damage = 15
kill_count = 13
if(SPUR_LOW_POWER,SPUR_NO_POWER)
icon_state = "spur_low"
damage = 10
kill_count = 7
/obj/item/projectile/spur/Bump(atom/A as mob|obj|turf|area)
if(loc)
var/turf/T = loc
var/impact_icon = null
var/impact_sound = null
var/PixelX = 0
var/PixelY = 0
switch(get_dir(src,A))
if(NORTH)
PixelY = 16
if(SOUTH)
PixelY = -16
if(EAST)
PixelX = 16
if(WEST)
PixelX = -16
if(ismob(A))
impact_icon = "spur_3"
impact_sound = 'sound/weapons/spur_hitmob.ogg'
else
impact_icon = "spur_1"
impact_sound = 'sound/weapons/spur_hitwall.ogg'
var/image/impact = image('icons/obj/projectiles_impacts.dmi',loc,impact_icon)
impact.pixel_x = PixelX
impact.pixel_y = PixelY
impact.layer = 13
T.overlays += impact
spawn(3)
T.overlays -= impact
playsound(impact, impact_sound, 30, 1)
if(istype(A, /turf/unsimulated/mineral))
var/turf/unsimulated/mineral/M = A
M.GetDrilled()
if(istype(A, /obj/structure/boulder))
returnToPool(A)
return ..()
/obj/item/projectile/spur/process_step()
if(kill_count <= 0)
if(loc)
var/turf/T = loc
var/image/impact = image('icons/obj/projectiles_impacts.dmi',loc,"spur_2")
impact.layer = 13
T.overlays += impact
spawn(3)
T.overlays -= impact
..()
#undef SPUR_FULL_POWER
#undef SPUR_HIGH_POWER
#undef SPUR_MEDIUM_POWER
#undef SPUR_LOW_POWER
#undef SPUR_NO_POWER
/obj/item/projectile/bullet/gatling
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "minigun"
damage = 30
/obj/item/projectile/bullet/osipr
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "osipr"
damage = 50
stun = 2
weaken = 2
destroy = 1
bounce_type = PROJREACT_WALLS|PROJREACT_WINDOWS
bounces = 1
/obj/item/projectile/bullet/hecate
name = "high penetration bullet"
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "hecate"
damage = 101//you're going to crit, lad
kill_count = 255//oh boy, we're crossing through the entire Z level!
stun = 5
weaken = 5
stutter = 5
phase_type = PROJREACT_WALLS|PROJREACT_WINDOWS|PROJREACT_OBJS|PROJREACT_MOBS|PROJREACT_MOBS|PROJREACT_BLOB
penetration = 20//can hit 3 mobs at once, or go through a wall and hit 2 more mobs, or go through an rwall/blast door and hit 1 mob
var/superspeed = 1
/obj/item/projectile/bullet/hecate/OnFired()
..()
for (var/mob/M in player_list)
if(M && M.client)
var/turf/M_turf = get_turf(M)
if(M_turf && (M_turf.z == starting.z))
M.playsound_local(starting, 'sound/weapons/hecate_fire_far.ogg', 25, 1)
for (var/mob/living/carbon/human/H in range(src,1))
if(!H.earprot())
H.Weaken(2)
H.Stun(2)
H.ear_damage += rand(3, 5)
H.ear_deaf = max(H.ear_deaf,15)
H << "<span class='warning'>Your ears ring!</span>"
/obj/item/projectile/bullet/hecate/bresenham_step(var/distA, var/distB, var/dA, var/dB)
if(..())
if(superspeed)
superspeed = 0
return 1
else
superspeed = 1
return 0
else
return 0

View File

@@ -121,4 +121,28 @@
/obj/item/projectile/energy/megabuster
name = "buster pellet"
icon_state = "megabuster"
nodamage = 1
nodamage = 1
/obj/item/projectile/energy/osipr
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "dark"
kill_count = 100
damage = 50
stun = 10
weaken = 10
stutter = 10
jittery = 30
destroy = 0
bounce_sound = 'sound/weapons/osipr_altbounce.ogg'
bounce_type = PROJREACT_WALLS|PROJREACT_WINDOWS
bounces = -1
phase_type = PROJREACT_OBJS|PROJREACT_MOBS
penetration = -1
/obj/item/projectile/energy/osipr/Destroy()
var/turf/T = loc
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(4, 0, T)
s.start()
T.turf_animation('icons/obj/projectiles_impacts.dmi',"dark_explosion",0, 0, 13, 'sound/weapons/osipr_altexplosion.ogg')
..()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,137 @@
/obj/item/projectile/hookshot
name = "hookshot"
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "hookshot"
damage = 0
nodamage = 1
var/length = 1
kill_count = 15
var/obj/effect/overlay/hookchain/last_link = null
/obj/item/projectile/hookshot/process_step()
var/sleeptime = 1
if(src.loc)
if(kill_count < 1)
var/obj/item/weapon/gun/hookshot/hookshot = shot_from
if(src.z != firer.z)
hookshot.cancel_chain()
bullet_die()
spawn()
hookshot.rewind_chain()
bullet_die()
if(dist_x > dist_y)
sleeptime = bresenham_step(dist_x,dist_y,dx,dy)
else
sleeptime = bresenham_step(dist_y,dist_x,dy,dx)
if(linear_movement)
update_pixel()
pixel_x = PixelX
pixel_y = PixelY
bumped = 0
if(sleeptime)
var/obj/item/weapon/gun/hookshot/hookshot = shot_from
var/obj/effect/overlay/hookchain/HC = hookshot.links["[length]"]
HC.loc = loc
HC.pixel_x = pixel_x
HC.pixel_y = pixel_y
if(last_link)
last_link.icon = bullet_master["hookshot_chain_angle[target_angle]"]
last_link = HC
length++
if(length < hookshot.maxlength)
if(!("hookshot_chain_angle[target_angle]" in bullet_master))
var/icon/I = new('icons/obj/projectiles_experimental.dmi',"hookshot_chain")
I.Turn(target_angle+45)
bullet_master["hookshot_chain_angle[target_angle]"] = I
var/icon/J = new('icons/obj/projectiles_experimental.dmi',"hookshot_pixel")
J.Turn(target_angle+45)
bullet_master["hookshot_head_angle[target_angle]"] = J
HC.icon = bullet_master["hookshot_head_angle[target_angle]"]
else
if(!("hookshot_head_angle[target_angle]" in bullet_master))
var/icon/I = new('icons/obj/projectiles_experimental.dmi',"hookshot_pixel")
I.Turn(target_angle+45)
bullet_master["hookshot_head_angle[target_angle]"] = I
HC.icon = bullet_master["hookshot_head_angle[target_angle]"]
spawn()
hookshot.rewind_chain()
bullet_die()
sleep(sleeptime)
/obj/item/projectile/hookshot/bullet_die()
var/obj/item/weapon/gun/hookshot/hookshot = shot_from
hookshot.hook = null
spawn()
OnDeath()
returnToPool(src)
/obj/item/projectile/hookshot/Bump(atom/A as mob|obj|turf|area)
if(bumped) return 0
bumped = 1
var/obj/item/weapon/gun/hookshot/hookshot = shot_from
spawn()
if(isturf(A)) //if we hit a wall or an anchored atom, we pull ourselves to it
hookshot.clockwerk_chain(length)
else if(istype(A,/atom/movable))
var/atom/movable/AM = A
if(AM.anchored)
hookshot.clockwerk_chain(length)
else if(!AM.tether && !firer.tether && !istype(AM,/obj/effect/)) //if we hit something that we can pull, let's tether ourselves to it
if(length <= 2) //unless we hit it at melee range, then let's just start pulling it
AM.CtrlClick(firer)
hookshot.cancel_chain()
bullet_die()
return
var/datum/chain/chain_datum = new()
hookshot.chain_datum = chain_datum
chain_datum.hookshot = hookshot
chain_datum.extremity_A = firer
chain_datum.extremity_B = AM
var/max_chains = length-1
for(var/i = 1; i < max_chains; i++) //first we create tether links on every turf that has one of the projectile's chain parts.
var/obj/effect/overlay/hookchain/HC = hookshot.links["[i]"]
if(!HC.loc || (HC.loc == hookshot))
max_chains = i
break
var/obj/effect/overlay/chain/C = new(HC.loc)
C.chain_datum = chain_datum
chain_datum.links["[i]"] = C
for(var/i = 1; i < max_chains; i++) //then we link them together
var/obj/effect/overlay/chain/C = chain_datum.links["[i]"]
if(i == 1)
firer.tether = C
C.extremity_A = firer
if(max_chains <= 2)
C.extremity_B = AM
C.update_overlays()
else
C.extremity_B = chain_datum.links["[i+1]"]
else if(i == (max_chains-1))
C.extremity_A = chain_datum.links["[i-1]"]
C.extremity_B = AM
AM.tether = C
C.update_overlays() //once we've placed and linked all the tether's links, we update their sprites
else
C.extremity_A = chain_datum.links["[i-1]"]
C.extremity_B = chain_datum.links["[i+1]"]
hookshot.cancel_chain() //then we remove the chain laid by the projectile
else
hookshot.rewind_chain()
else
hookshot.rewind_chain() //hit something that we can neither pull ourselves to nor drag to us? Just retract the chain.
bullet_die()
/obj/effect/overlay/hookchain
name = "hookshot"
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "hookshot_chain"
animate_movement = 0

View File

@@ -0,0 +1,407 @@
// RICOCHET SHOT
//A projectile that mones only in diagonal, bounces off walls and opaque doors, goes through everything else.
/obj/item/projectile/ricochet
name = "ricochet shot"
damage_type = BURN
flag = "laser"
kill_count = 100
layer = 13
damage = 30
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "ricochet_head"
animate_movement = 0
linear_movement = 0
custom_impact = 1
var/pos_from = EAST //which side of the turf is the shot coming from
var/pos_to = SOUTH //which side of the turf is the shot heading to
var/bouncin = 0
//list of objects that'll stop the shot, and apply bullet_act
var/list/obj/ricochet_bump = list(
/obj/effect/blob,
/obj/machinery/turret,
/obj/machinery/turretcover,
/obj/mecha,
/obj/structure/reagent_dispensers/fueltank,
/obj/structure/bed/chair/vehicle,
)
/obj/item/projectile/ricochet/OnFired() //The direction and position of the projectile when it spawns depends heavily on where the player clicks.
var/turf/T1 = get_turf(shot_from) //From a single turf, a player can fire the ricochet rifle in 8 different directions.
var/turf/T2 = get_turf(original)
shot_from.update_icon()
var/X = T2.x - T1.x
var/Y = T2.y - T1.y
var/X_spawn = 0
var/Y_spawn = 0
if(X>0)
if(Y>0)
if(X>Y)
pos_from = WEST
pos_to = NORTH
X_spawn = 1
else if(X<Y)
pos_from = SOUTH
pos_to = EAST
Y_spawn = 1
else
if(prob(50))
pos_from = WEST
pos_to = NORTH
X_spawn = 1
else
pos_from = SOUTH
pos_to = EAST
Y_spawn = 1
else if(Y<0)
if(X>(Y*-1))
pos_from = WEST
pos_to = SOUTH
X_spawn = 1
else if(X<(Y*-1))
pos_from = NORTH
pos_to = EAST
Y_spawn = -1
else
if(prob(50))
pos_from = WEST
pos_to = SOUTH
X_spawn = 1
else
pos_from = NORTH
pos_to = EAST
Y_spawn = -1
else if(Y==0)
pos_from = WEST
X_spawn = 1
if(prob(50))
pos_to = NORTH
else
pos_to = SOUTH
else if(X<0)
if(Y>0)
if((X*-1)>Y)
pos_from = EAST
pos_to = NORTH
X_spawn = -1
else if((X*-1)<Y)
pos_from = SOUTH
pos_to = WEST
Y_spawn = 1
else
if(prob(50))
pos_from = EAST
pos_to = NORTH
X_spawn = -1
else
pos_from = SOUTH
pos_to = WEST
Y_spawn = 1
else if(Y<0)
if((X*-1)>(Y*-1))
pos_from = EAST
pos_to = SOUTH
X_spawn = -1
else if((X*-1)<(Y*-1))
pos_from = NORTH
pos_to = WEST
Y_spawn = -1
else
if(prob(50))
pos_from = EAST
pos_to = SOUTH
X_spawn = -1
else
pos_from = NORTH
pos_to = WEST
Y_spawn = -1
else if(Y==0)
pos_from = EAST
X_spawn = -1
if(prob(50))
pos_to = NORTH
else
pos_to = SOUTH
else if(X==0)
if(Y>0)
Y_spawn = 1
pos_from = SOUTH
if(prob(50))
pos_to = EAST
else
pos_to = WEST
else if(Y<0)
Y_spawn = -1
pos_from = NORTH
if(prob(50))
pos_to = EAST
else
pos_to = WEST
else
OnDeath()
loc = null
returnToPool(src)
return
var/turf/newspawn = locate(T1.x + X_spawn, T1.y + Y_spawn, z)
src.loc = newspawn
update_icon()
..()
/obj/item/projectile/ricochet/update_icon()//8 possible combinations
switch(pos_to)
if(NORTH)
if(pos_from == WEST)
dir = NORTHWEST
else
dir = EAST
if(SOUTH)
if(pos_from == WEST)
dir = WEST
else
dir = SOUTHEAST
if(EAST)
if(pos_from == NORTH)
dir = NORTHEAST
else
dir = SOUTH
if(WEST)
if(pos_from == NORTH)
dir = NORTH
else
dir = SOUTHWEST
/obj/item/projectile/ricochet/proc/bounce()
bouncin = 1
var/obj/structure/ricochet_bump/bump = new(loc)
bump.dir = pos_to
playsound(get_turf(src), 'sound/items/metal_impact.ogg', 50, 1)
switch(pos_to)
if(NORTH)
if(pos_from == WEST)
pos_to = EAST
else
pos_to = WEST
pos_from = NORTH
if(SOUTH)
if(pos_from == WEST)
pos_to = EAST
else
pos_to = WEST
pos_from = SOUTH
if(EAST)
if(pos_from == NORTH)
pos_to = SOUTH
else
pos_to = NORTH
pos_from = EAST
if(WEST)
if(pos_from == NORTH)
pos_to = SOUTH
else
pos_to = NORTH
pos_from = WEST
/obj/item/projectile/ricochet/proc/bulletdies(var/atom/A = null)
var/obj/effect/overlay/beam/impact = getFromPool(/obj/effect/overlay/beam,get_turf(src),10,0,'icons/obj/projectiles_impacts.dmi')
if(A)
switch(get_dir(src,A))
if(NORTH)
impact.pixel_y = 16
if(SOUTH)
impact.pixel_y = -16
if(EAST)
impact.pixel_x = 16
if(WEST)
impact.pixel_x = -16
impact.icon_state = "ricochet_hit"
playsound(impact, 'sound/weapons/pierce.ogg', 30, 1)
spawn()
density = 0
invisibility = 101
returnToPool(src)
OnDeath()
/obj/item/projectile/ricochet/proc/admin_warn(mob/living/M)
if(istype(firer, /mob))
if(firer == M)
log_attack("<font color='red'>[key_name(firer)] shot himself with a [type].</font>")
M.attack_log += "\[[time_stamp()]\] <b>[key_name(firer)]</b> shot himself with a <b>[type]</b>"
firer.attack_log += "\[[time_stamp()]\] <b>[key_name(firer)]</b> shot himself with a <b>[type]</b>"
msg_admin_attack("[key_name(firer)] shot himself with a [type], [pick("top kek!","for shame.","he definitely meant to do that","probably not the last time either.")] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)")
if(!iscarbon(firer))
M.LAssailant = null
else
M.LAssailant = firer
else
log_attack("<font color='red'>[key_name(firer)] shot [key_name(M)] with a [type]</font>")
M.attack_log += "\[[time_stamp()]\] <b>[key_name(firer)]</b> shot <b>[key_name(M)]</b> with a <b>[type]</b>"
firer.attack_log += "\[[time_stamp()]\] <b>[key_name(firer)]</b> shot <b>[key_name(M)]</b> with a <b>[type]</b>"
msg_admin_attack("[key_name(firer)] shot [key_name(M)] with a [type] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)")
if(!iscarbon(firer))
M.LAssailant = null
else
M.LAssailant = firer
else
M.attack_log += "\[[time_stamp()]\] <b>UNKNOWN/(no longer exists)</b> shot <b>UNKNOWN/(no longer exists)</b> with a <b>[type]</b>"
msg_admin_attack("UNKNOWN/(no longer exists) shot UNKNOWN/(no longer exists) with a [type]. Wait what the fuck? (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)")
log_attack("<font color='red'>UNKNOWN/(no longer exists) shot UNKNOWN/(no longer exists) with a [type]</font>")
/obj/item/projectile/ricochet/Bump(atom/A as mob|obj|turf|area)
if(bumped) return 0
bumped = 1
if(A)
if(istype(A,/turf/) || (istype(A,/obj/machinery/door/) && A.opacity))
bounce()
else if(istype(A,/mob/living))//ricochet shots "never miss"
if(istype(A,/mob/living/carbon/human))
var/mob/living/carbon/human/H = A
if(istype(H.wear_suit,/obj/item/clothing/suit/armor/laserproof))// bwoing!!
visible_message("<span class='warning'>\the [src.name] bounces off \the [A.name]'s [H.wear_suit]!</span>")
bounce()
else
visible_message("<span class='warning'>\the [A.name] is hit by \the [src.name] in the [parse_zone(def_zone)]!</span>")
A.bullet_act(src, def_zone)
admin_warn(A)
bulletdies(A)
else
visible_message("<span class='warning'>\the [A.name] is hit by \the [src.name] in the [parse_zone(def_zone)]!</span>")
A.bullet_act(src, def_zone)
admin_warn(A)
bulletdies(A)
else if(is_type_in_list(A,ricochet_bump))//beware fuel tanks!
visible_message("<span class='warning'>\the [A.name] is hit by \the [src.name]!</span>")
A.bullet_act(src)
bulletdies(A)
else if((istype(A,/obj/structure/window) || istype(A,/obj/machinery/door/window) || istype(A,/obj/machinery/door/firedoor/border_only)) && (A.loc == src.loc))
//all this part is to prevent a bug that causes the shot to go through walls
//if they are one the same tile as a one-directional window/windoor and try to cross them
var/turf/T = get_step(src, pos_to)
if(T.density)
bounce()
else
ricochet_jump()
else
ricochet_jump()
/obj/item/projectile/ricochet/process_step()//unlike laser guns the projectile isn't instantaneous, but it still travels twice as fast as kinetic bullets since it moves twices per ticks
if(src.loc)
if(kill_count < 1)
bulletdies()
kill_count--
for(var/i=1;i<=2;i++)
ricochet_movement()
update_icon()
sleep(1)
/obj/item/projectile/ricochet/proc/ricochet_step(var/phase=1)
var/obj/structure/ricochet_trail/trail = new(loc)
switch(pos_to)
if(NORTH)
if(pos_from == WEST)
trail.dir = NORTH
else
trail.dir = EAST
if(SOUTH)
if(pos_from == WEST)
trail.dir = WEST
else
trail.dir = SOUTH
if(EAST)
if(pos_from == NORTH)
trail.dir = EAST
else
trail.dir = SOUTH
if(WEST)
if(pos_from == NORTH)
trail.dir = NORTH
else
trail.dir = WEST
if(phase)
current = get_step(src, pos_to)
step_towards(src, current)
else
var/turf/T = get_step(src, pos_to)
loc = T
if((bumped && !phase) || bouncin)
return
switch(pos_to)
if(NORTH)
if(pos_from == WEST)
pos_to = EAST
else
pos_to = WEST
pos_from = SOUTH
if(SOUTH)
if(pos_from == WEST)
pos_to = EAST
else
pos_to = WEST
pos_from = NORTH
if(EAST)
if(pos_from == NORTH)
pos_to = SOUTH
else
pos_to = NORTH
pos_from = WEST
if(WEST)
if(pos_from == NORTH)
pos_to = SOUTH
else
pos_to = NORTH
pos_from = EAST
/obj/item/projectile/ricochet/proc/ricochet_movement()//movement through empty space
if((x == 1 || x == world.maxx || y == 1 || y == world.maxy))
bulletdies()
return
ricochet_step()
bumped = 0
bouncin = 0
/obj/item/projectile/ricochet/proc/ricochet_jump()//movement through dense objects
if((x == 1 || x == world.maxx || y == 1 || y == world.maxy))
bulletdies()
return
ricochet_step(0)
/obj/structure/ricochet_trail //so pretty
name = "ricochet shot"
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "ricochet"
opacity = 0
density = 0
unacidable = 1
anchored = 1
layer = 12
/obj/structure/ricochet_trail/New()
. = ..()
spawn(30)
qdel(src)
/obj/structure/ricochet_bump //oh so pretty
name = "ricochet shot"
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "ricochet_bounce"
opacity = 0
density = 0
unacidable = 1
anchored = 1
layer = 14
/obj/structure/ricochet_bump/New()
. = ..()
spawn(30)
qdel(src)

View File

@@ -27,3 +27,140 @@
/obj/item/projectile/rocket/Bump(var/atom/rocket)
explosion(rocket, -1, 1, 4, 8)
qdel(src)
/obj/item/projectile/nikita
name = "\improper Nikita missile"
desc = "One does not simply dodge a nikita missile."
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "nikita"
damage = 50
stun = 5
weaken = 5
damage_type = BRUTE
nodamage = 0
flag = "bullet"
animate_movement = 2
linear_movement = 0
kill_count = 100
layer = 13
var/mob/living/carbon/mob = null
var/obj/item/weapon/gun/projectile/rocketlauncher/nikita/nikita = null
var/steps_since_last_turn = 0
var/last_dir = null
var/emagged = 0//the value is set by the Nikita when it fires it
/obj/item/projectile/nikita/OnFired()
nikita = shot_from
emagged = nikita.emagged
if(nikita && istype(nikita.loc,/mob/living/carbon))
var/mob/living/carbon/C = nikita.loc
if(C.get_active_hand() == nikita)
mob = C
mob.client.perspective = EYE_PERSPECTIVE
mob.client.eye = src
mob.orient_object = src
mob.canmove = 0
dir = get_dir_cardinal(starting,original)
last_dir = dir
if(mob && emagged)
for(var/obj/item/W in mob.get_all_slots())
mob.drop_from_inventory(W)//were you're going you won't need those!
/obj/item/projectile/nikita/emp_act(severity)
new/obj/item/ammo_casing/rocket_rpg/nikita(get_turf(src))
if(nikita)
nikita.fired = null
qdel(src)
/obj/item/projectile/nikita/bullet_act(var/obj/item/projectile/Proj)
if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet)||istype(Proj,/obj/item/projectile/ricochet))
if(!istype(Proj ,/obj/item/projectile/beam/lastertag) && !istype(Proj ,/obj/item/projectile/beam/practice) )
detonate()
/obj/item/projectile/nikita/Destroy()
reset_view()
if(nikita)
nikita.fired = null
..()
/obj/item/projectile/nikita/Bump(var/atom/A)
if(bumped)
return
if(emagged && (A == mob))
return
bumped = 1
detonate(get_turf(A))
/obj/item/projectile/nikita/Bumped(var/atom/A)
if(emagged && (A == mob))
return
detonate()
/obj/item/projectile/nikita/process_step()
if(!emagged && !check_user())//if the original user dropped the Nikita and the missile is still in the air, we check if someone picked it up.
if(nikita && istype(nikita.loc,/mob/living/carbon))
var/mob/living/carbon/C = nikita.loc
if(C.get_active_hand() == nikita)
mob = C
mob.client.perspective = EYE_PERSPECTIVE
mob.client.eye = src
mob.orient_object = src
mob.canmove = 0
if(src.loc)
var/atom/step = get_step(src, dir)
if(!step)
qdel(src)
src.Move(step)
if(mob)
if(emagged)
mob.loc = loc
mob.dir = dir
else
mob.dir = get_dir(mob,src)
if(!emagged)
kill_count--
if(!kill_count)
detonate()
if(kill_count == (initial(kill_count)/5))
mob.playsound_local(mob, 'sound/machines/twobeep.ogg', 30, 1)
mob << "<span class='warning'>WARNING: 20% fuel left on missile before self-detonation.<span>"
if(dir != last_dir)
last_dir = dir
steps_since_last_turn = 0
var/sleeptime = max(1,(steps_since_last_turn * -1) + 5)//5, 4, 3, 2, 1, 1, 1, 1, 1,...
steps_since_last_turn++
sleep(sleeptime)
/obj/item/projectile/nikita/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
return (!density || !height || air_group)
/obj/item/projectile/nikita/proc/check_user()
if(!mob || !mob.client)
return 0
if(mob.stat || (mob.get_active_hand() != src))
reset_view()
return 0
return 1
/obj/item/projectile/nikita/proc/detonate(var/explosion = loc)
explosion(explosion, -1, 1, 4, 8)
if(src)
qdel(src)
/obj/item/projectile/nikita/proc/reset_view()
if(mob && mob.client)
mob.client.eye = mob.client.mob
mob.client.perspective = MOB_PERSPECTIVE
mob.orient_object = null
mob.canmove = 1
mob = null

View File

@@ -8,9 +8,9 @@
flag = "energy"
on_hit(var/atom/target, var/blocked = 0)
empulse(target, 1, 1)
return 1
/obj/item/projectile/ion/on_hit(var/atom/target, var/blocked = 0)
empulse(target, 1, 1)
return 1
/obj/item/projectile/bullet/gyro
@@ -20,9 +20,9 @@
flag = "bullet"
on_hit(var/atom/target, var/blocked = 0)
explosion(target, -1, 0, 2)
return 1
/obj/item/projectile/bullet/gyro/on_hit(var/atom/target, var/blocked = 0)
explosion(target, -1, 0, 2)
return 1
/obj/item/projectile/temp
name = "freeze beam"
@@ -35,54 +35,54 @@
var/temperature = 300
var/obj/item/weapon/gun/energy/temperature/T = null
OnFired()
T = shot_from
temperature = T.temperature
switch(temperature)
if(501 to INFINITY)
name = "searing beam" //if emagged
icon_state = "temp_8"
if(400 to 500)
name = "burning beam" //temp at which mobs start taking HEAT_DAMAGE_LEVEL_2
icon_state = "temp_7"
if(360 to 400)
name = "hot beam" //temp at which mobs start taking HEAT_DAMAGE_LEVEL_1
icon_state = "temp_6"
if(335 to 360)
name = "warm beam" //temp at which players get notified of their high body temp
icon_state = "temp_5"
if(295 to 335)
name = "ambient beam"
icon_state = "temp_4"
if(260 to 295)
name = "cool beam" //temp at which players get notified of their low body temp
icon_state = "temp_3"
if(200 to 260)
name = "cold beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_1
icon_state = "temp_2"
if(120 to 260)
name = "ice beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_2
icon_state = "temp_1"
if(-INFINITY to 120)
name = "freeze beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_3
icon_state = "temp_0"
else
name = "temperature beam"//failsafe
icon_state = "temp_4"
/obj/item/projectile/temp/OnFired()
T = shot_from
temperature = T.temperature
switch(temperature)
if(501 to INFINITY)
name = "searing beam" //if emagged
icon_state = "temp_8"
if(400 to 500)
name = "burning beam" //temp at which mobs start taking HEAT_DAMAGE_LEVEL_2
icon_state = "temp_7"
if(360 to 400)
name = "hot beam" //temp at which mobs start taking HEAT_DAMAGE_LEVEL_1
icon_state = "temp_6"
if(335 to 360)
name = "warm beam" //temp at which players get notified of their high body temp
icon_state = "temp_5"
if(295 to 335)
name = "ambient beam"
icon_state = "temp_4"
if(260 to 295)
name = "cool beam" //temp at which players get notified of their low body temp
icon_state = "temp_3"
if(200 to 260)
name = "cold beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_1
icon_state = "temp_2"
if(120 to 260)
name = "ice beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_2
icon_state = "temp_1"
if(-INFINITY to 120)
name = "freeze beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_3
icon_state = "temp_0"
else
name = "temperature beam"//failsafe
icon_state = "temp_4"
on_hit(var/atom/target, var/blocked = 0)//These two could likely check temp protection on the mob
if(istype(target, /mob/living))
var/mob/living/M = target
if(M.flags & INVULNERABLE)
return 0
M.bodytemperature = temperature
if(temperature > 500)//emagged
M.adjust_fire_stacks(0.5)
M.on_fire = 1
M.update_icon = 1
playsound(M.loc, 'sound/effects/bamf.ogg', 50, 0)
return 1
/obj/item/projectile/temp/on_hit(var/atom/target, var/blocked = 0)//These two could likely check temp protection on the mob
if(istype(target, /mob/living))
var/mob/living/M = target
if(M.flags & INVULNERABLE)
return 0
M.bodytemperature = temperature
if(temperature > 500)//emagged
M.adjust_fire_stacks(0.5)
M.on_fire = 1
M.update_icon = 1
playsound(M.loc, 'sound/effects/bamf.ogg', 50, 0)
return 1
//This shouldn't fucking exist, just spawn a meteor damnit
/obj/item/projectile/meteor
@@ -117,37 +117,37 @@
nodamage = 1
flag = "energy"
on_hit(var/atom/target, var/blocked = 0)
var/mob/living/M = target
// if(ishuman(target) && M.dna && M.dna.mutantrace == "plant") //Plantmen possibly get mutated and damaged by the rays.
if(ishuman(target))
var/mob/living/carbon/human/H = M
if((H.species.flags & IS_PLANT) && (M.nutrition < 500))
if(prob(15))
M.apply_effect((rand(30,80)),IRRADIATE)
M.Weaken(5)
for (var/mob/V in viewers(src))
V.show_message("<span class='warning'>[M] writhes in pain as \his vacuoles boil.</span>", 3, "<span class='warning'>You hear the crunching of leaves.</span>", 2)
if(prob(35))
// for (var/mob/V in viewers(src)) //Public messages commented out to prevent possible metaish genetics experimentation and stuff. - Cheridan
// V.show_message("<span class='warning'>[M] is mutated by the radiation beam.</span>", 3, "<span class='warning'>You hear the snapping of twigs.</span>", 2)
if(prob(80))
randmutb(M)
domutcheck(M,null)
else
randmutg(M)
domutcheck(M,null)
/obj/item/projectile/energy/floramut/on_hit(var/atom/target, var/blocked = 0)
var/mob/living/M = target
// if(ishuman(target) && M.dna && M.dna.mutantrace == "plant") //Plantmen possibly get mutated and damaged by the rays.
if(ishuman(target))
var/mob/living/carbon/human/H = M
if((H.species.flags & IS_PLANT) && (M.nutrition < 500))
if(prob(15))
M.apply_effect((rand(30,80)),IRRADIATE)
M.Weaken(5)
for (var/mob/V in viewers(src))
V.show_message("<span class='warning'>[M] writhes in pain as \his vacuoles boil.</span>", 3, "<span class='warning'>You hear the crunching of leaves.</span>", 2)
if(prob(35))
// for (var/mob/V in viewers(src)) //Public messages commented out to prevent possible metaish genetics experimentation and stuff. - Cheridan
// V.show_message("<span class='warning'>[M] is mutated by the radiation beam.</span>", 3, "<span class='warning'>You hear the snapping of twigs.</span>", 2)
if(prob(80))
randmutb(M)
domutcheck(M,null)
else
M.adjustFireLoss(rand(5,15))
M.show_message("<span class='warning'>The radiation beam singes you!</span>")
// for (var/mob/V in viewers(src))
// V.show_message("<span class='warning'>[M] is singed by the radiation beam.</span>", 3, "<span class='warning'>You hear the crackle of burning leaves.</span>", 2)
else if(istype(target, /mob/living/carbon/))
// for (var/mob/V in viewers(src))
// V.show_message("The radiation beam dissipates harmlessly through [M]", 3)
M.show_message("<span class='notice'>The radiation beam dissipates harmlessly through your body.</span>")
else
return 1
randmutg(M)
domutcheck(M,null)
else
M.adjustFireLoss(rand(5,15))
M.show_message("<span class='warning'>The radiation beam singes you!</span>")
// for (var/mob/V in viewers(src))
// V.show_message("<span class='warning'>[M] is singed by the radiation beam.</span>", 3, "<span class='warning'>You hear the crackle of burning leaves.</span>", 2)
else if(istype(target, /mob/living/carbon/))
// for (var/mob/V in viewers(src))
// V.show_message("The radiation beam dissipates harmlessly through [M]", 3)
M.show_message("<span class='notice'>The radiation beam dissipates harmlessly through your body.</span>")
else
return 1
/obj/item/projectile/energy/florayield
name = "beta somatoray"
@@ -157,27 +157,27 @@
nodamage = 1
flag = "energy"
on_hit(var/atom/target, var/blocked = 0)
var/mob/M = target
// if(ishuman(target) && M.dna && M.dna.mutantrace == "plant") //These rays make plantmen fat.
if(ishuman(target)) //These rays make plantmen fat.
var/mob/living/carbon/human/H = M
if((H.species.flags & IS_PLANT) && (M.nutrition < 500))
M.nutrition += 30
else if (istype(target, /mob/living/carbon/))
M.show_message("<span class='notice'>The radiation beam dissipates harmlessly through your body.</span>")
else
return 1
/obj/item/projectile/energy/florayield/on_hit(var/atom/target, var/blocked = 0)
var/mob/M = target
// if(ishuman(target) && M.dna && M.dna.mutantrace == "plant") //These rays make plantmen fat.
if(ishuman(target)) //These rays make plantmen fat.
var/mob/living/carbon/human/H = M
if((H.species.flags & IS_PLANT) && (M.nutrition < 500))
M.nutrition += 30
else if (istype(target, /mob/living/carbon/))
M.show_message("<span class='notice'>The radiation beam dissipates harmlessly through your body.</span>")
else
return 1
/obj/item/projectile/beam/mindflayer
name = "flayer ray"
on_hit(var/atom/target, var/blocked = 0)
if(ishuman(target))
var/mob/living/carbon/human/M = target
M.adjustBrainLoss(20)
M.hallucination += 20
/obj/item/projectile/beam/mindflayer/on_hit(var/atom/target, var/blocked = 0)
if(ishuman(target))
var/mob/living/carbon/human/M = target
M.adjustBrainLoss(20)
M.hallucination += 20
/obj/item/projectile/kinetic
name = "kinetic force"
@@ -250,4 +250,195 @@ obj/item/projectile/kinetic/New()
/obj/item/effect/kinetic_blast/New()
..()
spawn(4)
returnToPool(src)
returnToPool(src)
/obj/item/projectile/stickybomb
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "stickybomb"
damage = 0
var/obj/item/stickybomb/sticky = null
/obj/item/projectile/stickybomb/Bump(atom/A as mob|obj|turf|area)
if(bumped) return 0
bumped = 1
if(A)
density = 0
invisibility = 101
kill_count = 0
if(isliving(A))
sticky.stick_to(A)
else if(loc)
var/turf/T = get_turf(src)
sticky.stick_to(T,get_dir(src,A))
bullet_die()
/obj/item/projectile/stickybomb/bump_original_check()//so players can aim at floors
if(!bumped)
if(loc == get_turf(original))
if(!(original in permutated))
Bump(original)
/obj/item/projectile/gravitywell
name = "gravity impulse"
icon = 'icons/obj/projectiles_experimental.dmi'
icon_state = "gravitywell"
damage = 0
nodamage = 1
phase_type = PROJREACT_WALLS|PROJREACT_WINDOWS|PROJREACT_OBJS|PROJREACT_MOBS|PROJREACT_MOBS|PROJREACT_BLOB
penetration = -1
/obj/item/projectile/gravitywell/bresenham_step(var/distA, var/distB, var/dA, var/dB)
if(..())
return 2
else
return 0
/obj/item/projectile/gravitywell/Bump(atom/A as mob|obj|turf|area)
if(loc == target)
spawnGravityWell()
if(isliving(A))
var/mob/living/M = A
M.Weaken(5)
forceMove(get_step(loc,dir))
if(loc == target)
spawnGravityWell()
/obj/item/projectile/gravitywell/proc/spawnGravityWell()
kill_count = 0
log_admin("\[[time_stamp()]\] <b>[key_name(firer)]</b> has created a gravity well at ([loc.x],[loc.y],[loc.z])")
message_admins("\[[time_stamp()]\] <b>[key_name(firer)]</b> has created a gravity well at (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[loc.x];Y=[loc.y];Z=[loc.z]'>([loc.x],[loc.y],[loc.z])</a>)", 1)
new/obj/effect/overlay/gravitywell(loc)
bullet_die()
/obj/item/projectile/gravitywell/bump_original_check()//so players can aim at floors
if(!bumped)
if(loc == get_turf(original))
if(!(original in permutated))
Bump(original)
/obj/effect/overlay/gravitywell
name = "gravity well"
icon = 'icons/effects/160x160.dmi'
icon_state = "gravitywell_shadow"
pixel_x = -64
pixel_y = -64
unacidable = 1
density = 0
layer = 2.1
anchored = 1
alpha = 255
mouse_opacity = 0
var/size = 2
var/xp = 6
var/xlevel = 4
var/obj/effect/overlay/gravitygrid/GG = null
/obj/effect/overlay/gravitywell/New()
..()
GG = new(loc)
playsound(loc, 'sound/weapons/emp.ogg', 75, 1)
animate(GG, alpha = 255, time = 10, easing = SINE_EASING)
spawn()
Pulse()
overlays += image(icon,"gravitywell_shadow",2.1)
/obj/effect/overlay/gravitywell/Destroy()
if(GG)
qdel(GG)
..()
/obj/effect/overlay/gravitywell/proc/Pulse()
xp--
if(xp <= 0)
xp = 6
xlevel--
if(xlevel <= -4)
empulse(loc,size,size+2)
if(locate(/obj/machinery/the_singularitygen/) in loc)
new/obj/machinery/singularity(loc)//How evil can one man be?
qdel(src)
return
else if(xlevel > 0)
size++
if(GG)
GG.LevelUp()
src.transform *= (size*2+1)/((size-1)*2+1)
var/outter_size = round(size+1)
for(var/atom/A in range(src,outter_size))
var/dist = get_dist_euclidian(src,A)
var/pull_force = size/max(1,round(dist))
if(istype(A,/atom/movable) && (size >= 4) && (get_dist(src,A) <= 1))
A.singularity_pull(src, (pull_force * 3), 1)
var/atom/movable/AM = A
AM.forceMove(loc)//KATAMARI DAMACYYyyYYyyYY
else
if(dist <= size)
A.singularity_pull(src, (pull_force * 3), 1)
if(istype(A,/mob/living))
var/mob/living/M = A
M.take_overall_damage(5,0)
M << "<span class='warning'>The [src]'s tidal force rips your skin!</span>"
for(var/mob/living/L in loc)//standing right in the center of the gravity well means double damage
if((L.stat == DEAD) && prob(5))
L.gib()
L.take_overall_damage(3,0)//less brute damage in the center, but the radiations caused by singularity_pull make up for it.
L << "<span class='danger'>The [src]'s tidal force is crushing you!</span>"
sleep(10)
Pulse()
/obj/effect/overlay/gravitygrid
name = "gravity well"
icon = 'icons/effects/160x160.dmi'
icon_state = "gravitywell_white"
pixel_x = -64
pixel_y = -64
unacidable = 1
density = 0
layer = 30
anchored = 1
color = "green"
alpha = 0
mouse_opacity = 0
var/obj/effect/overlay/gravitygrid/GG = null
var/size = 5
/obj/effect/overlay/gravitygrid/Destroy()
if(GG)
qdel(GG)//NO RE
..()
/obj/effect/overlay/gravitygrid/proc/LevelUp()
if(!GG)
GG = new(loc)
GG.layer = layer-1
GG.size = size+2
GG.alpha = 255
GG.transform *= size/5
var/matrix/M = matrix()
M.Scale((size/5)*(GG.size/size),(size/5)*(GG.size/size))
animate(GG, transform = M, time = 10)
else
GG.LevelUp()
var/newcolor = null
switch(color)
if("#00c000")
newcolor = "#ffa500"
if("#ffa500")
newcolor = "#ff0000"
else
newcolor = "#800080"
animate(src, color = newcolor, time = 10)