Forum

Water turb for func_water

Post tutorials on how to do certain tasks within game or engine code here.

Moderator: InsideQC Admins

Water turb for func_water

Postby Rikku2000 » Wed Jun 27, 2012 5:45 am

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...
User avatar
Rikku2000
 
Posts: 49
Joined: Wed Oct 20, 2010 6:33 pm
Location: Germany

Re: Water turb for func_water

Postby Spike » Wed Jun 27, 2012 6:12 am

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.
Spike
 
Posts: 2883
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Re: Water turb for func_water

Postby taniwha » Wed Jun 27, 2012 10:22 am

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/
taniwha
 
Posts: 399
Joined: Thu Jan 14, 2010 7:11 am


Return to Programming Tutorials

Who is online

Users browsing this forum: No registered users and 4 guests