mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-13 22:59:02 +00:00
Merge branch 'main' into 2393-show-boat-troops-as-attacking-troops
This commit is contained in:
@@ -90,3 +90,24 @@ export const PlayerProfileSchema = z.object({
|
||||
stats: PlayerStatsTreeSchema,
|
||||
});
|
||||
export type PlayerProfile = z.infer<typeof PlayerProfileSchema>;
|
||||
|
||||
export const ClanLeaderboardEntrySchema = z.object({
|
||||
clanTag: z.string(),
|
||||
games: z.number(),
|
||||
wins: z.number(),
|
||||
losses: z.number(),
|
||||
playerSessions: z.number(),
|
||||
weightedWins: z.number(),
|
||||
weightedLosses: z.number(),
|
||||
weightedWLRatio: z.number(),
|
||||
});
|
||||
export type ClanLeaderboardEntry = z.infer<typeof ClanLeaderboardEntrySchema>;
|
||||
|
||||
export const ClanLeaderboardResponseSchema = z.object({
|
||||
start: z.iso.datetime(),
|
||||
end: z.iso.datetime(),
|
||||
clans: ClanLeaderboardEntrySchema.array(),
|
||||
});
|
||||
export type ClanLeaderboardResponse = z.infer<
|
||||
typeof ClanLeaderboardResponseSchema
|
||||
>;
|
||||
|
||||
+140
-188
@@ -42,222 +42,174 @@ function generateTeamColors(baseColor: Colord): Colord[] {
|
||||
}
|
||||
|
||||
export const nationColors: Colord[] = [
|
||||
colord("rgb(210,210,100)"), // Lime Yellow
|
||||
colord("rgb(180,210,120)"), // Light Green
|
||||
colord("rgb(170,190,100)"), // Yellow Green
|
||||
colord("rgb(80,200,120)"), // Emerald Green
|
||||
colord("rgb(130,200,130)"), // Light Sea Green
|
||||
colord("rgb(140,180,140)"), // Dark Sea Green
|
||||
colord("rgb(160,190,160)"), // Pale Green
|
||||
colord("rgb(160,180,140)"), // Dark Olive Green
|
||||
colord("rgb(100,160,80)"), // Olive Green
|
||||
colord("rgb(100,140,110)"), // Sea Green
|
||||
colord("rgb(100,180,160)"), // Aquamarine
|
||||
colord("rgb(130,180,170)"), // Medium Aquamarine
|
||||
colord("rgb(170,190,180)"), // Pale Blue Green
|
||||
colord("rgb(100,130,150)"), // Steel Blue
|
||||
colord("rgb(120,160,200)"), // Cornflower Blue
|
||||
colord("rgb(140,150,180)"), // Light Slate Gray
|
||||
colord("rgb(100,210,210)"), // Turquoise
|
||||
colord("rgb(140,180,220)"), // Light Blue
|
||||
colord("rgb(130,170,190)"), // Cadet Blue
|
||||
colord("rgb(100,180,230)"), // Sky Blue
|
||||
colord("rgb(80,130,190)"), // Navy Blue
|
||||
colord("rgb(120,120,190)"), // Periwinkle
|
||||
colord("rgb(150,110,190)"), // Lavender
|
||||
colord("rgb(160,120,160)"), // Purple Gray
|
||||
colord("rgb(170,140,190)"), // Medium Purple
|
||||
colord("rgb(180,130,180)"), // Plum
|
||||
colord("rgb(190,140,150)"), // Puce
|
||||
colord("rgb(180,100,230)"), // Purple
|
||||
colord("rgb(180,160,180)"), // Mauve
|
||||
colord("rgb(170,150,170)"), // Dusty Rose
|
||||
colord("rgb(150,130,150)"), // Thistle
|
||||
colord("rgb(230,180,180)"), // Light Pink
|
||||
colord("rgb(210,160,200)"), // Orchid
|
||||
colord("rgb(230,130,180)"), // Pink
|
||||
colord("rgb(210,100,160)"), // Hot Pink
|
||||
colord("rgb(190,100,130)"), // Maroon
|
||||
colord("rgb(220,120,120)"), // Coral
|
||||
colord("rgb(200,130,110)"), // Dark Salmon
|
||||
colord("rgb(230,140,140)"), // Salmon
|
||||
colord("rgb(230,100,100)"), // Bright Red
|
||||
colord("rgb(100,180,230)"), // Sky Blue
|
||||
colord("rgb(230,180,80)"), // Golden Yellow
|
||||
colord("rgb(180,100,230)"), // Purple
|
||||
colord("rgb(80,200,120)"), // Emerald Green
|
||||
colord("rgb(230,130,180)"), // Pink
|
||||
colord("rgb(100,160,80)"), // Olive Green
|
||||
colord("rgb(230,150,100)"), // Peach
|
||||
colord("rgb(80,130,190)"), // Navy Blue
|
||||
colord("rgb(210,210,100)"), // Lime Yellow
|
||||
colord("rgb(190,100,130)"), // Maroon
|
||||
colord("rgb(100,210,210)"), // Turquoise
|
||||
colord("rgb(210,140,80)"), // Light Orange
|
||||
colord("rgb(150,110,190)"), // Lavender
|
||||
colord("rgb(180,210,120)"), // Light Green
|
||||
colord("rgb(210,100,160)"), // Hot Pink
|
||||
colord("rgb(100,140,110)"), // Sea Green
|
||||
colord("rgb(230,180,180)"), // Light Pink
|
||||
colord("rgb(120,120,190)"), // Periwinkle
|
||||
colord("rgb(190,170,100)"), // Sand
|
||||
colord("rgb(100,180,160)"), // Aquamarine
|
||||
colord("rgb(210,160,200)"), // Orchid
|
||||
colord("rgb(170,190,100)"), // Yellow Green
|
||||
colord("rgb(100,130,150)"), // Steel Blue
|
||||
colord("rgb(230,140,140)"), // Salmon
|
||||
colord("rgb(140,180,220)"), // Light Blue
|
||||
colord("rgb(200,160,110)"), // Tan
|
||||
colord("rgb(180,130,180)"), // Plum
|
||||
colord("rgb(130,200,130)"), // Light Sea Green
|
||||
colord("rgb(220,120,120)"), // Coral
|
||||
colord("rgb(120,160,200)"), // Cornflower Blue
|
||||
colord("rgb(200,200,140)"), // Khaki
|
||||
colord("rgb(160,120,160)"), // Purple Gray
|
||||
colord("rgb(140,180,140)"), // Dark Sea Green
|
||||
colord("rgb(200,130,110)"), // Dark Salmon
|
||||
colord("rgb(130,170,190)"), // Cadet Blue
|
||||
colord("rgb(190,180,160)"), // Tan Gray
|
||||
colord("rgb(170,140,190)"), // Medium Purple
|
||||
colord("rgb(160,190,160)"), // Pale Green
|
||||
colord("rgb(190,150,130)"), // Rosy Brown
|
||||
colord("rgb(140,150,180)"), // Light Slate Gray
|
||||
colord("rgb(180,170,140)"), // Dark Khaki
|
||||
colord("rgb(150,130,150)"), // Thistle
|
||||
colord("rgb(170,190,180)"), // Pale Blue Green
|
||||
colord("rgb(190,140,150)"), // Puce
|
||||
colord("rgb(130,180,170)"), // Medium Aquamarine
|
||||
colord("rgb(180,160,180)"), // Mauve
|
||||
colord("rgb(160,180,140)"), // Dark Olive Green
|
||||
colord("rgb(170,150,170)"), // Dusty Rose
|
||||
colord("rgb(100,180,230)"), // Sky Blue
|
||||
colord("rgb(230,180,80)"), // Golden Yellow
|
||||
colord("rgb(180,100,230)"), // Purple
|
||||
colord("rgb(80,200,120)"), // Emerald Green
|
||||
colord("rgb(230,130,180)"), // Pink
|
||||
colord("rgb(100,160,80)"), // Olive Green
|
||||
colord("rgb(230,150,100)"), // Peach
|
||||
colord("rgb(80,130,190)"), // Navy Blue
|
||||
colord("rgb(210,210,100)"), // Lime Yellow
|
||||
colord("rgb(190,100,130)"), // Maroon
|
||||
colord("rgb(100,210,210)"), // Turquoise
|
||||
colord("rgb(210,140,80)"), // Light Orange
|
||||
colord("rgb(150,110,190)"), // Lavender
|
||||
colord("rgb(180,210,120)"), // Light Green
|
||||
colord("rgb(210,100,160)"), // Hot Pink
|
||||
colord("rgb(100,140,110)"), // Sea Green
|
||||
colord("rgb(230,180,180)"), // Light Pink
|
||||
colord("rgb(120,120,190)"), // Periwinkle
|
||||
colord("rgb(190,170,100)"), // Sand
|
||||
colord("rgb(100,180,160)"), // Aquamarine
|
||||
colord("rgb(210,160,200)"), // Orchid
|
||||
colord("rgb(170,190,100)"), // Yellow Green
|
||||
colord("rgb(100,130,150)"), // Steel Blue
|
||||
colord("rgb(230,140,140)"), // Salmon
|
||||
colord("rgb(140,180,220)"), // Light Blue
|
||||
colord("rgb(200,160,110)"), // Tan
|
||||
colord("rgb(180,130,180)"), // Plum
|
||||
colord("rgb(130,200,130)"), // Light Sea Green
|
||||
colord("rgb(220,120,120)"), // Coral
|
||||
colord("rgb(120,160,200)"), // Cornflower Blue
|
||||
colord("rgb(200,200,140)"), // Khaki
|
||||
colord("rgb(160,120,160)"), // Purple Gray
|
||||
colord("rgb(140,180,140)"), // Dark Sea Green
|
||||
colord("rgb(200,130,110)"), // Dark Salmon
|
||||
colord("rgb(130,170,190)"), // Cadet Blue
|
||||
colord("rgb(190,180,160)"), // Tan Gray
|
||||
colord("rgb(170,140,190)"), // Medium Purple
|
||||
colord("rgb(160,190,160)"), // Pale Green
|
||||
colord("rgb(190,150,130)"), // Rosy Brown
|
||||
colord("rgb(140,150,180)"), // Light Slate Gray
|
||||
colord("rgb(190,180,160)"), // Tan Gray
|
||||
colord("rgb(180,170,140)"), // Dark Khaki
|
||||
colord("rgb(150,130,150)"), // Thistle
|
||||
colord("rgb(170,190,180)"), // Pale Blue Green
|
||||
colord("rgb(190,140,150)"), // Puce
|
||||
colord("rgb(130,180,170)"), // Medium Aquamarine
|
||||
colord("rgb(180,160,180)"), // Mauve
|
||||
colord("rgb(160,180,140)"), // Dark Olive Green
|
||||
colord("rgb(170,150,170)"), // Dusty Rose
|
||||
colord("rgb(200,200,140)"), // Khaki
|
||||
colord("rgb(190,170,100)"), // Sand
|
||||
];
|
||||
|
||||
// Bright pastel theme with 64 colors
|
||||
export const humanColors: Colord[] = [
|
||||
colord("rgb(16,185,129)"), // Sea Green
|
||||
colord("rgb(34,197,94)"), // Emerald
|
||||
colord("rgb(45,212,191)"), // Turquoise
|
||||
colord("rgb(48,178,180)"), // Teal
|
||||
colord("rgb(52,211,153)"), // Spearmint
|
||||
colord("rgb(56,189,248)"), // Light Blue
|
||||
colord("rgb(59,130,246)"), // Royal Blue
|
||||
colord("rgb(67,190,84)"), // Fresh Green
|
||||
colord("rgb(74,222,128)"), // Mint
|
||||
colord("rgb(79,70,229)"), // Indigo
|
||||
colord("rgb(82,183,136)"), // Jade
|
||||
colord("rgb(96,165,250)"), // Sky Blue
|
||||
colord("rgb(99,202,253)"), // Azure
|
||||
colord("rgb(110,231,183)"), // Seafoam
|
||||
colord("rgb(124,58,237)"), // Royal Purple
|
||||
colord("rgb(125,211,252)"), // Crystal Blue
|
||||
colord("rgb(132,204,22)"), // Lime
|
||||
colord("rgb(133,77,14)"), // Chocolate
|
||||
colord("rgb(134,239,172)"), // Light Green
|
||||
colord("rgb(147,51,234)"), // Bright Purple
|
||||
colord("rgb(147,197,253)"), // Powder Blue
|
||||
colord("rgb(151,255,187)"), // Fresh Mint
|
||||
colord("rgb(163,230,53)"), // Yellow Green
|
||||
colord("rgb(167,139,250)"), // Periwinkle
|
||||
colord("rgb(168,85,247)"), // Vibrant Purple
|
||||
colord("rgb(179,136,255)"), // Light Purple
|
||||
colord("rgb(132,204,22)"), // Lime
|
||||
colord("rgb(16,185,129)"), // Sea Green
|
||||
colord("rgb(52,211,153)"), // Spearmint
|
||||
colord("rgb(45,212,191)"), // Turquoise
|
||||
colord("rgb(74,222,128)"), // Mint
|
||||
colord("rgb(110,231,183)"), // Seafoam
|
||||
colord("rgb(134,239,172)"), // Light Green
|
||||
colord("rgb(151,255,187)"), // Fresh Mint
|
||||
colord("rgb(186,255,201)"), // Pale Emerald
|
||||
colord("rgb(230,250,210)"), // Pastel Lime
|
||||
colord("rgb(34,197,94)"), // Emerald
|
||||
colord("rgb(67,190,84)"), // Fresh Green
|
||||
colord("rgb(82,183,136)"), // Jade
|
||||
colord("rgb(48,178,180)"), // Teal
|
||||
colord("rgb(230,255,250)"), // Mint Whisper
|
||||
colord("rgb(220,240,250)"), // Ice Blue
|
||||
colord("rgb(233,213,255)"), // Light Lilac
|
||||
colord("rgb(204,204,255)"), // Soft Lavender Blue
|
||||
colord("rgb(220,220,255)"), // Meringue Blue
|
||||
colord("rgb(202,225,255)"), // Baby Blue
|
||||
colord("rgb(147,197,253)"), // Powder Blue
|
||||
colord("rgb(125,211,252)"), // Crystal Blue
|
||||
colord("rgb(99,202,253)"), // Azure
|
||||
colord("rgb(56,189,248)"), // Light Blue
|
||||
colord("rgb(96,165,250)"), // Sky Blue
|
||||
colord("rgb(59,130,246)"), // Royal Blue
|
||||
colord("rgb(79,70,229)"), // Indigo
|
||||
colord("rgb(124,58,237)"), // Royal Purple
|
||||
colord("rgb(147,51,234)"), // Bright Purple
|
||||
colord("rgb(179,136,255)"), // Light Purple
|
||||
colord("rgb(167,139,250)"), // Periwinkle
|
||||
colord("rgb(217,70,239)"), // Fuchsia
|
||||
colord("rgb(168,85,247)"), // Vibrant Purple
|
||||
colord("rgb(190,92,251)"), // Amethyst
|
||||
colord("rgb(192,132,252)"), // Lavender
|
||||
colord("rgb(202,138,4)"), // Rich Gold
|
||||
colord("rgb(202,225,255)"), // Baby Blue
|
||||
colord("rgb(204,204,255)"), // Soft Lavender Blue
|
||||
colord("rgb(217,70,239)"), // Fuchsia
|
||||
colord("rgb(220,38,38)"), // Ruby
|
||||
colord("rgb(220,220,255)"), // Meringue Blue
|
||||
colord("rgb(220,240,250)"), // Ice Blue
|
||||
colord("rgb(230,250,210)"), // Pastel Lime
|
||||
colord("rgb(230,255,250)"), // Mint Whisper
|
||||
colord("rgb(233,213,255)"), // Light Lilac
|
||||
colord("rgb(234,88,12)"), // Burnt Orange
|
||||
colord("rgb(234,179,8)"), // Sunflower
|
||||
colord("rgb(235,75,75)"), // Bright Red
|
||||
colord("rgb(236,72,153)"), // Deep Pink
|
||||
colord("rgb(239,68,68)"), // Crimson
|
||||
colord("rgb(240,171,252)"), // Orchid
|
||||
colord("rgb(240,240,200)"), // Light Khaki
|
||||
colord("rgb(244,114,182)"), // Rose
|
||||
colord("rgb(236,72,153)"), // Deep Pink
|
||||
colord("rgb(220,38,38)"), // Ruby
|
||||
colord("rgb(239,68,68)"), // Crimson
|
||||
colord("rgb(235,75,75)"), // Bright Red
|
||||
colord("rgb(245,101,101)"), // Coral
|
||||
colord("rgb(245,158,11)"), // Amber
|
||||
colord("rgb(248,113,113)"), // Warm Red
|
||||
colord("rgb(249,115,22)"), // Tangerine
|
||||
colord("rgb(250,215,225)"), // Cotton Candy
|
||||
colord("rgb(250,250,210)"), // Pastel Lemon
|
||||
colord("rgb(251,113,133)"), // Watermelon
|
||||
colord("rgb(251,146,60)"), // Light Orange
|
||||
colord("rgb(251,191,36)"), // Marigold
|
||||
colord("rgb(251,235,245)"), // Rose Powder
|
||||
colord("rgb(252,165,165)"), // Peach
|
||||
colord("rgb(252,211,77)"), // Golden
|
||||
colord("rgb(253,164,175)"), // Salmon Pink
|
||||
colord("rgb(252,165,165)"), // Peach
|
||||
colord("rgb(255,204,229)"), // Blush Pink
|
||||
colord("rgb(255,223,186)"), // Apricot Cream
|
||||
colord("rgb(250,215,225)"), // Cotton Candy
|
||||
colord("rgb(251,235,245)"), // Rose Powder
|
||||
colord("rgb(240,240,200)"), // Light Khaki
|
||||
colord("rgb(250,250,210)"), // Pastel Lemon
|
||||
colord("rgb(255,240,200)"), // Vanilla
|
||||
colord("rgb(255,223,186)"), // Apricot Cream
|
||||
colord("rgb(252,211,77)"), // Golden
|
||||
colord("rgb(251,191,36)"), // Marigold
|
||||
colord("rgb(234,179,8)"), // Sunflower
|
||||
colord("rgb(202,138,4)"), // Rich Gold
|
||||
colord("rgb(245,158,11)"), // Amber
|
||||
colord("rgb(251,146,60)"), // Light Orange
|
||||
colord("rgb(249,115,22)"), // Tangerine
|
||||
colord("rgb(234,88,12)"), // Burnt Orange
|
||||
colord("rgb(133,77,14)"), // Chocolate
|
||||
];
|
||||
|
||||
export const botColors: Colord[] = [
|
||||
colord("rgb(190,120,120)"), // Muted Red
|
||||
colord("rgb(120,160,190)"), // Muted Sky Blue
|
||||
colord("rgb(190,160,100)"), // Muted Golden Yellow
|
||||
colord("rgb(160,120,190)"), // Muted Purple
|
||||
colord("rgb(100,170,130)"), // Muted Emerald Green
|
||||
colord("rgb(190,130,160)"), // Muted Pink
|
||||
colord("rgb(120,150,100)"), // Muted Olive Green
|
||||
colord("rgb(190,140,120)"), // Muted Peach
|
||||
colord("rgb(100,120,160)"), // Muted Navy Blue
|
||||
colord("rgb(170,170,120)"), // Muted Lime Yellow
|
||||
colord("rgb(160,120,130)"), // Muted Maroon
|
||||
colord("rgb(120,170,170)"), // Muted Turquoise
|
||||
colord("rgb(170,140,100)"), // Muted Light Orange
|
||||
colord("rgb(140,120,160)"), // Muted Lavender
|
||||
colord("rgb(150,170,130)"), // Muted Light Green
|
||||
colord("rgb(170,120,140)"), // Muted Hot Pink
|
||||
colord("rgb(120,140,120)"), // Muted Sea Green
|
||||
colord("rgb(180,160,160)"), // Muted Light Pink
|
||||
colord("rgb(130,130,160)"), // Muted Periwinkle
|
||||
colord("rgb(160,150,120)"), // Muted Sand
|
||||
colord("rgb(120,160,150)"), // Muted Aquamarine
|
||||
colord("rgb(170,150,170)"), // Muted Orchid
|
||||
colord("rgb(150,160,120)"), // Muted Yellow Green
|
||||
colord("rgb(120,130,140)"), // Muted Steel Blue
|
||||
colord("rgb(180,140,140)"), // Muted Salmon
|
||||
colord("rgb(140,160,170)"), // Muted Light Blue
|
||||
colord("rgb(170,150,130)"), // Muted Tan
|
||||
colord("rgb(160,130,160)"), // Muted Plum
|
||||
colord("rgb(130,170,130)"), // Muted Light Sea Green
|
||||
colord("rgb(170,130,130)"), // Muted Coral
|
||||
colord("rgb(130,150,170)"), // Muted Cornflower Blue
|
||||
colord("rgb(170,170,140)"), // Muted Khaki
|
||||
colord("rgb(150,130,150)"), // Muted Purple Gray
|
||||
colord("rgb(140,160,140)"), // Muted Dark Sea Green
|
||||
colord("rgb(170,130,120)"), // Muted Dark Salmon
|
||||
colord("rgb(130,150,160)"), // Muted Cadet Blue
|
||||
colord("rgb(160,160,150)"), // Muted Tan Gray
|
||||
colord("rgb(150,140,160)"), // Muted Medium Purple
|
||||
colord("rgb(150,170,150)"), // Muted Pale Green
|
||||
colord("rgb(160,140,130)"), // Muted Rosy Brown
|
||||
colord("rgb(140,150,160)"), // Muted Light Slate Gray
|
||||
colord("rgb(160,150,140)"), // Muted Dark Khaki
|
||||
colord("rgb(140,130,140)"), // Muted Thistle
|
||||
colord("rgb(150,160,160)"), // Muted Pale Blue Green
|
||||
colord("rgb(160,140,150)"), // Muted Puce
|
||||
colord("rgb(130,160,150)"), // Muted Medium Aquamarine
|
||||
colord("rgb(160,150,160)"), // Muted Mauve
|
||||
colord("rgb(150,160,140)"), // Muted Dark Olive Green
|
||||
colord("rgb(160,160,150)"), // Muted Tan Gray
|
||||
colord("rgb(170,170,140)"), // Muted Khaki
|
||||
colord("rgb(170,170,120)"), // Muted Lime Yellow
|
||||
colord("rgb(150,160,120)"), // Muted Yellow Green
|
||||
colord("rgb(150,170,130)"), // Muted Light Green
|
||||
colord("rgb(150,170,150)"), // Muted Pale Green
|
||||
colord("rgb(130,170,130)"), // Muted Light Sea Green
|
||||
colord("rgb(140,160,140)"), // Muted Dark Sea Green
|
||||
colord("rgb(120,150,100)"), // Muted Olive Green
|
||||
colord("rgb(120,140,120)"), // Muted Sea Green
|
||||
colord("rgb(100,170,130)"), // Muted Emerald Green
|
||||
colord("rgb(120,160,150)"), // Muted Aquamarine
|
||||
colord("rgb(130,160,150)"), // Muted Medium Aquamarine
|
||||
colord("rgb(120,170,170)"), // Muted Turquoise
|
||||
colord("rgb(120,160,190)"), // Muted Sky Blue
|
||||
colord("rgb(130,150,170)"), // Muted Cornflower Blue
|
||||
colord("rgb(130,150,160)"), // Muted Cadet Blue
|
||||
colord("rgb(140,150,160)"), // Muted Light Slate Gray
|
||||
colord("rgb(140,160,170)"), // Muted Light Blue
|
||||
colord("rgb(150,160,160)"), // Muted Pale Blue Green
|
||||
colord("rgb(100,120,160)"), // Muted Navy Blue
|
||||
colord("rgb(120,130,140)"), // Muted Steel Blue
|
||||
colord("rgb(130,130,160)"), // Muted Periwinkle
|
||||
colord("rgb(140,130,140)"), // Muted Thistle
|
||||
colord("rgb(140,120,160)"), // Muted Lavender
|
||||
colord("rgb(150,130,150)"), // Muted Purple Gray
|
||||
colord("rgb(150,140,160)"), // Muted Medium Purple
|
||||
colord("rgb(160,130,160)"), // Muted Plum
|
||||
colord("rgb(170,150,170)"), // Muted Orchid
|
||||
colord("rgb(160,120,190)"), // Muted Purple
|
||||
colord("rgb(160,120,130)"), // Muted Maroon
|
||||
colord("rgb(170,120,140)"), // Muted Hot Pink
|
||||
colord("rgb(170,130,120)"), // Muted Dark Salmon
|
||||
colord("rgb(170,130,130)"), // Muted Coral
|
||||
colord("rgb(180,140,140)"), // Muted Salmon
|
||||
colord("rgb(190,130,160)"), // Muted Pink
|
||||
colord("rgb(190,120,120)"), // Muted Red
|
||||
colord("rgb(190,140,120)"), // Muted Peach
|
||||
colord("rgb(190,160,100)"), // Muted Golden Yellow
|
||||
colord("rgb(170,140,100)"), // Muted Light Orange
|
||||
colord("rgb(160,140,130)"), // Muted Rosy Brown
|
||||
colord("rgb(170,150,130)"), // Muted Tan
|
||||
colord("rgb(160,150,120)"), // Muted Sand
|
||||
colord("rgb(160,150,140)"), // Muted Dark Khaki
|
||||
colord("rgb(160,140,150)"), // Muted Puce
|
||||
colord("rgb(160,150,160)"), // Muted Mauve
|
||||
colord("rgb(150,140,150)"), // Muted Dusty Rose
|
||||
colord("rgb(180,160,160)"), // Muted Light Pink
|
||||
];
|
||||
|
||||
// Fallback colors for when the color palette is exhausted.
|
||||
|
||||
@@ -190,6 +190,8 @@ export interface Theme {
|
||||
// Don't call directly, use PlayerView
|
||||
territoryColor(playerInfo: PlayerView): Colord;
|
||||
// Don't call directly, use PlayerView
|
||||
structureColors(territoryColor: Colord): { light: Colord; dark: Colord };
|
||||
// Don't call directly, use PlayerView
|
||||
borderColor(territoryColor: Colord): Colord;
|
||||
// Don't call directly, use PlayerView
|
||||
defendedBorderColors(territoryColor: Colord): { light: Colord; dark: Colord };
|
||||
|
||||
@@ -60,6 +60,7 @@ const numPlayersConfig = {
|
||||
[GameMapType.Europe]: [100, 70, 50],
|
||||
[GameMapType.EuropeClassic]: [50, 30, 30],
|
||||
[GameMapType.FalklandIslands]: [50, 30, 20],
|
||||
[GameMapType.FourIslands]: [20, 15, 10],
|
||||
[GameMapType.FaroeIslands]: [20, 15, 10],
|
||||
[GameMapType.GatewayToTheAtlantic]: [100, 70, 50],
|
||||
[GameMapType.GiantWorldMap]: [100, 70, 50],
|
||||
@@ -692,7 +693,7 @@ export class DefaultConfig implements Config {
|
||||
|
||||
if (attacker.isPlayer() && defender.isPlayer()) {
|
||||
if (defender.isDisconnected() && attacker.isOnSameTeam(defender)) {
|
||||
// No troop loss if defender is disconnected.
|
||||
// No troop loss if defender is disconnected and on same team
|
||||
mag = 0;
|
||||
}
|
||||
if (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Colord, colord } from "colord";
|
||||
import { Colord, colord, LabaColor } from "colord";
|
||||
import { PseudoRandom } from "../PseudoRandom";
|
||||
import { PlayerType, Team, TerrainType } from "../game/Game";
|
||||
import { GameMap, TileRef } from "../game/GameMap";
|
||||
@@ -7,10 +7,7 @@ import { ColorAllocator } from "./ColorAllocator";
|
||||
import { botColors, fallbackColors, humanColors, nationColors } from "./Colors";
|
||||
import { Theme } from "./Config";
|
||||
|
||||
type ColorCache = Map<string, Colord>;
|
||||
|
||||
export class PastelTheme implements Theme {
|
||||
private borderColorCache: ColorCache = new Map<string, Colord>();
|
||||
private rand = new PseudoRandom(123);
|
||||
private humanColorAllocator = new ColorAllocator(humanColors, fallbackColors);
|
||||
private botColorAllocator = new ColorAllocator(botColors, botColors);
|
||||
@@ -65,6 +62,59 @@ export class PastelTheme implements Theme {
|
||||
return this.nationColorAllocator.assignColor(player.id());
|
||||
}
|
||||
|
||||
structureColors(territoryColor: Colord): { light: Colord; dark: Colord } {
|
||||
// Convert territory color to LAB color space. Territory color is rendered in game with alpha = 150/255, use that here.
|
||||
const lightLAB = territoryColor.alpha(150 / 255).toLab();
|
||||
// Get "border color" from territory color & convert to LAB color space
|
||||
const darkLAB = this.borderColor(territoryColor).toLab();
|
||||
// Calculate the contrast of the two provided colors
|
||||
let contrast = this.contrast(lightLAB, darkLAB);
|
||||
|
||||
// Don't want excessive contrast, so incrementally increase contrast within a loop.
|
||||
// Define target values, looping limits, and loop counter
|
||||
const loopLimit = 10; // Switch from darkening border to lightening fill if loopLimit is reached
|
||||
const maxIterations = 50; // maximum number of loops allowed, throw error above this limit
|
||||
const contrastTarget = 0.5;
|
||||
let loopCount = 0;
|
||||
|
||||
// Adjust luminance by 5 in each iteration. This is a balance between speed and not overdoing contrast changes.
|
||||
const luminanceChange = 5;
|
||||
|
||||
while (contrast < contrastTarget) {
|
||||
if (loopCount > maxIterations) {
|
||||
// Prevent runaway loops
|
||||
console.warn(`Infinite loop detected during structure color calculation.
|
||||
Light color: ${colord(lightLAB).toRgbString()},
|
||||
Dark color: ${colord(darkLAB).toRgbString()},
|
||||
Contrast: ${contrast}`);
|
||||
break;
|
||||
|
||||
// Increase the light color if the "loop limit" has been reach
|
||||
// (probably due to the dark color already being as dark as it can be)
|
||||
} else if (loopCount > loopLimit) {
|
||||
lightLAB.l = this.clamp(lightLAB.l + luminanceChange);
|
||||
|
||||
// Decrease the dark color first to keep the light color as close
|
||||
// to the territory color as possible
|
||||
} else {
|
||||
darkLAB.l = this.clamp(darkLAB.l - luminanceChange);
|
||||
}
|
||||
|
||||
// re-calculate contrast and increment loop counter
|
||||
contrast = this.contrast(lightLAB, darkLAB);
|
||||
loopCount++;
|
||||
}
|
||||
return { light: colord(lightLAB), dark: colord(darkLAB) };
|
||||
}
|
||||
|
||||
private contrast(first: LabaColor, second: LabaColor): number {
|
||||
return colord(first).delta(colord(second));
|
||||
}
|
||||
|
||||
private clamp(num: number, low: number = 0, high: number = 100): number {
|
||||
return Math.min(Math.max(low, num), high);
|
||||
}
|
||||
|
||||
// Don't call directly, use PlayerView
|
||||
borderColor(territoryColor: Colord): Colord {
|
||||
return territoryColor.darken(0.125);
|
||||
|
||||
@@ -186,6 +186,13 @@ export class AttackExecution implements Execution {
|
||||
this._owner.id(),
|
||||
);
|
||||
}
|
||||
if (this.removeTroops === false && this.sourceTile === null) {
|
||||
// startTroops are always added to attack troops at init but not always removed from owner troops
|
||||
// subtract startTroops from attack troops so we don't give back startTroops to owner that were never removed
|
||||
// boat attacks (sourceTile !== null) are the exception: troops were removed at departure and must be returned after attack still
|
||||
this.attack.setTroops(this.attack.troops() - (this.startTroops ?? 0));
|
||||
}
|
||||
|
||||
const survivors = this.attack.troops() - deaths;
|
||||
this._owner.addTroops(survivors);
|
||||
this.attack.delete();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { renderTroops } from "../../client/Utils";
|
||||
import {
|
||||
Execution,
|
||||
Game,
|
||||
@@ -14,6 +15,7 @@ import { PathFindResultType } from "../pathfinding/AStar";
|
||||
import { PathFinder } from "../pathfinding/PathFinding";
|
||||
import { AttackExecution } from "./AttackExecution";
|
||||
|
||||
const malusForRetreat = 25;
|
||||
export class TransportShipExecution implements Execution {
|
||||
private lastMove: number;
|
||||
|
||||
@@ -33,13 +35,17 @@ export class TransportShipExecution implements Execution {
|
||||
|
||||
private pathFinder: PathFinder;
|
||||
|
||||
private originalOwner: Player;
|
||||
|
||||
constructor(
|
||||
private attacker: Player,
|
||||
private targetID: PlayerID | null,
|
||||
private ref: TileRef,
|
||||
private startTroops: number,
|
||||
private src: TileRef | null,
|
||||
) {}
|
||||
) {
|
||||
this.originalOwner = this.attacker;
|
||||
}
|
||||
|
||||
activeDuringSpawnPhase(): boolean {
|
||||
return false;
|
||||
@@ -173,11 +179,44 @@ export class TransportShipExecution implements Execution {
|
||||
}
|
||||
this.lastMove = ticks;
|
||||
|
||||
if (this.boat.retreating()) {
|
||||
this.dst = this.src!; // src is guaranteed to be set at this point
|
||||
// Team mate can conquer disconnected player and get their ships
|
||||
// captureUnit has changed the owner of the unit, now update attacker
|
||||
const boatOwner = this.boat.owner();
|
||||
if (
|
||||
this.originalOwner.isDisconnected() &&
|
||||
boatOwner !== this.originalOwner &&
|
||||
boatOwner.isOnSameTeam(this.originalOwner)
|
||||
) {
|
||||
this.attacker = boatOwner;
|
||||
this.originalOwner = boatOwner; // for when this owner disconnects too
|
||||
}
|
||||
|
||||
if (this.boat.targetTile() !== this.dst) {
|
||||
this.boat.setTargetTile(this.dst);
|
||||
if (this.boat.retreating()) {
|
||||
// Ensure retreat source is still valid for (new) owner
|
||||
if (this.mg.owner(this.src!) !== this.attacker) {
|
||||
// Use bestTransportShipSpawn, not canBuild because of its max boats check etc
|
||||
const newSrc = this.attacker.bestTransportShipSpawn(this.dst);
|
||||
if (newSrc === false) {
|
||||
this.src = null;
|
||||
} else {
|
||||
this.src = newSrc;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.src === null) {
|
||||
console.warn(
|
||||
`TransportShipExecution: retreating but no src found for new attacker`,
|
||||
);
|
||||
this.attacker.addTroops(this.boat.troops());
|
||||
this.boat.delete(false);
|
||||
this.active = false;
|
||||
return;
|
||||
} else {
|
||||
this.dst = this.src;
|
||||
|
||||
if (this.boat.targetTile() !== this.dst) {
|
||||
this.boat.setTargetTile(this.dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,14 +229,23 @@ export class TransportShipExecution implements Execution {
|
||||
switch (result.type) {
|
||||
case PathFindResultType.Completed:
|
||||
if (this.mg.owner(this.dst) === this.attacker) {
|
||||
this.attacker.addTroops(this.boat.troops());
|
||||
const deaths = this.boat.troops() * (malusForRetreat / 100);
|
||||
const survivors = this.boat.troops() - deaths;
|
||||
this.attacker.addTroops(survivors);
|
||||
this.boat.delete(false);
|
||||
this.active = false;
|
||||
|
||||
// Record stats
|
||||
this.mg
|
||||
.stats()
|
||||
.boatArriveTroops(this.attacker, this.target, this.boat.troops());
|
||||
.boatArriveTroops(this.attacker, this.target, survivors);
|
||||
if (deaths) {
|
||||
this.mg.displayMessage(
|
||||
`Attack cancelled, ${renderTroops(deaths)} soldiers killed during retreat.`,
|
||||
MessageType.ATTACK_CANCELLED,
|
||||
this.attacker.id(),
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.attacker.conquer(this.dst);
|
||||
|
||||
@@ -55,10 +55,6 @@ export class WarshipExecution implements Execution {
|
||||
this.warship.delete();
|
||||
return;
|
||||
}
|
||||
if (this.warship.owner().isDisconnected()) {
|
||||
this.warship.delete();
|
||||
return;
|
||||
}
|
||||
|
||||
const hasPort = this.warship.owner().unitCount(UnitType.Port) > 0;
|
||||
if (hasPort) {
|
||||
@@ -93,7 +89,7 @@ export class WarshipExecution implements Execution {
|
||||
if (
|
||||
unit.owner() === this.warship.owner() ||
|
||||
unit === this.warship ||
|
||||
unit.owner().isFriendly(this.warship.owner()) ||
|
||||
unit.owner().isFriendly(this.warship.owner(), true) ||
|
||||
this.alreadySentShell.has(unit)
|
||||
) {
|
||||
continue;
|
||||
|
||||
@@ -101,6 +101,7 @@ export enum GameMapType {
|
||||
Montreal = "Montreal",
|
||||
Achiran = "Achiran",
|
||||
BaikalNukeWars = "Baikal (Nuke Wars)",
|
||||
FourIslands = "Four Islands",
|
||||
}
|
||||
|
||||
export type GameMapName = keyof typeof GameMapType;
|
||||
@@ -143,6 +144,7 @@ export const mapCategories: Record<string, GameMapType[]> = {
|
||||
GameMapType.DeglaciatedAntarctica,
|
||||
GameMapType.Achiran,
|
||||
GameMapType.BaikalNukeWars,
|
||||
GameMapType.FourIslands,
|
||||
],
|
||||
};
|
||||
|
||||
@@ -601,7 +603,7 @@ export interface Player {
|
||||
decayRelations(): void;
|
||||
isOnSameTeam(other: Player): boolean;
|
||||
// Either allied or on same team.
|
||||
isFriendly(other: Player): boolean;
|
||||
isFriendly(other: Player, treatAFKFriendly?: boolean): boolean;
|
||||
team(): Team | null;
|
||||
clan(): string | null;
|
||||
incomingAllianceRequests(): AllianceRequest[];
|
||||
|
||||
@@ -895,6 +895,20 @@ export class GameImpl implements Game {
|
||||
return this._railNetwork;
|
||||
}
|
||||
conquerPlayer(conqueror: Player, conquered: Player) {
|
||||
if (conquered.isDisconnected() && conqueror.isOnSameTeam(conquered)) {
|
||||
const ships = conquered
|
||||
.units()
|
||||
.filter(
|
||||
(u) =>
|
||||
u.type() === UnitType.Warship ||
|
||||
u.type() === UnitType.TransportShip,
|
||||
);
|
||||
|
||||
for (const ship of ships) {
|
||||
conqueror.captureUnit(ship);
|
||||
}
|
||||
}
|
||||
|
||||
const gold = conquered.gold();
|
||||
this.displayMessage(
|
||||
`Conquered ${conquered.displayName()} received ${renderNumber(
|
||||
|
||||
@@ -181,6 +181,7 @@ export interface AllianceView {
|
||||
other: PlayerID;
|
||||
createdAt: Tick;
|
||||
expiresAt: Tick;
|
||||
hasExtensionRequest: boolean;
|
||||
}
|
||||
|
||||
export interface AllianceRequestUpdate {
|
||||
|
||||
@@ -190,6 +190,8 @@ export class PlayerView {
|
||||
|
||||
private _territoryColor: Colord;
|
||||
private _borderColor: Colord;
|
||||
// Update here to include structure light and dark colors
|
||||
private _structureColors: { light: Colord; dark: Colord };
|
||||
private _defendedBorderColors: { light: Colord; dark: Colord };
|
||||
|
||||
constructor(
|
||||
@@ -235,6 +237,11 @@ export class PlayerView {
|
||||
this._territoryColor = defaultTerritoryColor;
|
||||
}
|
||||
|
||||
this._structureColors = this.game
|
||||
.config()
|
||||
.theme()
|
||||
.structureColors(this._territoryColor);
|
||||
|
||||
const maybeFocusedBorderColor =
|
||||
this.game.myClientID() === this.data.clientID
|
||||
? this.game.config().theme().focusedBorderColor()
|
||||
@@ -268,6 +275,10 @@ export class PlayerView {
|
||||
return isPrimary ? this._territoryColor : this._borderColor;
|
||||
}
|
||||
|
||||
structureColors(): { light: Colord; dark: Colord } {
|
||||
return this._structureColors;
|
||||
}
|
||||
|
||||
borderColor(tile?: TileRef, isDefended: boolean = false): Colord {
|
||||
if (tile === undefined || !isDefended) {
|
||||
return this._borderColor;
|
||||
|
||||
@@ -173,6 +173,10 @@ export class PlayerImpl implements Player {
|
||||
other: a.other(this).id(),
|
||||
createdAt: a.createdAt(),
|
||||
expiresAt: a.expiresAt(),
|
||||
hasExtensionRequest:
|
||||
a.expiresAt() <=
|
||||
this.mg.ticks() +
|
||||
this.mg.config().allianceExtensionPromptOffset(),
|
||||
}) satisfies AllianceView,
|
||||
),
|
||||
hasSpawned: this.hasSpawned(),
|
||||
@@ -791,8 +795,8 @@ export class PlayerImpl implements Player {
|
||||
return this._team === other.team();
|
||||
}
|
||||
|
||||
isFriendly(other: Player): boolean {
|
||||
if (other.isDisconnected()) {
|
||||
isFriendly(other: Player, treatAFKFriendly: boolean = false): boolean {
|
||||
if (other.isDisconnected() && !treatAFKFriendly) {
|
||||
return false;
|
||||
}
|
||||
return this.isOnSameTeam(other) || this.isAlliedWith(other);
|
||||
|
||||
@@ -148,6 +148,8 @@ export function bestShoreDeploymentSource(
|
||||
if (t === null) return false;
|
||||
|
||||
const candidates = candidateShoreTiles(gm, player, t);
|
||||
if (candidates.length === 0) return false;
|
||||
|
||||
const aStar = new MiniAStar(gm, gm.miniMap(), candidates, t, 1_000_000, 1);
|
||||
const result = aStar.compute();
|
||||
if (result !== PathFindResultType.Completed) {
|
||||
|
||||
Reference in New Issue
Block a user