feat(icons): Item-Icons fuer alle sechs Items
Lint / Lint Resource (push) Has been cancelled

128x128 PNG mit transparentem Hintergrund, aus SVG-Quellen per ImageMagick
(librsvg) erzeugt und damit reproduzierbar statt handgemalt.

- Tauchmaske, quer liegende Pressluft-Kartusche mit Manometer, drei
  Einzelflaschen und die Doppelflasche fuer XL
- Laufzeit als Zahl auf dem Farbband: ohne die waren die Einzelflaschen bei
  Slot-Groesse nur noch an der Bandfarbe zu unterscheiden, im 56px-Test gar
  nicht mehr
- Kartusche bewusst liegend statt hochkant, damit sie sich von den Flaschen
  abhebt - die erste Fassung las sich wie eine Flasche mit Download-Pfeil
- client.image faellt weg: ox_inventory laedt <imagepath>/<itemname>.png, und
  die Dateien heissen genau wie die Items

gen-icons.mjs schreibt zusaetzlich ein Kontrollblatt (Schachbrett, Slot-Groesse,
klein), mit dem die Icons gegengeprueft wurden.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 00:25:39 +02:00
co-authored by Claude Opus 5
parent ce0f693266
commit 6432550f68
20 changed files with 372 additions and 23 deletions
+3
View File
@@ -1,2 +1,5 @@
# Self-contained NUI-Vorschau, gebaut von .tools/nui-preview.mjs # Self-contained NUI-Vorschau, gebaut von .tools/nui-preview.mjs
nui/_preview.html nui/_preview.html
# Kontrollblatt, gebaut von icons/gen-icons.mjs
icons/_check.html
+30 -11
View File
@@ -61,23 +61,28 @@ weich ein und aus.
und in `ox_inventory/data/items.lua` innerhalb der `return { … }`-Klammer und in `ox_inventory/data/items.lua` innerhalb der `return { … }`-Klammer
einfügen. Sechs Items, nichts weiter anzupassen. einfügen. Sechs Items, nichts weiter anzupassen.
3. Icons nach `cdn.d4rkst3r.de/items/` legen: `diving_gear.png`, 3. Die sechs PNGs aus [`icons/`](icons) nach `cdn.d4rkst3r.de/items/` hochladen.
`diving_fill.png`, `diving_tank_small.png`, `diving_tank_medium.png`, Sie heißen genau wie die Items, deshalb braucht es kein `client.image`.
`diving_tank_large.png`, `diving_tank_xl.png`.
Es gibt bewusst **keine** fertige `items.lua` zum Ersetzen — die würde die Es gibt bewusst **keine** fertige `items.lua` zum Ersetzen — die würde die
restlichen Items des Servers überschreiben. restlichen Items des Servers überschreiben.
## Items ## Items
| Item | Label | Laufzeit | Fülldruck | Gewicht | | Icon | Item | Label | Laufzeit | Fülldruck | Gewicht |
|---|---|---|---|---| |---|---|---|---|---|---|
| `diving_gear` | Tauchausrüstung | — | — | 5000 | | <img src="icons/diving_gear.png" width="40"> | `diving_gear` | Tauchausrüstung | — | — | 5000 |
| `diving_fill` | Pressluft-Kartusche | — | — | 1000 | | <img src="icons/diving_fill.png" width="40"> | `diving_fill` | Pressluft-Kartusche | — | — | 1000 |
| `diving_tank_small` | Tauchflasche (5 Min) | 300 s | 300 bar | 4000 | | <img src="icons/diving_tank_small.png" width="40"> | `diving_tank_small` | Tauchflasche (5 Min) | 300 s | 300 bar | 4000 |
| `diving_tank_medium` | Tauchflasche (10 Min) | 600 s | 300 bar | 7000 | | <img src="icons/diving_tank_medium.png" width="40"> | `diving_tank_medium` | Tauchflasche (10 Min) | 600 s | 300 bar | 7000 |
| `diving_tank_large` | Tauchflasche (15 Min) | 900 s | 300 bar | 10000 | | <img src="icons/diving_tank_large.png" width="40"> | `diving_tank_large` | Tauchflasche (15 Min) | 900 s | 300 bar | 10000 |
| `diving_tank_xl` | Tauchflasche (20 Min) | 1200 s | 300 bar | 13000 | | <img src="icons/diving_tank_xl.png" width="40"> | `diving_tank_xl` | Tauchflasche (20 Min) | 1200 s | 300 bar | 13000 |
Die Icons liegen als 128×128 PNG mit transparentem Hintergrund in
[`icons/`](icons), die SVG-Quellen in `icons/src/`. Die Laufzeit steht als Zahl
auf dem Farbband — ohne die sind die Einzelflaschen im Inventar nur noch an der
Bandfarbe auseinanderzuhalten. Wer `capacity` ändert, sollte die Zahlen in
`icons/gen-icons.mjs` mitziehen.
Dass alle Flaschen mit demselben Fülldruck starten, ist gewollt: in echt macht das Dass alle Flaschen mit demselben Fülldruck starten, ist gewollt: in echt macht das
Volumen die Laufzeit, nicht der Druck. Die große Flasche hält 300 bar einfach länger. Volumen die Laufzeit, nicht der Druck. Die große Flasche hält 300 bar einfach länger.
@@ -197,8 +202,22 @@ solcher Punkte enthält also den Pitch.
node ../.tools/lint.mjs # Lua-Lint, CfxLua-tauglich node ../.tools/lint.mjs # Lua-Lint, CfxLua-tauglich
node ../.tools/nui-preview.mjs nui # HUD im Browser anschauen node ../.tools/nui-preview.mjs nui # HUD im Browser anschauen
node docs/gen-hud-svg.mjs docs # Renderings für diese README neu bauen node docs/gen-hud-svg.mjs docs # Renderings für diese README neu bauen
# Item-Icons neu bauen (SVG -> PNG, braucht ImageMagick mit librsvg)
node icons/gen-icons.mjs
for f in icons/src/*.svg; do
magick -background none "$f" -resize 128x128 "icons/$(basename "$f" .svg).png"
done
``` ```
`gen-icons.mjs` schreibt außerdem `icons/_check.html` — alle Icons auf
Schachbrett, in Slot-Größe und klein, zum Gegenschauen nach Änderungen.
> librsvg 2.40 wirft beim Rendern der Zahlen ein
> `Invalid UTF-8 string passed to pango_layout_set_text()`. Das ist harmlos und
> passiert bei jedem `<text>`-Element, auch im minimalsten Testfall — die Zahlen
> kommen korrekt raus.
Der Umbau ist in [PLAN.md](PLAN.md) dokumentiert, inklusive der offenen Punkte. Der Umbau ist in [PLAN.md](PLAN.md) dokumentiert, inklusive der offenen Punkte.
## Bekannte Unsicherheiten ## Bekannte Unsicherheiten
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

+175
View File
@@ -0,0 +1,175 @@
#!/usr/bin/env node
// Erzeugt die Item-Icons als SVG. Die PNGs macht danach ImageMagick daraus:
//
// node icons/gen-icons.mjs
// for f in icons/src/*.svg; do magick -background none "$f" -resize 128x128 "icons/$(basename "$f" .svg).png"; done
//
// Nur SVG 1.1 mit Presentation-Attributen, keine CSS-Bloecke und keine Filter -
// gerendert wird mit librsvg 2.40, und das ist alt.
//
// librsvg 2.40 wirft bei jedem <text>-Element ein
// WARNING: Invalid UTF-8 string passed to pango_layout_set_text()
// Das ist harmlos und tritt auch beim minimalsten Testfall auf - die Zahlen auf
// den Flaschen rendern korrekt. Nachgeprueft, nicht ignoriert.
//
// Erzeugt nebenbei icons/_check.html: alle Icons auf Schachbrett, in Slot-Groesse
// und klein, zum Gegenschauen nach Aenderungen.
import { writeFileSync, mkdirSync } from 'node:fs';
import { join, dirname } from 'node:path';
const OUT = join(process.argv[2] ?? 'icons', 'src');
mkdirSync(OUT, { recursive: true });
const S = 128; // Canvas, quadratisch
const C = {
steelLight: '#cbd5e1',
steel: '#94a3b8',
steelDark: '#64748b',
valve: '#334155',
valveDark: '#1e293b',
glass: '#38bdf8',
glassDark: '#0284c7',
rubber: '#1e293b',
outline: '#0f172a'
};
/** Farbband pro Groesse, damit die Flaschen im Inventar auf einen Blick unterscheidbar sind. */
const BANDS = {
small: '#4ade80',
medium: '#38bdf8',
large: '#fbbf24',
xl: '#f472b6'
};
const defs = `<defs>
<linearGradient id="steel" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="${C.steelDark}"/>
<stop offset="28%" stop-color="${C.steelLight}"/>
<stop offset="55%" stop-color="${C.steel}"/>
<stop offset="100%" stop-color="${C.steelDark}"/>
</linearGradient>
<linearGradient id="glass" x1="0" y1="0" x2="0.7" y2="1">
<stop offset="0%" stop-color="${C.glass}"/>
<stop offset="100%" stop-color="${C.glassDark}"/>
</linearGradient>
</defs>`;
const svg = (body) =>
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${S} ${S}" width="${S}" height="${S}">
${defs}
${body}
</svg>
`;
/**
* Eine Tauchflasche. cx = Mittelachse, w = Breite, top/bottom = Koerper in y.
* minutes = Laufzeit aufs Band gedruckt. Ohne die Zahl sind die Einzelflaschen
* bei kleiner Darstellung nur noch an der Bandfarbe auseinanderzuhalten.
*/
function tank(cx, w, top, bottom, band, minutes) {
const x = cx - w / 2;
const h = bottom - top;
const valveW = w * 0.4;
const bandY = top + h * 0.34;
const bandH = 22;
const label = minutes
? `<text x="${cx}" y="${bandY + bandH - 6}" text-anchor="middle" font-family="sans-serif"
font-size="16" font-weight="700" fill="${C.outline}">${minutes}</text>`
: '';
return ` <g>
<rect x="${cx - valveW / 2}" y="${top - 14}" width="${valveW}" height="17" rx="3" fill="${C.valve}"/>
<circle cx="${cx}" cy="${top - 17}" r="8" fill="none" stroke="${C.valveDark}" stroke-width="4.5"/>
<rect x="${x}" y="${top}" width="${w}" height="${h}" rx="${w / 2.4}" fill="url(#steel)" stroke="${C.outline}" stroke-width="2.5"/>
<rect x="${x + w * 0.15}" y="${top + h * 0.08}" width="${w * 0.13}" height="${h * 0.5}" rx="${w * 0.065}" fill="${C.steelLight}" opacity="0.75"/>
<rect x="${x}" y="${bandY}" width="${w}" height="${bandH}" fill="${band}"/>
${label}
</g>`;
}
// --- Flaschen: gleiche Breite, wachsende Hoehe. Die Silhouette traegt die Info,
// --- das Farbband hilft zusaetzlich.
const sizes = {
diving_tank_small: { w: 42, top: 48, bottom: 114, band: BANDS.small, minutes: 5 },
diving_tank_medium: { w: 46, top: 36, bottom: 116, band: BANDS.medium, minutes: 10 },
diving_tank_large: { w: 50, top: 26, bottom: 118, band: BANDS.large, minutes: 15 }
};
for (const [name, cfg] of Object.entries(sizes)) {
writeFileSync(join(OUT, `${name}.svg`), svg(tank(64, cfg.w, cfg.top, cfg.bottom, cfg.band, cfg.minutes)));
}
// --- XL = Doppelflasche, passend zum Label. Die Zahl steht auf einem Band
// --- ueber beide Flaschen, sonst muesste sie zweimal auftauchen.
writeFileSync(join(OUT, 'diving_tank_xl.svg'), svg(
` <rect x="38" y="26" width="52" height="8" rx="4" fill="${C.valveDark}"/>
${tank(46, 38, 38, 118, BANDS.xl)}
${tank(82, 38, 38, 118, BANDS.xl)}
<rect x="27" y="65" width="74" height="23" rx="4" fill="${BANDS.xl}" stroke="${C.outline}" stroke-width="2"/>
<text x="64" y="82" text-anchor="middle" font-family="sans-serif"
font-size="16" font-weight="700" fill="${C.outline}">20</text>`
));
// --- Tauchmaske
writeFileSync(join(OUT, 'diving_gear.svg'), svg(
` <path d="M18 62 L30 52 L30 78 L18 72 Z" fill="${C.rubber}"/>
<path d="M110 62 L98 52 L98 78 L110 72 Z" fill="${C.rubber}"/>
<rect x="22" y="60" width="84" height="9" rx="4.5" fill="${C.rubber}"/>
<path d="M34 40 h60 a12 12 0 0 1 12 12 v22 a16 16 0 0 1 -16 16 h-8 l-8 -7 h-12 l-8 7 h-8 a16 16 0 0 1 -16 -16 v-22 a12 12 0 0 1 12 -12 z"
fill="${C.rubber}" stroke="${C.outline}" stroke-width="2.5"/>
<path d="M42 50 h44 a7 7 0 0 1 7 7 v14 a10 10 0 0 1 -10 10 h-6 l-7 -6 h-12 l-7 6 h-6 a10 10 0 0 1 -10 -10 v-14 a7 7 0 0 1 7 -7 z"
fill="url(#glass)"/>
<path d="M48 55 h13 l-11 22 h-6 a5 5 0 0 1 -5 -5 v-9 z" fill="#ffffff" opacity="0.32"/>
<rect x="58" y="88" width="12" height="16" rx="4" fill="${C.valve}"/>
<circle cx="64" cy="104" r="9" fill="${C.valveDark}" stroke="${C.outline}" stroke-width="2"/>`
));
// --- Pressluft-Kartusche: liegende, gedrungene Form mit Manometer. Bewusst quer
// --- statt hochkant, damit sie sich auf einen Blick von den Flaschen abhebt.
writeFileSync(join(OUT, 'diving_fill.svg'), svg(
` <rect x="18" y="44" width="86" height="44" rx="22" fill="url(#steel)" stroke="${C.outline}" stroke-width="2.5"/>
<rect x="30" y="52" width="44" height="7" rx="3.5" fill="${C.steelLight}" opacity="0.8"/>
<rect x="24" y="44" width="9" height="44" fill="${C.glass}" opacity="0.85"/>
<rect x="88" y="44" width="9" height="44" fill="${C.glass}" opacity="0.85"/>
<rect x="99" y="58" width="14" height="16" rx="4" fill="${C.valve}"/>
<rect x="110" y="62" width="9" height="8" rx="3" fill="${C.valveDark}"/>
<circle cx="62" cy="66" r="17" fill="${C.valveDark}" stroke="${C.outline}" stroke-width="2.5"/>
<circle cx="62" cy="66" r="12" fill="${C.steelLight}"/>
<path d="M62 66 l8 -7" fill="none" stroke="${C.outline}" stroke-width="3" stroke-linecap="round"/>
<circle cx="62" cy="66" r="2.5" fill="${C.outline}"/>`
));
// --- Kontrollblatt
const NAMES = [
'diving_gear', 'diving_fill',
'diving_tank_small', 'diving_tank_medium', 'diving_tank_large', 'diving_tank_xl'
];
const slots = (extra = '') =>
NAMES.map((n) => `<div class="slot${extra}"><img src="${n}.png" alt="${n}" title="${n}"></div>`).join('');
writeFileSync(join(dirname(OUT), '_check.html'), `<style>
body{margin:0;padding:16px;font:12px 'Segoe UI',sans-serif;background:#0f172a;color:#cbd5e1}
h3{margin:18px 0 8px;font-size:11px;letter-spacing:1px;text-transform:uppercase;color:#94a3b8}
.row{display:flex;gap:10px;flex-wrap:wrap;padding:12px;border-radius:10px}
.checker{background-color:#94a3b8;background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0;
background-image:linear-gradient(45deg,#64748b 25%,transparent 25%),linear-gradient(-45deg,#64748b 25%,transparent 25%),
linear-gradient(45deg,transparent 75%,#64748b 75%),linear-gradient(-45deg,transparent 75%,#64748b 75%)}
.dark{background:#1e293b}
.slot{width:100px;height:100px;display:flex;align-items:center;justify-content:center}
.dark .slot{border:1px solid rgba(148,163,184,.35);border-radius:8px;background:rgba(0,0,0,.25)}
.slot img{max-width:88px;max-height:88px}
.small .slot{width:56px;height:56px}.small .slot img{max-width:48px;max-height:48px}
</style>
<h3>Transparenz</h3>
<div class="row checker">${slots()}</div>
<h3>Inventar-Slot 100px</h3>
<div class="row dark">${slots()}</div>
<h3>Klein 56px</h3>
<div class="row dark small">${slots()}</div>
`);
console.log('SVGs in', OUT, '+ _check.html');
+24
View File
@@ -0,0 +1,24 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
<defs>
<linearGradient id="steel" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#64748b"/>
<stop offset="28%" stop-color="#cbd5e1"/>
<stop offset="55%" stop-color="#94a3b8"/>
<stop offset="100%" stop-color="#64748b"/>
</linearGradient>
<linearGradient id="glass" x1="0" y1="0" x2="0.7" y2="1">
<stop offset="0%" stop-color="#38bdf8"/>
<stop offset="100%" stop-color="#0284c7"/>
</linearGradient>
</defs>
<rect x="18" y="44" width="86" height="44" rx="22" fill="url(#steel)" stroke="#0f172a" stroke-width="2.5"/>
<rect x="30" y="52" width="44" height="7" rx="3.5" fill="#cbd5e1" opacity="0.8"/>
<rect x="24" y="44" width="9" height="44" fill="#38bdf8" opacity="0.85"/>
<rect x="88" y="44" width="9" height="44" fill="#38bdf8" opacity="0.85"/>
<rect x="99" y="58" width="14" height="16" rx="4" fill="#334155"/>
<rect x="110" y="62" width="9" height="8" rx="3" fill="#1e293b"/>
<circle cx="62" cy="66" r="17" fill="#1e293b" stroke="#0f172a" stroke-width="2.5"/>
<circle cx="62" cy="66" r="12" fill="#cbd5e1"/>
<path d="M62 66 l8 -7" fill="none" stroke="#0f172a" stroke-width="3" stroke-linecap="round"/>
<circle cx="62" cy="66" r="2.5" fill="#0f172a"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+24
View File
@@ -0,0 +1,24 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
<defs>
<linearGradient id="steel" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#64748b"/>
<stop offset="28%" stop-color="#cbd5e1"/>
<stop offset="55%" stop-color="#94a3b8"/>
<stop offset="100%" stop-color="#64748b"/>
</linearGradient>
<linearGradient id="glass" x1="0" y1="0" x2="0.7" y2="1">
<stop offset="0%" stop-color="#38bdf8"/>
<stop offset="100%" stop-color="#0284c7"/>
</linearGradient>
</defs>
<path d="M18 62 L30 52 L30 78 L18 72 Z" fill="#1e293b"/>
<path d="M110 62 L98 52 L98 78 L110 72 Z" fill="#1e293b"/>
<rect x="22" y="60" width="84" height="9" rx="4.5" fill="#1e293b"/>
<path d="M34 40 h60 a12 12 0 0 1 12 12 v22 a16 16 0 0 1 -16 16 h-8 l-8 -7 h-12 l-8 7 h-8 a16 16 0 0 1 -16 -16 v-22 a12 12 0 0 1 12 -12 z"
fill="#1e293b" stroke="#0f172a" stroke-width="2.5"/>
<path d="M42 50 h44 a7 7 0 0 1 7 7 v14 a10 10 0 0 1 -10 10 h-6 l-7 -6 h-12 l-7 6 h-6 a10 10 0 0 1 -10 -10 v-14 a7 7 0 0 1 7 -7 z"
fill="url(#glass)"/>
<path d="M48 55 h13 l-11 22 h-6 a5 5 0 0 1 -5 -5 v-9 z" fill="#ffffff" opacity="0.32"/>
<rect x="58" y="88" width="12" height="16" rx="4" fill="#334155"/>
<circle cx="64" cy="104" r="9" fill="#1e293b" stroke="#0f172a" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+23
View File
@@ -0,0 +1,23 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
<defs>
<linearGradient id="steel" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#64748b"/>
<stop offset="28%" stop-color="#cbd5e1"/>
<stop offset="55%" stop-color="#94a3b8"/>
<stop offset="100%" stop-color="#64748b"/>
</linearGradient>
<linearGradient id="glass" x1="0" y1="0" x2="0.7" y2="1">
<stop offset="0%" stop-color="#38bdf8"/>
<stop offset="100%" stop-color="#0284c7"/>
</linearGradient>
</defs>
<g>
<rect x="54" y="12" width="20" height="17" rx="3" fill="#334155"/>
<circle cx="64" cy="9" r="8" fill="none" stroke="#1e293b" stroke-width="4.5"/>
<rect x="39" y="26" width="50" height="92" rx="20.833333333333336" fill="url(#steel)" stroke="#0f172a" stroke-width="2.5"/>
<rect x="46.5" y="33.36" width="6.5" height="46" rx="3.25" fill="#cbd5e1" opacity="0.75"/>
<rect x="39" y="57.28" width="50" height="22" fill="#fbbf24"/>
<text x="64" y="73.28" text-anchor="middle" font-family="sans-serif"
font-size="16" font-weight="700" fill="#0f172a">15</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+23
View File
@@ -0,0 +1,23 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
<defs>
<linearGradient id="steel" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#64748b"/>
<stop offset="28%" stop-color="#cbd5e1"/>
<stop offset="55%" stop-color="#94a3b8"/>
<stop offset="100%" stop-color="#64748b"/>
</linearGradient>
<linearGradient id="glass" x1="0" y1="0" x2="0.7" y2="1">
<stop offset="0%" stop-color="#38bdf8"/>
<stop offset="100%" stop-color="#0284c7"/>
</linearGradient>
</defs>
<g>
<rect x="54.8" y="22" width="18.400000000000002" height="17" rx="3" fill="#334155"/>
<circle cx="64" cy="19" r="8" fill="none" stroke="#1e293b" stroke-width="4.5"/>
<rect x="41" y="36" width="46" height="80" rx="19.166666666666668" fill="url(#steel)" stroke="#0f172a" stroke-width="2.5"/>
<rect x="47.9" y="42.4" width="5.98" height="40" rx="2.99" fill="#cbd5e1" opacity="0.75"/>
<rect x="41" y="63.2" width="46" height="22" fill="#38bdf8"/>
<text x="64" y="79.2" text-anchor="middle" font-family="sans-serif"
font-size="16" font-weight="700" fill="#0f172a">10</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+23
View File
@@ -0,0 +1,23 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
<defs>
<linearGradient id="steel" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#64748b"/>
<stop offset="28%" stop-color="#cbd5e1"/>
<stop offset="55%" stop-color="#94a3b8"/>
<stop offset="100%" stop-color="#64748b"/>
</linearGradient>
<linearGradient id="glass" x1="0" y1="0" x2="0.7" y2="1">
<stop offset="0%" stop-color="#38bdf8"/>
<stop offset="100%" stop-color="#0284c7"/>
</linearGradient>
</defs>
<g>
<rect x="55.6" y="34" width="16.8" height="17" rx="3" fill="#334155"/>
<circle cx="64" cy="31" r="8" fill="none" stroke="#1e293b" stroke-width="4.5"/>
<rect x="43" y="48" width="42" height="66" rx="17.5" fill="url(#steel)" stroke="#0f172a" stroke-width="2.5"/>
<rect x="49.3" y="53.28" width="5.46" height="33" rx="2.73" fill="#cbd5e1" opacity="0.75"/>
<rect x="43" y="70.44" width="42" height="22" fill="#4ade80"/>
<text x="64" y="86.44" text-anchor="middle" font-family="sans-serif"
font-size="16" font-weight="700" fill="#0f172a">5</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+34
View File
@@ -0,0 +1,34 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
<defs>
<linearGradient id="steel" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#64748b"/>
<stop offset="28%" stop-color="#cbd5e1"/>
<stop offset="55%" stop-color="#94a3b8"/>
<stop offset="100%" stop-color="#64748b"/>
</linearGradient>
<linearGradient id="glass" x1="0" y1="0" x2="0.7" y2="1">
<stop offset="0%" stop-color="#38bdf8"/>
<stop offset="100%" stop-color="#0284c7"/>
</linearGradient>
</defs>
<rect x="38" y="26" width="52" height="8" rx="4" fill="#1e293b"/>
<g>
<rect x="38.4" y="24" width="15.200000000000001" height="17" rx="3" fill="#334155"/>
<circle cx="46" cy="21" r="8" fill="none" stroke="#1e293b" stroke-width="4.5"/>
<rect x="27" y="38" width="38" height="80" rx="15.833333333333334" fill="url(#steel)" stroke="#0f172a" stroke-width="2.5"/>
<rect x="32.7" y="44.4" width="4.94" height="40" rx="2.47" fill="#cbd5e1" opacity="0.75"/>
<rect x="27" y="65.2" width="38" height="22" fill="#f472b6"/>
</g>
<g>
<rect x="74.4" y="24" width="15.200000000000001" height="17" rx="3" fill="#334155"/>
<circle cx="82" cy="21" r="8" fill="none" stroke="#1e293b" stroke-width="4.5"/>
<rect x="63" y="38" width="38" height="80" rx="15.833333333333334" fill="url(#steel)" stroke="#0f172a" stroke-width="2.5"/>
<rect x="68.7" y="44.4" width="4.94" height="40" rx="2.47" fill="#cbd5e1" opacity="0.75"/>
<rect x="63" y="65.2" width="38" height="22" fill="#f472b6"/>
</g>
<rect x="27" y="65" width="74" height="23" rx="4" fill="#f472b6" stroke="#0f172a" stroke-width="2"/>
<text x="64" y="82" text-anchor="middle" font-family="sans-serif"
font-size="16" font-weight="700" fill="#0f172a">20</text>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

+10 -12
View File
@@ -8,6 +8,10 @@
-- Bewusst KEINE fertige items.lua zum Ersetzen: die würde die restlichen Items -- Bewusst KEINE fertige items.lua zum Ersetzen: die würde die restlichen Items
-- des Servers mitlöschen. -- des Servers mitlöschen.
-- --
-- Kein client.image gesetzt: ox_inventory lädt <imagepath>/<itemname>.png, und die
-- Icons in icons/ heißen genau wie die Items. Einfach nach cdn.d4rkst3r.de/items/
-- hochladen, fertig.
--
-- WICHTIG: kein `decay = true` auf den Flaschen. Die durability trägt hier den -- WICHTIG: kein `decay = true` auf den Flaschen. Die durability trägt hier den
-- Füllstand, und ox_inventory löscht Items mit decay, sobald durability 0 erreicht -- Füllstand, und ox_inventory löscht Items mit decay, sobald durability 0 erreicht
-- (modules/items/server.lua) - die leere Flasche würde also verschwinden statt -- (modules/items/server.lua) - die leere Flasche würde also verschwinden statt
@@ -23,8 +27,7 @@
stack = false, stack = false,
close = true, close = true,
consume = 0, consume = 0,
description = 'Maske und Tauchanzug. Benutzen zum An- und Ausziehen.', description = 'Maske und Tauchanzug. Benutzen zum An- und Ausziehen.'
client = { image = 'diving_gear.png' }
}, },
['diving_fill'] = { ['diving_fill'] = {
@@ -33,8 +36,7 @@
stack = true, stack = true,
close = true, close = true,
consume = 0, consume = 0,
description = 'Füllt eine Tauchflasche wieder auf.', description = 'Füllt eine Tauchflasche wieder auf.'
client = { image = 'diving_fill.png' }
}, },
['diving_tank_small'] = { ['diving_tank_small'] = {
@@ -43,8 +45,7 @@
stack = false, stack = false,
close = true, close = true,
consume = 0, consume = 0,
description = 'Kleine Tauchflasche, 300 bar. Reicht für etwa 5 Minuten.', description = 'Kleine Tauchflasche, 300 bar. Reicht für etwa 5 Minuten.'
client = { image = 'diving_tank_small.png' }
}, },
['diving_tank_medium'] = { ['diving_tank_medium'] = {
@@ -53,8 +54,7 @@
stack = false, stack = false,
close = true, close = true,
consume = 0, consume = 0,
description = 'Mittlere Tauchflasche, 300 bar. Reicht für etwa 10 Minuten.', description = 'Mittlere Tauchflasche, 300 bar. Reicht für etwa 10 Minuten.'
client = { image = 'diving_tank_medium.png' }
}, },
['diving_tank_large'] = { ['diving_tank_large'] = {
@@ -63,8 +63,7 @@
stack = false, stack = false,
close = true, close = true,
consume = 0, consume = 0,
description = 'Große Tauchflasche, 300 bar. Reicht für etwa 15 Minuten.', description = 'Große Tauchflasche, 300 bar. Reicht für etwa 15 Minuten.'
client = { image = 'diving_tank_large.png' }
}, },
['diving_tank_xl'] = { ['diving_tank_xl'] = {
@@ -73,6 +72,5 @@
stack = false, stack = false,
close = true, close = true,
consume = 0, consume = 0,
description = 'Doppelflasche, 300 bar. Reicht für etwa 20 Minuten.', description = 'Doppelflasche, 300 bar. Reicht für etwa 20 Minuten.'
client = { image = 'diving_tank_xl.png' }
}, },
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40" width="40" height="40"><text x="20" y="25" text-anchor="middle" font-family="sans-serif" font-size="16" font-weight="700" fill="#000">5</text></svg>

After

Width:  |  Height:  |  Size: 208 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

+2
View File
@@ -0,0 +1,2 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40" width="40" height="40"><text x="20" y="25" text-anchor="middle" font-family="sans-serif"
font-size="16" font-weight="700" fill="#000">5</text></svg>

After

Width:  |  Height:  |  Size: 210 B