From e11a2b2fc74a1ed4befb02c566b8ed89a7196250 Mon Sep 17 00:00:00 2001 From: div0 Date: Wed, 24 Jun 2009 05:32:52 +0000 Subject: [PATCH] - healthbars for players with attached sprite (flag carrier, key carrier, ball kicker) - build bar (smoothly increasing) for powerup respawn git-svn-id: svn://svn.icculus.org/nexuiz/trunk@7092 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/client/sbar.qc | 17 +++++----- data/qcsrc/client/waypointsprites.qc | 37 ++++++++++++++++++++-- data/qcsrc/common/util.qc | 30 ++++++++++++++++++ data/qcsrc/common/util.qh | 3 ++ data/qcsrc/server/cl_client.qc | 3 ++ data/qcsrc/server/cl_player.qc | 12 +++++--- data/qcsrc/server/defs.qh | 1 - data/qcsrc/server/t_items.qc | 5 +-- data/qcsrc/server/waypointsprites.qc | 46 ++++++++++++++++++++++++---- 9 files changed, 129 insertions(+), 25 deletions(-) diff --git a/data/qcsrc/client/sbar.qc b/data/qcsrc/client/sbar.qc index ff0811bfe..6ae5cda67 100644 --- a/data/qcsrc/client/sbar.qc +++ b/data/qcsrc/client/sbar.qc @@ -2279,26 +2279,23 @@ void Sbar_Draw (void) if(sbar_hudselector == 2) // combined health and armor display { - // NOTE: we'll always choose the SMALLER value... - float healthdamage, armordamage, armorideal; - healthdamage = (health - 1) / (1 - armorblockpercent); // damage we can take if we could use more health - armordamage = armor + (health - 1); // damage we can take if we could use more armor - armorideal = healthdamage * armorblockpercent; + vector v; + v = healtharmor_maxdamage(health, armor, armorblockpercent); vector num_pos; num_pos = bottom - element_offset - '0 24 0' + '-96 0 0'; - if(armordamage < healthdamage) + x = floor(v_x + 1); + + if(v_z) // fully armored { // here, armorideal > armor - x = floor(armordamage + 1); drawpic(num_pos + '78 -3 0', "gfx/hud/sb_health", '32 32 0', '1 1 1', sbar_alpha_fg, 0); - drawpic(num_pos + '108 -3 0', "gfx/hud/sb_armor", '20 20 0', '1 1 1', sbar_alpha_fg * armor / armorideal, 0); + drawpic(num_pos + '108 -3 0', "gfx/hud/sb_armor", '20 20 0', '1 1 1', sbar_alpha_fg * armor / v_y, 0); } else { - x = floor(healthdamage + 1); - drawpic(num_pos + '108 -3 0', "gfx/hud/sb_health", '20 20 0', '1 1 1', sbar_alpha_fg * armorideal / armor, 0); + drawpic(num_pos + '108 -3 0', "gfx/hud/sb_health", '20 20 0', '1 1 1', sbar_alpha_fg * v_y / armor, 0); drawpic(num_pos + '78 -3 0', "gfx/hud/sb_armor", '32 32 0', '1 1 1', sbar_alpha_fg, 0); } Sbar_DrawXNum_Colored(num_pos, x, 24, sbar_alpha_fg); // draw the combined health and armor diff --git a/data/qcsrc/client/waypointsprites.qc b/data/qcsrc/client/waypointsprites.qc index d0a8f9aeb..eb569f256 100644 --- a/data/qcsrc/client/waypointsprites.qc +++ b/data/qcsrc/client/waypointsprites.qc @@ -18,6 +18,9 @@ float waypointsprite_scale; .float hideflags; .float spawntime; .float health; +.float build_started; +.float build_starthealth; +.float build_finished; vector SPRITE_SIZE = '256 32 0'; vector SPRITE_HOTSPOT = '128 32 0'; @@ -236,6 +239,21 @@ void Draw_WaypointSprite() drawrotpic(o, rot * 90 * DEG2RAD, spriteimage, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, '1 1 1', a, DRAWFLAG_MIPMAP); + 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; + } + if(self.health >= 0) { drawhealthbar(o, rot * 90 * DEG2RAD, self.health, SPRITE_SIZE * waypointsprite_scale * vidscale, SPRITE_HOTSPOT * waypointsprite_scale * vidscale, SPRITE_HEALTHBAR_WIDTH, SPRITE_HEALTHBAR_HEIGHT, SPRITE_HEALTHBAR_MARGIN, SPRITE_HEALTHBAR_BORDER, self.teamradar_color, a * SPRITE_HEALTHBAR_BORDERALPHA, self.teamradar_color, a * SPRITE_HEALTHBAR_HEALTHALPHA, DRAWFLAG_NORMAL); @@ -254,7 +272,7 @@ void Ent_RemoveWaypointSprite() void Ent_WaypointSprite() { - float sendflags, f; + float sendflags, f, t; sendflags = ReadByte(); if(!self.spawntime) @@ -265,7 +283,22 @@ void Ent_WaypointSprite() InterpolateOrigin_Undo(); if(sendflags & 0x80) - self.health = ReadByte() / 255.0; + { + t = ReadByte(); + if(t < 192) + { + self.health = t / 191.0; + self.build_finished = 0; + } + else + { + t = (t - 192) * 256 + ReadByte(); + self.build_started = servertime; + self.build_starthealth = bound(0, self.health, 1); + self.build_finished = servertime + t / 32; + //print("build: ", ftos(self.build_finished - self.build_started), "\n"); + } + } else self.health = -1; diff --git a/data/qcsrc/common/util.qc b/data/qcsrc/common/util.qc index 7bc7b4717..3fb8616c7 100644 --- a/data/qcsrc/common/util.qc +++ b/data/qcsrc/common/util.qc @@ -1564,3 +1564,33 @@ void RandomSelection_Add(entity e, float f, string s, float weight, float priori } } +vector healtharmor_maxdamage(float h, float a, float armorblock) +{ + // NOTE: we'll always choose the SMALLER value... + float healthdamage, armordamage, armorideal; + vector v; + healthdamage = (h - 1) / (1 - armorblock); // damage we can take if we could use more health + armordamage = a + (h - 1); // damage we can take if we could use more armor + armorideal = healthdamage * armorblock; + v_y = armorideal; + if(armordamage < healthdamage) + { + v_x = armordamage; + v_z = 1; + } + else + { + v_x = healthdamage; + v_z = 0; + } + return v; +} + +vector healtharmor_applydamage(float a, float armorblock, float damage) +{ + vector v; + v_y = bound(0, damage * armorblock, a); // save + v_x = bound(0, damage - v_y, damage); // take + v_z = 0; + return v; +} diff --git a/data/qcsrc/common/util.qh b/data/qcsrc/common/util.qh index 0ae496862..09f3cd0bc 100644 --- a/data/qcsrc/common/util.qh +++ b/data/qcsrc/common/util.qh @@ -170,3 +170,6 @@ float RandomSelection_chosen_float; string RandomSelection_chosen_string; void RandomSelection_Init(); void RandomSelection_Add(entity e, float f, string s, float weight, float priority); + +vector healtharmor_maxdamage(float h, float a, float armorblock); // returns vector: maxdamage, armorideal, 1 if fully armored +vector healtharmor_applydamage(float a, float armorblock, float damage); // returns vector: take, save, 0 diff --git a/data/qcsrc/server/cl_client.qc b/data/qcsrc/server/cl_client.qc index 2e1dc49f5..1e2883d33 100644 --- a/data/qcsrc/server/cl_client.qc +++ b/data/qcsrc/server/cl_client.qc @@ -2918,4 +2918,7 @@ void PlayerPostThink (void) Arena_Warmup(); //pointparticles(particleeffectnum("machinegun_impact"), self.origin + self.view_ofs + '0 0 7', '0 0 0', 1); + + if(self.waypointsprite_attachedforcarrier) + WaypointSprite_UpdateHealth(self.waypointsprite_attachedforcarrier, '1 0 0' * healtharmor_maxdamage(self.health, self.armorvalue, cvar("g_balance_armor_blockpercent"))); } diff --git a/data/qcsrc/server/cl_player.qc b/data/qcsrc/server/cl_player.qc index 23f02a8f2..d61c1773f 100644 --- a/data/qcsrc/server/cl_player.qc +++ b/data/qcsrc/server/cl_player.qc @@ -282,13 +282,15 @@ void SpawnThrownWeapon (vector org, float w) void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { local float take, save; + vector v; Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker); // damage resistance (ignore most of the damage from a bullet or similar) damage = max(damage - 5, 1); - save = bound(0, damage * cvar("g_balance_armor_blockpercent"), self.armorvalue); - take = bound(0, damage - save, damage); + v = healtharmor_applydamage(self.armorvalue, cvar("g_balance_armor_blockpercent"), damage); + take = v_x; + save = v_y; if(sound_allowed(MSG_BROADCAST, attacker)) { @@ -335,6 +337,7 @@ void ClientKill_Now_TeamChange(); void PlayerDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { local float take, save, waves, sdelay; + vector v; if(!DEATH_ISSPECIAL(deathtype)) { @@ -380,8 +383,9 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht if (!g_minstagib) { - save = bound(0, damage * cvar("g_balance_armor_blockpercent"), self.armorvalue); - take = bound(0, damage - save, damage); + v = healtharmor_applydamage(self.armorvalue, cvar("g_balance_armor_blockpercent"), damage); + take = v_x; + save = v_y; } else { diff --git a/data/qcsrc/server/defs.qh b/data/qcsrc/server/defs.qh index 2bbff4903..f714766ae 100644 --- a/data/qcsrc/server/defs.qh +++ b/data/qcsrc/server/defs.qh @@ -287,7 +287,6 @@ float isJoinAllowed(); //sv_timeout: pauses the game by setting the gamespeed to a really low value (see TIMEOUT_SLOWMO_VALUE) #define TIMEOUT_SLOWMO_VALUE 0.0001 -float sys_ticrate; // gets initialised in worlspawn, saves the value from cvar("sys_ticrate") float remainingTimeoutTime; // contains the time in seconds that the active timeout has left float remainingLeadTime; // contains the number of seconds left of the leadtime (before the timeout starts) float timeoutStatus; // (values: 0, 1, 2) contains whether a timeout is not active (0), was called but still at leadtime (1) or is active (2) diff --git a/data/qcsrc/server/t_items.qc b/data/qcsrc/server/t_items.qc index dea5ec6e7..33e71f017 100644 --- a/data/qcsrc/server/t_items.qc +++ b/data/qcsrc/server/t_items.qc @@ -102,7 +102,8 @@ void Item_RespawnCountdown (void) if(self.waypointsprite_attached) { WaypointSprite_UpdateTeamRadar(self.waypointsprite_attached, RADARICON_POWERUP, rgb); - WaypointSprite_UpdateMaxHealth(self.waypointsprite_attached, ITEM_RESPAWN_TICKS + 1); + //WaypointSprite_UpdateMaxHealth(self.waypointsprite_attached, ITEM_RESPAWN_TICKS + 1); + WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, time + ITEM_RESPAWN_TICKS); } } } @@ -110,7 +111,7 @@ void Item_RespawnCountdown (void) if(self.waypointsprite_attached) { WaypointSprite_Ping(self.waypointsprite_attached); - WaypointSprite_UpdateHealth(self.waypointsprite_attached, self.count); + //WaypointSprite_UpdateHealth(self.waypointsprite_attached, self.count); } } } diff --git a/data/qcsrc/server/waypointsprites.qc b/data/qcsrc/server/waypointsprites.qc index 1a63ba53b..09decfe6d 100644 --- a/data/qcsrc/server/waypointsprites.qc +++ b/data/qcsrc/server/waypointsprites.qc @@ -27,18 +27,31 @@ void WaypointSprite_UpdateSprites(entity e, string m1, string m2, string m3) void WaypointSprite_UpdateHealth(entity e, float f) { - if(f != e.health) + 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) + 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; } } @@ -192,17 +205,31 @@ float WaypointSprite_Customize() float WaypointSprite_SendEntity(entity to, float sendflags) { + float dt; + WriteByte(MSG_ENTITY, ENT_CLIENT_WAYPOINT); sendflags = sendflags & 0x7F; - if(self.max_health) + if(self.max_health || (self.pain_finished && (time < self.pain_finished + 0.25))) sendflags |= 0x80; WriteByte(MSG_ENTITY, sendflags); - if(self.max_health) - WriteByte(MSG_ENTITY, (self.health / self.max_health) * 255.0); + if(sendflags & 0x80) + { + if(self.max_health) + { + WriteByte(MSG_ENTITY, (self.health / self.max_health) * 191.0); + } + else + { + 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) { @@ -367,8 +394,15 @@ entity WaypointSprite_AttachCarrier( entity carrier ) { + entity e; WaypointSprite_Kill(carrier.waypointsprite_attached); // FC overrides attached - return WaypointSprite_Spawn(spr, 0, 0, carrier, '0 0 64', world, carrier.team, carrier, waypointsprite_attachedforcarrier, FALSE); + e = WaypointSprite_Spawn(spr, 0, 0, carrier, '0 0 64', world, carrier.team, carrier, waypointsprite_attachedforcarrier, FALSE); + if(e) + { + WaypointSprite_UpdateMaxHealth(e, '1 0 0' * healtharmor_maxdamage(start_health, start_armorvalue, cvar("g_balance_armor_blockpercent"))); + WaypointSprite_UpdateHealth(e, '1 0 0' * healtharmor_maxdamage(carrier.health, carrier.armorvalue, cvar("g_balance_armor_blockpercent"))); + } + return e; } void WaypointSprite_DetachCarrier(entity carrier) -- 2.39.2