r_mipsprites 1
r_mipskins 1
r_shadow_realtime_world_lightmaps 1
+r_shadow_realtime_world_importlightentitiesfrommap 0 // Whether build process uses keepLights is nontransparent and may change, so better make keepLights not matter.
cl_decals_fadetime 5
cl_decals_time 1
seta cl_gunalign 3 "Gun alignment; 1 = center (if allowed by g_shootfromclient) or right, 2 = center (if allowed by g_shootfromclient) or left, 3 = right only, 4 = left only"
return valstr;
}
-float dotproduct(vector a, vector b)
-{
- return a.x * b.x + a.y * b.y + a.z * b.z;
-}
-
-vector cross(vector a, vector b)
-{
- return
- '1 0 0' * (a.y * b.z - a.z * b.y)
- + '0 1 0' * (a.z * b.x - a.x * b.z)
- + '0 0 1' * (a.x * b.y - a.y * b.x);
-}
-
// compressed vector format:
// like MD3, just even shorter
// 4 bit pitch (16 angles), 0 is -90, 8 is 0, 16 would be 90
string ScoreString(float vflags, float value);
-float dotproduct(vector a, vector b);
-vector cross(vector a, vector b);
-
void compressShortVector_init();
vector decompressShortVector(float data);
float compressShortVector(vector vec);
center = CENTER_OR_VIEWOFS(head);
// find the closest point on the enemy to the center of the attack
- float ang; // angle between shotdir and h
float h; // hypotenuse, which is the distance between attacker to head
float a; // adjacent side, which is the distance between attacker and the point on w_shotdir that is closest to head.origin
h = vlen(center - self.origin);
- ang = acos(dotproduct(normalize(center - self.origin), w_shotdir));
- a = h * cos(ang);
+ a = h * (normalize(center - self.origin) * w_shotdir);
// WEAPONTODO: replace with simpler method
vector nearest_on_line = (w_shotorg + a * w_shotdir);
METHOD(XonoticResolutionSlider, saveCvars, void(entity))
METHOD(XonoticResolutionSlider, draw, void(entity))
ATTRIB(XonoticResolutionSlider, vid_fullscreen, float, -1)
+ ATTRIB(XonoticResolutionSlider, maxAllowedWidth, float, 0)
+ ATTRIB(XonoticResolutionSlider, maxAllowedHeight, float, 0)
ENDCLASS(XonoticResolutionSlider)
entity makeXonoticResolutionSlider();
float updateConwidths(float width, float height, float pixelheight);
}
void XonoticResolutionSlider_addResolution(entity me, float w, float h, float pixelheight)
{
+ if (me.maxAllowedWidth && w > me.maxAllowedWidth)
+ return;
+ if (me.maxAllowedHeight && h > me.maxAllowedHeight)
+ return;
float i;
for (i = 0; i < me.nValues; ++i)
{
}
// NOW we can safely clear.
me.clearValues(me);
+ me.maxAllowedWidth = 0;
+ me.maxAllowedHeight = 0;
if (fullscreen)
{
if(me.nValues == 0)
{
+ // Get workarea.
+ r = getresolution(-2);
+ // If workarea is not supported, get desktop size.
+ if(r.x == 0 && r.y == 0)
+ r = getresolution(-1);
+
+ // Add it, and limit all other resolutions to the workarea/desktop size.
+ if(r.x != 0 || r.y != 0)
+ {
+ me.maxAllowedWidth = r.x;
+ me.maxAllowedHeight = r.y;
+ me.addResolution(me, r.x, r.y, r.z);
+ }
+
+ // Add nice hardcoded defaults.
me.addResolution(me, 640, 480, 1); // pc res
#if 0
me.addResolution(me, 720, 480, 1.125); // DVD NTSC 4:3
void SV_ParseClientCommand(string command)
{
+ // If invalid UTF-8, don't even parse it
+ string command2 = "";
+ float len = strlen(command);
+ float i;
+ for (i = 0; i < len; ++i)
+ command2 = strcat(command2, chr2str(str2chr(command, i)));
+ if (command != command2)
+ return;
+
// if we're banned, don't even parse the command
if(Ban_MaybeEnforceBanOnce(self))
return;
makevectors(passer_angle);
// find the closest point on the enemy to the center of the attack
- float ang; // angle between shotdir and h
float h; // hypotenuse, which is the distance between attacker to head
float a; // adjacent side, which is the distance between attacker and the point on w_shotdir that is closest to head.origin
h = vlen(head_center - passer_center);
- ang = acos(dotproduct(normalize(head_center - passer_center), v_forward));
- a = h * cos(ang);
+ a = h * (normalize(head_center - passer_center) * v_forward);
vector nearest_on_line = (passer_center + a * v_forward);
float distance_from_line = vlen(nearest_to_passer - nearest_on_line);
{
return !(x < y || x == y || x > y);
}
+
+vector cross(vector a, vector b)
+{
+ return
+ '1 0 0' * (a.y * b.z - a.z * b.y)
+ + '0 1 0' * (a.z * b.x - a.x * b.z)
+ + '0 0 1' * (a.x * b.y - a.y * b.x);
+}
const float M_2_SQRTPI = 1.12837916709551257390; /* 2/sqrt(pi) */
const float M_SQRT2 = 1.41421356237309504880; /* sqrt(2) */
const float M_SQRT1_2 = 0.70710678118654752440; /* 1/sqrt(2) */
+
+// Non-<math.h> stuff follows here.
+vector cross(vector a, vector b);
+
#endif
{
vector org, ang, norm, point;
float area;
- vector tri, a, b, c, p, q, n;
+ vector tri, a, b, c, n;
float i_s, i_t, n_t;
string tex;
a = getsurfacepoint(self, i_s, tri.x);
b = getsurfacepoint(self, i_s, tri.y);
c = getsurfacepoint(self, i_s, tri.z);
- p = b - a;
- q = c - a;
- n = '1 0 0' * (q.y * p.z - q.z * p.y)
- + '0 1 0' * (q.z * p.x - q.x * p.z)
- + '0 0 1' * (q.x * p.y - q.y * p.x);
+ n = cross(c - a, b - a);
area = area + vlen(n);
norm = norm + n;
point = point + vlen(n) * (a + b + c);
makevectors (self.angles);
self.movedir = v_forward;
}
- self.warpzone_isboxy = 1;
- if(self.model != "")
+ if(self.model == "")
+ {
+ // It's a box! No need to match with exacttriggers.
+ self.warpzone_isboxy = 1;
+ }
+ else
{
mi = self.mins;
ma = self.maxs;
// let mapper-set mins/maxs override the model's bounds if set
if(mi != '0 0 0' || ma != '0 0 0')
{
+ // It's a box! No need to match with exacttriggers.
self.mins = mi;
self.maxs = ma;
+ self.warpzone_isboxy = 1;
}
- else
- self.warpzone_isboxy = 0; // enable exacttrigger matching
}
setorigin(self, self.origin);
if(self.scale)