REM-Client b61ca7c3: RTS mode - the system from above, orders for the own pilots, building in dynamic systems

This commit is contained in:
2026-11-09 14:21:51 +01:00
parent 3fc970d44e
commit 0816a38430
4 changed files with 167 additions and 3 deletions
+3 -3
View File
@@ -1,6 +1,6 @@
REM-Client test build (64-bit)
date: 2026-11-09 13:03
commit: f3b0dec7 (main)
subject: Skybox as a RemGfx cube map, captured environment and image based lighting
date: 2026-11-09 14:21
commit: b61ca7c3 (main)
subject: RTS mode: the real space camera from above, the own pilots ordered as in a strategy game
tree: clean
build: OK
Binary file not shown.
+1
View File
@@ -255,6 +255,7 @@
<div class="fp lhead">
<span class="ttl">{{ mode == 1 ? 'TARGET' : 'CONTACTS' }}<span class="sl">\\\</span></span>
<span class="sp"></span>
<div class="ib" data-action="rts" title="Tactical view (F9)"><img class="ico" src="3db:interface/HUD/HUD_contactgroup.3db"/></div>
<div class="ib" data-for="t : tabs" data-class-on="t.active" data-action="tab" data-attr-data-arg="t.key"><img class="ico" data-attr-src="t.icon"/></div>
</div>
<div class="fp lbody">
+163
View File
@@ -0,0 +1,163 @@
<rml>
<head>
<title>Tactical</title>
<link type="text/rcss" href="rem.rcss"/>
<style>
/* the RTS mode (rem_ui_rts.cpp): the system from above - <rtsview> over the whole screen draws the grid, the zones,
the objects, the pilots, their orders and the selection box; names as labels over it; around it the top bar,
the minimap (bottom left), the selection with its orders (bottom centre) and the pilot list (right) */
body.rts { position: absolute; left: 0; top: 0; right: 0; bottom: 0; background-color: transparent; font-family: "Saira SemiCondensed"; font-size: 15dp; color: #dbe6f0; }
rtsview { display: block; position: absolute; left: 0; top: 0; right: 0; bottom: 0; }
rtsmini { display: block; position: absolute; left: 14dp; top: 40dp; width: 212dp; height: 212dp; }
.fp { position: absolute; box-sizing: border-box; decorator: ninepatch(fb, fb-i); }
.ttl { font-weight: 600; font-size: 16dp; letter-spacing: 2dp; color: #f2b13c; white-space: nowrap; }
.ttl .sl { margin-left: 10dp; color: #5cc8f0; letter-spacing: -1dp; }
.cap { font-weight: 600; font-size: 11dp; letter-spacing: 1.5dp; color: #8fb3d0; text-transform: uppercase; }
/* labels in the view: no click target */
.lb { position: absolute; pointer-events: none; white-space: nowrap; font-size: 13dp; letter-spacing: 0.5dp; color: #b9d4ea; font-effect: shadow(1dp 1dp #000000e0); }
.lb.off { display: none; }
.lb.sector { font-family: "IBM Plex Mono"; font-size: 15dp; color: #5cc8f0aa; }
.lb.solar { color: #dbe6f0; }
.lb.zone { color: #8fb3d0; font-size: 12dp; text-transform: uppercase; letter-spacing: 1dp; }
.lb.mine { color: #f2b13c; }
.lb.unit { color: #5fd08a; font-weight: 600; }
.lb.unit.sel { color: #f2b13c; }
.lb.ship { color: #b9d4ea; font-size: 12dp; }
.lb.me { color: #ffffff; font-weight: 600; }
/* top bar */
.top { left: 50%; margin-left: -330dp; top: 8dp; width: 660dp; height: 46dp; display: flex; flex-direction: row; align-items: center; padding: 0 12dp 0 18dp; }
.top .sys { margin-left: 14dp; font-weight: 600; font-size: 16dp; color: #e8f4ff; white-space: nowrap; }
.top .sec { margin-left: 10dp; font-family: "IBM Plex Mono"; font-size: 14dp; color: #5cc8f0; white-space: nowrap; }
.top .sp { flex: 1; }
.top .net { margin-left: 10dp; padding: 1dp 6dp; border: 1dp #5cc8f0; font-weight: 600; font-size: 11dp; letter-spacing: 1.5dp; color: #5cc8f0; white-space: nowrap; }
.top .btn { margin-left: 6dp; }
.msg { position: absolute; left: 50%; margin-left: -330dp; top: 58dp; width: 660dp; text-align: center; font-size: 14dp; color: #f2d23c; font-effect: shadow(1dp 1dp #000000e0); pointer-events: none; }
.hint { position: absolute; left: 50%; margin-left: -330dp; top: 78dp; width: 660dp; text-align: center; font-size: 13dp; color: #8197ad; font-effect: shadow(1dp 1dp #000000e0); pointer-events: none; }
/* minimap */
.mini { left: 8dp; bottom: 8dp; width: 240dp; height: 268dp; padding: 10dp 14dp; }
.mini rtsmini { left: 14dp; top: 40dp; }
/* selection + orders */
.selp { left: 50%; margin-left: -330dp; bottom: 8dp; width: 660dp; height: 222dp; padding: 10dp 16dp; }
.selp .head { display: flex; flex-direction: row; align-items: center; height: 26dp; }
.selp .head .sp { flex: 1; }
.cards { display: flex; flex-direction: row; flex-wrap: wrap; height: 92dp; overflow: hidden auto; margin-top: 4dp; }
.card { width: 150dp; height: 40dp; margin: 0 6dp 6dp 0; padding: 3dp 6dp; border: 1dp #24405c; background-color: #122033c0; }
.card:hover { border-color: #5cc8f0; }
.card .n { display: block; font-weight: 600; font-size: 14dp; color: #e8f4ff; white-space: nowrap; overflow: hidden; height: 18dp; }
.card .o { display: block; font-size: 11dp; color: #8fb3d0; white-space: nowrap; overflow: hidden; height: 13dp; }
.card .hb { position: relative; height: 3dp; background-color: #e0484e33; }
.card .hb .f { position: absolute; left: 0; top: 0; bottom: 0; background-color: #5fd08a; }
.none { font-size: 14dp; color: #8197ad; margin-top: 10dp; }
.orders { display: flex; flex-direction: row; flex-wrap: wrap; margin-top: 2dp; }
.orders .btn { margin: 0 6dp 4dp 0; padding: 3dp 10dp; font-size: 13dp; }
.orders .btn.on { color: #f2b13c; }
.orders .btn.off { opacity: 0.4; }
/* building (dynamic systems): the catalog, place / cancel */
.build { left: 8dp; bottom: 284dp; width: 240dp; height: 330dp; padding: 10dp 14dp; }
.blist { position: absolute; left: 14dp; right: 12dp; top: 40dp; bottom: 52dp; }
.bt { position: relative; height: 30dp; padding: 3dp 70dp 0 8dp; border-bottom: 1dp #24405c66; border-left: 3dp #00000000; font-size: 14dp; color: #dbe6f0; white-space: nowrap; overflow: hidden; }
.bt:hover { background-color: #3a8fc822; }
.bt.sel { border-left-color: #f2b13c; color: #f2b13c; background-color: #f2b13c14; }
.bt .pr { position: absolute; right: 4dp; top: 2dp; width: 66dp; text-align: right; font-family: "IBM Plex Mono"; font-size: 11dp; color: #8fb3d0; }
.bt .ct { position: absolute; right: 4dp; top: 15dp; width: 66dp; text-align: right; font-family: "IBM Plex Mono"; font-size: 10dp; color: #5cc8f0; }
.bbtn { position: absolute; left: 14dp; right: 12dp; bottom: 12dp; }
.bbtn .btn { margin-right: 6dp; }
.bbtn .btn.off { opacity: 0.4; }
/* the pilots */
.units { right: 8dp; top: 62dp; width: 300dp; bottom: 238dp; padding: 10dp 14dp; }
.ulist { position: absolute; left: 14dp; right: 10dp; top: 42dp; bottom: 12dp; overflow: hidden auto; }
.u { position: relative; height: 34dp; padding: 2dp 50dp 0 8dp; border-bottom: 1dp #24405c66; border-left: 3dp #00000000; }
.u:hover { background-color: #3a8fc822; }
.u.sel { border-left-color: #f2b13c; background-color: #f2b13c14; }
.u.away { opacity: 0.55; }
.u .n { display: block; font-weight: 600; font-size: 14dp; color: #e8f4ff; height: 17dp; white-space: nowrap; overflow: hidden; }
.u .n .g { font-family: "IBM Plex Mono"; font-size: 12dp; color: #f2b13c; margin-right: 6dp; }
.u .s { display: block; font-size: 11dp; color: #8fb3d0; height: 14dp; white-space: nowrap; overflow: hidden; }
.u .h { position: absolute; right: 6dp; top: 9dp; width: 44dp; text-align: right; font-family: "IBM Plex Mono"; font-size: 12dp; color: #5fd08a; }
.u .h.low { color: #ef6a5b; }
.empty { font-size: 13dp; color: #8197ad; margin: 8dp 0; }
</style>
</head>
<body class="rts" data-model="rts">
<rtsview id="view"/>
<div id="labels"></div>
<div class="fp top">
<span class="ttl">TACTICAL<span class="sl">\\\</span></span>
<span class="sys">{{ system }}</span>
<span class="sec">{{ sector }}</span>
<span class="net" data-if="sensor_net">SENSOR NET</span>
<span class="sp"></span>
<div class="btn" data-if="can_build" data-class-primary="build_open" data-action="build">Build</div>
<div class="btn" data-action="center">Center ship</div>
<div class="btn" data-action="view">{{ topdown ? 'Tilted' : 'Top down' }}</div>
<div class="btn primary" data-action="exit">Exit (F9)</div>
</div>
<div class="msg" data-if="msg != ''">{{ msg }}</div>
<div class="hint">{{ hint }}</div>
<div class="fp mini">
<span class="ttl">SYSTEM<span class="sl">\\\</span></span>
<rtsmini id="mini"/>
</div>
<div class="fp build" data-if="build_open">
<span class="ttl">BUILD<span class="sl">\\\</span></span>
<div class="blist">
<div class="bt" data-for="b : build_types" data-class-sel="b.sel" data-action="btype" data-attr-data-arg="b.id">{{ b.name }}<span class="pr">{{ b.price }}</span><span class="ct">{{ b.count }}</span></div>
</div>
<div class="bbtn">
<div class="btn primary" data-class-off="!plan_set" data-action="place">Place (Enter)</div>
<div class="btn" data-action="bcancel">Cancel</div>
</div>
</div>
<div class="fp selp">
<div class="head">
<span class="ttl">SELECTED {{ sel_count }}<span class="sl">\\\</span></span>
<span class="sp"></span>
<span class="cap">{{ sel_kinds }}</span>
</div>
<div class="none" data-if="sel_count == 0">Drag a box around your pilots or click one. Right click: fly there, attack, follow or mine. Shift queues, Ctrl+1-9 groups.</div>
<div class="cards" data-if="sel_count > 0">
<div class="card" data-for="c : cards" data-action="card" data-attr-data-arg="c.id">
<span class="n">{{ c.name }}</span>
<div class="hb"><div class="f" data-style-width="c.hull"></div></div>
<span class="o">{{ c.order }}</span>
</div>
</div>
<div class="orders" data-if="sel_count > 0">
<div class="btn" data-action="hold">Stop (H)</div>
<div class="btn" data-class-on="mode == 1" data-action="patrol">Patrol (P)</div>
<div class="btn" data-class-on="mode == 2" data-action="amove">Attack (X)</div>
<div class="btn" data-class-on="mode == 5" data-action="defend">Defend area (V)</div>
<div class="btn" data-class-on="mode == 6" data-action="sweep">Clear area (C)</div>
<div class="btn" data-class-on="mode == 7" data-action="jumpwait">Jump &amp; wait (T)</div>
<div class="btn" data-action="guardme">Guard me (G)</div>
<div class="btn" data-action="followme">Follow me</div>
<div class="btn" data-class-off="!can_mine" data-action="mine">Mine (M)</div>
<div class="btn" data-action="job">Back to job (J)</div>
<div class="btn" data-action="home">Home (B)</div>
<div class="btn" data-class-off="!can_launch" data-action="launch">Launch</div>
</div>
</div>
<div class="fp units">
<span class="ttl">PILOTS {{ unit_count }}<span class="sl">\\\</span></span>
<div class="ulist">
<div class="empty" data-if="unit_count == 0">{{ no_units }}</div>
<div class="u" data-for="u : units" data-class-sel="u.sel" data-class-away="!u.here" data-action="unit" data-attr-data-arg="u.id">
<span class="n"><span class="g" data-if="u.group != ''">{{ u.group }}</span>{{ u.name }}</span>
<span class="s">{{ u.status }}</span>
<span class="h" data-class-low="u.low">{{ u.hull }}</span>
</div>
</div>
</div>
</body>
</rml>