quake-rerelease-qc/quakec_mg1/fog.qc
2022-04-06 14:43:08 -05:00

296 lines
6.5 KiB
C++

/* Copyright (C) 1996-2022 id Software LLC
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
See file, 'COPYING', for details.
*/
const float FORCE_SET_FOG = 1;
void stuffcmd_digit( entity client, float f) =
{
float d;
d = floor(f);
d = mod(d, 10);
if(d == 0)
stuffcmd(client, "0");
else if(d == 1)
stuffcmd(client, "1");
else if(d == 2)
stuffcmd(client, "2");
else if(d == 3)
stuffcmd(client, "3");
else if(d == 4)
stuffcmd(client, "4");
else if(d == 5)
stuffcmd(client, "5");
else if(d == 6)
stuffcmd(client, "6");
else if(d == 7)
stuffcmd(client, "7");
else if(d == 8)
stuffcmd(client, "8");
else if(d == 9)
stuffcmd(client, "9");
}
void stuffcmd_int( entity client, float f, float numdigits) =
{
float tmp;
if(f == 0){
stuffcmd( client, "0");
return;
}
if(f < 0){
// Yeah sure.
stuffcmd( client, "-");
f = fabs(f);
}
if(numdigits <= 0){
tmp = f;
numdigits = 1;
while(tmp >= 1){
tmp = tmp / 10;
numdigits = numdigits * 10;
}
}
//I need to do this to get zero-padding to work.
while( numdigits > 1 ){
numdigits = numdigits / 10;
tmp = f / numdigits;
stuffcmd_digit( client, tmp);
}
}
void stuffcmd_float( entity client, float f) =
{
float intpart, decpart, isNegative;
isNegative = FALSE;
if(f == 0){
stuffcmd( client, "0");
return;
}
if(f < 0){
// easier this way
isNegative = TRUE;
f = fabs(f);
}
// 1: stuff the sign.
if(isNegative)
stuffcmd( client, "-");
// 2: stuff the integer part.
intpart = floor(f);
stuffcmd_int( client, intpart, 0);
// 3: stuff the decimal point.
stuffcmd( client, ".");
// 4: stuff the decimal part.
decpart = mod( f, 1);
decpart = decpart * 10000;
stuffcmd_int( client, decpart, 10000);
}
.float fog_density;
.vector fog_color;
.entity fog_active_fog_trigger;
.string fog_info_entity;
void SetFog(entity client, float density, vector color, float transitionTime = 0)
{
client.fog_density = density;
client.fog_color = color;
stuffcmd(client, "\nfog ");
stuffcmd_float(client, density);
stuffcmd(client, " ");
stuffcmd_float(client, color_x);
stuffcmd(client, " ");
stuffcmd_float(client, color_y);
stuffcmd(client, " ");
stuffcmd_float(client, color_z);
if(transitionTime > 0)
{
stuffcmd(client, " ");
stuffcmd_float(client, transitionTime);
}
stuffcmd(client, "\n");
}
entity GetFogInfoEntity(entity e, .string field = fog_info_entity)
{
if(e.field)
{
e = find(world, targetname, e.field);
if(e.classname == "info_fog")
{
return e;
}
}
return world;
}
float FogPushSettingsFrom(entity client, entity source, float transitionTime)
{
if(client.classname != "player") return FALSE;
source = GetFogInfoEntity(source);
if(!source) return FALSE;
if(source.fog_density || source.fog_color || (source.spawnflags & FORCE_SET_FOG))
{
SetFog(client, source.fog_density, source.fog_color, transitionTime);
return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
/*QUAKED info_fog (0.5 .5 .8) (-8 -8 -8) (8 8 8)
Fog value definition
wait: fog density
dest: fog color
*/
void info_fog()
{
if(!self.fog_density) self.fog_density = 0.05;
else if(self.fog_color_x > 1.0 || self.fog_color_y > 1.0 || self.fog_color_z > 1.0) //Not in 0..1 range?
{
self.fog_color = self.fog_color * (1.0 / 255);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
void trigger_fog_activate()
{
if(self == other.fog_active_fog_trigger) return;
if (other.classname != "player") // Yoder add, 27/09/2020 to fix crash
return;
other.fog_active_fog_trigger = self;
FogPushSettingsFrom(other, self, self.delay);
}
/*QUAKED trigger_fog (0.5 .5 .8) (? ? ?) (? ? ?)
Trigger to transition fog
fog_info_entity: info_fog that contains values this trigger should use.
delay: time to fade the transition over
*/
void trigger_fog()
{
// Fog is set on the server, so transitions and triggers work really bad in multiplayer.
// Just remove ourself if we're in multiplayer.
if(coop || deathmatch)
{
remove(self);
return;
}
if(!self.delay) self.delay = 0.5;
self.use = trigger_fog_activate;
if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
{
self.touch = trigger_fog_activate;
}
InitTrigger ();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
float trigger_fog_transition_touch_get_tween(entity pl)
{
vector t = pl.origin - self.mins;
vector b = self.size;
float tween;
if(self.style == 0)
{
tween = t_x / b_x;
}
else if(self.style == 1)
{
tween = t_y / b_y;
}
else if(self.style == 2)
{
tween = t_z / b_z;
}
if(tween < 0) tween = 0;
if(tween > 1) tween = 1;
return tween;
}
void trigger_fog_transition_touch()
{
if(other.classname != "player") return;
float tween = trigger_fog_transition_touch_get_tween(other);
entity fog1 = GetFogInfoEntity(self);
entity fog2 = GetFogInfoEntity(self, target);
float density = ((1 - tween) * fog1.fog_density) + (tween * fog2.fog_density);
vector color = ((1 - tween) * fog1.fog_color) + (tween * fog2.fog_color);
SetFog(other, density, color);
}
/*QUAKED trigger_fog_transition (0.5 .5 .8) (? ? ?) (? ? ?)
Trigger to transition fog between two sides.
fog_info_entity: info_fog that contains values this trigger should use on the 'left' side.
target: info_fog that contains values this trigger should use on the 'right' side.
style: Which axis this trigger fades across. 0 = X, 1 = Y, 2 = Z
*/
void trigger_fog_transition()
{
// Fog is set on the server, so transitions and triggers work really bad in multiplayer.
// Just remove ourself if we're in multiplayer.
if(coop || deathmatch)
{
remove(self);
return;
}
if(self.style < 0 || self.style > 2)
{
objerror("Invalid style for trigger_fog_transition. Needs to be 0, 1 or 2.");
}
self.touch = trigger_fog_transition_touch;
InitTrigger ();
}