Skip to content

Commit

Permalink
Set average level of headless to all players in the current match
Browse files Browse the repository at this point in the history
  • Loading branch information
ArchangelWTF committed Jan 30, 2025
1 parent cedad4c commit b5c198a
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/models/fika/config/IFikaConfigHeadless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ export interface IFikaConfigHeadless {
generate: boolean;
forceIp: string;
};
/** If this is true, sets the headless's average level to that of the entire lobby, if set to false it will take the level of the requester. */
setLevelToAverageOfLobby: boolean;
}
2 changes: 2 additions & 0 deletions src/models/fika/headless/IHeadlessClientInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export interface IHeadlessClientInfo {
webSocket: SPTWebSocket;
/** State of the headless client */
state: EHeadlessStatus;
/** The players that are playing on this headless client, only set if the state is IN_RAID */
players?: string[];
/** SessionID of the person who has requested the headless client, it will only ever be set if the status is IN_RAID */
requesterSessionID?: string;
/** Allows for checking if the requester has been notified the match has started through the requester WebSocket so he can auto-join */
Expand Down
6 changes: 5 additions & 1 deletion src/services/FikaMatchService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ export class FikaMatchService {
locationData: locationData,
status: EFikaMatchStatus.LOADING,
timeout: 0,
players: new Map(),
players: new Map<string, IFikaPlayer>(),
gameVersion: data.gameVersion,
fikaVersion: data.fikaVersion,
side: data.side,
Expand Down Expand Up @@ -316,6 +316,10 @@ export class FikaMatchService {

this.fikaInsuranceService.addPlayerToMatchId(matchId, playerId);

if (this.fikaHeadlessService.isHeadlessClient(matchId)) {
this.fikaHeadlessService.addPlayerToHeadlessMatch(matchId, playerId);
}

this.fikaPresenceService.updatePlayerPresence(playerId, this.fikaPresenceService.generateSetPresence(EFikaPlayerPresences.IN_RAID, this.fikaPresenceService.generateRaidPresence(match.locationData.Id, match.side, match.time)));
}

Expand Down
58 changes: 58 additions & 0 deletions src/services/headless/FikaHeadlessService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { inject, injectable } from "tsyringe";

import type { ILogger } from "@spt/models/spt/utils/ILogger";

import { SaveServer } from "@spt/servers/SaveServer";
import { SPTWebSocket } from "@spt/servers/ws/SPTWebsocket";
import { EFikaHeadlessWSMessageTypes } from "../../models/enums/EFikaHeadlessWSMessageTypes";
import { EHeadlessStatus } from "../../models/enums/EHeadlessStatus";
import { IHeadlessClientInfo } from "../../models/fika/headless/IHeadlessClientInfo";
import { IStartHeadlessRequest } from "../../models/fika/routes/raid/headless/IStartHeadlessRequest";
import { IHeadlessRequesterJoinRaid } from "../../models/fika/websocket/headless/IHeadlessRequesterJoinRaid";
import { IStartHeadlessRaid } from "../../models/fika/websocket/headless/IHeadlessStartRaid";
import { FikaConfig } from "../../utils/FikaConfig";
import { FikaHeadlessRequesterWebSocket } from "../../websockets/FikaHeadlessRequesterWebSocket";
import { FikaHeadlessProfileService } from "./FikaHeadlessProfileService";

Expand All @@ -19,7 +21,9 @@ export class FikaHeadlessService {
constructor(
@inject("FikaHeadlessProfileService") protected fikaHeadlessProfileService: FikaHeadlessProfileService,
@inject("FikaHeadlessRequesterWebSocket") protected fikaHeadlessRequesterWebSocket: FikaHeadlessRequesterWebSocket,
@inject("SaveServer") protected saveServer: SaveServer,
@inject("WinstonLogger") protected logger: ILogger,
@inject("FikaConfig") protected fikaConfig: FikaConfig,
) {}

public addHeadlessClient(sessionID: string, webSocket: SPTWebSocket): void {
Expand Down Expand Up @@ -48,6 +52,7 @@ export class FikaHeadlessService {
}

headlessClient.state = EHeadlessStatus.IN_RAID;
headlessClient.players = [];
headlessClient.requesterSessionID = requesterSessionID;
headlessClient.hasNotifiedRequester = false;

Expand Down Expand Up @@ -88,6 +93,58 @@ export class FikaHeadlessService {
headlessClient.hasNotifiedRequester = true;
}

public addPlayerToHeadlessMatch(headlessClientId: string, sessionID: string): void {
const headlessClient = this.headlessClients.get(headlessClientId);

if (!headlessClient || headlessClient?.state != EHeadlessStatus.IN_RAID) {
return;
}

if (headlessClientId === sessionID) {
return;
}

headlessClient.players.push(sessionID);

if (!this.fikaConfig.getConfig().headless.setLevelToAverageOfLobby) {
// Doing this everytime is unecessary if we're not setting the average level so only set it once the original requester of the headless joins.
if (headlessClient.requesterSessionID === sessionID) {
this.setHeadlessLevel(headlessClientId);
}
} else {
this.setHeadlessLevel(headlessClientId);
}
}

public setHeadlessLevel(headlessClientId: string): void {
const headlessClient = this.headlessClients.get(headlessClientId);

if (!headlessClient || headlessClient?.state != EHeadlessStatus.IN_RAID) {
return;
}

const headlessProfile = this.saveServer.getProfile(headlessClientId);

// Set level of headless to that of the requester.
if (!this.fikaConfig.getConfig().headless.setLevelToAverageOfLobby) {
headlessProfile.characters.pmc.Info.Level = this.saveServer.getProfile(headlessClient.requesterSessionID).characters.pmc.Info.Level;
return;
}

let baseHeadlessLevel = 0;
let players = headlessClient.players.length;

for (const sessionID of headlessClient.players) {
baseHeadlessLevel += this.saveServer.getProfile(sessionID).characters.pmc.Info.Level;
}

baseHeadlessLevel = Math.round(baseHeadlessLevel / players);

this.logger.debug(`[${headlessClientId}] Setting headless level to: ${baseHeadlessLevel} | Players: ${players}`);

headlessProfile.characters.pmc.Info.Level = baseHeadlessLevel;
}

/** End the raid for the specified headless client, sets the state back to READY so that he can be requested to host again. */
public endHeadlessRaid(headlessClientId: string): void {
const headlessClient = this.headlessClients.get(headlessClientId);
Expand All @@ -97,6 +154,7 @@ export class FikaHeadlessService {
}

headlessClient.state = EHeadlessStatus.READY;
headlessClient.players = null;
headlessClient.requesterSessionID = null;
headlessClient.hasNotifiedRequester = null;
}
Expand Down
3 changes: 2 additions & 1 deletion src/utils/FikaConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class FikaConfig {
sharedQuestProgression: false,
canEditRaidSettings: true,
enableTransits: true,
anyoneCanStartRaid: false
anyoneCanStartRaid: false,
},
server: {
SPT: {
Expand Down Expand Up @@ -70,6 +70,7 @@ export class FikaConfig {
generate: true,
forceIp: "",
},
setLevelToAverageOfLobby: true,
},
background: {
enable: true,
Expand Down

0 comments on commit b5c198a

Please sign in to comment.