diff --git a/src/Gang/Gang.ts b/src/Gang/Gang.ts index 358e3c9ba..fed1e6a58 100644 --- a/src/Gang/Gang.ts +++ b/src/Gang/Gang.ts @@ -27,6 +27,14 @@ import { PowerMultiplier } from "./data/power"; import { FactionName } from "@enums"; import { CONSTANTS } from "../Constants"; +export enum RecruitmentResult { + Success = "Success", + EmptyName = "Member name cannot be an empty string", + DuplicatedName = "This name was used", + ExceedMaxNumber = "Your gang recruited maximum number of members", + NotEnoughRespect = "Your gang does not have enough respect to recruit more members", +} + export const GangPromise: PromisePair = { promise: null, resolve: null }; export class Gang { @@ -301,9 +309,14 @@ export class Gang { } } - canRecruitMember(): boolean { - if (this.members.length >= GangConstants.MaximumGangMembers) return false; - return this.respect >= this.respectForNextRecruit(); + canRecruitMember(): RecruitmentResult { + if (this.members.length >= GangConstants.MaximumGangMembers) { + return RecruitmentResult.ExceedMaxNumber; + } + if (this.respect < this.respectForNextRecruit()) { + return RecruitmentResult.NotEnoughRespect; + } + return RecruitmentResult.Success; } /** @returns The respect threshold needed for the next member recruitment. Infinity if already at or above max members. */ @@ -327,17 +340,24 @@ export class Gang { return Math.min(membersRecruitabile, GangConstants.MaximumGangMembers) - this.members.length; } - recruitMember(name: string): boolean { - name = String(name); - if (name === "" || !this.canRecruitMember()) return false; + recruitMember(name: string): RecruitmentResult { + if (name === "") { + return RecruitmentResult.EmptyName; + } + + const resultOfCheckingIfGangCanRecruitMember = this.canRecruitMember(); + if (resultOfCheckingIfGangCanRecruitMember !== RecruitmentResult.Success) { + return resultOfCheckingIfGangCanRecruitMember; + } // Check for already-existing names - const sameNames = this.members.filter((m) => m.name === name); - if (sameNames.length >= 1) return false; + if (this.members.some((m) => m.name === name)) { + return RecruitmentResult.DuplicatedName; + } const member = new GangMember(name); this.members.push(member); - return true; + return RecruitmentResult.Success; } // Money and Respect gains multiplied by this number (< 1) diff --git a/src/Gang/ui/RecruitButton.tsx b/src/Gang/ui/RecruitButton.tsx index 98658e0d0..46e1b3675 100644 --- a/src/Gang/ui/RecruitButton.tsx +++ b/src/Gang/ui/RecruitButton.tsx @@ -5,6 +5,7 @@ import { useGang } from "./Context"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import Box from "@mui/material/Box"; +import { RecruitmentResult } from "../Gang"; interface IProps { onRecruit: () => void; @@ -16,7 +17,7 @@ export function RecruitButton(props: IProps): React.ReactElement { const [open, setOpen] = useState(false); const recruitsAvailable = gang.getRecruitsAvailable(); - if (!gang.canRecruitMember()) { + if (gang.canRecruitMember() !== RecruitmentResult.Success) { const respectNeeded = gang.respectForNextRecruit(); return ( diff --git a/src/Gang/ui/RecruitModal.tsx b/src/Gang/ui/RecruitModal.tsx index 0a1092ef9..e25dd7c8a 100644 --- a/src/Gang/ui/RecruitModal.tsx +++ b/src/Gang/ui/RecruitModal.tsx @@ -6,6 +6,7 @@ import Typography from "@mui/material/Typography"; import TextField from "@mui/material/TextField"; import Button from "@mui/material/Button"; import { KEY } from "../../utils/helpers/keyCodes"; +import { RecruitmentResult } from "../Gang"; interface IRecruitPopupProps { open: boolean; @@ -18,13 +19,14 @@ export function RecruitModal(props: IRecruitPopupProps): React.ReactElement { const gang = useGang(); const [name, setName] = useState(""); - const disabled = name === "" || !gang.canRecruitMember(); + const disabled = name === "" || gang.canRecruitMember() !== RecruitmentResult.Success; function recruit(): void { - if (disabled) return; - // At this point, the only way this can fail is if you already - // have a gang member with the same name - if (!gang.recruitMember(name) && name !== "") { - dialogBoxCreate("You already have a gang member with this name!"); + if (disabled) { + return; + } + const result = gang.recruitMember(name); + if (result !== RecruitmentResult.Success) { + dialogBoxCreate(result); return; } diff --git a/src/NetscriptFunctions/Gang.ts b/src/NetscriptFunctions/Gang.ts index 3ea4c752d..c0995865b 100644 --- a/src/NetscriptFunctions/Gang.ts +++ b/src/NetscriptFunctions/Gang.ts @@ -4,7 +4,7 @@ import type { GangMember } from "../Gang/GangMember"; import type { GangMemberTask } from "../Gang/GangMemberTask"; import type { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; -import { GangPromise } from "../Gang/Gang"; +import { GangPromise, RecruitmentResult } from "../Gang/Gang"; import { Player } from "@player"; import { FactionName } from "@enums"; import { GangConstants } from "../Gang/data/Constants"; @@ -160,7 +160,7 @@ export function NetscriptGang(): InternalAPI { }, canRecruitMember: (ctx) => () => { const gang = getGang(ctx); - return gang.canRecruitMember(); + return gang.canRecruitMember() === RecruitmentResult.Success; }, getRecruitsAvailable: (ctx) => () => { const gang = getGang(ctx); @@ -173,20 +173,13 @@ export function NetscriptGang(): InternalAPI { recruitMember: (ctx) => (_memberName) => { const memberName = helpers.string(ctx, "memberName", _memberName); const gang = getGang(ctx); - const recruited = gang.recruitMember(memberName); - if (memberName === "") { - ctx.workerScript.log("gang.recruitMember", () => `Failed to recruit Gang Member. Name must be provided.`); + const result = gang.recruitMember(memberName); + if (result !== RecruitmentResult.Success) { + ctx.workerScript.log("gang.recruitMember", () => `Failed to recruit gang member '${memberName}'. ${result}.`); return false; - } else if (recruited) { - ctx.workerScript.log("gang.recruitMember", () => `Successfully recruited Gang Member '${memberName}'`); - return recruited; - } else { - ctx.workerScript.log( - "gang.recruitMember", - () => `Failed to recruit Gang Member '${memberName}'. Name already used.`, - ); - return recruited; } + ctx.workerScript.log("gang.recruitMember", () => `Successfully recruited gang member '${memberName}'`); + return true; }, getTaskNames: (ctx) => () => { const gang = getGang(ctx);