getMilestones() : []; // Lightens ($percent > 0) or darkens ($percent < 0) a "#rrggbb" color, used // to build each badge's radial-gradient inline (kept as plain computed hex // stops rather than CSS color-mix()/custom properties, for broader browser // compatibility with this project's existing baseline). function tzms_shade($hex, $percent) { $hex = ltrim($hex, '#'); $r = hexdec(substr($hex, 0, 2)); $g = hexdec(substr($hex, 2, 2)); $b = hexdec(substr($hex, 4, 2)); $adjust = function ($c) use ($percent) { $c = $percent < 0 ? $c * (1 + $percent / 100) : $c + (255 - $c) * ($percent / 100); return max(0, min(255, (int) round($c))); }; return sprintf('#%02x%02x%02x', $adjust($r), $adjust($g), $adjust($b)); } // Simple line-icon set (inline SVG, no external image files, so there's // nothing that can 404 regardless of where this is deployed). $milestoneIcons = [ 'village' => '', 'population' => '', 'artifact' => '', 'wonder' => '', 'plan' => '', 'alliance' => '', 'conquest' => '', 'five_villages' => '', ]; $milestoneDefs = [ 'second_village' => ['label' => TZ_MILESTONE_SECOND_VILLAGE, 'icon' => 'village', 'color' => '#c0783c'], 'population_1000' => ['label' => TZ_MILESTONE_POPULATION_1000, 'icon' => 'population', 'color' => '#3c78c0'], 'first_artifact' => ['label' => TZ_MILESTONE_FIRST_ARTIFACT, 'icon' => 'artifact', 'color' => '#8a4fc0'], 'first_ww' => ['label' => TZ_MILESTONE_FIRST_WW, 'icon' => 'wonder', 'color' => '#c0a030'], 'first_ww_plan' => ['label' => TZ_MILESTONE_FIRST_WW_PLAN, 'icon' => 'plan', 'color' => '#2f9e8f'], 'first_alliance' => ['label' => TZ_MILESTONE_FIRST_ALLIANCE, 'icon' => 'alliance', 'color' => '#3fa14a'], 'first_pvp_conquest' => ['label' => TZ_MILESTONE_FIRST_PVP_CONQUEST, 'icon' => 'conquest', 'color' => '#b6362f'], 'five_villages' => ['label' => TZ_MILESTONE_FIVE_VILLAGES, 'icon' => 'five_villages', 'color' => '#7a6030'], ]; ?>
$mdef): $achieved = $milestonesData[$mkey] ?? null; $light = tzms_shade($mdef['color'], 28); $dark = tzms_shade($mdef['color'], -32); $bg = $achieved ? sprintf('background:radial-gradient(circle at 32%% 28%%, %s, %s 55%%, %s 100%%);border-color:rgba(255,255,255,0.35);', $light, $mdef['color'], $dark) : 'background:#d8d8d8;border-color:rgba(0,0,0,0.08);'; $title = htmlspecialchars($mdef['label'], ENT_QUOTES, 'UTF-8'); // Caption text under badge: // - first_alliance shows the alliance name/tag (stored in `extra`) // - all others show the player username if ($achieved) { if ($mkey === 'first_alliance') { $caption = htmlspecialchars($achieved['extra'] ?: $achieved['username'] ?: '', ENT_QUOTES, 'UTF-8'); } else { $caption = htmlspecialchars($achieved['username'] ?: '', ENT_QUOTES, 'UTF-8'); } } else { $caption = ''; } // Tooltip meta line: // - first_alliance: shows alliance name on first line, founder + date on second // - all others: "Username — dd.mm.yy H:i:s" if ($achieved) { if ($mkey === 'first_alliance') { $meta = htmlspecialchars( ($achieved['extra'] ?: '-') . "\n" . TZ_MILESTONE_FOUNDED_BY . ' ' . ($achieved['username'] ?: '-') . ' — ' . date('d.m.y G:i:s', (int)$achieved['achieved_time']), ENT_QUOTES, 'UTF-8' ); } else { $meta = htmlspecialchars( ($achieved['username'] ?: '-') . ' — ' . date('d.m.y G:i:s', (int)$achieved['achieved_time']), ENT_QUOTES, 'UTF-8' ); } } else { $meta = htmlspecialchars(TZ_MILESTONE_NOT_YET, ENT_QUOTES, 'UTF-8'); } ?>