GANG: Show confirmation popup if player enables territory clashes while being too weak (#1760)

This commit is contained in:
catloversg 2024-11-10 12:12:17 +07:00 committed by GitHub
parent d6874d68aa
commit f4c2b29d40
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 14 deletions

@ -48,3 +48,9 @@ export function resetGangs(): void {
export function loadAllGangs(saveString: string): void { export function loadAllGangs(saveString: string): void {
AllGangs = JSON.parse(saveString, Reviver); AllGangs = JSON.parse(saveString, Reviver);
} }
export function getClashWinChance(thisGang: string, otherGang: string): number {
const thisGangPower = AllGangs[thisGang].power;
const otherGangPower = AllGangs[otherGang].power;
return thisGangPower / (thisGangPower + otherGangPower);
}

@ -18,7 +18,7 @@ import { GangConstants } from "./data/Constants";
import { GangMemberTasks } from "./GangMemberTasks"; import { GangMemberTasks } from "./GangMemberTasks";
import { IAscensionResult } from "./IAscensionResult"; import { IAscensionResult } from "./IAscensionResult";
import { AllGangs } from "./AllGangs"; import { AllGangs, getClashWinChance } from "./AllGangs";
import { GangMember } from "./GangMember"; import { GangMember } from "./GangMember";
import { WorkerScript } from "../Netscript/WorkerScript"; import { WorkerScript } from "../Netscript/WorkerScript";
@ -236,11 +236,7 @@ export class Gang {
if (!(Math.random() < this.territoryClashChance)) continue; if (!(Math.random() < this.territoryClashChance)) continue;
} }
const thisPwr = AllGangs[thisGang].power; if (Math.random() < getClashWinChance(thisGang, otherGang)) {
const otherPwr = AllGangs[otherGang].power;
const thisChance = thisPwr / (thisPwr + otherPwr);
if (Math.random() < thisChance) {
if (AllGangs[otherGang].territory <= 0) return; if (AllGangs[otherGang].territory <= 0) return;
const territoryGain = calculateTerritoryGain(thisGang, otherGang); const territoryGain = calculateTerritoryGain(thisGang, otherGang);
AllGangs[thisGang].territory += territoryGain; AllGangs[thisGang].territory += territoryGain;

@ -5,10 +5,11 @@ import { Help } from "@mui/icons-material";
import { formatNumberNoSuffix, formatPercent } from "../../ui/formatNumber"; import { formatNumberNoSuffix, formatPercent } from "../../ui/formatNumber";
import { AllGangs } from "../AllGangs"; import { AllGangs, getClashWinChance } from "../AllGangs";
import { useGang } from "./Context"; import { useGang } from "./Context";
import { TerritoryInfoModal } from "./TerritoryInfoModal"; import { TerritoryInfoModal } from "./TerritoryInfoModal";
import { PromptEvent } from "../../ui/React/PromptManager";
/** React Component for the territory subpage. */ /** React Component for the territory subpage. */
export function TerritorySubpage(): React.ReactElement { export function TerritorySubpage(): React.ReactElement {
@ -37,7 +38,34 @@ export function TerritorySubpage(): React.ReactElement {
control={ control={
<Switch <Switch
checked={gang.territoryWarfareEngaged} checked={gang.territoryWarfareEngaged}
onChange={(event) => (gang.territoryWarfareEngaged = event.target.checked)} onChange={(event) => {
let canWinAtLeastOneGang = false;
for (const gangName of Object.keys(AllGangs)) {
if (gang.facName === gangName) {
continue;
}
if (getClashWinChance(gang.facName, gangName) >= 0.5) {
canWinAtLeastOneGang = true;
break;
}
}
/**
* Show a confirmation popup if the player tries to enable the territory clash when their gang is too
* weak and cannot win any other gangs.
*/
if (event.target.checked && !canWinAtLeastOneGang) {
PromptEvent.emit({
txt: "Your gang is too weak. Its win chances against all other gangs are below 50%.\nOn average, you will always lose territory when being engaged in clashes.\n\nDo you really want to engage in territory clashes?",
resolve: (value: string | boolean) => {
if (value === true) {
gang.territoryWarfareEngaged = true;
}
},
});
} else {
gang.territoryWarfareEngaged = event.target.checked;
}
}}
/> />
} }
label={ label={
@ -114,20 +142,17 @@ interface ITerritoryProps {
function OtherGangTerritory(props: ITerritoryProps): React.ReactElement { function OtherGangTerritory(props: ITerritoryProps): React.ReactElement {
const gang = useGang(); const gang = useGang();
const playerPower = AllGangs[gang.facName].power;
const power = AllGangs[props.name].power;
const clashVictoryChance = playerPower / (power + playerPower);
const territory = AllGangs[props.name].territory; const territory = AllGangs[props.name].territory;
const opacity = territory ? 1 : 0.75; const opacity = territory > 0 ? 1 : 0.75;
return ( return (
<Box component={Paper} sx={{ p: 1, opacity }}> <Box component={Paper} sx={{ p: 1, opacity }}>
<Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}> <Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
{props.name} {props.name}
</Typography> </Typography>
<Typography> <Typography>
<b>Power:</b> {formatNumberNoSuffix(power, 3)} <br /> <b>Power:</b> {formatNumberNoSuffix(AllGangs[props.name].power, 3)} <br />
<b>Territory:</b> {formatTerritory(territory)}% <br /> <b>Territory:</b> {formatTerritory(territory)}% <br />
<b>Clash Win Chance:</b> {formatPercent(clashVictoryChance, 3)} <b>Clash Win Chance:</b> {formatPercent(getClashWinChance(gang.facName, props.name), 3)}
</Typography> </Typography>
</Box> </Box>
); );