/datum/round_event_control/pirates
name = "Space Pirates"
typepath = /datum/round_event/pirates
weight = 8
max_occurrences = 1
min_players = 10
earliest_start = 30 MINUTES
dynamic_should_hijack = TRUE
category = EVENT_CATEGORY_INVASION
description = "The crew will either pay up, or face a pirate assault."
#define PIRATES_ROGUES "Rogues"
// #define PIRATES_SILVERSCALES "Silverscales"
// #define PIRATES_DUTCHMAN "Flying Dutchman"
/datum/round_event_control/pirates/preRunEvent()
if (!SSmapping.empty_space)
return EVENT_CANT_RUN
return ..()
/datum/round_event/pirates/start()
send_pirate_threat()
/proc/send_pirate_threat()
var/pirate_type = PIRATES_ROGUES //pick(PIRATES_ROGUES, PIRATES_SILVERSCALES, PIRATES_DUTCHMAN)
var/datum/comm_message/threat_msg = new
var/payoff = 0
var/payoff_min = 10000 //documented this time
var/ship_template
var/ship_name = "Space Privateers Association"
var/initial_send_time = world.time
var/response_max_time = 2 MINUTES
switch(pirate_type)
if(PIRATES_ROGUES)
ship_name = pick(strings(PIRATE_NAMES_FILE, "rogue_names"))
// if(PIRATES_SILVERSCALES)
// ship_name = pick(strings(PIRATE_NAMES_FILE, "silverscale_names"))
// if(PIRATES_DUTCHMAN)
// ship_name = "Flying Dutchman"
priority_announce("Incoming subspace communication. Secure channel opened at all communication consoles.", "Incoming Message", SSstation.announcer.get_rand_report_sound(), has_important_message = TRUE)
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
payoff = max(payoff_min, FLOOR(D.account_balance * 0.80, 1000))
switch(pirate_type)
if(PIRATES_ROGUES)
ship_template = /datum/map_template/shuttle/pirate/default
threat_msg.title = "Sector protection offer"
threat_msg.content = "Hey, pal, this is the [ship_name]. Can't help but notice you're rocking a wild and crazy shuttle there with NO INSURANCE! Crazy. What if something happened to it, huh?! We've done a quick evaluation on your rates in this sector and we're offering [payoff] to cover for your shuttle in case of any disaster."
threat_msg.possible_answers = list("Purchase Insurance.","Reject Offer.")
// if(PIRATES_SILVERSCALES)
// ship_template = /datum/map_template/shuttle/pirate/silverscale
// threat_msg.title = "Tribute to high society"
// threat_msg.content = "This is the [ship_name]. The Silver Scales wish for some tribute from your plebeian lizards. [payoff] credits should do the trick."
// threat_msg.possible_answers = list("We'll pay.","Tribute? Really? Go away.")
// if(PIRATES_DUTCHMAN)
// ship_template = /datum/map_template/shuttle/pirate/dutchman
// threat_msg.title = "Business proposition"
// threat_msg.content = "Ahoy! This be the [ship_name]. Cough up [payoff] credits or you'll walk the plank."
// threat_msg.possible_answers = list("We'll pay.","We will not be extorted.")
threat_msg.answer_callback = CALLBACK(GLOBAL_PROC, .proc/pirates_answered, threat_msg, payoff, ship_name, initial_send_time, response_max_time, ship_template)
addtimer(CALLBACK(GLOBAL_PROC, .proc/spawn_pirates, threat_msg, ship_template, FALSE), response_max_time)
SScommunications.send_message(threat_msg,unique = TRUE)
/proc/pirates_answered(datum/comm_message/threat_msg, payoff, ship_name, initial_send_time, response_max_time, ship_template)
if(world.time > initial_send_time + response_max_time)
priority_announce("Too late to beg for mercy!",sender_override = ship_name, has_important_message = TRUE)
return
if(threat_msg && threat_msg.answered == 1)
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
if(D.adjust_money(-payoff))
priority_announce("Thanks for the credits, landlubbers.",sender_override = ship_name, has_important_message = TRUE)
return
else
priority_announce("Trying to cheat us? You'll regret this!",sender_override = ship_name, has_important_message = TRUE)
spawn_pirates(threat_msg, ship_template, TRUE)
/proc/spawn_pirates(datum/comm_message/threat_msg, ship_template, skip_answer_check)
if(!skip_answer_check && threat_msg?.answered == 1)
return
var/list/candidates = pollGhostCandidates("Do you wish to be considered for pirate crew?", ROLE_TRAITOR)
shuffle_inplace(candidates)
var/datum/map_template/shuttle/pirate/ship = new ship_template
var/x = rand(TRANSITIONEDGE,world.maxx - TRANSITIONEDGE - ship.width)
var/y = rand(TRANSITIONEDGE,world.maxy - TRANSITIONEDGE - ship.height)
var/z = SSmapping.empty_space.z_value
var/turf/T = locate(x,y,z)
if(!T)
CRASH("Pirate event found no turf to load in")
if(!ship.load(T))
CRASH("Loading pirate ship failed!")
for(var/turf/A in ship.get_affected_turfs(T))
for(var/obj/effect/mob_spawn/human/pirate/spawner in A)
if(candidates.len > 0)
var/mob/our_candidate = candidates[1]
spawner.create(our_candidate.ckey)
candidates -= our_candidate
notify_ghosts("The pirate ship has an object of interest: [our_candidate]!", source=our_candidate, action=NOTIFY_ORBIT, header="Something's Interesting!")
else
notify_ghosts("The pirate ship has an object of interest: [spawner]!", source=spawner, action=NOTIFY_ORBIT, header="Something's Interesting!")
priority_announce("Unidentified armed ship detected near the station.")
//Shuttle equipment
/obj/machinery/shuttle_scrambler
name = "Data Siphon"
desc = "This heap of machinery steals credits and data from unprotected systems and locks down cargo shuttles."
icon = 'icons/obj/machines/dominator.dmi'
icon_state = "dominator"
density = TRUE
var/active = FALSE
var/credits_stored = 0
var/siphon_per_tick = 5
/obj/machinery/shuttle_scrambler/Initialize(mapload)
. = ..()
update_icon()
/obj/machinery/shuttle_scrambler/process()
if(active)
if(is_station_level(z))
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
if(D)
var/siphoned = min(D.account_balance,siphon_per_tick)
D.adjust_money(-siphoned)
credits_stored += siphoned
interrupt_research()
else
return
else
STOP_PROCESSING(SSobj,src)
/obj/machinery/shuttle_scrambler/proc/toggle_on(mob/user)
SSshuttle.registerTradeBlockade(src)
AddComponent(/datum/component/gps, "Nautical Signal")
active = TRUE
to_chat(user,"You toggle [src] [active ? "on":"off"].")
to_chat(user,"The scrambling signal can be now tracked by GPS.")
START_PROCESSING(SSobj,src)
/obj/machinery/shuttle_scrambler/interact(mob/user)
if(!active)
if(alert(user, "Turning the scrambler on will make the shuttle trackable by GPS. Are you sure you want to do it?", "Scrambler", "Yes", "Cancel") == "Cancel")
return
if(active || !user.canUseTopic(src, BE_CLOSE))
return
toggle_on(user)
update_icon()
send_notification()
else
dump_loot(user)
//interrupt_research
/obj/machinery/shuttle_scrambler/proc/interrupt_research()
for(var/obj/machinery/rnd/server/S in GLOB.machines)
if(S.stat & (NOPOWER|BROKEN))
continue
S.emp_act(80)
new /obj/effect/temp_visual/emp(get_turf(S))
/obj/machinery/shuttle_scrambler/proc/dump_loot(mob/user)
if(credits_stored) // Prevents spamming empty holochips
new /obj/item/holochip(drop_location(), credits_stored)
to_chat(user,"You retrieve the siphoned credits!")
credits_stored = 0
else
to_chat(user,"There's nothing to withdraw.")
/obj/machinery/shuttle_scrambler/proc/send_notification()
priority_announce("Data theft signal detected, source registered on local gps units.")
/obj/machinery/shuttle_scrambler/proc/toggle_off(mob/user)
SSshuttle.clearTradeBlockade(src)
active = FALSE
STOP_PROCESSING(SSobj,src)
/obj/machinery/shuttle_scrambler/update_icon_state()
icon_state = active ? "dominator-blue" : "dominator"
return ..()
/obj/machinery/shuttle_scrambler/Destroy()
toggle_off()
return ..()
/obj/machinery/computer/shuttle/pirate
name = "pirate shuttle console"
shuttleId = "pirateship"
icon_screen = "syndishuttle"
icon_keyboard = "syndie_key"
light_color = LIGHT_COLOR_RED
req_access = list(ACCESS_SYNDICATE)
possible_destinations = "pirateship_away;pirateship_home;pirateship_custom"
/obj/machinery/computer/camera_advanced/shuttle_docker/syndicate/pirate
name = "pirate shuttle navigation computer"
desc = "Used to designate a precise transit location for the pirate shuttle."
shuttleId = "pirateship"
lock_override = CAMERA_LOCK_STATION
shuttlePortId = "pirateship_custom"
x_offset = 11
y_offset = 1
see_hidden = FALSE
/obj/docking_port/mobile/pirate
name = "pirate shuttle"
id = "pirateship"
rechargeTime = 3 MINUTES
/obj/machinery/suit_storage_unit/pirate
storage_type = /obj/item/tank/jetpack/carbondioxide
/obj/machinery/loot_locator
name = "Booty Locator"
desc = "This sophisticated machine scans the nearby space for items of value."
icon = 'icons/obj/machines/research.dmi'
icon_state = "tdoppler"
density = TRUE
var/cooldown = 300
var/next_use = 0
/obj/machinery/loot_locator/interact(mob/user)
if(world.time <= next_use)
to_chat(user,"[src] is recharging.")
return
next_use = world.time + cooldown
var/atom/movable/AM = find_random_loot()
if(!AM)
say("No valuables located. Try again later.")
else
say("Located: [AM.name] at [get_area_name(AM)]")
/obj/machinery/loot_locator/proc/find_random_loot()
if(!GLOB.exports_list.len)
setupExports()
var/list/possible_loot = list()
for(var/datum/export/pirate/E in GLOB.exports_list)
possible_loot += E
var/datum/export/pirate/P
var/atom/movable/AM
while(!AM && possible_loot.len)
P = pick_n_take(possible_loot)
AM = P.find_loot()
return AM
//Pad & Pad Terminal
/obj/machinery/piratepad
name = "cargo hold pad"
icon = 'icons/obj/telescience.dmi'
icon_state = "lpad-idle-off"
var/idle_state = "lpad-idle"
var/warmup_state = "lpad-idle"
var/sending_state = "lpad-beam"
var/cargo_hold_id
/obj/machinery/piratepad/multitool_act(mob/living/user, obj/item/multitool/I)
. = ..()
if (istype(I))
to_chat(user, "You register [src] in [I]s buffer.")
I.buffer = src
return TRUE
/obj/machinery/piratepad/screwdriver_act(mob/living/user, obj/item/screwdriver/screw)
. = ..()
if(!.)
return default_deconstruction_screwdriver(user, "lpad-idle-open", "lpad-idle-off", screw)
/obj/machinery/piratepad/crowbar_act(mob/living/user, obj/item/tool)
. = ..()
default_deconstruction_crowbar(tool)
return TRUE
/obj/machinery/computer/piratepad_control
name = "cargo hold control terminal"
var/status_report = "Ready for delivery."
var/obj/machinery/piratepad/pad
var/warmup_time = 100
var/sending = FALSE
var/points = 0
var/datum/export_report/total_report
var/sending_timer
var/cargo_hold_id
///Reference to the specific pad that the control computer is linked up to.
var/datum/weakref/pad_ref
/obj/machinery/computer/piratepad_control/Initialize(mapload)
..()
return INITIALIZE_HINT_LATELOAD
/obj/machinery/computer/piratepad_control/multitool_act(mob/living/user, obj/item/multitool/I)
. = ..()
if (istype(I) && istype(I.buffer,/obj/machinery/piratepad))
to_chat(user, "You link [src] with [I.buffer] in [I] buffer.")
pad_ref = WEAKREF(I.buffer)
return TRUE
/obj/machinery/computer/piratepad_control/LateInitialize()
. = ..()
if(cargo_hold_id)
for(var/obj/machinery/piratepad/P in GLOB.machines)
if(P.cargo_hold_id == cargo_hold_id)
pad_ref = WEAKREF(P)
return
else
pad = locate() in range(4,src)
pad_ref = WEAKREF(pad)
/obj/machinery/computer/piratepad_control/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "CargoHoldTerminal", name)
ui.open()
/obj/machinery/computer/piratepad_control/ui_data(mob/user)
var/list/data = list()
data["points"] = points
data["pad"] = pad_ref?.resolve() ? TRUE : FALSE
data["sending"] = sending
data["status_report"] = status_report
return data
/obj/machinery/computer/piratepad_control/ui_act(action, params)
. = ..()
if(.)
return
if(!pad_ref?.resolve())
return
switch(action)
if("recalc")
recalc()
. = TRUE
if("send")
start_sending()
. = TRUE
if("stop")
stop_sending()
. = TRUE
/obj/machinery/computer/piratepad_control/proc/recalc()
if(sending)
return
status_report = "Predicted value: "
var/value = 0
var/datum/export_report/ex = new
var/obj/machinery/piratepad/pad = pad_ref?.resolve()
for(var/atom/movable/AM in get_turf(pad))
if(AM == pad)
continue
export_item_and_contents(AM, EXPORT_PIRATE | EXPORT_CARGO | EXPORT_CONTRABAND | EXPORT_EMAG, apply_elastic = FALSE, dry_run = TRUE, external_report = ex)
for(var/datum/export/E in ex.total_amount)
status_report += E.total_printout(ex,notes = FALSE)
status_report += " "
value += ex.total_value[E]
if(!value)
status_report += "0"
/obj/machinery/computer/piratepad_control/proc/send()
if(!sending)
return
var/datum/export_report/ex = new
var/obj/machinery/piratepad/pad = pad_ref?.resolve()
for(var/atom/movable/AM in get_turf(pad))
if(AM == pad)
continue
export_item_and_contents(AM, EXPORT_PIRATE | EXPORT_CARGO | EXPORT_CONTRABAND | EXPORT_EMAG, apply_elastic = FALSE, delete_unsold = FALSE, external_report = ex)
status_report = "Sold: "
var/value = 0
for(var/datum/export/E in ex.total_amount)
var/export_text = E.total_printout(ex,notes = FALSE) //Don't want nanotrasen messages, makes no sense here.
if(!export_text)
continue
status_report += export_text
status_report += " "
value += ex.total_value[E]
if(!total_report)
total_report = ex
else
total_report.exported_atoms += ex.exported_atoms
for(var/datum/export/E in ex.total_amount)
total_report.total_amount[E] += ex.total_amount[E]
total_report.total_value[E] += ex.total_value[E]
// playsound(loc, 'sound/machines/wewewew.ogg', 70, TRUE)
points += value
if(!value)
status_report += "Nothing"
pad.visible_message("[pad] activates!")
flick(pad.sending_state,pad)
pad.icon_state = pad.idle_state
sending = FALSE
/obj/machinery/computer/piratepad_control/proc/start_sending()
var/obj/machinery/piratepad/pad = pad_ref?.resolve()
if(!pad)
status_report = "No pad detected. Build or link a pad."
pad.audible_message(span_notice("[pad] beeps."))
return
if(pad?.panel_open)
status_report = "Please screwdrive pad closed to send. "
pad.audible_message(span_notice("[pad] beeps."))
return
if(sending)
return
sending = TRUE
status_report = "Sending... "
pad.visible_message("[pad] starts charging up.")
pad.icon_state = pad.warmup_state
sending_timer = addtimer(CALLBACK(src,.proc/send),warmup_time, TIMER_STOPPABLE)
/obj/machinery/computer/piratepad_control/proc/stop_sending(custom_report)
if(!sending)
return
sending = FALSE
status_report = "Ready for delivery."
if(custom_report)
status_report = custom_report
pad.icon_state = pad.idle_state
deltimer(sending_timer)
/datum/export/pirate
export_category = EXPORT_PIRATE
//Attempts to find the thing on station
/datum/export/pirate/proc/find_loot()
return
/datum/export/pirate/ransom
cost = 3000
unit_name = "hostage"
export_types = list(/mob/living/carbon/human)
/datum/export/pirate/ransom/find_loot()
var/list/head_minds = SSjob.get_living_heads()
var/list/head_mobs = list()
for(var/datum/mind/M in head_minds)
head_mobs += M.current
if(head_mobs.len)
return pick(head_mobs)
/datum/export/pirate/ransom/get_cost(atom/movable/AM)
var/mob/living/carbon/human/H = AM
if(H.stat != CONSCIOUS || !H.mind || !H.mind.assigned_role) //mint condition only
return 0
else if("pirate" in H.faction) //can't ransom your fellow pirates to CentCom!
return 0
else
if(H.mind.assigned_role in GLOB.command_positions)
return 3000
else
return 1000
/datum/export/pirate/parrot
cost = 2000
unit_name = "alive parrot"
export_types = list(/mob/living/simple_animal/parrot)
/datum/export/pirate/parrot/find_loot()
for(var/mob/living/simple_animal/parrot/P in GLOB.alive_mob_list)
var/turf/T = get_turf(P)
if(T && is_station_level(T.z))
return P
/datum/export/pirate/cash
cost = 1
unit_name = "bills"
export_types = list(/obj/item/stack/spacecash)
/datum/export/pirate/cash/get_amount(obj/O)
var/obj/item/stack/spacecash/C = O
return ..() * C.amount * C.value
/datum/export/pirate/holochip
cost = 1
unit_name = "holochip"
export_types = list(/obj/item/holochip)
/datum/export/pirate/holochip/get_cost(atom/movable/AM)
var/obj/item/holochip/H = AM
return H.credits