46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
import type { CargoType, GameConfig } from "@deadhead/content";
|
||
import type { RealTime } from "./clock";
|
||
|
||
export interface Contract {
|
||
id: string;
|
||
originId: string;
|
||
destinationId: string;
|
||
cargoTypeId: string;
|
||
/** 0 for Standard; 1–5 otherwise, and equal to the required cargo-skill level (decision 0.5.6). */
|
||
tier: number;
|
||
massTonnes: number;
|
||
/** Credits, fixed at offer time (decision 0.5.11). */
|
||
payout: number;
|
||
/** Cargo skill and level needed; null for Standard. */
|
||
requiredSkill: { skillId: string; level: number } | null;
|
||
requiredLongHaulLevel: number;
|
||
offeredAt: RealTime;
|
||
/** End of the board period the contract was offered in. */
|
||
expiresAt: RealTime;
|
||
firstContact: boolean;
|
||
}
|
||
|
||
export interface PayoutInput {
|
||
cargoType: CargoType;
|
||
tier: number;
|
||
massTonnes: number;
|
||
/** Route distance at offer time. */
|
||
distanceMillionKm: number;
|
||
firstContact: boolean;
|
||
}
|
||
|
||
/**
|
||
* Payout in whole credits: base pay per tonne per million km × tierMultiplier^tier
|
||
* × mass × distance, × the first-contact multiplier when flagged.
|
||
*/
|
||
export function contractPayout(input: PayoutInput, config: GameConfig): number {
|
||
const { cargoType, tier, massTonnes, distanceMillionKm, firstContact } = input;
|
||
const pay =
|
||
cargoType.basePayPerTonnePerMillionKm *
|
||
cargoType.tierPayMultiplier ** tier *
|
||
massTonnes *
|
||
distanceMillionKm *
|
||
(firstContact ? config.firstContactPayoutMultiplier : 1);
|
||
return Math.round(pay);
|
||
}
|