shithub: sce

Download patch

ref: 9fba9b42bfc9df98b00fa01753cdfeb9bc214ca8
parent: f409e8573caf34c1fd9a963cc0afb612e8ebc525
author: qwx <qwx@sciops.net>
date: Mon Sep 28 19:26:08 EDT 2020

fs: add support for transparent floating sprites

add gfx entries, which are sprite objects linked to a unit object's
state.
sprite objects are to be decorations drawn on top of a unit.
such sprites use an alpha channel, in which case we save it.
use of an alpha channel is specified in the db file.

--- a/dat.h
+++ b/dat.h
@@ -3,6 +3,7 @@
 typedef struct Attack Attack;
 typedef struct Pic Pic;
 typedef struct Pics Pics;
+typedef struct OState OState;
 typedef struct Obj Obj;
 typedef struct Path Path;
 typedef struct Mobj Mobj;
@@ -68,6 +69,8 @@
 	PFterrain = 1<<0,
 	PFidle = 1<<1,
 	PFmove = 1<<2,
+	PFfloat = 1<<13,
+	PFalpha = 1<<14,
 	PFshadow = 1<<15,
 };
 struct Pic{
@@ -90,10 +93,19 @@
 	Fair = 1<<2,
 	Fbuild = 1<<3,
 };
+enum{
+	OSidle,
+	OSmove,
+	OSend
+};
+struct OState{
+	Pics pics;
+	Obj *gfx;
+	Mobj *mgfx;
+};
 struct Obj{
 	char *name;
-	Pics pidle;
-	Pics pmove;
+	OState state[OSend];
 	int w;
 	int h;
 	int f;
--- a/drw.c
+++ b/drw.c
@@ -273,7 +273,7 @@
 	if(pp->pic != nil)
 		frm = tc % pp->nf;
 	else{
-		pp = &mo->o->pmove;
+		pp = &mo->o->state[OSmove].pics;
 		frm = mo->freezefrm;
 	}
 	assert(pp->pic != nil && pp->shadow != nil);
--- a/fs.c
+++ b/fs.c
@@ -28,6 +28,7 @@
 struct Picl{
 	int frm;
 	int type;
+	int teamcol;
 	char *name;
 	char iname[64];
 	int nr;
@@ -53,7 +54,7 @@
 };
 
 static void
-loadpic(char *name, Pic *pic)
+loadpic(char *name, Pic *pic, int alpha)
 {
 	int fd, n, m, dx, dy;
 	Image *i;
@@ -65,8 +66,8 @@
 	if((i = readimage(display, fd, 0)) == nil)
 		sysfatal("readimage: %r");
 	close(fd);
-	if(i->chan != RGB24)
-		sysfatal("loadpic %s: non-RGB24 image", name);
+	if(alpha && i->chan != RGBA32 || !alpha && i->chan != RGB24)
+		sysfatal("loadpic %s: inappropriate image format", name);
 	dx = Dx(i->r);
 	dy = Dy(i->r);
 	n = dx * dy;
@@ -83,10 +84,12 @@
 	s = b;
 	while(n-- > 0){
 		v = s[2] << 16 | s[1] << 8 | s[0];
-		if(v != bgcol)
+		if(alpha)
+			v |= s[3] << 24; 
+		else if(v != bgcol)
 			v |= 0xff << 24;
 		*p++ = v;
-		s += 3;
+		s += i->depth / 8;
 	}
 	free(b);
 }
@@ -100,7 +103,7 @@
 	for(i=0; i<pl->nr; i++){
 		snprint(path, sizeof path, "%s.%02d.%02d.s.bit",
 			pl->name, pl->frm, rot17idx[i]);
-		loadpic(path, pic++);
+		loadpic(path, pic++, 0);
 	}
 }
 
@@ -115,7 +118,11 @@
 	for(i=0; i<pl->nr; i++){
 		snprint(path, sizeof path, "%s.%02d.%02d.bit",
 			pl->name, pl->frm, rot17idx[i]);
-		loadpic(path, &pic0);
+		loadpic(path, &pic0, pl->type & PFalpha);
+		if(!pl->teamcol){		
+			memcpy(pic, &pic0, sizeof *pic);
+			continue;
+		}
 		if(pic0.h % Nteam != 0)
 			sysfatal("loadobjpic: obj %s sprite sheet %d,%d: height not multiple of %d\n",
 				pl->name, pic0.w, pic0.h, Nteam);
@@ -140,7 +147,7 @@
 
 	if(tilesetpic.p == nil){
 		snprint(path, sizeof path, "%s.bit", tileset);
-		loadpic(path, &tilesetpic);
+		loadpic(path, &tilesetpic, 0);
 		if(tilesetpic.h % tilesetpic.w != 0)
 			sysfatal("loadterpic: tiles not squares: tilepic %d,%d\n",
 				tilesetpic.w, tilesetpic.h);
@@ -197,8 +204,9 @@
 		if(nr != 17 && nr != 1)
 			sysfatal("pushpic %s: invalid number of rotations", iname);
 		n = nr;
-		/* nteam isn't guaranteed to be set correctly by now */
-		if((type & (PFshadow|PFterrain)) == 0)
+		/* nteam isn't guaranteed to be set correctly by now, so
+		 * just set to max */
+		if(pl->teamcol = (type & (PFshadow|PFterrain|PFfloat)) == 0)
 			n *= Nteam;
 		pl->p = emalloc(n * sizeof *pl->p);
 		pl->l = pic->l;
@@ -281,7 +289,7 @@
 			if(*s == 0)
 				sysfatal("vunpack: empty obj");
 			for(o=obj; o<obj+nobj; o++)
-				if(strcmp(s, o->name) == 0)
+				if(o->name != nil && strcmp(s, o->name) == 0)
 					break;
 			if(o == obj + nobj)
 				sysfatal("vunpack: no such obj %s", s);
@@ -387,6 +395,28 @@
 }
 
 static void
+readgfx(char **fld, int, Table *tab)
+{
+	int f;
+	Obj *fxo, *o;
+	OState *s;
+
+	if(obj == nil)
+		obj = emalloc(nobj * sizeof *obj);
+	fxo = obj + nobj - 1 - tab->row;
+	fxo->name = estrdup(*fld++);
+	unpack(fld, "od", &o, &f);
+	fxo->f = f;
+	s = nil;
+	switch(f){
+	case PFidle: s = o->state + OSidle; break;
+	case PFmove: s = o->state + OSmove; break;
+	default: sysfatal("readgfx: %s unknown flag", fxo->name);
+	}
+	s->gfx = fxo;
+}
+
+static void
 readobj(char **fld, int, Table *tab)
 {
 	Obj *o;
@@ -421,9 +451,9 @@
 	fld += 3;
 	n -= 3;
 	ps = nil;
-	switch(type & 0x7e){
-	case PFidle: ps = &o->pidle; break;
-	case PFmove: ps = &o->pmove; break;
+	switch(type & 0xf){
+	case PFidle: ps = &o->state[OSidle].pics; break;
+	case PFmove: ps = &o->state[OSmove].pics; break;
 	default: sysfatal("readspr %s: invalid type %#02ux", o->name, type & 0x7e);
 	}
 	ppp = type & PFshadow ? &ps->shadow : &ps->pic;
@@ -441,15 +471,27 @@
 	}
 }
 
+enum{
+	Tmapobj,
+	Tobj,
+	Tgfx,
+	Tattack,
+	Tresource,
+	Tspawn,
+	Ttileset,
+	Tmap,
+	Tspr,
+};
 Table table[] = {
-	{"mapobj", readmapobj, 4, &nobjp},
-	{"obj", readobj, 17, &nobj},
-	{"attack", readattack, 4, &nattack},
-	{"resource", readresource, 2, &nresource},
-	{"spawn", readspawn, -1, nil},
-	{"tileset", readtileset, 1, nil},
-	{"map", readmap, -1, &terheight},
-	{"spr", readspr, -1, nil},
+	[Tmapobj] {"mapobj", readmapobj, 4, &nobjp},
+	[Tobj] {"obj", readobj, 17, &nobj},
+	[Tgfx] {"gfx", readgfx, 3, &nobj},
+	[Tattack] {"attack", readattack, 4, &nattack},
+	[Tresource] {"resource", readresource, 2, &nresource},
+	[Tspawn] {"spawn", readspawn, -1, nil},
+	[Ttileset] {"tileset", readtileset, 1, nil},
+	[Tmap] {"map", readmap, -1, &terheight},
+	[Tspr] {"spr", readspr, -1, nil},
 };
 
 static int
--- a/sce/sce.db
+++ b/sce/sce.db
@@ -6,18 +6,21 @@
 attack,fusion cutter,5,1,15
 attack,spines,5,1,22
 # obj: name, flags, w, h, hp, def, vis, cost[3], time, attack[2], speed, accel, halt, turn
-obj,scv,3,4,4,60,0,7,1,50,0,20,fusion cutter,,4.97,67,12227,40
-obj,drone,1,4,4,40,0,7,1,50,0,20,spines,,4.97,67,12227,40
-obj,control,8,16,12,1500,1,1,10,400,0,1800,,,0,0,0,0
-obj,hatchery,8,16,12,1250,1,1,10,300,0,1800,,,0,0,0,0
+obj,scv,0x3,4,4,60,0,7,1,50,0,20,fusion cutter,,4.97,67,12227,40
+obj,drone,0x1,4,4,40,0,7,1,50,0,20,spines,,4.97,67,12227,40
+obj,control,0x8,16,12,1500,1,1,10,400,0,1800,,,0,0,0,0
+obj,hatchery,0x8,16,12,1250,1,1,10,300,0,1800,,,0,0,0,0
+# gfx: name, obj, flags (PF enum)
+gfx,tscglow,scv,0x4
 # spawn: objname, [obj..]
 spawn,control,scv
 # spr: objname, flags (PF enum), rotations, [frame..]
-spr,scv,2,17,0
+spr,scv,0x2,17,0
 spr,scv,0x8002,17,0
-spr,control,2,1,0
+spr,control,0x2,1,0
 spr,control,0x8002,1,0
-spr,drone,4,17,0,1,2,3,4
+spr,drone,0x4,17,0,1,2,3,4
 spr,drone,0x8004,17,0,1,2,3,4
 spr,hatchery,2,1,0,1,2,3,3,2,1,0
 spr,hatchery,0x8002,1,0,0,0,0,0,0,0,0
+spr,tscglow,0x6004,17,0,1,2,3
--- a/sim.c
+++ b/sim.c
@@ -90,7 +90,7 @@
 	mo->pathp = nil;
 	if(mo->pics->nf > 0)
 		mo->freezefrm = tc % mo->pics->nf;
-	mo->pics = &mo->o->pidle;
+	mo->pics = &mo->o->state[OSidle].pics;
 	resetcoords(mo);
 }
 
@@ -112,7 +112,8 @@
 	}
 	mo->movingp = linkmobj(moving, mo, mo->movingp);
 	mo->pathp = mo->paths;
-	mo->pics = mo->o->pmove.pic != nil ? &mo->o->pmove : &mo->o->pidle;
+	mo->pics = mo->o->state[OSmove].pics.pic != nil
+		? &mo->o->state[OSmove].pics : &mo->o->state[OSidle].pics;
 	nextmove(mo);
 	return 0;
 }
@@ -141,7 +142,7 @@
 	if((mo = mapspawn(x, y, o)) == nil)
 		return -1;
 	mo->team = n;
-	mo->pics = &mo->o->pidle;
+	mo->pics = &mo->o->state[OSidle].pics;
 	if(mo->f & Fbuild)
 		team[n].nbuild++;
 	else