mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
putting some order in my guns
This commit is contained in:
@@ -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
|
||||
..()
|
||||
|
||||
@@ -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
53
code/modules/projectiles/guns/energy/gravitywell.dm
Normal file
53
code/modules/projectiles/guns/energy/gravitywell.dm
Normal 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"
|
||||
@@ -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
|
||||
|
||||
384
code/modules/projectiles/guns/hookshot.dm
Normal file
384
code/modules/projectiles/guns/hookshot.dm
Normal 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()
|
||||
..()
|
||||
94
code/modules/projectiles/guns/projectile/minigun.dm
Normal file
94
code/modules/projectiles/guns/projectile/minigun.dm
Normal 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)
|
||||
170
code/modules/projectiles/guns/projectile/osipr.dm
Normal file
170
code/modules/projectiles/guns/projectile/osipr.dm
Normal 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)
|
||||
@@ -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)
|
||||
|
||||
51
code/modules/projectiles/guns/projectile/sniper.dm
Normal file
51
code/modules/projectiles/guns/projectile/sniper.dm
Normal 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)
|
||||
251
code/modules/projectiles/guns/projectile/stickylauncher.dm
Normal file
251
code/modules/projectiles/guns/projectile/stickylauncher.dm
Normal 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
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
137
code/modules/projectiles/projectile/hookshot.dm
Normal file
137
code/modules/projectiles/projectile/hookshot.dm
Normal 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
|
||||
407
code/modules/projectiles/projectile/ricochet.dm
Normal file
407
code/modules/projectiles/projectile/ricochet.dm
Normal 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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user