5420: Improvments for new HUD r=def- a=C0D3D3V

for testing set `#define CLIENT_VERSIONNR 16020`
Some of the changes are only available in the next version

Impressions: https://youtu.be/E770vGp4KKY

Implements a few of the recommendations from https://github.com/ddnet/ddnet/issues/5159 and Discord
- removes all player capability messages send by the server, that are now displayed in the HUD
- ~~remove `cl_ddrace_hud` and cl_show_freeze_bars~~, 
- Added option `cl_freezebars_alpha_inside_freeze` setting to change the opacity if the player is inside a freeze tile (default visible 100%)
- Added option `cl_show_jumps_indicator`
- We send now the real weapon the player is holding if he is frozen
    -> for that we added a new particle "snow flakes" or frozen flakes :D that are spawned over the tees body, to indicate he is frozen.
    -> new extras.png asset (+ corresponding asset tab, that can potentially be used for all sorts of extras for our mod, e.g. material particles, but in the future maybe also for other mods using a similar structure like it is for entities)
- stars are no longer send to new clients, because it is duplication to the freezebar, and we decided to not allow to disable it 
- also ninja stars are no longer send. They are not vanilla, and we now have a ninja bar in the new HUD.
- display target angle from 0 to 360 (looks mirrored on the x-axis to the normal trigonometry circle, but that is just how the world coordinates are) 
- dummy action display is increased in size ( but only the border margin :D not the icons. so the icons are still the same size as the icons on the left side)
- allow the server to also show old HUD elements (see https://github.com/ddnet/ddnet/pull/5427 for screenshots)


fixes #5149
fixes #198
closes #5159

fixes #2252   ~~(But not clear if we should also display the weapon, still investigating)~~
- we do no longer display a weapon inside freeze, instead we have nice freeze particles

## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [x] Considered possible null pointers and out of bounds array indexing
- [x] Changed no physics that affect existing maps
- [x] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: c0d3d3v <c0d3d3v@mag-keinen-spam.de>
This commit is contained in:
bors[bot] 2022-06-26 07:57:33 +00:00 committed by GitHub
commit 1e31db257f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 851 additions and 447 deletions

View file

@ -1269,6 +1269,7 @@ set(EXPECTED_DATA
editor/water.rules editor/water.rules
editor/winter_main.rules editor/winter_main.rules
emoticons.png emoticons.png
extras.png
file_icons.png file_icons.png
fonts/DejaVuSans.ttf fonts/DejaVuSans.ttf
fonts/GlowSansJCompressed-Book.otf fonts/GlowSansJCompressed-Book.otf

BIN
data/extras.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View file

@ -239,6 +239,7 @@ image_demobuttons2 = Image("demobuttons2", "demo_buttons2.png")
image_audio_source = Image("audio_source", "editor/audio_source.png") image_audio_source = Image("audio_source", "editor/audio_source.png")
image_strongweak = Image("strongweak", "strong_weak.png") image_strongweak = Image("strongweak", "strong_weak.png")
image_hud = Image("hud", "hud.png") image_hud = Image("hud", "hud.png")
image_extras = Image("extras", "extras.png")
container.images.Add(image_null) container.images.Add(image_null)
container.images.Add(image_game) container.images.Add(image_game)
@ -258,6 +259,7 @@ container.images.Add(image_demobuttons2)
container.images.Add(image_audio_source) container.images.Add(image_audio_source)
container.images.Add(image_strongweak) container.images.Add(image_strongweak)
container.images.Add(image_hud) container.images.Add(image_hud)
container.images.Add(image_extras)
container.pickups.Add(Pickup("health")) container.pickups.Add(Pickup("health"))
container.pickups.Add(Pickup("armor")) container.pickups.Add(Pickup("armor"))
@ -280,7 +282,8 @@ set_guiicons = SpriteSet("guiicons", image_guiicons, 12, 2)
set_demobuttons2 = SpriteSet("demobuttons2", image_demobuttons2, 4, 1) set_demobuttons2 = SpriteSet("demobuttons2", image_demobuttons2, 4, 1)
set_audio_source = SpriteSet("audio_source", image_audio_source, 1, 1) set_audio_source = SpriteSet("audio_source", image_audio_source, 1, 1)
set_strongweak = SpriteSet("strongweak", image_strongweak, 2, 1) set_strongweak = SpriteSet("strongweak", image_strongweak, 2, 1)
set_hud = SpriteSet("hud", image_hud, 14, 12) set_hud = SpriteSet("hud", image_hud, 16, 16)
set_extras = SpriteSet("extras", image_extras, 16, 16)
container.spritesets.Add(set_particles) container.spritesets.Add(set_particles)
container.spritesets.Add(set_game) container.spritesets.Add(set_game)
@ -295,6 +298,7 @@ container.spritesets.Add(set_demobuttons2)
container.spritesets.Add(set_audio_source) container.spritesets.Add(set_audio_source)
container.spritesets.Add(set_strongweak) container.spritesets.Add(set_strongweak)
container.spritesets.Add(set_hud) container.spritesets.Add(set_hud)
container.spritesets.Add(set_extras)
container.sprites.Add(Sprite("part_slice", set_particles, 0,0,1,1)) container.sprites.Add(Sprite("part_slice", set_particles, 0,0,1,1))
container.sprites.Add(Sprite("part_ball", set_particles, 1,0,1,1)) container.sprites.Add(Sprite("part_ball", set_particles, 1,0,1,1))
@ -462,6 +466,7 @@ container.sprites.Add(Sprite("hud_no_hammer_hit", set_hud, 6,2,2,2))
container.sprites.Add(Sprite("hud_no_shotgun_hit", set_hud, 8,2,2,2)) container.sprites.Add(Sprite("hud_no_shotgun_hit", set_hud, 8,2,2,2))
container.sprites.Add(Sprite("hud_no_grenade_hit", set_hud, 10,2,2,2)) container.sprites.Add(Sprite("hud_no_grenade_hit", set_hud, 10,2,2,2))
container.sprites.Add(Sprite("hud_no_laser_hit", set_hud, 12,2,2,2)) container.sprites.Add(Sprite("hud_no_laser_hit", set_hud, 12,2,2,2))
container.sprites.Add(Sprite("hud_no_gun_hit", set_hud, 14,2,2,2))
container.sprites.Add(Sprite("hud_deep_frozen", set_hud, 10,4,2,2)) container.sprites.Add(Sprite("hud_deep_frozen", set_hud, 10,4,2,2))
container.sprites.Add(Sprite("hud_live_frozen", set_hud, 12,4,2,2)) container.sprites.Add(Sprite("hud_live_frozen", set_hud, 12,4,2,2))
container.sprites.Add(Sprite("hud_teleport_grenade", set_hud, 4,4,2,2)) container.sprites.Add(Sprite("hud_teleport_grenade", set_hud, 4,4,2,2))
@ -471,6 +476,9 @@ container.sprites.Add(Sprite("hud_practice_mode", set_hud, 4,6,2,2))
container.sprites.Add(Sprite("hud_dummy_hammer", set_hud, 6,6,2,2)) container.sprites.Add(Sprite("hud_dummy_hammer", set_hud, 6,6,2,2))
container.sprites.Add(Sprite("hud_dummy_copy", set_hud, 8,6,2,2)) container.sprites.Add(Sprite("hud_dummy_copy", set_hud, 8,6,2,2))
container.sprites.Add(Sprite("part_snowflake", set_extras, 0,0,2,2))
anim = Animation("base") anim = Animation("base")
anim.body.frames.Add(AnimKeyframe(0, 0, -4, 0)) anim.body.frames.Add(AnimKeyframe(0, 0, -4, 0))
anim.back_foot.frames.Add(AnimKeyframe(0, 0, 10, 0)) anim.back_foot.frames.Add(AnimKeyframe(0, 0, 10, 0))

View file

@ -10,7 +10,8 @@ GameStateFlags = ["GAMEOVER", "SUDDENDEATH", "PAUSED", "RACETIME"]
CharacterFlags = ["SOLO", "JETPACK", "NO_COLLISION", "ENDLESS_HOOK", "ENDLESS_JUMP", "SUPER", CharacterFlags = ["SOLO", "JETPACK", "NO_COLLISION", "ENDLESS_HOOK", "ENDLESS_JUMP", "SUPER",
"NO_HAMMER_HIT", "NO_SHOTGUN_HIT", "NO_GRENADE_HIT", "NO_LASER_HIT", "NO_HOOK", "NO_HAMMER_HIT", "NO_SHOTGUN_HIT", "NO_GRENADE_HIT", "NO_LASER_HIT", "NO_HOOK",
"TELEGUN_GUN", "TELEGUN_GRENADE", "TELEGUN_LASER", "TELEGUN_GUN", "TELEGUN_GRENADE", "TELEGUN_LASER",
"WEAPON_HAMMER", "WEAPON_GUN", "WEAPON_SHOTGUN", "WEAPON_GRENADE", "WEAPON_LASER", "WEAPON_NINJA", "NO_MOVEMENTS"] "WEAPON_HAMMER", "WEAPON_GUN", "WEAPON_SHOTGUN", "WEAPON_GRENADE", "WEAPON_LASER", "WEAPON_NINJA",
"NO_MOVEMENTS"]
GameInfoFlags = [ GameInfoFlags = [
"TIMESCORE", "GAMETYPE_RACE", "GAMETYPE_FASTCAP", "GAMETYPE_FNG", "TIMESCORE", "GAMETYPE_RACE", "GAMETYPE_FASTCAP", "GAMETYPE_FNG",
"GAMETYPE_DDRACE", "GAMETYPE_DDNET", "GAMETYPE_BLOCK_WORLDS", "GAMETYPE_DDRACE", "GAMETYPE_DDNET", "GAMETYPE_BLOCK_WORLDS",
@ -24,7 +25,8 @@ GameInfoFlags = [
# Full, use GameInfoFlags2 for more flags # Full, use GameInfoFlags2 for more flags
] ]
GameInfoFlags2 = [ GameInfoFlags2 = [
"ALLOW_X_SKINS", "GAMETYPE_CITY", "GAMETYPE_FDDRACE", "ENTITIES_FDDRACE", "ALLOW_X_SKINS", "GAMETYPE_CITY", "GAMETYPE_FDDRACE", "ENTITIES_FDDRACE", "HUD_HEALTH_ARMOR", "HUD_AMMO",
"HUD_DDRACE",
] ]
ExPlayerFlags = ["AFK", "PAUSED", "SPEC"] ExPlayerFlags = ["AFK", "PAUSED", "SPEC"]
ProjectileFlags = ["CLIENTID_BIT{}".format(i) for i in range(8)] + [ ProjectileFlags = ["CLIENTID_BIT{}".format(i) for i in range(8)] + [
@ -62,7 +64,7 @@ enum
enum enum
{ {
GAMEINFO_CURVERSION=6, GAMEINFO_CURVERSION=7,
}; };
''' '''

View file

@ -42,6 +42,7 @@ MACRO_CONFIG_STR(ClAssetGame, cl_asset_game, 50, "default", CFGFLAG_SAVE | CFGFL
MACRO_CONFIG_STR(ClAssetEmoticons, cl_asset_emoticons, 50, "default", CFGFLAG_SAVE | CFGFLAG_CLIENT, "The asset for emoticons") MACRO_CONFIG_STR(ClAssetEmoticons, cl_asset_emoticons, 50, "default", CFGFLAG_SAVE | CFGFLAG_CLIENT, "The asset for emoticons")
MACRO_CONFIG_STR(ClAssetParticles, cl_asset_particles, 50, "default", CFGFLAG_SAVE | CFGFLAG_CLIENT, "The asset for particles") MACRO_CONFIG_STR(ClAssetParticles, cl_asset_particles, 50, "default", CFGFLAG_SAVE | CFGFLAG_CLIENT, "The asset for particles")
MACRO_CONFIG_STR(ClAssetHud, cl_asset_hud, 50, "default", CFGFLAG_SAVE | CFGFLAG_CLIENT, "The asset for HUD") MACRO_CONFIG_STR(ClAssetHud, cl_asset_hud, 50, "default", CFGFLAG_SAVE | CFGFLAG_CLIENT, "The asset for HUD")
MACRO_CONFIG_STR(ClAssetExtras, cl_asset_extras, 50, "default", CFGFLAG_SAVE | CFGFLAG_CLIENT, "The asset for the game graphics that do not come from Teeworlds")
MACRO_CONFIG_STR(BrFilterString, br_filter_string, 25, "Novice", CFGFLAG_SAVE | CFGFLAG_CLIENT, "Server browser filtering string") MACRO_CONFIG_STR(BrFilterString, br_filter_string, 25, "Novice", CFGFLAG_SAVE | CFGFLAG_CLIENT, "Server browser filtering string")
MACRO_CONFIG_STR(BrExcludeString, br_exclude_string, 25, "", CFGFLAG_SAVE | CFGFLAG_CLIENT, "Server browser exclusion string") MACRO_CONFIG_STR(BrExcludeString, br_exclude_string, 25, "", CFGFLAG_SAVE | CFGFLAG_CLIENT, "Server browser exclusion string")
@ -317,7 +318,8 @@ MACRO_CONFIG_INT(ClRaceSaveGhost, cl_race_save_ghost, 1, 0, 1, CFGFLAG_CLIENT |
MACRO_CONFIG_INT(ClDDRaceHud, cl_ddrace_hud, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Enable DDRace HUD") MACRO_CONFIG_INT(ClDDRaceHud, cl_ddrace_hud, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Enable DDRace HUD")
MACRO_CONFIG_INT(ClDDRaceScoreBoard, cl_ddrace_scoreboard, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Enable DDRace Scoreboard") MACRO_CONFIG_INT(ClDDRaceScoreBoard, cl_ddrace_scoreboard, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Enable DDRace Scoreboard")
MACRO_CONFIG_INT(ClShowFreezeBars, cl_show_freeze_bars, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Show a freeze bar under frozen players to indicate the thaw time") MACRO_CONFIG_INT(ClShowJumpsIndicator, cl_show_jumps_indicator, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Whether to show in the HUD how many jumps you have and have used")
MACRO_CONFIG_INT(ClShowFreezeBars, cl_show_freeze_bars, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Whether to show a freeze bar under frozen players to indicate the thaw time")
MACRO_CONFIG_INT(SvResetPickups, sv_reset_pickups, 0, 0, 1, CFGFLAG_SERVER | CFGFLAG_GAME, "Whether the weapons are reset on passing the start tile or not") MACRO_CONFIG_INT(SvResetPickups, sv_reset_pickups, 0, 0, 1, CFGFLAG_SERVER | CFGFLAG_GAME, "Whether the weapons are reset on passing the start tile or not")
MACRO_CONFIG_INT(ClShowOthers, cl_show_others, 0, 0, 2, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show players in other teams (2 to show own team only)") MACRO_CONFIG_INT(ClShowOthers, cl_show_others, 0, 0, 2, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show players in other teams (2 to show own team only)")
MACRO_CONFIG_INT(ClShowOthersAlpha, cl_show_others_alpha, 40, 0, 100, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show players in other teams (alpha value, 0 invisible, 100 fully visible)") MACRO_CONFIG_INT(ClShowOthersAlpha, cl_show_others_alpha, 40, 0, 100, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show players in other teams (alpha value, 0 invisible, 100 fully visible)")

View file

@ -117,6 +117,7 @@ enum
VERSION_DDNET_SWITCH = 15060, VERSION_DDNET_SWITCH = 15060,
VERSION_DDNET_INDEPENDENT_SPECTATORS_TEAM = 16000, VERSION_DDNET_INDEPENDENT_SPECTATORS_TEAM = 16000,
VERSION_DDNET_WEAPON_SHIELDS = 16010, VERSION_DDNET_WEAPON_SHIELDS = 16010,
VERSION_DDNET_NEW_HUD = 16020,
}; };
#endif #endif

View file

@ -80,6 +80,7 @@ public:
fs_makedir(GetPath(TYPE_SAVE, "assets/game", aPath, sizeof(aPath))); fs_makedir(GetPath(TYPE_SAVE, "assets/game", aPath, sizeof(aPath)));
fs_makedir(GetPath(TYPE_SAVE, "assets/particles", aPath, sizeof(aPath))); fs_makedir(GetPath(TYPE_SAVE, "assets/particles", aPath, sizeof(aPath)));
fs_makedir(GetPath(TYPE_SAVE, "assets/hud", aPath, sizeof(aPath))); fs_makedir(GetPath(TYPE_SAVE, "assets/hud", aPath, sizeof(aPath)));
fs_makedir(GetPath(TYPE_SAVE, "assets/extras", aPath, sizeof(aPath)));
#if defined(CONF_VIDEORECORDER) #if defined(CONF_VIDEORECORDER)
fs_makedir(GetPath(TYPE_SAVE, "videos", aPath, sizeof(aPath))); fs_makedir(GetPath(TYPE_SAVE, "videos", aPath, sizeof(aPath)));
#endif #endif

View file

@ -47,7 +47,7 @@ void CDamageInd::Create(vec2 Pos, vec2 Dir)
void CDamageInd::OnRender() void CDamageInd::OnRender()
{ {
Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteStars[0]); Graphics()->TextureSet(GameClient()->m_GameSkin.m_aSpriteStars[0]);
static float s_LastLocalTime = LocalTime(); static float s_LastLocalTime = LocalTime();
for(int i = 0; i < m_NumItems;) for(int i = 0; i < m_NumItems;)
{ {

View file

@ -37,15 +37,15 @@ void CDebugHud::RenderNetCorrections()
x = Width - 10.0f; x = Width - 10.0f;
char aBuf[128]; char aBuf[128];
str_format(aBuf, sizeof(aBuf), "%.2f Bps", Velspeed / 32); str_format(aBuf, sizeof(aBuf), "%.0f Bps", Velspeed / 32);
float w = TextRender()->TextWidth(0, Fontsize, aBuf, -1, -1.0f); float w = TextRender()->TextWidth(0, Fontsize, aBuf, -1, -1.0f);
TextRender()->Text(0, x - w, y, Fontsize, aBuf, -1.0f); TextRender()->Text(0, x - w, y, Fontsize, aBuf, -1.0f);
y += LineHeight; y += LineHeight;
str_format(aBuf, sizeof(aBuf), "%.2f Bps", VelspeedX / 32 * Ramp); str_format(aBuf, sizeof(aBuf), "%.0f Bps", VelspeedX / 32 * Ramp);
w = TextRender()->TextWidth(0, Fontsize, aBuf, -1, -1.0f); w = TextRender()->TextWidth(0, Fontsize, aBuf, -1, -1.0f);
TextRender()->Text(0, x - w, y, Fontsize, aBuf, -1.0f); TextRender()->Text(0, x - w, y, Fontsize, aBuf, -1.0f);
y += LineHeight; y += LineHeight;
str_format(aBuf, sizeof(aBuf), "%.2f Bps", VelspeedY / 32); str_format(aBuf, sizeof(aBuf), "%.0f Bps", VelspeedY / 32);
w = TextRender()->TextWidth(0, Fontsize, aBuf, -1, -1.0f); w = TextRender()->TextWidth(0, Fontsize, aBuf, -1, -1.0f);
TextRender()->Text(0, x - w, y, Fontsize, aBuf, -1.0f); TextRender()->Text(0, x - w, y, Fontsize, aBuf, -1.0f);
y += LineHeight; y += LineHeight;

View file

@ -19,6 +19,7 @@ inline vec2 RandomDir() { return normalize(vec2(random_float() - 0.5f, random_fl
CEffects::CEffects() CEffects::CEffects()
{ {
m_Add5hz = false;
m_Add50hz = false; m_Add50hz = false;
m_Add100hz = false; m_Add100hz = false;
} }
@ -57,7 +58,7 @@ void CEffects::ResetDamageIndicator()
m_pClient->m_DamageInd.Reset(); m_pClient->m_DamageInd.Reset();
} }
void CEffects::PowerupShine(vec2 Pos, vec2 size) void CEffects::PowerupShine(vec2 Pos, vec2 Size)
{ {
if(!m_Add50hz) if(!m_Add50hz)
return; return;
@ -65,7 +66,7 @@ void CEffects::PowerupShine(vec2 Pos, vec2 size)
CParticle p; CParticle p;
p.SetDefault(); p.SetDefault();
p.m_Spr = SPRITE_PART_SLICE; p.m_Spr = SPRITE_PART_SLICE;
p.m_Pos = Pos + vec2((random_float() - 0.5f) * size.x, (random_float() - 0.5f) * size.y); p.m_Pos = Pos + vec2((random_float() - 0.5f) * Size.x, (random_float() - 0.5f) * Size.y);
p.m_Vel = vec2(0, 0); p.m_Vel = vec2(0, 0);
p.m_LifeSpan = 0.5f; p.m_LifeSpan = 0.5f;
p.m_StartSize = 16.0f; p.m_StartSize = 16.0f;
@ -78,6 +79,31 @@ void CEffects::PowerupShine(vec2 Pos, vec2 size)
m_pClient->m_Particles.Add(CParticles::GROUP_GENERAL, &p); m_pClient->m_Particles.Add(CParticles::GROUP_GENERAL, &p);
} }
void CEffects::FreezingFlakes(vec2 Pos, vec2 Size)
{
if(!m_Add5hz)
return;
CParticle p;
p.SetDefault();
p.m_Spr = SPRITE_PART_SNOWFLAKE;
p.m_Pos = Pos + vec2((random_float() - 0.5f) * Size.x, (random_float() - 0.5f) * Size.y);
p.m_Vel = vec2(0, 0);
p.m_LifeSpan = 1.5f;
p.m_StartSize = (random_float() + 0.5f) * 16.0f;
p.m_EndSize = p.m_StartSize * 0.5f;
p.m_UseAlphaFading = true;
p.m_StartAlpha = 1.0f;
p.m_EndAlpha = 0.0f;
p.m_Rot = random_float() * pi * 2;
p.m_Rotspeed = pi;
p.m_Gravity = random_float() * 250.0f;
p.m_Friction = 0.9f;
p.m_FlowAffected = 0.0f;
p.m_Collides = false;
m_pClient->m_Particles.Add(CParticles::GROUP_EXTRA, &p);
}
void CEffects::SmokeTrail(vec2 Pos, vec2 Vel, float Alpha, float TimePassed) void CEffects::SmokeTrail(vec2 Pos, vec2 Vel, float Alpha, float TimePassed)
{ {
if(!m_Add50hz && TimePassed < 0.001f) if(!m_Add50hz && TimePassed < 0.001f)
@ -255,50 +281,37 @@ void CEffects::HammerHit(vec2 Pos)
void CEffects::OnRender() void CEffects::OnRender()
{ {
static int64_t LastUpdate100hz = 0; static int64_t s_LastUpdate100hz = 0;
static int64_t LastUpdate50hz = 0; static int64_t s_LastUpdate50hz = 0;
static int64_t s_LastUpdate5hz = 0;
float Speed = 1.0f;
if(Client()->State() == IClient::STATE_DEMOPLAYBACK) if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
{ Speed = DemoPlayer()->BaseInfo()->m_Speed;
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
if(time() - LastUpdate100hz > time_freq() / (100 * pInfo->m_Speed)) if(time() - s_LastUpdate100hz > time_freq() / (100 * Speed))
{ {
m_Add100hz = true; m_Add100hz = true;
LastUpdate100hz = time(); s_LastUpdate100hz = time();
} }
else else
m_Add100hz = false; m_Add100hz = false;
if(time() - LastUpdate50hz > time_freq() / (100 * pInfo->m_Speed)) if(time() - s_LastUpdate50hz > time_freq() / (50 * Speed))
{ {
m_Add50hz = true; m_Add50hz = true;
LastUpdate50hz = time(); s_LastUpdate50hz = time();
} }
else else
m_Add50hz = false; m_Add50hz = false;
if(m_Add50hz) if(time() - s_LastUpdate5hz > time_freq() / (5 * Speed))
m_pClient->m_Flow.Update();
return;
}
if(time() - LastUpdate100hz > time_freq() / 100)
{ {
m_Add100hz = true; m_Add5hz = true;
LastUpdate100hz = time(); s_LastUpdate5hz = time();
} }
else else
m_Add100hz = false; m_Add5hz = false;
if(time() - LastUpdate50hz > time_freq() / 100)
{
m_Add50hz = true;
LastUpdate50hz = time();
}
else
m_Add50hz = false;
if(m_Add50hz) if(m_Add50hz)
m_pClient->m_Flow.Update(); m_pClient->m_Flow.Update();

View file

@ -6,6 +6,7 @@
class CEffects : public CComponent class CEffects : public CComponent
{ {
bool m_Add5hz;
bool m_Add50hz; bool m_Add50hz;
bool m_Add100hz; bool m_Add100hz;
@ -26,6 +27,7 @@ public:
void PlayerSpawn(vec2 Pos); void PlayerSpawn(vec2 Pos);
void PlayerDeath(vec2 Pos, int ClientID); void PlayerDeath(vec2 Pos, int ClientID);
void PowerupShine(vec2 Pos, vec2 Size); void PowerupShine(vec2 Pos, vec2 Size);
void FreezingFlakes(vec2 Pos, vec2 Size);
void Update(); void Update();
}; };

View file

@ -121,7 +121,7 @@ void CEmoticon::OnRender()
float Size = Selected ? 80.0f : 50.0f; float Size = Selected ? 80.0f : 50.0f;
Graphics()->TextureSet(GameClient()->m_EmoticonsSkin.m_SpriteEmoticons[i]); Graphics()->TextureSet(GameClient()->m_EmoticonsSkin.m_aSpriteEmoticons[i]);
Graphics()->QuadsSetSubset(0, 0, 1, 1); Graphics()->QuadsSetSubset(0, 0, 1, 1);
Graphics()->QuadsBegin(); Graphics()->QuadsBegin();

View file

@ -10,7 +10,7 @@ void CFreezeBars::RenderFreezeBar(const int ClientID)
// pCharacter contains the predicted character for local players or the last snap for players who are spectated // pCharacter contains the predicted character for local players or the last snap for players who are spectated
CCharacterCore *pCharacter = &m_pClient->m_aClients[ClientID].m_Predicted; CCharacterCore *pCharacter = &m_pClient->m_aClients[ClientID].m_Predicted;
if(pCharacter->m_FreezeEnd <= 0.0f || pCharacter->m_FreezeTick == 0 || !m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo || pCharacter->m_IsInFreeze) if(pCharacter->m_FreezeEnd <= 0.0f || pCharacter->m_FreezeTick == 0 || !m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo || (pCharacter->m_IsInFreeze && g_Config.m_ClFreezeBarsAlphaInsideFreeze == 0))
{ {
return; return;
} }
@ -27,6 +27,10 @@ void CFreezeBars::RenderFreezeBar(const int ClientID)
Position.y += 32; Position.y += 32;
float Alpha = m_pClient->IsOtherTeam(ClientID) ? g_Config.m_ClShowOthersAlpha / 100.0f : 1.0f; float Alpha = m_pClient->IsOtherTeam(ClientID) ? g_Config.m_ClShowOthersAlpha / 100.0f : 1.0f;
if(pCharacter->m_IsInFreeze)
{
Alpha *= g_Config.m_ClFreezeBarsAlphaInsideFreeze / 100.0f;
}
RenderFreezeBarPos(Position.x, Position.y, FreezeBarWidth, FreezeBarHight, FreezeProgress, Alpha); RenderFreezeBarPos(Position.x, Position.y, FreezeBarWidth, FreezeBarHight, FreezeProgress, Alpha);
} }

View file

@ -26,7 +26,7 @@ void CGhost::GetGhostSkin(CGhostSkin *pSkin, const char *pSkinName, int UseCusto
pSkin->m_ColorFeet = ColorFeet; pSkin->m_ColorFeet = ColorFeet;
} }
void CGhost::GetGhostCharacter(CGhostCharacter *pGhostChar, const CNetObj_Character *pChar) void CGhost::GetGhostCharacter(CGhostCharacter *pGhostChar, const CNetObj_Character *pChar, const CNetObj_DDNetCharacter *pDDnetChar)
{ {
pGhostChar->m_X = pChar->m_X; pGhostChar->m_X = pChar->m_X;
pGhostChar->m_Y = pChar->m_Y; pGhostChar->m_Y = pChar->m_Y;
@ -34,7 +34,12 @@ void CGhost::GetGhostCharacter(CGhostCharacter *pGhostChar, const CNetObj_Charac
pGhostChar->m_VelY = 0; pGhostChar->m_VelY = 0;
pGhostChar->m_Angle = pChar->m_Angle; pGhostChar->m_Angle = pChar->m_Angle;
pGhostChar->m_Direction = pChar->m_Direction; pGhostChar->m_Direction = pChar->m_Direction;
pGhostChar->m_Weapon = pChar->m_Weapon; int Weapon = pChar->m_Weapon;
if(pDDnetChar != nullptr && pDDnetChar->m_FreezeEnd != 0)
{
Weapon = WEAPON_NINJA;
}
pGhostChar->m_Weapon = Weapon;
pGhostChar->m_HookState = pChar->m_HookState; pGhostChar->m_HookState = pChar->m_HookState;
pGhostChar->m_HookX = pChar->m_HookX; pGhostChar->m_HookX = pChar->m_HookX;
pGhostChar->m_HookY = pChar->m_HookY; pGhostChar->m_HookY = pChar->m_HookY;
@ -134,7 +139,7 @@ void CGhost::GetPath(char *pBuf, int Size, const char *pPlayerName, int Time) co
str_format(pBuf, Size, "%s/%s_%s_%d.%03d_%s.gho", ms_pGhostDir, pMap, aPlayerName, Time / 1000, Time % 1000, aSha256); str_format(pBuf, Size, "%s/%s_%s_%d.%03d_%s.gho", ms_pGhostDir, pMap, aPlayerName, Time / 1000, Time % 1000, aSha256);
} }
void CGhost::AddInfos(const CNetObj_Character *pChar) void CGhost::AddInfos(const CNetObj_Character *pChar, const CNetObj_DDNetCharacter *pDDnetChar)
{ {
int NumTicks = m_CurGhost.m_Path.Size(); int NumTicks = m_CurGhost.m_Path.Size();
@ -151,7 +156,7 @@ void CGhost::AddInfos(const CNetObj_Character *pChar)
} }
CGhostCharacter GhostChar; CGhostCharacter GhostChar;
GetGhostCharacter(&GhostChar, pChar); GetGhostCharacter(&GhostChar, pChar, pDDnetChar);
m_CurGhost.m_Path.Add(GhostChar); m_CurGhost.m_Path.Add(GhostChar);
if(GhostRecorder()->IsRecording()) if(GhostRecorder()->IsRecording())
GhostRecorder()->WriteData(GHOSTDATA_TYPE_CHARACTER, &GhostChar, sizeof(CGhostCharacter)); GhostRecorder()->WriteData(GHOSTDATA_TYPE_CHARACTER, &GhostChar, sizeof(CGhostCharacter));
@ -279,7 +284,7 @@ void CGhost::OnNewSnapshot()
CheckStart(); CheckStart();
if(m_Recording) if(m_Recording)
AddInfos(m_pClient->m_Snap.m_pLocalCharacter); AddInfos(m_pClient->m_Snap.m_pLocalCharacter, (m_pClient->m_Snap.m_LocalClientID != -1 && m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_LocalClientID].m_HasExtendedData) ? &m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_LocalClientID].m_ExtendedData : nullptr);
} }
// Record m_LastRaceTick for g_Config.m_ClConfirmDisconnect/QuitTime anyway // Record m_LastRaceTick for g_Config.m_ClConfirmDisconnect/QuitTime anyway

View file

@ -5,6 +5,7 @@
#include <game/client/component.h> #include <game/client/component.h>
#include <game/client/components/menus.h> #include <game/client/components/menus.h>
#include <game/generated/protocol.h>
#include <game/client/render.h> #include <game/client/render.h>
@ -124,12 +125,12 @@ private:
bool m_RenderingStartedByServer; bool m_RenderingStartedByServer;
static void GetGhostSkin(CGhostSkin *pSkin, const char *pSkinName, int UseCustomColor, int ColorBody, int ColorFeet); static void GetGhostSkin(CGhostSkin *pSkin, const char *pSkinName, int UseCustomColor, int ColorBody, int ColorFeet);
static void GetGhostCharacter(CGhostCharacter *pGhostChar, const CNetObj_Character *pChar); static void GetGhostCharacter(CGhostCharacter *pGhostChar, const CNetObj_Character *pChar, const CNetObj_DDNetCharacter *pDDnetChar);
static void GetNetObjCharacter(CNetObj_Character *pChar, const CGhostCharacter *pGhostChar); static void GetNetObjCharacter(CNetObj_Character *pChar, const CGhostCharacter *pGhostChar);
void GetPath(char *pBuf, int Size, const char *pPlayerName, int Time = -1) const; void GetPath(char *pBuf, int Size, const char *pPlayerName, int Time = -1) const;
void AddInfos(const CNetObj_Character *pChar); void AddInfos(const CNetObj_Character *pChar, const CNetObj_DDNetCharacter *pDDnetChar);
int GetSlot() const; int GetSlot() const;
void CheckStart(); void CheckStart();

View file

@ -658,7 +658,7 @@ void CHud::RenderCursor()
// render cursor // render cursor
int CurWeapon = m_pClient->m_Snap.m_pLocalCharacter->m_Weapon % NUM_WEAPONS; int CurWeapon = m_pClient->m_Snap.m_pLocalCharacter->m_Weapon % NUM_WEAPONS;
Graphics()->SetColor(1.f, 1.f, 1.f, 1.f); Graphics()->SetColor(1.f, 1.f, 1.f, 1.f);
Graphics()->TextureSet(m_pClient->m_GameSkin.m_SpriteWeaponCursors[CurWeapon]); Graphics()->TextureSet(m_pClient->m_GameSkin.m_aSpriteWeaponCursors[CurWeapon]);
Graphics()->RenderQuadContainerAsSprite(m_HudQuadContainerIndex, m_CursorOffset[CurWeapon], m_pClient->m_Controls.m_TargetPos[g_Config.m_ClDummy].x, m_pClient->m_Controls.m_TargetPos[g_Config.m_ClDummy].y); Graphics()->RenderQuadContainerAsSprite(m_HudQuadContainerIndex, m_CursorOffset[CurWeapon], m_pClient->m_Controls.m_TargetPos[g_Config.m_ClDummy].x, m_pClient->m_Controls.m_TargetPos[g_Config.m_ClDummy].y);
} }
@ -673,7 +673,7 @@ void CHud::PrepareAmmoHealthAndArmorQuads()
{ {
// 0.6 // 0.6
for(int n = 0; n < 10; n++) for(int n = 0; n < 10; n++)
Array[n] = IGraphics::CQuadItem(x + n * 12, y + 24, 10, 10); Array[n] = IGraphics::CQuadItem(x + n * 12, y, 10, 10);
m_AmmoOffset[i] = Graphics()->QuadContainerAddQuads(m_HudQuadContainerIndex, Array, 10); m_AmmoOffset[i] = Graphics()->QuadContainerAddQuads(m_HudQuadContainerIndex, Array, 10);
@ -682,12 +682,12 @@ void CHud::PrepareAmmoHealthAndArmorQuads()
{ {
// special case for 0.7 grenade // special case for 0.7 grenade
for(int n = 0; n < 10; n++) for(int n = 0; n < 10; n++)
Array[n] = IGraphics::CQuadItem(1 + x + n * 12, y + 24, 10, 10); Array[n] = IGraphics::CQuadItem(1 + x + n * 12, y, 10, 10);
} }
else else
{ {
for(int n = 0; n < 10; n++) for(int n = 0; n < 10; n++)
Array[n] = IGraphics::CQuadItem(x + n * 12, y + 24, 12, 12); Array[n] = IGraphics::CQuadItem(x + n * 12, y, 12, 12);
} }
Graphics()->QuadContainerAddQuads(m_HudQuadContainerIndex, Array, 10); Graphics()->QuadContainerAddQuads(m_HudQuadContainerIndex, Array, 10);
@ -742,14 +742,27 @@ void CHud::RenderAmmoHealthAndArmor(const CNetObj_Character *pCharacter)
bool IsSixupGameSkin = m_pClient->m_GameSkin.IsSixup(); bool IsSixupGameSkin = m_pClient->m_GameSkin.IsSixup();
int QuadOffsetSixup = (IsSixupGameSkin ? 10 : 0); int QuadOffsetSixup = (IsSixupGameSkin ? 10 : 0);
// ammo display if(GameClient()->m_GameInfo.m_HudAmmo)
int CurWeapon = pCharacter->m_Weapon % NUM_WEAPONS; {
if(m_pClient->m_GameSkin.m_SpriteWeaponProjectiles[CurWeapon].IsValid()) // ammo display
float AmmoOffsetY = GameClient()->m_GameInfo.m_HudHealthArmor ? 24 : 0;
int CurWeapon = pCharacter->m_Weapon % NUM_WEAPONS;
if(m_pClient->m_GameSkin.m_aSpriteWeaponProjectiles[CurWeapon].IsValid())
{
Graphics()->TextureSet(m_pClient->m_GameSkin.m_aSpriteWeaponProjectiles[CurWeapon]);
if(AmmoOffsetY > 0)
{
Graphics()->RenderQuadContainerEx(m_HudQuadContainerIndex, m_AmmoOffset[CurWeapon] + QuadOffsetSixup, minimum(pCharacter->m_AmmoCount, 10), 0, AmmoOffsetY);
}
else
{ {
Graphics()->TextureSet(m_pClient->m_GameSkin.m_SpriteWeaponProjectiles[CurWeapon]);
Graphics()->RenderQuadContainer(m_HudQuadContainerIndex, m_AmmoOffset[CurWeapon] + QuadOffsetSixup, minimum(pCharacter->m_AmmoCount, 10)); Graphics()->RenderQuadContainer(m_HudQuadContainerIndex, m_AmmoOffset[CurWeapon] + QuadOffsetSixup, minimum(pCharacter->m_AmmoCount, 10));
} }
}
}
if(GameClient()->m_GameInfo.m_HudHealthArmor)
{
// health display // health display
Graphics()->TextureSet(m_pClient->m_GameSkin.m_SpriteHealthFull); Graphics()->TextureSet(m_pClient->m_GameSkin.m_SpriteHealthFull);
Graphics()->RenderQuadContainer(m_HudQuadContainerIndex, m_HealthOffset + QuadOffsetSixup, minimum(pCharacter->m_Health, 10)); Graphics()->RenderQuadContainer(m_HudQuadContainerIndex, m_HealthOffset + QuadOffsetSixup, minimum(pCharacter->m_Health, 10));
@ -762,6 +775,7 @@ void CHud::RenderAmmoHealthAndArmor(const CNetObj_Character *pCharacter)
Graphics()->TextureSet(m_pClient->m_GameSkin.m_SpriteArmorEmpty); Graphics()->TextureSet(m_pClient->m_GameSkin.m_SpriteArmorEmpty);
Graphics()->RenderQuadContainer(m_HudQuadContainerIndex, m_ArmorOffset + QuadOffsetSixup + minimum(pCharacter->m_Armor, 10), 10 - minimum(pCharacter->m_Armor, 10)); Graphics()->RenderQuadContainer(m_HudQuadContainerIndex, m_ArmorOffset + QuadOffsetSixup + minimum(pCharacter->m_Armor, 10), 10 - minimum(pCharacter->m_Armor, 10));
} }
}
void CHud::PreparePlayerStateQuads() void CHud::PreparePlayerStateQuads()
{ {
@ -807,6 +821,7 @@ void CHud::PreparePlayerStateQuads()
m_NoCollisionOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f); m_NoCollisionOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f);
m_NoHookHitOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f); m_NoHookHitOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f);
m_NoHammerHitOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f); m_NoHammerHitOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f);
m_NoGunHitOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f);
m_NoShotgunHitOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f); m_NoShotgunHitOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f);
m_NoGrenadeHitOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f); m_NoGrenadeHitOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f);
m_NoLaserHitOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f); m_NoLaserHitOffset = RenderTools()->QuadContainerAddSprite(m_HudQuadContainerIndex, 0.f, 0.f, 12.f, 12.f);
@ -829,8 +844,9 @@ void CHud::RenderPlayerState(const int ClientID)
// pCharacter contains the predicted character for local players or the last snap for players who are spectated // pCharacter contains the predicted character for local players or the last snap for players who are spectated
CCharacterCore *pCharacter = &m_pClient->m_aClients[ClientID].m_Predicted; CCharacterCore *pCharacter = &m_pClient->m_aClients[ClientID].m_Predicted;
int TotalJumpsToDisplay = 0, AvailableJumpsToDisplay = 0;
int TotalJumpsToDisplay, AvailableJumpsToDisplay; if(g_Config.m_ClShowJumpsIndicator)
{
if(m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo) if(m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo)
{ {
bool Grounded = false; bool Grounded = false;
@ -881,13 +897,27 @@ void CHud::RenderPlayerState(const int ClientID)
} }
// render available and used jumps // render available and used jumps
int JumpsOffsetY = ((GameClient()->m_GameInfo.m_HudHealthArmor && g_Config.m_ClShowhudHealthAmmo ? 24 : 0) +
(GameClient()->m_GameInfo.m_HudAmmo && g_Config.m_ClShowhudHealthAmmo ? 12 : 0));
if(JumpsOffsetY > 0)
{
Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudAirjump);
Graphics()->RenderQuadContainerEx(m_HudQuadContainerIndex, m_AirjumpOffset, AvailableJumpsToDisplay, 0, JumpsOffsetY);
Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudAirjumpEmpty);
Graphics()->RenderQuadContainerEx(m_HudQuadContainerIndex, m_AirjumpEmptyOffset + AvailableJumpsToDisplay, TotalJumpsToDisplay - AvailableJumpsToDisplay, 0, JumpsOffsetY);
}
else
{
Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudAirjump); Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudAirjump);
Graphics()->RenderQuadContainer(m_HudQuadContainerIndex, m_AirjumpOffset, AvailableJumpsToDisplay); Graphics()->RenderQuadContainer(m_HudQuadContainerIndex, m_AirjumpOffset, AvailableJumpsToDisplay);
Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudAirjumpEmpty); Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudAirjumpEmpty);
Graphics()->RenderQuadContainer(m_HudQuadContainerIndex, m_AirjumpEmptyOffset + AvailableJumpsToDisplay, TotalJumpsToDisplay - AvailableJumpsToDisplay); Graphics()->RenderQuadContainer(m_HudQuadContainerIndex, m_AirjumpEmptyOffset + AvailableJumpsToDisplay, TotalJumpsToDisplay - AvailableJumpsToDisplay);
}
}
float x = 5 + 12; float x = 5 + 12;
float y = 5 + 12; float y = (5 + 12 + (GameClient()->m_GameInfo.m_HudHealthArmor && g_Config.m_ClShowhudHealthAmmo ? 24 : 0) +
(GameClient()->m_GameInfo.m_HudAmmo && g_Config.m_ClShowhudHealthAmmo ? 12 : 0));
// render weapons // render weapons
if(pCharacter->m_aWeapons[WEAPON_HAMMER].m_Got) if(pCharacter->m_aWeapons[WEAPON_HAMMER].m_Got)
@ -1062,6 +1092,13 @@ void CHud::RenderPlayerState(const int ClientID)
Graphics()->RenderQuadContainerAsSprite(m_HudQuadContainerIndex, m_NoHammerHitOffset, x, y); Graphics()->RenderQuadContainerAsSprite(m_HudQuadContainerIndex, m_NoHammerHitOffset, x, y);
x += 12; x += 12;
} }
if((pCharacter->m_NoGrenadeHit && pCharacter->m_HasTelegunGun && pCharacter->m_aWeapons[WEAPON_GUN].m_Got))
{
HasProhibitedCapabilities = true;
Graphics()->TextureSet(m_pClient->m_HudSkin.m_SpriteHudNoGunHit);
Graphics()->RenderQuadContainerAsSprite(m_HudQuadContainerIndex, m_NoLaserHitOffset, x, y);
x += 12;
}
if((pCharacter->m_NoShotgunHit && pCharacter->m_aWeapons[WEAPON_SHOTGUN].m_Got)) if((pCharacter->m_NoShotgunHit && pCharacter->m_aWeapons[WEAPON_SHOTGUN].m_Got))
{ {
HasProhibitedCapabilities = true; HasProhibitedCapabilities = true;
@ -1266,8 +1303,8 @@ void CHud::RenderDummyActions()
return; return;
} }
// render small dummy actions hud // render small dummy actions hud
const float BoxHeight = 27.0f; const float BoxHeight = 29.0f;
const float BoxWidth = 14.0f; const float BoxWidth = 16.0f;
float StartX = m_Width - BoxWidth; float StartX = m_Width - BoxWidth;
float StartY = 285.0f - BoxHeight - 4; // 4 units distance to the next display; float StartY = 285.0f - BoxHeight - 4; // 4 units distance to the next display;
@ -1289,8 +1326,8 @@ void CHud::RenderDummyActions()
Graphics()->QuadsEnd(); Graphics()->QuadsEnd();
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
float y = StartY + 1; float y = StartY + 2;
float x = StartX + 1; float x = StartX + 2;
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.4f); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.4f);
if(g_Config.m_ClDummyHammer) if(g_Config.m_ClDummyHammer)
{ {
@ -1390,17 +1427,21 @@ void CHud::RenderMovementInformation(const int ClientID)
DisplaySpeedX *= (m_pClient->m_Snap.m_aCharacters[ClientID].m_ExtendedDisplayInfo.m_RampValue / 1000.0f); DisplaySpeedX *= (m_pClient->m_Snap.m_aCharacters[ClientID].m_ExtendedDisplayInfo.m_RampValue / 1000.0f);
} }
float Angle = Character->m_Angle / 256.0f; float Angle = 0.0f;
if(Angle > pi)
{
Angle -= 2.0f * pi;
}
if(m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo) if(m_pClient->m_Snap.m_aCharacters[ClientID].m_HasExtendedDisplayInfo)
{ {
// On DDNet servers the more accurate angle is displayed, calculated from the target coordinates // On DDNet servers the more accurate angle is displayed, calculated from the target coordinates
CNetObj_DDNetCharacterDisplayInfo *CharacterDisplayInfo = &m_pClient->m_Snap.m_aCharacters[ClientID].m_ExtendedDisplayInfo; CNetObj_DDNetCharacterDisplayInfo *CharacterDisplayInfo = &m_pClient->m_Snap.m_aCharacters[ClientID].m_ExtendedDisplayInfo;
Angle = atan2f(CharacterDisplayInfo->m_TargetY, CharacterDisplayInfo->m_TargetX); Angle = atan2f(CharacterDisplayInfo->m_TargetY, CharacterDisplayInfo->m_TargetX);
} }
else
{
Angle = Character->m_Angle / 256.0f;
}
if(Angle < 0)
{
Angle += 2.0f * pi;
}
float DisplayAngle = Angle * 180.0f / pi; float DisplayAngle = Angle * 180.0f / pi;
char aBuf[128]; char aBuf[128];
@ -1528,11 +1569,11 @@ void CHud::OnRender()
{ {
if(m_pClient->m_Snap.m_pLocalCharacter && !m_pClient->m_Snap.m_SpecInfo.m_Active && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags & GAMESTATEFLAG_GAMEOVER)) if(m_pClient->m_Snap.m_pLocalCharacter && !m_pClient->m_Snap.m_SpecInfo.m_Active && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags & GAMESTATEFLAG_GAMEOVER))
{ {
if(g_Config.m_ClShowhudHealthAmmo && (!m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_LocalClientID].m_HasExtendedData || !g_Config.m_ClDDRaceHud)) if(g_Config.m_ClShowhudHealthAmmo)
{ {
RenderAmmoHealthAndArmor(m_pClient->m_Snap.m_pLocalCharacter); RenderAmmoHealthAndArmor(m_pClient->m_Snap.m_pLocalCharacter);
} }
if(m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_LocalClientID].m_HasExtendedData && g_Config.m_ClDDRaceHud) if(m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_LocalClientID].m_HasExtendedData && g_Config.m_ClDDRaceHud && GameClient()->m_GameInfo.m_HudDDRace)
{ {
RenderPlayerState(m_pClient->m_Snap.m_LocalClientID); RenderPlayerState(m_pClient->m_Snap.m_LocalClientID);
} }
@ -1542,11 +1583,11 @@ void CHud::OnRender()
else if(m_pClient->m_Snap.m_SpecInfo.m_Active) else if(m_pClient->m_Snap.m_SpecInfo.m_Active)
{ {
int SpectatorID = m_pClient->m_Snap.m_SpecInfo.m_SpectatorID; int SpectatorID = m_pClient->m_Snap.m_SpecInfo.m_SpectatorID;
if(SpectatorID != SPEC_FREEVIEW && g_Config.m_ClShowhudHealthAmmo && (!m_pClient->m_Snap.m_aCharacters[SpectatorID].m_HasExtendedData || !g_Config.m_ClDDRaceHud)) if(SpectatorID != SPEC_FREEVIEW && g_Config.m_ClShowhudHealthAmmo)
{ {
RenderAmmoHealthAndArmor(&m_pClient->m_Snap.m_aCharacters[SpectatorID].m_Cur); RenderAmmoHealthAndArmor(&m_pClient->m_Snap.m_aCharacters[SpectatorID].m_Cur);
} }
if(SpectatorID != SPEC_FREEVIEW && m_pClient->m_Snap.m_aCharacters[SpectatorID].m_HasExtendedData && g_Config.m_ClDDRaceHud) if(SpectatorID != SPEC_FREEVIEW && m_pClient->m_Snap.m_aCharacters[SpectatorID].m_HasExtendedData && g_Config.m_ClDDRaceHud && GameClient()->m_GameInfo.m_HudDDRace)
{ {
RenderPlayerState(SpectatorID); RenderPlayerState(SpectatorID);
} }

View file

@ -123,6 +123,7 @@ private:
int m_NoCollisionOffset; int m_NoCollisionOffset;
int m_NoHookHitOffset; int m_NoHookHitOffset;
int m_NoHammerHitOffset; int m_NoHammerHitOffset;
int m_NoGunHitOffset;
int m_NoShotgunHitOffset; int m_NoShotgunHitOffset;
int m_NoGrenadeHitOffset; int m_NoGrenadeHitOffset;
int m_NoLaserHitOffset; int m_NoLaserHitOffset;

View file

@ -128,9 +128,9 @@ void CItems::RenderProjectile(const CProjectileData *pCurrent, int ItemID)
Graphics()->QuadsSetRotation(0); Graphics()->QuadsSetRotation(0);
} }
if(GameClient()->m_GameSkin.m_SpriteWeaponProjectiles[CurWeapon].IsValid()) if(GameClient()->m_GameSkin.m_aSpriteWeaponProjectiles[CurWeapon].IsValid())
{ {
Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteWeaponProjectiles[CurWeapon]); Graphics()->TextureSet(GameClient()->m_GameSkin.m_aSpriteWeaponProjectiles[CurWeapon]);
Graphics()->SetColor(1.f, 1.f, 1.f, Alpha); Graphics()->SetColor(1.f, 1.f, 1.f, Alpha);
Graphics()->RenderQuadContainerAsSprite(m_ItemsQuadContainerIndex, m_ProjectileOffset[CurWeapon], Pos.x, Pos.y); Graphics()->RenderQuadContainerAsSprite(m_ItemsQuadContainerIndex, m_ProjectileOffset[CurWeapon], Pos.x, Pos.y);
} }
@ -156,7 +156,7 @@ void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCu
else if(pCurrent->m_Type == POWERUP_WEAPON) else if(pCurrent->m_Type == POWERUP_WEAPON)
{ {
QuadOffset = m_PickupWeaponOffset[CurWeapon]; QuadOffset = m_PickupWeaponOffset[CurWeapon];
Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpritePickupWeapons[CurWeapon]); Graphics()->TextureSet(GameClient()->m_GameSkin.m_aSpritePickupWeapons[CurWeapon]);
} }
else if(pCurrent->m_Type == POWERUP_NINJA) else if(pCurrent->m_Type == POWERUP_NINJA)
{ {
@ -168,7 +168,7 @@ void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCu
else if(pCurrent->m_Type >= POWERUP_ARMOR_SHOTGUN && pCurrent->m_Type <= POWERUP_ARMOR_LASER) else if(pCurrent->m_Type >= POWERUP_ARMOR_SHOTGUN && pCurrent->m_Type <= POWERUP_ARMOR_LASER)
{ {
QuadOffset = m_PickupWeaponArmorOffset[pCurrent->m_Type - POWERUP_ARMOR_SHOTGUN]; QuadOffset = m_PickupWeaponArmorOffset[pCurrent->m_Type - POWERUP_ARMOR_SHOTGUN];
Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpritePickupWeaponArmor[pCurrent->m_Type - POWERUP_ARMOR_SHOTGUN]); Graphics()->TextureSet(GameClient()->m_GameSkin.m_aSpritePickupWeaponArmor[pCurrent->m_Type - POWERUP_ARMOR_SHOTGUN]);
} }
Graphics()->QuadsSetRotation(0); Graphics()->QuadsSetRotation(0);
Graphics()->SetColor(1.f, 1.f, 1.f, 1.f); Graphics()->SetColor(1.f, 1.f, 1.f, 1.f);
@ -298,7 +298,7 @@ void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent, bool IsPredicted)
// render head // render head
{ {
int CurParticle = (Client()->GameTick(g_Config.m_ClDummy) % 3); int CurParticle = (Client()->GameTick(g_Config.m_ClDummy) % 3);
Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_SpriteParticleSplat[CurParticle]); Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_aSpriteParticleSplat[CurParticle]);
Graphics()->QuadsSetRotation(Client()->GameTick(g_Config.m_ClDummy)); Graphics()->QuadsSetRotation(Client()->GameTick(g_Config.m_ClDummy));
Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f); Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f);
Graphics()->RenderQuadContainerAsSprite(m_ItemsQuadContainerIndex, m_ParticleSplatOffset[CurParticle], Pos.x, Pos.y); Graphics()->RenderQuadContainerAsSprite(m_ItemsQuadContainerIndex, m_ParticleSplatOffset[CurParticle], Pos.x, Pos.y);

View file

@ -254,7 +254,7 @@ void CKillMessages::OnRender()
x -= 44.0f; x -= 44.0f;
if(m_aKillmsgs[r].m_Weapon >= 0) if(m_aKillmsgs[r].m_Weapon >= 0)
{ {
Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteWeapons[m_aKillmsgs[r].m_Weapon]); Graphics()->TextureSet(GameClient()->m_GameSkin.m_aSpriteWeapons[m_aKillmsgs[r].m_Weapon]);
Graphics()->RenderQuadContainerAsSprite(m_SpriteQuadContainerIndex, 4 + m_aKillmsgs[r].m_Weapon, x, y + 28); Graphics()->RenderQuadContainerAsSprite(m_SpriteQuadContainerIndex, 4 + m_aKillmsgs[r].m_Weapon, x, y + 28);
} }
x -= 52.0f; x -= 52.0f;

View file

@ -346,7 +346,7 @@ void CMenus::DoLaserPreview(const CUIRect *pRect, const ColorHSLA LaserOutlineCo
Graphics()->BlendNormal(); Graphics()->BlendNormal();
int SpriteIndex = time_get() % 3; int SpriteIndex = time_get() % 3;
Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_SpriteParticleSplat[SpriteIndex]); Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_aSpriteParticleSplat[SpriteIndex]);
Graphics()->QuadsBegin(); Graphics()->QuadsBegin();
Graphics()->QuadsSetRotation(time_get()); Graphics()->QuadsSetRotation(time_get());
Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f); Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f);
@ -999,6 +999,7 @@ void CMenus::OnInit()
Console()->Chain("cl_asset_emoticons", ConchainAssetEmoticons, this); Console()->Chain("cl_asset_emoticons", ConchainAssetEmoticons, this);
Console()->Chain("cl_asset_particles", ConchainAssetParticles, this); Console()->Chain("cl_asset_particles", ConchainAssetParticles, this);
Console()->Chain("cl_asset_hud", ConchainAssetHud, this); Console()->Chain("cl_asset_hud", ConchainAssetHud, this);
Console()->Chain("cl_asset_extras", ConchainAssetExtras, this);
m_TextureBlob = Graphics()->LoadTexture("blob.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0); m_TextureBlob = Graphics()->LoadTexture("blob.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0);

View file

@ -256,12 +256,17 @@ public:
{ {
}; };
struct SCustomExtras : public SCustomItem
{
};
protected: protected:
std::vector<SCustomEntities> m_vEntitiesList; std::vector<SCustomEntities> m_vEntitiesList;
std::vector<SCustomGame> m_vGameList; std::vector<SCustomGame> m_vGameList;
std::vector<SCustomEmoticon> m_vEmoticonList; std::vector<SCustomEmoticon> m_vEmoticonList;
std::vector<SCustomParticle> m_vParticlesList; std::vector<SCustomParticle> m_vParticlesList;
std::vector<SCustomHud> m_vHudList; std::vector<SCustomHud> m_vHudList;
std::vector<SCustomExtras> m_vExtrasList;
bool m_IsInit = false; bool m_IsInit = false;
@ -272,12 +277,14 @@ protected:
static int EmoticonsScan(const char *pName, int IsDir, int DirType, void *pUser); static int EmoticonsScan(const char *pName, int IsDir, int DirType, void *pUser);
static int ParticlesScan(const char *pName, int IsDir, int DirType, void *pUser); static int ParticlesScan(const char *pName, int IsDir, int DirType, void *pUser);
static int HudScan(const char *pName, int IsDir, int DirType, void *pUser); static int HudScan(const char *pName, int IsDir, int DirType, void *pUser);
static int ExtrasScan(const char *pName, int IsDir, int DirType, void *pUser);
static void ConchainAssetsEntities(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainAssetsEntities(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainAssetGame(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainAssetGame(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainAssetParticles(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainAssetParticles(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainAssetEmoticons(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainAssetEmoticons(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainAssetHud(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData); static void ConchainAssetHud(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainAssetExtras(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
void ClearCustomItems(int CurTab); void ClearCustomItems(int CurTab);

View file

@ -1041,7 +1041,7 @@ void CMenus::RenderGhost(CUIRect MainView)
if(pItem->Active()) if(pItem->Active())
{ {
Graphics()->WrapClamp(); Graphics()->WrapClamp();
Graphics()->TextureSet(GameClient()->m_EmoticonsSkin.m_SpriteEmoticons[(SPRITE_OOP + 7) - SPRITE_OOP]); Graphics()->TextureSet(GameClient()->m_EmoticonsSkin.m_aSpriteEmoticons[(SPRITE_OOP + 7) - SPRITE_OOP]);
Graphics()->QuadsBegin(); Graphics()->QuadsBegin();
IGraphics::CQuadItem QuadItem(Button.x + Button.w / 2, Button.y + Button.h / 2, 20.0f, 20.0f); IGraphics::CQuadItem QuadItem(Button.x + Button.w / 2, Button.y + Button.h / 2, 20.0f, 20.0f);
Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsDraw(&QuadItem, 1);

View file

@ -2508,6 +2508,7 @@ ColorHSLA CMenus::RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool
void CMenus::RenderSettingsHUD(CUIRect MainView) void CMenus::RenderSettingsHUD(CUIRect MainView)
{ {
char aBuf[128];
static int s_CurTab = 0; static int s_CurTab = 0;
CUIRect TabLabel1, TabLabel2, Column, CUIRect TabLabel1, TabLabel2, Column,
@ -2540,10 +2541,9 @@ void CMenus::RenderSettingsHUD(CUIRect MainView)
// ***** HUD ***** // // ***** HUD ***** //
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowhud, Localize("Show ingame HUD"), &g_Config.m_ClShowhud, &MainView, LineMargin); DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowhud, Localize("Show ingame HUD"), &g_Config.m_ClShowhud, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClDDRaceHud, Localize("Use DDRace HUD"), &g_Config.m_ClDDRaceHud, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClDDRaceScoreBoard, Localize("Use DDRace Scoreboard"), &g_Config.m_ClDDRaceScoreBoard, &MainView, LineMargin); DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClDDRaceScoreBoard, Localize("Use DDRace Scoreboard"), &g_Config.m_ClDDRaceScoreBoard, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowhudDummyActions, Localize("Show dummy actions"), &g_Config.m_ClShowhudDummyActions, &MainView, LineMargin); DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowhudDummyActions, Localize("Show dummy actions"), &g_Config.m_ClShowhudDummyActions, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowFreezeBars, Localize("Show freeze bars"), &g_Config.m_ClShowFreezeBars, &MainView, LineMargin); DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowJumpsIndicator, Localize("Show jump indicator"), &g_Config.m_ClShowJumpsIndicator, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowIDs, Localize("Show client IDs"), &g_Config.m_ClShowIDs, &MainView, LineMargin); DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowIDs, Localize("Show client IDs"), &g_Config.m_ClShowIDs, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowhudPlayerPosition, Localize("Show player position"), &g_Config.m_ClShowhudPlayerPosition, &MainView, LineMargin); DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowhudPlayerPosition, Localize("Show player position"), &g_Config.m_ClShowhudPlayerPosition, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowhudPlayerSpeed, Localize("Show player speed"), &g_Config.m_ClShowhudPlayerSpeed, &MainView, LineMargin); DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowhudPlayerSpeed, Localize("Show player speed"), &g_Config.m_ClShowhudPlayerSpeed, &MainView, LineMargin);
@ -2554,22 +2554,21 @@ void CMenus::RenderSettingsHUD(CUIRect MainView)
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClChatTeamColors, Localize("Show names in chat in team colors"), &g_Config.m_ClChatTeamColors, &MainView, LineMargin); DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClChatTeamColors, Localize("Show names in chat in team colors"), &g_Config.m_ClChatTeamColors, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowVotesAfterVoting, Localize("Show votes window after voting"), &g_Config.m_ClShowVotesAfterVoting, &MainView, LineMargin); DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowVotesAfterVoting, Localize("Show votes window after voting"), &g_Config.m_ClShowVotesAfterVoting, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowKillMessages, Localize("Show kill messages"), &g_Config.m_ClShowKillMessages, &MainView, LineMargin); DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowKillMessages, Localize("Show kill messages"), &g_Config.m_ClShowKillMessages, &MainView, LineMargin);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowFreezeBars, Localize("Show freeze bars"), &g_Config.m_ClShowFreezeBars, &MainView, LineMargin);
{
if(g_Config.m_ClShowFreezeBars)
{
CUIRect Button, Label;
MainView.HSplitTop(2.5f, 0, &MainView);
MainView.HSplitTop(20.0f, &Label, &MainView);
MainView.HSplitTop(20.0f, &Button, &MainView);
str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Opacity of freeze bars inside freeze"), g_Config.m_ClFreezeBarsAlphaInsideFreeze);
UI()->DoLabel(&Label, aBuf, 13.0f, TEXTALIGN_LEFT);
g_Config.m_ClFreezeBarsAlphaInsideFreeze = (int)(UIEx()->DoScrollbarH(&g_Config.m_ClFreezeBarsAlphaInsideFreeze, &Button, g_Config.m_ClFreezeBarsAlphaInsideFreeze / 100.0f) * 100.0f);
}
}
MainView.HSplitTop(60.0f, 0x0, &MainView); MainView.HSplitTop(30.0f, 0x0, &MainView);
// ***** Kill Messages ***** //
MainView.HSplitTop(30.0f, &Section, &MainView);
UI()->DoLabel(&Section, Localize("Kill Messages"), 20.0f, TEXTALIGN_LEFT);
MainView.VSplitLeft(5.0f, 0x0, &MainView);
MainView.HSplitTop(10.0f, 0x0, &MainView);
static int KillMessageNormalColorID;
DoLine_ColorPicker(&KillMessageNormalColorID, 25.0f, 250.0f, 13.0f, 5.0f, &MainView, Localize("Kill Message Normal Color"), &g_Config.m_ClKillMessageNormalColor, ColorRGBA(1.0f, 1.0f, 1.0f), false);
static int KillMessageHighlightColorID;
DoLine_ColorPicker(&KillMessageHighlightColorID, 25.0f, 250.0f, 13.0f, 5.0f, &MainView, Localize("Kill Message Highlight Color"), &g_Config.m_ClKillMessageHighlightColor, ColorRGBA(1.0f, 1.0f, 1.0f), false);
// ***** Laser ***** // // ***** Laser ***** //
@ -2597,6 +2596,8 @@ void CMenus::RenderSettingsHUD(CUIRect MainView)
DoLaserPreview(&Section, LaserOutlineColor, LaserInnerColor); DoLaserPreview(&Section, LaserOutlineColor, LaserInnerColor);
// ***** Hookline ***** //
MainView.HSplitTop(25.0f, 0x0, &MainView); MainView.HSplitTop(25.0f, 0x0, &MainView);
MainView.HSplitTop(20.0f, &SectionTwo, &MainView); MainView.HSplitTop(20.0f, &SectionTwo, &MainView);
@ -2636,6 +2637,23 @@ void CMenus::RenderSettingsHUD(CUIRect MainView)
MainView.HSplitTop(25.0f, &SectionTwo, &MainView); MainView.HSplitTop(25.0f, &SectionTwo, &MainView);
DoLine_ColorPicker(&HookCollTeeCollResetID, 25.0f, 180.0f, 13.0f, 5.0f, &SectionTwo, Localize("Tee"), &g_Config.m_ClHookCollColorTeeColl, ColorRGBA(1.0f, 1.0f, 0.0f, 1.0f), false); DoLine_ColorPicker(&HookCollTeeCollResetID, 25.0f, 180.0f, 13.0f, 5.0f, &SectionTwo, Localize("Tee"), &g_Config.m_ClHookCollColorTeeColl, ColorRGBA(1.0f, 1.0f, 0.0f, 1.0f), false);
// ***** Kill Messages ***** //
MainView.HSplitTop(25.0f, 0x0, &MainView);
MainView.HSplitTop(20.0f, &Section, &MainView);
UI()->DoLabel(&Section, Localize("Kill Messages"), 20.0f, TEXTALIGN_LEFT);
MainView.HSplitTop(5.0f, 0x0, &MainView);
MainView.HSplitTop(25.0f, &SectionTwo, &MainView);
static int KillMessageNormalColorID, KillMessageHighlightColorID;
DoLine_ColorPicker(&KillMessageNormalColorID, 25.0f, 180.0f, 13.0f, 5.0f, &SectionTwo, Localize("Normal Color"), &g_Config.m_ClKillMessageNormalColor, ColorRGBA(1.0f, 1.0f, 1.0f), false);
MainView.HSplitTop(5.0f, 0x0, &MainView);
MainView.HSplitTop(25.0f, &SectionTwo, &MainView);
DoLine_ColorPicker(&KillMessageHighlightColorID, 25.0f, 180.0f, 13.0f, 5.0f, &SectionTwo, Localize("Highlight Color"), &g_Config.m_ClKillMessageHighlightColor, ColorRGBA(1.0f, 1.0f, 1.0f), false);
} }
else if(s_CurTab == 1) else if(s_CurTab == 1)
{ // ***** CHAT TAB ***** // { // ***** CHAT TAB ***** //
@ -2659,8 +2677,6 @@ void CMenus::RenderSettingsHUD(CUIRect MainView)
const float LabelSize = 13.0f; const float LabelSize = 13.0f;
const float LineSpacing = 5.0f; const float LineSpacing = 5.0f;
char aBuf[64];
int i = 0; int i = 0;
static int ResetIDs[24]; static int ResetIDs[24];

View file

@ -27,7 +27,8 @@ enum
ASSETS_TAB_GAME = 1, ASSETS_TAB_GAME = 1,
ASSETS_TAB_EMOTICONS = 2, ASSETS_TAB_EMOTICONS = 2,
ASSETS_TAB_PARTICLES = 3, ASSETS_TAB_PARTICLES = 3,
ASSETS_TAB_HUD = 4 ASSETS_TAB_HUD = 4,
ASSETS_TAB_EXTRAS = 5
}; };
void CMenus::LoadEntities(SCustomEntities *pEntitiesItem, void *pUser) void CMenus::LoadEntities(SCustomEntities *pEntitiesItem, void *pUser)
@ -231,13 +232,22 @@ int CMenus::HudScan(const char *pName, int IsDir, int DirType, void *pUser)
return AssetScan(pName, IsDir, DirType, pThis->m_vHudList, "hud", pGraphics, pUser); return AssetScan(pName, IsDir, DirType, pThis->m_vHudList, "hud", pGraphics, pUser);
} }
int CMenus::ExtrasScan(const char *pName, int IsDir, int DirType, void *pUser)
{
auto *pRealUser = (SMenuAssetScanUser *)pUser;
auto *pThis = (CMenus *)pRealUser->m_pUser;
IGraphics *pGraphics = pThis->Graphics();
return AssetScan(pName, IsDir, DirType, pThis->m_vExtrasList, "extras", pGraphics, pUser);
}
static std::vector<const CMenus::SCustomEntities *> s_vpSearchEntitiesList; static std::vector<const CMenus::SCustomEntities *> s_vpSearchEntitiesList;
static std::vector<const CMenus::SCustomGame *> s_vpSearchGamesList; static std::vector<const CMenus::SCustomGame *> s_vpSearchGamesList;
static std::vector<const CMenus::SCustomEmoticon *> s_vpSearchEmoticonsList; static std::vector<const CMenus::SCustomEmoticon *> s_vpSearchEmoticonsList;
static std::vector<const CMenus::SCustomParticle *> s_vpSearchParticlesList; static std::vector<const CMenus::SCustomParticle *> s_vpSearchParticlesList;
static std::vector<const CMenus::SCustomHud *> s_vpSearchHudList; static std::vector<const CMenus::SCustomHud *> s_vpSearchHudList;
static std::vector<const CMenus::SCustomExtras *> s_vpSearchExtrasList;
static const int NumberOfAssetsTabs = 5; static const int NumberOfAssetsTabs = 6;
static bool s_InitCustomList[NumberOfAssetsTabs] = { static bool s_InitCustomList[NumberOfAssetsTabs] = {
true, true,
}; };
@ -262,6 +272,8 @@ static const CMenus::SCustomItem *GetCustomItem(int CurTab, size_t Index)
return s_vpSearchParticlesList[Index]; return s_vpSearchParticlesList[Index];
else if(CurTab == ASSETS_TAB_HUD) else if(CurTab == ASSETS_TAB_HUD)
return s_vpSearchHudList[Index]; return s_vpSearchHudList[Index];
else if(CurTab == ASSETS_TAB_EXTRAS)
return s_vpSearchExtrasList[Index];
return NULL; return NULL;
} }
@ -324,6 +336,13 @@ void CMenus::ClearCustomItems(int CurTab)
// reload current hud skin // reload current hud skin
GameClient()->LoadHudSkin(g_Config.m_ClAssetHud); GameClient()->LoadHudSkin(g_Config.m_ClAssetHud);
} }
else if(CurTab == ASSETS_TAB_EXTRAS)
{
ClearAssetList(m_vExtrasList, Graphics());
// reload current DDNet particles skin
GameClient()->LoadExtrasSkin(g_Config.m_ClAssetExtras);
}
s_InitCustomList[CurTab] = true; s_InitCustomList[CurTab] = true;
} }
@ -365,7 +384,7 @@ int InitSearchList(std::vector<const TName *> &vpSearchList, std::vector<TName>
void CMenus::RenderSettingsCustom(CUIRect MainView) void CMenus::RenderSettingsCustom(CUIRect MainView)
{ {
CUIRect Label, CustomList, QuickSearch, QuickSearchClearButton, DirectoryButton, Page1Tab, Page2Tab, Page3Tab, Page4Tab, Page5Tab, ReloadButton; CUIRect Label, CustomList, QuickSearch, QuickSearchClearButton, DirectoryButton, Page1Tab, Page2Tab, Page3Tab, Page4Tab, Page5Tab, Page6Tab, ReloadButton;
MainView.HSplitTop(20, &Label, &MainView); MainView.HSplitTop(20, &Label, &MainView);
float TabsW = Label.w; float TabsW = Label.w;
@ -373,6 +392,7 @@ void CMenus::RenderSettingsCustom(CUIRect MainView)
Page2Tab.VSplitLeft(TabsW / NumberOfAssetsTabs, &Page2Tab, &Page3Tab); Page2Tab.VSplitLeft(TabsW / NumberOfAssetsTabs, &Page2Tab, &Page3Tab);
Page3Tab.VSplitLeft(TabsW / NumberOfAssetsTabs, &Page3Tab, &Page4Tab); Page3Tab.VSplitLeft(TabsW / NumberOfAssetsTabs, &Page3Tab, &Page4Tab);
Page4Tab.VSplitLeft(TabsW / NumberOfAssetsTabs, &Page4Tab, &Page5Tab); Page4Tab.VSplitLeft(TabsW / NumberOfAssetsTabs, &Page4Tab, &Page5Tab);
Page5Tab.VSplitLeft(TabsW / NumberOfAssetsTabs, &Page5Tab, &Page6Tab);
static int s_aPageTabs[NumberOfAssetsTabs] = {}; static int s_aPageTabs[NumberOfAssetsTabs] = {};
@ -384,8 +404,10 @@ void CMenus::RenderSettingsCustom(CUIRect MainView)
s_CurCustomTab = ASSETS_TAB_EMOTICONS; s_CurCustomTab = ASSETS_TAB_EMOTICONS;
if(DoButton_MenuTab((void *)&s_aPageTabs[3], Localize("Particles"), s_CurCustomTab == ASSETS_TAB_PARTICLES, &Page4Tab, 0, NULL, NULL, NULL, NULL, 4)) if(DoButton_MenuTab((void *)&s_aPageTabs[3], Localize("Particles"), s_CurCustomTab == ASSETS_TAB_PARTICLES, &Page4Tab, 0, NULL, NULL, NULL, NULL, 4))
s_CurCustomTab = ASSETS_TAB_PARTICLES; s_CurCustomTab = ASSETS_TAB_PARTICLES;
if(DoButton_MenuTab((void *)&s_aPageTabs[4], Localize("HUD"), s_CurCustomTab == ASSETS_TAB_HUD, &Page5Tab, 10, NULL, NULL, NULL, NULL, 4)) if(DoButton_MenuTab((void *)&s_aPageTabs[4], Localize("HUD"), s_CurCustomTab == ASSETS_TAB_HUD, &Page5Tab, 0, NULL, NULL, NULL, NULL, 4))
s_CurCustomTab = ASSETS_TAB_HUD; s_CurCustomTab = ASSETS_TAB_HUD;
if(DoButton_MenuTab((void *)&s_aPageTabs[5], Localize("Extras"), s_CurCustomTab == ASSETS_TAB_EXTRAS, &Page6Tab, 10, NULL, NULL, NULL, NULL, 4))
s_CurCustomTab = ASSETS_TAB_EXTRAS;
auto LoadStartTime = time_get_nanoseconds(); auto LoadStartTime = time_get_nanoseconds();
SMenuAssetScanUser User; SMenuAssetScanUser User;
@ -426,6 +448,10 @@ void CMenus::RenderSettingsCustom(CUIRect MainView)
{ {
InitAssetList(m_vHudList, "assets/hud", "hud", HudScan, Graphics(), Storage(), &User); InitAssetList(m_vHudList, "assets/hud", "hud", HudScan, Graphics(), Storage(), &User);
} }
else if(s_CurCustomTab == ASSETS_TAB_EXTRAS)
{
InitAssetList(m_vExtrasList, "assets/extras", "extras", ExtrasScan, Graphics(), Storage(), &User);
}
MainView.HSplitTop(10.0f, 0, &MainView); MainView.HSplitTop(10.0f, 0, &MainView);
@ -466,6 +492,10 @@ void CMenus::RenderSettingsCustom(CUIRect MainView)
{ {
ListSize = InitSearchList(s_vpSearchHudList, m_vHudList); ListSize = InitSearchList(s_vpSearchHudList, m_vHudList);
} }
else if(s_CurCustomTab == ASSETS_TAB_EXTRAS)
{
ListSize = InitSearchList(s_vpSearchExtrasList, m_vExtrasList);
}
s_InitCustomList[s_CurCustomTab] = false; s_InitCustomList[s_CurCustomTab] = false;
s_CustomListSize[s_CurCustomTab] = ListSize; s_CustomListSize[s_CurCustomTab] = ListSize;
} }
@ -497,7 +527,10 @@ void CMenus::RenderSettingsCustom(CUIRect MainView)
else if(s_CurCustomTab == ASSETS_TAB_HUD) else if(s_CurCustomTab == ASSETS_TAB_HUD)
{ {
SearchListSize = s_vpSearchHudList.size(); SearchListSize = s_vpSearchHudList.size();
TextureHeight = 128; }
else if(s_CurCustomTab == ASSETS_TAB_EXTRAS)
{
SearchListSize = s_vpSearchExtrasList.size();
} }
UiDoListboxStart(&s_InitCustomList[s_CurCustomTab], &CustomList, TextureHeight + 15.0f + 10.0f + Margin, "", "", SearchListSize, CustomList.w / (Margin + TextureWidth), OldSelected, s_ScrollValue, true); UiDoListboxStart(&s_InitCustomList[s_CurCustomTab], &CustomList, TextureHeight + 15.0f + 10.0f + Margin, "", "", SearchListSize, CustomList.w / (Margin + TextureWidth), OldSelected, s_ScrollValue, true);
@ -532,6 +565,11 @@ void CMenus::RenderSettingsCustom(CUIRect MainView)
if(str_comp(s->m_aName, g_Config.m_ClAssetHud) == 0) if(str_comp(s->m_aName, g_Config.m_ClAssetHud) == 0)
OldSelected = i; OldSelected = i;
} }
else if(s_CurCustomTab == ASSETS_TAB_EXTRAS)
{
if(str_comp(s->m_aName, g_Config.m_ClAssetExtras) == 0)
OldSelected = i;
}
CListboxItem Item = UiDoListboxNextItem(s, OldSelected >= 0 && (size_t)OldSelected == i); CListboxItem Item = UiDoListboxNextItem(s, OldSelected >= 0 && (size_t)OldSelected == i);
CUIRect ItemRect = Item.m_Rect; CUIRect ItemRect = Item.m_Rect;
@ -586,6 +624,11 @@ void CMenus::RenderSettingsCustom(CUIRect MainView)
str_copy(g_Config.m_ClAssetHud, GetCustomItem(s_CurCustomTab, NewSelected)->m_aName, sizeof(g_Config.m_ClAssetHud)); str_copy(g_Config.m_ClAssetHud, GetCustomItem(s_CurCustomTab, NewSelected)->m_aName, sizeof(g_Config.m_ClAssetHud));
GameClient()->LoadHudSkin(g_Config.m_ClAssetHud); GameClient()->LoadHudSkin(g_Config.m_ClAssetHud);
} }
else if(s_CurCustomTab == ASSETS_TAB_EXTRAS)
{
str_copy(g_Config.m_ClAssetExtras, GetCustomItem(s_CurCustomTab, NewSelected)->m_aName, sizeof(g_Config.m_ClAssetExtras));
GameClient()->LoadExtrasSkin(g_Config.m_ClAssetExtras);
}
} }
} }
@ -639,6 +682,8 @@ void CMenus::RenderSettingsCustom(CUIRect MainView)
str_copy(aBufFull, "assets/particles", sizeof(aBufFull)); str_copy(aBufFull, "assets/particles", sizeof(aBufFull));
else if(s_CurCustomTab == ASSETS_TAB_HUD) else if(s_CurCustomTab == ASSETS_TAB_HUD)
str_copy(aBufFull, "assets/hud", sizeof(aBufFull)); str_copy(aBufFull, "assets/hud", sizeof(aBufFull));
else if(s_CurCustomTab == ASSETS_TAB_EXTRAS)
str_copy(aBufFull, "assets/extras", sizeof(aBufFull));
Storage()->GetCompletePath(IStorage::TYPE_SAVE, aBufFull, aBuf, sizeof(aBuf)); Storage()->GetCompletePath(IStorage::TYPE_SAVE, aBufFull, aBuf, sizeof(aBuf));
Storage()->CreateFolder("assets", IStorage::TYPE_SAVE); Storage()->CreateFolder("assets", IStorage::TYPE_SAVE);
Storage()->CreateFolder(aBufFull, IStorage::TYPE_SAVE); Storage()->CreateFolder(aBufFull, IStorage::TYPE_SAVE);
@ -733,3 +778,18 @@ void CMenus::ConchainAssetHud(IConsole::IResult *pResult, void *pUserData, ICons
pfnCallback(pResult, pCallbackUserData); pfnCallback(pResult, pCallbackUserData);
} }
void CMenus::ConchainAssetExtras(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
CMenus *pThis = (CMenus *)pUserData;
if(pResult->NumArguments() == 1)
{
const char *pArg = pResult->GetString(0);
if(str_comp(pArg, g_Config.m_ClAssetExtras) != 0)
{
pThis->GameClient()->LoadExtrasSkin(pArg);
}
}
pfnCallback(pResult, pCallbackUserData);
}

View file

@ -15,6 +15,7 @@ CParticles::CParticles()
OnReset(); OnReset();
m_RenderTrail.m_pParts = this; m_RenderTrail.m_pParts = this;
m_RenderExplosions.m_pParts = this; m_RenderExplosions.m_pParts = this;
m_RenderExtra.m_pParts = this;
m_RenderGeneral.m_pParts = this; m_RenderGeneral.m_pParts = this;
} }
@ -104,7 +105,14 @@ void CParticles::Update(float TimePassed)
// move the point // move the point
vec2 Vel = m_aParticles[i].m_Vel * TimePassed; vec2 Vel = m_aParticles[i].m_Vel * TimePassed;
if(m_aParticles[i].m_Collides)
{
Collision()->MovePoint(&m_aParticles[i].m_Pos, &Vel, 0.1f + 0.9f * random_float(), NULL); Collision()->MovePoint(&m_aParticles[i].m_Pos, &Vel, 0.1f + 0.9f * random_float(), NULL);
}
else
{
m_aParticles[i].m_Pos += Vel;
}
m_aParticles[i].m_Vel = Vel * (1.0f / TimePassed); m_aParticles[i].m_Vel = Vel * (1.0f / TimePassed);
m_aParticles[i].m_Life += TimePassed; m_aParticles[i].m_Life += TimePassed;
@ -172,6 +180,13 @@ void CParticles::OnInit()
RenderTools()->QuadContainerAddSprite(m_ParticleQuadContainerIndex, 1.f); RenderTools()->QuadContainerAddSprite(m_ParticleQuadContainerIndex, 1.f);
} }
Graphics()->QuadContainerUpload(m_ParticleQuadContainerIndex); Graphics()->QuadContainerUpload(m_ParticleQuadContainerIndex);
m_ExtraParticleQuadContainerIndex = Graphics()->CreateQuadContainer(false);
// TODO: Use a loop similar to the one for m_ParticleQuadContainerIndex if you add more additional particles
Graphics()->QuadsSetSubset(0, 0, 1, 1);
RenderTools()->QuadContainerAddSprite(m_ExtraParticleQuadContainerIndex, 1.f);
Graphics()->QuadContainerUpload(m_ExtraParticleQuadContainerIndex);
} }
bool CParticles::ParticleIsVisibleOnScreen(const vec2 &CurPos, float CurSize) bool CParticles::ParticleIsVisibleOnScreen(const vec2 &CurPos, float CurSize)
@ -191,6 +206,16 @@ bool CParticles::ParticleIsVisibleOnScreen(const vec2 &CurPos, float CurSize)
void CParticles::RenderGroup(int Group) void CParticles::RenderGroup(int Group)
{ {
IGraphics::CTextureHandle *aParticles = GameClient()->m_ParticlesSkin.m_aSpriteParticles;
int FirstParticleOffset = SPRITE_PART_SLICE;
int ParticleQuadContainerIndex = m_ParticleQuadContainerIndex;
if(Group == GROUP_EXTRA)
{
aParticles = GameClient()->m_ExtrasSkin.m_aSpriteParticles;
FirstParticleOffset = SPRITE_PART_SNOWFLAKE;
ParticleQuadContainerIndex = m_ExtraParticleQuadContainerIndex;
}
// don't use the buffer methods here, else the old renderer gets many draw calls // don't use the buffer methods here, else the old renderer gets many draw calls
if(Graphics()->IsQuadContainerBufferingEnabled()) if(Graphics()->IsQuadContainerBufferingEnabled())
{ {
@ -206,16 +231,22 @@ void CParticles::RenderGroup(int Group)
if(i != -1) if(i != -1)
{ {
float Alpha = m_aParticles[i].m_Color.a;
if(m_aParticles[i].m_UseAlphaFading)
{
float a = m_aParticles[i].m_Life / m_aParticles[i].m_LifeSpan;
Alpha = mix(m_aParticles[i].m_StartAlpha, m_aParticles[i].m_EndAlpha, a);
}
LastColor[0] = m_aParticles[i].m_Color.r; LastColor[0] = m_aParticles[i].m_Color.r;
LastColor[1] = m_aParticles[i].m_Color.g; LastColor[1] = m_aParticles[i].m_Color.g;
LastColor[2] = m_aParticles[i].m_Color.b; LastColor[2] = m_aParticles[i].m_Color.b;
LastColor[3] = m_aParticles[i].m_Color.a; LastColor[3] = Alpha;
Graphics()->SetColor( Graphics()->SetColor(
m_aParticles[i].m_Color.r, m_aParticles[i].m_Color.r,
m_aParticles[i].m_Color.g, m_aParticles[i].m_Color.g,
m_aParticles[i].m_Color.b, m_aParticles[i].m_Color.b,
m_aParticles[i].m_Color.a); Alpha);
LastQuadOffset = m_aParticles[i].m_Spr; LastQuadOffset = m_aParticles[i].m_Spr;
} }
@ -226,14 +257,19 @@ void CParticles::RenderGroup(int Group)
float a = m_aParticles[i].m_Life / m_aParticles[i].m_LifeSpan; float a = m_aParticles[i].m_Life / m_aParticles[i].m_LifeSpan;
vec2 p = m_aParticles[i].m_Pos; vec2 p = m_aParticles[i].m_Pos;
float Size = mix(m_aParticles[i].m_StartSize, m_aParticles[i].m_EndSize, a); float Size = mix(m_aParticles[i].m_StartSize, m_aParticles[i].m_EndSize, a);
float Alpha = m_aParticles[i].m_Color.a;
if(m_aParticles[i].m_UseAlphaFading)
{
Alpha = mix(m_aParticles[i].m_StartAlpha, m_aParticles[i].m_EndAlpha, a);
}
// the current position, respecting the size, is inside the viewport, render it, else ignore // the current position, respecting the size, is inside the viewport, render it, else ignore
if(ParticleIsVisibleOnScreen(p, Size)) if(ParticleIsVisibleOnScreen(p, Size))
{ {
if((size_t)CurParticleRenderCount == gs_GraphicsMaxParticlesRenderCount || LastColor[0] != m_aParticles[i].m_Color.r || LastColor[1] != m_aParticles[i].m_Color.g || LastColor[2] != m_aParticles[i].m_Color.b || LastColor[3] != m_aParticles[i].m_Color.a || LastQuadOffset != QuadOffset) if((size_t)CurParticleRenderCount == gs_GraphicsMaxParticlesRenderCount || LastColor[0] != m_aParticles[i].m_Color.r || LastColor[1] != m_aParticles[i].m_Color.g || LastColor[2] != m_aParticles[i].m_Color.b || LastColor[3] != Alpha || LastQuadOffset != QuadOffset)
{ {
Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_SpriteParticles[LastQuadOffset - SPRITE_PART_SLICE]); Graphics()->TextureSet(aParticles[LastQuadOffset - FirstParticleOffset]);
Graphics()->RenderQuadContainerAsSpriteMultiple(m_ParticleQuadContainerIndex, LastQuadOffset, CurParticleRenderCount, s_aParticleRenderInfo); Graphics()->RenderQuadContainerAsSpriteMultiple(ParticleQuadContainerIndex, LastQuadOffset - FirstParticleOffset, CurParticleRenderCount, s_aParticleRenderInfo);
CurParticleRenderCount = 0; CurParticleRenderCount = 0;
LastQuadOffset = QuadOffset; LastQuadOffset = QuadOffset;
@ -241,12 +277,12 @@ void CParticles::RenderGroup(int Group)
m_aParticles[i].m_Color.r, m_aParticles[i].m_Color.r,
m_aParticles[i].m_Color.g, m_aParticles[i].m_Color.g,
m_aParticles[i].m_Color.b, m_aParticles[i].m_Color.b,
m_aParticles[i].m_Color.a); Alpha);
LastColor[0] = m_aParticles[i].m_Color.r; LastColor[0] = m_aParticles[i].m_Color.r;
LastColor[1] = m_aParticles[i].m_Color.g; LastColor[1] = m_aParticles[i].m_Color.g;
LastColor[2] = m_aParticles[i].m_Color.b; LastColor[2] = m_aParticles[i].m_Color.b;
LastColor[3] = m_aParticles[i].m_Color.a; LastColor[3] = Alpha;
} }
s_aParticleRenderInfo[CurParticleRenderCount].m_Pos[0] = p.x; s_aParticleRenderInfo[CurParticleRenderCount].m_Pos[0] = p.x;
@ -261,8 +297,8 @@ void CParticles::RenderGroup(int Group)
i = m_aParticles[i].m_NextPart; i = m_aParticles[i].m_NextPart;
} }
Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_SpriteParticles[LastQuadOffset - SPRITE_PART_SLICE]); Graphics()->TextureSet(aParticles[LastQuadOffset - FirstParticleOffset]);
Graphics()->RenderQuadContainerAsSpriteMultiple(m_ParticleQuadContainerIndex, LastQuadOffset, CurParticleRenderCount, s_aParticleRenderInfo); Graphics()->RenderQuadContainerAsSpriteMultiple(ParticleQuadContainerIndex, LastQuadOffset - FirstParticleOffset, CurParticleRenderCount, s_aParticleRenderInfo);
} }
else else
{ {
@ -276,11 +312,16 @@ void CParticles::RenderGroup(int Group)
float a = m_aParticles[i].m_Life / m_aParticles[i].m_LifeSpan; float a = m_aParticles[i].m_Life / m_aParticles[i].m_LifeSpan;
vec2 p = m_aParticles[i].m_Pos; vec2 p = m_aParticles[i].m_Pos;
float Size = mix(m_aParticles[i].m_StartSize, m_aParticles[i].m_EndSize, a); float Size = mix(m_aParticles[i].m_StartSize, m_aParticles[i].m_EndSize, a);
float Alpha = m_aParticles[i].m_Color.a;
if(m_aParticles[i].m_UseAlphaFading)
{
Alpha = mix(m_aParticles[i].m_StartAlpha, m_aParticles[i].m_EndAlpha, a);
}
// the current position, respecting the size, is inside the viewport, render it, else ignore // the current position, respecting the size, is inside the viewport, render it, else ignore
if(ParticleIsVisibleOnScreen(p, Size)) if(ParticleIsVisibleOnScreen(p, Size))
{ {
Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_SpriteParticles[m_aParticles[i].m_Spr - SPRITE_PART_SLICE]); Graphics()->TextureSet(aParticles[m_aParticles[i].m_Spr - FirstParticleOffset]);
Graphics()->QuadsBegin(); Graphics()->QuadsBegin();
Graphics()->QuadsSetRotation(m_aParticles[i].m_Rot); Graphics()->QuadsSetRotation(m_aParticles[i].m_Rot);
@ -289,7 +330,7 @@ void CParticles::RenderGroup(int Group)
m_aParticles[i].m_Color.r, m_aParticles[i].m_Color.r,
m_aParticles[i].m_Color.g, m_aParticles[i].m_Color.g,
m_aParticles[i].m_Color.b, m_aParticles[i].m_Color.b,
m_aParticles[i].m_Color.a); // pow(a, 0.75f) * Alpha);
IGraphics::CQuadItem QuadItem(p.x, p.y, Size, Size); IGraphics::CQuadItem QuadItem(p.x, p.y, Size, Size);
Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsDraw(&QuadItem, 1);

View file

@ -14,12 +14,16 @@ struct CParticle
m_LifeSpan = 0; m_LifeSpan = 0;
m_StartSize = 32; m_StartSize = 32;
m_EndSize = 32; m_EndSize = 32;
m_UseAlphaFading = false;
m_StartAlpha = 1;
m_EndAlpha = 1;
m_Rot = 0; m_Rot = 0;
m_Rotspeed = 0; m_Rotspeed = 0;
m_Gravity = 0; m_Gravity = 0;
m_Friction = 0; m_Friction = 0;
m_FlowAffected = 1.0f; m_FlowAffected = 1.0f;
m_Color = ColorRGBA(1, 1, 1, 1); m_Color = ColorRGBA(1, 1, 1, 1);
m_Collides = true;
} }
vec2 m_Pos; vec2 m_Pos;
@ -34,6 +38,10 @@ struct CParticle
float m_StartSize; float m_StartSize;
float m_EndSize; float m_EndSize;
bool m_UseAlphaFading;
float m_StartAlpha;
float m_EndAlpha;
float m_Rot; float m_Rot;
float m_Rotspeed; float m_Rotspeed;
@ -42,6 +50,8 @@ struct CParticle
ColorRGBA m_Color; ColorRGBA m_Color;
bool m_Collides;
// set by the particle system // set by the particle system
float m_Life; float m_Life;
int m_PrevPart; int m_PrevPart;
@ -57,6 +67,7 @@ public:
{ {
GROUP_PROJECTILE_TRAIL = 0, GROUP_PROJECTILE_TRAIL = 0,
GROUP_EXPLOSIONS, GROUP_EXPLOSIONS,
GROUP_EXTRA,
GROUP_GENERAL, GROUP_GENERAL,
NUM_GROUPS NUM_GROUPS
}; };
@ -72,6 +83,7 @@ public:
private: private:
int m_ParticleQuadContainerIndex; int m_ParticleQuadContainerIndex;
int m_ExtraParticleQuadContainerIndex;
enum enum
{ {
@ -96,6 +108,7 @@ private:
CRenderGroup<GROUP_PROJECTILE_TRAIL> m_RenderTrail; CRenderGroup<GROUP_PROJECTILE_TRAIL> m_RenderTrail;
CRenderGroup<GROUP_EXPLOSIONS> m_RenderExplosions; CRenderGroup<GROUP_EXPLOSIONS> m_RenderExplosions;
CRenderGroup<GROUP_EXTRA> m_RenderExtra;
CRenderGroup<GROUP_GENERAL> m_RenderGeneral; CRenderGroup<GROUP_GENERAL> m_RenderGeneral;
bool ParticleIsVisibleOnScreen(const vec2 &CurPos, float CurSize); bool ParticleIsVisibleOnScreen(const vec2 &CurPos, float CurSize);

View file

@ -452,6 +452,8 @@ void CPlayers::RenderPlayer(
} }
// draw gun // draw gun
{
if(!(RenderInfo.m_TeeRenderFlags & TEE_NO_WEAPON))
{ {
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
Graphics()->QuadsSetRotation(State.GetAttach()->m_Angle * pi * 2 + Angle); Graphics()->QuadsSetRotation(State.GetAttach()->m_Angle * pi * 2 + Angle);
@ -460,54 +462,54 @@ void CPlayers::RenderPlayer(
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.5f); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 0.5f);
// normal weapons // normal weapons
int iw = clamp(Player.m_Weapon, 0, NUM_WEAPONS - 1); int CurrentWeapon = clamp(Player.m_Weapon, 0, NUM_WEAPONS - 1);
Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteWeapons[iw]); Graphics()->TextureSet(GameClient()->m_GameSkin.m_aSpriteWeapons[CurrentWeapon]);
int QuadOffset = iw * 2 + (Direction.x < 0 ? 1 : 0); int QuadOffset = CurrentWeapon * 2 + (Direction.x < 0 ? 1 : 0);
Graphics()->SetColor(1.0f, 1.0f, 1.0f, Alpha); Graphics()->SetColor(1.0f, 1.0f, 1.0f, Alpha);
vec2 Dir = Direction; vec2 Dir = Direction;
float Recoil = 0.0f; float Recoil = 0.0f;
vec2 p; vec2 WeaponPosition;
if(Player.m_Weapon == WEAPON_HAMMER) if(Player.m_Weapon == WEAPON_HAMMER)
{ {
// Static position for hammer // Static position for hammer
p = Position + vec2(State.GetAttach()->m_X, State.GetAttach()->m_Y); WeaponPosition = Position + vec2(State.GetAttach()->m_X, State.GetAttach()->m_Y);
p.y += g_pData->m_Weapons.m_aId[iw].m_Offsety; WeaponPosition.y += g_pData->m_Weapons.m_aId[CurrentWeapon].m_Offsety;
// if attack is under way, bash stuffs // if attack is under way, bash stuffs
if(Direction.x < 0) if(Direction.x < 0)
{ {
Graphics()->QuadsSetRotation(-pi / 2 - State.GetAttach()->m_Angle * pi * 2); Graphics()->QuadsSetRotation(-pi / 2 - State.GetAttach()->m_Angle * pi * 2);
p.x -= g_pData->m_Weapons.m_aId[iw].m_Offsetx; WeaponPosition.x -= g_pData->m_Weapons.m_aId[CurrentWeapon].m_Offsetx;
} }
else else
{ {
Graphics()->QuadsSetRotation(-pi / 2 + State.GetAttach()->m_Angle * pi * 2); Graphics()->QuadsSetRotation(-pi / 2 + State.GetAttach()->m_Angle * pi * 2);
} }
Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, p.x, p.y); Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, WeaponPosition.x, WeaponPosition.y);
} }
else if(Player.m_Weapon == WEAPON_NINJA) else if(Player.m_Weapon == WEAPON_NINJA)
{ {
p = Position; WeaponPosition = Position;
p.y += g_pData->m_Weapons.m_aId[iw].m_Offsety; WeaponPosition.y += g_pData->m_Weapons.m_aId[CurrentWeapon].m_Offsety;
if(Direction.x < 0) if(Direction.x < 0)
{ {
Graphics()->QuadsSetRotation(-pi / 2 - State.GetAttach()->m_Angle * pi * 2); Graphics()->QuadsSetRotation(-pi / 2 - State.GetAttach()->m_Angle * pi * 2);
p.x -= g_pData->m_Weapons.m_aId[iw].m_Offsetx; WeaponPosition.x -= g_pData->m_Weapons.m_aId[CurrentWeapon].m_Offsetx;
m_pClient->m_Effects.PowerupShine(p + vec2(32, 0), vec2(32, 12)); m_pClient->m_Effects.PowerupShine(WeaponPosition + vec2(32, 0), vec2(32, 12));
} }
else else
{ {
Graphics()->QuadsSetRotation(-pi / 2 + State.GetAttach()->m_Angle * pi * 2); Graphics()->QuadsSetRotation(-pi / 2 + State.GetAttach()->m_Angle * pi * 2);
m_pClient->m_Effects.PowerupShine(p - vec2(32, 0), vec2(32, 12)); m_pClient->m_Effects.PowerupShine(WeaponPosition - vec2(32, 0), vec2(32, 12));
} }
Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, p.x, p.y); Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, WeaponPosition.x, WeaponPosition.y);
// HADOKEN // HADOKEN
if(AttackTime <= 1 / 6.f && g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles) if(AttackTime <= 1 / 6.f && g_pData->m_Weapons.m_aId[CurrentWeapon].m_NumSpriteMuzzles)
{ {
int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles; int IteX = rand() % g_pData->m_Weapons.m_aId[CurrentWeapon].m_NumSpriteMuzzles;
static int s_LastIteX = IteX; static int s_LastIteX = IteX;
if(Client()->State() == IClient::STATE_DEMOPLAYBACK) if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
{ {
@ -524,7 +526,7 @@ void CPlayers::RenderPlayer(
else else
s_LastIteX = IteX; s_LastIteX = IteX;
} }
if(g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX]) if(g_pData->m_Weapons.m_aId[CurrentWeapon].m_aSpriteMuzzles[IteX])
{ {
if(PredictLocalWeapons) if(PredictLocalWeapons)
Dir = vec2(pPlayerChar->m_X, pPlayerChar->m_Y) - vec2(pPrevChar->m_X, pPrevChar->m_Y); Dir = vec2(pPlayerChar->m_X, pPlayerChar->m_Y) - vec2(pPrevChar->m_X, pPrevChar->m_Y);
@ -543,11 +545,11 @@ void CPlayers::RenderPlayer(
Graphics()->QuadsSetRotation(HadOkenAngle); Graphics()->QuadsSetRotation(HadOkenAngle);
QuadOffset = IteX * 2; QuadOffset = IteX * 2;
vec2 DirY(-Dir.y, Dir.x); vec2 DirY(-Dir.y, Dir.x);
p = Position; WeaponPosition = Position;
float OffsetX = g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsetx; float OffsetX = g_pData->m_Weapons.m_aId[CurrentWeapon].m_Muzzleoffsetx;
p -= Dir * OffsetX; WeaponPosition -= Dir * OffsetX;
Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteWeaponsMuzzles[iw][IteX]); Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteWeaponsMuzzles[CurrentWeapon][IteX]);
Graphics()->RenderQuadContainerAsSprite(m_WeaponSpriteMuzzleQuadContainerIndex[iw], QuadOffset, p.x, p.y); Graphics()->RenderQuadContainerAsSprite(m_WeaponSpriteMuzzleQuadContainerIndex[CurrentWeapon], QuadOffset, WeaponPosition.x, WeaponPosition.y);
} }
} }
} }
@ -558,38 +560,26 @@ void CPlayers::RenderPlayer(
float a = AttackTicksPassed / 5.0f; float a = AttackTicksPassed / 5.0f;
if(a < 1) if(a < 1)
Recoil = sinf(a * pi); Recoil = sinf(a * pi);
p = Position + Dir * g_pData->m_Weapons.m_aId[iw].m_Offsetx - Dir * Recoil * 10.0f; WeaponPosition = Position + Dir * g_pData->m_Weapons.m_aId[CurrentWeapon].m_Offsetx - Dir * Recoil * 10.0f;
p.y += g_pData->m_Weapons.m_aId[iw].m_Offsety; WeaponPosition.y += g_pData->m_Weapons.m_aId[CurrentWeapon].m_Offsety;
if(Player.m_Weapon == WEAPON_GUN && g_Config.m_ClOldGunPosition) if(Player.m_Weapon == WEAPON_GUN && g_Config.m_ClOldGunPosition)
p.y -= 8; WeaponPosition.y -= 8;
Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, p.x, p.y); Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, WeaponPosition.x, WeaponPosition.y);
}
if(RenderInfo.m_ShineDecoration)
{
if(Direction.x < 0)
{
m_pClient->m_Effects.PowerupShine(p + vec2(32, 0), vec2(32, 12));
}
else
{
m_pClient->m_Effects.PowerupShine(p - vec2(32, 0), vec2(32, 12));
}
} }
if(Player.m_Weapon == WEAPON_GUN || Player.m_Weapon == WEAPON_SHOTGUN) if(Player.m_Weapon == WEAPON_GUN || Player.m_Weapon == WEAPON_SHOTGUN)
{ {
// check if we're firing stuff // check if we're firing stuff
if(g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles) //prev.attackticks) if(g_pData->m_Weapons.m_aId[CurrentWeapon].m_NumSpriteMuzzles) //prev.attackticks)
{ {
float AlphaMuzzle = 0.0f; float AlphaMuzzle = 0.0f;
if(AttackTicksPassed < g_pData->m_Weapons.m_aId[iw].m_Muzzleduration + 3) if(AttackTicksPassed < g_pData->m_Weapons.m_aId[CurrentWeapon].m_Muzzleduration + 3)
{ {
float t = AttackTicksPassed / g_pData->m_Weapons.m_aId[iw].m_Muzzleduration; float t = AttackTicksPassed / g_pData->m_Weapons.m_aId[CurrentWeapon].m_Muzzleduration;
AlphaMuzzle = mix(2.0f, 0.0f, minimum(1.0f, maximum(0.0f, t))); AlphaMuzzle = mix(2.0f, 0.0f, minimum(1.0f, maximum(0.0f, t)));
} }
int IteX = rand() % g_pData->m_Weapons.m_aId[iw].m_NumSpriteMuzzles; int IteX = rand() % g_pData->m_Weapons.m_aId[CurrentWeapon].m_NumSpriteMuzzles;
static int s_LastIteX = IteX; static int s_LastIteX = IteX;
if(Client()->State() == IClient::STATE_DEMOPLAYBACK) if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
{ {
@ -606,17 +596,17 @@ void CPlayers::RenderPlayer(
else else
s_LastIteX = IteX; s_LastIteX = IteX;
} }
if(AlphaMuzzle > 0.0f && g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX]) if(AlphaMuzzle > 0.0f && g_pData->m_Weapons.m_aId[CurrentWeapon].m_aSpriteMuzzles[IteX])
{ {
float OffsetY = -g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsety; float OffsetY = -g_pData->m_Weapons.m_aId[CurrentWeapon].m_Muzzleoffsety;
QuadOffset = IteX * 2 + (Direction.x < 0 ? 1 : 0); QuadOffset = IteX * 2 + (Direction.x < 0 ? 1 : 0);
if(Direction.x < 0) if(Direction.x < 0)
OffsetY = -OffsetY; OffsetY = -OffsetY;
vec2 DirY(-Dir.y, Dir.x); vec2 DirY(-Dir.y, Dir.x);
vec2 MuzzlePos = p + Dir * g_pData->m_Weapons.m_aId[iw].m_Muzzleoffsetx + DirY * OffsetY; vec2 MuzzlePos = WeaponPosition + Dir * g_pData->m_Weapons.m_aId[CurrentWeapon].m_Muzzleoffsetx + DirY * OffsetY;
Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteWeaponsMuzzles[iw][IteX]); Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteWeaponsMuzzles[CurrentWeapon][IteX]);
Graphics()->RenderQuadContainerAsSprite(m_WeaponSpriteMuzzleQuadContainerIndex[iw], QuadOffset, MuzzlePos.x, MuzzlePos.y); Graphics()->RenderQuadContainerAsSprite(m_WeaponSpriteMuzzleQuadContainerIndex[CurrentWeapon], QuadOffset, MuzzlePos.x, MuzzlePos.y);
} }
} }
} }
@ -625,33 +615,42 @@ void CPlayers::RenderPlayer(
switch(Player.m_Weapon) switch(Player.m_Weapon)
{ {
case WEAPON_GUN: RenderHand(&RenderInfo, p, Direction, -3 * pi / 4, vec2(-15, 4), Alpha); break; case WEAPON_GUN: RenderHand(&RenderInfo, WeaponPosition, Direction, -3 * pi / 4, vec2(-15, 4), Alpha); break;
case WEAPON_SHOTGUN: RenderHand(&RenderInfo, p, Direction, -pi / 2, vec2(-5, 4), Alpha); break; case WEAPON_SHOTGUN: RenderHand(&RenderInfo, WeaponPosition, Direction, -pi / 2, vec2(-5, 4), Alpha); break;
case WEAPON_GRENADE: RenderHand(&RenderInfo, p, Direction, -pi / 2, vec2(-4, 7), Alpha); break; case WEAPON_GRENADE: RenderHand(&RenderInfo, WeaponPosition, Direction, -pi / 2, vec2(-4, 7), Alpha); break;
}
} }
} }
// render the "shadow" tee // render the "shadow" tee
if(Local && ((g_Config.m_Debug && g_Config.m_ClUnpredictedShadow >= 0) || g_Config.m_ClUnpredictedShadow == 1)) if(Local && ((g_Config.m_Debug && g_Config.m_ClUnpredictedShadow >= 0) || g_Config.m_ClUnpredictedShadow == 1))
{ {
vec2 GhostPosition = Position; vec2 ShadowPosition = Position;
if(ClientID >= 0) if(ClientID >= 0)
GhostPosition = mix( ShadowPosition = mix(
vec2(m_pClient->m_Snap.m_aCharacters[ClientID].m_Prev.m_X, m_pClient->m_Snap.m_aCharacters[ClientID].m_Prev.m_Y), vec2(m_pClient->m_Snap.m_aCharacters[ClientID].m_Prev.m_X, m_pClient->m_Snap.m_aCharacters[ClientID].m_Prev.m_Y),
vec2(m_pClient->m_Snap.m_aCharacters[ClientID].m_Cur.m_X, m_pClient->m_Snap.m_aCharacters[ClientID].m_Cur.m_Y), vec2(m_pClient->m_Snap.m_aCharacters[ClientID].m_Cur.m_X, m_pClient->m_Snap.m_aCharacters[ClientID].m_Cur.m_Y),
Client()->IntraGameTick(g_Config.m_ClDummy)); Client()->IntraGameTick(g_Config.m_ClDummy));
CTeeRenderInfo Ghost = RenderInfo; CTeeRenderInfo Shadow = RenderInfo;
RenderTools()->RenderTee(&State, &Ghost, Player.m_Emote, Direction, GhostPosition, 0.5f); // render ghost RenderTools()->RenderTee(&State, &Shadow, Player.m_Emote, Direction, ShadowPosition, 0.5f); // render ghost
} }
RenderTools()->RenderTee(&State, &RenderInfo, Player.m_Emote, Direction, Position, Alpha); RenderTools()->RenderTee(&State, &RenderInfo, Player.m_Emote, Direction, Position, Alpha);
float TeeAnimScale, TeeBaseSize;
RenderTools()->GetRenderTeeAnimScaleAndBaseSize(&State, &RenderInfo, TeeAnimScale, TeeBaseSize);
vec2 BodyPos = Position + vec2(State.GetBody()->m_X, State.GetBody()->m_Y) * TeeAnimScale;
if(RenderInfo.m_TeeRenderFlags & TEE_EFFECT_FROZEN)
{
GameClient()->m_Effects.FreezingFlakes(BodyPos, vec2(32, 32));
}
int QuadOffsetToEmoticon = NUM_WEAPONS * 2 + 2 + 2; int QuadOffsetToEmoticon = NUM_WEAPONS * 2 + 2 + 2;
if((Player.m_PlayerFlags & PLAYERFLAG_CHATTING) && !m_pClient->m_aClients[ClientID].m_Afk) if((Player.m_PlayerFlags & PLAYERFLAG_CHATTING) && !m_pClient->m_aClients[ClientID].m_Afk)
{ {
int CurEmoticon = (SPRITE_DOTDOT - SPRITE_OOP); int CurEmoticon = (SPRITE_DOTDOT - SPRITE_OOP);
Graphics()->TextureSet(GameClient()->m_EmoticonsSkin.m_SpriteEmoticons[CurEmoticon]); Graphics()->TextureSet(GameClient()->m_EmoticonsSkin.m_aSpriteEmoticons[CurEmoticon]);
int QuadOffset = QuadOffsetToEmoticon + CurEmoticon; int QuadOffset = QuadOffsetToEmoticon + CurEmoticon;
Graphics()->SetColor(1.0f, 1.0f, 1.0f, Alpha); Graphics()->SetColor(1.0f, 1.0f, 1.0f, Alpha);
Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, Position.x + 24.f, Position.y - 40.f); Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, Position.x + 24.f, Position.y - 40.f);
@ -666,7 +665,7 @@ void CPlayers::RenderPlayer(
if(g_Config.m_ClAfkEmote && m_pClient->m_aClients[ClientID].m_Afk && !(Client()->DummyConnected() && ClientID == m_pClient->m_LocalIDs[!g_Config.m_ClDummy])) if(g_Config.m_ClAfkEmote && m_pClient->m_aClients[ClientID].m_Afk && !(Client()->DummyConnected() && ClientID == m_pClient->m_LocalIDs[!g_Config.m_ClDummy]))
{ {
int CurEmoticon = (SPRITE_ZZZ - SPRITE_OOP); int CurEmoticon = (SPRITE_ZZZ - SPRITE_OOP);
Graphics()->TextureSet(GameClient()->m_EmoticonsSkin.m_SpriteEmoticons[CurEmoticon]); Graphics()->TextureSet(GameClient()->m_EmoticonsSkin.m_aSpriteEmoticons[CurEmoticon]);
int QuadOffset = QuadOffsetToEmoticon + CurEmoticon; int QuadOffset = QuadOffsetToEmoticon + CurEmoticon;
Graphics()->SetColor(1.0f, 1.0f, 1.0f, Alpha); Graphics()->SetColor(1.0f, 1.0f, 1.0f, Alpha);
Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, Position.x + 24.f, Position.y - 40.f); Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, Position.x + 24.f, Position.y - 40.f);
@ -702,7 +701,7 @@ void CPlayers::RenderPlayer(
Graphics()->SetColor(1.0f, 1.0f, 1.0f, a * Alpha); Graphics()->SetColor(1.0f, 1.0f, 1.0f, a * Alpha);
// client_datas::emoticon is an offset from the first emoticon // client_datas::emoticon is an offset from the first emoticon
int QuadOffset = QuadOffsetToEmoticon + m_pClient->m_aClients[ClientID].m_Emoticon; int QuadOffset = QuadOffsetToEmoticon + m_pClient->m_aClients[ClientID].m_Emoticon;
Graphics()->TextureSet(GameClient()->m_EmoticonsSkin.m_SpriteEmoticons[m_pClient->m_aClients[ClientID].m_Emoticon]); Graphics()->TextureSet(GameClient()->m_EmoticonsSkin.m_aSpriteEmoticons[m_pClient->m_aClients[ClientID].m_Emoticon]);
Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, Position.x, Position.y - 23.f - 32.f * h, 1.f, (64.f * h) / 64.f); Graphics()->RenderQuadContainerAsSprite(m_WeaponEmoteQuadContainerIndex, QuadOffset, Position.x, Position.y - 23.f - 32.f * h, 1.f, (64.f * h) / 64.f);
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f); Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
@ -727,8 +726,14 @@ void CPlayers::OnRender()
for(int i = 0; i < MAX_CLIENTS; ++i) for(int i = 0; i < MAX_CLIENTS; ++i)
{ {
m_aRenderInfo[i] = m_pClient->m_aClients[i].m_RenderInfo; m_aRenderInfo[i] = m_pClient->m_aClients[i].m_RenderInfo;
m_aRenderInfo[i].m_ShineDecoration = m_pClient->m_aClients[i].m_LiveFrozen; m_aRenderInfo[i].m_TeeRenderFlags = 0;
if(m_pClient->m_Snap.m_aCharacters[i].m_Cur.m_Weapon == WEAPON_NINJA && g_Config.m_ClShowNinja) if(m_pClient->m_aClients[i].m_FreezeEnd != 0)
m_aRenderInfo[i].m_TeeRenderFlags |= TEE_EFFECT_FROZEN | TEE_NO_WEAPON;
if(m_pClient->m_aClients[i].m_LiveFrozen)
m_aRenderInfo[i].m_TeeRenderFlags |= TEE_EFFECT_FROZEN;
CGameClient::CSnapState::CCharacterInfo &CharacterInfo = m_pClient->m_Snap.m_aCharacters[i];
if((CharacterInfo.m_Cur.m_Weapon == WEAPON_NINJA || (CharacterInfo.m_HasExtendedData && CharacterInfo.m_ExtendedData.m_FreezeEnd != 0)) && g_Config.m_ClShowNinja)
{ {
// change the skin for the player to the ninja // change the skin for the player to the ninja
int Skin = m_pClient->m_Skins.Find("x_ninja"); int Skin = m_pClient->m_Skins.Find("x_ninja");

View file

@ -222,7 +222,7 @@ void CStatboard::RenderGlobalStats()
continue; continue;
float ScaleX, ScaleY; float ScaleX, ScaleY;
RenderTools()->GetSpriteScale(g_pData->m_Weapons.m_aId[i].m_pSpriteBody, ScaleX, ScaleY); RenderTools()->GetSpriteScale(g_pData->m_Weapons.m_aId[i].m_pSpriteBody, ScaleX, ScaleY);
Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteWeapons[i]); Graphics()->TextureSet(GameClient()->m_GameSkin.m_aSpriteWeapons[i]);
Graphics()->QuadsBegin(); Graphics()->QuadsBegin();
if(i == 0) if(i == 0)
RenderTools()->DrawSprite(x + px, y + 10, g_pData->m_Weapons.m_aId[i].m_VisualSize * 0.8f * ScaleX, g_pData->m_Weapons.m_aId[i].m_VisualSize * 0.8f * ScaleY); RenderTools()->DrawSprite(x + px, y + 10, g_pData->m_Weapons.m_aId[i].m_VisualSize * 0.8f * ScaleX, g_pData->m_Weapons.m_aId[i].m_VisualSize * 0.8f * ScaleY);

View file

@ -124,6 +124,7 @@ void CGameClient::OnConsoleInit()
&m_MapLayersForeGround, &m_MapLayersForeGround,
&m_Particles.m_RenderExplosions, &m_Particles.m_RenderExplosions,
&m_NamePlates, &m_NamePlates,
&m_Particles.m_RenderExtra,
&m_Particles.m_RenderGeneral, &m_Particles.m_RenderGeneral,
&m_FreezeBars, &m_FreezeBars,
&m_DamageInd, &m_DamageInd,
@ -275,6 +276,8 @@ void CGameClient::OnInit()
LoadParticlesSkin(g_Config.m_ClAssetParticles); LoadParticlesSkin(g_Config.m_ClAssetParticles);
else if(i == IMAGE_HUD) else if(i == IMAGE_HUD)
LoadHudSkin(g_Config.m_ClAssetHud); LoadHudSkin(g_Config.m_ClAssetHud);
else if(i == IMAGE_EXTRAS)
LoadExtrasSkin(g_Config.m_ClAssetExtras);
else else
g_pData->m_aImages[i].m_Id = Graphics()->LoadTexture(g_pData->m_aImages[i].m_pFilename, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0); g_pData->m_aImages[i].m_Id = Graphics()->LoadTexture(g_pData->m_aImages[i].m_pFilename, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0);
m_Menus.RenderLoading(false); m_Menus.RenderLoading(false);
@ -1032,6 +1035,9 @@ static CGameInfo GetGameInfo(const CNetObj_GameInfoEx *pInfoEx, int InfoExSize,
Info.m_DontMaskEntities = !DDNet; Info.m_DontMaskEntities = !DDNet;
Info.m_AllowXSkins = false; Info.m_AllowXSkins = false;
Info.m_EntitiesFDDrace = FDDrace; Info.m_EntitiesFDDrace = FDDrace;
Info.m_HudHealthArmor = !DDNet;
Info.m_HudAmmo = !DDNet;
Info.m_HudDDRace = DDNet;
if(Version >= 0) if(Version >= 0)
{ {
@ -1077,6 +1083,12 @@ static CGameInfo GetGameInfo(const CNetObj_GameInfoEx *pInfoEx, int InfoExSize,
{ {
Info.m_EntitiesFDDrace = Flags2 & GAMEINFOFLAG2_ENTITIES_FDDRACE; Info.m_EntitiesFDDrace = Flags2 & GAMEINFOFLAG2_ENTITIES_FDDRACE;
} }
if(Version >= 7)
{
Info.m_HudHealthArmor = Flags2 & GAMEINFOFLAG2_HUD_HEALTH_ARMOR;
Info.m_HudAmmo = Flags2 & GAMEINFOFLAG2_HUD_AMMO;
Info.m_HudDDRace = Flags2 & GAMEINFOFLAG2_HUD_DDRACE;
}
return Info; return Info;
} }
@ -2655,7 +2667,7 @@ void CGameClient::LoadGameSkin(const char *pPath, bool AsDir)
Graphics()->UnloadTexture(&m_GameSkin.m_SpriteWeaponNinjaCursor); Graphics()->UnloadTexture(&m_GameSkin.m_SpriteWeaponNinjaCursor);
Graphics()->UnloadTexture(&m_GameSkin.m_SpriteWeaponLaserCursor); Graphics()->UnloadTexture(&m_GameSkin.m_SpriteWeaponLaserCursor);
for(auto &SpriteWeaponCursor : m_GameSkin.m_SpriteWeaponCursors) for(auto &SpriteWeaponCursor : m_GameSkin.m_aSpriteWeaponCursors)
{ {
SpriteWeaponCursor = IGraphics::CTextureHandle(); SpriteWeaponCursor = IGraphics::CTextureHandle();
} }
@ -2669,17 +2681,17 @@ void CGameClient::LoadGameSkin(const char *pPath, bool AsDir)
Graphics()->UnloadTexture(&m_GameSkin.m_SpriteWeaponNinja); Graphics()->UnloadTexture(&m_GameSkin.m_SpriteWeaponNinja);
Graphics()->UnloadTexture(&m_GameSkin.m_SpriteWeaponLaser); Graphics()->UnloadTexture(&m_GameSkin.m_SpriteWeaponLaser);
for(auto &SpriteWeapon : m_GameSkin.m_SpriteWeapons) for(auto &SpriteWeapon : m_GameSkin.m_aSpriteWeapons)
{ {
SpriteWeapon = IGraphics::CTextureHandle(); SpriteWeapon = IGraphics::CTextureHandle();
} }
for(auto &SpriteParticle : m_GameSkin.m_SpriteParticles) for(auto &SpriteParticle : m_GameSkin.m_aSpriteParticles)
{ {
Graphics()->UnloadTexture(&SpriteParticle); Graphics()->UnloadTexture(&SpriteParticle);
} }
for(auto &SpriteStar : m_GameSkin.m_SpriteStars) for(auto &SpriteStar : m_GameSkin.m_aSpriteStars)
{ {
Graphics()->UnloadTexture(&SpriteStar); Graphics()->UnloadTexture(&SpriteStar);
} }
@ -2691,7 +2703,7 @@ void CGameClient::LoadGameSkin(const char *pPath, bool AsDir)
Graphics()->UnloadTexture(&m_GameSkin.m_SpriteWeaponNinjaProjectile); Graphics()->UnloadTexture(&m_GameSkin.m_SpriteWeaponNinjaProjectile);
Graphics()->UnloadTexture(&m_GameSkin.m_SpriteWeaponLaserProjectile); Graphics()->UnloadTexture(&m_GameSkin.m_SpriteWeaponLaserProjectile);
for(auto &SpriteWeaponProjectile : m_GameSkin.m_SpriteWeaponProjectiles) for(auto &SpriteWeaponProjectile : m_GameSkin.m_aSpriteWeaponProjectiles)
{ {
SpriteWeaponProjectile = IGraphics::CTextureHandle(); SpriteWeaponProjectile = IGraphics::CTextureHandle();
} }
@ -2721,12 +2733,12 @@ void CGameClient::LoadGameSkin(const char *pPath, bool AsDir)
Graphics()->UnloadTexture(&m_GameSkin.m_SpritePickupGun); Graphics()->UnloadTexture(&m_GameSkin.m_SpritePickupGun);
Graphics()->UnloadTexture(&m_GameSkin.m_SpritePickupHammer); Graphics()->UnloadTexture(&m_GameSkin.m_SpritePickupHammer);
for(auto &SpritePickupWeapon : m_GameSkin.m_SpritePickupWeapons) for(auto &SpritePickupWeapon : m_GameSkin.m_aSpritePickupWeapons)
{ {
SpritePickupWeapon = IGraphics::CTextureHandle(); SpritePickupWeapon = IGraphics::CTextureHandle();
} }
for(auto &SpritePickupWeaponArmor : m_GameSkin.m_SpritePickupWeaponArmor) for(auto &SpritePickupWeaponArmor : m_GameSkin.m_aSpritePickupWeaponArmor)
{ {
SpritePickupWeaponArmor = IGraphics::CTextureHandle(); SpritePickupWeaponArmor = IGraphics::CTextureHandle();
} }
@ -2783,12 +2795,12 @@ void CGameClient::LoadGameSkin(const char *pPath, bool AsDir)
m_GameSkin.m_SpriteWeaponNinjaCursor = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_WEAPON_NINJA_CURSOR]); m_GameSkin.m_SpriteWeaponNinjaCursor = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_WEAPON_NINJA_CURSOR]);
m_GameSkin.m_SpriteWeaponLaserCursor = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_WEAPON_LASER_CURSOR]); m_GameSkin.m_SpriteWeaponLaserCursor = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_WEAPON_LASER_CURSOR]);
m_GameSkin.m_SpriteWeaponCursors[0] = m_GameSkin.m_SpriteWeaponHammerCursor; m_GameSkin.m_aSpriteWeaponCursors[0] = m_GameSkin.m_SpriteWeaponHammerCursor;
m_GameSkin.m_SpriteWeaponCursors[1] = m_GameSkin.m_SpriteWeaponGunCursor; m_GameSkin.m_aSpriteWeaponCursors[1] = m_GameSkin.m_SpriteWeaponGunCursor;
m_GameSkin.m_SpriteWeaponCursors[2] = m_GameSkin.m_SpriteWeaponShotgunCursor; m_GameSkin.m_aSpriteWeaponCursors[2] = m_GameSkin.m_SpriteWeaponShotgunCursor;
m_GameSkin.m_SpriteWeaponCursors[3] = m_GameSkin.m_SpriteWeaponGrenadeCursor; m_GameSkin.m_aSpriteWeaponCursors[3] = m_GameSkin.m_SpriteWeaponGrenadeCursor;
m_GameSkin.m_SpriteWeaponCursors[4] = m_GameSkin.m_SpriteWeaponLaserCursor; m_GameSkin.m_aSpriteWeaponCursors[4] = m_GameSkin.m_SpriteWeaponLaserCursor;
m_GameSkin.m_SpriteWeaponCursors[5] = m_GameSkin.m_SpriteWeaponNinjaCursor; m_GameSkin.m_aSpriteWeaponCursors[5] = m_GameSkin.m_SpriteWeaponNinjaCursor;
// weapons and hook // weapons and hook
m_GameSkin.m_SpriteHookChain = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HOOK_CHAIN]); m_GameSkin.m_SpriteHookChain = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HOOK_CHAIN]);
@ -2800,23 +2812,23 @@ void CGameClient::LoadGameSkin(const char *pPath, bool AsDir)
m_GameSkin.m_SpriteWeaponNinja = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_WEAPON_NINJA_BODY]); m_GameSkin.m_SpriteWeaponNinja = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_WEAPON_NINJA_BODY]);
m_GameSkin.m_SpriteWeaponLaser = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_WEAPON_LASER_BODY]); m_GameSkin.m_SpriteWeaponLaser = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_WEAPON_LASER_BODY]);
m_GameSkin.m_SpriteWeapons[0] = m_GameSkin.m_SpriteWeaponHammer; m_GameSkin.m_aSpriteWeapons[0] = m_GameSkin.m_SpriteWeaponHammer;
m_GameSkin.m_SpriteWeapons[1] = m_GameSkin.m_SpriteWeaponGun; m_GameSkin.m_aSpriteWeapons[1] = m_GameSkin.m_SpriteWeaponGun;
m_GameSkin.m_SpriteWeapons[2] = m_GameSkin.m_SpriteWeaponShotgun; m_GameSkin.m_aSpriteWeapons[2] = m_GameSkin.m_SpriteWeaponShotgun;
m_GameSkin.m_SpriteWeapons[3] = m_GameSkin.m_SpriteWeaponGrenade; m_GameSkin.m_aSpriteWeapons[3] = m_GameSkin.m_SpriteWeaponGrenade;
m_GameSkin.m_SpriteWeapons[4] = m_GameSkin.m_SpriteWeaponLaser; m_GameSkin.m_aSpriteWeapons[4] = m_GameSkin.m_SpriteWeaponLaser;
m_GameSkin.m_SpriteWeapons[5] = m_GameSkin.m_SpriteWeaponNinja; m_GameSkin.m_aSpriteWeapons[5] = m_GameSkin.m_SpriteWeaponNinja;
// particles // particles
for(int i = 0; i < 9; ++i) for(int i = 0; i < 9; ++i)
{ {
m_GameSkin.m_SpriteParticles[i] = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART1 + i]); m_GameSkin.m_aSpriteParticles[i] = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART1 + i]);
} }
// stars // stars
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
{ {
m_GameSkin.m_SpriteStars[i] = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_STAR1 + i]); m_GameSkin.m_aSpriteStars[i] = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_STAR1 + i]);
} }
// projectiles // projectiles
@ -2830,12 +2842,12 @@ void CGameClient::LoadGameSkin(const char *pPath, bool AsDir)
m_GameSkin.m_SpriteWeaponLaserProjectile = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_WEAPON_LASER_PROJ]); m_GameSkin.m_SpriteWeaponLaserProjectile = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_WEAPON_LASER_PROJ]);
m_GameSkin.m_SpriteWeaponProjectiles[0] = m_GameSkin.m_SpriteWeaponHammerProjectile; m_GameSkin.m_aSpriteWeaponProjectiles[0] = m_GameSkin.m_SpriteWeaponHammerProjectile;
m_GameSkin.m_SpriteWeaponProjectiles[1] = m_GameSkin.m_SpriteWeaponGunProjectile; m_GameSkin.m_aSpriteWeaponProjectiles[1] = m_GameSkin.m_SpriteWeaponGunProjectile;
m_GameSkin.m_SpriteWeaponProjectiles[2] = m_GameSkin.m_SpriteWeaponShotgunProjectile; m_GameSkin.m_aSpriteWeaponProjectiles[2] = m_GameSkin.m_SpriteWeaponShotgunProjectile;
m_GameSkin.m_SpriteWeaponProjectiles[3] = m_GameSkin.m_SpriteWeaponGrenadeProjectile; m_GameSkin.m_aSpriteWeaponProjectiles[3] = m_GameSkin.m_SpriteWeaponGrenadeProjectile;
m_GameSkin.m_SpriteWeaponProjectiles[4] = m_GameSkin.m_SpriteWeaponLaserProjectile; m_GameSkin.m_aSpriteWeaponProjectiles[4] = m_GameSkin.m_SpriteWeaponLaserProjectile;
m_GameSkin.m_SpriteWeaponProjectiles[5] = m_GameSkin.m_SpriteWeaponNinjaProjectile; m_GameSkin.m_aSpriteWeaponProjectiles[5] = m_GameSkin.m_SpriteWeaponNinjaProjectile;
// muzzles // muzzles
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
@ -2863,17 +2875,17 @@ void CGameClient::LoadGameSkin(const char *pPath, bool AsDir)
m_GameSkin.m_SpritePickupArmorNinja = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PICKUP_ARMOR_NINJA]); m_GameSkin.m_SpritePickupArmorNinja = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PICKUP_ARMOR_NINJA]);
m_GameSkin.m_SpritePickupArmorLaser = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PICKUP_ARMOR_LASER]); m_GameSkin.m_SpritePickupArmorLaser = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PICKUP_ARMOR_LASER]);
m_GameSkin.m_SpritePickupWeapons[0] = m_GameSkin.m_SpritePickupHammer; m_GameSkin.m_aSpritePickupWeapons[0] = m_GameSkin.m_SpritePickupHammer;
m_GameSkin.m_SpritePickupWeapons[1] = m_GameSkin.m_SpritePickupGun; m_GameSkin.m_aSpritePickupWeapons[1] = m_GameSkin.m_SpritePickupGun;
m_GameSkin.m_SpritePickupWeapons[2] = m_GameSkin.m_SpritePickupShotgun; m_GameSkin.m_aSpritePickupWeapons[2] = m_GameSkin.m_SpritePickupShotgun;
m_GameSkin.m_SpritePickupWeapons[3] = m_GameSkin.m_SpritePickupGrenade; m_GameSkin.m_aSpritePickupWeapons[3] = m_GameSkin.m_SpritePickupGrenade;
m_GameSkin.m_SpritePickupWeapons[4] = m_GameSkin.m_SpritePickupLaser; m_GameSkin.m_aSpritePickupWeapons[4] = m_GameSkin.m_SpritePickupLaser;
m_GameSkin.m_SpritePickupWeapons[5] = m_GameSkin.m_SpritePickupNinja; m_GameSkin.m_aSpritePickupWeapons[5] = m_GameSkin.m_SpritePickupNinja;
m_GameSkin.m_SpritePickupWeaponArmor[0] = m_GameSkin.m_SpritePickupArmorShotgun; m_GameSkin.m_aSpritePickupWeaponArmor[0] = m_GameSkin.m_SpritePickupArmorShotgun;
m_GameSkin.m_SpritePickupWeaponArmor[1] = m_GameSkin.m_SpritePickupArmorGrenade; m_GameSkin.m_aSpritePickupWeaponArmor[1] = m_GameSkin.m_SpritePickupArmorGrenade;
m_GameSkin.m_SpritePickupWeaponArmor[2] = m_GameSkin.m_SpritePickupArmorNinja; m_GameSkin.m_aSpritePickupWeaponArmor[2] = m_GameSkin.m_SpritePickupArmorNinja;
m_GameSkin.m_SpritePickupWeaponArmor[3] = m_GameSkin.m_SpritePickupArmorLaser; m_GameSkin.m_aSpritePickupWeaponArmor[3] = m_GameSkin.m_SpritePickupArmorLaser;
// flags // flags
m_GameSkin.m_SpriteFlagBlue = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_FLAG_BLUE]); m_GameSkin.m_SpriteFlagBlue = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_FLAG_BLUE]);
@ -2901,7 +2913,7 @@ void CGameClient::LoadEmoticonsSkin(const char *pPath, bool AsDir)
{ {
if(m_EmoticonsSkinLoaded) if(m_EmoticonsSkinLoaded)
{ {
for(auto &SpriteEmoticon : m_EmoticonsSkin.m_SpriteEmoticons) for(auto &SpriteEmoticon : m_EmoticonsSkin.m_aSpriteEmoticons)
Graphics()->UnloadTexture(&SpriteEmoticon); Graphics()->UnloadTexture(&SpriteEmoticon);
m_EmoticonsSkinLoaded = false; m_EmoticonsSkinLoaded = false;
@ -2934,7 +2946,7 @@ void CGameClient::LoadEmoticonsSkin(const char *pPath, bool AsDir)
else if(PngLoaded && Graphics()->CheckImageDivisibility(aPath, ImgInfo, g_pData->m_aSprites[SPRITE_OOP].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_OOP].m_pSet->m_Gridy, true) && Graphics()->IsImageFormatRGBA(aPath, ImgInfo)) else if(PngLoaded && Graphics()->CheckImageDivisibility(aPath, ImgInfo, g_pData->m_aSprites[SPRITE_OOP].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_OOP].m_pSet->m_Gridy, true) && Graphics()->IsImageFormatRGBA(aPath, ImgInfo))
{ {
for(int i = 0; i < 16; ++i) for(int i = 0; i < 16; ++i)
m_EmoticonsSkin.m_SpriteEmoticons[i] = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_OOP + i]); m_EmoticonsSkin.m_aSpriteEmoticons[i] = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_OOP + i]);
m_EmoticonsSkinLoaded = true; m_EmoticonsSkinLoaded = true;
Graphics()->FreePNG(&ImgInfo); Graphics()->FreePNG(&ImgInfo);
@ -2947,7 +2959,7 @@ void CGameClient::LoadParticlesSkin(const char *pPath, bool AsDir)
{ {
Graphics()->UnloadTexture(&m_ParticlesSkin.m_SpriteParticleSlice); Graphics()->UnloadTexture(&m_ParticlesSkin.m_SpriteParticleSlice);
Graphics()->UnloadTexture(&m_ParticlesSkin.m_SpriteParticleBall); Graphics()->UnloadTexture(&m_ParticlesSkin.m_SpriteParticleBall);
for(auto &SpriteParticleSplat : m_ParticlesSkin.m_SpriteParticleSplat) for(auto &SpriteParticleSplat : m_ParticlesSkin.m_aSpriteParticleSplat)
Graphics()->UnloadTexture(&SpriteParticleSplat); Graphics()->UnloadTexture(&SpriteParticleSplat);
Graphics()->UnloadTexture(&m_ParticlesSkin.m_SpriteParticleSmoke); Graphics()->UnloadTexture(&m_ParticlesSkin.m_SpriteParticleSmoke);
Graphics()->UnloadTexture(&m_ParticlesSkin.m_SpriteParticleShell); Graphics()->UnloadTexture(&m_ParticlesSkin.m_SpriteParticleShell);
@ -2955,7 +2967,7 @@ void CGameClient::LoadParticlesSkin(const char *pPath, bool AsDir)
Graphics()->UnloadTexture(&m_ParticlesSkin.m_SpriteParticleAirJump); Graphics()->UnloadTexture(&m_ParticlesSkin.m_SpriteParticleAirJump);
Graphics()->UnloadTexture(&m_ParticlesSkin.m_SpriteParticleHit); Graphics()->UnloadTexture(&m_ParticlesSkin.m_SpriteParticleHit);
for(auto &SpriteParticle : m_ParticlesSkin.m_SpriteParticles) for(auto &SpriteParticle : m_ParticlesSkin.m_aSpriteParticles)
SpriteParticle = IGraphics::CTextureHandle(); SpriteParticle = IGraphics::CTextureHandle();
m_ParticlesSkinLoaded = false; m_ParticlesSkinLoaded = false;
@ -2990,22 +3002,22 @@ void CGameClient::LoadParticlesSkin(const char *pPath, bool AsDir)
m_ParticlesSkin.m_SpriteParticleSlice = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_SLICE]); m_ParticlesSkin.m_SpriteParticleSlice = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_SLICE]);
m_ParticlesSkin.m_SpriteParticleBall = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_BALL]); m_ParticlesSkin.m_SpriteParticleBall = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_BALL]);
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
m_ParticlesSkin.m_SpriteParticleSplat[i] = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_SPLAT01 + i]); m_ParticlesSkin.m_aSpriteParticleSplat[i] = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_SPLAT01 + i]);
m_ParticlesSkin.m_SpriteParticleSmoke = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_SMOKE]); m_ParticlesSkin.m_SpriteParticleSmoke = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_SMOKE]);
m_ParticlesSkin.m_SpriteParticleShell = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_SHELL]); m_ParticlesSkin.m_SpriteParticleShell = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_SHELL]);
m_ParticlesSkin.m_SpriteParticleExpl = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_EXPL01]); m_ParticlesSkin.m_SpriteParticleExpl = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_EXPL01]);
m_ParticlesSkin.m_SpriteParticleAirJump = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_AIRJUMP]); m_ParticlesSkin.m_SpriteParticleAirJump = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_AIRJUMP]);
m_ParticlesSkin.m_SpriteParticleHit = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_HIT01]); m_ParticlesSkin.m_SpriteParticleHit = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_HIT01]);
m_ParticlesSkin.m_SpriteParticles[0] = m_ParticlesSkin.m_SpriteParticleSlice; m_ParticlesSkin.m_aSpriteParticles[0] = m_ParticlesSkin.m_SpriteParticleSlice;
m_ParticlesSkin.m_SpriteParticles[1] = m_ParticlesSkin.m_SpriteParticleBall; m_ParticlesSkin.m_aSpriteParticles[1] = m_ParticlesSkin.m_SpriteParticleBall;
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
m_ParticlesSkin.m_SpriteParticles[2 + i] = m_ParticlesSkin.m_SpriteParticleSplat[i]; m_ParticlesSkin.m_aSpriteParticles[2 + i] = m_ParticlesSkin.m_aSpriteParticleSplat[i];
m_ParticlesSkin.m_SpriteParticles[5] = m_ParticlesSkin.m_SpriteParticleSmoke; m_ParticlesSkin.m_aSpriteParticles[5] = m_ParticlesSkin.m_SpriteParticleSmoke;
m_ParticlesSkin.m_SpriteParticles[6] = m_ParticlesSkin.m_SpriteParticleShell; m_ParticlesSkin.m_aSpriteParticles[6] = m_ParticlesSkin.m_SpriteParticleShell;
m_ParticlesSkin.m_SpriteParticles[7] = m_ParticlesSkin.m_SpriteParticleExpl; m_ParticlesSkin.m_aSpriteParticles[7] = m_ParticlesSkin.m_SpriteParticleExpl;
m_ParticlesSkin.m_SpriteParticles[8] = m_ParticlesSkin.m_SpriteParticleAirJump; m_ParticlesSkin.m_aSpriteParticles[8] = m_ParticlesSkin.m_SpriteParticleAirJump;
m_ParticlesSkin.m_SpriteParticles[9] = m_ParticlesSkin.m_SpriteParticleHit; m_ParticlesSkin.m_aSpriteParticles[9] = m_ParticlesSkin.m_SpriteParticleHit;
m_ParticlesSkinLoaded = true; m_ParticlesSkinLoaded = true;
free(ImgInfo.m_pData); free(ImgInfo.m_pData);
@ -3036,6 +3048,7 @@ void CGameClient::LoadHudSkin(const char *pPath, bool AsDir)
Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudNoShotgunHit); Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudNoShotgunHit);
Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudNoGrenadeHit); Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudNoGrenadeHit);
Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudNoLaserHit); Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudNoLaserHit);
Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudNoGunHit);
Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudDeepFrozen); Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudDeepFrozen);
Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudLiveFrozen); Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudLiveFrozen);
Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudTeleportGrenade); Graphics()->UnloadTexture(&m_HudSkin.m_SpriteHudTeleportGrenade);
@ -3093,6 +3106,7 @@ void CGameClient::LoadHudSkin(const char *pPath, bool AsDir)
m_HudSkin.m_SpriteHudNoShotgunHit = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_NO_SHOTGUN_HIT]); m_HudSkin.m_SpriteHudNoShotgunHit = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_NO_SHOTGUN_HIT]);
m_HudSkin.m_SpriteHudNoGrenadeHit = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_NO_GRENADE_HIT]); m_HudSkin.m_SpriteHudNoGrenadeHit = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_NO_GRENADE_HIT]);
m_HudSkin.m_SpriteHudNoLaserHit = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_NO_LASER_HIT]); m_HudSkin.m_SpriteHudNoLaserHit = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_NO_LASER_HIT]);
m_HudSkin.m_SpriteHudNoGunHit = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_NO_GUN_HIT]);
m_HudSkin.m_SpriteHudDeepFrozen = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_DEEP_FROZEN]); m_HudSkin.m_SpriteHudDeepFrozen = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_DEEP_FROZEN]);
m_HudSkin.m_SpriteHudLiveFrozen = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_LIVE_FROZEN]); m_HudSkin.m_SpriteHudLiveFrozen = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_LIVE_FROZEN]);
m_HudSkin.m_SpriteHudTeleportGrenade = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_TELEPORT_GRENADE]); m_HudSkin.m_SpriteHudTeleportGrenade = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_HUD_TELEPORT_GRENADE]);
@ -3107,6 +3121,51 @@ void CGameClient::LoadHudSkin(const char *pPath, bool AsDir)
} }
} }
void CGameClient::LoadExtrasSkin(const char *pPath, bool AsDir)
{
if(m_ExtrasSkinLoaded)
{
Graphics()->UnloadTexture(&m_ExtrasSkin.m_SpriteParticleSnowflake);
for(auto &SpriteParticle : m_ExtrasSkin.m_aSpriteParticles)
SpriteParticle = IGraphics::CTextureHandle();
m_ExtrasSkinLoaded = false;
}
char aPath[IO_MAX_PATH_LENGTH];
bool IsDefault = false;
if(str_comp(pPath, "default") == 0)
{
str_format(aPath, sizeof(aPath), "%s", g_pData->m_aImages[IMAGE_EXTRAS].m_pFilename);
IsDefault = true;
}
else
{
if(AsDir)
str_format(aPath, sizeof(aPath), "assets/extras/%s/%s", pPath, g_pData->m_aImages[IMAGE_EXTRAS].m_pFilename);
else
str_format(aPath, sizeof(aPath), "assets/extras/%s.png", pPath);
}
CImageInfo ImgInfo;
bool PngLoaded = Graphics()->LoadPNG(&ImgInfo, aPath, IStorage::TYPE_ALL);
if(!PngLoaded && !IsDefault)
{
if(AsDir)
LoadExtrasSkin("default");
else
LoadExtrasSkin(pPath, true);
}
else if(PngLoaded && Graphics()->CheckImageDivisibility(aPath, ImgInfo, g_pData->m_aSprites[SPRITE_PART_SNOWFLAKE].m_pSet->m_Gridx, g_pData->m_aSprites[SPRITE_PART_SNOWFLAKE].m_pSet->m_Gridy, true) && Graphics()->IsImageFormatRGBA(aPath, ImgInfo))
{
m_ExtrasSkin.m_SpriteParticleSnowflake = Graphics()->LoadSpriteTexture(ImgInfo, &g_pData->m_aSprites[SPRITE_PART_SNOWFLAKE]);
m_ExtrasSkin.m_aSpriteParticles[0] = m_ExtrasSkin.m_SpriteParticleSnowflake;
m_ExtrasSkinLoaded = true;
free(ImgInfo.m_pData);
}
}
void CGameClient::RefindSkins() void CGameClient::RefindSkins()
{ {
for(auto &Client : m_aClients) for(auto &Client : m_aClients)

View file

@ -90,6 +90,10 @@ public:
bool m_DontMaskEntities; bool m_DontMaskEntities;
bool m_AllowXSkins; bool m_AllowXSkins;
bool m_HudHealthArmor;
bool m_HudAmmo;
bool m_HudDDRace;
}; };
class CSnapEntities class CSnapEntities
@ -525,6 +529,7 @@ public:
void LoadEmoticonsSkin(const char *pPath, bool AsDir = false); void LoadEmoticonsSkin(const char *pPath, bool AsDir = false);
void LoadParticlesSkin(const char *pPath, bool AsDir = false); void LoadParticlesSkin(const char *pPath, bool AsDir = false);
void LoadHudSkin(const char *pPath, bool AsDir = false); void LoadHudSkin(const char *pPath, bool AsDir = false);
void LoadExtrasSkin(const char *pPath, bool AsDir = false);
void RefindSkins(); void RefindSkins();
@ -544,7 +549,7 @@ public:
IGraphics::CTextureHandle m_SpriteWeaponNinjaCursor; IGraphics::CTextureHandle m_SpriteWeaponNinjaCursor;
IGraphics::CTextureHandle m_SpriteWeaponLaserCursor; IGraphics::CTextureHandle m_SpriteWeaponLaserCursor;
IGraphics::CTextureHandle m_SpriteWeaponCursors[6]; IGraphics::CTextureHandle m_aSpriteWeaponCursors[6];
// weapons and hook // weapons and hook
IGraphics::CTextureHandle m_SpriteHookChain; IGraphics::CTextureHandle m_SpriteHookChain;
@ -556,13 +561,13 @@ public:
IGraphics::CTextureHandle m_SpriteWeaponNinja; IGraphics::CTextureHandle m_SpriteWeaponNinja;
IGraphics::CTextureHandle m_SpriteWeaponLaser; IGraphics::CTextureHandle m_SpriteWeaponLaser;
IGraphics::CTextureHandle m_SpriteWeapons[6]; IGraphics::CTextureHandle m_aSpriteWeapons[6];
// particles // particles
IGraphics::CTextureHandle m_SpriteParticles[9]; IGraphics::CTextureHandle m_aSpriteParticles[9];
// stars // stars
IGraphics::CTextureHandle m_SpriteStars[3]; IGraphics::CTextureHandle m_aSpriteStars[3];
// projectiles // projectiles
IGraphics::CTextureHandle m_SpriteWeaponGunProjectile; IGraphics::CTextureHandle m_SpriteWeaponGunProjectile;
@ -572,7 +577,7 @@ public:
IGraphics::CTextureHandle m_SpriteWeaponNinjaProjectile; IGraphics::CTextureHandle m_SpriteWeaponNinjaProjectile;
IGraphics::CTextureHandle m_SpriteWeaponLaserProjectile; IGraphics::CTextureHandle m_SpriteWeaponLaserProjectile;
IGraphics::CTextureHandle m_SpriteWeaponProjectiles[6]; IGraphics::CTextureHandle m_aSpriteWeaponProjectiles[6];
// muzzles // muzzles
IGraphics::CTextureHandle m_SpriteWeaponGunMuzzles[3]; IGraphics::CTextureHandle m_SpriteWeaponGunMuzzles[3];
@ -595,8 +600,8 @@ public:
IGraphics::CTextureHandle m_SpritePickupGun; IGraphics::CTextureHandle m_SpritePickupGun;
IGraphics::CTextureHandle m_SpritePickupHammer; IGraphics::CTextureHandle m_SpritePickupHammer;
IGraphics::CTextureHandle m_SpritePickupWeapons[6]; IGraphics::CTextureHandle m_aSpritePickupWeapons[6];
IGraphics::CTextureHandle m_SpritePickupWeaponArmor[4]; IGraphics::CTextureHandle m_aSpritePickupWeaponArmor[4];
// flags // flags
IGraphics::CTextureHandle m_SpriteFlagBlue; IGraphics::CTextureHandle m_SpriteFlagBlue;
@ -621,13 +626,13 @@ public:
{ {
IGraphics::CTextureHandle m_SpriteParticleSlice; IGraphics::CTextureHandle m_SpriteParticleSlice;
IGraphics::CTextureHandle m_SpriteParticleBall; IGraphics::CTextureHandle m_SpriteParticleBall;
IGraphics::CTextureHandle m_SpriteParticleSplat[3]; IGraphics::CTextureHandle m_aSpriteParticleSplat[3];
IGraphics::CTextureHandle m_SpriteParticleSmoke; IGraphics::CTextureHandle m_SpriteParticleSmoke;
IGraphics::CTextureHandle m_SpriteParticleShell; IGraphics::CTextureHandle m_SpriteParticleShell;
IGraphics::CTextureHandle m_SpriteParticleExpl; IGraphics::CTextureHandle m_SpriteParticleExpl;
IGraphics::CTextureHandle m_SpriteParticleAirJump; IGraphics::CTextureHandle m_SpriteParticleAirJump;
IGraphics::CTextureHandle m_SpriteParticleHit; IGraphics::CTextureHandle m_SpriteParticleHit;
IGraphics::CTextureHandle m_SpriteParticles[10]; IGraphics::CTextureHandle m_aSpriteParticles[10];
}; };
SClientParticlesSkin m_ParticlesSkin; SClientParticlesSkin m_ParticlesSkin;
@ -635,7 +640,7 @@ public:
struct SClientEmoticonsSkin struct SClientEmoticonsSkin
{ {
IGraphics::CTextureHandle m_SpriteEmoticons[16]; IGraphics::CTextureHandle m_aSpriteEmoticons[16];
}; };
SClientEmoticonsSkin m_EmoticonsSkin; SClientEmoticonsSkin m_EmoticonsSkin;
@ -663,6 +668,7 @@ public:
IGraphics::CTextureHandle m_SpriteHudNoShotgunHit; IGraphics::CTextureHandle m_SpriteHudNoShotgunHit;
IGraphics::CTextureHandle m_SpriteHudNoGrenadeHit; IGraphics::CTextureHandle m_SpriteHudNoGrenadeHit;
IGraphics::CTextureHandle m_SpriteHudNoLaserHit; IGraphics::CTextureHandle m_SpriteHudNoLaserHit;
IGraphics::CTextureHandle m_SpriteHudNoGunHit;
IGraphics::CTextureHandle m_SpriteHudDeepFrozen; IGraphics::CTextureHandle m_SpriteHudDeepFrozen;
IGraphics::CTextureHandle m_SpriteHudLiveFrozen; IGraphics::CTextureHandle m_SpriteHudLiveFrozen;
IGraphics::CTextureHandle m_SpriteHudTeleportGrenade; IGraphics::CTextureHandle m_SpriteHudTeleportGrenade;
@ -676,6 +682,15 @@ public:
SClientHudSkin m_HudSkin; SClientHudSkin m_HudSkin;
bool m_HudSkinLoaded; bool m_HudSkinLoaded;
struct SClientExtrasSkin
{
IGraphics::CTextureHandle m_SpriteParticleSnowflake;
IGraphics::CTextureHandle m_aSpriteParticles[1];
};
SClientExtrasSkin m_ExtrasSkin;
bool m_ExtrasSkinLoaded;
const std::vector<CSnapEntities> &SnapEntities() { return m_vSnapEntities; } const std::vector<CSnapEntities> &SnapEntities() { return m_vSnapEntities; }
private: private:

View file

@ -32,7 +32,7 @@ public:
m_ColorFeet = ColorRGBA(1, 1, 1); m_ColorFeet = ColorRGBA(1, 1, 1);
m_Size = 1.0f; m_Size = 1.0f;
m_GotAirJump = 1; m_GotAirJump = 1;
m_ShineDecoration = 0; m_TeeRenderFlags = 0;
}; };
CSkin::SSkinTextures m_OriginalRenderSkin; CSkin::SSkinTextures m_OriginalRenderSkin;
@ -47,7 +47,14 @@ public:
ColorRGBA m_ColorFeet; ColorRGBA m_ColorFeet;
float m_Size; float m_Size;
int m_GotAirJump; int m_GotAirJump;
int m_ShineDecoration; int m_TeeRenderFlags;
};
// Tee Render Flags
enum
{
TEE_EFFECT_FROZEN = 1,
TEE_NO_WEAPON = 2,
}; };
// sprite renderings // sprite renderings
@ -71,7 +78,6 @@ class CRenderTools
int m_TeeQuadContainerIndex; int m_TeeQuadContainerIndex;
void GetRenderTeeAnimScaleAndBaseSize(class CAnimState *pAnim, CTeeRenderInfo *pInfo, float &AnimScale, float &BaseSize);
void GetRenderTeeBodyScale(float BaseSize, float &BodyScale); void GetRenderTeeBodyScale(float BaseSize, float &BodyScale);
void GetRenderTeeFeetScale(float BaseSize, float &FeetScaleWidth, float &FeetScaleHeight); void GetRenderTeeFeetScale(float BaseSize, float &FeetScaleWidth, float &FeetScaleHeight);
@ -116,6 +122,7 @@ public:
// larger rendering methods // larger rendering methods
void GetRenderTeeBodySize(class CAnimState *pAnim, CTeeRenderInfo *pInfo, vec2 &BodyOffset, float &Width, float &Height); void GetRenderTeeBodySize(class CAnimState *pAnim, CTeeRenderInfo *pInfo, vec2 &BodyOffset, float &Width, float &Height);
void GetRenderTeeFeetSize(class CAnimState *pAnim, CTeeRenderInfo *pInfo, vec2 &FeetOffset, float &Width, float &Height); void GetRenderTeeFeetSize(class CAnimState *pAnim, CTeeRenderInfo *pInfo, vec2 &FeetOffset, float &Width, float &Height);
void GetRenderTeeAnimScaleAndBaseSize(class CAnimState *pAnim, CTeeRenderInfo *pInfo, float &AnimScale, float &BaseSize);
// returns the offset to use, to render the tee with @see RenderTee exactly in the mid // returns the offset to use, to render the tee with @see RenderTee exactly in the mid
void GetRenderTeeOffsetToRenderedTee(class CAnimState *pAnim, CTeeRenderInfo *pInfo, vec2 &TeeOffsetToMid); void GetRenderTeeOffsetToRenderedTee(class CAnimState *pAnim, CTeeRenderInfo *pInfo, vec2 &TeeOffsetToMid);

View file

@ -207,7 +207,7 @@ void CCharacter::HandleNinja()
if(NinjaTime % Server()->TickSpeed() == 0 && NinjaTime / Server()->TickSpeed() <= 5) if(NinjaTime % Server()->TickSpeed() == 0 && NinjaTime / Server()->TickSpeed() <= 5)
{ {
GameServer()->CreateDamageInd(m_Pos, 0, NinjaTime / Server()->TickSpeed(), TeamMask()); GameServer()->CreateDamageInd(m_Pos, 0, NinjaTime / Server()->TickSpeed(), TeamMask() & GameServer()->ClientsMaskExcludeClientVersionAndHigher(VERSION_DDNET_NEW_HUD));
} }
m_Armor = clamp(10 - (NinjaTime / 15), 0, 10); m_Armor = clamp(10 - (NinjaTime / 15), 0, 10);
@ -918,6 +918,9 @@ bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon)
//TODO: Move the emote stuff to a function //TODO: Move the emote stuff to a function
void CCharacter::SnapCharacter(int SnappingClient, int ID) void CCharacter::SnapCharacter(int SnappingClient, int ID)
{ {
int SnappingClientVersion = SnappingClient != SERVER_DEMO_CLIENT ?
GameServer()->GetClientVersion(SnappingClient) :
CLIENT_VERSIONNR;
CCharacterCore *pCore; CCharacterCore *pCore;
int Tick, Emote = m_EmoteType, Weapon = m_Core.m_ActiveWeapon, AmmoCount = 0, int Tick, Emote = m_EmoteType, Weapon = m_Core.m_ActiveWeapon, AmmoCount = 0,
Health = 0, Armor = 0; Health = 0, Armor = 0;
@ -938,7 +941,7 @@ void CCharacter::SnapCharacter(int SnappingClient, int ID)
if(Emote == EMOTE_NORMAL) if(Emote == EMOTE_NORMAL)
Emote = (m_DeepFreeze || m_LiveFreeze) ? EMOTE_PAIN : EMOTE_BLINK; Emote = (m_DeepFreeze || m_LiveFreeze) ? EMOTE_PAIN : EMOTE_BLINK;
if(m_DeepFreeze || m_FreezeTime > 0 || m_FreezeTime == -1) if((m_DeepFreeze || m_FreezeTime > 0 || m_FreezeTime == -1) && SnappingClientVersion < VERSION_DDNET_NEW_HUD)
Weapon = WEAPON_NINJA; Weapon = WEAPON_NINJA;
} }
@ -965,7 +968,8 @@ void CCharacter::SnapCharacter(int SnappingClient, int ID)
} }
// change eyes, use ninja graphic and set ammo count if player has ninjajetpack // change eyes, use ninja graphic and set ammo count if player has ninjajetpack
if(m_pPlayer->m_NinjaJetpack && m_Jetpack && m_Core.m_ActiveWeapon == WEAPON_GUN && !m_DeepFreeze && !(m_FreezeTime > 0 || m_FreezeTime == -1) && !m_Core.m_HasTelegunGun) if(m_pPlayer->m_NinjaJetpack && m_Jetpack && m_Core.m_ActiveWeapon == WEAPON_GUN && !m_DeepFreeze &&
!(m_FreezeTime > 0 || m_FreezeTime == -1) && !m_Core.m_HasTelegunGun)
{ {
if(Emote == EMOTE_NORMAL) if(Emote == EMOTE_NORMAL)
Emote = EMOTE_HAPPY; Emote = EMOTE_HAPPY;
@ -1155,9 +1159,7 @@ void CCharacter::Snap(int SnappingClient)
if(m_Core.m_ActiveWeapon == WEAPON_NINJA) if(m_Core.m_ActiveWeapon == WEAPON_NINJA)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_WEAPON_NINJA; pDDNetCharacter->m_Flags |= CHARACTERFLAG_WEAPON_NINJA;
if(m_Core.m_LiveFrozen) if(m_Core.m_LiveFrozen)
{
pDDNetCharacter->m_Flags |= CHARACTERFLAG_NO_MOVEMENTS; pDDNetCharacter->m_Flags |= CHARACTERFLAG_NO_MOVEMENTS;
}
pDDNetCharacter->m_FreezeEnd = m_DeepFreeze ? -1 : m_FreezeTime == 0 ? 0 : Server()->Tick() + m_FreezeTime; pDDNetCharacter->m_FreezeEnd = m_DeepFreeze ? -1 : m_FreezeTime == 0 ? 0 : Server()->Tick() + m_FreezeTime;
pDDNetCharacter->m_Jumps = m_Core.m_Jumps; pDDNetCharacter->m_Jumps = m_Core.m_Jumps;
@ -1443,8 +1445,11 @@ void CCharacter::HandleTiles(int Index)
// hit others // hit others
if(((m_TileIndex == TILE_HIT_DISABLE) || (m_TileFIndex == TILE_HIT_DISABLE)) && m_Hit != (DISABLE_HIT_GRENADE | DISABLE_HIT_HAMMER | DISABLE_HIT_LASER | DISABLE_HIT_SHOTGUN)) if(((m_TileIndex == TILE_HIT_DISABLE) || (m_TileFIndex == TILE_HIT_DISABLE)) && m_Hit != (DISABLE_HIT_GRENADE | DISABLE_HIT_HAMMER | DISABLE_HIT_LASER | DISABLE_HIT_SHOTGUN))
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't hit others"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't hit others");
}
m_Hit = DISABLE_HIT_GRENADE | DISABLE_HIT_HAMMER | DISABLE_HIT_LASER | DISABLE_HIT_SHOTGUN; m_Hit = DISABLE_HIT_GRENADE | DISABLE_HIT_HAMMER | DISABLE_HIT_LASER | DISABLE_HIT_SHOTGUN;
m_Core.m_NoShotgunHit = true; m_Core.m_NoShotgunHit = true;
m_Core.m_NoGrenadeHit = true; m_Core.m_NoGrenadeHit = true;
@ -1454,8 +1459,11 @@ void CCharacter::HandleTiles(int Index)
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
} }
else if(((m_TileIndex == TILE_HIT_ENABLE) || (m_TileFIndex == TILE_HIT_ENABLE)) && m_Hit != HIT_ALL) else if(((m_TileIndex == TILE_HIT_ENABLE) || (m_TileFIndex == TILE_HIT_ENABLE)) && m_Hit != HIT_ALL)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can hit others"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can hit others");
}
m_Hit = HIT_ALL; m_Hit = HIT_ALL;
m_Core.m_NoShotgunHit = false; m_Core.m_NoShotgunHit = false;
m_Core.m_NoGrenadeHit = false; m_Core.m_NoGrenadeHit = false;
@ -1467,15 +1475,21 @@ void CCharacter::HandleTiles(int Index)
// collide with others // collide with others
if(((m_TileIndex == TILE_NPC_DISABLE) || (m_TileFIndex == TILE_NPC_DISABLE)) && !m_Core.m_NoCollision) if(((m_TileIndex == TILE_NPC_DISABLE) || (m_TileFIndex == TILE_NPC_DISABLE)) && !m_Core.m_NoCollision)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't collide with others"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't collide with others");
}
m_Core.m_NoCollision = true; m_Core.m_NoCollision = true;
m_NeededFaketuning |= FAKETUNE_NOCOLL; m_NeededFaketuning |= FAKETUNE_NOCOLL;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
} }
else if(((m_TileIndex == TILE_NPC_ENABLE) || (m_TileFIndex == TILE_NPC_ENABLE)) && m_Core.m_NoCollision) else if(((m_TileIndex == TILE_NPC_ENABLE) || (m_TileFIndex == TILE_NPC_ENABLE)) && m_Core.m_NoCollision)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can collide with others"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can collide with others");
}
m_Core.m_NoCollision = false; m_Core.m_NoCollision = false;
m_NeededFaketuning &= ~FAKETUNE_NOCOLL; m_NeededFaketuning &= ~FAKETUNE_NOCOLL;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
@ -1483,15 +1497,21 @@ void CCharacter::HandleTiles(int Index)
// hook others // hook others
if(((m_TileIndex == TILE_NPH_DISABLE) || (m_TileFIndex == TILE_NPH_DISABLE)) && !m_Core.m_NoHookHit) if(((m_TileIndex == TILE_NPH_DISABLE) || (m_TileFIndex == TILE_NPH_DISABLE)) && !m_Core.m_NoHookHit)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't hook others"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't hook others");
}
m_Core.m_NoHookHit = true; m_Core.m_NoHookHit = true;
m_NeededFaketuning |= FAKETUNE_NOHOOK; m_NeededFaketuning |= FAKETUNE_NOHOOK;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
} }
else if(((m_TileIndex == TILE_NPH_ENABLE) || (m_TileFIndex == TILE_NPH_ENABLE)) && m_Core.m_NoHookHit) else if(((m_TileIndex == TILE_NPH_ENABLE) || (m_TileFIndex == TILE_NPH_ENABLE)) && m_Core.m_NoHookHit)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can hook others"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can hook others");
}
m_Core.m_NoHookHit = false; m_Core.m_NoHookHit = false;
m_NeededFaketuning &= ~FAKETUNE_NOHOOK; m_NeededFaketuning &= ~FAKETUNE_NOHOOK;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
@ -1499,8 +1519,11 @@ void CCharacter::HandleTiles(int Index)
// unlimited air jumps // unlimited air jumps
if(((m_TileIndex == TILE_UNLIMITED_JUMPS_ENABLE) || (m_TileFIndex == TILE_UNLIMITED_JUMPS_ENABLE)) && !m_SuperJump) if(((m_TileIndex == TILE_UNLIMITED_JUMPS_ENABLE) || (m_TileFIndex == TILE_UNLIMITED_JUMPS_ENABLE)) && !m_SuperJump)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You have unlimited air jumps"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You have unlimited air jumps");
}
m_SuperJump = true; m_SuperJump = true;
m_Core.m_EndlessJump = true; m_Core.m_EndlessJump = true;
if(m_Core.m_Jumps == 0) if(m_Core.m_Jumps == 0)
@ -1510,8 +1533,11 @@ void CCharacter::HandleTiles(int Index)
} }
} }
else if(((m_TileIndex == TILE_UNLIMITED_JUMPS_DISABLE) || (m_TileFIndex == TILE_UNLIMITED_JUMPS_DISABLE)) && m_SuperJump) else if(((m_TileIndex == TILE_UNLIMITED_JUMPS_DISABLE) || (m_TileFIndex == TILE_UNLIMITED_JUMPS_DISABLE)) && m_SuperJump)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You don't have unlimited air jumps"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You don't have unlimited air jumps");
}
m_SuperJump = false; m_SuperJump = false;
m_Core.m_EndlessJump = false; m_Core.m_EndlessJump = false;
if(m_Core.m_Jumps == 0) if(m_Core.m_Jumps == 0)
@ -1534,14 +1560,20 @@ void CCharacter::HandleTiles(int Index)
// jetpack gun // jetpack gun
if(((m_TileIndex == TILE_JETPACK_ENABLE) || (m_TileFIndex == TILE_JETPACK_ENABLE)) && !m_Jetpack) if(((m_TileIndex == TILE_JETPACK_ENABLE) || (m_TileFIndex == TILE_JETPACK_ENABLE)) && !m_Jetpack)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You have a jetpack gun"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You have a jetpack gun");
}
m_Jetpack = true; m_Jetpack = true;
m_Core.m_Jetpack = true; m_Core.m_Jetpack = true;
} }
else if(((m_TileIndex == TILE_JETPACK_DISABLE) || (m_TileFIndex == TILE_JETPACK_DISABLE)) && m_Jetpack) else if(((m_TileIndex == TILE_JETPACK_DISABLE) || (m_TileFIndex == TILE_JETPACK_DISABLE)) && m_Jetpack)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You lost your jetpack gun"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You lost your jetpack gun");
}
m_Jetpack = false; m_Jetpack = false;
m_Core.m_Jetpack = false; m_Core.m_Jetpack = false;
} }
@ -1562,35 +1594,53 @@ void CCharacter::HandleTiles(int Index)
if(((m_TileIndex == TILE_TELE_GUN_ENABLE) || (m_TileFIndex == TILE_TELE_GUN_ENABLE)) && !m_Core.m_HasTelegunGun) if(((m_TileIndex == TILE_TELE_GUN_ENABLE) || (m_TileFIndex == TILE_TELE_GUN_ENABLE)) && !m_Core.m_HasTelegunGun)
{ {
m_Core.m_HasTelegunGun = true; m_Core.m_HasTelegunGun = true;
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport gun enabled"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport gun enabled");
} }
}
else if(((m_TileIndex == TILE_TELE_GUN_DISABLE) || (m_TileFIndex == TILE_TELE_GUN_DISABLE)) && m_Core.m_HasTelegunGun) else if(((m_TileIndex == TILE_TELE_GUN_DISABLE) || (m_TileFIndex == TILE_TELE_GUN_DISABLE)) && m_Core.m_HasTelegunGun)
{ {
m_Core.m_HasTelegunGun = false; m_Core.m_HasTelegunGun = false;
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport gun disabled"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport gun disabled");
} }
}
if(((m_TileIndex == TILE_TELE_GRENADE_ENABLE) || (m_TileFIndex == TILE_TELE_GRENADE_ENABLE)) && !m_Core.m_HasTelegunGrenade) if(((m_TileIndex == TILE_TELE_GRENADE_ENABLE) || (m_TileFIndex == TILE_TELE_GRENADE_ENABLE)) && !m_Core.m_HasTelegunGrenade)
{ {
m_Core.m_HasTelegunGrenade = true; m_Core.m_HasTelegunGrenade = true;
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport grenade enabled"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport grenade enabled");
} }
}
else if(((m_TileIndex == TILE_TELE_GRENADE_DISABLE) || (m_TileFIndex == TILE_TELE_GRENADE_DISABLE)) && m_Core.m_HasTelegunGrenade) else if(((m_TileIndex == TILE_TELE_GRENADE_DISABLE) || (m_TileFIndex == TILE_TELE_GRENADE_DISABLE)) && m_Core.m_HasTelegunGrenade)
{ {
m_Core.m_HasTelegunGrenade = false; m_Core.m_HasTelegunGrenade = false;
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport grenade disabled"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport grenade disabled");
} }
}
if(((m_TileIndex == TILE_TELE_LASER_ENABLE) || (m_TileFIndex == TILE_TELE_LASER_ENABLE)) && !m_Core.m_HasTelegunLaser) if(((m_TileIndex == TILE_TELE_LASER_ENABLE) || (m_TileFIndex == TILE_TELE_LASER_ENABLE)) && !m_Core.m_HasTelegunLaser)
{ {
m_Core.m_HasTelegunLaser = true; m_Core.m_HasTelegunLaser = true;
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport laser enabled"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport laser enabled");
} }
}
else if(((m_TileIndex == TILE_TELE_LASER_DISABLE) || (m_TileFIndex == TILE_TELE_LASER_DISABLE)) && m_Core.m_HasTelegunLaser) else if(((m_TileIndex == TILE_TELE_LASER_DISABLE) || (m_TileFIndex == TILE_TELE_LASER_DISABLE)) && m_Core.m_HasTelegunLaser)
{ {
m_Core.m_HasTelegunLaser = false; m_Core.m_HasTelegunLaser = false;
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport laser disabled"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport laser disabled");
} }
}
// stopper // stopper
if(m_Core.m_Vel.y > 0 && (m_MoveRestrictions & CANTMOVE_DOWN)) if(m_Core.m_Vel.y > 0 && (m_MoveRestrictions & CANTMOVE_DOWN))
@ -1663,54 +1713,78 @@ void CCharacter::HandleTiles(int Index)
} }
} }
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_HAMMER && Collision()->GetSwitchDelay(MapIndex) == WEAPON_HAMMER) else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_HAMMER && Collision()->GetSwitchDelay(MapIndex) == WEAPON_HAMMER)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can hammer hit others"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can hammer hit others");
}
m_Hit &= ~DISABLE_HIT_HAMMER; m_Hit &= ~DISABLE_HIT_HAMMER;
m_NeededFaketuning &= ~FAKETUNE_NOHAMMER; m_NeededFaketuning &= ~FAKETUNE_NOHAMMER;
m_Core.m_NoHammerHit = false; m_Core.m_NoHammerHit = false;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
} }
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_HAMMER) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_HAMMER) else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_HAMMER) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_HAMMER)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't hammer hit others"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't hammer hit others");
}
m_Hit |= DISABLE_HIT_HAMMER; m_Hit |= DISABLE_HIT_HAMMER;
m_NeededFaketuning |= FAKETUNE_NOHAMMER; m_NeededFaketuning |= FAKETUNE_NOHAMMER;
m_Core.m_NoHammerHit = true; m_Core.m_NoHammerHit = true;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
} }
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_SHOTGUN && Collision()->GetSwitchDelay(MapIndex) == WEAPON_SHOTGUN) else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_SHOTGUN && Collision()->GetSwitchDelay(MapIndex) == WEAPON_SHOTGUN)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can shoot others with shotgun"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can shoot others with shotgun");
}
m_Hit &= ~DISABLE_HIT_SHOTGUN; m_Hit &= ~DISABLE_HIT_SHOTGUN;
m_Core.m_NoShotgunHit = false; m_Core.m_NoShotgunHit = false;
} }
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_SHOTGUN) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_SHOTGUN) else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_SHOTGUN) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_SHOTGUN)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't shoot others with shotgun"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't shoot others with shotgun");
}
m_Hit |= DISABLE_HIT_SHOTGUN; m_Hit |= DISABLE_HIT_SHOTGUN;
m_Core.m_NoShotgunHit = true; m_Core.m_NoShotgunHit = true;
} }
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_GRENADE && Collision()->GetSwitchDelay(MapIndex) == WEAPON_GRENADE) else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_GRENADE && Collision()->GetSwitchDelay(MapIndex) == WEAPON_GRENADE)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can shoot others with grenade"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can shoot others with grenade");
}
m_Hit &= ~DISABLE_HIT_GRENADE; m_Hit &= ~DISABLE_HIT_GRENADE;
m_Core.m_NoGrenadeHit = false; m_Core.m_NoGrenadeHit = false;
} }
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_GRENADE) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_GRENADE) else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_GRENADE) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_GRENADE)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't shoot others with grenade"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't shoot others with grenade");
}
m_Hit |= DISABLE_HIT_GRENADE; m_Hit |= DISABLE_HIT_GRENADE;
m_Core.m_NoGrenadeHit = true; m_Core.m_NoGrenadeHit = true;
} }
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_LASER && Collision()->GetSwitchDelay(MapIndex) == WEAPON_LASER) else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_ENABLE && m_Hit & DISABLE_HIT_LASER && Collision()->GetSwitchDelay(MapIndex) == WEAPON_LASER)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can shoot others with laser"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can shoot others with laser");
}
m_Hit &= ~DISABLE_HIT_LASER; m_Hit &= ~DISABLE_HIT_LASER;
m_Core.m_NoLaserHit = false; m_Core.m_NoLaserHit = false;
} }
else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_LASER) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_LASER) else if(Collision()->GetSwitchType(MapIndex) == TILE_HIT_DISABLE && !(m_Hit & DISABLE_HIT_LASER) && Collision()->GetSwitchDelay(MapIndex) == WEAPON_LASER)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't shoot others with laser"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't shoot others with laser");
}
m_Hit |= DISABLE_HIT_LASER; m_Hit |= DISABLE_HIT_LASER;
m_Core.m_NoLaserHit = true; m_Core.m_NoLaserHit = true;
} }
@ -1723,6 +1797,8 @@ void CCharacter::HandleTiles(int Index)
} }
if(NewJumps != m_Core.m_Jumps) if(NewJumps != m_Core.m_Jumps)
{
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{ {
char aBuf[256]; char aBuf[256];
if(NewJumps == -1) if(NewJumps == -1)
@ -1732,7 +1808,7 @@ void CCharacter::HandleTiles(int Index)
else else
str_format(aBuf, sizeof(aBuf), "You can jump %d times", NewJumps); str_format(aBuf, sizeof(aBuf), "You can jump %d times", NewJumps);
GameServer()->SendChatTarget(GetPlayer()->GetCID(), aBuf); GameServer()->SendChatTarget(GetPlayer()->GetCID(), aBuf);
}
if(NewJumps == 0 && !m_SuperJump) if(NewJumps == 0 && !m_SuperJump)
{ {
m_NeededFaketuning |= FAKETUNE_NOJUMP; m_NeededFaketuning |= FAKETUNE_NOJUMP;
@ -1991,7 +2067,7 @@ void CCharacter::SetRescue()
void CCharacter::DDRaceTick() void CCharacter::DDRaceTick()
{ {
mem_copy(&m_Input, &m_SavedInput, sizeof(m_Input)); mem_copy(&m_Input, &m_SavedInput, sizeof(m_Input));
m_Armor = (m_FreezeTime >= 0) ? 10 - (m_FreezeTime / 15) : 0; m_Armor = (m_FreezeTime >= 0) ? clamp(10 - (m_FreezeTime / 15), 0, 10) : 0;
if(m_Input.m_Direction != 0 || m_Input.m_Jump != 0) if(m_Input.m_Direction != 0 || m_Input.m_Jump != 0)
m_LastMove = Server()->Tick(); m_LastMove = Server()->Tick();
@ -2005,7 +2081,7 @@ void CCharacter::DDRaceTick()
{ {
if(m_FreezeTime % Server()->TickSpeed() == Server()->TickSpeed() - 1 || m_FreezeTime == -1) if(m_FreezeTime % Server()->TickSpeed() == Server()->TickSpeed() - 1 || m_FreezeTime == -1)
{ {
GameServer()->CreateDamageInd(m_Pos, 0, (m_FreezeTime + 1) / Server()->TickSpeed(), TeamMask()); GameServer()->CreateDamageInd(m_Pos, 0, (m_FreezeTime + 1) / Server()->TickSpeed(), TeamMask() & GameServer()->ClientsMaskExcludeClientVersionAndHigher(VERSION_DDNET_NEW_HUD));
} }
if(m_FreezeTime > 0) if(m_FreezeTime > 0)
m_FreezeTime--; m_FreezeTime--;
@ -2209,8 +2285,10 @@ void CCharacter::SetEndlessHook(bool Enable)
{ {
return; return;
} }
if(GameServer()->GetClientVersion(GetPlayer()->GetCID()) < VERSION_DDNET_NEW_HUD)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), Enable ? "Endless hook has been activated" : "Endless hook has been deactivated"); GameServer()->SendChatTarget(GetPlayer()->GetCID(), Enable ? "Endless hook has been activated" : "Endless hook has been deactivated");
}
m_EndlessHook = Enable; m_EndlessHook = Enable;
m_Core.m_EndlessHook = Enable; m_Core.m_EndlessHook = Enable;
} }

View file

@ -4105,6 +4105,18 @@ int CGameContext::GetClientVersion(int ClientID) const
return Info.m_DDNetVersion; return Info.m_DDNetVersion;
} }
int64_t CGameContext::ClientsMaskExcludeClientVersionAndHigher(int Version)
{
int64_t Mask = 0;
for(int i = 0; i < MAX_CLIENTS; ++i)
{
if(GetClientVersion(i) >= Version)
continue;
Mask |= 1LL << i;
}
return Mask;
}
bool CGameContext::PlayerModerating() const bool CGameContext::PlayerModerating() const
{ {
return std::any_of(std::begin(m_apPlayers), std::end(m_apPlayers), [](const CPlayer *pPlayer) { return pPlayer && pPlayer->m_Moderating; }); return std::any_of(std::begin(m_apPlayers), std::end(m_apPlayers), [](const CPlayer *pPlayer) { return pPlayer && pPlayer->m_Moderating; });

View file

@ -291,6 +291,7 @@ public:
int64_t m_NonEmptySince; int64_t m_NonEmptySince;
int64_t m_LastMapVote; int64_t m_LastMapVote;
int GetClientVersion(int ClientID) const; int GetClientVersion(int ClientID) const;
int64_t ClientsMaskExcludeClientVersionAndHigher(int Version);
bool PlayerExists(int ClientID) const override { return m_apPlayers[ClientID]; } bool PlayerExists(int ClientID) const override { return m_apPlayers[ClientID]; }
// Returns true if someone is actively moderating. // Returns true if someone is actively moderating.
bool PlayerModerating() const; bool PlayerModerating() const;

View file

@ -604,7 +604,7 @@ void IGameController::Snap(int SnappingClient)
GAMEINFOFLAG_ENTITIES_DDRACE | GAMEINFOFLAG_ENTITIES_DDRACE |
GAMEINFOFLAG_ENTITIES_RACE | GAMEINFOFLAG_ENTITIES_RACE |
GAMEINFOFLAG_RACE; GAMEINFOFLAG_RACE;
pGameInfoEx->m_Flags2 = 0; pGameInfoEx->m_Flags2 = GAMEINFOFLAG2_HUD_DDRACE;
pGameInfoEx->m_Version = GAMEINFO_CURVERSION; pGameInfoEx->m_Version = GAMEINFO_CURVERSION;
if(Server()->IsSixup(SnappingClient)) if(Server()->IsSixup(SnappingClient))

View file

@ -40,7 +40,7 @@ void CGameControllerDDRace::OnCharacterSpawn(CCharacter *pChr)
void CGameControllerDDRace::HandleCharacterTiles(CCharacter *pChr, int MapIndex) void CGameControllerDDRace::HandleCharacterTiles(CCharacter *pChr, int MapIndex)
{ {
CPlayer *pPlayer = pChr->GetPlayer(); CPlayer *pPlayer = pChr->GetPlayer();
int ClientID = pPlayer->GetCID(); const int ClientID = pPlayer->GetCID();
int m_TileIndex = GameServer()->Collision()->GetTileIndex(MapIndex); int m_TileIndex = GameServer()->Collision()->GetTileIndex(MapIndex);
int m_TileFIndex = GameServer()->Collision()->GetFTileIndex(MapIndex); int m_TileFIndex = GameServer()->Collision()->GetFTileIndex(MapIndex);
@ -105,13 +105,19 @@ void CGameControllerDDRace::HandleCharacterTiles(CCharacter *pChr, int MapIndex)
// solo part // solo part
if(((m_TileIndex == TILE_SOLO_ENABLE) || (m_TileFIndex == TILE_SOLO_ENABLE)) && !m_Teams.m_Core.GetSolo(ClientID)) if(((m_TileIndex == TILE_SOLO_ENABLE) || (m_TileFIndex == TILE_SOLO_ENABLE)) && !m_Teams.m_Core.GetSolo(ClientID))
{
if(GameServer()->GetClientVersion(ClientID) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(ClientID, "You are now in a solo part"); GameServer()->SendChatTarget(ClientID, "You are now in a solo part");
}
pChr->SetSolo(true); pChr->SetSolo(true);
} }
else if(((m_TileIndex == TILE_SOLO_DISABLE) || (m_TileFIndex == TILE_SOLO_DISABLE)) && m_Teams.m_Core.GetSolo(ClientID)) else if(((m_TileIndex == TILE_SOLO_DISABLE) || (m_TileFIndex == TILE_SOLO_DISABLE)) && m_Teams.m_Core.GetSolo(ClientID))
{
if(GameServer()->GetClientVersion(ClientID) < VERSION_DDNET_NEW_HUD)
{ {
GameServer()->SendChatTarget(ClientID, "You are now out of the solo part"); GameServer()->SendChatTarget(ClientID, "You are now out of the solo part");
}
pChr->SetSolo(false); pChr->SetSolo(false);
} }
} }

View file

@ -694,7 +694,7 @@ void CGameTeams::OnFinish(CPlayer *Player, float Time, const char *pTimestamp)
if(g_Config.m_SvHideScore || !g_Config.m_SvSaveWorseScores) if(g_Config.m_SvHideScore || !g_Config.m_SvSaveWorseScores)
GameServer()->SendChatTarget(ClientID, aBuf, CGameContext::CHAT_SIX); GameServer()->SendChatTarget(ClientID, aBuf, CGameContext::CHAT_SIX);
else else
GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf, CGameContext::CHAT_SIX); GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf, -1, CGameContext::CHAT_SIX);
} }
else if(pData->m_BestTime != 0) // tee has already finished? else if(pData->m_BestTime != 0) // tee has already finished?
{ {

View file

@ -45,6 +45,7 @@ MACRO_CONFIG_INT(ClShowhudDummyActions, cl_showhud_dummy_actions, 1, 0, 1, CFGFL
MACRO_CONFIG_INT(ClShowhudPlayerPosition, cl_showhud_player_position, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show ingame HUD (Player Position)") MACRO_CONFIG_INT(ClShowhudPlayerPosition, cl_showhud_player_position, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show ingame HUD (Player Position)")
MACRO_CONFIG_INT(ClShowhudPlayerSpeed, cl_showhud_player_speed, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show ingame HUD (Player Speed)") MACRO_CONFIG_INT(ClShowhudPlayerSpeed, cl_showhud_player_speed, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show ingame HUD (Player Speed)")
MACRO_CONFIG_INT(ClShowhudPlayerAngle, cl_showhud_player_angle, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show ingame HUD (Player Aim Angle)") MACRO_CONFIG_INT(ClShowhudPlayerAngle, cl_showhud_player_angle, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show ingame HUD (Player Aim Angle)")
MACRO_CONFIG_INT(ClFreezeBarsAlphaInsideFreeze, cl_freezebars_alpha_inside_freeze, 100, 0, 100, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Opacity of freeze bars inside freeze (0 invisible, 100 fully visible)")
MACRO_CONFIG_INT(ClShowRecord, cl_showrecord, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show old style DDRace client records") MACRO_CONFIG_INT(ClShowRecord, cl_showrecord, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show old style DDRace client records")
MACRO_CONFIG_INT(ClShowNotifications, cl_shownotifications, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Make the client notify when someone highlights you") MACRO_CONFIG_INT(ClShowNotifications, cl_shownotifications, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Make the client notify when someone highlights you")
MACRO_CONFIG_INT(ClShowEmotes, cl_showemotes, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show tee emotes") MACRO_CONFIG_INT(ClShowEmotes, cl_showemotes, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show tee emotes")