Skip to content

Commit

Permalink
Merge pull request Baystation12#14401 from atlantiscze/2016-10-13-Shi…
Browse files Browse the repository at this point in the history
…elds

Advanced Shield Generators
  • Loading branch information
PsiOmegaDelta authored Nov 8, 2016
2 parents f1eae32 + fd61d9b commit 8f61a80
Show file tree
Hide file tree
Showing 35 changed files with 1,635 additions and 978 deletions.
11 changes: 7 additions & 4 deletions baystation12.dme
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "code\__defines\mobs.dm"
#include "code\__defines\process_scheduler.dm"
#include "code\__defines\research.dm"
#include "code\__defines\shields.dm"
#include "code\__defines\species_languages.dm"
#include "code\__defines\targeting.dm"
#include "code\__defines\tgui.dm"
Expand Down Expand Up @@ -322,6 +323,7 @@
#include "code\datums\wires\particle_accelerator.dm"
#include "code\datums\wires\radio.dm"
#include "code\datums\wires\robot.dm"
#include "code\datums\wires\shield_generator.dm"
#include "code\datums\wires\smartfridge.dm"
#include "code\datums\wires\smes.dm"
#include "code\datums\wires\suit_storage_unit.dm"
Expand Down Expand Up @@ -1977,12 +1979,13 @@
#include "code\modules\scripting\Scanner\Tokens.dm"
#include "code\modules\security levels\keycard authentication.dm"
#include "code\modules\security levels\security levels.dm"
#include "code\modules\shield_generators\floor_diffuser.dm"
#include "code\modules\shield_generators\handheld_diffuser.dm"
#include "code\modules\shield_generators\modes.dm"
#include "code\modules\shield_generators\shield.dm"
#include "code\modules\shield_generators\shield_generator.dm"
#include "code\modules\shieldgen\emergency_shield.dm"
#include "code\modules\shieldgen\energy_field.dm"
#include "code\modules\shieldgen\shield_capacitor.dm"
#include "code\modules\shieldgen\shield_dis.dm"
#include "code\modules\shieldgen\shield_gen.dm"
#include "code\modules\shieldgen\shield_gen_external.dm"
#include "code\modules\shieldgen\shieldwallgen.dm"
#include "code\modules\shuttles\_defines.dm"
#include "code\modules\shuttles\antagonist.dm"
Expand Down
55 changes: 55 additions & 0 deletions code/__defines/shields.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#define SHIELD_DAMTYPE_PHYSICAL 1 // Physical damage - bullets, meteors, various hand objects - aka. "brute" damtype.
#define SHIELD_DAMTYPE_EM 2 // Electromagnetic damage - Ion weaponry, stun beams, ...
#define SHIELD_DAMTYPE_HEAT 3 // Heat damage - Lasers, fire

#define ENERGY_PER_HP (50 KILOWATTS)// Base amount energy that will be deducted from the generator's internal reserve per 1 HP of damage taken
#define ENERGY_UPKEEP_PER_TILE 100 // Base upkeep per tile protected. Multiplied by various enabled shield modes. Without them the field does literally nothing.

// This shield model is slightly inspired by Sins of a Solar Empire series. In short, shields are designed to analyze what hits them, and adapt themselves against that type of damage.
// This means shields will become increasingly effective against things like emitters - as they will adapt to heat damage, however they will be vulnerable to brute and EM damage.
// In a theoretical assault scenario, it is best to combine all damage types, so mitigation can't build up. The value is capped to prevent full scale invulnerability.

#define MAX_MITIGATION_BASE 50 // % Base maximal reachable mitigation.
#define MAX_MITIGATION_RESEARCH 10 // % Added to MAX_MITIGATION_BASE when generator is built using more advanced components. This value is added for each "tier" of used component, ie. basic one has 1, the best one has 3. Actual maximum should be 80% in this case (with best components). Make sure you won't get above 100%!
#define MITIGATION_HIT_GAIN 5 // Mitigation gain per hit of respective damage type.
#define MITIGATION_HIT_LOSS 4 // Mitigation loss per hit. If we get hit once by EM damage type, EM mitigation will grow, while Physical and Heat mitigation values drop.
#define MITIGATION_LOSS_PASSIVE 0.5 // Mitigation of all damage types will drop by this every tick, up to 0.

// Shield modes allow you to calibrate the field to fit specific needs. It is, for example, possible to create a field that will block airflow, but let people pass by calibrating it
// properly. Each enabled shield mode adds up to the upkeep power usage, however. The following defines are a multiplier - 1.5 means the power usage will be increased 1.5x.

#define MODEUSAGE_HYPERKINETIC // Blocks meteors and projectile based weapons. Relatively low as the shields are primarily intended as an anti-meteor countermeasure.
#define MODEUSAGE_PHOTONIC // Blocks energy weapons, and makes the field opaque.
#define MODEUSAGE_NONHUMANS // Blocks most organic lifeforms, with an exception being humanoid mobs. Typical uses include carps.
#define MODEUSAGE_HUMANOIDS // Blocks humanoid mobs.
#define MODEUSAGE_ANORGANIC // Blocks silicon-based mobs (cyborgs, drones, FBPs, IPCs, ..)
#define MODEUSAGE_ATMOSPHERIC // Blocks airflow.
#define MODEUSAGE_HULL 1 // Enables hull shielding mode, which changes a square shaped field into a field that covers external hull only.
#define MODEUSAGE_BYPASS // Attempts to counter shield diffusers. Puts very large EM strain on the shield when doing so. Has to be hacked.
#define MODEUSAGE_OVERCHARGE 3 // Overcharges the shield, causing it to shock anyone who touches a field segment. Best used with MODE_ORGANIC_HUMANOIDS. Has to be hacked.
#define MODEUSAGE_MODULATE 2 // Modulates the shield, enabling the mitigation system.

// Relevant mode bitflags (maximal of 16 flags due to current BYOND limitations)
#define MODEFLAG_HYPERKINETIC 1
#define MODEFLAG_PHOTONIC 2
#define MODEFLAG_NONHUMANS 4
#define MODEFLAG_HUMANOIDS 8
#define MODEFLAG_ANORGANIC 16
#define MODEFLAG_ATMOSPHERIC 32
#define MODEFLAG_HULL 64
#define MODEFLAG_BYPASS 128
#define MODEFLAG_OVERCHARGE 256
#define MODEFLAG_MODULATE 512

// Return codes for shield hits.
#define SHIELD_ABSORBED 1 // The shield has completely absorbed the hit
#define SHIELD_BREACHED_MINOR 2 // The hit was absorbed, but a small gap will be created in the field (1-3 tiles)
#define SHIELD_BREACHED_MAJOR 3 // Same as above, with 2-5 tile gap
#define SHIELD_BREACHED_CRITICAL 4 // Same as above, with 4-8 tile gap
#define SHIELD_BREACHED_FAILURE 5 // Same as above, with 8-16 tile gap. Occurs when the hit exhausts all remaining shield energy.

#define SHIELD_OFF 0 // The shield is offline
#define SHIELD_DISCHARGING 1 // The shield is shutting down and discharging.
#define SHIELD_RUNNING 2 // The shield is running

#define SHIELD_SHUTDOWN_DISPERSION_RATE (500 KILOWATTS) // The rate at which shield energy disperses when shutdown is initiated.
24 changes: 4 additions & 20 deletions code/datums/supplypacks/engineering.dm
Original file line number Diff line number Diff line change
Expand Up @@ -194,28 +194,12 @@
containername = "\improper Disposal Dispenser Crate"
access = access_atmospherics

/decl/hierarchy/supply_pack/engineering/shield_gen
name = "Bubble shield generator circuitry"
contains = list(/obj/item/weapon/circuitboard/shield_gen)
/decl/hierarchy/supply_pack/engineering/shield_generator
name = "Shield Generator Construction Kit"
contains = list(/obj/item/weapon/circuitboard/shield_generator, /obj/item/weapon/stock_parts/capacitor, /obj/item/weapon/stock_parts/micro_laser, /obj/item/weapon/smes_coil, /obj/item/weapon/stock_parts/console_screen)
cost = 50
containertype = /obj/structure/closet/crate/secure
containername = "\improper bubble shield generator circuitry crate"
access = access_ce

/decl/hierarchy/supply_pack/engineering/shield_gen_ex
name = "Hull shield generator circuitry"
contains = list(/obj/item/weapon/circuitboard/shield_gen_ex)
cost = 50
containertype = /obj/structure/closet/crate/secure
containername = "\improper hull shield generator circuitry crate"
access = access_ce

/decl/hierarchy/supply_pack/engineering/shield_cap
name = "Bubble shield capacitor circuitry"
contains = list(/obj/item/weapon/circuitboard/shield_cap)
cost = 50
containertype = /obj/structure/closet/crate/secure
containername = "\improper shield capacitor circuitry crate"
containername = "\improper shield generator construction kit crate"
access = access_ce

/decl/hierarchy/supply_pack/engineering/smbig
Expand Down
6 changes: 3 additions & 3 deletions code/datums/uplink/devices and tools.dm
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@
item_cost = 16
path = /obj/item/device/encryptionkey/syndicate

/datum/uplink_item/item/tools/shield_disrupter
name = "Shield disrupter"
/datum/uplink_item/item/tools/shield_diffuser
name = "Handheld Shield Diffuser"
item_cost = 16
path = /obj/item/device/shield_disrupter
path = /obj/item/weapon/shield_diffuser

/datum/uplink_item/item/tools/suit_sensor_mobile
name = "Suit Sensor Jamming Device"
Expand Down
46 changes: 46 additions & 0 deletions code/datums/wires/shield_generator.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/datum/wires/shield_generator
holder_type = /obj/machinery/power/shield_generator/
wire_count = 5

var/const/SHIELDGEN_WIRE_POWER = 1 // Cut to disable power input into the generator. Pulse does nothing. Mend to restore.
var/const/SHIELDGEN_WIRE_HACK = 2 // Pulse to hack the generator, enabling hacked modes. Cut to unhack. Mend does nothing.
var/const/SHIELDGEN_WIRE_CONTROL = 4 // Cut to lock most shield controls. Mend to unlock them. Pulse does nothing.
var/const/SHIELDGEN_WIRE_AICONTROL = 8 // Cut to disable AI control. Mend to restore.
var/const/SHIELDGEN_WIRE_NOTHING = 16 // A blank wire that doesn't have any specific function

/datum/wires/shield_generator/CanUse()
var/obj/machinery/power/shield_generator/S = holder
if(S.panel_open)
return 1
return 0

/datum/wires/shield_generator/UpdateCut(index, mended)
var/obj/machinery/power/shield_generator/S = holder
switch(index)
if(SHIELDGEN_WIRE_POWER)
S.input_cut = !mended
if(SHIELDGEN_WIRE_HACK)
if(!mended)
S.hacked = 0
if(S.check_flag(MODEFLAG_BYPASS))
S.toggle_flag(MODEFLAG_BYPASS)
if(S.check_flag(MODEFLAG_OVERCHARGE))
S.toggle_flag(MODEFLAG_OVERCHARGE)
if(SHIELDGEN_WIRE_CONTROL)
S.mode_changes_locked = !mended
if(SHIELDGEN_WIRE_AICONTROL)
S.ai_control_disabled = !mended

/datum/wires/shield_generator/UpdatePulsed(var/index)
var/obj/machinery/power/shield_generator/S = holder
switch(index)
if(SHIELDGEN_WIRE_HACK)
S.hacked = 1

/datum/wires/shield_generator/GetInteractWindow()
var/obj/machinery/power/shield_generator/S = holder
. += ..()
. += "<BR>A red light labeled \"Safety Override\" is [S.hacked ? "blinking" : "off"]."
. += "<BR>A green light labeled \"Power Connection\" is [S.input_cut ? "off" : "on"]."
. += "<BR>A blue light labeled \"Network Control\" is [S.ai_control_disabled ? "off" : "on"]."
. += "<BR>A yellow light labeled \"Interface Connection\" is [S.mode_changes_locked ? "off" : "on"].<BR>"
87 changes: 50 additions & 37 deletions code/game/gamemodes/meteor/meteor.dm
Original file line number Diff line number Diff line change
@@ -1,48 +1,61 @@
#define METEOR_DELAY 6000

#define METEOR_DELAY 30 MINUTES // This should be enough for crew to set up.
#define METEOR_DELAY_MULTIPLIER 5 // 5x larger duration between waves. That ensures the mode is less of a instant destruction of the station, and more of a continous stress.
// In general, a PVE oriented game mode. A middle ground between Extended and actual antagonist based rounds.
/datum/game_mode/meteor
name = "Meteor"
round_description = "The space station has been stuck in a major meteor shower."
extended_round_description = "The station is on an unavoidable collision course with an asteroid field. The station will be continuously slammed with meteors, venting hallways, rooms, and ultimately destroying a majority of the basic life functions of the entire structure. Coordinate with your fellow crew members to survive the inevitable destruction of the station and get back home in one piece!"
round_description = "The space station is about to enter an asteroid belt!"
extended_round_description = "The station is on an unavoidable collision course with an asteroid field. You have only a moment to prepare before the station is barraged by dust and meteors. As if it was not enough, all kinds of negative events seem to happen more frequently. Good Luck."
config_tag = "meteor"
required_players = 0
votable = 0
deny_respawn = 1
var/next_wave = METEOR_DELAY
required_players = 5 // Definitely not good for low-pop
votable = 1
var/next_wave = INFINITY // Set in post_setup() correctly to take into account potential longer pre-start times.
var/alert_sent = 0
var/meteor_severity = 1 // Slowly increases the tension at the beginning of meteor strikes. Prevents "tunguska on first wave" style problems.
var/alert_title
var/alert_text
var/start_text

event_delay_mod_moderate = 0.5 // As a bonus, more frequent events.
event_delay_mod_major = 0.5

/datum/game_mode/meteor/post_setup()
defer_powernet_rebuild = 2//Might help with the lag
..()
alert_title = "Automated Beacon AB-[rand(10, 99)]"
alert_text = "This is an automatic warning. Your facility: [using_map.full_name] is on a collision course with a nearby asteroid belt. Estimated time until impact is: [METEOR_DELAY / 240] MINUTES. Please perform necessary actions to secure your ship or station from the threat. Have a nice day."
start_text = "This is an automatic warning. Your facility: [using_map.full_name] has entered an asteroid belt. For your safety, please consider changing course or using protective equipment. Have a nice day."
next_wave = round_duration_in_ticks + METEOR_DELAY

/datum/game_mode/meteor/process()
if(world.time >= next_wave)
next_wave = world.time + meteor_wave_delay
spawn() spawn_meteors(6, meteors_normal)

/datum/game_mode/meteor/declare_completion()
var/text
var/survivors = 0
for(var/mob/living/player in player_list)
if(player.stat != DEAD)
var/area/A = get_area(player)
if(!A)
continue
if(is_type_in_list(A, using_map.post_round_safe_areas))
text += "<br><b><font size=2>[player.real_name] escaped in an emergenchy vehicle.</font></b>"
else
text += "<br><font size=1>[player.real_name] survived but is stranded without any hope of rescue.</font>"
survivors++

if(survivors)
to_world("<span class='notice'><B>The following survived the meteor storm</B></span>:[text]")
else
to_world("<span class='notice'><B>Nobody survived the meteor storm!</B></span>")
// Send an alert halfway through the round.
if((round_duration_in_ticks >= (next_wave / 2)) && !alert_sent)
alert_sent = 1
command_announcement.Announce(alert_text, alert_title)
// And then another one when the meteors start flying around.
if((round_duration_in_ticks >= next_wave) && (alert_sent == 1))
alert_sent = 2
command_announcement.Announce(start_text, alert_title)

if(round_duration_in_ticks >= next_wave)
next_wave = round_duration_in_ticks + (meteor_wave_delay * METEOR_DELAY_MULTIPLIER)
// Starts as barely noticeable dust impact, ends as barrage of most severe meteor types the code has to offer. Have fun.
spawn()
spawn_meteors(meteor_severity, get_meteor_types(), pick(cardinal))
if(prob(25))
meteor_severity = min(meteor_severity + 1, 10)

/datum/game_mode/meteor/proc/get_meteor_types()
switch(meteor_severity)
if(1 to 3)
return meteors_dust
if(4 to 6)
return meteors_normal
if(7 to 9)
return meteors_threatening
if(10)
return meteors_catastrophic
// Just in case we /somehow/ get here (looking at you, varedit)
return meteors_normal

feedback_set_details("round_end_result","end - evacuation")
feedback_set("round_end_result",survivors)

..()
return 1

#undef METEOR_DELAY

#undef METEOR_DELAY_MULTIPLIER
31 changes: 17 additions & 14 deletions code/game/gamemodes/meteor/meteors.dm
Original file line number Diff line number Diff line change
Expand Up @@ -97,26 +97,29 @@
pass_flags = PASSTABLE
var/heavy = 0
var/z_original

var/meteordrop = /obj/item/weapon/ore/iron
var/dropamt = 2

/obj/effect/meteor/proc/get_shield_damage()
return max(((max(hits, 2)) * (heavy + 1) * rand(30, 60)) / hitpwr , 0)


/obj/effect/meteor/New()
..()
z_original = z


/obj/effect/meteor/Move()
if(z != z_original || loc == dest)
qdel(src)
return

. = ..() //process movement...

if(.)//.. if did move, ram the turf we get in
if(.)
var/turf/T = get_turf(loc)
ram_turf(T)

if(prob(10) && !istype(T, /turf/space))//randomly takes a 'hit' from ramming
if(prob(20) && !istype(loc, /turf/space/))
get_hit()

return .
Expand All @@ -130,7 +133,8 @@
SpinAnimation()

/obj/effect/meteor/Bump(atom/A)
if(A)
..()
if(A && !deleted(src)) // Prevents explosions and other effects when we were deleted by whatever we Bumped() - currently used by shields.
ram_turf(get_turf(A))
get_hit()

Expand Down Expand Up @@ -256,21 +260,20 @@
// Worst case scenario: Comparable to a standard yield EMP grenade.
empulse(src, rand(2, 4), rand(4, 10))

/obj/effect/meteor/emp/get_shield_damage()
return ..() * rand(2,4)

//Station buster Tunguska
/obj/effect/meteor/tunguska
name = "tunguska meteor"
icon_state = "flaming"
desc = "Your life briefly passes before your eyes the moment you lay them on this monstruosity."
hits = 30
desc = "Your life briefly passes before your eyes the moment you lay them on this monstrosity."
hits = 10
hitpwr = 1
heavy = 1
meteordrop = /obj/item/weapon/ore/phoron
dropamt = 15
meteordrop = /obj/item/weapon/ore/diamond // Probably means why it penetrates the hull so easily before exploding.

/obj/effect/meteor/tunguska/meteor_effect()
..()
explosion(src.loc, 5, 10, 15, 20, 0)

/obj/effect/meteor/tunguska/Bump()
..()
if(prob(20))
explosion(src.loc,2,4,6,8)
explosion(src.loc, 3, 6, 9, 20, 0)
5 changes: 4 additions & 1 deletion code/game/machinery/recharger.dm
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ obj/machinery/recharger
idle_power_usage = 4
active_power_usage = 15000 //15 kW
var/obj/item/charging = null
var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/laptop, /obj/item/weapon/cell, /obj/item/modular_computer/, /obj/item/device/suit_sensor_jammer, /obj/item/weapon/computer_hardware/battery_module)
var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/laptop, /obj/item/weapon/cell, /obj/item/modular_computer/, /obj/item/device/suit_sensor_jammer, /obj/item/weapon/computer_hardware/battery_module, /obj/item/weapon/shield_diffuser)
var/icon_state_charged = "recharger2"
var/icon_state_charging = "recharger1"
var/icon_state_idle = "recharger0" //also when unpowered
Expand Down Expand Up @@ -105,6 +105,9 @@ obj/machinery/recharger/process()
else if(istype(charging, /obj/item/weapon/computer_hardware/battery_module))
var/obj/item/weapon/computer_hardware/battery_module/BM = charging
cell = BM.battery
else if(istype(charging, /obj/item/weapon/shield_diffuser))
var/obj/item/weapon/shield_diffuser/SD = charging
cell = SD.cell
if(istype(cell, /obj/item/weapon/cell))
var/obj/item/weapon/cell/C = cell
if(!C.fully_charged())
Expand Down
Loading

0 comments on commit 8f61a80

Please sign in to comment.