[fugitives.len] [fugitives.len == 1 ? "fugitive" : "fugitives"] took refuge on [station_name()]!"
-
- for(var/datum/antagonist/fugitive/antag in fugitives)
- if(antag.owner)
- result += "
[printplayer(antag.owner)]"
-
- return result.Join("
")
diff --git a/code/modules/antagonists/fugitive/fugitive_outfits.dm b/code/modules/antagonists/fugitive/fugitive_outfits.dm
index 068117698ff8..be343bb8bc6e 100644
--- a/code/modules/antagonists/fugitive/fugitive_outfits.dm
+++ b/code/modules/antagonists/fugitive/fugitive_outfits.dm
@@ -152,7 +152,3 @@
ears = /obj/item/radio/headset
id = /obj/item/card/id
r_hand = /obj/item/storage/firstaid/regular
-
- backpack_contents = list(
- /obj/item/bountytrap = 4
- )
diff --git a/code/modules/antagonists/fugitive/fugitive_ship.dm b/code/modules/antagonists/fugitive/fugitive_ship.dm
deleted file mode 100644
index 26d8f42e94b9..000000000000
--- a/code/modules/antagonists/fugitive/fugitive_ship.dm
+++ /dev/null
@@ -1,47 +0,0 @@
-//works similar to the experiment machine (experiment.dm) except it just holds more and more prisoners
-
-/obj/machinery/fugitive_capture
- name = "bluespace capture machine"
- desc = "Much, MUCH bigger on the inside to transport prisoners safely."
- icon = 'icons/obj/machines/research.dmi'
- icon_state = "bluespace-prison"
- density = TRUE
- resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF //ha ha no getting out!!
-
-/obj/machinery/fugitive_capture/examine(mob/user)
- . = ..()
- . += "
Add a prisoner by dragging them into the machine."
-
-/obj/machinery/fugitive_capture/MouseDrop_T(mob/target, mob/user)
- var/mob/living/fugitive_hunter = user
- if(!isliving(fugitive_hunter))
- return
- if(HAS_TRAIT(fugitive_hunter, TRAIT_UI_BLOCKED) || !Adjacent(fugitive_hunter) || !target.Adjacent(fugitive_hunter) || !ishuman(target))
- return
- var/mob/living/carbon/human/fugitive = target
- var/datum/antagonist/fugitive/fug_antag = fugitive.mind.has_antag_datum(/datum/antagonist/fugitive)
- if(!fug_antag)
- to_chat(fugitive_hunter, "
This is not a wanted fugitive!")
- return
- if(do_after(fugitive_hunter, 50, target = fugitive))
- add_prisoner(fugitive, fug_antag)
-
-/obj/machinery/fugitive_capture/proc/add_prisoner(mob/living/carbon/human/fugitive, datum/antagonist/fugitive/antag)
- fugitive.forceMove(src)
- antag.is_captured = TRUE
- to_chat(fugitive, "
You are thrown into a vast void of bluespace, and as you fall further into oblivion the comparatively small entrance to reality gets smaller and smaller until you cannot see it anymore. You have failed to avoid capture.")
- fugitive.ghostize(TRUE) //so they cannot suicide, round end stuff.
-
-/obj/structure/closet/crate/eva
- name = "EVA crate"
-
-/obj/structure/closet/crate/eva/PopulateContents()
- ..()
- for(var/i in 1 to 3)
- new /obj/item/clothing/suit/space/eva(src)
- for(var/i in 1 to 3)
- new /obj/item/clothing/head/helmet/space/eva(src)
- for(var/i in 1 to 3)
- new /obj/item/clothing/mask/breath(src)
- for(var/i in 1 to 3)
- new /obj/item/tank/internals/oxygen(src)
diff --git a/code/modules/antagonists/fugitive/hunter.dm b/code/modules/antagonists/fugitive/hunter.dm
deleted file mode 100644
index 090b243e5310..000000000000
--- a/code/modules/antagonists/fugitive/hunter.dm
+++ /dev/null
@@ -1,172 +0,0 @@
-//The hunters!!
-/datum/antagonist/fugitive_hunter
- name = "Fugitive Hunter"
- roundend_category = "Fugitive"
- silent = TRUE //greet called by the spawn
- show_in_antagpanel = FALSE
- prevent_roundtype_conversion = FALSE
- antag_hud_type = ANTAG_HUD_FUGITIVE
- antag_hud_name = "fugitive_hunter"
- var/datum/team/fugitive_hunters/hunter_team
- var/backstory = "error"
-
-/datum/antagonist/fugitive_hunter/apply_innate_effects(mob/living/mob_override)
- var/mob/living/M = mob_override || owner.current
- add_antag_hud(antag_hud_type, antag_hud_name, M)
-
-/datum/antagonist/fugitive_hunter/remove_innate_effects(mob/living/mob_override)
- var/mob/living/M = mob_override || owner.current
- remove_antag_hud(antag_hud_type, M)
-
-/datum/antagonist/fugitive_hunter/on_gain()
- forge_objectives()
- . = ..()
-
-/datum/antagonist/fugitive_hunter/proc/forge_objectives() //this isn't an actual objective because it's about round end rosters
- var/datum/objective/capture = new /datum/objective
- capture.owner = owner
- capture.explanation_text = "Capture the fugitives in the station and put them into the bluespace capture machine on your ship."
- objectives += capture
-
-/datum/antagonist/fugitive_hunter/greet()
- switch(backstory)
- if("space cop")
- to_chat(owner, "
Justice has arrived. I am a member of the Spacepol!")
- to_chat(owner, "
The criminals should be on the station, we have special huds implanted to recognize them.")
- to_chat(owner, "
As we have lost pretty much all power over these damned lawless megacorporations, it's a mystery if their security will cooperate with us.")
- if("russian")
- to_chat(src, "
Ay blyat. I am a space-russian smuggler! We were mid-flight when our cargo was beamed off our ship!")
- to_chat(src, "
We were hailed by a man in a green uniform, promising the safe return of our goods in exchange for a favor:")
- to_chat(src, "
There is a local station housing fugitives that the man is after, he wants them returned; dead or alive.")
- to_chat(src, "
We will not be able to make ends meet without our cargo, so we must do as he says and capture them.")
-
- to_chat(owner, "
You are not an antagonist in that you may kill whomever you please, but you can do anything to ensure the capture of the fugitives, even if that means going through the station.")
- owner.announce_objectives()
-
-/datum/antagonist/fugitive_hunter/create_team(datum/team/fugitive_hunters/new_team)
- if(!new_team)
- for(var/datum/antagonist/fugitive_hunter/H in GLOB.antagonists)
- if(!H.owner)
- continue
- if(H.hunter_team)
- hunter_team = H.hunter_team
- return
- hunter_team = new /datum/team/fugitive_hunters
- hunter_team.backstory = backstory
- hunter_team.update_objectives()
- return
- if(!istype(new_team))
- stack_trace("Wrong team type passed to [type] initialization.")
- hunter_team = new_team
-
-/datum/antagonist/fugitive_hunter/get_team()
- return hunter_team
-
-/datum/team/fugitive_hunters
- var/backstory = "error"
-
-/datum/team/fugitive_hunters/proc/update_objectives(initial = FALSE)
- objectives = list()
- var/datum/objective/O = new()
- O.team = src
- objectives += O
-
-/datum/team/fugitive_hunters/proc/assemble_fugitive_results()
- var/list/fugitives_counted = list()
- var/list/fugitives_dead = list()
- var/list/fugitives_captured = list()
- for(var/datum/antagonist/fugitive/A in GLOB.antagonists)
- if(!A.owner)
- continue
- fugitives_counted += A
- if(A.owner.current.stat == DEAD)
- fugitives_dead += A
- if(A.is_captured)
- fugitives_captured += A
- . = list(fugitives_counted, fugitives_dead, fugitives_captured) //okay, check out how cool this is.
-
-/datum/team/fugitive_hunters/proc/all_hunters_dead()
- var/dead_boys = 0
- for(var/I in members)
- var/datum/mind/hunter_mind = I
- if(!(ishuman(hunter_mind.current) || (hunter_mind.current.stat == DEAD)))
- dead_boys++
- return dead_boys >= members.len
-
-/datum/team/fugitive_hunters/proc/get_result()
- var/list/fugitive_results = assemble_fugitive_results()
- var/list/fugitives_counted = fugitive_results[1]
- var/list/fugitives_dead = fugitive_results[2]
- var/list/fugitives_captured = fugitive_results[3]
- var/hunters_dead = all_hunters_dead()
- //this gets a little confusing so follow the comments if it helps
- if(!fugitives_counted.len)
- return
- if(fugitives_captured.len)//any captured
- if(fugitives_captured.len == fugitives_counted.len)//if the hunters captured all the fugitives, there's a couple special wins
- if(!fugitives_dead)//specifically all of the fugitives alive
- return FUGITIVE_RESULT_BADASS_HUNTER
- else if(hunters_dead)//specifically all of the hunters died (while capturing all the fugitives)
- return FUGITIVE_RESULT_POSTMORTEM_HUNTER
- else//no special conditional wins, so just the normal major victory
- return FUGITIVE_RESULT_MAJOR_HUNTER
- else if(!hunters_dead)//so some amount captured, and the hunters survived.
- return FUGITIVE_RESULT_HUNTER_VICTORY
- else//so some amount captured, but NO survivors.
- return FUGITIVE_RESULT_MINOR_HUNTER
- else//from here on out, hunters lost because they did not capture any fugitive dead or alive. there are different levels of getting beat though:
- if(!fugitives_dead)//all fugitives survived
- return FUGITIVE_RESULT_MAJOR_FUGITIVE
- else if(fugitives_dead < fugitives_counted)//at least ANY fugitive lived
- return FUGITIVE_RESULT_FUGITIVE_VICTORY
- else if(!hunters_dead)//all fugitives died, but none were taken in by the hunters. minor win
- return FUGITIVE_RESULT_MINOR_FUGITIVE
- else//all fugitives died, all hunters died, nobody brought back. seems weird to not give fugitives a victory if they managed to kill the hunters but literally no progress to either goal should lead to a nobody wins situation
- return FUGITIVE_RESULT_STALEMATE
-
-/datum/team/fugitive_hunters/roundend_report() //shows the number of fugitives, but not if they won in case there is no security
- if(!members.len)
- return
-
- var/list/result = list()
-
- result += "
...And [members.len] [backstory]s tried to hunt them down!"
-
- for(var/datum/mind/M in members)
- result += "[printplayer(M)]"
-
- switch(get_result())
- if(FUGITIVE_RESULT_BADASS_HUNTER)//use defines
- result += "Badass [capitalize(backstory)] Victory!"
- result += "The [backstory]s managed to capture every fugitive, alive!"
- if(FUGITIVE_RESULT_POSTMORTEM_HUNTER)
- result += "Postmortem [capitalize(backstory)] Victory!"
- result += "The [backstory]s managed to capture every fugitive, but all of them died! Spooky!"
- if(FUGITIVE_RESULT_MAJOR_HUNTER)
- result += "Major [capitalize(backstory)] Victory"
- result += "The [backstory]s managed to capture every fugitive, dead or alive."
- if(FUGITIVE_RESULT_HUNTER_VICTORY)
- result += "[capitalize(backstory)] Victory"
- result += "The [backstory]s managed to capture a fugitive, dead or alive."
- if(FUGITIVE_RESULT_MINOR_HUNTER)
- result += "Minor [capitalize(backstory)] Victory"
- result += "All the [backstory]s died, but managed to capture a fugitive, dead or alive."
- if(FUGITIVE_RESULT_STALEMATE)
- result += "Bloody Stalemate"
- result += "Everyone died, and no fugitives were recovered!"
- if(FUGITIVE_RESULT_MINOR_FUGITIVE)
- result += "Minor Fugitive Victory"
- result += "All the fugitives died, but none were recovered!"
- if(FUGITIVE_RESULT_FUGITIVE_VICTORY)
- result += "Fugitive Victory"
- result += "A fugitive survived, and no bodies were recovered by the [backstory]s."
- if(FUGITIVE_RESULT_MAJOR_FUGITIVE)
- result += "Major Fugitive Victory"
- result += "All of the fugitives survived and avoided capture!"
- else //get_result returned null- either bugged or no fugitives showed
- result += "Prank Call!"
- result += "[capitalize(backstory)]s were called, yet there were no fugitives...?"
-
- result += "
"
-
- return result.Join("
")
diff --git a/code/modules/antagonists/pirate/pirate.dm b/code/modules/antagonists/pirate/pirate.dm
deleted file mode 100644
index 91bc063869a7..000000000000
--- a/code/modules/antagonists/pirate/pirate.dm
+++ /dev/null
@@ -1,108 +0,0 @@
-/datum/antagonist/pirate
- name = "Space Pirate"
- job_rank = ROLE_TRAITOR
- roundend_category = "space pirates"
- antagpanel_category = "Pirate"
- show_to_ghosts = TRUE
- var/datum/team/pirate/crew
-
-/datum/antagonist/pirate/greet()
- to_chat(owner, "
You are a Space Pirate!")
- to_chat(owner, "
The station refused to pay for your protection, protect the ship, siphon the credits from the station and raid it for even more loot.")
- owner.announce_objectives()
-
-/datum/antagonist/pirate/get_team()
- return crew
-
-/datum/antagonist/pirate/create_team(datum/team/pirate/new_team)
- if(!new_team)
- for(var/datum/antagonist/pirate/P in GLOB.antagonists)
- if(!P.owner)
- continue
- if(P.crew)
- crew = P.crew
- return
- if(!new_team)
- crew = new /datum/team/pirate
- crew.forge_objectives()
- return
- if(!istype(new_team))
- stack_trace("Wrong team type passed to [type] initialization.")
- crew = new_team
-
-/datum/antagonist/pirate/on_gain()
- if(crew)
- objectives |= crew.objectives
- . = ..()
-
-/datum/team/pirate
- name = "Pirate crew"
-
-/datum/team/pirate/proc/forge_objectives()
- var/datum/objective/loot/getbooty = new()
- getbooty.team = src
- for(var/obj/machinery/computer/piratepad_control/P in GLOB.machines)
- var/area/A = get_area(P)
- if(istype(A,/area/shuttle/pirate))
- getbooty.cargo_hold = P
- break
- getbooty.update_explanation_text()
- objectives += getbooty
- for(var/datum/mind/M in members)
- var/datum/antagonist/pirate/P = M.has_antag_datum(/datum/antagonist/pirate)
- if(P)
- P.objectives |= objectives
-
-
-/datum/objective/loot
- var/obj/machinery/computer/piratepad_control/cargo_hold
- explanation_text = "Acquire valuable loot and store it in designated area."
- var/target_value = 50000
-
-
-/datum/objective/loot/update_explanation_text()
- if(cargo_hold)
- var/area/storage_area = get_area(cargo_hold)
- explanation_text = "Acquire loot and store [target_value] of credits worth in [storage_area.name] cargo hold."
-
-/datum/objective/loot/proc/loot_listing()
- //Lists notable loot.
- if(!cargo_hold || !cargo_hold.total_report)
- return "Nothing"
- cargo_hold.total_report.total_value = sortTim(cargo_hold.total_report.total_value, cmp = /proc/cmp_numeric_dsc, associative = TRUE)
- var/count = 0
- var/list/loot_texts = list()
- for(var/datum/export/E in cargo_hold.total_report.total_value)
- if(++count > 5)
- break
- loot_texts += E.total_printout(cargo_hold.total_report,notes = FALSE)
- return loot_texts.Join(", ")
-
-/datum/objective/loot/proc/get_loot_value()
- return cargo_hold ? cargo_hold.points : 0
-
-/datum/objective/loot/check_completion()
- return ..() || get_loot_value() >= target_value
-
-/datum/team/pirate/roundend_report()
- var/list/parts = list()
-
- parts += ""
-
- var/all_dead = TRUE
- for(var/datum/mind/M in members)
- if(considered_alive(M))
- all_dead = FALSE
- parts += printplayerlist(members)
-
- parts += "Loot stolen: "
- var/datum/objective/loot/L = locate() in objectives
- parts += L.loot_listing()
- parts += "Total loot value : [L.get_loot_value()]/[L.target_value] credits"
-
- if(L.check_completion() && !all_dead)
- parts += "
The pirate crew was successful!"
- else
- parts += "
The pirate crew has failed."
-
- return "
[parts.Join("
")]
"
diff --git a/code/modules/events/fugitive_spawning.dm b/code/modules/events/fugitive_spawning.dm
deleted file mode 100644
index 8cf295310282..000000000000
--- a/code/modules/events/fugitive_spawning.dm
+++ /dev/null
@@ -1,112 +0,0 @@
-/datum/round_event_control/fugitives
- name = "Spawn Fugitives"
- typepath = /datum/round_event/ghost_role/fugitives
- max_occurrences = 1
- min_players = 20
- earliest_start = 30 MINUTES //deadchat sink, lets not even consider it early on.
- gamemode_blacklist = list("nuclear")
-
-/datum/round_event/ghost_role/fugitives
- minimum_required = 1
- role_name = "fugitive"
- fakeable = FALSE
-
-/datum/round_event/ghost_role/fugitives/spawn_role()
- var/list/possible_spawns = list()//Some xeno spawns are in some spots that will instantly kill the refugees, like atmos
- for(var/turf/X in GLOB.xeno_spawn)
- if(istype(X.loc, /area/ship/maintenance))
- possible_spawns += X
- if(!possible_spawns.len)
- message_admins("No valid spawn locations found, aborting...")
- return MAP_ERROR
- var/turf/landing_turf = pick(possible_spawns)
- var/list/possible_backstories = list()
- var/list/candidates = get_candidates(ROLE_TRAITOR, null, ROLE_TRAITOR)
- if(candidates.len >= 1) //solo refugees
- if(prob(30))
- possible_backstories.Add("waldo") //less common as it comes with magicks and is kind of immershun shattering
- else //For accurate deadchat feedback
- minimum_required = 4
- if(candidates.len >= 4)//group refugees
- possible_backstories.Add("prisoner", "cultist", "synth")
- if(!possible_backstories.len)
- return NOT_ENOUGH_PLAYERS
-
- var/backstory = pick(possible_backstories)
- var/member_size = 3
- var/leader
- switch(backstory)
- if("synth")
- leader = pick_n_take(candidates)
- if("waldo")
- member_size = 0 //solo refugees have no leader so the member_size gets bumped to one a bit later
- var/list/members = list()
- var/list/spawned_mobs = list()
- if(isnull(leader))
- member_size++ //if there is no leader role, then the would be leader is a normal member of the team.
-
- for(var/i in 1 to member_size)
- members += pick_n_take(candidates)
-
- for(var/mob/dead/selected in members)
- var/mob/living/carbon/human/S = gear_fugitive(selected, landing_turf, backstory)
- spawned_mobs += S
- if(!isnull(leader))
- gear_fugitive_leader(leader, landing_turf, backstory)
-
-//after spawning
- playsound(src, 'sound/weapons/emitter.ogg', 50, TRUE)
- new /obj/item/storage/toolbox/mechanical(landing_turf) //so they can actually escape maint
- addtimer(CALLBACK(src, .proc/spawn_hunters), 10 MINUTES)
- role_name = "fugitive hunter"
- return SUCCESSFUL_SPAWN
-
-/datum/round_event/ghost_role/fugitives/proc/gear_fugitive(mob/dead/selected, turf/landing_turf, backstory) //spawns normal fugitive
- var/datum/mind/player_mind = new /datum/mind(selected.key)
- player_mind.active = TRUE
- var/mob/living/carbon/human/S = new(landing_turf)
- player_mind.transfer_to(S)
- player_mind.assigned_role = "Fugitive"
- player_mind.special_role = "Fugitive"
- player_mind.add_antag_datum(/datum/antagonist/fugitive)
- var/datum/antagonist/fugitive/fugitiveantag = player_mind.has_antag_datum(/datum/antagonist/fugitive)
- INVOKE_ASYNC(fugitiveantag, /datum/antagonist/fugitive.proc/greet, backstory) //some fugitives have a sleep on their greet, so we don't want to stop the entire antag granting proc with fluff
-
- switch(backstory)
- if("prisoner")
- S.equipOutfit(/datum/outfit/prisoner)
- if("cultist")
- S.equipOutfit(/datum/outfit/yalp_cultist)
- if("waldo")
- S.equipOutfit(/datum/outfit/waldo)
- if("synth")
- S.equipOutfit(/datum/outfit/synthetic)
- message_admins("[ADMIN_LOOKUPFLW(S)] has been made into a Fugitive by an event.")
- log_game("[key_name(S)] was spawned as a Fugitive by an event.")
- spawned_mobs += S
- return S
-
-//special spawn for one member. it can be used for a special mob or simply to give one normal member special items.
-/datum/round_event/ghost_role/fugitives/proc/gear_fugitive_leader(mob/dead/leader, turf/landing_turf, backstory)
- var/datum/mind/player_mind = new /datum/mind(leader.key)
- player_mind.active = TRUE
- //if you want to add a fugitive with a special leader in the future, make this switch with the backstory
- var/mob/living/carbon/human/S = gear_fugitive(leader, landing_turf, backstory)
- var/obj/item/choice_beacon/augments/A = new(S)
- S.put_in_hands(A)
- new /obj/item/autosurgeon(landing_turf)
-
-//security team gets called in after 10 minutes of prep to find the refugees
-/datum/round_event/ghost_role/fugitives/proc/spawn_hunters()
- var/backstory = pick( "russian", "bounty hunter")
- var/datum/map_template/shuttle/template
- if (backstory == "russian")
- template = new /datum/map_template/shuttle/hunter/russian
- else
- template = new /datum/map_template/shuttle/hunter/bounty
-
- var/datum/overmap/ship/controlled/ship = new(SSovermap.get_unused_overmap_square(), template)
-
- if(!ship)
- CRASH("Loading [backstory] ship failed!")
- priority_announce("Unidentified ship detected near the station.")
diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm
deleted file mode 100644
index 186922c76a8f..000000000000
--- a/code/modules/events/pirates.dm
+++ /dev/null
@@ -1,324 +0,0 @@
-/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/pirates
- startWhen = 60 //2 minutes to answer
- var/datum/comm_message/threat
- var/payoff = 0
- var/payoff_min = 20000
- 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("Incoming subspace communication. Secure channel opened at all communication consoles.", "Incoming Message", 'sound/ai/commandreport.ogg')
- if(fake)
- return
- threat = new
- var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
- if(D)
- payoff = max(payoff_min, FLOOR(D.account_balance * 0.80, 1000))
- threat.title = "Business proposition"
- threat.content = "This is [ship_name]. Pay up [payoff] credits or you'll walk the plank."
- threat.possible_answers = list("We'll pay.","No way.")
- threat.answer_callback = CALLBACK(src,.proc/answered)
- SScommunications.send_message(threat,unique = TRUE)
-
-/datum/round_event/pirates/proc/answered()
- if(threat && threat.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)
- spawn_shuttle()
- else
- priority_announce("Too late to beg for mercy!",sender_override = ship_name)
-
-/datum/round_event/pirates/start()
- if(threat && !threat.answered)
- threat.possible_answers = list("Too late")
- threat.answered = 1
- 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)
-
- var/datum/map_template/shuttle/pirate/default/template = new
- var/datum/overmap/ship/controlled/ship = new(SSovermap.get_unused_overmap_square(), template)
-
- if(!ship)
- CRASH("Loading pirate ship failed!")
-
- for(var/turf/A in ship.shuttle_port.return_turfs())
- 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 armed ship detected near the station.")
-
-/obj/docking_port/mobile/pirate
- name = "pirate shuttle"
- rechargeTime = 3 MINUTES
-
-/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/internals/oxygen
-
-/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-o"
- 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"
- icon_screen = "bounty"
- 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 = "Ready for delivery."
- 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/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/cash
- cost = 1
- unit_name = "bills"
- export_types = list(/obj/item/spacecash/bundle)
-
-/datum/export/pirate/cash/get_amount(obj/O)
- var/obj/item/spacecash/bundle/C = O
- return ..() * 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
diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
index 4d97ff8fdcd1..4de55c4264af 100644
--- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
@@ -365,8 +365,8 @@ All effects don't start immediately, but rather get worse over time; the rate is
shot_glass_icon_state = "shotglassred"
/datum/reagent/consumable/ethanol/lizardwine
- name = "lizard wine"
- description = "An alcoholic beverage from Space China, made by infusing lizard tails in ethanol."
+ name = "Kalixcis Wine"
+ description = "A relatively popular Kalixcane beverage, made by infusing cacti in ethanol."
color = "#7E4043" // rgb: 126, 64, 67
boozepwr = 45
quality = DRINK_FANTASTIC
diff --git a/code/modules/research/designs/limbgrower_designs.dm b/code/modules/research/designs/limbgrower_designs.dm
index 4f48995190dc..16bf2a9241cb 100644
--- a/code/modules/research/designs/limbgrower_designs.dm
+++ b/code/modules/research/designs/limbgrower_designs.dm
@@ -116,7 +116,7 @@
build_path = /obj/item/organ/tongue
category = list("initial",SPECIES_HUMAN)
-// Grows a fake lizard tail - not usable in lizard wine and other similar recipes.
+// Grows a fake lizard tail
/datum/design/lizard_tail
name = "Lizard Tail"
id = "liztail"
diff --git a/code/modules/surgery/organs/tails.dm b/code/modules/surgery/organs/tails.dm
index f587a26d8404..2d3e402150a2 100644
--- a/code/modules/surgery/organs/tails.dm
+++ b/code/modules/surgery/organs/tails.dm
@@ -83,7 +83,7 @@
/obj/item/organ/tail/lizard/fake
name = "fabricated lizard tail"
- desc = "A fabricated severed lizard tail. This one's made of synthflesh. Probably not usable for lizard wine."
+ desc = "A fabricated severed lizard tail. This one's made of synthflesh."
/obj/item/organ/tail/elzu
name = "\improper Elzuose tail"
diff --git a/code/modules/tgs/core/core.dm b/code/modules/tgs/core/core.dm
index 41a047339452..b9a9f27a28ae 100644
--- a/code/modules/tgs/core/core.dm
+++ b/code/modules/tgs/core/core.dm
@@ -153,4 +153,9 @@
/world/TgsSecurityLevel()
var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
if(api)
- api.SecurityLevel()
+ return api.SecurityLevel()
+
+/world/TgsVisibility()
+ var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs)
+ if(api)
+ return api.Visibility()
diff --git a/code/modules/tgs/core/datum.dm b/code/modules/tgs/core/datum.dm
index 68b0330fe860..de420a2a325a 100644
--- a/code/modules/tgs/core/datum.dm
+++ b/code/modules/tgs/core/datum.dm
@@ -11,6 +11,10 @@ TGS_DEFINE_AND_SET_GLOBAL(tgs, null)
src.event_handler = event_handler
src.version = version
+/datum/tgs_api/proc/TerminateWorld()
+ del(world)
+ sleep(1) // https://www.byond.com/forum/post/2894866
+
/datum/tgs_api/latest
parent_type = /datum/tgs_api/v5
@@ -57,3 +61,6 @@ TGS_PROTECT_DATUM(/datum/tgs_api)
/datum/tgs_api/proc/SecurityLevel()
return TGS_UNIMPLEMENTED
+
+/datum/tgs_api/proc/Visibility()
+ return TGS_UNIMPLEMENTED
diff --git a/code/modules/tgs/v4/api.dm b/code/modules/tgs/v4/api.dm
index b9a75c4abb48..945e2e411767 100644
--- a/code/modules/tgs/v4/api.dm
+++ b/code/modules/tgs/v4/api.dm
@@ -73,7 +73,7 @@
if(cached_json["apiValidateOnly"])
TGS_INFO_LOG("Validating API and exiting...")
Export(TGS4_COMM_VALIDATE, list(TGS4_PARAMETER_DATA = "[minimum_required_security_level]"))
- del(world)
+ TerminateWorld()
security_level = cached_json["securityLevel"]
chat_channels_json_path = cached_json["chatChannelsJson"]
@@ -188,7 +188,7 @@
requesting_new_port = TRUE
if(!world.OpenPort(0)) //open any port
TGS_ERROR_LOG("Unable to open random port to retrieve new port![TGS4_PORT_CRITFAIL_MESSAGE]")
- del(world)
+ TerminateWorld()
//request a new port
export_lock = FALSE
@@ -196,16 +196,16 @@
if(!new_port_json)
TGS_ERROR_LOG("No new port response from server![TGS4_PORT_CRITFAIL_MESSAGE]")
- del(world)
+ TerminateWorld()
var/new_port = new_port_json[TGS4_PARAMETER_DATA]
if(!isnum(new_port) || new_port <= 0)
TGS_ERROR_LOG("Malformed new port json ([json_encode(new_port_json)])![TGS4_PORT_CRITFAIL_MESSAGE]")
- del(world)
+ TerminateWorld()
if(new_port != world.port && !world.OpenPort(new_port))
TGS_ERROR_LOG("Unable to open port [new_port]![TGS4_PORT_CRITFAIL_MESSAGE]")
- del(world)
+ TerminateWorld()
requesting_new_port = FALSE
while(export_lock)
diff --git a/code/modules/tgs/v5/__interop_version.dm b/code/modules/tgs/v5/__interop_version.dm
index 5d3d491a7362..1b52b31d6a73 100644
--- a/code/modules/tgs/v5/__interop_version.dm
+++ b/code/modules/tgs/v5/__interop_version.dm
@@ -1 +1 @@
-"5.6.1"
+"5.6.2"
diff --git a/code/modules/tgs/v5/_defines.dm b/code/modules/tgs/v5/_defines.dm
index f973338daa03..bdcd4e4dd58e 100644
--- a/code/modules/tgs/v5/_defines.dm
+++ b/code/modules/tgs/v5/_defines.dm
@@ -48,6 +48,7 @@
#define DMAPI5_RUNTIME_INFORMATION_REVISION "revision"
#define DMAPI5_RUNTIME_INFORMATION_TEST_MERGES "testMerges"
#define DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL "securityLevel"
+#define DMAPI5_RUNTIME_INFORMATION_VISIBILITY "visibility"
#define DMAPI5_CHAT_UPDATE_CHANNELS "channels"
diff --git a/code/modules/tgs/v5/api.dm b/code/modules/tgs/v5/api.dm
index 34cc43f8762f..7226f29bba60 100644
--- a/code/modules/tgs/v5/api.dm
+++ b/code/modules/tgs/v5/api.dm
@@ -4,6 +4,7 @@
var/instance_name
var/security_level
+ var/visibility
var/reboot_mode = TGS_REBOOT_MODE_NORMAL
@@ -50,10 +51,11 @@
if(runtime_information[DMAPI5_RUNTIME_INFORMATION_API_VALIDATE_ONLY])
TGS_INFO_LOG("DMAPI validation, exiting...")
- del(world)
+ TerminateWorld()
version = new /datum/tgs_version(runtime_information[DMAPI5_RUNTIME_INFORMATION_SERVER_VERSION])
security_level = runtime_information[DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL]
+ visibility = runtime_information[DMAPI5_RUNTIME_INFORMATION_VISIBILITY]
instance_name = runtime_information[DMAPI5_RUNTIME_INFORMATION_INSTANCE_NAME]
var/list/revisionData = runtime_information[DMAPI5_RUNTIME_INFORMATION_REVISION]
@@ -252,3 +254,7 @@
/datum/tgs_api/v5/SecurityLevel()
RequireInitialBridgeResponse()
return security_level
+
+/datum/tgs_api/v5/Visibility()
+ RequireInitialBridgeResponse()
+ return visibility
diff --git a/code/modules/tgs/v5/undefs.dm b/code/modules/tgs/v5/undefs.dm
index c679737dfc49..f163adaaafe3 100644
--- a/code/modules/tgs/v5/undefs.dm
+++ b/code/modules/tgs/v5/undefs.dm
@@ -48,6 +48,7 @@
#undef DMAPI5_RUNTIME_INFORMATION_REVISION
#undef DMAPI5_RUNTIME_INFORMATION_TEST_MERGES
#undef DMAPI5_RUNTIME_INFORMATION_SECURITY_LEVEL
+#undef DMAPI5_RUNTIME_INFORMATION_VISIBILITY
#undef DMAPI5_CHAT_UPDATE_CHANNELS
diff --git a/icons/obj/lighting.dmi b/icons/obj/lighting.dmi
index 25a990b61d01..ae86489bb340 100644
Binary files a/icons/obj/lighting.dmi and b/icons/obj/lighting.dmi differ
diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi
index d779a15bc717..ff211d21d5c2 100644
Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ
diff --git a/shiptest.dme b/shiptest.dme
index 1e00ac6238c5..f603da984043 100644
--- a/shiptest.dme
+++ b/shiptest.dme
@@ -1309,6 +1309,7 @@
#include "code\game\objects\structures\barsigns.dm"
#include "code\game\objects\structures\bedsheet_bin.dm"
#include "code\game\objects\structures\catwalk.dm"
+#include "code\game\objects\structures\crateshelf.dm"
#include "code\game\objects\structures\curtains.dm"
#include "code\game\objects\structures\destructible_structures.dm"
#include "code\game\objects\structures\displaycase.dm"
@@ -1665,10 +1666,7 @@
#include "code\modules\antagonists\disease\disease_event.dm"
#include "code\modules\antagonists\disease\disease_mob.dm"
#include "code\modules\antagonists\ert\ert.dm"
-#include "code\modules\antagonists\fugitive\fugitive.dm"
#include "code\modules\antagonists\fugitive\fugitive_outfits.dm"
-#include "code\modules\antagonists\fugitive\fugitive_ship.dm"
-#include "code\modules\antagonists\fugitive\hunter.dm"
#include "code\modules\antagonists\gang\outfits.dm"
#include "code\modules\antagonists\greentext\greentext.dm"
#include "code\modules\antagonists\magic_servant\servant.dm"
@@ -1682,7 +1680,6 @@
#include "code\modules\antagonists\nukeop\equipment\nuclear_challenge.dm"
#include "code\modules\antagonists\nukeop\equipment\nuclearbomb.dm"
#include "code\modules\antagonists\nukeop\equipment\pinpointer.dm"
-#include "code\modules\antagonists\pirate\pirate.dm"
#include "code\modules\antagonists\revenant\revenant.dm"
#include "code\modules\antagonists\revenant\revenant_abilities.dm"
#include "code\modules\antagonists\revenant\revenant_antag.dm"
@@ -2043,7 +2040,6 @@
#include "code\modules\events\electrical_storm.dm"
#include "code\modules\events\fake_virus.dm"
#include "code\modules\events\false_alarm.dm"
-#include "code\modules\events\fugitive_spawning.dm"
#include "code\modules\events\ghost_role.dm"
#include "code\modules\events\grid_check.dm"
#include "code\modules\events\heart_attack.dm"
@@ -2056,7 +2052,6 @@
#include "code\modules\events\meteor_wave.dm"
#include "code\modules\events\nightmare.dm"
#include "code\modules\events\operative.dm"
-#include "code\modules\events\pirates.dm"
#include "code\modules\events\prison_break.dm"
#include "code\modules\events\processor_overload.dm"
#include "code\modules\events\radiation_storm.dm"
diff --git a/tools/requirements.txt b/tools/requirements.txt
index efa47b8a5eae..dbaed6f0260b 100644
--- a/tools/requirements.txt
+++ b/tools/requirements.txt
@@ -1,6 +1,6 @@
pygit2==1.7.2
bidict==0.22.0
-Pillow==10.0.1
+Pillow==9.5.0
# check_regex.py
colorama==0.4.4