Merge pull request #1031 from Citadel-Station-13/upstream-merge-27234
[MIRROR] [READY]Peacekeeper cyborg projectile dampening fields, attempt three
This commit is contained in:
@@ -504,6 +504,113 @@
|
||||
S.change_head_color(color2)
|
||||
dropped = TRUE
|
||||
|
||||
//Peacekeeper Cyborg Projectile Dampenening Field
|
||||
/obj/item/borg/projectile_dampen
|
||||
name = "Hyperkinetic Dampening projector"
|
||||
desc = "A device that projects a dampening field that weakens kinetic energy above a certain threshold. <span class='boldnotice'>Projects a field that drains power per second \
|
||||
while active, that will weaken and slow damaging projectiles inside its field.</span> Still being a prototype, it tends to induce a charge on ungrounded metallic surfaces."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "shield"
|
||||
var/maxenergy = 1500
|
||||
var/energy = 1500
|
||||
var/energy_recharge = 7.5
|
||||
var/energy_recharge_cyborg_drain_coefficient = 0.4
|
||||
var/cyborg_cell_critical_percentage = 0.05
|
||||
var/mob/living/silicon/robot/host = null
|
||||
var/datum/proximity_monitor/advanced/dampening_field
|
||||
var/projectile_damage_coefficient = 0.5
|
||||
var/projectile_damage_tick_ecost_coefficient = 2 //Lasers get half their damage chopped off, drains 50 power/tick. Note that fields are processed 5 times per second.
|
||||
var/projectile_speed_coefficient = 1.5 //Higher the coefficient slower the projectile.
|
||||
var/projectile_tick_speed_ecost = 15
|
||||
var/current_damage_dampening = 0
|
||||
var/list/obj/item/projectile/tracked
|
||||
var/image/projectile_effect
|
||||
var/field_radius = 3
|
||||
|
||||
/obj/item/borg/projectile_dampen/debug
|
||||
maxenergy = 50000
|
||||
energy = 50000
|
||||
energy_recharge = 5000
|
||||
|
||||
/obj/item/borg/projectile_dampen/Initialize()
|
||||
. = ..()
|
||||
projectile_effect = image('icons/effects/fields.dmi', "projectile_dampen_effect")
|
||||
tracked = list()
|
||||
icon_state = "shield0"
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/obj/item/borg/projectile_dampen/Destroy()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/borg/projectile_dampen/attack_self(mob/user)
|
||||
var/active = FALSE
|
||||
if(!istype(dampening_field))
|
||||
activate_field()
|
||||
active = TRUE
|
||||
else
|
||||
deactivate_field()
|
||||
active = FALSE
|
||||
to_chat(user, "<span class='boldnotice'>You [active? "activate":"deactivate"] the [src].</span>")
|
||||
icon_state = "[initial(icon_state)][active]"
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/activate_field()
|
||||
if(!istype(dampening_field))
|
||||
dampening_field = make_field(/datum/proximity_monitor/advanced/peaceborg_dampener, list("current_range" = field_radius, "host" = src, "projector" = src))
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/deactivate_field()
|
||||
QDEL_NULL(dampening_field)
|
||||
visible_message("<span class='warning'>The [src] shuts off!</span>")
|
||||
for(var/obj/item/projectile/P in tracked)
|
||||
restore_projectile(P)
|
||||
|
||||
/obj/item/borg/projectile_dampen/process()
|
||||
process_recharge()
|
||||
process_usage()
|
||||
update_location()
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/update_location()
|
||||
if(dampening_field)
|
||||
dampening_field.HandleMove()
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/process_usage()
|
||||
var/usage = 0
|
||||
for(var/I in tracked)
|
||||
if(!tracked[I]) //No damage
|
||||
continue
|
||||
usage += projectile_tick_speed_ecost
|
||||
usage += (current_damage_dampening * projectile_damage_tick_ecost_coefficient)
|
||||
energy = Clamp(energy - usage, 0, maxenergy)
|
||||
if(energy <= 0)
|
||||
deactivate_field()
|
||||
visible_message("<span class='warning'>The [src] blinks \"ENERGY DEPLETED\"</span>")
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/process_recharge()
|
||||
if(!istype(host))
|
||||
energy = Clamp(energy + energy_recharge, 0, maxenergy)
|
||||
return
|
||||
if((host.cell.charge >= (host.cell.maxcharge * cyborg_cell_critical_percentage)) && (energy < maxenergy))
|
||||
host.cell.use(energy_recharge*energy_recharge_cyborg_drain_coefficient)
|
||||
energy += energy_recharge
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/dampen_projectile(obj/item/projectile/P, track_projectile = TRUE)
|
||||
if(tracked[P])
|
||||
return
|
||||
if(track_projectile)
|
||||
tracked[P] = P.damage
|
||||
current_damage_dampening += P.damage
|
||||
P.damage *= projectile_damage_coefficient
|
||||
P.speed *= projectile_speed_coefficient
|
||||
P.add_overlay(projectile_effect)
|
||||
|
||||
/obj/item/borg/projectile_dampen/proc/restore_projectile(obj/item/projectile/P)
|
||||
tracked -= P
|
||||
P.damage *= (1/projectile_damage_coefficient)
|
||||
P.speed *= (1/projectile_speed_coefficient)
|
||||
P.cut_overlay(projectile_effect)
|
||||
current_damage_dampening -= P.damage
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
HUD/SIGHT things
|
||||
***********************************************************************/
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
if (opacity)
|
||||
has_opaque_atom = TRUE
|
||||
|
||||
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
|
||||
/turf/open/space/attack_ghost(mob/dead/observer/user)
|
||||
@@ -177,7 +177,7 @@
|
||||
ChangeTurf(/turf/open/floor/plating)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/turf/open/space/ReplaceWithLattice()
|
||||
var/dest_x = destination_x
|
||||
var/dest_y = destination_y
|
||||
@@ -186,4 +186,4 @@
|
||||
destination_x = dest_x
|
||||
destination_y = dest_y
|
||||
destination_z = dest_z
|
||||
|
||||
|
||||
|
||||
+19
-18
@@ -92,39 +92,39 @@
|
||||
LC.attackby(C,user)
|
||||
return
|
||||
coil.place_turf(src, user)
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/turf/CanPass(atom/movable/mover, turf/target, height=1.5)
|
||||
if(!target) return 0
|
||||
if(!target) return FALSE
|
||||
|
||||
if(istype(mover)) // turf/Enter(...) will perform more advanced checks
|
||||
return !density
|
||||
|
||||
else // Now, doing more detailed checks for air movement and air group formation
|
||||
if(target.blocks_air||blocks_air)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
for(var/obj/obstacle in src)
|
||||
if(!obstacle.CanPass(mover, target, height))
|
||||
return 0
|
||||
return FALSE
|
||||
for(var/obj/obstacle in target)
|
||||
if(!obstacle.CanPass(mover, src, height))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area)
|
||||
if (!mover)
|
||||
return 1
|
||||
return TRUE
|
||||
// First, make sure it can leave its square
|
||||
if(isturf(mover.loc))
|
||||
// Nothing but border objects stop you from leaving a tile, only one loop is needed
|
||||
for(var/obj/obstacle in mover.loc)
|
||||
if(!obstacle.CheckExit(mover, src) && obstacle != mover && obstacle != forget)
|
||||
mover.Bump(obstacle, 1)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/list/large_dense = list()
|
||||
//Next, check objects to block entry that are on the border
|
||||
@@ -132,14 +132,14 @@
|
||||
if(border_obstacle.flags & ON_BORDER)
|
||||
if(!border_obstacle.CanPass(mover, mover.loc, 1) && (forget != border_obstacle))
|
||||
mover.Bump(border_obstacle, 1)
|
||||
return 0
|
||||
return FALSE
|
||||
else
|
||||
large_dense += border_obstacle
|
||||
|
||||
//Then, check the turf itself
|
||||
if (!src.CanPass(mover, src))
|
||||
mover.Bump(src, 1)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
//Finally, check objects/mobs to block entry that are not on the border
|
||||
var/atom/movable/tompost_bump
|
||||
@@ -151,8 +151,9 @@
|
||||
top_layer = obstacle.layer
|
||||
if(tompost_bump)
|
||||
mover.Bump(tompost_bump,1)
|
||||
return 0
|
||||
return 1 //Nothing found to block so return success!
|
||||
return FALSE
|
||||
|
||||
return TRUE //Nothing found to block so return success!
|
||||
|
||||
/turf/Entered(atom/movable/AM)
|
||||
if(explosion_level && AM.ex_check(explosion_id))
|
||||
@@ -185,7 +186,7 @@
|
||||
O.make_unfrozen()
|
||||
|
||||
/turf/proc/is_plasteel_floor()
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/turf/proc/levelupdate()
|
||||
for(var/obj/O in src)
|
||||
@@ -303,7 +304,7 @@
|
||||
if(src_object.contents.len)
|
||||
to_chat(usr, "<span class='notice'>You start dumping out the contents...</span>")
|
||||
if(!do_after(usr,20,target=src_object))
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/list/things = src_object.contents.Copy()
|
||||
var/datum/progressbar/progress = new(user, things.len, src)
|
||||
@@ -311,7 +312,7 @@
|
||||
sleep(1)
|
||||
qdel(progress)
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
//////////////////////////////
|
||||
//Distance procs
|
||||
@@ -325,7 +326,7 @@
|
||||
// possible. It results in more efficient (CPU-wise) pathing
|
||||
// for bots and anything else that only moves in cardinal dirs.
|
||||
/turf/proc/Distance_cardinal(turf/T)
|
||||
if(!src || !T) return 0
|
||||
if(!src || !T) return FALSE
|
||||
return abs(x - T.x) + abs(y - T.y)
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
@@ -341,7 +342,7 @@
|
||||
return(2)
|
||||
|
||||
/turf/proc/can_have_cabling()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/turf/proc/can_lay_cable()
|
||||
return can_have_cabling() & !intact
|
||||
|
||||
Reference in New Issue
Block a user