Files
2016-03-06 20:52:14 +01:00

587 lines
16 KiB
Plaintext

/datum/construction_controller
var/human_next_event
var/next_event_type = null
var/datum/construction_event/current_event = null
var/datum/construction_event/next_event = null
var/datum/construction_event/fallback_event = null
var/list/all_events = list()
var/list/possible_events = list()
var/list/event_types = list()
var/event_delay = 0
var/choose_at = 0
var/next_event_at = 0
New()
for (var/evtype in typesof(/datum/construction_event))
var/datum/construction_event/E = new evtype()
if (E.is_abstract)
qdel(E)
else
all_events += E
if (E.milestone == null)
possible_events += E
rebuild_event_types()
proc/notify_milestone_complete(var/datum/progress/P)
for (var/datum/construction_event/E in all_events)
if (istype(P, E.milestone))
possible_events += E
rebuild_event_types()
proc/notify_milestone_uncomplete(var/datum/progress/P)
for (var/datum/construction_event/E in possible_events)
if (istype(P, E.milestone))
possible_events -= E
rebuild_event_types()
proc/rebuild_event_types()
event_types.len = 0
for (var/datum/construction_event/E in possible_events)
if (!(E.event_type in event_types))
event_types += E.event_type
proc/process()
if (!ticker)
return
if (!ticker.mode)
return
if (!istype(ticker.mode, /datum/game_mode/construction))
return
if (event_delay)
if (ticker.round_elapsed_ticks < event_delay)
if (current_event)
current_event.process()
return
else
if (current_event)
current_event.tear_down()
current_event = null
event_delay = 0
if (!next_event_type)
next_event_type = pick(event_types)
var/minutes = rand(15, 30)
next_event_at = ticker.round_elapsed_ticks + minutes * 60 * 10 + rand(0, 59) * 10
choose_at = ticker.round_elapsed_ticks + rand(5, round(minutes / 2)) * 60 * 10 + rand(0, 59) * 10
for (var/datum/construction_event/E in possible_events)
if (E.event_type == next_event_type)
fallback_event = E
break
if (!fallback_event)
next_event_type = null
return
if (choose_at)
if (ticker.round_elapsed_ticks >= choose_at)
var/list/type_events = list()
for (var/datum/construction_event/E in possible_events)
if (E.event_type == next_event_type)
type_events += E
if (type_events.len)
next_event = pick(type_events)
else
next_event = fallback_event
next_event.early_warning()
fallback_event = null
if (next_event.additional_prep_time)
next_event_at += next_event.additional_prep_time
choose_at = 0
else
return
if (next_event_at)
if (ticker.round_elapsed_ticks >= next_event_at)
next_event.set_up()
current_event = next_event
next_event = null
event_delay = ticker.round_elapsed_ticks + current_event.duration
next_event_at = 0
next_event_type = null
else
return
/datum/construction_event
var/name = null
var/early_warning_heading = "Anomaly alert"
var/early_warning_text = "An anomaly is heading towards the station."
var/warning_heading = "Anomaly alert"
var/warning_text = "The anomaly has reached the station."
var/datum/progress/milestone = null
var/event_type = "Anomaly"
var/duration = 600 // 1 min
var/additional_prep_time = 0
var/is_abstract = 1
var/time_scaling = 0.167
var/time_modifier = 0
var/player_scaling = 0.1
var/player_modifier = 0
proc/early_warning()
for (var/obj/machinery/communications_dish/C in machines)
C.add_centcom_report("[command_name()] Update", early_warning_text)
if (!early_warning_heading)
command_alert(early_warning_text)
else
command_alert(early_warning_text, early_warning_heading)
proc/set_up()
for (var/obj/machinery/communications_dish/C in machines)
C.add_centcom_report("[command_name()] Update", warning_text)
if (!warning_heading)
command_alert(warning_text)
else
command_alert(warning_text, warning_heading)
calculate_player_modifier()
calculate_time_modifier()
proc/process()
return
proc/tear_down()
return
proc/calculate_player_modifier()
player_modifier = 1
for (var/mob/living/M in mobs)
if (M.client && M.stat < 2)
player_modifier += player_scaling
proc/calculate_time_modifier()
var/datum/game_mode/construction/C = ticker.mode
var/elapsed_time = ticker.round_elapsed_ticks - C.starttime
time_modifier = (1 + round(elapsed_time / 36000) * time_scaling)
/datum/construction_event/nothing
duration = 600
name = "Nothing"
siege
early_warning_heading = "Siege alert"
early_warning_text = "A large attack force has been detected on collision course with the station."
warning_heading = "Siege alert averted"
warning_text = "The attacking force changed course towards a nearby planet."
event_type = "Siege"
syndicate
event_type = "Syndicate Siege"
anomaly
early_warning_text = "Chunks from a nearby asteroid collision are headed towards the station from the"
warning_text = "The gravitational field of a nearby planet diverted the meteors off collision course."
event_type = "Cosmic Anomaly"
early_warning()
var/early_warning_orig = early_warning_heading
early_warning_text = "[early_warning_heading] [pick("north!", "south!", "east!", "west!")]"
..()
early_warning_text = early_warning_orig
#define METHOD_TELEPORT 1
#define METHOD_SPAWN 2
//#define METHOD_TELEPORT_TO_SPACE 3
#define METHOD_EDGE_WANDER 4
/datum/construction_event/siege
name = "Siege"
early_warning_heading = "Siege alert"
early_warning_text = "A large attack force has been detected on collision course with the station."
warning_heading = "Siege alert"
warning_text = "We are under attack!"
event_type = "Siege"
time_scaling = 0.33
player_scaling = 0.2
var/original_duration = 600
var/spawn_delay = 2
var/current_delay = 0
var/max_attack_force_size = 50
var/original_size = 50
var/current_attack_force_size = 0
var/list/attacker_types = list()
var/list/bosses = list()
var/current_bosses = 0
var/difficulty_multiplier = 0
var/original_bosses = 2
var/max_bosses = 2
var/method = METHOD_TELEPORT
var/list/possible_target_turfs = list()
var/per_process = 1
var/x_min
var/x_max
var/y_min
var/y_max
set_up()
..()
player_modifier -= 1
time_modifier -= 0.5
difficulty_multiplier = time_modifier * player_modifier
duration = original_duration * difficulty_multiplier
max_attack_force_size = round(original_size * difficulty_multiplier)
per_process = max(1, round(max_attack_force_size / 20))
max_bosses = round(original_bosses * difficulty_multiplier)
current_attack_force_size = 0
current_delay = 0
current_bosses = 0
possible_target_turfs.len = 0
var/area/shuttle/arrival/station/A = locate() in world
var/turf/Q = A.find_middle(0)
for (var/turf/simulated/floor/F in range(50, Q))
if (!(F in A))
possible_target_turfs += F
if (method == METHOD_EDGE_WANDER)
switch(rand(1,4))
if (1)
x_min = 50
x_max = 250
y_min = 295
y_max = 297
if (2)
x_min = 50
x_max = 250
y_min = 3
y_max = 5
if (3)
x_min = 295
x_max = 297
y_min = 50
y_max = 250
if (4)
x_min = 3
x_max = 5
y_min = 50
y_max = 250
process()
if (current_attack_force_size < max_attack_force_size)
var/runs = 1
if (per_process > 1)
runs = rand(1, per_process)
for (var/times = 1, times <= runs, times++)
if (current_delay > 0)
current_delay--
else if (prob(25 * difficulty_multiplier))
if (method == METHOD_TELEPORT || method == METHOD_SPAWN)
var/valid = 0
while (!valid)
if (!possible_target_turfs.len)
current_attack_force_size = max_attack_force_size
break
var/turf/target = pick(possible_target_turfs)
if (target.density)
possible_target_turfs -= target
continue
valid = 1
for (var/obj/O in target)
if (O.density)
possible_target_turfs -= target
valid = 0
break
if (!valid)
continue
var/attacker_type
if (current_bosses < max_bosses && bosses.len && prob(5))
attacker_type = pick(bosses)
current_bosses++
else
attacker_type = pick(attacker_types)
new attacker_type(target)
current_attack_force_size++
current_delay = spawn_delay
if (method == METHOD_TELEPORT)
showswirl(target)
else if (method == METHOD_EDGE_WANDER)
var/valid = 0
while (!valid)
if (!possible_target_turfs.len)
current_attack_force_size = max_attack_force_size
break
var/turf/target = pick(possible_target_turfs)
if (target.density)
possible_target_turfs -= target
continue
valid = 1
for (var/obj/O in target)
if (O.density)
possible_target_turfs -= target
valid = 0
break
if (!valid)
continue
var/attacker_type
if (current_bosses < max_bosses && bosses.len && prob(5))
attacker_type = pick(bosses)
current_bosses++
else
attacker_type = pick(attacker_types)
var/obj/critter/CR = new attacker_type(locate(rand(x_min, x_max), rand(y_min, y_max), 1))
current_attack_force_size++
CR.task = "following path"
CR.followed_path = findPath(CR.loc, target)
CR.followed_path_retry_target = target
if (prob(30 / difficulty_multiplier))
CR.follow_path_blindly = 1
/datum/construction_event/siege/rockworm
name = "Siege?"
warning_text = "We are under attack by the Space Rock Worm Federation!"
attacker_types = list(/obj/critter/rockworm)
original_size = 20
original_bosses = 0
is_abstract = 0
/datum/construction_event/siege/hobo
name = "Siege?"
warning_text = "We are under attack by the Space Hobo Federation!"
attacker_types = list(/mob/living/carbon/human/biker)
original_size = 3
original_bosses = 0
is_abstract = 0
/datum/construction_event/siege/martian
name = "Martian Siege"
warning_text = "We are under attack by a martian siege force!"
attacker_types = list(/obj/critter/martian/warrior, /obj/critter/martian/soldier)
bosses = list(/obj/critter/martian/psychic/weak, /obj/critter/martian/sapper)
original_size = 20
original_bosses = 2
is_abstract = 0
/datum/construction_event/siege/spirits
name = "Spirit Siege"
warning_text = "We are under siege from a dimensional fissure!"
attacker_types = list(/obj/critter/spirit)
bosses = list(/obj/critter/aberration)
method = METHOD_SPAWN
original_size = 15
original_bosses = 1
is_abstract = 0
/datum/construction_event/siege/animals
name = "Animal Siege"
warning_text = "A pack of animals have been teleported on board our station!"
attacker_types = list(/obj/critter/spacebee, /obj/critter/mouse, /obj/critter/goose, /obj/critter/owl, /obj/critter/bat/buff, /obj/critter/cat, /obj/critter/nicespider, /obj/critter/spider/spacerachnid)
bosses = list(/obj/critter/lion, /obj/critter/bear)
original_size = 30
original_bosses = 5
is_abstract = 0
/datum/construction_event/siege/plants
name = "Plant Siege"
warning_text = "We are under attack by a group of sentient vegetables!"
attacker_types = list(/obj/critter/killertomato)
bosses = list(/obj/critter/maneater)
original_size = 30
original_bosses = 1
is_abstract = 0
/datum/construction_event/siege/drones
name = "Drone Siege"
event_type = "Syndicate Siege"
warning_text = "We are under siege from a small drone force!"
attacker_types = list(/obj/critter/gunbot/drone)
bosses = list(/obj/critter/gunbot/drone/buzzdrone)
original_size = 8
original_bosses = 1
is_abstract = 0
method = METHOD_EDGE_WANDER
/datum/construction_event/siege/drones_buzz
name = "Buzz Drone Siege"
event_type = "Syndicate Siege"
warning_text = "We are under siege from a small drone force!"
attacker_types = list(/obj/critter/gunbot/drone/buzzdrone)
bosses = list(/obj/critter/gunbot/drone/buzzdrone)
milestone = /datum/progress/pods/tier1
original_size = 6
original_bosses = 1
is_abstract = 0
method = METHOD_EDGE_WANDER
/datum/construction_event/siege/drones_heavy
name = "Heavy Drone Siege"
event_type = "Syndicate Siege"
warning_text = "We are under siege from a small drone force!"
attacker_types = list(/obj/critter/gunbot/drone/buzzdrone)
bosses = list(/obj/critter/gunbot/drone/heavydrone)
milestone = /datum/progress/pods/tier2
original_size = 6
original_bosses = 1
is_abstract = 0
method = METHOD_EDGE_WANDER
/datum/construction_event/meteors
warning_text = "The meteor shower has reached the station."
var/early_warning_original = "Chunks from a nearby asteroid collision are headed towards the station"
event_type = "Cosmic Anomaly"
var/direction = 0
var/x_min = 0
var/x_max = 0
var/y_min = 0
var/y_max = 0
var/turf/around = null
is_abstract = 1
early_warning()
direction = rand(1,4)
switch (direction)
if (1)
early_warning_text = "[early_warning_original] from the north!"
if (2)
early_warning_text = "[early_warning_original] from the south!"
if (3)
early_warning_text = "[early_warning_original] from the east!"
if (4)
early_warning_text = "[early_warning_original] from the west!"
..()
set_up()
..()
player_modifier -= 1
var/area/shuttle/arrival/station/A = locate() in world
around = A.find_middle(0)
if (!around)
around = locate(150, 150, 1)
switch(direction)
if (1)
x_min = 50
x_max = 250
y_min = 295
y_max = 297
if (2)
x_min = 50
x_max = 250
y_min = 3
y_max = 5
if (3)
x_min = 295
x_max = 297
y_min = 50
y_max = 250
if (4)
x_min = 3
x_max = 5
y_min = 50
y_max = 250
process()
if (prob(20 * player_modifier * time_modifier))
var/turf/target = null
var/retries = 0
do
if (retries > 5)
return
target = pick(range(50, around))
retries++
while (!target)
if (!isturf(target))
target = get_turf(target)
if (!target)
return
create_meteor(locate(rand(x_min, x_max), rand(y_min, y_max), 1), target)
proc/create_meteor(var/turf/from, var/turf/target)
return
/datum/construction_event/meteors/small_meteor_storm
name = "Small Meteor Shower"
early_warning_original = "Chunks from a nearby asteroid collision are headed towards the station"
is_abstract = 0
create_meteor(var/turf/from, var/turf/target)
new /obj/newmeteor/small(from, target)
/datum/construction_event/meteors/medium_meteor_storm
name = "Medium Meteor Shower"
milestone = /datum/progress/time/twohours
early_warning_original = "Chunks from a nearby microplanet collision are headed towards the station"
is_abstract = 0
create_meteor(var/turf/from, var/turf/target)
if (prob(80))
new /obj/newmeteor/small(from, target)
else
new /obj/newmeteor/massive(from, target)
/datum/construction_event/meteors/massive_meteor_storm
name = "Large Meteor Shower"
milestone = /datum/progress/time/sixhours
early_warning_original = "Chunks from a nearby planetary collision are headed towards the station"
is_abstract = 0
create_meteor(var/turf/from, var/turf/target)
if (prob(30))
new /obj/newmeteor/small(from, target)
else
new /obj/newmeteor/massive(from, target)
/datum/construction_event/radiation_storm
name = "Radiation Storm"
early_warning_text = "A large wave of radiation is approaching the station."
warning_text = "The radiation wave is hitting the station!"
event_type = "Cosmic Anomaly"
is_abstract = 0
var/sound/radsound = 'sound/weapons/ACgun2.ogg'
var/list/possible_target_turfs = list()
set_up()
..()
possible_target_turfs.len = 0
var/area/shuttle/arrival/station/A = locate() in world
var/turf/Q = A.find_middle(0)
for (var/turf/simulated/floor/F in range(50, Q))
if (!(F in A))
possible_target_turfs += F
process()
if (prob(40))
var/turf/target = pick(possible_target_turfs)
if (!target)
possible_target_turfs -= target
return
create_radwave(target, rand(30, 60), radsound)
/proc/trigger_construction_event()
if (!ticker)
return
if (!ticker.mode)
return
if (!istype(ticker.mode, /datum/game_mode/construction))
return
var/datum/game_mode/construction/C = ticker.mode
var/datum/construction_controller/E = C.events
E.event_delay = 1
E.process()
E.choose_at = 1
E.process()
E.next_event_at = 1
E.process()
/proc/trigger_specific_construction_event()
if (!ticker)
return
if (!ticker.mode)
return
if (!istype(ticker.mode, /datum/game_mode/construction))
return
var/datum/game_mode/construction/C = ticker.mode
var/datum/construction_controller/E = C.events
var/datum/construction_event/EV = input("Which event", "Event", null) in E.all_events
E.event_delay = 1
E.process()
E.next_event_type = EV.type
E.choose_at = 1
E.process()
E.next_event = EV
E.next_event_at = 1
E.process()