From: TimePath Date: Mon, 24 Aug 2015 11:34:10 +0000 (+1000) Subject: Create waypoint definitions X-Git-Tag: xonotic-v0.8.2~2027^2~1 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=3cc2f37092129be173109ef4c47d765945e94b7a;p=xonotic%2Fxonotic-data.pk3dir.git Create waypoint definitions --- diff --git a/qcsrc/common/monsters/sv_monsters.qc b/qcsrc/common/monsters/sv_monsters.qc index 249e6f97e..6a3553b1c 100644 --- a/qcsrc/common/monsters/sv_monsters.qc +++ b/qcsrc/common/monsters/sv_monsters.qc @@ -1144,7 +1144,9 @@ float monster_spawn() MonsterSound(monstersound_spawn, 0, false, CH_VOICE); - WaypointSprite_Spawn(M_NAME(self.monsterid), 0, 1024, self, '0 0 1' * (self.maxs.z + 15), world, self.team, self, sprite, true, RADARICON_DANGER, ((self.team) ? Team_ColorRGB(self.team) : '1 0 0')); + entity wp = WaypointSprite_Spawn(WP_Monster, 0, 1024, self, '0 0 1' * (self.maxs.z + 15), world, self.team, self, sprite, true, RADARICON_DANGER); + wp.wp_extra = self.monsterid; + wp.colormod = ((self.team) ? Team_ColorRGB(self.team) : '1 0 0'); if(!(self.spawnflags & MONSTERFLAG_INVINCIBLE)) { WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health); diff --git a/qcsrc/common/mutators/all.inc b/qcsrc/common/mutators/all.inc index 0471dff7c..ffdc453f1 100644 --- a/qcsrc/common/mutators/all.inc +++ b/qcsrc/common/mutators/all.inc @@ -1,3 +1,3 @@ #include "mutator/damagetext.qc" #include "mutator/itemstime.qc" -#include "mutator/waypointsprites.qc" +#include "mutator/waypoints/waypointsprites.qc" diff --git a/qcsrc/common/mutators/mutator/waypoints/all.inc b/qcsrc/common/mutators/mutator/waypoints/all.inc new file mode 100644 index 000000000..e1153c2b8 --- /dev/null +++ b/qcsrc/common/mutators/mutator/waypoints/all.inc @@ -0,0 +1,68 @@ +/** If you register a new waypoint, make sure to add it to this list */ +REGISTER_WAYPOINT(, "", '0 0 0', 1); +#define WP_Null WP_ + +REGISTER_WAYPOINT(Waypoint, _("Waypoint"), '0 1 1', 1); +REGISTER_WAYPOINT(Helpme, _("Help me!"), '1 0.5 0', 1); +REGISTER_WAYPOINT(Here, _("Here"), '0 1 0', 1); +REGISTER_WAYPOINT(Danger, _("DANGER"), '1 0.5 0', 1); + +REGISTER_WAYPOINT(Frozen, _("Frozen!"), '0.25 0.90 1', 1); + +REGISTER_WAYPOINT(Item, _("Item"), '1 0 1', 1); + +REGISTER_WAYPOINT(RaceCheckpoint, _("Checkpoint"), '1 0.5 0', 1); +REGISTER_WAYPOINT(RaceFinish, _("Finish"), '1 0.5 0', 1); +REGISTER_WAYPOINT(RaceStart, _("Start"), '1 0.5 0', 1); +REGISTER_WAYPOINT(RaceStartFinish, _("Start"), '1 0.5 0', 1); + +REGISTER_WAYPOINT(Assault, _(""), '1 0.5 0', 1); +REGISTER_WAYPOINT(AssaultDefend, _("Defend"), '1 0.5 0', 1); +REGISTER_WAYPOINT(AssaultDestroy, _("Destroy"), '1 0.5 0', 1); +REGISTER_WAYPOINT(AssaultPush, _("Push"), '1 0.5 0', 1); + +REGISTER_WAYPOINT(FlagCarrier, _("Flag carrier"), '0.8 0.8 0', 1); +REGISTER_WAYPOINT(FlagCarrierEnemy, _("Enemy carrier"), '1 1 1', 1); +REGISTER_WAYPOINT(FlagDropped, _("Dropped flag"), '1 1 1', 1); +REGISTER_WAYPOINT(FlagBaseNeutral, _("White base"), '0.8 0.8 0', 1); +REGISTER_WAYPOINT(FlagBaseRed, _("Red base"), '0.8 0.8 0', 1); +REGISTER_WAYPOINT(FlagBaseBlue, _("Blue base"), '0.8 0.8 0', 1); +REGISTER_WAYPOINT(FlagBaseYellow, _("Yellow base"), '0.8 0.8 0', 1); +REGISTER_WAYPOINT(FlagBasePink, _("Pink base"), '0.8 0.8 0', 1); + +REGISTER_WAYPOINT(DomNeut, _("Control point"), '0 1 1', 1); +REGISTER_WAYPOINT(DomRed, _("Control point"), '0 1 1', 1); +REGISTER_WAYPOINT(DomBlue, _("Control point"), '0 1 1', 1); +REGISTER_WAYPOINT(DomYellow, _("Control point"), '0 1 1', 1); +REGISTER_WAYPOINT(DomPink, _("Control point"), '0 1 1', 1); + +REGISTER_WAYPOINT(KeyDropped, _("Dropped key"), '0 1 1', 1); +REGISTER_WAYPOINT(KeyCarrierFriend, _("Key carrier"), '0 1 0', 1); +REGISTER_WAYPOINT(KeyCarrierFinish, _("Run here"), '0 1 1', 1); +REGISTER_WAYPOINT(KeyCarrierRed, _("Key carrier"), '0 1 1', 1); +REGISTER_WAYPOINT(KeyCarrierBlue, _("Key carrier"), '0 1 1', 1); +REGISTER_WAYPOINT(KeyCarrierYellow, _("Key carrier"), '0 1 1', 1); +REGISTER_WAYPOINT(KeyCarrierPink, _("Key carrier"), '0 1 1', 1); + +REGISTER_WAYPOINT(KaBall, _("Ball"), '0 1 1', 1); +REGISTER_WAYPOINT(KaBallCarrier, _("Ball carrier"), '1 0 0', 1); + +REGISTER_WAYPOINT(NbBall, _("Ball"), '0.91 0.85 0.62', 1); +REGISTER_WAYPOINT(NbGoal, _("Goal"), '1 0.5 0', 1); + +REGISTER_WAYPOINT(OnsCP, _("Control point"), '1 0.5 0', 1); +REGISTER_WAYPOINT(OnsCPDefend, _("Control point"), '1 0.5 0', 0.5); +REGISTER_WAYPOINT(OnsCPAttack, _("Control point"), '1 0.5 0', 2); +REGISTER_WAYPOINT(OnsGen, _("Generator"), '1 0.5 0', 1); +REGISTER_WAYPOINT(OnsGenShielded, _("Generator"), '1 0.5 0', 1); + +REGISTER_WAYPOINT(Buff, _("Buff"), '1 0.5 0', 1); + +REGISTER_WAYPOINT(Weapon, _("Weapon"), '0 0 0', 1); + +REGISTER_WAYPOINT(Monster, _("Monster"), '1 0 0', 1); + +REGISTER_WAYPOINT(Vehicle, _("Vehicle"), '1 1 1', 1); +REGISTER_WAYPOINT(VehicleIntruder, _("Intruder!"), '1 1 1', 1); + +REGISTER_WAYPOINT(Seeker, _("Tagged"), '0.5 1 0', 2); diff --git a/qcsrc/common/mutators/mutator/waypoints/all.qh b/qcsrc/common/mutators/mutator/waypoints/all.qh new file mode 100644 index 000000000..9670a6f38 --- /dev/null +++ b/qcsrc/common/mutators/mutator/waypoints/all.qh @@ -0,0 +1,35 @@ +#include "../../../registry.qh" + +#ifndef WAYPOINTS_ALL_H +#define WAYPOINTS_ALL_H + +#include "waypointsprites.qh" + +void RegisterWaypoints(); +const int MAX_WAYPOINTS = 240; +entity WAYPOINTS[MAX_WAYPOINTS], WAYPOINTS_first, WAYPOINTS_last; +int WAYPOINT_COUNT; +/** If you register a new waypoint, make sure to add it to all.inc */ +#define REGISTER_WAYPOINT_(id, init) REGISTER(RegisterWaypoints, WP, WAYPOINTS, WAYPOINT_COUNT, id, m_id, init) +REGISTER_REGISTRY(RegisterWaypoints) + +CLASS(Waypoint, Object) + ATTRIB(Waypoint, m_id, int, 0) + ATTRIB(Waypoint, netname, string, string_null) + ATTRIB(Waypoint, m_name, string, string_null) + ATTRIB(Waypoint, m_color, vector, '1 1 1') + ATTRIB(Waypoint, m_blink, int, 1) + CONSTRUCTOR(Waypoint, string _netname, string _name, vector _color, int _blink) { + CONSTRUCT(Waypoint); + this.netname = _netname; + this.m_name = _name; + this.m_color = _color; + this.m_blink = _blink; + } +ENDCLASS(Waypoint) + +#define REGISTER_WAYPOINT(id, text, color, blink) REGISTER_WAYPOINT_(id, NEW(Waypoint, #id, text, color, blink)) + +#include "all.inc" + +#endif diff --git a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc new file mode 100644 index 000000000..c5fa1ac00 --- /dev/null +++ b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc @@ -0,0 +1,1161 @@ +#include "waypointsprites.qh" + +REGISTER_MUTATOR(waypointsprites, true); + +#ifdef SVQC +/** flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable] */ +float WaypointSprite_SendEntity(entity to, float sendflags) +{ + WriteMutator(MSG_ENTITY, waypointsprites); + + sendflags = sendflags & 0x7F; + + if (g_nexball) + sendflags &= ~0x80; + else if (self.max_health || (self.pain_finished && (time < self.pain_finished + 0.25))) + sendflags |= 0x80; + + WriteByte(MSG_ENTITY, sendflags); + WriteByte(MSG_ENTITY, self.wp_extra); + + if (sendflags & 0x80) + { + if (self.max_health) + { + WriteByte(MSG_ENTITY, (self.health / self.max_health) * 191.0); + } + else + { + float dt = self.pain_finished - time; + dt = bound(0, dt * 32, 16383); + WriteByte(MSG_ENTITY, (dt & 0xFF00) / 256 + 192); + WriteByte(MSG_ENTITY, (dt & 0x00FF)); + } + } + + if (sendflags & 64) + { + WriteCoord(MSG_ENTITY, self.origin.x); + WriteCoord(MSG_ENTITY, self.origin.y); + WriteCoord(MSG_ENTITY, self.origin.z); + } + + if (sendflags & 1) + { + WriteByte(MSG_ENTITY, self.team); + WriteByte(MSG_ENTITY, self.rule); + } + + if (sendflags & 2) + WriteString(MSG_ENTITY, self.model1); + + if (sendflags & 4) + WriteString(MSG_ENTITY, self.model2); + + if (sendflags & 8) + WriteString(MSG_ENTITY, self.model3); + + if (sendflags & 16) + { + WriteCoord(MSG_ENTITY, self.fade_time); + WriteCoord(MSG_ENTITY, self.teleport_time); + WriteShort(MSG_ENTITY, self.fade_rate); // maxdist + float f = 0; + if (self.currentammo) + f |= 1; // hideable + if (self.exteriormodeltoclient == to) + f |= 2; // my own + if (g_onslaught) + { + if (self.owner.classname == "onslaught_controlpoint") + { + entity wp_owner = self.owner; + entity e = WaypointSprite_getviewentity(to); + if (SAME_TEAM(e, wp_owner) && wp_owner.goalentity.health >= wp_owner.goalentity.max_health) { f |= 2; } + if (!ons_ControlPoint_Attackable(wp_owner, e.team)) { f |= 2; } + } + if (self.owner.classname == "onslaught_generator") + { + entity wp_owner = self.owner; + if (wp_owner.isshielded && wp_owner.health >= wp_owner.max_health) { f |= 2; } + if (wp_owner.health <= 0) { f |= 2; } + } + } + WriteByte(MSG_ENTITY, f); + } + + if (sendflags & 32) + { + WriteByte(MSG_ENTITY, self.cnt); // icon on radar + WriteByte(MSG_ENTITY, self.colormod.x * 255.0); + WriteByte(MSG_ENTITY, self.colormod.y * 255.0); + WriteByte(MSG_ENTITY, self.colormod.z * 255.0); + + if (WaypointSprite_isteammate(self.owner, WaypointSprite_getviewentity(to))) + { + float dt = (self.waypointsprite_helpmetime - time) / 0.1; + if (dt < 0) + dt = 0; + if (dt > 255) + dt = 255; + WriteByte(MSG_ENTITY, dt); + } + else + WriteByte(MSG_ENTITY, 0); + } + + return true; +} +#endif + +#ifdef CSQC +void Ent_WaypointSprite(); +MUTATOR_HOOKFUNCTION(waypointsprites, CSQC_Ent_Update) { + if (MUTATOR_RETURNVALUE) return false; + if (!ReadMutatorEquals(mutator_argv_int_0, waypointsprites)) return false; + Ent_WaypointSprite(); + return true; +} + +void Ent_RemoveWaypointSprite() +{ + if (self.netname) strunzone(self.netname); + if (self.netname2) strunzone(self.netname2); + if (self.netname3) strunzone(self.netname3); +} + +/** flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable] */ +void Ent_WaypointSprite() +{ + int sendflags = ReadByte(); + self.wp_extra = ReadByte(); + + if (!self.spawntime) + self.spawntime = time; + + self.draw2d = Draw_WaypointSprite; + + InterpolateOrigin_Undo(); + self.iflags |= IFLAG_ORIGIN; + + if (sendflags & 0x80) + { + int t = ReadByte(); + if (t < 192) + { + self.health = t / 191.0; + self.build_finished = 0; + } + else + { + t = (t - 192) * 256 + ReadByte(); + self.build_started = servertime; + if (self.build_finished) + self.build_starthealth = bound(0, self.health, 1); + else + self.build_starthealth = 0; + self.build_finished = servertime + t / 32; + } + } + else + { + self.health = -1; + self.build_finished = 0; + } + + if (sendflags & 64) + { + // unfortunately, this needs to be exact (for the 3D display) + self.origin_x = ReadCoord(); + self.origin_y = ReadCoord(); + self.origin_z = ReadCoord(); + setorigin(self, self.origin); + } + + if (sendflags & 1) + { + self.team = ReadByte(); + self.rule = ReadByte(); + } + + if (sendflags & 2) + { + if (self.netname) + strunzone(self.netname); + self.netname = strzone(ReadString()); + } + + if (sendflags & 4) + { + if (self.netname2) + strunzone(self.netname2); + self.netname2 = strzone(ReadString()); + } + + if (sendflags & 8) + { + if (self.netname3) + strunzone(self.netname3); + self.netname3 = strzone(ReadString()); + } + + if (sendflags & 16) + { + self.lifetime = ReadCoord(); + self.fadetime = ReadCoord(); + self.maxdistance = ReadShort(); + self.hideflags = ReadByte(); + } + + if (sendflags & 32) + { + int f = ReadByte(); + self.teamradar_icon = (f & 0x7F); + if (f & 0x80) + { + self.(teamradar_times[self.teamradar_time_index]) = time; + self.teamradar_time_index = (self.teamradar_time_index + 1) % MAX_TEAMRADAR_TIMES; + } + self.teamradar_color_x = ReadByte() / 255.0; + self.teamradar_color_y = ReadByte() / 255.0; + self.teamradar_color_z = ReadByte() / 255.0; + self.helpme = ReadByte() * 0.1; + if (self.helpme > 0) + self.helpme += servertime; + } + + InterpolateOrigin_Note(); + + self.entremove = Ent_RemoveWaypointSprite; +} +#endif + +#ifdef CSQC +float spritelookupblinkvalue(string s) +{ + if (s == WP_Weapon.netname) { + if (get_weaponinfo(self.wp_extra).spawnflags & WEP_FLAG_SUPERWEAPON) + return 2; + } + if (s == WP_Item.netname) return ITEMS[self.wp_extra].m_waypointblink; + + switch (s) + { + case "item-invis": return 2; + case "item-extralife": return 2; + case "item-speed": return 2; + default: return 1; + } +} + +vector spritelookupcolor(string s, vector def) +{ + if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).wpcolor; + if (s == WP_Item.netname) return ITEMS[self.wp_extra].m_color; + if (s == WP_Buff.netname) return BUFFS[self.wp_extra].m_color; + return def; +} + +string spritelookuptext(string s) +{ + if (s == WP_RaceStartFinish.netname) return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start"); + if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).message; + if (s == WP_Item.netname) return ITEMS[self.wp_extra].m_waypoint; + if (s == WP_Buff.netname) return BUFFS[self.wp_extra].m_prettyName; + if (s == WP_Monster.netname) return get_monsterinfo(self.wp_extra).monster_name; + + // need to loop, as our netname could be one of three + FOREACH(WAYPOINTS, it.netname == s, LAMBDA( + return it.m_name; + )); + + switch (s) + { + case "item-invis": return _("Invisibility"); + case "item-extralife": return _("Extra life"); + case "item-speed": return _("Speed"); + default: return s; + } +} +#endif + +#ifdef CSQC +void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f) +{ + vector v1, v2, v3, v4; + + hotspot = -1 * hotspot; + + // hotspot-relative coordinates of the corners + v1 = hotspot; + v2 = hotspot + '1 0 0' * sz.x; + v3 = hotspot + '1 0 0' * sz.x + '0 1 0' * sz.y; + v4 = hotspot + '0 1 0' * sz.y; + + // rotate them, and make them absolute + rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed + v1 = rotate(v1, rot) + org; + v2 = rotate(v2, rot) + org; + v3 = rotate(v3, rot) + org; + v4 = rotate(v4, rot) + org; + + // draw them + R_BeginPolygon(pic, f); + R_PolygonVertex(v1, '0 0 0', rgb, a); + R_PolygonVertex(v2, '1 0 0', rgb, a); + R_PolygonVertex(v3, '1 1 0', rgb, a); + R_PolygonVertex(v4, '0 1 0', rgb, a); + R_EndPolygon(); +} + +void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f) +{ + R_BeginPolygon(pic, f); + R_PolygonVertex(o, '0 0 0', rgb, a); + R_PolygonVertex(o + ri, '1 0 0', rgb, a); + R_PolygonVertex(o + up + ri, '1 1 0', rgb, a); + R_PolygonVertex(o + up, '0 1 0', rgb, a); + R_EndPolygon(); +} + +void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float theheight, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f) +{ + vector o, ri, up; + float owidth; // outer width + + hotspot = -1 * hotspot; + + // hotspot-relative coordinates of the healthbar corners + o = hotspot; + ri = '1 0 0'; + up = '0 1 0'; + + rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed + o = rotate(o, rot) + org; + ri = rotate(ri, rot); + up = rotate(up, rot); + + owidth = width + 2 * border; + o = o - up * (margin + border + theheight) + ri * (sz.x - owidth) * 0.5; + + drawquad(o - up * border, ri * owidth, up * border, "", rgb, a, f); + drawquad(o + up * theheight, ri * owidth, up * border, "", rgb, a, f); + drawquad(o, ri * border, up * theheight, "", rgb, a, f); + drawquad(o + ri * (owidth - border), ri * border, up * theheight, "", rgb, a, f); + drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * theheight, "", hrgb, ha, f); +} + +// returns location of sprite text +vector drawspritearrow(vector o, float ang, vector rgb, float a, float t) +{ + float size = 9.0 * t; + float border = 1.5 * t; + float margin = 4.0 * t; + + float borderDiag = border * 1.414; + vector arrowX = eX * size; + vector arrowY = eY * (size+borderDiag); + vector borderX = eX * (size+borderDiag); + vector borderY = eY * (size+borderDiag+border); + + R_BeginPolygon("", DRAWFLAG_NORMAL); + R_PolygonVertex(o, '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate(arrowY - borderX, ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate(borderY - borderX, ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate(borderY + borderX, ang), '0 0 0', '0 0 0', a); + R_PolygonVertex(o + rotate(arrowY + borderX, ang), '0 0 0', '0 0 0', a); + R_EndPolygon(); + + R_BeginPolygon("", DRAWFLAG_ADDITIVE); + R_PolygonVertex(o + rotate(eY * borderDiag, ang), '0 0 0', rgb, a); + R_PolygonVertex(o + rotate(arrowY - arrowX, ang), '0 0 0', rgb, a); + R_PolygonVertex(o + rotate(arrowY + arrowX, ang), '0 0 0', rgb, a); + R_EndPolygon(); + + return o + rotate(eY * (borderDiag+size+margin), 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; +} + +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() +{ + if (self.lifetime) + self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent); + else + self.alpha = 1; + + if (self.hideflags & 2) + return; // radar only + + if (autocvar_cl_hidewaypoints >= 2) + return; + + if (self.hideflags & 1) + if (autocvar_cl_hidewaypoints) + return; // fixed waypoint + + InterpolateOrigin_Do(); + + float t = GetPlayerColor(player_localnum) + 1; + + string spriteimage = ""; + + // choose the sprite + switch (self.rule) + { + case SPRITERULE_SPECTATOR: + if (!( + (autocvar_g_waypointsprite_itemstime == 1 && t == NUM_SPECTATOR + 1) + || (autocvar_g_waypointsprite_itemstime == 2 && (t == NUM_SPECTATOR + 1 || warmup_stage)) + )) + return; + spriteimage = self.netname; + break; + case SPRITERULE_DEFAULT: + if (self.team) + { + if (self.team == t) + spriteimage = self.netname; + else + spriteimage = ""; + } + else + spriteimage = self.netname; + break; + case SPRITERULE_TEAMPLAY: + if (t == NUM_SPECTATOR + 1) + spriteimage = self.netname3; + else if (self.team == t) + spriteimage = self.netname2; + else + spriteimage = self.netname; + break; + default: + error("Invalid waypointsprite rule!"); + break; + } + + if (spriteimage == "") + return; + + ++waypointsprite_newcount; + + float dist; + dist = vlen(self.origin - view_origin); + + float a; + a = self.alpha * autocvar_hud_panel_fg_alpha; + + if (self.maxdistance > waypointsprite_normdistance) + a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent); + 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 = spritelookupcolor(spriteimage, self.teamradar_color); + if (rgb == '0 0 0') + { + self.teamradar_color = '1 0 1'; + printf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage); + } + + if (time - floor(time) > 0.5) + { + if (self.helpme && time < self.helpme) + a *= SPRITE_HELPME_BLINK; + else if (!self.lifetime) // fading out waypoints don't blink + a *= spritelookupblinkvalue(spriteimage); + } + + if (a > 1) + { + rgb *= a; + a = 1; + } + + if (a <= 0.003) + return; + + rgb = fixrgbexcess(rgb); + + vector o; + float ang; + + o = project_3d_to_2d(self.origin); + if (o.z < 0 + || o.x < (vid_conwidth * waypointsprite_edgeoffset_left) + || o.y < (vid_conheight * waypointsprite_edgeoffset_top) + || o.x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) + || o.y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom))) + { + // scale it to be just in view + vector d; + float f1, f2; + + d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight; + ang = atan2(-d.x, -d.y); + if (o.z < 0) + ang += M_PI; + + f1 = d.x / vid_conwidth; + f2 = d.y / vid_conheight; + + if (max(f1, -f1) > max(f2, -f2)) { + if (d.z * f1 > 0) { + // RIGHT edge + d = d * ((0.5 - waypointsprite_edgeoffset_right) / f1); + } else { + // LEFT edge + d = d * (-(0.5 - waypointsprite_edgeoffset_left) / f1); + } + } else { + if (d.z * f2 > 0) { + // BOTTOM edge + d = d * ((0.5 - waypointsprite_edgeoffset_bottom) / f2); + } else { + // TOP edge + d = d * (-(0.5 - waypointsprite_edgeoffset_top) / f2); + } + } + + o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight; + } + else + { +#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 = min((o.y - (vid_conheight * waypointsprite_edgeoffset_top)), + (o.x - (vid_conwidth * waypointsprite_edgeoffset_left)), + (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o.x, + (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o.y); + + float vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height); + + float crosshairdistance = sqrt( pow(o.x - vid_conwidth/2, 2) + pow(o.y - vid_conheight/2, 2) ); + + t = waypointsprite_scale * vidscale; + a *= waypointsprite_alpha; + + { + a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1))); + t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1))); + } + if (edgedistance_min < waypointsprite_edgefadedistance) { + a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1))); + t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1))); + } + if (crosshairdistance < waypointsprite_crosshairfadedistance) { + 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))); + } + + if (self.build_finished) + { + if (time < self.build_finished + 0.25) + { + if (time < self.build_started) + self.health = self.build_starthealth; + else if (time < self.build_finished) + self.health = (time - self.build_started) / (self.build_finished - self.build_started) * (1 - self.build_starthealth) + self.build_starthealth; + else + self.health = 1; + } + else + self.health = -1; + } + + o = drawspritearrow(o, ang, rgb, a, SPRITE_ARROW_SCALE * t); + + string txt; + if (autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam) + txt = _("Spam"); + else + txt = spritelookuptext(spriteimage); + if (self.helpme && time < self.helpme) + txt = sprintf(_("%s needing help!"), txt); + if (autocvar_g_waypointsprite_uppercase) + txt = strtoupper(txt); + + draw_beginBoldFont(); + if (self.health >= 0) + { + 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; + 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); + } + draw_endBoldFont(); +} + +void WaypointSprite_Load_Frames(string ext) +{ + int dh = search_begin(strcat("models/sprites/*_frame*", ext), false, false); + if (dh < 0) return; + int ext_len = strlen(ext); + int n = search_getsize(dh); + for (int i = 0; i < n; ++i) + { + string s = search_getfilename(dh, i); + s = substring(s, 15, strlen(s) - 15 - ext_len); // strip models/sprites/ and extension + + int o = strstrofs(s, "_frame", 0); + string sname = strcat("/spriteframes/", substring(s, 0, o)); + string sframes = substring(s, o + 6, strlen(s) - o - 6); + int f = stof(sframes) + 1; + db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname))))); + } + search_end(dh); +} + +void WaypointSprite_Load(); +STATIC_INIT(WaypointSprite_Load) { + WaypointSprite_Load(); + WaypointSprite_Load_Frames(".tga"); + WaypointSprite_Load_Frames(".jpg"); +} +void WaypointSprite_Load() +{ + 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_edgeoffset_bottom = autocvar_g_waypointsprite_edgeoffset_bottom; + waypointsprite_edgeoffset_left = autocvar_g_waypointsprite_edgeoffset_left; + waypointsprite_edgeoffset_right = autocvar_g_waypointsprite_edgeoffset_right; + waypointsprite_edgeoffset_top = autocvar_g_waypointsprite_edgeoffset_top; + 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); + + waypointsprite_count = waypointsprite_newcount; + waypointsprite_newcount = 0; +} +#endif + +#ifdef SVQC +void WaypointSprite_UpdateSprites(entity e, entity _m1, entity _m2, entity _m3) +{ + string m1 = _m1.netname; + string m2 = _m2.netname; + string m3 = _m3.netname; + if (m1 != e.model1) + { + e.model1 = m1; + e.SendFlags |= 2; + } + if (m2 != e.model2) + { + e.model2 = m2; + e.SendFlags |= 4; + } + if (m3 != e.model3) + { + e.model3 = m3; + e.SendFlags |= 8; + } +} + +void WaypointSprite_UpdateHealth(entity e, float f) +{ + f = bound(0, f, e.max_health); + if (f != e.health || e.pain_finished) + { + e.health = f; + e.pain_finished = 0; + e.SendFlags |= 0x80; + } +} + +void WaypointSprite_UpdateMaxHealth(entity e, float f) +{ + if (f != e.max_health || e.pain_finished) + { + e.max_health = f; + e.pain_finished = 0; + e.SendFlags |= 0x80; + } +} + +void WaypointSprite_UpdateBuildFinished(entity e, float f) +{ + if (f != e.pain_finished || e.max_health) + { + e.max_health = 0; + e.pain_finished = f; + e.SendFlags |= 0x80; + } +} + +void WaypointSprite_UpdateOrigin(entity e, vector o) +{ + if (o != e.origin) + { + setorigin(e, o); + e.SendFlags |= 64; + } +} + +void WaypointSprite_UpdateRule(entity e, float t, float r) +{ + // no check, as this is never called without doing an actual change (usually only once) + e.rule = r; + e.team = t; + e.SendFlags |= 1; +} + +void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col) +{ + // no check, as this is never called without doing an actual change (usually only once) + e.cnt = (icon & 0x7F) | (e.cnt & 0x80); + e.colormod = col; + e.SendFlags |= 32; +} + +void WaypointSprite_Ping(entity e) +{ + // anti spam + if (time < e.waypointsprite_pingtime) return; + e.waypointsprite_pingtime = time + 0.3; + // ALWAYS sends (this causes a radar circle), thus no check + e.cnt |= 0x80; + e.SendFlags |= 32; +} + +void WaypointSprite_HelpMePing(entity e) +{ + WaypointSprite_Ping(e); + e.waypointsprite_helpmetime = time + waypointsprite_deployed_lifetime; + e.SendFlags |= 32; +} + +void WaypointSprite_FadeOutIn(entity e, float t) +{ + if (!e.fade_time) + { + e.fade_time = t; + e.teleport_time = time + t; + } + else if (t < (e.teleport_time - time)) + { + // accelerate the waypoint's dying + // ensure: + // (e.teleport_time - time) / wp.fade_time stays + // e.teleport_time = time + fadetime + float current_fadetime; + current_fadetime = e.teleport_time - time; + e.teleport_time = time + t; + e.fade_time = e.fade_time * t / current_fadetime; + } + + e.SendFlags |= 16; +} + +void WaypointSprite_Init() +{ + waypointsprite_limitedrange = autocvar_sv_waypointsprite_limitedrange; + waypointsprite_deployed_lifetime = autocvar_sv_waypointsprite_deployed_lifetime; + waypointsprite_deadlifetime = autocvar_sv_waypointsprite_deadlifetime; +} + +void WaypointSprite_InitClient(entity e) +{ +} + +void WaypointSprite_Kill(entity wp) +{ + if (!wp) return; + if (wp.owner) wp.owner.(wp.owned_by_field) = world; + remove(wp); +} + +void WaypointSprite_Disown(entity wp, float fadetime) +{ + if (!wp) return; + if (wp.classname != "sprite_waypoint") + { + backtrace("Trying to disown a non-waypointsprite"); + return; + } + if (wp.owner) + { + if (wp.exteriormodeltoclient == wp.owner) + wp.exteriormodeltoclient = world; + wp.owner.(wp.owned_by_field) = world; + wp.owner = world; + + WaypointSprite_FadeOutIn(wp, fadetime); + } +} + +void WaypointSprite_Think() +{ + bool doremove = false; + + if (self.fade_time && time >= self.teleport_time) + { + doremove = true; + } + + if (self.exteriormodeltoclient) + WaypointSprite_UpdateOrigin(self, self.exteriormodeltoclient.origin + self.view_ofs); + + if (doremove) + WaypointSprite_Kill(self); + else + self.nextthink = time; // WHY?!? +} + +float WaypointSprite_visible_for_player(entity e) +{ + // personal waypoints + if (self.enemy && self.enemy != e) + return false; + + // team waypoints + if (self.rule == SPRITERULE_SPECTATOR) + { + if (!autocvar_sv_itemstime) + return false; + if (!warmup_stage && IS_PLAYER(e)) + return false; + } + else if (self.team && self.rule == SPRITERULE_DEFAULT) + { + if (self.team != e.team) + return false; + if (!IS_PLAYER(e)) + return false; + } + + return true; +} + +entity WaypointSprite_getviewentity(entity e) +{ + if (IS_SPEC(e)) e = e.enemy; + /* TODO idea (check this breaks nothing) + else if (e.classname == "observer") + e = world; + */ + return e; +} + +float WaypointSprite_isteammate(entity e, entity e2) +{ + if (teamplay) + return e2.team == e.team; + return e2 == e; +} + +float WaypointSprite_Customize() +{ + // this is not in SendEntity because it shall run every frame, not just every update + + // make spectators see what the player would see + entity e = WaypointSprite_getviewentity(other); + + if (MUTATOR_CALLHOOK(CustomizeWaypoint, self, other)) + return false; + + return self.waypointsprite_visible_for_player(e); +} + +float WaypointSprite_SendEntity(entity to, float sendflags); + +void WaypointSprite_Reset() +{ + // if a WP wants to time out, let it time out immediately; other WPs ought to be reset/killed by their owners + + if (self.fade_time) // there was there before: || g_keyhunt, do we really need this? + WaypointSprite_Kill(self); +} + +entity WaypointSprite_Spawn( + entity spr, // sprite + float _lifetime, float maxdistance, // lifetime, max distance + entity ref, vector ofs, // position + entity showto, float t, // show to whom? Use a flag to indicate a team + entity own, .entity ownfield, // remove when own gets killed + float hideable, // true when it should be controlled by cl_hidewaypoints + float icon // initial icon +) +{ + entity wp = new(sprite_waypoint); + wp.teleport_time = time + _lifetime; + wp.fade_time = _lifetime; + wp.exteriormodeltoclient = ref; + if (ref) + { + wp.view_ofs = ofs; + setorigin(wp, ref.origin + ofs); + } + else + setorigin(wp, ofs); + wp.enemy = showto; + wp.team = t; + wp.owner = own; + wp.currentammo = hideable; + if (own) + { + if (own.(ownfield)) + remove(own.(ownfield)); + own.(ownfield) = wp; + wp.owned_by_field = ownfield; + } + wp.fade_rate = maxdistance; + wp.think = WaypointSprite_Think; + wp.nextthink = time; + wp.model1 = spr.netname; + wp.customizeentityforclient = WaypointSprite_Customize; + wp.waypointsprite_visible_for_player = WaypointSprite_visible_for_player; + wp.reset2 = WaypointSprite_Reset; + wp.cnt = icon; + wp.colormod = spr.m_color; + Net_LinkEntity(wp, false, 0, WaypointSprite_SendEntity); + return wp; +} + +entity WaypointSprite_SpawnFixed( + entity spr, + vector ofs, + entity own, + .entity ownfield, + float icon // initial icon +) +{ + return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, own, ownfield, true, icon); +} + +entity WaypointSprite_DeployFixed( + entity spr, + float limited_range, + vector ofs, + float icon // initial icon +) +{ + float t; + if (teamplay) + t = self.team; + else + t = 0; + float maxdistance; + if (limited_range) + maxdistance = waypointsprite_limitedrange; + else + maxdistance = 0; + return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, world, ofs, world, t, self, waypointsprite_deployed_fixed, false, icon); +} + +entity WaypointSprite_DeployPersonal( + entity spr, + vector ofs, + float icon // initial icon +) +{ + return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, self, waypointsprite_deployed_personal, false, icon); +} + +entity WaypointSprite_Attach( + entity spr, + float limited_range, + float icon // initial icon +) +{ + float t; + if (self.waypointsprite_attachedforcarrier) + return world; // can't attach to FC + if (teamplay) + t = self.team; + else + t = 0; + float maxdistance; + if (limited_range) + maxdistance = waypointsprite_limitedrange; + else + maxdistance = 0; + return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, self, '0 0 64', world, t, self, waypointsprite_attached, false, icon); +} + +entity WaypointSprite_AttachCarrier( + entity spr, + entity carrier, + float icon // initial icon and color +) +{ + WaypointSprite_Kill(carrier.waypointsprite_attached); // FC overrides attached + entity e = WaypointSprite_Spawn(spr, 0, 0, carrier, '0 0 64', world, carrier.team, carrier, waypointsprite_attachedforcarrier, false, icon); + if (e) + { + WaypointSprite_UpdateMaxHealth(e, '1 0 0' * healtharmor_maxdamage(start_health, start_armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON) * 2); + WaypointSprite_UpdateHealth(e, '1 0 0' * healtharmor_maxdamage(carrier.health, carrier.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON)); + } + return e; +} + +void WaypointSprite_DetachCarrier(entity carrier) +{ + WaypointSprite_Disown(carrier.waypointsprite_attachedforcarrier, waypointsprite_deadlifetime); +} + +void WaypointSprite_ClearPersonal() +{ + WaypointSprite_Kill(self.waypointsprite_deployed_personal); +} + +void WaypointSprite_ClearOwned() +{ + WaypointSprite_Kill(self.waypointsprite_deployed_fixed); + WaypointSprite_Kill(self.waypointsprite_deployed_personal); + WaypointSprite_Kill(self.waypointsprite_attached); +} + +void WaypointSprite_PlayerDead() +{ + WaypointSprite_Disown(self.waypointsprite_attached, waypointsprite_deadlifetime); + WaypointSprite_DetachCarrier(self); +} + +void WaypointSprite_PlayerGone() +{ + WaypointSprite_Disown(self.waypointsprite_deployed_fixed, waypointsprite_deadlifetime); + WaypointSprite_Kill(self.waypointsprite_deployed_personal); + WaypointSprite_Disown(self.waypointsprite_attached, waypointsprite_deadlifetime); + WaypointSprite_DetachCarrier(self); +} +#endif diff --git a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh new file mode 100644 index 000000000..d6ea51867 --- /dev/null +++ b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh @@ -0,0 +1,236 @@ +#ifndef WAYPOINTSPRITES_H +#define WAYPOINTSPRITES_H + +#include "all.qh" + +/** Additional networked waypoint state, used for items, weapons, buffs */ +.int wp_extra; + +#ifdef CSQC +entityclass(WaypointSprite); +class(WaypointSprite) .float helpme; +class(WaypointSprite) .float rule; +class(WaypointSprite) .string netname; // primary picture +class(WaypointSprite) .string netname2; // secondary picture +class(WaypointSprite) .string netname3; // tertiary picture +class(WaypointSprite) .int team; // team that gets netname2 +class(WaypointSprite) .float lifetime; +class(WaypointSprite) .float fadetime; +class(WaypointSprite) .float maxdistance; +class(WaypointSprite) .int hideflags; +class(WaypointSprite) .float spawntime; +class(WaypointSprite) .float health; +class(WaypointSprite) .float build_started; +class(WaypointSprite) .float build_starthealth; +class(WaypointSprite) .float build_finished; + +bool autocvar_g_waypointsprite_uppercase; +float autocvar_g_waypointsprite_alpha; +float autocvar_g_waypointsprite_crosshairfadealpha; +float autocvar_g_waypointsprite_crosshairfadedistance; +float autocvar_g_waypointsprite_crosshairfadescale; +float autocvar_g_waypointsprite_distancealphaexponent; +float autocvar_g_waypointsprite_distancefadealpha; +float autocvar_g_waypointsprite_distancefadedistancemultiplier; +float autocvar_g_waypointsprite_distancefadescale; +float autocvar_g_waypointsprite_edgefadealpha; +float autocvar_g_waypointsprite_edgefadedistance; +float autocvar_g_waypointsprite_edgefadescale; +float autocvar_g_waypointsprite_edgeoffset_bottom; +float autocvar_g_waypointsprite_edgeoffset_left; +float autocvar_g_waypointsprite_edgeoffset_right; +float autocvar_g_waypointsprite_edgeoffset_top; +float autocvar_g_waypointsprite_fontsize; +int autocvar_g_waypointsprite_itemstime; +float autocvar_g_waypointsprite_minalpha; +float autocvar_g_waypointsprite_minscale; +float autocvar_g_waypointsprite_normdistance; +float autocvar_g_waypointsprite_scale; +int autocvar_g_waypointsprite_spam; +float autocvar_g_waypointsprite_timealphaexponent; +bool autocvar_g_waypointsprite_turrets = true; +float autocvar_g_waypointsprite_turrets_maxdist = 5000; + +float waypointsprite_fadedistance; +float waypointsprite_normdistance; +float waypointsprite_minscale; +float waypointsprite_minalpha; +float waypointsprite_distancealphaexponent; +float waypointsprite_timealphaexponent; +float waypointsprite_scale; +float waypointsprite_fontsize; +float waypointsprite_edgefadealpha; +float waypointsprite_edgefadescale; +float waypointsprite_edgefadedistance; +float waypointsprite_edgeoffset_bottom; +float waypointsprite_edgeoffset_left; +float waypointsprite_edgeoffset_right; +float waypointsprite_edgeoffset_top; +float waypointsprite_crosshairfadealpha; +float waypointsprite_crosshairfadescale; +float waypointsprite_crosshairfadedistance; +float waypointsprite_distancefadealpha; +float waypointsprite_distancefadescale; +float waypointsprite_distancefadedistance; +float waypointsprite_alpha; + +const float SPRITE_HEALTHBAR_WIDTH = 144; +const float SPRITE_HEALTHBAR_HEIGHT = 9; +const float SPRITE_HEALTHBAR_MARGIN = 6; +const float SPRITE_HEALTHBAR_BORDER = 2; +const float SPRITE_HEALTHBAR_BORDERALPHA = 1; +const float SPRITE_HEALTHBAR_HEALTHALPHA = 0.5; +const float SPRITE_ARROW_SCALE = 1.0; +const float SPRITE_HELPME_BLINK = 2; + +float waypointsprite_count, waypointsprite_newcount; + +void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f); + +void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f); + +void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float height, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f); + +// returns location of sprite text +vector drawspritearrow(vector o, float ang, vector rgb, float a, float t); + +// returns location of sprite healthbar +vector drawspritetext(vector o, float ang, float minwidth, vector rgb, float a, vector fontsize, string s); + +float spritelookupblinkvalue(string s); +vector spritelookupcolor(string s, vector def); +string spritelookuptext(string s); + +vector fixrgbexcess_move(vector rgb, vector src, vector dst); +vector fixrgbexcess(vector rgb); + +// they are drawn using a .draw function + +void Ent_RemoveWaypointSprite(); + +void Ent_WaypointSprite(); + +void WaypointSprite_Load_Frames(string ext); + +void WaypointSprite_Load(); +.float alpha; +void Draw_WaypointSprite(); +#endif + +#ifdef SVQC +float autocvar_sv_waypointsprite_deadlifetime; +float autocvar_sv_waypointsprite_deployed_lifetime; +float autocvar_sv_waypointsprite_limitedrange; + +..entity owned_by_field; +.float rule; +.string model1; +.string model2; +.string model3; + +.float(entity) waypointsprite_visible_for_player; + +void WaypointSprite_UpdateSprites(entity e, entity m1, entity m2, entity m3); + +void WaypointSprite_UpdateHealth(entity e, float f); + +void WaypointSprite_UpdateMaxHealth(entity e, float f); + +void WaypointSprite_UpdateBuildFinished(entity e, float f); + +void WaypointSprite_UpdateOrigin(entity e, vector o); + +void WaypointSprite_UpdateRule(entity e, float t, float r); + +void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col); + +.float waypointsprite_pingtime; +.float waypointsprite_helpmetime; +void WaypointSprite_Ping(entity e); + +float waypointsprite_limitedrange, waypointsprite_deployed_lifetime, waypointsprite_deadlifetime; + +void WaypointSprite_HelpMePing(entity e); + +void WaypointSprite_FadeOutIn(entity e, float t); + +void WaypointSprite_Init(); +void WaypointSprite_InitClient(entity e); + +void WaypointSprite_Kill(entity wp); + +void WaypointSprite_Disown(entity wp, float fadetime); + +void WaypointSprite_Think(); + +float WaypointSprite_visible_for_player(entity e); + +entity WaypointSprite_getviewentity(entity e); + +float WaypointSprite_isteammate(entity e, entity e2); + +float WaypointSprite_Customize(); + +float WaypointSprite_SendEntity(entity to, float sendflags); + +void WaypointSprite_Reset(); + +entity WaypointSprite_Spawn( + entity spr, // sprite + float lifetime, float maxdistance, // lifetime, max distance + entity ref, vector ofs, // position + entity showto, float t, // show to whom? Use a flag to indicate a team + entity own, .entity ownfield, // remove when own gets killed + float hideable, // true when it should be controlled by cl_hidewaypoints + float icon // initial icon +); + +entity WaypointSprite_SpawnFixed( + entity spr, + vector ofs, + entity own, + .entity ownfield, + float icon // initial icon +); + +.entity waypointsprite_deployed_fixed; +entity WaypointSprite_DeployFixed( + entity spr, + float limited_range, + vector ofs, + float icon // initial icon +); + +.entity waypointsprite_deployed_personal; +entity WaypointSprite_DeployPersonal( + entity spr, + vector ofs, + float icon // initial icon +); + +.entity waypointsprite_attached; +.entity waypointsprite_attachedforcarrier; +entity WaypointSprite_Attach( + entity spr, + float limited_range, + float icon // initial icon +); + +entity WaypointSprite_AttachCarrier( + entity spr, + entity carrier, + float icon // initial icon +); + +void WaypointSprite_DetachCarrier(entity carrier); + +void WaypointSprite_ClearPersonal(); + +void WaypointSprite_ClearOwned(); + +void WaypointSprite_PlayerDead(); + +void WaypointSprite_PlayerGone(); +#endif + +#endif diff --git a/qcsrc/common/mutators/mutator/waypointsprites.qc b/qcsrc/common/mutators/mutator/waypointsprites.qc deleted file mode 100644 index 18d00518e..000000000 --- a/qcsrc/common/mutators/mutator/waypointsprites.qc +++ /dev/null @@ -1,1209 +0,0 @@ -#include "waypointsprites.qh" - -REGISTER_MUTATOR(waypointsprites, true); - -#ifdef SVQC -/** flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable] */ -float WaypointSprite_SendEntity(entity to, float sendflags) -{ - WriteMutator(MSG_ENTITY, waypointsprites); - - sendflags = sendflags & 0x7F; - - if (g_nexball) - sendflags &= ~0x80; - else if (self.max_health || (self.pain_finished && (time < self.pain_finished + 0.25))) - sendflags |= 0x80; - - WriteByte(MSG_ENTITY, sendflags); - - if (sendflags & 0x80) - { - if (self.max_health) - { - WriteByte(MSG_ENTITY, (self.health / self.max_health) * 191.0); - } - else - { - float dt = self.pain_finished - time; - dt = bound(0, dt * 32, 16383); - WriteByte(MSG_ENTITY, (dt & 0xFF00) / 256 + 192); - WriteByte(MSG_ENTITY, (dt & 0x00FF)); - } - } - - if (sendflags & 64) - { - WriteCoord(MSG_ENTITY, self.origin.x); - WriteCoord(MSG_ENTITY, self.origin.y); - WriteCoord(MSG_ENTITY, self.origin.z); - } - - if (sendflags & 1) - { - WriteByte(MSG_ENTITY, self.team); - WriteByte(MSG_ENTITY, self.rule); - } - - if (sendflags & 2) - WriteString(MSG_ENTITY, self.model1); - - if (sendflags & 4) - WriteString(MSG_ENTITY, self.model2); - - if (sendflags & 8) - WriteString(MSG_ENTITY, self.model3); - - if (sendflags & 16) - { - WriteCoord(MSG_ENTITY, self.fade_time); - WriteCoord(MSG_ENTITY, self.teleport_time); - WriteShort(MSG_ENTITY, self.fade_rate); // maxdist - float f = 0; - if (self.currentammo) - f |= 1; // hideable - if (self.exteriormodeltoclient == to) - f |= 2; // my own - if (g_onslaught) - { - if (self.owner.classname == "onslaught_controlpoint") - { - entity wp_owner = self.owner; - entity e = WaypointSprite_getviewentity(to); - if (SAME_TEAM(e, wp_owner) && wp_owner.goalentity.health >= wp_owner.goalentity.max_health) { f |= 2; } - if (!ons_ControlPoint_Attackable(wp_owner, e.team)) { f |= 2; } - } - if (self.owner.classname == "onslaught_generator") - { - entity wp_owner = self.owner; - if (wp_owner.isshielded && wp_owner.health >= wp_owner.max_health) { f |= 2; } - if (wp_owner.health <= 0) { f |= 2; } - } - } - WriteByte(MSG_ENTITY, f); - } - - if (sendflags & 32) - { - WriteByte(MSG_ENTITY, self.cnt); // icon on radar - WriteByte(MSG_ENTITY, self.colormod.x * 255.0); - WriteByte(MSG_ENTITY, self.colormod.y * 255.0); - WriteByte(MSG_ENTITY, self.colormod.z * 255.0); - - if (WaypointSprite_isteammate(self.owner, WaypointSprite_getviewentity(to))) - { - float dt = (self.waypointsprite_helpmetime - time) / 0.1; - if (dt < 0) - dt = 0; - if (dt > 255) - dt = 255; - WriteByte(MSG_ENTITY, dt); - } - else - WriteByte(MSG_ENTITY, 0); - } - - return true; -} -#endif - -#ifdef CSQC -void Ent_WaypointSprite(); -MUTATOR_HOOKFUNCTION(waypointsprites, CSQC_Ent_Update) { - if (MUTATOR_RETURNVALUE) return false; - if (!ReadMutatorEquals(mutator_argv_int_0, waypointsprites)) return false; - Ent_WaypointSprite(); - return true; -} - -void Ent_RemoveWaypointSprite() -{ - if (self.netname) strunzone(self.netname); - if (self.netname2) strunzone(self.netname2); - if (self.netname3) strunzone(self.netname3); -} - -/** flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable] */ -void Ent_WaypointSprite() -{ - int sendflags = ReadByte(); - - if (!self.spawntime) - self.spawntime = time; - - self.draw2d = Draw_WaypointSprite; - - InterpolateOrigin_Undo(); - self.iflags |= IFLAG_ORIGIN; - - if (sendflags & 0x80) - { - int t = ReadByte(); - if (t < 192) - { - self.health = t / 191.0; - self.build_finished = 0; - } - else - { - t = (t - 192) * 256 + ReadByte(); - self.build_started = servertime; - if (self.build_finished) - self.build_starthealth = bound(0, self.health, 1); - else - self.build_starthealth = 0; - self.build_finished = servertime + t / 32; - } - } - else - { - self.health = -1; - self.build_finished = 0; - } - - if (sendflags & 64) - { - // unfortunately, this needs to be exact (for the 3D display) - self.origin_x = ReadCoord(); - self.origin_y = ReadCoord(); - self.origin_z = ReadCoord(); - setorigin(self, self.origin); - } - - if (sendflags & 1) - { - self.team = ReadByte(); - self.rule = ReadByte(); - } - - if (sendflags & 2) - { - if (self.netname) - strunzone(self.netname); - self.netname = strzone(ReadString()); - } - - if (sendflags & 4) - { - if (self.netname2) - strunzone(self.netname2); - self.netname2 = strzone(ReadString()); - } - - if (sendflags & 8) - { - if (self.netname3) - strunzone(self.netname3); - self.netname3 = strzone(ReadString()); - } - - if (sendflags & 16) - { - self.lifetime = ReadCoord(); - self.fadetime = ReadCoord(); - self.maxdistance = ReadShort(); - self.hideflags = ReadByte(); - } - - if (sendflags & 32) - { - int f = ReadByte(); - self.teamradar_icon = (f & 0x7F); - if (f & 0x80) - { - self.(teamradar_times[self.teamradar_time_index]) = time; - self.teamradar_time_index = (self.teamradar_time_index + 1) % MAX_TEAMRADAR_TIMES; - } - self.teamradar_color_x = ReadByte() / 255.0; - self.teamradar_color_y = ReadByte() / 255.0; - self.teamradar_color_z = ReadByte() / 255.0; - self.helpme = ReadByte() * 0.1; - if (self.helpme > 0) - self.helpme += servertime; - } - - InterpolateOrigin_Note(); - - self.entremove = Ent_RemoveWaypointSprite; -} -#endif - -#ifdef CSQC -float spritelookupblinkvalue(string s) -{ - if (substring(s, 0, 4) == "wpn-") - if (get_weaponinfo(stof(substring(s, 4, strlen(s)))).spawnflags & WEP_FLAG_SUPERWEAPON) - return 2; - - FOREACH(ITEMS, it.m_waypoint == s, LAMBDA( - return it.m_waypointblink; - )); - - switch (s) - { - case "ons-cp-atck": return 2; - case "ons-cp-dfnd": return 0.5; - case "item-invis": return 2; - case "item-extralife": return 2; - case "item-speed": return 2; - case "tagged-target": return 2; - default: return 1; - } -} - -vector spritelookupcolor(string s, vector def) -{ - if (substring(s, 0, 4) == "wpn-") - return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).wpcolor); - - switch (s) - { - case "keycarrier-friend": return '0 1 0'; - default: return def; - } -} - -string spritelookuptext(string s) -{ - if (substring(s, 0, 4) == "wpn-") { return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).message); } - if (substring(s, 0, 5) == "buff-") - { - entity buff = BUFF_NULL; - FOREACH(BUFFS, it.m_sprite == s, LAMBDA( - buff = it; - break; - )); - return buff.m_prettyName; - } - - 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 "enemyflagcarrier": return _("Enemy carrier"); - 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 "yellowbase": return _("Yellow base"); - case "neutralbase": return _("White base"); - case "pinkbase": return _("Pink base"); - case "waypoint": return _("Waypoint"); - case "ons-gen": return _("Generator"); - case "ons-gen-shielded": return _("Generator"); - case "ons-cp": return _("Control point"); - case "ons-cp-atck": return _("Control point"); - case "ons-cp-dfnd": return _("Control point"); - case "race-checkpoint": return _("Checkpoint"); - case "race-finish": return _("Finish"); - case "race-start": return _("Start"); - case "race-start-finish": return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start"); - case "goal": return _("Goal"); - case "nb-ball": return _("Ball"); - case "ka-ball": return _("Ball"); - case "ka-ballcarrier": return _("Ball carrier"); - 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 "frozen": return _("Frozen!"); - case "tagged-target": return _("Tagged"); - case "vehicle": return _("Vehicle"); - case "intruder": return _("Intruder!"); - default: return s; - } -} -#endif - -#ifdef CSQC -void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f) -{ - vector v1, v2, v3, v4; - - hotspot = -1 * hotspot; - - // hotspot-relative coordinates of the corners - v1 = hotspot; - v2 = hotspot + '1 0 0' * sz.x; - v3 = hotspot + '1 0 0' * sz.x + '0 1 0' * sz.y; - v4 = hotspot + '0 1 0' * sz.y; - - // rotate them, and make them absolute - rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed - v1 = rotate(v1, rot) + org; - v2 = rotate(v2, rot) + org; - v3 = rotate(v3, rot) + org; - v4 = rotate(v4, rot) + org; - - // draw them - R_BeginPolygon(pic, f); - R_PolygonVertex(v1, '0 0 0', rgb, a); - R_PolygonVertex(v2, '1 0 0', rgb, a); - R_PolygonVertex(v3, '1 1 0', rgb, a); - R_PolygonVertex(v4, '0 1 0', rgb, a); - R_EndPolygon(); -} - -void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f) -{ - R_BeginPolygon(pic, f); - R_PolygonVertex(o, '0 0 0', rgb, a); - R_PolygonVertex(o + ri, '1 0 0', rgb, a); - R_PolygonVertex(o + up + ri, '1 1 0', rgb, a); - R_PolygonVertex(o + up, '0 1 0', rgb, a); - R_EndPolygon(); -} - -void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float theheight, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f) -{ - vector o, ri, up; - float owidth; // outer width - - hotspot = -1 * hotspot; - - // hotspot-relative coordinates of the healthbar corners - o = hotspot; - ri = '1 0 0'; - up = '0 1 0'; - - rot = -rot; // rotate by the opposite angle, as our coordinate system is reversed - o = rotate(o, rot) + org; - ri = rotate(ri, rot); - up = rotate(up, rot); - - owidth = width + 2 * border; - o = o - up * (margin + border + theheight) + ri * (sz.x - owidth) * 0.5; - - drawquad(o - up * border, ri * owidth, up * border, "", rgb, a, f); - drawquad(o + up * theheight, ri * owidth, up * border, "", rgb, a, f); - drawquad(o, ri * border, up * theheight, "", rgb, a, f); - drawquad(o + ri * (owidth - border), ri * border, up * theheight, "", rgb, a, f); - drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * theheight, "", hrgb, ha, f); -} - -// returns location of sprite text -vector drawspritearrow(vector o, float ang, vector rgb, float a, float t) -{ - float size = 9.0 * t; - float border = 1.5 * t; - float margin = 4.0 * t; - - float borderDiag = border * 1.414; - vector arrowX = eX * size; - vector arrowY = eY * (size+borderDiag); - vector borderX = eX * (size+borderDiag); - vector borderY = eY * (size+borderDiag+border); - - R_BeginPolygon("", DRAWFLAG_NORMAL); - R_PolygonVertex(o, '0 0 0', '0 0 0', a); - R_PolygonVertex(o + rotate(arrowY - borderX, ang), '0 0 0', '0 0 0', a); - R_PolygonVertex(o + rotate(borderY - borderX, ang), '0 0 0', '0 0 0', a); - R_PolygonVertex(o + rotate(borderY + borderX, ang), '0 0 0', '0 0 0', a); - R_PolygonVertex(o + rotate(arrowY + borderX, ang), '0 0 0', '0 0 0', a); - R_EndPolygon(); - - R_BeginPolygon("", DRAWFLAG_ADDITIVE); - R_PolygonVertex(o + rotate(eY * borderDiag, ang), '0 0 0', rgb, a); - R_PolygonVertex(o + rotate(arrowY - arrowX, ang), '0 0 0', rgb, a); - R_PolygonVertex(o + rotate(arrowY + arrowX, ang), '0 0 0', rgb, a); - R_EndPolygon(); - - return o + rotate(eY * (borderDiag+size+margin), 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; -} - -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() -{ - if (self.lifetime) - self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent); - else - self.alpha = 1; - - if (self.hideflags & 2) - return; // radar only - - if (autocvar_cl_hidewaypoints >= 2) - return; - - if (self.hideflags & 1) - if (autocvar_cl_hidewaypoints) - return; // fixed waypoint - - InterpolateOrigin_Do(); - - float t = GetPlayerColor(player_localnum) + 1; - - string spriteimage = ""; - - // choose the sprite - switch (self.rule) - { - case SPRITERULE_SPECTATOR: - if (!( - (autocvar_g_waypointsprite_itemstime == 1 && t == NUM_SPECTATOR + 1) - || (autocvar_g_waypointsprite_itemstime == 2 && (t == NUM_SPECTATOR + 1 || warmup_stage)) - )) - return; - spriteimage = self.netname; - break; - case SPRITERULE_DEFAULT: - if (self.team) - { - if (self.team == t) - spriteimage = self.netname; - else - spriteimage = ""; - } - else - spriteimage = self.netname; - break; - case SPRITERULE_TEAMPLAY: - if (t == NUM_SPECTATOR + 1) - spriteimage = self.netname3; - else if (self.team == t) - spriteimage = self.netname2; - else - spriteimage = self.netname; - break; - default: - error("Invalid waypointsprite rule!"); - break; - } - - if (spriteimage == "") - return; - - ++waypointsprite_newcount; - - float dist; - dist = vlen(self.origin - view_origin); - - float a; - a = self.alpha * autocvar_hud_panel_fg_alpha; - - if (self.maxdistance > waypointsprite_normdistance) - a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent); - 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 = spritelookupcolor(spriteimage, self.teamradar_color); - if (rgb == '0 0 0') - { - self.teamradar_color = '1 0 1'; - printf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage); - } - - if (time - floor(time) > 0.5) - { - if (self.helpme && time < self.helpme) - a *= SPRITE_HELPME_BLINK; - else if (!self.lifetime) // fading out waypoints don't blink - a *= spritelookupblinkvalue(spriteimage); - } - - if (a > 1) - { - rgb *= a; - a = 1; - } - - if (a <= 0.003) - return; - - rgb = fixrgbexcess(rgb); - - vector o; - float ang; - - o = project_3d_to_2d(self.origin); - if (o.z < 0 - || o.x < (vid_conwidth * waypointsprite_edgeoffset_left) - || o.y < (vid_conheight * waypointsprite_edgeoffset_top) - || o.x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - || o.y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom))) - { - // scale it to be just in view - vector d; - float f1, f2; - - d = o - '0.5 0 0' * vid_conwidth - '0 0.5 0' * vid_conheight; - ang = atan2(-d.x, -d.y); - if (o.z < 0) - ang += M_PI; - - f1 = d.x / vid_conwidth; - f2 = d.y / vid_conheight; - - if (max(f1, -f1) > max(f2, -f2)) { - if (d.z * f1 > 0) { - // RIGHT edge - d = d * ((0.5 - waypointsprite_edgeoffset_right) / f1); - } else { - // LEFT edge - d = d * (-(0.5 - waypointsprite_edgeoffset_left) / f1); - } - } else { - if (d.z * f2 > 0) { - // BOTTOM edge - d = d * ((0.5 - waypointsprite_edgeoffset_bottom) / f2); - } else { - // TOP edge - d = d * (-(0.5 - waypointsprite_edgeoffset_top) / f2); - } - } - - o = d + '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight; - } - else - { -#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 = min((o.y - (vid_conheight * waypointsprite_edgeoffset_top)), - (o.x - (vid_conwidth * waypointsprite_edgeoffset_left)), - (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o.x, - (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o.y); - - float vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height); - - float crosshairdistance = sqrt( pow(o.x - vid_conwidth/2, 2) + pow(o.y - vid_conheight/2, 2) ); - - t = waypointsprite_scale * vidscale; - a *= waypointsprite_alpha; - - { - a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1))); - t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1))); - } - if (edgedistance_min < waypointsprite_edgefadedistance) { - a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1))); - t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1))); - } - if (crosshairdistance < waypointsprite_crosshairfadedistance) { - 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))); - } - - if (self.build_finished) - { - if (time < self.build_finished + 0.25) - { - if (time < self.build_started) - self.health = self.build_starthealth; - else if (time < self.build_finished) - self.health = (time - self.build_started) / (self.build_finished - self.build_started) * (1 - self.build_starthealth) + self.build_starthealth; - else - self.health = 1; - } - else - self.health = -1; - } - - o = drawspritearrow(o, ang, rgb, a, SPRITE_ARROW_SCALE * t); - - string txt; - if (autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam) - txt = _("Spam"); - else - txt = spritelookuptext(spriteimage); - if (self.helpme && time < self.helpme) - txt = sprintf(_("%s needing help!"), txt); - if (autocvar_g_waypointsprite_uppercase) - txt = strtoupper(txt); - - draw_beginBoldFont(); - if (self.health >= 0) - { - 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; - 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); - } - draw_endBoldFont(); -} - -void WaypointSprite_Load_Frames(string ext) -{ - int dh = search_begin(strcat("models/sprites/*_frame*", ext), false, false); - if (dh < 0) return; - int ext_len = strlen(ext); - int n = search_getsize(dh); - for (int i = 0; i < n; ++i) - { - string s = search_getfilename(dh, i); - s = substring(s, 15, strlen(s) - 15 - ext_len); // strip models/sprites/ and extension - - int o = strstrofs(s, "_frame", 0); - string sname = strcat("/spriteframes/", substring(s, 0, o)); - string sframes = substring(s, o + 6, strlen(s) - o - 6); - int f = stof(sframes) + 1; - db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname))))); - } - search_end(dh); -} - -void WaypointSprite_Load(); -STATIC_INIT(WaypointSprite_Load) { - WaypointSprite_Load(); - WaypointSprite_Load_Frames(".tga"); - WaypointSprite_Load_Frames(".jpg"); -} -void WaypointSprite_Load() -{ - 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_edgeoffset_bottom = autocvar_g_waypointsprite_edgeoffset_bottom; - waypointsprite_edgeoffset_left = autocvar_g_waypointsprite_edgeoffset_left; - waypointsprite_edgeoffset_right = autocvar_g_waypointsprite_edgeoffset_right; - waypointsprite_edgeoffset_top = autocvar_g_waypointsprite_edgeoffset_top; - 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); - - waypointsprite_count = waypointsprite_newcount; - waypointsprite_newcount = 0; -} -#endif - -#ifdef SVQC -void WaypointSprite_UpdateSprites(entity e, string m1, string m2, string m3) -{ - if (m1 != e.model1) - { - e.model1 = m1; - e.SendFlags |= 2; - } - if (m2 != e.model2) - { - e.model2 = m2; - e.SendFlags |= 4; - } - if (m3 != e.model3) - { - e.model3 = m3; - e.SendFlags |= 8; - } -} - -void WaypointSprite_UpdateHealth(entity e, float f) -{ - f = bound(0, f, e.max_health); - if (f != e.health || e.pain_finished) - { - e.health = f; - e.pain_finished = 0; - e.SendFlags |= 0x80; - } -} - -void WaypointSprite_UpdateMaxHealth(entity e, float f) -{ - if (f != e.max_health || e.pain_finished) - { - e.max_health = f; - e.pain_finished = 0; - e.SendFlags |= 0x80; - } -} - -void WaypointSprite_UpdateBuildFinished(entity e, float f) -{ - if (f != e.pain_finished || e.max_health) - { - e.max_health = 0; - e.pain_finished = f; - e.SendFlags |= 0x80; - } -} - -void WaypointSprite_UpdateOrigin(entity e, vector o) -{ - if (o != e.origin) - { - setorigin(e, o); - e.SendFlags |= 64; - } -} - -void WaypointSprite_UpdateRule(entity e, float t, float r) -{ - // no check, as this is never called without doing an actual change (usually only once) - e.rule = r; - e.team = t; - e.SendFlags |= 1; -} - -void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col) -{ - // no check, as this is never called without doing an actual change (usually only once) - e.cnt = (icon & 0x7F) | (e.cnt & 0x80); - e.colormod = col; - e.SendFlags |= 32; -} - -void WaypointSprite_Ping(entity e) -{ - // anti spam - if (time < e.waypointsprite_pingtime) return; - e.waypointsprite_pingtime = time + 0.3; - // ALWAYS sends (this causes a radar circle), thus no check - e.cnt |= 0x80; - e.SendFlags |= 32; -} - -void WaypointSprite_HelpMePing(entity e) -{ - WaypointSprite_Ping(e); - e.waypointsprite_helpmetime = time + waypointsprite_deployed_lifetime; - e.SendFlags |= 32; -} - -void WaypointSprite_FadeOutIn(entity e, float t) -{ - if (!e.fade_time) - { - e.fade_time = t; - e.teleport_time = time + t; - } - else if (t < (e.teleport_time - time)) - { - // accelerate the waypoint's dying - // ensure: - // (e.teleport_time - time) / wp.fade_time stays - // e.teleport_time = time + fadetime - float current_fadetime; - current_fadetime = e.teleport_time - time; - e.teleport_time = time + t; - e.fade_time = e.fade_time * t / current_fadetime; - } - - e.SendFlags |= 16; -} - -void WaypointSprite_Init() -{ - waypointsprite_limitedrange = autocvar_sv_waypointsprite_limitedrange; - waypointsprite_deployed_lifetime = autocvar_sv_waypointsprite_deployed_lifetime; - waypointsprite_deadlifetime = autocvar_sv_waypointsprite_deadlifetime; -} - -void WaypointSprite_InitClient(entity e) -{ -} - -void WaypointSprite_Kill(entity wp) -{ - if (!wp) return; - if (wp.owner) wp.owner.(wp.owned_by_field) = world; - remove(wp); -} - -void WaypointSprite_Disown(entity wp, float fadetime) -{ - if (!wp) return; - if (wp.classname != "sprite_waypoint") - { - backtrace("Trying to disown a non-waypointsprite"); - return; - } - if (wp.owner) - { - if (wp.exteriormodeltoclient == wp.owner) - wp.exteriormodeltoclient = world; - wp.owner.(wp.owned_by_field) = world; - wp.owner = world; - - WaypointSprite_FadeOutIn(wp, fadetime); - } -} - -void WaypointSprite_Think() -{ - bool doremove = false; - - if (self.fade_time && time >= self.teleport_time) - { - doremove = true; - } - - if (self.exteriormodeltoclient) - WaypointSprite_UpdateOrigin(self, self.exteriormodeltoclient.origin + self.view_ofs); - - if (doremove) - WaypointSprite_Kill(self); - else - self.nextthink = time; // WHY?!? -} - -float WaypointSprite_visible_for_player(entity e) -{ - // personal waypoints - if (self.enemy && self.enemy != e) - return false; - - // team waypoints - if (self.rule == SPRITERULE_SPECTATOR) - { - if (!autocvar_sv_itemstime) - return false; - if (!warmup_stage && IS_PLAYER(e)) - return false; - } - else if (self.team && self.rule == SPRITERULE_DEFAULT) - { - if (self.team != e.team) - return false; - if (!IS_PLAYER(e)) - return false; - } - - return true; -} - -entity WaypointSprite_getviewentity(entity e) -{ - if (IS_SPEC(e)) e = e.enemy; - /* TODO idea (check this breaks nothing) - else if (e.classname == "observer") - e = world; - */ - return e; -} - -float WaypointSprite_isteammate(entity e, entity e2) -{ - if (teamplay) - return e2.team == e.team; - return e2 == e; -} - -float WaypointSprite_Customize() -{ - // this is not in SendEntity because it shall run every frame, not just every update - - // make spectators see what the player would see - entity e = WaypointSprite_getviewentity(other); - - if (MUTATOR_CALLHOOK(CustomizeWaypoint, self, other)) - return false; - - return self.waypointsprite_visible_for_player(e); -} - -float WaypointSprite_SendEntity(entity to, float sendflags); - -void WaypointSprite_Reset() -{ - // if a WP wants to time out, let it time out immediately; other WPs ought to be reset/killed by their owners - - if (self.fade_time) // there was there before: || g_keyhunt, do we really need this? - WaypointSprite_Kill(self); -} - -entity WaypointSprite_Spawn( - string spr, // sprite - float _lifetime, float maxdistance, // lifetime, max distance - entity ref, vector ofs, // position - entity showto, float t, // show to whom? Use a flag to indicate a team - entity own, .entity ownfield, // remove when own gets killed - float hideable, // true when it should be controlled by cl_hidewaypoints - float icon, vector rgb // initial icon and color -) -{ - entity wp = new(sprite_waypoint); - wp.teleport_time = time + _lifetime; - wp.fade_time = _lifetime; - wp.exteriormodeltoclient = ref; - if (ref) - { - wp.view_ofs = ofs; - setorigin(wp, ref.origin + ofs); - } - else - setorigin(wp, ofs); - wp.enemy = showto; - wp.team = t; - wp.owner = own; - wp.currentammo = hideable; - if (own) - { - if (own.(ownfield)) - remove(own.(ownfield)); - own.(ownfield) = wp; - wp.owned_by_field = ownfield; - } - wp.fade_rate = maxdistance; - wp.think = WaypointSprite_Think; - wp.nextthink = time; - wp.model1 = spr; - wp.customizeentityforclient = WaypointSprite_Customize; - wp.waypointsprite_visible_for_player = WaypointSprite_visible_for_player; - wp.reset2 = WaypointSprite_Reset; - wp.cnt = icon; - wp.colormod = rgb; - Net_LinkEntity(wp, false, 0, WaypointSprite_SendEntity); - return wp; -} - -entity WaypointSprite_SpawnFixed( - string spr, - vector ofs, - entity own, - .entity ownfield, - float icon, vector rgb // initial icon and color -) -{ - return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, own, ownfield, true, icon, rgb); -} - -entity WaypointSprite_DeployFixed( - string spr, - float limited_range, - vector ofs, - float icon, vector rgb // initial icon and color -) -{ - float t; - if (teamplay) - t = self.team; - else - t = 0; - float maxdistance; - if (limited_range) - maxdistance = waypointsprite_limitedrange; - else - maxdistance = 0; - return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, world, ofs, world, t, self, waypointsprite_deployed_fixed, false, icon, rgb); -} - -entity WaypointSprite_DeployPersonal( - string spr, - vector ofs, - float icon, vector rgb // initial icon and color -) -{ - return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, self, waypointsprite_deployed_personal, false, icon, rgb); -} - -entity WaypointSprite_Attach( - string spr, - float limited_range, - float icon, vector rgb // initial icon and color -) -{ - float t; - if (self.waypointsprite_attachedforcarrier) - return world; // can't attach to FC - if (teamplay) - t = self.team; - else - t = 0; - float maxdistance; - if (limited_range) - maxdistance = waypointsprite_limitedrange; - else - maxdistance = 0; - return WaypointSprite_Spawn(spr, waypointsprite_deployed_lifetime, maxdistance, self, '0 0 64', world, t, self, waypointsprite_attached, false, icon, rgb); -} - -entity WaypointSprite_AttachCarrier( - string spr, - entity carrier, - float icon, vector rgb // initial icon and color -) -{ - WaypointSprite_Kill(carrier.waypointsprite_attached); // FC overrides attached - entity e = WaypointSprite_Spawn(spr, 0, 0, carrier, '0 0 64', world, carrier.team, carrier, waypointsprite_attachedforcarrier, false, icon, rgb); - if (e) - { - WaypointSprite_UpdateMaxHealth(e, '1 0 0' * healtharmor_maxdamage(start_health, start_armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON) * 2); - WaypointSprite_UpdateHealth(e, '1 0 0' * healtharmor_maxdamage(carrier.health, carrier.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON)); - } - return e; -} - -void WaypointSprite_DetachCarrier(entity carrier) -{ - WaypointSprite_Disown(carrier.waypointsprite_attachedforcarrier, waypointsprite_deadlifetime); -} - -void WaypointSprite_ClearPersonal() -{ - WaypointSprite_Kill(self.waypointsprite_deployed_personal); -} - -void WaypointSprite_ClearOwned() -{ - WaypointSprite_Kill(self.waypointsprite_deployed_fixed); - WaypointSprite_Kill(self.waypointsprite_deployed_personal); - WaypointSprite_Kill(self.waypointsprite_attached); -} - -void WaypointSprite_PlayerDead() -{ - WaypointSprite_Disown(self.waypointsprite_attached, waypointsprite_deadlifetime); - WaypointSprite_DetachCarrier(self); -} - -void WaypointSprite_PlayerGone() -{ - WaypointSprite_Disown(self.waypointsprite_deployed_fixed, waypointsprite_deadlifetime); - WaypointSprite_Kill(self.waypointsprite_deployed_personal); - WaypointSprite_Disown(self.waypointsprite_attached, waypointsprite_deadlifetime); - WaypointSprite_DetachCarrier(self); -} -#endif diff --git a/qcsrc/common/mutators/mutator/waypointsprites.qh b/qcsrc/common/mutators/mutator/waypointsprites.qh deleted file mode 100644 index 0c6cfadf5..000000000 --- a/qcsrc/common/mutators/mutator/waypointsprites.qh +++ /dev/null @@ -1,231 +0,0 @@ -#ifndef WAYPOINTSPRITES_H -#define WAYPOINTSPRITES_H - -#ifdef CSQC -entityclass(WaypointSprite); -class(WaypointSprite) .float helpme; -class(WaypointSprite) .float rule; -class(WaypointSprite) .string netname; // primary picture -class(WaypointSprite) .string netname2; // secondary picture -class(WaypointSprite) .string netname3; // tertiary picture -class(WaypointSprite) .int team; // team that gets netname2 -class(WaypointSprite) .float lifetime; -class(WaypointSprite) .float fadetime; -class(WaypointSprite) .float maxdistance; -class(WaypointSprite) .int hideflags; -class(WaypointSprite) .float spawntime; -class(WaypointSprite) .float health; -class(WaypointSprite) .float build_started; -class(WaypointSprite) .float build_starthealth; -class(WaypointSprite) .float build_finished; - -bool autocvar_g_waypointsprite_uppercase; -float autocvar_g_waypointsprite_alpha; -float autocvar_g_waypointsprite_crosshairfadealpha; -float autocvar_g_waypointsprite_crosshairfadedistance; -float autocvar_g_waypointsprite_crosshairfadescale; -float autocvar_g_waypointsprite_distancealphaexponent; -float autocvar_g_waypointsprite_distancefadealpha; -float autocvar_g_waypointsprite_distancefadedistancemultiplier; -float autocvar_g_waypointsprite_distancefadescale; -float autocvar_g_waypointsprite_edgefadealpha; -float autocvar_g_waypointsprite_edgefadedistance; -float autocvar_g_waypointsprite_edgefadescale; -float autocvar_g_waypointsprite_edgeoffset_bottom; -float autocvar_g_waypointsprite_edgeoffset_left; -float autocvar_g_waypointsprite_edgeoffset_right; -float autocvar_g_waypointsprite_edgeoffset_top; -float autocvar_g_waypointsprite_fontsize; -int autocvar_g_waypointsprite_itemstime; -float autocvar_g_waypointsprite_minalpha; -float autocvar_g_waypointsprite_minscale; -float autocvar_g_waypointsprite_normdistance; -float autocvar_g_waypointsprite_scale; -int autocvar_g_waypointsprite_spam; -float autocvar_g_waypointsprite_timealphaexponent; -bool autocvar_g_waypointsprite_turrets = true; -float autocvar_g_waypointsprite_turrets_maxdist = 5000; - -float waypointsprite_fadedistance; -float waypointsprite_normdistance; -float waypointsprite_minscale; -float waypointsprite_minalpha; -float waypointsprite_distancealphaexponent; -float waypointsprite_timealphaexponent; -float waypointsprite_scale; -float waypointsprite_fontsize; -float waypointsprite_edgefadealpha; -float waypointsprite_edgefadescale; -float waypointsprite_edgefadedistance; -float waypointsprite_edgeoffset_bottom; -float waypointsprite_edgeoffset_left; -float waypointsprite_edgeoffset_right; -float waypointsprite_edgeoffset_top; -float waypointsprite_crosshairfadealpha; -float waypointsprite_crosshairfadescale; -float waypointsprite_crosshairfadedistance; -float waypointsprite_distancefadealpha; -float waypointsprite_distancefadescale; -float waypointsprite_distancefadedistance; -float waypointsprite_alpha; - -const float SPRITE_HEALTHBAR_WIDTH = 144; -const float SPRITE_HEALTHBAR_HEIGHT = 9; -const float SPRITE_HEALTHBAR_MARGIN = 6; -const float SPRITE_HEALTHBAR_BORDER = 2; -const float SPRITE_HEALTHBAR_BORDERALPHA = 1; -const float SPRITE_HEALTHBAR_HEALTHALPHA = 0.5; -const float SPRITE_ARROW_SCALE = 1.0; -const float SPRITE_HELPME_BLINK = 2; - -float waypointsprite_count, waypointsprite_newcount; - -void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f); - -void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f); - -void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float height, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f); - -// returns location of sprite text -vector drawspritearrow(vector o, float ang, vector rgb, float a, float t); - -// returns location of sprite healthbar -vector drawspritetext(vector o, float ang, float minwidth, vector rgb, float a, vector fontsize, string s); - -float spritelookupblinkvalue(string s); -vector spritelookupcolor(string s, vector def); -string spritelookuptext(string s); - -vector fixrgbexcess_move(vector rgb, vector src, vector dst); -vector fixrgbexcess(vector rgb); - -// they are drawn using a .draw function - -void Ent_RemoveWaypointSprite(); - -void Ent_WaypointSprite(); - -void WaypointSprite_Load_Frames(string ext); - -void WaypointSprite_Load(); -.float alpha; -void Draw_WaypointSprite(); -#endif - -#ifdef SVQC -float autocvar_sv_waypointsprite_deadlifetime; -float autocvar_sv_waypointsprite_deployed_lifetime; -float autocvar_sv_waypointsprite_limitedrange; - -..entity owned_by_field; -.float rule; -.string model1; -.string model2; -.string model3; - -.float(entity) waypointsprite_visible_for_player; - -void WaypointSprite_UpdateSprites(entity e, string m1, string m2, string m3); - -void WaypointSprite_UpdateHealth(entity e, float f); - -void WaypointSprite_UpdateMaxHealth(entity e, float f); - -void WaypointSprite_UpdateBuildFinished(entity e, float f); - -void WaypointSprite_UpdateOrigin(entity e, vector o); - -void WaypointSprite_UpdateRule(entity e, float t, float r); - -void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col); - -.float waypointsprite_pingtime; -.float waypointsprite_helpmetime; -void WaypointSprite_Ping(entity e); - -float waypointsprite_limitedrange, waypointsprite_deployed_lifetime, waypointsprite_deadlifetime; - -void WaypointSprite_HelpMePing(entity e); - -void WaypointSprite_FadeOutIn(entity e, float t); - -void WaypointSprite_Init(); -void WaypointSprite_InitClient(entity e); - -void WaypointSprite_Kill(entity wp); - -void WaypointSprite_Disown(entity wp, float fadetime); - -void WaypointSprite_Think(); - -float WaypointSprite_visible_for_player(entity e); - -entity WaypointSprite_getviewentity(entity e); - -float WaypointSprite_isteammate(entity e, entity e2); - -float WaypointSprite_Customize(); - -float WaypointSprite_SendEntity(entity to, float sendflags); - -void WaypointSprite_Reset(); - -entity WaypointSprite_Spawn( - string spr, // sprite - float lifetime, float maxdistance, // lifetime, max distance - entity ref, vector ofs, // position - entity showto, float t, // show to whom? Use a flag to indicate a team - entity own, .entity ownfield, // remove when own gets killed - float hideable, // true when it should be controlled by cl_hidewaypoints - float icon, vector rgb // initial icon and color -); - -entity WaypointSprite_SpawnFixed( - string spr, - vector ofs, - entity own, - .entity ownfield, - float icon, vector rgb // initial icon and color -); - -.entity waypointsprite_deployed_fixed; -entity WaypointSprite_DeployFixed( - string spr, - float limited_range, - vector ofs, - float icon, vector rgb // initial icon and color -); - -.entity waypointsprite_deployed_personal; -entity WaypointSprite_DeployPersonal( - string spr, - vector ofs, - float icon, vector rgb // initial icon and color -); - -.entity waypointsprite_attached; -.entity waypointsprite_attachedforcarrier; -entity WaypointSprite_Attach( - string spr, - float limited_range, - float icon, vector rgb // initial icon and color -); - -entity WaypointSprite_AttachCarrier( - string spr, - entity carrier, - float icon, vector rgb // initial icon and color -); - -void WaypointSprite_DetachCarrier(entity carrier); - -void WaypointSprite_ClearPersonal(); - -void WaypointSprite_ClearOwned(); - -void WaypointSprite_PlayerDead(); - -void WaypointSprite_PlayerGone(); -#endif - -#endif diff --git a/qcsrc/common/vehicles/sv_vehicles.qc b/qcsrc/common/vehicles/sv_vehicles.qc index d4b1e1acf..17e1d7388 100644 --- a/qcsrc/common/vehicles/sv_vehicles.qc +++ b/qcsrc/common/vehicles/sv_vehicles.qc @@ -529,7 +529,8 @@ void vehicles_showwp() rgb = Team_ColorRGB(self.team); else rgb = '1 1 1'; - WaypointSprite_Spawn("vehicle", 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP, rgb); + entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP); + wp.colormod = rgb; if(self.waypointsprite_attached) { WaypointSprite_UpdateRule(self.waypointsprite_attached, self.wp00.team, SPRITERULE_DEFAULT); @@ -1023,8 +1024,10 @@ void vehicles_enter(entity pl, entity veh) Send_Notification(NOTIF_ONE, pl, MSG_CENTER, CENTER_VEHICLE_STEAL_SELF); - if(autocvar_g_vehicles_steal_show_waypoint) - WaypointSprite_Spawn("intruder", 0, 0, pl, '0 0 68', world, veh.team, veh, wps_intruder, true, RADARICON_DANGER, Team_ColorRGB(pl.team)); + if (autocvar_g_vehicles_steal_show_waypoint) { + entity wp = WaypointSprite_Spawn(WP_VehicleIntruder, 0, 0, pl, '0 0 68', world, veh.team, veh, wps_intruder, true, RADARICON_DANGER); + wp.colormod = Team_ColorRGB(pl.team); + } } else return; diff --git a/qcsrc/common/weapons/w_seeker.qc b/qcsrc/common/weapons/w_seeker.qc index 313d5defd..13687eeb0 100644 --- a/qcsrc/common/weapons/w_seeker.qc +++ b/qcsrc/common/weapons/w_seeker.qc @@ -546,7 +546,7 @@ void W_Seeker_Tag_Touch(void) if(WEP_CVAR(seeker, type) == 1) { - WaypointSprite_Spawn("tagged-target", WEP_CVAR(seeker, tag_tracker_lifetime), 0, other, '0 0 64', self.realowner, 0, other, wps_tag_tracker, true, RADARICON_TAGGED, '0.5 1 0'); + WaypointSprite_Spawn(WP_Seeker, WEP_CVAR(seeker, tag_tracker_lifetime), 0, other, '0 0 64', self.realowner, 0, other, wps_tag_tracker, true, RADARICON_TAGGED); WaypointSprite_UpdateRule(other.wps_tag_tracker, 0, SPRITERULE_DEFAULT); } } diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index 8caae09dd..8460cb38a 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -33,7 +33,7 @@ #include "../common/items/all.qc" -#include "../common/mutators/mutator/waypointsprites.qh" +#include "../common/mutators/mutator/waypoints/all.qh" #include "../common/triggers/subs.qh" #include "../common/triggers/triggers.qh" diff --git a/qcsrc/server/cl_impulse.qc b/qcsrc/server/cl_impulse.qc index 692b0c269..61c8d49aa 100644 --- a/qcsrc/server/cl_impulse.qc +++ b/qcsrc/server/cl_impulse.qc @@ -167,14 +167,14 @@ void ImpulseCommands (void) switch(imp) { case 30: - wp = WaypointSprite_DeployPersonal("waypoint", self.origin, RADARICON_WAYPOINT, '0 1 1'); + wp = WaypointSprite_DeployPersonal(WP_Waypoint, self.origin, RADARICON_WAYPOINT); if(wp) WaypointSprite_Ping(wp); sprint(self, "personal waypoint spawned at location\n"); break; case 31: WarpZone_crosshair_trace(self); - wp = WaypointSprite_DeployPersonal("waypoint", trace_endpos, RADARICON_WAYPOINT, '0 1 1'); + wp = WaypointSprite_DeployPersonal(WP_Waypoint, trace_endpos, RADARICON_WAYPOINT); if(wp) WaypointSprite_Ping(wp); sprint(self, "personal waypoint spawned at crosshair\n"); @@ -182,7 +182,7 @@ void ImpulseCommands (void) case 32: if(vlen(self.death_origin)) { - wp = WaypointSprite_DeployPersonal("waypoint", self.death_origin, RADARICON_WAYPOINT, '0 1 1'); + wp = WaypointSprite_DeployPersonal(WP_Waypoint, self.death_origin, RADARICON_WAYPOINT); if(wp) WaypointSprite_Ping(wp); sprint(self, "personal waypoint spawned at death location\n"); @@ -193,7 +193,7 @@ void ImpulseCommands (void) { if (!MUTATOR_CALLHOOK(HelpMePing, self)) { - wp = WaypointSprite_Attach("helpme", true, RADARICON_HELPME, '1 0.5 0'); + wp = WaypointSprite_Attach(WP_Helpme, true, RADARICON_HELPME); if(!wp) WaypointSprite_HelpMePing(self.waypointsprite_attachedforcarrier); else @@ -203,14 +203,14 @@ void ImpulseCommands (void) } break; case 34: - wp = WaypointSprite_DeployFixed("here", false, self.origin, RADARICON_HERE, '0 1 0'); + wp = WaypointSprite_DeployFixed(WP_Here, false, self.origin, RADARICON_HERE); if(wp) WaypointSprite_Ping(wp); sprint(self, "HERE spawned at location\n"); break; case 35: WarpZone_crosshair_trace(self); - wp = WaypointSprite_DeployFixed("here", false, trace_endpos, RADARICON_HERE, '0 1 0'); + wp = WaypointSprite_DeployFixed(WP_Here, false, trace_endpos, RADARICON_HERE); if(wp) WaypointSprite_Ping(wp); sprint(self, "HERE spawned at crosshair\n"); @@ -218,21 +218,21 @@ void ImpulseCommands (void) case 36: if(vlen(self.death_origin)) { - wp = WaypointSprite_DeployFixed("here", false, self.death_origin, RADARICON_HERE, '0 1 0'); + wp = WaypointSprite_DeployFixed(WP_Here, false, self.death_origin, RADARICON_HERE); if(wp) WaypointSprite_Ping(wp); sprint(self, "HERE spawned at death location\n"); } break; case 37: - wp = WaypointSprite_DeployFixed("danger", false, self.origin, RADARICON_DANGER, '1 0.5 0'); + wp = WaypointSprite_DeployFixed(WP_Danger, false, self.origin, RADARICON_DANGER); if(wp) WaypointSprite_Ping(wp); sprint(self, "DANGER spawned at location\n"); break; case 38: WarpZone_crosshair_trace(self); - wp = WaypointSprite_DeployFixed("danger", false, trace_endpos, RADARICON_DANGER, '1 0.5 0'); + wp = WaypointSprite_DeployFixed(WP_Danger, false, trace_endpos, RADARICON_DANGER); if(wp) WaypointSprite_Ping(wp); sprint(self, "DANGER spawned at crosshair\n"); @@ -240,7 +240,7 @@ void ImpulseCommands (void) case 39: if(vlen(self.death_origin)) { - wp = WaypointSprite_DeployFixed("danger", false, self.death_origin, RADARICON_DANGER, '1 0.5 0'); + wp = WaypointSprite_DeployFixed(WP_Danger, false, self.death_origin, RADARICON_DANGER); if(wp) WaypointSprite_Ping(wp); sprint(self, "DANGER spawned at death location\n"); diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc index 238040406..967a475e1 100644 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@ -594,7 +594,7 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo // add waypoint if(show_waypoint) - WaypointSprite_Spawn("frozen", 0, 0, targ, '0 0 64', world, targ.team, targ, waypointsprite_attached, true, RADARICON_WAYPOINT, '0.25 0.90 1'); + WaypointSprite_Spawn(WP_Frozen, 0, 0, targ, '0 0 64', world, targ.team, targ, waypointsprite_attached, true, RADARICON_WAYPOINT); } void Unfreeze (entity targ) diff --git a/qcsrc/server/mutators/gamemode_assault.qc b/qcsrc/server/mutators/gamemode_assault.qc index 4700c57d8..6364b7dad 100644 --- a/qcsrc/server/mutators/gamemode_assault.qc +++ b/qcsrc/server/mutators/gamemode_assault.qc @@ -131,20 +131,20 @@ void target_objective_decrease_activate() ent.sprite = world; } - spr = WaypointSprite_SpawnFixed("", 0.5 * (ent.absmin + ent.absmax), ent, assault_sprite, RADARICON_OBJECTIVE, '1 0.5 0'); + spr = WaypointSprite_SpawnFixed(WP_Assault, 0.5 * (ent.absmin + ent.absmax), ent, assault_sprite, RADARICON_OBJECTIVE); spr.assault_decreaser = self; spr.waypointsprite_visible_for_player = assault_decreaser_sprite_visible; spr.classname = "sprite_waypoint"; WaypointSprite_UpdateRule(spr, assault_attacker_team, SPRITERULE_TEAMPLAY); if(ent.classname == "func_assault_destructible") { - WaypointSprite_UpdateSprites(spr, "as-defend", "as-destroy", "as-destroy"); + WaypointSprite_UpdateSprites(spr, WP_AssaultDefend, WP_AssaultDestroy, WP_AssaultDestroy); WaypointSprite_UpdateMaxHealth(spr, ent.max_health); WaypointSprite_UpdateHealth(spr, ent.health); ent.sprite = spr; } else - WaypointSprite_UpdateSprites(spr, "as-defend", "as-push", "as-push"); + WaypointSprite_UpdateSprites(spr, WP_AssaultDefend, WP_AssaultPush, WP_AssaultPush); } } diff --git a/qcsrc/server/mutators/gamemode_ctf.qc b/qcsrc/server/mutators/gamemode_ctf.qc index 87bbb3b99..6ebf651f2 100644 --- a/qcsrc/server/mutators/gamemode_ctf.qc +++ b/qcsrc/server/mutators/gamemode_ctf.qc @@ -53,7 +53,7 @@ void ctf_CaptureRecord(entity flag, entity player) void ctf_FlagcarrierWaypoints(entity player) { - WaypointSprite_Spawn("flagcarrier", 0, 0, player, FLAG_WAYPOINT_OFFSET, world, player.team, player, wps_flagcarrier, true, RADARICON_FLAG, WPCOLOR_FLAGCARRIER(player.team)); + WaypointSprite_Spawn(WP_FlagCarrier, 0, 0, player, FLAG_WAYPOINT_OFFSET, world, player.team, player, wps_flagcarrier, true, RADARICON_FLAG); WaypointSprite_UpdateMaxHealth(player.wps_flagcarrier, '1 0 0' * healtharmor_maxdamage(start_health, start_armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON) * 2); WaypointSprite_UpdateHealth(player.wps_flagcarrier, '1 0 0' * healtharmor_maxdamage(player.health, player.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON)); WaypointSprite_UpdateTeamRadar(player.wps_flagcarrier, RADARICON_FLAGCARRIER, WPCOLOR_FLAGCARRIER(player.team)); @@ -248,8 +248,10 @@ void ctf_Handle_Drop(entity flag, entity player, int droptype) PlayerScore_Add(player, SP_CTF_DROPS, 1); // waypoints - if(autocvar_g_ctf_flag_dropped_waypoint) - WaypointSprite_Spawn("flagdropped", 0, 0, flag, FLAG_WAYPOINT_OFFSET, world, ((autocvar_g_ctf_flag_dropped_waypoint == 2) ? 0 : player.team), flag, wps_flagdropped, true, RADARICON_FLAG, WPCOLOR_DROPPEDFLAG(flag.team)); + if(autocvar_g_ctf_flag_dropped_waypoint) { + entity wp = WaypointSprite_Spawn(WP_FlagDropped, 0, 0, flag, FLAG_WAYPOINT_OFFSET, world, ((autocvar_g_ctf_flag_dropped_waypoint == 2) ? 0 : player.team), flag, wps_flagdropped, true, RADARICON_FLAG); + wp.colormod = WPCOLOR_DROPPEDFLAG(flag.team); + } if(autocvar_g_ctf_flag_return_time || (autocvar_g_ctf_flag_return_damage && autocvar_g_ctf_flag_health)) { @@ -712,7 +714,8 @@ void ctf_CheckStalemate(void) { if((tmp_entity.owner) && (!tmp_entity.owner.wps_enemyflagcarrier)) { - WaypointSprite_Spawn(((ctf_oneflag) ? "flagcarrier" : "enemyflagcarrier"), 0, 0, tmp_entity.owner, FLAG_WAYPOINT_OFFSET, world, 0, tmp_entity.owner, wps_enemyflagcarrier, true, RADARICON_FLAG, WPCOLOR_ENEMYFC(tmp_entity.owner.team)); + entity wp = WaypointSprite_Spawn(((ctf_oneflag) ? WP_FlagCarrier : WP_FlagCarrierEnemy), 0, 0, tmp_entity.owner, FLAG_WAYPOINT_OFFSET, world, 0, tmp_entity.owner, wps_enemyflagcarrier, true, RADARICON_FLAG); + wp.colormod = WPCOLOR_ENEMYFC(tmp_entity.owner.team); tmp_entity.owner.wps_enemyflagcarrier.customizeentityforclient = ctf_Stalemate_Customize; } } @@ -1063,18 +1066,18 @@ void ctf_DelayedFlagSetup(void) // called after a flag is placed on a map by ctf self.bot_basewaypoint = self.nearestwaypoint; // waypointsprites - string basename = "base"; - - switch(self.team) + entity basename; + switch (self.team) { - case NUM_TEAM_1: basename = "redbase"; break; - case NUM_TEAM_2: basename = "bluebase"; break; - case NUM_TEAM_3: basename = "yellowbase"; break; - case NUM_TEAM_4: basename = "pinkbase"; break; - default: basename = "neutralbase"; break; + case NUM_TEAM_1: basename = WP_FlagBaseRed; break; + case NUM_TEAM_2: basename = WP_FlagBaseBlue; break; + case NUM_TEAM_3: basename = WP_FlagBaseYellow; break; + case NUM_TEAM_4: basename = WP_FlagBasePink; break; + default: basename = WP_FlagBaseNeutral; break; } - WaypointSprite_SpawnFixed(basename, self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG, ((self.team) ? Team_ColorRGB(self.team) : '1 1 1')); + entity wp = WaypointSprite_SpawnFixed(basename, self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG); + wp.colormod = ((self.team) ? Team_ColorRGB(self.team) : '1 1 1'); WaypointSprite_UpdateTeamRadar(self.wps_flagbase, RADARICON_FLAG, ((self.team) ? colormapPaletteColor(self.team - 1, false) : '1 1 1')); // captureshield setup @@ -2126,7 +2129,7 @@ MUTATOR_HOOKFUNCTION(ctf_HelpMePing) } else // create a normal help me waypointsprite { - WaypointSprite_Spawn("helpme", waypointsprite_deployed_lifetime, waypointsprite_limitedrange, self, FLAG_WAYPOINT_OFFSET, world, self.team, self, wps_helpme, false, RADARICON_HELPME, '1 0.5 0'); + WaypointSprite_Spawn(WP_Helpme, waypointsprite_deployed_lifetime, waypointsprite_limitedrange, self, FLAG_WAYPOINT_OFFSET, world, self.team, self, wps_helpme, false, RADARICON_HELPME); WaypointSprite_Ping(self.wps_helpme); } diff --git a/qcsrc/server/mutators/gamemode_ctf.qh b/qcsrc/server/mutators/gamemode_ctf.qh index a9e83a2a5..b5ff1774a 100644 --- a/qcsrc/server/mutators/gamemode_ctf.qh +++ b/qcsrc/server/mutators/gamemode_ctf.qh @@ -37,7 +37,7 @@ const float VEHICLE_FLAG_SCALE = 1.0; // waypoint colors #define WPCOLOR_ENEMYFC(t) ((t) ? colormapPaletteColor(t - 1, false) * 0.75 : '1 1 1') -#define WPCOLOR_FLAGCARRIER(t) ('0.8 0.8 0') +#define WPCOLOR_FLAGCARRIER(t) (WP_FlagCarrier.m_color) #define WPCOLOR_DROPPEDFLAG(t) ((t) ? ('0.25 0.25 0.25' + colormapPaletteColor(t - 1, false)) * 0.5 : '1 1 1') // sounds diff --git a/qcsrc/server/mutators/gamemode_domination.qc b/qcsrc/server/mutators/gamemode_domination.qc index c365eddd3..d10cedcd8 100644 --- a/qcsrc/server/mutators/gamemode_domination.qc +++ b/qcsrc/server/mutators/gamemode_domination.qc @@ -24,7 +24,6 @@ void dompoint_captured () { entity head; float old_delay, old_team, real_team; - string msg = "dom-neut"; // now that the delay has expired, switch to the latest team to lay claim to this point head = self.owner; @@ -80,15 +79,16 @@ void dompoint_captured () self.delay = old_delay; self.team = old_team; + entity msg = WP_DomNeut; switch(self.team) { - case NUM_TEAM_1: msg = "dom-red"; break; - case NUM_TEAM_2: msg = "dom-blue"; break; - case NUM_TEAM_3: msg = "dom-yellow"; break; - case NUM_TEAM_4: msg = "dom-pink"; break; + case NUM_TEAM_1: msg = WP_DomRed; break; + case NUM_TEAM_2: msg = WP_DomBlue; break; + case NUM_TEAM_3: msg = WP_DomYellow; break; + case NUM_TEAM_4: msg = WP_DomPink; break; } - WaypointSprite_UpdateSprites(self.sprite, msg, "", ""); + WaypointSprite_UpdateSprites(self.sprite, msg, WP_Null, WP_Null); total_pps = 0, pps_red = 0, pps_blue = 0, pps_yellow = 0, pps_pink = 0; for(head = world; (head = find(head, classname, "dom_controlpoint")) != world; ) @@ -226,7 +226,7 @@ void dompointtouch() if(head == world) return; - WaypointSprite_UpdateSprites(self.sprite, "dom-neut", "", ""); + WaypointSprite_UpdateSprites(self.sprite, WP_DomNeut, WP_Null, WP_Null); WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, '0 1 1'); WaypointSprite_Ping(self.sprite); @@ -292,7 +292,7 @@ void dom_controlpoint_setup() droptofloor(); waypoint_spawnforitem(self); - WaypointSprite_SpawnFixed("dom-neut", self.origin + '0 0 32', self, sprite, RADARICON_DOMPOINT, '0 1 1'); + WaypointSprite_SpawnFixed(WP_DomNeut, self.origin + '0 0 32', self, sprite, RADARICON_DOMPOINT); } float total_controlpoints, redowned, blueowned, yellowowned, pinkowned; diff --git a/qcsrc/server/mutators/gamemode_keepaway.qc b/qcsrc/server/mutators/gamemode_keepaway.qc index 8cc302486..01695f5e2 100644 --- a/qcsrc/server/mutators/gamemode_keepaway.qc +++ b/qcsrc/server/mutators/gamemode_keepaway.qc @@ -50,7 +50,7 @@ void ka_RespawnBall() // runs whenever the ball needs to be relocated Send_Effect("electro_combo", oldballorigin, '0 0 0', 1); Send_Effect("electro_combo", self.origin, '0 0 0', 1); - WaypointSprite_Spawn("ka-ball", 0, 0, self, '0 0 64', world, self.team, self, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER, '0 1 1'); + WaypointSprite_Spawn(WP_KaBall, 0, 0, self, '0 0 64', world, self.team, self, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER); WaypointSprite_Ping(self.waypointsprite_attachedforcarrier); sound(self, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere) @@ -118,7 +118,7 @@ void ka_TouchEvent() // runs any time that the ball comes in contact with someth PlayerScore_Add(other, SP_KEEPAWAY_PICKUPS, 1); // waypoints - WaypointSprite_AttachCarrier("ka-ballcarrier", other, RADARICON_FLAGCARRIER, '1 0 0'); + WaypointSprite_AttachCarrier(WP_KaBallCarrier, other, RADARICON_FLAGCARRIER); other.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = ka_ballcarrier_waypointsprite_visible_for_player; WaypointSprite_UpdateRule(other.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT); WaypointSprite_Ping(other.waypointsprite_attachedforcarrier); @@ -160,7 +160,7 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los // PlayerScore_Add(plyr, SP_KEEPAWAY_DROPS, 1); Not anymore, this is 100% the same as pickups and is useless. // waypoints - WaypointSprite_Spawn("ka-ball", 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER, '0 1 1'); + WaypointSprite_Spawn(WP_KaBall, 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER); WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT); WaypointSprite_Ping(ball.waypointsprite_attachedforcarrier); WaypointSprite_Kill(plyr.waypointsprite_attachedforcarrier); diff --git a/qcsrc/server/mutators/gamemode_keyhunt.qc b/qcsrc/server/mutators/gamemode_keyhunt.qc index 5fa2f6db2..1de67e2b0 100644 --- a/qcsrc/server/mutators/gamemode_keyhunt.qc +++ b/qcsrc/server/mutators/gamemode_keyhunt.qc @@ -351,17 +351,18 @@ void kh_Key_AssignTo(entity key, entity player) // runs every time a key is pic if(key.kh_next == world) { // player is now a key carrier - WaypointSprite_AttachCarrier("", player, RADARICON_FLAGCARRIER, colormapPaletteColor(player.team - 1, 0)); + entity wp = WaypointSprite_AttachCarrier(WP_Null, player, RADARICON_FLAGCARRIER); + wp.colormod = colormapPaletteColor(player.team - 1, 0); player.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_KeyCarrier_waypointsprite_visible_for_player; WaypointSprite_UpdateRule(player.waypointsprite_attachedforcarrier, player.team, SPRITERULE_TEAMPLAY); if(player.team == NUM_TEAM_1) - WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-red", "keycarrier-friend", "keycarrier-red"); + WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, WP_KeyCarrierRed, WP_KeyCarrierFriend, WP_KeyCarrierRed); else if(player.team == NUM_TEAM_2) - WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-blue", "keycarrier-friend", "keycarrier-blue"); + WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, WP_KeyCarrierBlue, WP_KeyCarrierFriend, WP_KeyCarrierBlue); else if(player.team == NUM_TEAM_3) - WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-yellow", "keycarrier-friend", "keycarrier-yellow"); + WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, WP_KeyCarrierYellow, WP_KeyCarrierFriend, WP_KeyCarrierYellow); else if(player.team == NUM_TEAM_4) - WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-pink", "keycarrier-friend", "keycarrier-pink"); + WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, WP_KeyCarrierPink, WP_KeyCarrierFriend, WP_KeyCarrierPink); if(!kh_no_radar_circles) WaypointSprite_Ping(player.waypointsprite_attachedforcarrier); } @@ -383,8 +384,12 @@ void kh_Key_AssignTo(entity key, entity player) // runs every time a key is pic // audit all key carrier sprites, update them to RUN HERE FOR_EACH_KH_KEY(k) { - if(k.owner) - WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model1, "keycarrier-finish", k.owner.waypointsprite_attachedforcarrier.model3); + if (!k.owner) continue; + entity first = WP_Null; + FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break)); + entity third = WP_Null; + FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break)); + WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, first, WP_KeyCarrierFinish, third); } } else @@ -394,8 +399,12 @@ void kh_Key_AssignTo(entity key, entity player) // runs every time a key is pic // audit all key carrier sprites, update them to RUN HERE FOR_EACH_KH_KEY(k) { - if(k.owner) - WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model1, "keycarrier-friend", k.owner.waypointsprite_attachedforcarrier.model3); + if (!k.owner) continue; + entity first = WP_Null; + FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break)); + entity third = WP_Null; + FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break)); + WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, first, WP_KeyCarrierFriend, third); } } } @@ -773,7 +782,7 @@ void kh_Key_Spawn(entity initial_owner, float angle, float i) // runs every tim Send_Notification(NOTIF_ONE, initial_owner, MSG_CENTER, APP_TEAM_NUM_4(initial_owner.team, CENTER_KEYHUNT_START_)); - WaypointSprite_Spawn("key-dropped", 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, false, RADARICON_FLAG, '0 1 1'); + WaypointSprite_Spawn(WP_KeyDropped, 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, false, RADARICON_FLAG); key.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_Key_waypointsprite_visible_for_player; kh_Key_AssignTo(key, initial_owner); diff --git a/qcsrc/server/mutators/gamemode_nexball.qc b/qcsrc/server/mutators/gamemode_nexball.qc index a22a17110..91ed4ef9c 100644 --- a/qcsrc/server/mutators/gamemode_nexball.qc +++ b/qcsrc/server/mutators/gamemode_nexball.qc @@ -144,7 +144,7 @@ void GiveBall(entity plyr, entity ball) ball.effects |= EF_NOSHADOW; ball.scale = 1; // scale down. - WaypointSprite_AttachCarrier("nb-ball", plyr, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); + WaypointSprite_AttachCarrier(WP_NbBall, plyr, RADARICON_FLAGCARRIER); WaypointSprite_UpdateRule(plyr.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT); if(autocvar_g_nexball_basketball_delay_hold) @@ -188,7 +188,7 @@ void DropBall(entity ball, vector org, vector vel) } WaypointSprite_Kill(ball.owner.waypointsprite_attachedforcarrier); - WaypointSprite_Spawn("nb-ball", 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); // no health bar please + WaypointSprite_Spawn(WP_NbBall, 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER); // no health bar please WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT); ball.owner.ballcarried = world; @@ -530,7 +530,7 @@ void SpawnBall(void) precache_sound(self.noise1); precache_sound(self.noise2); - WaypointSprite_AttachCarrier("nb-ball", self, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); // the ball's team is not set yet, no rule update needed + WaypointSprite_AttachCarrier(WP_NbBall, self, RADARICON_FLAGCARRIER); // the ball's team is not set yet, no rule update needed self.reset = ball_restart; self.think = InitBall; @@ -589,7 +589,8 @@ void SpawnGoal(void) if(self.team != GOAL_OUT && Team_TeamToNumber(self.team) != -1) { - WaypointSprite_SpawnFixed("goal", (self.absmin + self.absmax) * 0.5, self, sprite, RADARICON_NONE, ((self.team) ? Team_ColorRGB(self.team) : '1 0.5 0')); + entity wp = WaypointSprite_SpawnFixed(WP_NbGoal, (self.absmin + self.absmax) * 0.5, self, sprite, RADARICON_NONE); + wp.colormod = ((self.team) ? Team_ColorRGB(self.team) : '1 0.5 0'); self.sprite.customizeentityforclient = nb_Goal_Customize; } diff --git a/qcsrc/server/mutators/gamemode_nexball.qh b/qcsrc/server/mutators/gamemode_nexball.qh index 199e15c3b..e28fad883 100644 --- a/qcsrc/server/mutators/gamemode_nexball.qh +++ b/qcsrc/server/mutators/gamemode_nexball.qh @@ -6,7 +6,6 @@ const float BALL_EFFECTMASK = 1229; const vector BALL_MINS = '-16 -16 -16'; // The model is 24*24*24 const vector BALL_MAXS = '16 16 16'; const vector BALL_ATTACHORG = '3 0 16'; -const vector BALL_SPRITECOLOR = '0.91 0.85 0.62'; const float BALL_FOOT = 1; const float BALL_BASKET = 2; //spawnflags diff --git a/qcsrc/server/mutators/gamemode_onslaught.qc b/qcsrc/server/mutators/gamemode_onslaught.qc index fb6e0c10e..448664a90 100644 --- a/qcsrc/server/mutators/gamemode_onslaught.qc +++ b/qcsrc/server/mutators/gamemode_onslaught.qc @@ -604,26 +604,25 @@ void ons_ControlPoint_Icon_Spawn(entity cp, entity player) onslaught_controlpoint_icon_link(e, ons_ControlPoint_Icon_BuildThink); } -string ons_ControlPoint_Waypoint(entity e) +entity ons_ControlPoint_Waypoint(entity e) { if(e.team) { int a = ons_ControlPoint_Attackable(e, e.team); - if(a == -2) { return "ons-cp-dfnd"; } // defend now - if(a == -1 || a == 1 || a == 2) { return "ons-cp"; } // touch - if(a == 3 || a == 4) { return "ons-cp-atck"; } // attack + if(a == -2) { return WP_OnsCPDefend; } // defend now + if(a == -1 || a == 1 || a == 2) { return WP_OnsCP; } // touch + if(a == 3 || a == 4) { return WP_OnsCPAttack; } // attack } else - return "ons-cp"; + return WP_OnsCP; - return ""; + return WP_Null; } void ons_ControlPoint_UpdateSprite(entity e) { - string s1; - s1 = ons_ControlPoint_Waypoint(e); + entity s1 = ons_ControlPoint_Waypoint(e); WaypointSprite_UpdateSprites(e.sprite, s1, s1, s1); bool sh; @@ -807,7 +806,7 @@ void ons_ControlPoint_Setup(entity cp) } // waypointsprites - WaypointSprite_SpawnFixed(string_null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE, '0 0 0'); + WaypointSprite_SpawnFixed(WP_Null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE); WaypointSprite_UpdateRule(self.sprite, self.team, SPRITERULE_TEAMPLAY); InitializeEntity(cp, ons_DelayedControlPoint_Setup, INITPRIO_SETLOCATION); @@ -818,16 +817,16 @@ void ons_ControlPoint_Setup(entity cp) // Main Generator Functions // ========================= -string ons_Generator_Waypoint(entity e) +entity ons_Generator_Waypoint(entity e) { - if(e.isshielded) - return "ons-gen-shielded"; - return "ons-gen"; + if (e.isshielded) + return WP_OnsGenShielded; + return WP_OnsGen; } void ons_Generator_UpdateSprite(entity e) { - string s1 = ons_Generator_Waypoint(e); + entity s1 = ons_Generator_Waypoint(e); WaypointSprite_UpdateSprites(e.sprite, s1, s1, s1); if(e.lastteam != e.team + 2 || e.lastshielded != e.isshielded) @@ -1061,7 +1060,7 @@ void ons_GeneratorSetup(entity gen) // called when spawning a generator entity o droptofloor(); // waypointsprites - WaypointSprite_SpawnFixed(string_null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE, '0 0 0'); + WaypointSprite_SpawnFixed(WP_Null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE); WaypointSprite_UpdateRule(self.sprite, self.team, SPRITERULE_TEAMPLAY); WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health); WaypointSprite_UpdateHealth(self.sprite, self.health); diff --git a/qcsrc/server/mutators/mutator_buffs.qc b/qcsrc/server/mutators/mutator_buffs.qc index f144899c8..cd327e3ea 100644 --- a/qcsrc/server/mutators/mutator_buffs.qc +++ b/qcsrc/server/mutators/mutator_buffs.qc @@ -89,7 +89,8 @@ float buff_Waypoint_visible_for_player(entity plr) void buff_Waypoint_Spawn(entity e) { entity buff = buff_FirstFromFlags(e.buffs); - WaypointSprite_Spawn(buff.m_sprite, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_POWERUP, e.glowmod); + entity wp = WaypointSprite_Spawn(WP_Buff, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_POWERUP); + wp.wp_extra = buff.m_id; WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_POWERUP, e.glowmod); e.buff_waypoint.waypointsprite_visible_for_player = buff_Waypoint_visible_for_player; } diff --git a/qcsrc/server/race.qc b/qcsrc/server/race.qc index cc6d8c4f5..eab7017d1 100644 --- a/qcsrc/server/race.qc +++ b/qcsrc/server/race.qc @@ -827,9 +827,9 @@ void trigger_race_checkpoint_verify() if(defrag_ents) { for(cp = world; (cp = find(cp, classname, "target_startTimer"));) - WaypointSprite_UpdateSprites(cp.sprite, "race-start", "", ""); + WaypointSprite_UpdateSprites(cp.sprite, WP_RaceStart, WP_Null, WP_Null); for(cp = world; (cp = find(cp, classname, "target_stopTimer"));) - WaypointSprite_UpdateSprites(cp.sprite, "race-finish", "", ""); + WaypointSprite_UpdateSprites(cp.sprite, WP_RaceFinish, WP_Null, WP_Null); for(cp = world; (cp = find(cp, classname, "target_checkpoint"));) { @@ -862,9 +862,9 @@ void trigger_race_checkpoint_verify() if(cp.sprite) { if(cp.race_checkpoint == 0) - WaypointSprite_UpdateSprites(cp.sprite, "race-start", "", ""); + WaypointSprite_UpdateSprites(cp.sprite, WP_RaceStart, WP_Null, WP_Null); else if(cp.race_checkpoint == race_timed_checkpoint) - WaypointSprite_UpdateSprites(cp.sprite, "race-finish", "", ""); + WaypointSprite_UpdateSprites(cp.sprite, WP_RaceFinish, WP_Null, WP_Null); } } } @@ -967,9 +967,9 @@ void spawnfunc_trigger_race_checkpoint() if(!self.race_penalty) { if(self.race_checkpoint) - WaypointSprite_SpawnFixed("race-checkpoint", o, self, sprite, RADARICON_NONE, '1 0.5 0'); + WaypointSprite_SpawnFixed(WP_RaceCheckpoint, o, self, sprite, RADARICON_NONE); else - WaypointSprite_SpawnFixed("race-start-finish", o, self, sprite, RADARICON_NONE, '1 0.5 0'); + WaypointSprite_SpawnFixed(WP_RaceStartFinish, o, self, sprite, RADARICON_NONE); } self.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player; @@ -1010,9 +1010,9 @@ void spawnfunc_target_checkpoint() // defrag entity race_timed_checkpoint = 1; if(self.race_checkpoint == 0) - WaypointSprite_SpawnFixed("race-start", o, self, sprite, RADARICON_NONE, '1 0.5 0'); + WaypointSprite_SpawnFixed(WP_RaceStart, o, self, sprite, RADARICON_NONE); else - WaypointSprite_SpawnFixed("race-checkpoint", o, self, sprite, RADARICON_NONE, '1 0.5 0'); + WaypointSprite_SpawnFixed(WP_RaceCheckpoint, o, self, sprite, RADARICON_NONE); self.sprite.waypointsprite_visible_for_player = race_waypointsprite_visible_for_player; diff --git a/qcsrc/server/t_items.qc b/qcsrc/server/t_items.qc index a0dbb61d2..a6d4d2402 100644 --- a/qcsrc/server/t_items.qc +++ b/qcsrc/server/t_items.qc @@ -455,40 +455,22 @@ void Item_RespawnCountdown (void) self.count += 1; if(self.count == 1) { - string name = string_null; - vector rgb = '1 0 1'; + MUTATOR_CALLHOOK(Item_RespawnCountdown, string_null, '0 0 0'); + int wpextra = 0; entity e = self.itemdef; - if (e) { - name = e.m_waypoint; - rgb = e.m_color; - } - MUTATOR_CALLHOOK(Item_RespawnCountdown, name, rgb); - name = item_name; - rgb = item_color; - if(self.flags & FL_WEAPON) - { + if (e) wpextra = e.m_id; + if (self.flags & FL_WEAPON) { entity wi = get_weaponinfo(self.weapon); - if(wi) - { - name = wi.wpmodel; - rgb = '1 0 0'; - } - } - if(name) - { - WaypointSprite_Spawn(name, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP, rgb); - if(self.waypointsprite_attached) - { - if (self.items == IT_HEALTH || self.items == IT_ARMOR) - WaypointSprite_UpdateRule(self.waypointsprite_attached, 0, SPRITERULE_SPECTATOR); - WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, time + ITEM_RESPAWN_TICKS); - } - } - else - { - print("Unknown powerup-marked item is wanting to respawn\n"); - localcmd(sprintf("prvm_edict server %d\n", num_for_edict(self))); + if (wi) wpextra = wi.m_id; } + entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP); + wp.wp_extra = wpextra; + if(self.waypointsprite_attached) + { + if (self.items == IT_HEALTH || self.items == IT_ARMOR) + WaypointSprite_UpdateRule(self.waypointsprite_attached, 0, SPRITERULE_SPECTATOR); + WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, time + ITEM_RESPAWN_TICKS); + } } if(self.waypointsprite_attached) diff --git a/qcsrc/server/weapons/selection.qc b/qcsrc/server/weapons/selection.qc index 1190dceb1..8a4edbd9b 100644 --- a/qcsrc/server/weapons/selection.qc +++ b/qcsrc/server/weapons/selection.qc @@ -91,15 +91,16 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain) continue; if(!(e.flags & FL_ITEM)) continue; - WaypointSprite_Spawn( - (get_weaponinfo(wpn)).wpmodel, + entity wp = WaypointSprite_Spawn( + WP_Weapon, 1, 0, world, e.origin + ('0 0 1' * e.maxs.z) * 1.2, self, 0, world, enemy, 0, - RADARICON_NONE, '0 0 0' + RADARICON_NONE ); + wp.wp_extra = wpn; } } }