/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 gamemode_blacklist = list("nuclear") /datum/round_event_control/pirates/preRunEvent() if (!SSmapping.empty_space) return EVENT_CANT_RUN return ..() /datum/round_event/pirates startWhen = 60 //2 minutes to answer var/datum/comm_message/threat_message var/payoff = 0 var/paid_off = FALSE var/ship_name = "Space Privateers Association" var/shuttle_spawned = FALSE /datum/round_event/pirates/setup() ship_name = pick(strings(PIRATE_NAMES_FILE, "ship_names")) /datum/round_event/pirates/announce(fake) priority_announce("A business proposition has been downloaded and printed out at all communication consoles.", "Incoming Business Proposition", "commandreport") if(fake) return threat_message = new var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) if(D) payoff = round(D.account_balance * 0.80) threat_message.title = "Business proposition" threat_message.content = "This is [ship_name]. Pay up [payoff] credits or you'll walk the plank." threat_message.possible_answers = list("We'll pay.","No way.") threat_message.answer_callback = CALLBACK(src,.proc/answered) SScommunications.send_message(threat_message,unique = TRUE) /datum/round_event/pirates/proc/answered() if(threat_message && threat_message.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) paid_off = TRUE return else priority_announce("Trying to cheat us? You'll regret this!",sender_override = ship_name) if(!shuttle_spawned) priority_announce("You won't listen to reason? Then we'll take what's yours or die trying!",sender_override = ship_name) spawn_shuttle() /datum/round_event/pirates/start() if(!paid_off && !shuttle_spawned) spawn_shuttle() /datum/round_event/pirates/proc/spawn_shuttle() shuttle_spawned = TRUE var/list/candidates = pollGhostCandidates("Do you wish to be considered for pirate crew?", ROLE_TRAITOR) shuffle_inplace(candidates) if(!SSmapping.empty_space) SSmapping.empty_space = SSmapping.add_new_zlevel("Empty Area For Pirates", list(ZTRAIT_LINKAGE = SELFLOOPING)) var/datum/map_template/shuttle/pirate/default/ship = new 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/M = candidates[1] spawner.create(M.ckey) candidates -= M announce_to_ghosts(M) else announce_to_ghosts(spawner) priority_announce("Unidentified 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() if(active) icon_state = "dominator-blue" else icon_state = "dominator" /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" resistance_flags = INDESTRUCTIBLE light_color = LIGHT_COLOR_RED 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" resistance_flags = INDESTRUCTIBLE lock_override = CAMERA_LOCK_STATION shuttlePortId = "pirateship_custom" x_offset = 9 y_offset = 0 see_hidden = FALSE /obj/docking_port/mobile/pirate name = "pirate shuttle" id = "pirateship" var/engines_cooling = FALSE var/engine_cooldown = 3 MINUTES /obj/docking_port/mobile/pirate/getStatusText() . = ..() if(engines_cooling) return "[.] - Engines cooling." /obj/docking_port/mobile/pirate/initiate_docking(obj/docking_port/stationary/new_dock, movement_direction, force=FALSE) . = ..() if(. == DOCKING_SUCCESS && !is_reserved_level(new_dock.z)) engines_cooling = TRUE addtimer(CALLBACK(src,.proc/reset_cooldown),engine_cooldown,TIMER_UNIQUE) /obj/docking_port/mobile/pirate/proc/reset_cooldown() engines_cooling = FALSE /obj/docking_port/mobile/pirate/canMove() if(engines_cooling) return FALSE return ..() /obj/machinery/suit_storage_unit/pirate suit_type = /obj/item/clothing/suit/space helmet_type = /obj/item/clothing/head/helmet/space mask_type = /obj/item/clothing/mask/breath storage_type = /obj/item/tank/jetpack/void /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" resistance_flags = INDESTRUCTIBLE 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-o" resistance_flags = INDESTRUCTIBLE var/idle_state = "lpad-idle-o" 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/computer/piratepad_control name = "cargo hold control terminal" resistance_flags = INDESTRUCTIBLE ui_x = 600 ui_y = 230 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 /obj/machinery/computer/piratepad_control/Initialize() ..() 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 = 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 = P return else pad = locate() in range(4,src) /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 ? 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) 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 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 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] 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() 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() if(!sending) return sending = FALSE status_report = "Idle" 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