]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into nifrek/longjumpanim
authornifrek <nifrek@gmail.com>
Mon, 20 Jun 2011 20:59:14 +0000 (16:59 -0400)
committernifrek <nifrek@gmail.com>
Mon, 20 Jun 2011 20:59:14 +0000 (16:59 -0400)
30 files changed:
defaultXonotic.cfg
gfx/loading.tga
gfx/loading10.tga
gfx/loading11.tga
gfx/loading12.tga
gfx/loading13.tga [new file with mode: 0644]
gfx/loading2.tga
gfx/loading3.tga
gfx/loading4.tga
gfx/loading5.tga
gfx/loading6.tga
gfx/loading7.tga
gfx/loading8.tga
gfx/loading9.tga
models/player/megaerebus_lod1.iqm_0.skin [new file with mode: 0644]
models/player/megaerebus_lod2.iqm_0.skin [new file with mode: 0644]
qcsrc/client/autocvars.qh
qcsrc/client/waypointsprites.qc
qcsrc/server/bot/aim.qc
qcsrc/server/bot/havocbot/havocbot.qc
qcsrc/server/bot/havocbot/role_keepaway.qc [new file with mode: 0644]
qcsrc/server/bot/havocbot/roles.qc
qcsrc/server/defs.qh
qcsrc/server/mutators/gamemode_keepaway.qc
qcsrc/server/portals.qc
qcsrc/warpzonelib/anglestransform.qc
qcsrc/warpzonelib/anglestransform.qh
qcsrc/warpzonelib/common.qc
qcsrc/warpzonelib/common.qh
qcsrc/warpzonelib/server.qc

index 76371bf0ef9f45f1db3c1e8465a7c609001a5f81..35eb6b24efa3ea6ef570655c03f66697e50559e4 100644 (file)
@@ -1228,6 +1228,7 @@ set g_nick_flood_penalty 0.5 "duration of the nick flood penalty"
 set g_nick_flood_penalty_yellow 3 "number of changes to allow before warning and movement blocking"
 set g_nick_flood_penalty_red 30 "number of changes to allow before totally disorienting the player"
 
+seta g_waypointsprite_uppercase 1
 set g_waypointsprite_normdistance 512
 set g_waypointsprite_minscale 0.5
 set g_waypointsprite_minalpha 0.4
@@ -1238,6 +1239,7 @@ set g_waypointsprite_deadlifetime 1
 set g_waypointsprite_limitedrange 5120
 set g_waypointsprite_stuffbinds 0
 seta g_waypointsprite_scale 1
+seta g_waypointsprite_fontsize 12
 seta g_waypointsprite_alpha 1 "This allows the client to control transparency of the waypoint"
 seta g_waypointsprite_edgefadealpha 0.5 "alpha multiplier near the edge"
 seta g_waypointsprite_edgefadescale 1 "scale multiplier near the edge"
@@ -2125,7 +2127,7 @@ set snd_soundradius 1200
 scr_loadingscreen_background 0
 scr_loadingscreen_barcolor "0 0.5 1"
 scr_loadingscreen_barheight 12
-scr_loadingscreen_count 12
+scr_loadingscreen_count 13
 scr_loadingscreen_scale 999
 scr_loadingscreen_scale_base 1
 scr_loadingscreen_scale_limit 2
index 76a7edf1fad45a5333f64ec13d3430c071efa4d2..67580e9daccdd08a4e6e8a66ce63fd7f42e7997f 100644 (file)
Binary files a/gfx/loading.tga and b/gfx/loading.tga differ
index 5f453bed6fd06bfe5918d341139166f5333cd60e..6cddc0ca32b09d1ca0b69b9c9ed574bab7e8bff3 100644 (file)
Binary files a/gfx/loading10.tga and b/gfx/loading10.tga differ
index 5fb261efc6cc1d8bc8416a6c266a83856c6613e0..0cee44b8c5ebb1385f428d99ac610a783dd6500c 100644 (file)
Binary files a/gfx/loading11.tga and b/gfx/loading11.tga differ
index 6345a9aa67343c06f38faa3f28e1450cab08a587..0314a97a7a1c4f836516d7d608ff9a11b8e49bcc 100644 (file)
Binary files a/gfx/loading12.tga and b/gfx/loading12.tga differ
diff --git a/gfx/loading13.tga b/gfx/loading13.tga
new file mode 100644 (file)
index 0000000..ef30878
Binary files /dev/null and b/gfx/loading13.tga differ
index 3aa4a29e150abc0068394c2a16c9761c4c936d33..63c4c4782023651f310c4c51aa5c3a6656450465 100644 (file)
Binary files a/gfx/loading2.tga and b/gfx/loading2.tga differ
index 639608565eafd28867b74cdebb00158f1aa02d15..42ae5cd48f228478a6ae26ac18f08571cfa53b2c 100644 (file)
Binary files a/gfx/loading3.tga and b/gfx/loading3.tga differ
index eaf44d09496ca033b8e57f97c1e79739117211be..62877a6729f2dcf2ca2e72520be72a041c790d68 100644 (file)
Binary files a/gfx/loading4.tga and b/gfx/loading4.tga differ
index c06d32320fd7370f5376f3feb839c3a1b476139a..96ec6c4a742a03742dc65aedf8178a07b7e0fe29 100644 (file)
Binary files a/gfx/loading5.tga and b/gfx/loading5.tga differ
index 7c8007c44680432d5f14cf900e20796951f65caf..a0e2fc85318dbf9081544ac239a531ee743e96da 100644 (file)
Binary files a/gfx/loading6.tga and b/gfx/loading6.tga differ
index 56aa4afc4b19b7bbd24c7bb01a5824004471ccdc..87d5f13e058959833fc64cb1a90237f7a004bc39 100644 (file)
Binary files a/gfx/loading7.tga and b/gfx/loading7.tga differ
index a41d344ef8b8e8b225d8f3d534a830aa1fc3078c..c8689704489adb6baf9b7bc5a0b4c3e2cef98a63 100644 (file)
Binary files a/gfx/loading8.tga and b/gfx/loading8.tga differ
index dc636036947a0671376bf6fc9528afa92ad0db96..ac758099aa2eda35a61f45fd31c58dd3c688449d 100644 (file)
Binary files a/gfx/loading9.tga and b/gfx/loading9.tga differ
diff --git a/models/player/megaerebus_lod1.iqm_0.skin b/models/player/megaerebus_lod1.iqm_0.skin
new file mode 100644 (file)
index 0000000..4597cef
--- /dev/null
@@ -0,0 +1,2 @@
+erebus,erebusfullbright
+erebus.001,shadowhead
diff --git a/models/player/megaerebus_lod2.iqm_0.skin b/models/player/megaerebus_lod2.iqm_0.skin
new file mode 100644 (file)
index 0000000..4597cef
--- /dev/null
@@ -0,0 +1,2 @@
+erebus,erebusfullbright
+erebus.001,shadowhead
index bf9924a9279ddd1ac6f3f0cc5266527cffa26a34..4edfda3ad56149281c1c13cec32d2d7eeecdd946 100644 (file)
@@ -122,6 +122,7 @@ float autocvar_g_balance_tuba_attenuation;
 float autocvar_g_balance_tuba_fadetime;
 float autocvar_g_balance_tuba_volume;
 float autocvar_g_warmup_limit;
+var float autocvar_g_waypointsprite_uppercase = 1;
 var float autocvar_g_waypointsprite_alpha = 1;
 var float autocvar_g_waypointsprite_crosshairfadealpha = 1;
 float autocvar_g_waypointsprite_crosshairfadedistance;
@@ -137,6 +138,7 @@ float autocvar_g_waypointsprite_minalpha;
 float autocvar_g_waypointsprite_minscale;
 float autocvar_g_waypointsprite_normdistance;
 var float autocvar_g_waypointsprite_scale = 1;
+var float autocvar_g_waypointsprite_fontsize = 12;
 float autocvar_g_waypointsprite_timealphaexponent;
 var float autocvar_hud_colorflash_alpha = 0.5;
 float autocvar_hud_configure_bg_minalpha;
index bcd8c433e07b185d3eb997f60d976daee526b2d2..8ea4ec8d82b51cddfb398e1870b60d33d0f71422 100644 (file)
@@ -6,6 +6,7 @@ float waypointsprite_minalpha;
 float waypointsprite_distancealphaexponent;
 float waypointsprite_timealphaexponent;
 float waypointsprite_scale;
+float waypointsprite_fontsize;
 float waypointsprite_edgefadealpha;
 float waypointsprite_edgefadescale;
 float waypointsprite_edgefadedistance;
@@ -32,14 +33,13 @@ float waypointsprite_alpha;
 .float build_starthealth;
 .float build_finished;
 
-vector SPRITE_SIZE = '288 36 0';
-vector SPRITE_HOTSPOT = '144 36 0';
 float SPRITE_HEALTHBAR_WIDTH = 144;
 float SPRITE_HEALTHBAR_HEIGHT = 9;
 float SPRITE_HEALTHBAR_MARGIN = 6;
 float SPRITE_HEALTHBAR_BORDER = 2;
 float SPRITE_HEALTHBAR_BORDERALPHA = 1;
 float SPRITE_HEALTHBAR_HEALTHALPHA = 0.5;
+float SPRITE_ARROW_SCALE = 1.0;
 
 void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
 {
@@ -106,6 +106,256 @@ void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, fl
        drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * height, "", hrgb, ha, f);
 }
 
+// returns location of sprite text
+vector drawspritearrow(vector o, float ang, vector rgb, float a, float t)
+{
+       float SQRT2 = 1.414;
+       float BORDER; BORDER = 1.5 * t;
+       float TSIZE; TSIZE = 8 * t;
+       float RLENGTH; RLENGTH = 8 * t;
+       float RWIDTH; RWIDTH = 4 * t;
+       float MLENGTH; MLENGTH = 4 * t;
+
+       R_BeginPolygon("", DRAWFLAG_NORMAL);
+       R_PolygonVertex(o + rotate(eX * -(TSIZE + BORDER * (1 + SQRT2)) + eY * (TSIZE + BORDER), ang), '0 0 0', '0 0 0', a);
+       R_PolygonVertex(o + rotate(eX *  (TSIZE + BORDER * (1 + SQRT2)) + eY * (TSIZE + BORDER), ang), '0 0 0', '0 0 0', a);
+       R_PolygonVertex(o + rotate(eY * -(        BORDER *      SQRT2),                          ang), '0 0 0', '0 0 0', a);
+       R_EndPolygon();
+       R_BeginPolygon("", DRAWFLAG_NORMAL);
+       R_PolygonVertex(o + rotate(eX * -(RWIDTH + BORDER) + eY * (TSIZE           + BORDER), ang), '0 0 0', '0 0 0', a);
+       R_PolygonVertex(o + rotate(eX * -(RWIDTH + BORDER) + eY * (TSIZE + RLENGTH + BORDER), ang), '0 0 0', '0 0 0', a);
+       R_PolygonVertex(o + rotate(eX *  (RWIDTH + BORDER) + eY * (TSIZE + RLENGTH + BORDER), ang), '0 0 0', '0 0 0', a);
+       R_PolygonVertex(o + rotate(eX *  (RWIDTH + BORDER) + eY * (TSIZE           + BORDER), ang), '0 0 0', '0 0 0', a);
+       R_EndPolygon();
+
+       R_BeginPolygon("", DRAWFLAG_ADDITIVE);
+       R_PolygonVertex(o + rotate(eX * -TSIZE + eY * TSIZE, ang), '0 0 0', rgb, a);
+       R_PolygonVertex(o + rotate(eX *  TSIZE + eY * TSIZE, ang), '0 0 0', rgb, a);
+       R_PolygonVertex(o + rotate('0 0 0',                  ang), '0 0 0', rgb, a);
+       R_EndPolygon();
+       R_BeginPolygon("", DRAWFLAG_ADDITIVE);
+       R_PolygonVertex(o + rotate(eX * -RWIDTH + eY *  TSIZE,            ang), '0 0 0', rgb, a);
+       R_PolygonVertex(o + rotate(eX * -RWIDTH + eY * (TSIZE + RLENGTH), ang), '0 0 0', rgb, a);
+       R_PolygonVertex(o + rotate(eX *  RWIDTH + eY * (TSIZE + RLENGTH), ang), '0 0 0', rgb, a);
+       R_PolygonVertex(o + rotate(eX *  RWIDTH + eY *  TSIZE,            ang), '0 0 0', rgb, a);
+       R_EndPolygon();
+
+       return
+               o + rotate(eY * (TSIZE + RLENGTH + MLENGTH), ang);
+}
+
+// returns location of sprite healthbar
+vector drawspritetext(vector o, float ang, float minwidth, vector rgb, float a, vector fontsize, string s)
+{
+       float algnx, algny;
+       float sw, w, h;
+       float aspect, sa, ca;
+
+       sw = stringwidth(s, FALSE, fontsize);
+       if(sw > minwidth)
+               w = sw;
+       else
+               w = minwidth;
+       h = fontsize_y;
+
+       // how do corners work?
+       aspect = vid_conwidth / vid_conheight;
+       sa = sin(ang);
+       ca = cos(ang) * aspect;
+       if(fabs(sa) > fabs(ca))
+       {
+               algnx = (sa < 0);
+               algny = 0.5 - 0.5 * ca / fabs(sa);
+       }
+       else
+       {
+               algnx = 0.5 - 0.5 * sa / fabs(ca);
+               algny = (ca < 0);
+       }
+
+       // align
+       o_x -= w * algnx;
+       o_y -= h * algny;
+
+       // we want to be onscreen
+       if(o_x < 0)
+               o_x = 0;
+       if(o_y < 0)
+               o_y = 0;
+       if(o_x > vid_conwidth - w)
+               o_x = vid_conwidth - w;
+       if(o_y > vid_conheight - h)
+               o_x = vid_conheight - h;
+
+       o_x += 0.5 * (w - sw);
+
+       drawstring(o, s, fontsize, rgb, a, DRAWFLAG_NORMAL);
+
+       o_x += 0.5 * sw;
+       o_y += 0.5 * h;
+
+       return o;
+}
+
+float spritelookupblinkvalue(string s)
+{
+       switch(s)
+       {
+               case "ons-cp-atck-neut": return 2;
+               case "ons-cp-atck-red":  return 2;
+               case "ons-cp-atck-blue": return 2;
+               case "ons-cp-dfnd-red":  return 0.5;
+               case "ons-cp-dfnd-blue": return 0.5;
+               case "item-invis":       return 2;
+               case "item-extralife":   return 2;
+               case "item-speed":       return 2;
+               case "item-strength":    return 2;
+               case "item-shueld":      return 2;
+               case "item-fuelregen":   return 2;
+               case "item-jetpack":     return 2;
+               default:                 return 1;
+       }
+}
+vector spritelookupcolor(string s, vector def)
+{
+       switch(s)
+       {
+               case "keycarrier-friend": return '0 1 0';
+               default:                  return def;
+       }
+}
+string spritelookuptext(string s)
+{
+       switch(s)
+       {
+               case "as-push": return _("Push");
+               case "as-destroy": return _("Destroy");
+               case "as-defend": return _("Defend");
+               case "bluebase": return _("Blue base");
+               case "danger": return _("DANGER");
+               case "flagcarrier": return _("Flag carrier");
+               case "flagdropped": return _("Dropped flag");
+               case "helpme": return _("Help me!");
+               case "here": return _("Here");
+               case "key-dropped": return _("Dropped key");
+               case "keycarrier-blue": return _("Key carrier");
+               case "keycarrier-finish": return _("Run here");
+               case "keycarrier-friend": return _("Key carrier");
+               case "keycarrier-pink": return _("Key carrier");
+               case "keycarrier-red": return _("Key carrier");
+               case "keycarrier-yellow": return _("Key carrier");
+               case "redbase": return _("Red base");
+               case "waypoint": return _("Waypoint");
+               case "ons-gen-red": return _("Generator");
+               case "ons-gen-blue": return _("Generator");
+               case "ons-gen-shielded": return _("Generator");
+               case "ons-cp-neut": return _("Control point");
+               case "ons-cp-red": return _("Control point");
+               case "ons-cp-blue": return _("Control point");
+               case "ons-cp-atck-neut": return _("Control point");
+               case "ons-cp-atck-red": return _("Control point");
+               case "ons-cp-atck-blue": return _("Control point");
+               case "ons-cp-dfnd-red": return _("Control point");
+               case "ons-cp-dfnd-blue": return _("Control point");
+               case "race-checkpoint": return _("Checkpoint");
+               case "race-finish": return _("Finish");
+               case "race-start": return _("Start");
+               case "nb-ball": return _("Ball");
+               case "ka-ball": return _("Ball");
+               case "ka-ballcarrier": return _("Ball carrier");
+               case "wpn-laser": return _("Laser");
+               case "wpn-shotgun": return _("Shotgun");
+               case "wpn-uzi": return _("Machine Gun");
+               case "wpn-gl": return _("Mortar");
+               case "wpn-electro": return _("Electro");
+               case "wpn-crylink": return _("Crylink");
+               case "wpn-nex": return _("Nex");
+               case "wpn-hagar": return _("Hagar");
+               case "wpn-rl": return _("Rocket Launcher");
+               case "wpn-porto": return _("Port-O-Launch");
+               case "wpn-minstanex": return _("Minstanex");
+               case "wpn-hookgun": return _("Hook");
+               case "wpn-fireball": return _("Fireball");
+               case "wpn-hlac": return _("HLAC");
+               case "wpn-campingrifle": return _("Rifle");
+               case "wpn-minelayer": return _("Mine Layer");
+               case "dom-neut": return _("Control point");
+               case "dom-red": return _("Control point");
+               case "dom-blue": return _("Control point");
+               case "dom-yellow": return _("Control point");
+               case "dom-pink": return _("Control point");
+               case "item-invis": return _("Invisibility");
+               case "item-extralife": return _("Extra life");
+               case "item-speed": return _("Speed");
+               case "item-strength": return _("Strength");
+               case "item-shield": return _("Shield");
+               case "item-fuelregen": return _("Fuel regen");
+               case "item-jetpack": return _("Jet Pack");
+               case "freezetag_frozen": return _("Frozen!");
+               case "tagged-target": return _("Tagged");
+               case "vehicle": return _("Vehicle");
+               default: return s;
+       }
+}
+
+vector fixrgbexcess_move(vector rgb, vector src, vector dst)
+{
+       vector yvec = '0.299 0.587 0.114';
+       return rgb + dst * ((src * yvec) / (dst * yvec)) * ((rgb - '1 1 1') * src);
+}
+vector fixrgbexcess(vector rgb)
+{
+       if(rgb_x > 1)
+       {
+               rgb = fixrgbexcess_move(rgb, '1 0 0', '0 1 1');
+               if(rgb_y > 1)
+               {
+                       rgb = fixrgbexcess_move(rgb, '0 1 0', '0 0 1');
+                       if(rgb_z > 1)
+                               rgb_z = 1;
+               }
+               else if(rgb_z > 1)
+               {
+                       rgb = fixrgbexcess_move(rgb, '0 0 1', '0 1 0');
+                       if(rgb_y > 1)
+                               rgb_y = 1;
+               }
+       }
+       else if(rgb_y > 1)
+       {
+               rgb = fixrgbexcess_move(rgb, '0 1 0', '1 0 1');
+               if(rgb_x > 1)
+               {
+                       rgb = fixrgbexcess_move(rgb, '1 0 0', '0 0 1');
+                       if(rgb_z > 1)
+                               rgb_z = 1;
+               }
+               else if(rgb_z > 1)
+               {
+                       rgb = fixrgbexcess_move(rgb, '0 0 1', '1 0 0');
+                       if(rgb_x > 1)
+                               rgb_x = 1;
+               }
+       }
+       else if(rgb_z > 1)
+       {
+               rgb = fixrgbexcess_move(rgb, '0 0 1', '1 1 0');
+               if(rgb_x > 1)
+               {
+                       rgb = fixrgbexcess_move(rgb, '1 0 0', '0 1 0');
+                       if(rgb_y > 1)
+                               rgb_y = 1;
+               }
+               else if(rgb_y > 1)
+               {
+                       rgb = fixrgbexcess_move(rgb, '0 1 0', '1 0 0');
+                       if(rgb_x > 1)
+                               rgb_x = 1;
+               }
+       }
+       return rgb;
+}
+
 void Draw_WaypointSprite()
 {
        string spriteimage;
@@ -173,34 +423,43 @@ void Draw_WaypointSprite()
        else if(self.maxdistance > 0)
                a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
 
+       vector rgb;
+       rgb = self.teamradar_color;
+       rgb = spritelookupcolor(spriteimage, rgb);
+       if(rgb == '0 0 0')
+       {
+               self.teamradar_color = '1 0 1';
+               print(sprintf("WARNING: sprite of name %s has no color, using pink so you notice it\n")); 
+       }
+
+       if(time - floor(time) > 0.5)
+               a *= spritelookupblinkvalue(spriteimage);
+
+       if(a > 1)
+       {
+               rgb *= a;
+               a = 1;
+       }
+
        if(a <= 0)
                return;
-       
-       // draw the sprite image
+
+       rgb = fixrgbexcess(rgb);
+
        vector o;
-       float rot;
-       o = project_3d_to_2d(self.origin);
-       rot = 0;
+       float ang;
 
+       o = project_3d_to_2d(self.origin);
        if(o_z < 0 || o_x < 0 || o_y < 0 || o_x > vid_conwidth || o_y > vid_conheight)
        {
                // scale it to be just in view
                vector d;
                float f1, f2;
 
-               // get the waypoint angle vector
-               /*
-               d_x = view_right * (self.origin - view_origin) * vid_conwidth / vid_width;
-               d_y = -view_up * (self.origin - view_origin) * vid_conheight / (vid_height * vid_pixelheight);
-               d_z = 0;
-               */
-               
                d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
-
-               /*
-               if(autocvar_v_flipped)
-                       d_x = -d_x;
-               */
+               ang = atan2(-d_x, -d_y);
+               if(o_z < 0)
+                       ang += M_PI;
 
                f1 = d_x / vid_conwidth;
                f2 = d_y / vid_conheight;
@@ -211,13 +470,11 @@ void Draw_WaypointSprite()
                        {
                                // RIGHT edge
                                d = d * (0.5 / f1);
-                               rot = 3;
                        }
                        else
                        {
                                // LEFT edge
                                d = d * (-0.5 / f1);
-                               rot = 1;
                        }
                }
                else
@@ -226,32 +483,34 @@ void Draw_WaypointSprite()
                        {
                                // BOTTOM edge
                                d = d * (0.5 / f2);
-                               rot = 0;
                        }
                        else
                        {
                                // TOP edge
                                d = d * (-0.5 / f2);
-                               rot = 2;
                        }
                }
 
                o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
        }
-       o_z = 0;
-
-       float vidscale;
-       vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
-
-       t = stof(db_get(tempdb, strcat("/spriteframes/", spriteimage)));
-       if(t == 0)
-               spriteimage = strcat("models/sprites/", spriteimage);
        else
-               spriteimage = strcat("models/sprites/", spriteimage, "_frame", ftos(mod(floor((max(0, time - self.spawntime)) * 2), t)));
+       {
+#if 1
+               ang = M_PI;
+#else
+               vector d;
+               d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight;
+               ang = atan2(-d_x, -d_y);
+#endif
+       }
+       o_z = 0;
 
        float edgedistance_min, crosshairdistance;
        edgedistance_min = min4(o_y, o_x,vid_conwidth - o_x, vid_conheight - o_y);
 
+       float vidscale;
+       vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
+
        crosshairdistance = sqrt( pow(o_x - vid_conwidth/2, 2) + pow(o_y - vid_conheight/2, 2) );
 
        t = waypointsprite_scale * vidscale;
@@ -269,7 +528,6 @@ void Draw_WaypointSprite()
                a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
                t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
        }
-       drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * t, SPRITE_HOTSPOT * t, '1 1 1', a, DRAWFLAG_MIPMAP);
 
        if(self.build_finished)
        {
@@ -286,14 +544,47 @@ void Draw_WaypointSprite()
                        self.health = -1;
        }
 
+       o = drawspritearrow(o, ang, rgb, a, SPRITE_ARROW_SCALE * t);
+       
+       string txt;
+       txt = spritelookuptext(spriteimage);
+       if(autocvar_g_waypointsprite_uppercase)
+               txt = strtoupper(txt);
+
        if(self.health >= 0)
        {
-               float align;
+               o = drawspritetext(o, ang, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
+
+               float align, marg;
                if(self.build_finished)
                        align = 0.5;
                else
                        align = 0;
-               drawhealthbar(o, rot * 90 * DEG2RAD, self.health, SPRITE_SIZE * t, SPRITE_HOTSPOT * t, SPRITE_HEALTHBAR_WIDTH * t, SPRITE_HEALTHBAR_HEIGHT * t, SPRITE_HEALTHBAR_MARGIN * t, SPRITE_HEALTHBAR_BORDER * t, align, self.teamradar_color, a * SPRITE_HEALTHBAR_BORDERALPHA, self.teamradar_color, a * SPRITE_HEALTHBAR_HEALTHALPHA, DRAWFLAG_NORMAL);
+               if(cos(ang) > 0)
+                       marg = -(SPRITE_HEALTHBAR_MARGIN + SPRITE_HEALTHBAR_HEIGHT + 2 * SPRITE_HEALTHBAR_BORDER) * t - 0.5 * waypointsprite_fontsize;
+               else
+                       marg = SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize;
+               drawhealthbar(
+                               o,
+                               0,
+                               self.health,
+                               '0 0 0',
+                               '0 0 0',
+                               SPRITE_HEALTHBAR_WIDTH * t,
+                               SPRITE_HEALTHBAR_HEIGHT * t,
+                               marg,
+                               SPRITE_HEALTHBAR_BORDER * t,
+                               align,
+                               rgb,
+                               a * SPRITE_HEALTHBAR_BORDERALPHA,
+                               rgb,
+                               a * SPRITE_HEALTHBAR_HEALTHALPHA,
+                               DRAWFLAG_NORMAL
+                            );
+       }
+       else
+       {
+               o = drawspritetext(o, ang, 0, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
        }
 }
 
@@ -438,6 +729,7 @@ void WaypointSprite_Load()
        waypointsprite_distancealphaexponent = autocvar_g_waypointsprite_distancealphaexponent;
        waypointsprite_timealphaexponent = autocvar_g_waypointsprite_timealphaexponent;
        waypointsprite_scale = autocvar_g_waypointsprite_scale;
+       waypointsprite_fontsize = autocvar_g_waypointsprite_fontsize;
        waypointsprite_edgefadealpha = autocvar_g_waypointsprite_edgefadealpha;
        waypointsprite_edgefadescale = autocvar_g_waypointsprite_edgefadescale;
        waypointsprite_edgefadedistance = autocvar_g_waypointsprite_edgefadedistance;
index 9300ac721d889366a386bc8b0a06fb0656ad1443..63e971b17da9c52cacc638e8ae6c3f006cff096f 100644 (file)
@@ -1,4 +1,5 @@
 
+entity ka_ball;
 // traces multiple trajectories to find one that will impact the target
 // 'end' vector is the place it aims for,
 // returns TRUE only if it hit targ (don't target non-solid entities)
@@ -113,6 +114,12 @@ float bot_shouldattack(entity e)
                if(e.freezetag_frozen)
                        return FALSE;
 
+       // If neither player has ball then don't attack unless the ball is on the
+       // ground.
+       if (g_keepaway)
+               if (!e.ballcarried && !self.ballcarried && ka_ball.owner)
+                       return FALSE;
+
        if(teamplay)
        {
                if(e.team==0)
index dd111d9f00400f376eedd8ea6462ec90c3caaddd..5da945c90124d8d7262bdbd5830653860ad336d2 100644 (file)
@@ -2,6 +2,7 @@
 #include "role_ctf.qc"
 #include "role_onslaught.qc"
 #include "role_keyhunt.qc"
+#include "role_keepaway.qc"
 #include "roles.qc"
 
 void havocbot_ai()
diff --git a/qcsrc/server/bot/havocbot/role_keepaway.qc b/qcsrc/server/bot/havocbot/role_keepaway.qc
new file mode 100644 (file)
index 0000000..30d9649
--- /dev/null
@@ -0,0 +1,82 @@
+void() havocbot_role_ka_carrier;
+void() havocbot_role_ka_collector;
+void() havocbot_chooserole_ka;
+
+entity ka_ball;
+
+// Keepaway
+// If you don't have the ball, get it; if you do, kill people.
+
+void havocbot_goalrating_ball(float ratingscale, vector org)
+{
+       local float t, distance;
+       local entity ball_owner;
+       ball_owner = ka_ball.owner;
+
+       if (ball_owner == self)
+               return;
+
+       // If ball is carried by player then hunt them down.
+       if (ball_owner)
+       {
+               t = (self.health + self.armorvalue) / (ball_owner.health + ball_owner.armorvalue);
+               navigation_routerating(ball_owner, t * ratingscale, 2000);
+       }
+
+       // Ball has been dropped so collect.
+       navigation_routerating(ka_ball, ratingscale, 2000);
+};
+
+void havocbot_role_ka_carrier()
+{
+       if (self.deadflag != DEAD_NO)
+               return;
+
+       if (time > self.bot_strategytime)
+       {
+               self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
+
+               navigation_goalrating_start();
+               havocbot_goalrating_items(10000, self.origin, 10000);
+               havocbot_goalrating_enemyplayers(20000, self.origin, 10000);
+               //havocbot_goalrating_waypoints(1, self.origin, 1000);
+               navigation_goalrating_end();
+       }
+
+       if (!self.ballcarried)
+       {
+               self.havocbot_role = havocbot_role_ka_collector;
+               self.bot_strategytime = 0;
+       }
+};
+
+void havocbot_role_ka_collector()
+{
+       if (self.deadflag != DEAD_NO)
+               return;
+
+       if (time > self.bot_strategytime)
+       {
+               self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
+
+               navigation_goalrating_start();
+               havocbot_goalrating_items(10000, self.origin, 10000);
+               havocbot_goalrating_enemyplayers(1000, self.origin, 10000);
+               havocbot_goalrating_ball(20000, self.origin);
+               navigation_goalrating_end();
+       }
+
+       if (self.ballcarried)
+       {
+               self.havocbot_role = havocbot_role_ka_carrier;
+               self.bot_strategytime = 0;
+       }
+};
+
+void havocbot_chooserole_ka()
+{
+       if (self.ballcarried)
+               self.havocbot_role = havocbot_role_ka_carrier;
+       else
+               self.havocbot_role = havocbot_role_ka_collector;
+};
index ebd0d4e44d1cc28458c547c46df2c8c2906b7d07..b10834092606d1c4c2d57c27d42e2e51dc6ee786 100644 (file)
@@ -274,24 +274,6 @@ void havocbot_role_race()
        }
 };
 
-// Keepaway
-// If you don't have the ball, get it; if you do, kill people.
-void havocbot_role_ka()
-{
-       if(self.deadflag != DEAD_NO)
-               return;
-
-       if (self.bot_strategytime < time)
-       {
-               self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
-               navigation_goalrating_start();
-               havocbot_goalrating_items(10000, self.origin, 10000);
-               havocbot_goalrating_enemyplayers(20000, self.origin, 10000);
-               //havocbot_goalrating_waypoints(1, self.origin, 1000);
-               navigation_goalrating_end();
-       }
-}
-
 void havocbot_chooserole_dm()
 {
        self.havocbot_role = havocbot_role_dm;
@@ -307,11 +289,6 @@ void havocbot_chooserole_dom()
        self.havocbot_role = havocbot_role_dom;
 };
 
-void havocbot_chooserole_ka()
-{
-       self.havocbot_role = havocbot_role_ka;
-}
-
 void havocbot_chooserole()
 {
        dprint("choosing a role...\n");
index d6140ea2afaaab83b826f0890820c5062e93550e..cb88d354e4087a13d40ddf5473b50bb9ecef754a 100644 (file)
@@ -562,10 +562,6 @@ void ClientData_Touch(entity e);
 
 vector debug_shotorg; // if non-zero, overrides the shot origin of all weapons
 
-// the QC VM sucks
-#define BITXOR(v,b)        ((v) + (b) - 2 * ((v) & (b)))
-#define BITXOR_ASSIGN(v,b) ((v) += ((b) - 2 * ((v) & (b))))
-
 .float wasplayer;
 
 float servertime, serverprevtime, serverframetime;
index 85a29031a8ec8ecc8a55bb9a60f3f6a8c7613e9a..1d091b1156763ddf1c1b49d6ffbc0b0fda98b4f0 100644 (file)
@@ -4,6 +4,8 @@ void ka_RespawnBall(void);
 void ka_DropEvent(entity);
 void ka_TimeScoring(void);
 
+entity ka_ball;
+
 float ka_ballcarrier_waypointsprite_visible_for_player(entity);
 
 void ka_Initialize() // run at the start of a match, initiates game mode
@@ -50,6 +52,7 @@ void ka_SpawnBall() // loads various values for the ball, runs only once at star
        e.reset = ka_Reset;
        e.touch = ka_TouchEvent;
        e.owner = world;
+       ka_ball = e;
 
        InitializeEntity(e, ka_RespawnBall, INITPRIO_SETLOCATION); // is this the right priority? Neh, I have no idea.. Well-- it works! So. 
 }
index 0ce3d515a1d537837699d88b825fc9216dad9276..a0f750b05beef72ba6ee7b2daa907d21dbc7b32e 100644 (file)
@@ -355,7 +355,7 @@ void Portal_Disconnect(entity teleporter, entity destination)
 
 void Portal_Connect(entity teleporter, entity destination)
 {
-       teleporter.portal_transform = AnglesTransform_Divide(AnglesTransform_TurnDirectionFR(destination.mangle), teleporter.mangle);
+       teleporter.portal_transform = AnglesTransform_RightDivide(AnglesTransform_TurnDirectionFR(destination.mangle), teleporter.mangle);
 
        teleporter.enemy = destination;
        destination.enemy = teleporter;
index 56f72bfd75bfee9235523ff55ffe8c418a732b83..3233f6a31cef9d6fbe6b5a14decc5af1654c05e8 100644 (file)
@@ -84,11 +84,16 @@ vector AnglesTransform_TurnDirectionFU(vector transform)
        return transform;
 }
 
-vector AnglesTransform_Divide(vector to_transform, vector from_transform)
+vector AnglesTransform_RightDivide(vector to_transform, vector from_transform)
 {
        return AnglesTransform_Multiply(to_transform, AnglesTransform_Invert(from_transform));
 }
 
+vector AnglesTransform_LeftDivide(vector from_transform, vector to_transform)
+{
+       return AnglesTransform_Multiply(AnglesTransform_Invert(from_transform), to_transform);
+}
+
 vector AnglesTransform_Normalize(vector t, float minimize_roll)
 {
        float need_flip;
index 045fb24b3afcc196759e661a2d5bb6e96fb80b00..b1c8a85e9da5916983322a5fad1016216e3250d1 100644 (file)
@@ -11,11 +11,12 @@ void fixedmakevectors(vector a);
 #endif
 
 vector AnglesTransform_Apply(vector transform, vector v);
-vector AnglesTransform_Multiply(vector t1, vector t2);
+vector AnglesTransform_Multiply(vector t1, vector t2); // A B
 vector AnglesTransform_Invert(vector transform);
 vector AnglesTransform_TurnDirectionFU(vector transform);
 vector AnglesTransform_TurnDirectionFR(vector transform);
-vector AnglesTransform_Divide(vector to_transform, vector from_transform);
+vector AnglesTransform_RightDivide(vector to_transform, vector from_transform); // A B^-1
+vector AnglesTransform_LeftDivide(vector from_transform, vector to_transform); // A^-1 B
 
 vector AnglesTransform_Normalize(vector t, float minimize_roll); // makes sure all angles are in their range: yaw in -180..180, pitch in -90..90, roll in -180..180 (or if minimize_roll is set, pitch in -180..180, roll in -90..90)
 
index 62e74682090c725e544ce7725e57bc8ba2a06294..bb4f965f77ad5a49e5e0a780e5fc5c6c0334fa28 100644 (file)
@@ -52,7 +52,7 @@ vector WarpZone_camera_transform(vector org, vector ang)
 
 void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, vector other_ang)
 {
-       e.warpzone_transform = AnglesTransform_Divide(other_ang, AnglesTransform_TurnDirectionFR(my_ang));
+       e.warpzone_transform = AnglesTransform_RightDivide(other_ang, AnglesTransform_TurnDirectionFR(my_ang));
        e.warpzone_shift = AnglesTransform_PrePostShift_GetPostShift(my_org, e.warpzone_transform, other_org);
        e.warpzone_origin = my_org;
        e.warpzone_targetorigin = other_org;
@@ -230,7 +230,7 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end,
                        break;
        }
        if((contentshack = (forent.dphitcontentsmask && !(forent.dphitcontentsmask & DPCONTENTS_SOLID))))
-               forent.dphitcontentsmask |= DPCONTENTS_SOLID;
+               BITSET_ASSIGN(forent.dphitcontentsmask, DPCONTENTS_SOLID);
 
        // if starting in warpzone, first transform
        wz = WarpZone_Find(org + mi, org + ma);
@@ -304,7 +304,7 @@ void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end,
        WarpZone_MakeAllOther();
 :fail
        if(contentshack)
-               forent.dphitcontentsmask &~= DPCONTENTS_SOLID;
+               BITCLR_ASSIGN(forent.dphitcontentsmask, DPCONTENTS_SOLID);
        trace_startsolid = sol;
        v_forward = vf;
        v_right = vr;
index 72485f25c4bc91ef64d1af1ab4c81576a407a6da..1dc12b8cfe97f60bc75d5139bb653a04b1eacf3e 100644 (file)
@@ -4,8 +4,6 @@
 float warpzone_warpzones_exist;
 float warpzone_cameras_exist;
 
-const void func_null(void); // never assign to this one please
-
 .float warpzone_isboxy;
 .vector warpzone_shift;
 .vector warpzone_origin;
@@ -71,3 +69,22 @@ vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel);
 vector WarpZone_RefSys_TransformAngles(entity from, entity to, vector ang);
 vector WarpZone_RefSys_TransformVAngles(entity from, entity to, vector ang);
 entity WarpZone_RefSys_SpawnSameRefSys(entity me);
+
+#ifndef BITCLR
+# define BITCLR(a,b) ((a) - ((a) & (b)))
+#endif
+#ifndef BITSET
+# define BITSET(a,b) ((a) | (b))
+#endif
+#ifndef BITXOR
+# define BITXOR(a,b) (((a) | (b)) - ((a) & (b)))
+#endif
+#ifndef BITCLR_ASSIGN
+# define BITCLR_ASSIGN(a,b) ((a) = (a) - ((a) & (b)))
+#endif
+#ifndef BITSET_ASSIGN
+# define BITSET_ASSIGN(a,b) ((a) |= (b))
+#endif
+#ifndef BITXOR_ASSIGN
+# define BITXOR_ASSIGN(a,b) ((a) = ((a) | (b)) - ((a) & (b)))
+#endif
index 29f5dc8db11aaf218354895ed5bba94f53e76397..1ec66022144fbf74bf67a1fa9196627e108cddc7 100644 (file)
@@ -1,3 +1,10 @@
+// for think function
+.vector warpzone_save_origin;
+.vector warpzone_save_angles;
+.vector warpzone_save_eorigin;
+.vector warpzone_save_eangles;
+
+// for all entities
 .vector warpzone_oldorigin, warpzone_oldvelocity, warpzone_oldangles;
 .float warpzone_teleport_time;
 .entity warpzone_teleport_zone;
@@ -22,13 +29,10 @@ void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector
        player.fixangle = TRUE;
        player.velocity = to_velocity;
 
-       if(player.effects & EF_TELEPORT_BIT)
-               player.effects &~= EF_TELEPORT_BIT;
-       else
-               player.effects |= EF_TELEPORT_BIT;
+       BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT);
 
        if(player.classname == "player")
-               player.flags &~= FL_ONGROUND;
+               BITCLR_ASSIGN(player.flags, FL_ONGROUND);
 
        WarpZone_PostTeleportPlayer_Callback(player);
 }
@@ -171,11 +175,11 @@ float WarpZone_Send(entity to, float sendflags)
        // we must send this flag for clientside to match properly too
        f = 0;
        if(self.warpzone_isboxy)
-               f |= 1;
+               BITSET_ASSIGN(f, 1);
        if(self.warpzone_fadestart)
-               f |= 2;
+               BITSET_ASSIGN(f, 2);
        if(self.origin != '0 0 0')
-               f |= 4;
+               BITSET_ASSIGN(f, 4);
        WriteByte(MSG_ENTITY, f);
 
        // we need THESE to render the warpzone (and cull properly)...
@@ -224,9 +228,9 @@ float WarpZone_Camera_Send(entity to, float sendflags)
        WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_CAMERA);
 
        if(self.warpzone_fadestart)
-               f |= 2;
+               BITSET_ASSIGN(f, 2);
        if(self.origin != '0 0 0')
-               f |= 4;
+               BITSET_ASSIGN(f, 4);
        WriteByte(MSG_ENTITY, f);
 
        // we need THESE to render the warpzone (and cull properly)...
@@ -369,6 +373,22 @@ void WarpZonePosition_InitStep_FindTarget()
        self.enemy.aiment = self;
 }
 
+void WarpZoneCamera_Think(void)
+{
+       if(self.warpzone_save_origin != self.origin
+       || self.warpzone_save_angles != self.angles
+       || self.warpzone_save_eorigin != self.enemy.origin
+       || self.warpzone_save_eangles != self.enemy.angles)
+       {
+               WarpZone_Camera_SetUp(self, self.enemy.origin, self.enemy.angles);
+               self.warpzone_save_origin = self.origin;
+               self.warpzone_save_angles = self.angles;
+               self.warpzone_save_eorigin = self.enemy.origin;
+               self.warpzone_save_eangles = self.enemy.angles;
+       }
+       self.nextthink = time;
+}
+
 void WarpZoneCamera_InitStep_FindTarget()
 {
        entity e;
@@ -390,6 +410,13 @@ void WarpZoneCamera_InitStep_FindTarget()
        warpzone_cameras_exist = 1;
        WarpZone_Camera_SetUp(self, self.enemy.origin, self.enemy.angles);
        self.SendFlags = 0xFFFFFF;
+       if(self.spawnflags & 1)
+       {
+               self.think = WarpZoneCamera_Think;
+               self.nextthink = time;
+       }
+       else
+               self.nextthink = 0;
 }
 
 void WarpZone_InitStep_UpdateTransform()
@@ -411,7 +438,7 @@ void WarpZone_InitStep_UpdateTransform()
                tex = getsurfacetexture(self, i_s);
                if not(tex)
                        break; // this is beyond the last one
-               if(tex == "textures/common/trigger")
+               if(tex == "textures/common/trigger" || tex == "trigger")
                        continue;
                n_t = getsurfacenumtriangles(self, i_s);
                for(i_t = 0; i_t < n_t; ++i_t)
@@ -514,6 +541,7 @@ void WarpZone_InitStep_FindTarget()
        }
 }
 
+void WarpZone_Think();
 void WarpZone_InitStep_FinalizeTransform()
 {
        if(!self.enemy || self.enemy.enemy != self)
@@ -526,6 +554,13 @@ void WarpZone_InitStep_FinalizeTransform()
        WarpZone_SetUp(self, self.warpzone_origin, self.warpzone_angles, self.enemy.warpzone_origin, self.enemy.warpzone_angles);
        self.touch = WarpZone_Touch;
        self.SendFlags = 0xFFFFFF;
+       if(self.spawnflags & 1)
+       {
+               self.think = WarpZone_Think;
+               self.nextthink = time;
+       }
+       else
+               self.nextthink = 0;
 }
 
 float warpzone_initialized;
@@ -553,6 +588,11 @@ void spawnfunc_trigger_warpzone(void)
        //              the map, with another killtarget to designate its
        //              orientation
 
+#ifndef WARPZONE_USE_FIXANGLE
+       // used when teleporting
+       precache_model("null");
+#endif
+
        if(!self.scale)
                self.scale = self.modelscale;
        if(!self.scale)
@@ -572,7 +612,7 @@ void spawnfunc_trigger_warpzone(void)
                setsize(self, self.mins, self.maxs);
        self.SendEntity = WarpZone_Send;
        self.SendFlags = 0xFFFFFF;
-       self.effects |= EF_NODEPTHTEST;
+       BITSET_ASSIGN(self.effects, EF_NODEPTHTEST);
        self.warpzone_next = warpzone_first;
        warpzone_first = self;
 }
@@ -616,6 +656,31 @@ void WarpZones_Reconnect()
        self = e;
 }
 
+void WarpZone_Think()
+{
+       if(self.warpzone_save_origin != self.origin
+       || self.warpzone_save_angles != self.angles
+       || self.warpzone_save_eorigin != self.enemy.origin
+       || self.warpzone_save_eangles != self.enemy.angles)
+       {
+               entity oldself;
+               oldself = self;
+               WarpZone_InitStep_UpdateTransform();
+               self = self.enemy;
+               WarpZone_InitStep_UpdateTransform();
+               self = oldself;
+               WarpZone_InitStep_FinalizeTransform();
+               self = self.enemy;
+               WarpZone_InitStep_FinalizeTransform();
+               self = oldself;
+               self.warpzone_save_origin = self.origin;
+               self.warpzone_save_angles = self.angles;
+               self.warpzone_save_eorigin = self.enemy.origin;
+               self.warpzone_save_eangles = self.enemy.angles;
+       }
+       self.nextthink = time;
+}
+
 void WarpZone_StartFrame()
 {
        entity e;