Water turb for func_water

Post tutorials on how to do certain tasks within game or engine code here.
Post Reply
Rikku2000
Posts: 49
Joined: Wed Oct 20, 2010 6:33 pm
Location: Germany
Contact:

Water turb for func_water

Post by Rikku2000 »

Hey guys may someone need this in his engine i copy the water from quake_life "Half-life" to my engine so on HL maps
for "func_water": here the QuakeC code:

Code: Select all

float EASEUNDERCURRENT = 16;

void () liquid_movetopos2;
void () liquid_movetopos1;

void () CheckFuncWaterDeath = {
	local entity ent;
	local vector spot, rgb;
	local float i;

	spot = self.origin + self.view_ofs;
	ent = find(world, classname, "fliquid");

	while(ent) {
		if (
			(spot_x<ent.absmax_x) &&
			(spot_y<ent.absmax_y) &&
			(spot_z<ent.absmax_z) &&
			(spot_x>ent.absmin_x) && 
			(spot_y>ent.absmin_y) && 
			(spot_z>ent.absmin_z)
		) {
			self.fwatershifttime = time + frametime;
			self.fwatershift = TRUE;

			return;
		}

		ent = find(ent, classname, "fliquid");
	}
};

void () liquid_playmovesound = {
	if (self.noise != string_null)
		sound (self.aiment, CHAN_VOICE, self.noise, 1.0, ATTN_NORM);
};

void () liquid_playreturnsound = {
	if (self.noise1 != string_null)
		sound (self.aiment, CHAN_VOICE, self.noise1, 1.0, ATTN_NORM);
};

void () liquid_playstopsound = {
	if (self.noise2 != string_null)
		sound (self.aiment, CHAN_VOICE, self.noise2, 1.0, ATTN_NORM);
};

void () liquid_at_pos1 = {
	setorigin(self.aiment, self.aiment.pos1);
	liquid_playstopsound();
	self.state = STATE_BOTTOM;

	if (!self.targetname) {
		if (self.wait > 0) {
			self.think = liquid_movetopos2;
			self.nextthink = time + self.wait;
		} else if (!self.wait)
			liquid_movetopos2();
	}

	if (self.target) {
		activator = self.enemy;
		SUB_UseTargets();
	}
};

void () liquid_at_pos2 = {
	setorigin(self.aiment, self.aiment.pos2);
	liquid_playstopsound();
	self.state = STATE_TOP;

	if (self.wait > 0) {
		self.think = liquid_movetopos1;
		self.nextthink = time + self.wait;
	} else if (!self.wait)
		liquid_movetopos1();

	if (self.target) {
		activator = self.enemy;
		SUB_UseTargets();
	}
};

void () liquid_movetopos1 = {
	self.state = STATE_DOWN;
	setorigin(self.aiment, self.aiment.dest2);
	liquid_playreturnsound();

	SUB_fCalcMove(self.pos1, self.speed2, liquid_at_pos1);
};

void () liquid_movetopos2 = {
	self.state = STATE_UP;
	setorigin(self.aiment, self.aiment.dest1);
	liquid_playmovesound();

	SUB_fCalcMove(self.pos2, self.speed, liquid_at_pos2);
};

void () liquid_use = {
	if (self.nextthink > time)
		return;

	self.enemy = activator;

	if (self.state == STATE_BOTTOM)
		liquid_movetopos2();
	else if (self.state == STATE_TOP)
		liquid_movetopos1();
};

void () liquid_touch = {
	local float test;
	local float r,g,b,i,c;

	if (!(other.flags & FL_CLIENT)) {
		if (other.classname == "drip") {
			setorigin(other, other.origin + '0 0 6');
			self = other;
			self.think1();

			return;
		} else if (other.classname == "spark") {
			self = other;
			self.think1();

			return;
		} else if (other.classname == "particle") {
			self = other;
			self.think1();

			return;
		}

		if (other.movetype == MOVETYPE_NONE || other.movetype == MOVETYPE_PUSH	|| other.movetype == MOVETYPE_NOCLIP)
			return;

		 if (other.fwatershifttime < time && other.watertype) {
			other.watertype = self.watertype;
			other.waterlevel = 1;
		}

		other.fwatershifttime = time + 0.1;

		return;
	}

	if (other.laddertime > time)
		return;

	test = other.origin_z + other.mins_z + 1;
	if (test <= self.absmax_z && test >= self.absmin_z) {
		other.watertype = self.watertype;
		other.waterlevel = 1;

		test = other.origin_z + (other.mins_z + other.maxs_z) * 0.5;
		if (test <= self.absmax_z) {
			other.waterlevel = 2;
			other.zerogtime = time+0.05;
		}

		test = other.origin_z + other.view_ofs_z;
		if (test <= self.absmax_z) {
			other.waterlevel = 3;
			other.fwatershifttime = time+frametime;
			other.fwatershift = TRUE;
		}

		if (self.spawnflags & EASEUNDERCURRENT)
			c = 4-other.waterlevel;
		else
			c = other.waterlevel;	

		if (self.drag)
			other.velocity = other.velocity + self.velocity*(self.drag*frametime)*c;

		if (self.mangle != '0 0 0')
			other.velocity = other.velocity + self.mangle*frametime*(c/3);
	}
};

void () liquid_spawnnoisemaker = {
	self.aiment = spawn();
	self.aiment.movetype = MOVETYPE_NOCLIP;
	self.aiment.solid = SOLID_NOT;

	self.aiment.pos1_z = self.maxs_z;
	self.aiment.pos1_x = (self.mins_x + self.maxs_x)*0.5;
	self.aiment.pos1_y = (self.mins_y + self.maxs_y)*0.5;

	self.aiment.dest1 = self.aiment.pos1;
	self.aiment.dest1_z = (self.mins_z + self.maxs_z)*0.5;

	self.aiment.pos2_z = self.maxs_z + self.height;
	self.aiment.pos2_x = (self.mins_x + self.maxs_x)*0.5;
	self.aiment.pos2_y = (self.mins_y + self.maxs_y)*0.5;

	self.aiment.dest2 = self.aiment.pos2;
	self.aiment.dest2_z = self.height + (self.mins_z + self.maxs_z)*0.5;

	setorigin(self.aiment, self.aiment.pos1);
};

void () func_water = {
	if (self.noise != string_null)
		precache_sound (self.noise);

	if (self.noise1 != string_null)
		precache_sound (self.noise1);

	if (self.noise2 != string_null)
		precache_sound (self.noise2);

	self.solid = SOLID_TRIGGER;
	self.movetype = MOVETYPE_NONE;
	setmodel (self, self.model);
	setsize (self, self.mins , self.maxs);
	setorigin (self, self.origin);

	self.classname = "fliquid";
	self.touch = liquid_touch;

	if (self.watertype<-5 || self.watertype>-3)
		self.watertype = CONTENT_WATER;

	 if (self.cshift == string_null) {
		if (self.watertype == CONTENT_WATER)
			self.cshift = "130 80 50 128";
		else if (self.watertype == CONTENT_SLIME)
			self.cshift = "0 25 5 150";
		else if (self.watertype == CONTENT_LAVA)
			self.cshift = "255 80 0 150";
	}

	if (self.drag > 100)
		self.drag = 100;
	if (self.drag < 0)
		self.drag = 0;

	if (self.mangle != '0 0 0')
		self.mangle = self.mangle*50;

	if (!self.speed)
		self.speed = 10;
	if (!self.speed2)
		self.speed2 = self.speed;

	self.pos1 = self.origin;
	self.pos2 = self.origin;
	self.pos2_z = self.origin_z + self.height;

	self.state = STATE_BOTTOM;

	liquid_spawnnoisemaker();

	if (!self.targetname) {	
		if (self.wait <= 0)
			liquid_movetopos2();
	} else
		self.use = liquid_use;
};
on c code i change a small code on "void Mod_LoadFaces (lump_t *l)":

Code: Select all

		int turb_flag;

		...

		turb_flag = (loadmodel->bspversion == HL_BSPVERSION ? "!" : "*"); // turbulent

		if (!Q_strncmp(out->texinfo->texture->name, turb_flag, 1)) {
			out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
			for (i=0 ; i<2 ; i++) {
				out->extents[i] = 16384;
				out->texturemins[i] = -8192;
			}

			GL_SubdivideSurface (out); // cut up polygon for warps

			continue;
		}
So it make the water texture turbed other way its just a static texture.
I am sorry for my English...
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Water turb for func_water

Post by Spike »

that sort of thing really messes up prediction in engines that support it (eg: dp+fte)
fte supports .skin=CONTENT_WATER like halflife does, supposedly, so view+player movement all automagically works.
Can use it on func_doors too (doors made of lava!!). :)

My biggest point of contention with this is with backface culling of water brushes on quake maps. I don't know what halflife does there.
taniwha
Posts: 401
Joined: Thu Jan 14, 2010 7:11 am
Contact:

Re: Water turb for func_water

Post by taniwha »

Rikku2000 wrote:

Code: Select all

		int turb_flag;
		...
		turb_flag = (loadmodel->bspversion == HL_BSPVERSION ? "!" : "*"); // turbulent
		if (!Q_strncmp(out->texinfo->texture->name, turb_flag, 1)) {
turb_flag is int, which is good, but the rest...

use '!' and '*' instead (note quote type). also, don't use any form of strcmp for single chars.

Code: Select all

if (*out->texinfo->texture->name == turb_flag)
is much better. Or out->texinfo->texture->name[0] if you prefer.

[edit]
PS: turn on as many warnings as you can, then turn them into errors. That way, similar errors will not get past you :)
Leave others their otherness.
http://quakeforge.net/
Post Reply