bounty app for PDA (#91802)

## About The Pull Request

This PR adds a brand new app to the PDA allowing you to view your
current bounties and even generate new ones.

You can even select a bounty remotely and it will seemlessly work.

The program is not without its own drawbacks. Choosing to reroll your
bounties from the app will always trigger a 5 minute cooldown, and this
cannot be reduced. Meaning that rerolling directly from the bounty
terminal (assuming it has been upgraded) is preferable as an upgraded
bounty pad will give the terminal a shorter cooldown. The cooldown is
shared between the app and the terminal, and depends on where you
initially rerolled it. So if you rerolled it from the app, it will
always be 5 minutes, but if you rerolled it from the terminal, it may be
as low as 2 minutes.

Otherwise it is identical to the way the bounty terminal functions,
minus the fact you cannot actually turn in the bounty using your PDA,
you still have to go to a terminal with connected bounty pad for that!

And in addition to that, in order for the app to work you must have your
ID inside your PDA, the app will not function without it (the top button
will be greyed out, and trying to push one of the options will just give
you a minor error sound)

Size is 5 GQ since that seemed like a good enough size for it.

## Why It's Good For The Game

It always annoyed me that I had to run all the way back to cargo to
check on what my bounties are, and this solves that. It also lets you
reroll your bounties remotely with a punishment of it always having the
default (5 min) waiting period between rerolls.

## Changelog

🆑
add: Adds a new bounty app to the PDA allowing you to remotely check
your bounties
/🆑

![image](https://github.com/user-attachments/assets/b0a10106-1c6d-4f9e-91b1-f95f8cc377cb)

![image](https://github.com/user-attachments/assets/c2cc8075-7314-48b1-a668-e7f8a44bc217)

![image](https://github.com/user-attachments/assets/9536b8cb-8c95-47ed-ba42-2a8d162123c7)

![image](https://github.com/user-attachments/assets/eb254331-35f0-413a-9b74-77c5f9ad6ccb)

---------

Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
This commit is contained in:
plsleavemealon
2025-08-13 14:08:48 -05:00
committed by GitHub
parent 736116b243
commit 574595529f
3 changed files with 251 additions and 0 deletions
@@ -0,0 +1,110 @@
///Everything within this file is an edited form from this file, stripping it of some various components because they are not needed for the PDA app: code/game/machinery/civilian_bounties.dm
///Percentage of a civilian bounty the civilian will make.
#define CIV_BOUNTY_SPLIT 30
/datum/computer_file/program/civilianbounties
filename = "bountyapp"
filedesc = "Civilian Bounties"
downloader_category = PROGRAM_CATEGORY_SUPPLY
program_open_overlay = "request"
extended_desc = "Nanotrasen Civilian Bounty Requisition Network interface for displaying wanted items."
program_flags = PROGRAM_ON_NTNET_STORE | PROGRAM_REQUIRES_NTNET
can_run_on_flags = PROGRAM_LAPTOP | PROGRAM_PDA
size = 5
tgui_id = "NtosCivCargoHoldTerminal"
program_icon = FA_ICON_BOXES_STACKED
var/status_report = "Ready for delivery."
var/points = 0
/datum/computer_file/program/civilianbounties/ui_data(mob/user)
var/list/data = list()
data["points"] = points
data["status_report"] = status_report
data["id_inserted"] = computer.computer_id_slot
if(computer.computer_id_slot?.registered_account)
if(computer.computer_id_slot.registered_account.civilian_bounty)
data["id_bounty_info"] = computer.computer_id_slot.registered_account.civilian_bounty.description
data["id_bounty_num"] = computer.computer_id_slot.registered_account.bounty_num()
data["id_bounty_value"] = (computer.computer_id_slot.registered_account.civilian_bounty.reward) * (CIV_BOUNTY_SPLIT/100)
if(computer.computer_id_slot.registered_account.bounties)
data["picking"] = TRUE
data["id_bounty_names"] = list(computer.computer_id_slot.registered_account.bounties[1].name,
computer.computer_id_slot.registered_account.bounties[2].name,
computer.computer_id_slot.registered_account.bounties[3].name)
data["id_bounty_infos"] = list(computer.computer_id_slot.registered_account.bounties[1].description,
computer.computer_id_slot.registered_account.bounties[2].description,
computer.computer_id_slot.registered_account.bounties[3].description)
data["id_bounty_values"] = list(computer.computer_id_slot.registered_account.bounties[1].reward * (CIV_BOUNTY_SPLIT/100),
computer.computer_id_slot.registered_account.bounties[2].reward * (CIV_BOUNTY_SPLIT/100),
computer.computer_id_slot.registered_account.bounties[3].reward * (CIV_BOUNTY_SPLIT/100))
else
data["picking"] = FALSE
return data
/datum/computer_file/program/civilianbounties/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
var/mob/user = ui.user
switch(action)
if("pick")
pick_bounty(params["value"])
if("bounty")
add_bounties(user, 0)
///Here is where cargo bounties are added to the player's bank accounts, then adjusted and scaled into a civilian bounty.
/datum/computer_file/program/civilianbounties/proc/add_bounties(mob/user, cooldown_reduction = 0)
var/datum/bank_account/id_account = computer.computer_id_slot?.registered_account
if(!id_account)
return
if((id_account.civilian_bounty || id_account.bounties) && !COOLDOWN_FINISHED(id_account, bounty_timer))
var/time_left = DisplayTimeText(COOLDOWN_TIMELEFT(id_account, bounty_timer), round_seconds_to = 1)
computer.balloon_alert(user, "try again in [time_left]!")
return FALSE
if(!id_account.account_job)
computer.say("Requesting ID card has no job assignment registered!")
return FALSE
var/list/datum/bounty/crumbs = generate_bounty_list(id_account.account_job.bounty_types)
COOLDOWN_START(id_account, bounty_timer, (5 MINUTES) - cooldown_reduction)
id_account.bounties = crumbs
/**
* Proc that assigned a civilian bounty to an ID card, from the list of potential bounties that that bank account currently has available.
* Available choices are assigned during add_bounties, and one is locked in here.
*
* @param choice The index of the bounty in the list of bounties that the player can choose from.
*/
/datum/computer_file/program/civilianbounties/proc/pick_bounty(datum/bounty/choice)
var/datum/bank_account/id_account = computer.computer_id_slot?.registered_account
if(!id_account?.bounties?[choice])
playsound(computer.loc, 'sound/machines/synth/synth_no.ogg', 40 , TRUE)
return
id_account.civilian_bounty = id_account.bounties[choice]
id_account.bounties = null
SSblackbox.record_feedback("tally", "bounties_assigned", 1, id_account.civilian_bounty.type)
return id_account.civilian_bounty
/**
* Generates a list of bounties for use with the civilian bounty pad, this is virtually identical to the stuff contained within: code/game/machinery/civilian_bounties.dm
* @param bounty_types the define taken from a job for selection of a random_bounty() proc.
* @param bounty_rolls the number of bounties to be selected from.
* @param assistant_failsafe Do we guarentee one assistant bounty per generated list? Used for non-assistant jobs to give an easier alternative to that job's default bounties.
*/
/datum/computer_file/program/civilianbounties/proc/generate_bounty_list(bounty_types, bounty_rolls = 3, assistant_failsafe = TRUE)
var/list/rolling_list = list()
if(assistant_failsafe)
rolling_list += random_bounty(CIV_JOB_BASIC)
while(bounty_rolls > 1)
var/datum/bounty/potential_bounty = random_bounty(bounty_types)
var/repeats_bool = FALSE
for(var/datum/iterator in rolling_list)
if(iterator.type == potential_bounty.type)
repeats_bool = TRUE
if(repeats_bool)
continue
rolling_list += potential_bounty
bounty_rolls -= 1
return rolling_list
#undef CIV_BOUNTY_SPLIT