X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fclient%2Fwaypointsprites.qc;h=d3dd4f7ece93155dada8f8d190961a7de13188ff;hb=a2355ecd27ceaf4de66bce0bdfc78579254a7ece;hp=d7b9ee9d01960829aa3992dcebec4eb6bb7e84c8;hpb=c6b8947c5875567662ac5c3e156325bcff42aee9;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/client/waypointsprites.qc b/qcsrc/client/waypointsprites.qc index d7b9ee9d01..d3dd4f7ece 100644 --- a/qcsrc/client/waypointsprites.qc +++ b/qcsrc/client/waypointsprites.qc @@ -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,248 @@ 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) +{ + R_BeginPolygon("", DRAWFLAG_NORMAL); + R_PolygonVertex(o + rotate('-11.5 9.5 0'*t, ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate('11.5 9.5 0'*t, ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate('0 -2 0'*t, ang), '0 0 0', '0 0 0', a); + R_EndPolygon(); + R_BeginPolygon("", DRAWFLAG_NORMAL); + R_PolygonVertex(o + rotate('-5.5 9.5 0'*t, ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate('-5.5 17.5 0'*t, ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate('5.5 17.5 0'*t, ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate('5.5 9.5 0'*t, ang), '0 0 0', '0 0 0', a); + R_EndPolygon(); + + R_BeginPolygon("", DRAWFLAG_ADDITIVE); + R_PolygonVertex(o + rotate('-8 8 0'*t, ang), '0 0 0', rgb, a); + R_PolygonVertex(o + rotate('8 8 0'*t, ang), '0 0 0', rgb, a); + R_PolygonVertex(o + rotate('0 0 0'*t, ang), '0 0 0', rgb, a); + R_EndPolygon(); + R_BeginPolygon("", DRAWFLAG_ADDITIVE); + R_PolygonVertex(o + rotate('-4 8 0'*t, ang), '0 0 0', rgb, a); + R_PolygonVertex(o + rotate('-4 16 0'*t, ang), '0 0 0', rgb, a); + R_PolygonVertex(o + rotate('4 16 0'*t, ang), '0 0 0', rgb, a); + R_PolygonVertex(o + rotate('4 8 0'*t, ang), '0 0 0', rgb, a); + R_EndPolygon(); + + return + o + rotate('0 20 0'*t, 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"); + 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; @@ -119,11 +361,11 @@ void Draw_WaypointSprite() if(self.hideflags & 2) return; // radar only - if(cvar("cl_hidewaypoints") >= 2) + if(autocvar_cl_hidewaypoints >= 2) return; if(self.hideflags & 1) - if(cvar("cl_hidewaypoints")) + if(autocvar_cl_hidewaypoints) return; // fixed waypoint InterpolateOrigin_Do(); @@ -173,34 +415,38 @@ 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(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(cvar("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 +457,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 +470,28 @@ 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))); + { + ang = M_PI; + } + 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 +509,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 +525,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); } } @@ -336,7 +608,6 @@ void Ent_WaypointSprite() else self.build_starthealth = 0; self.build_finished = servertime + t / 32; - //print("build: ", ftos(self.build_finished - self.build_started), "\n"); } } else @@ -407,48 +678,54 @@ void Ent_WaypointSprite() self.entremove = Ent_RemoveWaypointSprite; } +void WaypointSprite_Load_Frames(string ext) +{ + float dh, n, i, o, f; + string s, sname, sframes; + dh = search_begin(strcat("models/sprites/*_frame*", ext), FALSE, FALSE); + if (dh < 0) + return; + float ext_len = strlen(ext); + n = search_getsize(dh); + for(i = 0; i < n; ++i) + { + s = search_getfilename(dh, i); + s = substring(s, 15, strlen(s) - 15 - ext_len); // strip models/sprites/ and extension + + o = strstrofs(s, "_frame", 0); + sname = strcat("/spriteframes/", substring(s, 0, o)); + sframes = substring(s, o + 6, strlen(s) - o - 6); + f = stof(sframes) + 1; + db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname))))); + } + search_end(dh); +} + void WaypointSprite_Load() { - waypointsprite_fadedistance = vlen(mi_max - mi_min); - waypointsprite_normdistance = cvar("g_waypointsprite_normdistance"); - waypointsprite_minscale = cvar("g_waypointsprite_minscale"); - waypointsprite_minalpha = cvar("g_waypointsprite_minalpha"); - waypointsprite_distancealphaexponent = cvar("g_waypointsprite_distancealphaexponent"); - waypointsprite_timealphaexponent = cvar("g_waypointsprite_timealphaexponent"); - waypointsprite_scale = cvar_or("g_waypointsprite_scale", 1); - waypointsprite_edgefadealpha = cvar_or("g_waypointsprite_edgefadealpha", 1); - waypointsprite_edgefadescale = cvar_or("g_waypointsprite_edgefadescale", 1); - waypointsprite_edgefadedistance = cvar("g_waypointsprite_edgefadedistance"); - waypointsprite_crosshairfadealpha = cvar_or("g_waypointsprite_crosshairfadealpha", 1); - waypointsprite_crosshairfadescale = cvar_or("g_waypointsprite_crosshairfadescale", 1); - waypointsprite_crosshairfadedistance = cvar("g_waypointsprite_crosshairfadedistance"); - waypointsprite_distancefadealpha = cvar_or("g_waypointsprite_distancefadealpha", 1); - waypointsprite_distancefadescale = cvar_or("g_waypointsprite_distancefadescale", 1); - waypointsprite_distancefadedistance = vlen(mi_max - mi_min) * cvar_or("g_waypointsprite_distancefadedistancemultiplier", 1); - waypointsprite_alpha = cvar_or("g_waypointsprite_alpha", 1) * (1 - cvar("_menu_alpha")); + waypointsprite_fadedistance = vlen(mi_scale); + waypointsprite_normdistance = autocvar_g_waypointsprite_normdistance; + waypointsprite_minscale = autocvar_g_waypointsprite_minscale; + waypointsprite_minalpha = autocvar_g_waypointsprite_minalpha; + 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; + waypointsprite_crosshairfadealpha = autocvar_g_waypointsprite_crosshairfadealpha; + waypointsprite_crosshairfadescale = autocvar_g_waypointsprite_crosshairfadescale; + waypointsprite_crosshairfadedistance = autocvar_g_waypointsprite_crosshairfadedistance; + waypointsprite_distancefadealpha = autocvar_g_waypointsprite_distancefadealpha; + waypointsprite_distancefadescale = autocvar_g_waypointsprite_distancefadescale; + waypointsprite_distancefadedistance = waypointsprite_fadedistance * autocvar_g_waypointsprite_distancefadedistancemultiplier; + waypointsprite_alpha = autocvar_g_waypointsprite_alpha * (1 - autocvar__menu_alpha); if(!waypointsprite_initialized) { - float dh, n, i, o, f; - string s, sname, sframes; - dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE); - n = search_getsize(dh); - for(i = 0; i < n; ++i) - { - s = search_getfilename(dh, i); - if(substring(s, 0, 15) != "models/sprites/") - continue; - if(substring(s, strlen(s) - 4, 4) != ".tga") - continue; - s = substring(s, 15, strlen(s) - 19); - - o = strstrofs(s, "_frame", 0); - sname = strcat("/spriteframes/", substring(s, 0, o)); - sframes = substring(s, o + 6, strlen(s) - o - 6); - f = stof(sframes) + 1; - db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname))))); - } - search_end(dh); + WaypointSprite_Load_Frames(".tga"); + WaypointSprite_Load_Frames(".jpg"); + waypointsprite_initialized = true; } - waypointsprite_initialized = 1; }