I decided to take a mixed solution (QuakeC + engine), so that's why I am posting the problem here.
From the QuakeC side, I am creating a new kind of func_door (func_liquid_door), adding this to the end of doors.qc:
Code: Select all
void() liquid_door_touch =
{
if (other.health <= 0)
{
return;
}
setwater (self, other);
};
// just a simplified copy & paste from original func_door
void() func_liquid_door =
{
SetMovedir ();
self.solid = SOLID_TRIGGER;
self.movetype = MOVETYPE_PUSH;
setorigin (self, self.origin);
setmodel (self, self.model);
self.classname = "liquid_door";
self.use = door_use;
if (!self.speed)
self.speed = 100;
if (!self.wait)
self.wait = 3;
if (!self.lip)
self.lip = 8;
if (!self.dmg)
self.dmg = 2;
if (!self.watertype)
self.watertype = 3;
self.pos1 = self.origin;
self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
if (self.spawnflags & DOOR_START_OPEN)
{
setorigin (self, self.pos2);
self.pos2 = self.pos1;
self.pos1 = self.origin;
}
self.state = STATE_BOTTOM;
self.touch = liquid_door_touch;
self.think = LinkDoors;
self.nextthink = self.ltime + 0.1;
};
Code: Select all
qboolean CheckPointInsideEntity (vec3_t p, edict_t *e)
{
return (
(p[0] >= e->v.mins[0]) &&
(p[1] >= e->v.mins[1]) &&
(p[2] >= e->v.mins[2]) &&
(p[0] <= e->v.maxs[0]) &&
(p[1] <= e->v.maxs[1]) &&
(p[2] <= e->v.maxs[2]));
}
/**
* setwater (entity waterbrush, entity other)
**/
void PF_SetWater (void)
{
edict_t *ent1, *ent2;
vec3_t point;
ent1 = G_EDICT(OFS_PARM0);
ent2 = G_EDICT(OFS_PARM1);
point[0] = ent2->v.origin[0];
point[1] = ent2->v.origin[1];
point[2] = ent2->v.origin[2] + ent2->v.mins[2] + 1;
ent2->v.waterlevel = 0;
ent2->v.watertype = CONTENTS_EMPTY;
if (CheckPointInsideEntity (point, ent1))
{
ent2->v.watertype = ent1->v.watertype;
ent2->v.waterlevel = 1;
point[2] = ent2->v.origin[2] + (ent2->v.mins[2] + ent2->v.maxs[2]) * 0.5;
if (CheckPointInsideEntity (point, ent1))
{
ent2->v.waterlevel = 2;
point[2] = ent2->v.origin[2] + ent2->v.view_ofs[2];
if (CheckPointInsideEntity (point, ent1))
{
ent2->v.waterlevel = 3;
}
}
}
}
So, after that, I created a test map with a func_liquid_door toggled by buttons to mimic a pool being flooded and drained. And it works... kinda. The physics part works pretty well, you can swim and drown into the brush, and when toggled you can walk normally. But visually, there's no warped view, no colorshift. Checking the code, I found that (at least in FitzQuake) water warping is checked in gl_rmain.c (R_SetupView). But I have no idea how I could force the engine to render the water brush correctly, since it only checks contents against the world model. I could eventually hack something to do the trick, but I prefer to make it in an more elegant way.
Any suggestions ?