Skip to content

Commit

Permalink
Players can no longer open additional job slots (#2824)
Browse files Browse the repository at this point in the history
## Changelog

:cl:
balance: Only admins can open job slots
fix: Cryoing correctly opens a job slot
code: Refactored ShipOwner into tsx
/:cl:

<!-- Both :cl:'s are required for the changelog to work! You can put
your name to the right of the first :cl: if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->
  • Loading branch information
ZephyrTFA authored Mar 12, 2024
1 parent 544135c commit 0da3e66
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 29 deletions.
31 changes: 22 additions & 9 deletions code/game/machinery/cryopod.dm
Original file line number Diff line number Diff line change
Expand Up @@ -303,15 +303,28 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/cryopod/retro, 17)
/obj/machinery/cryopod/proc/despawn_occupant()
var/mob/living/mob_occupant = occupant

if(linked_ship)
if(mob_occupant.job in linked_ship.current_ship.job_slots)
linked_ship.current_ship.job_slots[mob_occupant.job]++

if(mob_occupant.mind && mob_occupant.mind.assigned_role)
//Handle job slot/tater cleanup.
if(LAZYLEN(mob_occupant.mind.objectives))
mob_occupant.mind.objectives.Cut()
mob_occupant.mind.special_role = null
if(!isnull(mob_occupant.mind.original_ship))
var/datum/overmap/ship/controlled/original_ship_instance = mob_occupant.mind.original_ship.resolve()

var/job_identifier = mob_occupant.job

var/datum/job/crew_job
for(var/datum/job/job as anything in original_ship_instance.job_slots)
if(job.name == job_identifier)
crew_job = job
break

if(isnull(crew_job))
message_admins(span_warning("Failed to identify the job of [key_name_admin(mob_occupant)] belonging to [original_ship_instance.name] at [loc_name(src)]."))
else
original_ship_instance.job_slots[crew_job]++
original_ship_instance.job_holder_refs[crew_job] -= WEAKREF(mob_occupant)

if(mob_occupant.mind && mob_occupant.mind.assigned_role)
//Handle job slot/tater cleanup.
if(LAZYLEN(mob_occupant.mind.objectives))
mob_occupant.mind.objectives.Cut()
mob_occupant.mind.special_role = null

// Delete them from datacore.
var/announce_rank = null
Expand Down
11 changes: 10 additions & 1 deletion code/modules/overmap/ships/controlled_ship_datum.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,13 @@
var/list/datum/mission/missions
/// The maximum number of currently active missions that a ship may take on.
var/max_missions = 2
/// Manifest list of people on the ship

/// Manifest list of people on the ship. Indexed by mob REAL NAME. value is JOB INSTANCE
var/list/manifest = list()

/// List of mob refs indexed by their job instance
var/list/datum/weakref/job_holder_refs = list()

var/list/datum/mind/owner_candidates

/// The mob of the current ship owner. Tracking mostly uses this; that lets us pick up on logouts, which let us
Expand Down Expand Up @@ -130,6 +134,7 @@
if(!QDELETED(shipkey))
QDEL_NULL(shipkey)
QDEL_LIST(manifest)
job_holder_refs.Cut()
job_slots.Cut()
blacklisted.Cut()
for(var/a_key in applications)
Expand Down Expand Up @@ -298,6 +303,10 @@
if(!owner_mob)
set_owner_mob(H)

if(!(human_job in job_holder_refs))
job_holder_refs[human_job] = list()
job_holder_refs[human_job] += WEAKREF(H)

/datum/overmap/ship/controlled/proc/set_owner_mob(mob/new_owner)
if(owner_mob)
// we (hopefully) don't have to hook qdeletion,
Expand Down
52 changes: 44 additions & 8 deletions code/modules/overmap/ships/owner_action.dm
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,42 @@
ui = new(user, src, "ShipOwner", name)
ui.open()

/datum/action/ship_owner/proc/allow_job_slot_increase(datum/job/job_target)
var/default_slots = parent_ship.source_template.job_slots[job_target]
var/current_slots = parent_ship.job_slots[job_target]

var/used_slots = 0
var/job_holders = parent_ship.job_holder_refs[job_target]

for(var/datum/weakref/job_holder_ref as anything in job_holders)
var/mob/living/job_holder = job_holder_ref.resolve()
if(isnull(job_holder))
continue

if(job_holder.client)
used_slots += 1
continue

var/mob/dead/observer/job_holder_ghost
for(var/mob/dead/observer/ghost in GLOB.dead_mob_list)
if(ghost.mind == job_holder.mind)
job_holder_ghost = ghost
break
if(!isnull(job_holder_ghost))
used_slots += 1
continue

var/actual_slots = current_slots + used_slots
return actual_slots < default_slots

/datum/action/ship_owner/ui_data(mob/user)
. = list()
.["memo"] = parent_ship.memo
// .["noMemo"] = parent_ship.memo == null || (length(parent_ship.memo) <= 0)
.["pending"] = FALSE
.["joinMode"] = parent_ship.join_mode
.["cooldown"] = COOLDOWN_TIMELEFT(parent_ship, job_slot_adjustment_cooldown)
.["isAdmin"] = !!user.client?.holder
.["applications"] = list()
for(var/a_key as anything in parent_ship.applications)
var/datum/ship_application/app = parent_ship.applications[a_key]
Expand All @@ -85,6 +114,10 @@
text = app.app_msg,
status = app.status
))
var/list/job_increase_allowed = list()
for(var/datum/job/job as anything in parent_ship.job_slots)
job_increase_allowed[job.name] = allow_job_slot_increase(job)
.["jobIncreaseAllowed"] = job_increase_allowed

/datum/action/ship_owner/ui_static_data(mob/user)
. = list()
Expand Down Expand Up @@ -197,18 +230,21 @@
if(!target_job || target_job.officer || !COOLDOWN_FINISHED(parent_ship, job_slot_adjustment_cooldown))
return TRUE

var/change_amount = params["delta"]
if(change_amount > 0 && !allow_job_slot_increase(target_job))
if(!user.client.holder)
to_chat(user, span_warning("You cannot increase the number of slots for this job."))
return TRUE
message_admins("[key_name_admin(user)] has increased the number of slots for [target_job.name] on [parent_ship.name] by [change_amount].")

var/new_amount = parent_ship.job_slots[target_job] + change_amount
var/job_default_slots = parent_ship.source_template.job_slots[target_job]
var/job_max_slots = min(job_default_slots * 2, job_default_slots + 3)
var/new_slots = parent_ship.job_slots[target_job] + params["delta"]
if(new_slots < 0 || new_slots > job_max_slots)
if(new_amount < 0 || new_amount > job_max_slots)
return TRUE

var/cooldown_time = 5 SECONDS
if(params["delta"] > 0 && new_slots > job_default_slots)
cooldown_time = 2 MINUTES
COOLDOWN_START(parent_ship, job_slot_adjustment_cooldown, cooldown_time * cooldown_coeff)

parent_ship.job_slots[target_job] = new_slots
COOLDOWN_START(parent_ship, job_slot_adjustment_cooldown, (5 SECONDS) * cooldown_coeff)
parent_ship.job_slots[target_job] = new_amount
update_static_data(user)
return TRUE

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,40 @@ import {
} from '../components';
import { Window } from '../layouts';

type ShipOwnerData = {
crew: [CrewData];
jobs: [JobData];
jobIncreaseAllowed: [string];
memo: string;
pending: boolean;
joinMode: string;
cooldown: number;
applications: [ApplicationData];
isAdmin: boolean;
};

type ApplicationData = {
ref: string;
key: string;
name: string;
text: string;
status: string;
};

type CrewData = {
ref: string;
name: string;
allowed: boolean;
};

type JobData = {
ref: string;
name: string;
slots: number;
max: number;
def: number;
};

export const ShipOwner = (props, context) => {
return (
<Window width={620} height={620} resizable>
Expand All @@ -19,8 +53,8 @@ export const ShipOwner = (props, context) => {
);
};

const ShipOwnerContent = (props, context) => {
const { act, data } = useBackend(context);
const ShipOwnerContent = (_, context: any) => {
const { act, data } = useBackend<ShipOwnerData>(context);
const [tab, setTab] = useLocalState(context, 'tab', 1);
const {
crew = [],
Expand All @@ -30,6 +64,8 @@ const ShipOwnerContent = (props, context) => {
joinMode,
cooldown = 1,
applications = [],
isAdmin,
jobIncreaseAllowed = [],
} = data;
return (
<Section
Expand Down Expand Up @@ -85,7 +121,7 @@ const ShipOwnerContent = (props, context) => {
<Table.Cell>Message</Table.Cell>
<Table.Cell>Status</Table.Cell>
</Table.Row>
{applications.map((app) => (
{applications.map((app: ApplicationData) => (
<Table.Row key={app.ref}>
<Table.Cell>{app.key}</Table.Cell>
<Table.Cell>{app.name}</Table.Cell>
Expand Down Expand Up @@ -144,16 +180,16 @@ const ShipOwnerContent = (props, context) => {
<Table.Cell>Can be owner</Table.Cell>
<Table.Cell>Transfer Ownership</Table.Cell>
</Table.Row>
{crew.map((mind) => (
<Table.Row key={mind.name}>
<Table.Cell>{mind.name}</Table.Cell>
{crew.map((crew_data: CrewData) => (
<Table.Row key={crew_data.name}>
<Table.Cell>{crew_data.name}</Table.Cell>
<Table.Cell>
<Button.Checkbox
content="Candidate"
checked={mind.allowed}
checked={crew_data.allowed}
onClick={() =>
act('toggleCandidate', {
ref: mind.ref,
ref: crew_data.ref,
})
}
/>
Expand All @@ -163,7 +199,7 @@ const ShipOwnerContent = (props, context) => {
content="Transfer Owner"
onClick={() =>
act('transferOwner', {
ref: mind.ref,
ref: crew_data.ref,
})
}
/>
Expand All @@ -184,13 +220,22 @@ const ShipOwnerContent = (props, context) => {
<Table.Cell>Job Name</Table.Cell>
<Table.Cell>Slots</Table.Cell>
</Table.Row>
{jobs.map((job) => (
{jobs.map((job: JobData) => (
<Table.Row key={job.name}>
<Table.Cell>{job.name}</Table.Cell>
<Table.Cell>
<Button
content="+"
disabled={cooldown > 0 || job.slots >= job.max}
disabled={
!(isAdmin || jobIncreaseAllowed[job.name]) ||
cooldown > 0 ||
job.slots >= job.max
}
tooltip={
!jobIncreaseAllowed[job.name] && !isAdmin
? 'Cannot increase job slots above maximum.'
: undefined
}
color={job.slots >= job.def ? 'average' : 'default'}
onClick={() =>
act('adjustJobSlot', {
Expand Down

0 comments on commit 0da3e66

Please sign in to comment.