From 6907895ee5574ad501aa7b75b8474576349340f1 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Thu, 15 Sep 2022 00:57:39 +0200 Subject: [PATCH 1/3] Add LASERTYPE enum --- datasrc/network.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/datasrc/network.py b/datasrc/network.py index af4997e50..57b89f7d5 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -34,6 +34,8 @@ ProjectileFlags = [f"CLIENTID_BIT{i}" for i in range(8)] + [ "EXPLOSIVE", "FREEZE", ] +LaserTypes = ["RIFLE", "SHOTGUN", "DOOR", "FREEZE"] + Emoticons = ["OOP", "EXCLAMATION", "HEARTS", "DROP", "DOTDOT", "MUSIC", "SORRY", "GHOST", "SUSHI", "SPLATTEE", "DEVILTEE", "ZOMG", "ZZZ", "WTF", "EYES", "QUESTION"] Powerups = ["HEALTH", "ARMOR", "WEAPON", "NINJA", "ARMOR_SHOTGUN", "ARMOR_GRENADE", "ARMOR_NINJA", "ARMOR_LASER"] @@ -78,6 +80,7 @@ Enums = [ Enum("EMOTICON", Emoticons), Enum("AUTHED", Authed), Enum("ENTITYCLASS", EntityClasses), + Enum("LASERTYPE", LaserTypes), ] Flags = [ From 03b90f4f3dfefd8be96d0213ec311197d051aafc Mon Sep 17 00:00:00 2001 From: VoxelDoesCode Date: Tue, 26 Jul 2022 21:58:16 -0400 Subject: [PATCH 2/3] Added new cl colors and tweaked the settings menu Merging of DoLaserPreview and static int fix Replace if else statement with switch function Adjusted RenderDropDown header to match static int cbuttoncontainer fix, potential bugs --- src/engine/shared/config_variables.h | 10 ++++- src/game/client/components/items.cpp | 4 +- src/game/client/components/menus.cpp | 36 +++++++++++++--- src/game/client/components/menus.h | 3 +- src/game/client/components/menus_settings.cpp | 43 +++++++++++++++---- 5 files changed, 76 insertions(+), 20 deletions(-) diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index bf08fc1ec..447a85f92 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -296,8 +296,14 @@ MACRO_CONFIG_COL(ClMessageClientColor, cl_message_client_color, 9633471, CFGFLAG MACRO_CONFIG_COL(ClMessageHighlightColor, cl_message_highlight_color, 65471, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Highlighted message color") MACRO_CONFIG_COL(ClMessageTeamColor, cl_message_team_color, 5636050, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Team message color") MACRO_CONFIG_COL(ClMessageColor, cl_message_color, 255, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Message color") -MACRO_CONFIG_COL(ClLaserInnerColor, cl_laser_inner_color, 11206591, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Laser inner color") -MACRO_CONFIG_COL(ClLaserOutlineColor, cl_laser_outline_color, 11176233, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Laser outline color") +MACRO_CONFIG_COL(ClLaserRifleInnerColor, cl_laser_rifle_inner_color, 11206591, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Laser inner color for Rifle") +MACRO_CONFIG_COL(ClLaserRifleOutlineColor, cl_laser_rifle_outline_color, 11176233, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Laser outline color for Rifle") +MACRO_CONFIG_COL(ClLaserShotgunInnerColor, cl_laser_sg_inner_color, 1900385, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Laser inner color for Shotgun") +MACRO_CONFIG_COL(ClLaserShotgunOutlineColor, cl_laser_sg_outline_color, 1866773, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Laser outline color for Shotgun") +MACRO_CONFIG_COL(ClLaserDoorInnerColor, cl_laser_door_inner_color, 7701379, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Laser inner color for doors") +MACRO_CONFIG_COL(ClLaserDoorOutlineColor, cl_laser_door_outline_color, 7667473, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Laser outline color for doors") +MACRO_CONFIG_COL(ClLaserFreezeInnerColor, cl_laser_freeze_inner_color, 15958915, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Laser inner color for freezes") +MACRO_CONFIG_COL(ClLaserFreezeOutlineColor, cl_laser_freeze_outline_color, 15972381, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Laser outline color for freezes") MACRO_CONFIG_COL(ClKillMessageNormalColor, cl_kill_message_normal_color, 255, CFGFLAG_CLIENT | CFGFLAG_SAVE | CFGFLAG_COLALPHA, "Kill message normal color") MACRO_CONFIG_COL(ClKillMessageHighlightColor, cl_kill_message_highlight_color, 255, CFGFLAG_CLIENT | CFGFLAG_SAVE | CFGFLAG_COLALPHA, "Kill message highlight color") diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index a679dd2e5..b9d5a96e1 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -243,9 +243,9 @@ void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent, bool IsPredicted) vec2 Pos = vec2(pCurrent->m_X, pCurrent->m_Y); vec2 From = vec2(pCurrent->m_FromX, pCurrent->m_FromY); float Len = distance(Pos, From); - RGB = color_cast(ColorHSLA(g_Config.m_ClLaserOutlineColor)); + RGB = color_cast(ColorHSLA(g_Config.m_ClLaserRifleOutlineColor)); ColorRGBA OuterColor(RGB.r, RGB.g, RGB.b, 1.0f); - RGB = color_cast(ColorHSLA(g_Config.m_ClLaserInnerColor)); + RGB = color_cast(ColorHSLA(g_Config.m_ClLaserRifleInnerColor)); ColorRGBA InnerColor(RGB.r, RGB.g, RGB.b, 1.0f); int TuneZone = GameClient()->m_GameWorld.m_WorldConfig.m_UseTuneZones ? Collision()->IsTune(Collision()->GetMapIndex(From)) : 0; diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index c9e4319e0..2fa51cc63 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -315,7 +315,7 @@ int CMenus::DoButton_CheckBox_Common(const void *pID, const char *pText, const c return UI()->DoButtonLogic(pID, 0, pRect); } -void CMenus::DoLaserPreview(const CUIRect *pRect, const ColorHSLA LaserOutlineColor, const ColorHSLA LaserInnerColor) +void CMenus::DoLaserPreview(const CUIRect *pRect, const ColorHSLA LaserOutlineColor, const ColorHSLA LaserInnerColor, const int LaserType) { ColorRGBA LaserRGB; CUIRect Section = *pRect; @@ -356,12 +356,34 @@ void CMenus::DoLaserPreview(const CUIRect *pRect, const ColorHSLA LaserOutlineCo Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsEnd(); - Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteWeaponLaser); - Graphics()->QuadsBegin(); - RenderTools()->SelectSprite(SPRITE_WEAPON_LASER_BODY); - Graphics()->QuadsSetSubset(0, 0, 1, 1); - RenderTools()->DrawSprite(Section.x + 30.0f, Section.y + Section.h / 2.0f, 60.0f); - Graphics()->QuadsEnd(); + switch(LaserType) + { + case LASERTYPE_RIFLE: + Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteWeaponLaser); + RenderTools()->SelectSprite(SPRITE_WEAPON_LASER_BODY); + Graphics()->QuadsBegin(); + Graphics()->QuadsSetSubset(0, 0, 1, 1); + RenderTools()->DrawSprite(Section.x + 30.0f, Section.y + Section.h / 2.0f, 60.0f); + Graphics()->QuadsEnd(); + break; + case LASERTYPE_SHOTGUN: + Graphics()->TextureSet(GameClient()->m_GameSkin.m_SpriteWeaponShotgun); + RenderTools()->SelectSprite(SPRITE_WEAPON_SHOTGUN_BODY); + Graphics()->QuadsBegin(); + Graphics()->QuadsSetSubset(0, 0, 1, 1); + RenderTools()->DrawSprite(Section.x + 30.0f, Section.y + Section.h / 2.0f, 60.0f); + Graphics()->QuadsEnd(); + break; + default: + Graphics()->QuadsBegin(); + Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f); + QuadItem = IGraphics::CQuadItem(From.x, From.y, 24, 24); + Graphics()->QuadsDraw(&QuadItem, 1); + Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, 1.0f); + QuadItem = IGraphics::CQuadItem(From.x, From.y, 20, 20); + Graphics()->QuadsDraw(&QuadItem, 1); + Graphics()->QuadsEnd(); + } } ColorHSLA CMenus::DoLine_ColorPicker(CButtonContainer *pResetID, const float LineSize, const float WantedPickerPosition, const float LabelSize, const float BottomMargin, CUIRect *pMainRect, const char *pText, unsigned int *pColorValue, const ColorRGBA DefaultColor, bool CheckBoxSpacing, bool UseCheckBox, int *pCheckBoxValue) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 66f6fd18b..99be4f151 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -87,8 +87,9 @@ class CMenus : public CComponent int DoButton_CheckBox(const void *pID, const char *pText, int Checked, const CUIRect *pRect); int DoButton_CheckBoxAutoVMarginAndSet(const void *pID, const char *pText, int *pValue, CUIRect *pRect, float VMargin); int DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect); + ColorHSLA DoLine_ColorPicker(CButtonContainer *pResetID, float LineSize, float WantedPickerPosition, float LabelSize, float BottomMargin, CUIRect *pMainRect, const char *pText, unsigned int *pColorValue, ColorRGBA DefaultColor, bool CheckBoxSpacing = true, bool UseCheckBox = false, int *pCheckBoxValue = nullptr); - void DoLaserPreview(const CUIRect *pRect, ColorHSLA OutlineColor, ColorHSLA InnerColor); + void DoLaserPreview(const CUIRect *pRect, ColorHSLA OutlineColor, ColorHSLA InnerColor, const int LaserType); int DoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, bool UseScroll, int Current, int Min, int Max, int Step, float Scale, bool IsHex, float Round, ColorRGBA *pColor); int DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect); diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp index 417d591b7..cc9761604 100644 --- a/src/game/client/components/menus_settings.cpp +++ b/src/game/client/components/menus_settings.cpp @@ -2966,18 +2966,34 @@ void CMenus::RenderSettingsAppearance(CUIRect MainView) { MainView.VSplitMid(&LeftView, &RightView); - // ***** Laser ***** // + // ***** Weapons ***** // LeftView.HSplitTop(HeadlineAndVMargin, &Label, &LeftView); - UI()->DoLabel(&Label, Localize("Laser"), HeadlineFontSize, TEXTALIGN_LEFT); + UI()->DoLabel(&Label, Localize("Weapons"), HeadlineFontSize, TEXTALIGN_LEFT); - // General laser settings - LeftView.HSplitTop(SectionTotalMargin + 2 * ColorPickerLineSize, &Section, &LeftView); + // General weapon laser settings + LeftView.HSplitTop(SectionTotalMargin + 4 * ColorPickerLineSize, &Section, &LeftView); Section.Margin(SectionMargin, &Section); - static CButtonContainer s_LaserOutResetID, s_LaserInResetID; + static CButtonContainer s_LaserRifleOutResetID, s_LaserRifleInResetID, s_LaserShotgunOutResetID, s_LaserShotgunInResetID; - ColorHSLA LaserOutlineColor = DoLine_ColorPicker(&s_LaserOutResetID, ColorPickerLineSize, LeftViewColorPickerPosition, ColorPickerLabelSize, ColorPickerLineSpacing, &Section, Localize("Laser Outline Color"), &g_Config.m_ClLaserOutlineColor, ColorRGBA(0.074402f, 0.074402f, 0.247166f, 1.0f), false); - ColorHSLA LaserInnerColor = DoLine_ColorPicker(&s_LaserInResetID, ColorPickerLineSize, LeftViewColorPickerPosition, ColorPickerLabelSize, ColorPickerLineSpacing, &Section, Localize("Laser Inner Color"), &g_Config.m_ClLaserInnerColor, ColorRGBA(0.498039f, 0.498039f, 1.0f, 1.0f), false); + ColorHSLA LaserRifleOutlineColor = DoLine_ColorPicker(&s_LaserRifleOutResetID, ColorPickerLineSize, LeftViewColorPickerPosition, ColorPickerLabelSize, ColorPickerLineSpacing, &Section, Localize("Rifle Laser Outline Color"), &g_Config.m_ClLaserRifleOutlineColor, ColorRGBA(0.074402f, 0.074402f, 0.247166f, 1.0f), false); + ColorHSLA LaserRifleInnerColor = DoLine_ColorPicker(&s_LaserRifleInResetID, ColorPickerLineSize, LeftViewColorPickerPosition, ColorPickerLabelSize, ColorPickerLineSpacing, &Section, Localize("Rifle Laser Inner Color"), &g_Config.m_ClLaserRifleInnerColor, ColorRGBA(0.498039f, 0.498039f, 1.0f, 1.0f), false); + ColorHSLA LaserShotgunOutlineColor = DoLine_ColorPicker(&s_LaserShotgunOutResetID, ColorPickerLineSize, LeftViewColorPickerPosition, ColorPickerLabelSize, ColorPickerLineSpacing, &Section, Localize("Shotgun Laser Outline Color"), &g_Config.m_ClLaserShotgunOutlineColor, ColorRGBA(0.125490f, 0.098039f, 0.043137f, 1.0f), false); + ColorHSLA LaserShotgunInnerColor = DoLine_ColorPicker(&s_LaserShotgunInResetID, ColorPickerLineSize, LeftViewColorPickerPosition, ColorPickerLabelSize, ColorPickerLineSpacing, &Section, Localize("Shotgun Laser Inner Color"), &g_Config.m_ClLaserShotgunInnerColor, ColorRGBA(0.764705f, 0.505882f, 0.0f, 1.0f), false); + // ***** Entities ***** // + LeftView.HSplitTop(HeadlineAndVMargin, &Label, &LeftView); + UI()->DoLabel(&Label, Localize("Entities"), HeadlineFontSize, TEXTALIGN_LEFT); + + // General entity laser settings + LeftView.HSplitTop(SectionTotalMargin + 4 * ColorPickerLineSize, &Section, &LeftView); + Section.Margin(SectionMargin, &Section); + + static CButtonContainer s_LaserDoorOutResetID, s_LaserDoorInResetID, s_LaserFreezeOutResetID, s_LaserFreezeInResetID; + + ColorHSLA LaserDoorOutlineColor = DoLine_ColorPicker(&s_LaserDoorOutResetID, ColorPickerLineSize, LeftViewColorPickerPosition, ColorPickerLabelSize, ColorPickerLineSpacing, &Section, Localize("Door Laser Outline Color"), &g_Config.m_ClLaserDoorOutlineColor, ColorRGBA(0.0f, 0.129411f, 0.094117f, 1.0f), false); + ColorHSLA LaserDoorInnerColor = DoLine_ColorPicker(&s_LaserDoorInResetID, ColorPickerLineSize, LeftViewColorPickerPosition, ColorPickerLabelSize, ColorPickerLineSpacing, &Section, Localize("Door Laser Inner Color"), &g_Config.m_ClLaserDoorInnerColor, ColorRGBA(0.262745f, 0.760784f, 0.639215f, 1.0f), false); + ColorHSLA LaserFreezeOutlineColor = DoLine_ColorPicker(&s_LaserFreezeOutResetID, ColorPickerLineSize, LeftViewColorPickerPosition, ColorPickerLabelSize, ColorPickerLineSpacing, &Section, Localize("Freeze Laser Outline Color"), &g_Config.m_ClLaserFreezeOutlineColor, ColorRGBA(0.192156f, 0.031372f, 0.074509f, 1.0f), false); + ColorHSLA LaserFreezeInnerColor = DoLine_ColorPicker(&s_LaserFreezeInResetID, ColorPickerLineSize, LeftViewColorPickerPosition, ColorPickerLabelSize, ColorPickerLineSpacing, &Section, Localize("Freeze Laser Inner Color"), &g_Config.m_ClLaserFreezeInnerColor, ColorRGBA(0.760784f, 0.262745f, 0.403921f, 1.0f), false); // ***** Laser Preview ***** // RightView.HSplitTop(HeadlineAndVMargin, &Label, &RightView); @@ -2985,8 +3001,19 @@ void CMenus::RenderSettingsAppearance(CUIRect MainView) RightView.HSplitTop(SectionTotalMargin + 50.0f, &Section, &RightView); Section.Margin(SectionMargin, &Section); + DoLaserPreview(&Section, LaserRifleOutlineColor, LaserRifleInnerColor, LASERTYPE_RIFLE); - DoLaserPreview(&Section, LaserOutlineColor, LaserInnerColor); + RightView.HSplitTop(SectionTotalMargin + 50.0f, &Section, &RightView); + Section.Margin(SectionMargin, &Section); + DoLaserPreview(&Section, LaserShotgunOutlineColor, LaserShotgunInnerColor, LASERTYPE_SHOTGUN); + + RightView.HSplitTop(SectionTotalMargin + 50.0f, &Section, &RightView); + Section.Margin(SectionMargin, &Section); + DoLaserPreview(&Section, LaserDoorOutlineColor, LaserDoorInnerColor, LASERTYPE_DOOR); + + RightView.HSplitTop(SectionTotalMargin + 50.0f, &Section, &RightView); + Section.Margin(SectionMargin, &Section); + DoLaserPreview(&Section, LaserFreezeOutlineColor, LaserFreezeInnerColor, LASERTYPE_DOOR); } } From 5deeb299fa01ac10aad5d08416b002dbbda948d3 Mon Sep 17 00:00:00 2001 From: fokkonaut <35420825+fokkonaut@users.noreply.github.com> Date: Thu, 15 Sep 2022 00:49:40 +0200 Subject: [PATCH 3/3] Add DDNetLaser to have more info about a laser shot --- CMakeLists.txt | 2 + datasrc/network.py | 10 +++ src/engine/shared/protocol.h | 1 + src/game/client/components/items.cpp | 87 ++++++++++++++----- src/game/client/components/items.h | 3 +- src/game/client/gameclient.cpp | 2 +- src/game/client/laser_data.cpp | 40 +++++++++ src/game/client/laser_data.h | 28 ++++++ src/game/client/prediction/entities/laser.cpp | 26 ++++-- src/game/client/prediction/entities/laser.h | 5 +- src/game/client/prediction/gameworld.cpp | 34 +++++++- src/game/server/entities/laser.cpp | 34 ++++++-- 12 files changed, 232 insertions(+), 40 deletions(-) create mode 100644 src/game/client/laser_data.cpp create mode 100644 src/game/client/laser_data.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d8f2328e..7ea43b034 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2073,6 +2073,8 @@ if(CLIENT) components/voting.h gameclient.cpp gameclient.h + laser_data.cpp + laser_data.h lineinput.cpp lineinput.h prediction/entities/character.cpp diff --git a/datasrc/network.py b/datasrc/network.py index 57b89f7d5..021392950 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -276,6 +276,16 @@ Objects = [ NetTick("m_StartTick"), ]), + NetObjectEx("DDNetLaser", "laser@netobj.ddnet.tw", [ + NetIntAny("m_ToX"), + NetIntAny("m_ToY"), + NetIntAny("m_FromX"), + NetIntAny("m_FromY"), + NetTick("m_StartTick"), + NetIntRange("m_Owner", 0, 'MAX_CLIENTS-1'), + NetIntAny("m_Type"), + ]), + ## Events NetEvent("Common", [ diff --git a/src/engine/shared/protocol.h b/src/engine/shared/protocol.h index ed60441a2..fe84c85c9 100644 --- a/src/engine/shared/protocol.h +++ b/src/engine/shared/protocol.h @@ -120,6 +120,7 @@ enum VERSION_DDNET_INDEPENDENT_SPECTATORS_TEAM = 16000, VERSION_DDNET_WEAPON_SHIELDS = 16010, VERSION_DDNET_NEW_HUD = 16020, + VERSION_DDNET_MULTI_LASER = 16040, }; #endif diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index b9d5a96e1..690a72ccc 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -237,18 +238,52 @@ void CItems::RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent, Graphics()->RenderQuadContainerAsSprite(m_ItemsQuadContainerIndex, QuadOffset, Pos.x, Pos.y - Size * 0.75f); } -void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent, bool IsPredicted) +void CItems::RenderLaser(const CLaserData *pCurrent, bool IsPredicted) { + int Type = clamp(pCurrent->m_Type, -1, NUM_LASERTYPES - 1); + ColorRGBA RGB; - vec2 Pos = vec2(pCurrent->m_X, pCurrent->m_Y); - vec2 From = vec2(pCurrent->m_FromX, pCurrent->m_FromY); + vec2 Pos = pCurrent->m_To; + vec2 From = pCurrent->m_From; float Len = distance(Pos, From); - RGB = color_cast(ColorHSLA(g_Config.m_ClLaserRifleOutlineColor)); + + int ColorIn, ColorOut; + switch(Type) + { + case LASERTYPE_RIFLE: + ColorOut = g_Config.m_ClLaserRifleOutlineColor; + ColorIn = g_Config.m_ClLaserRifleInnerColor; + break; + case LASERTYPE_SHOTGUN: + ColorOut = g_Config.m_ClLaserShotgunOutlineColor; + ColorIn = g_Config.m_ClLaserShotgunInnerColor; + break; + case LASERTYPE_DOOR: + ColorOut = g_Config.m_ClLaserDoorOutlineColor; + ColorIn = g_Config.m_ClLaserDoorInnerColor; + break; + case LASERTYPE_FREEZE: + ColorOut = g_Config.m_ClLaserFreezeOutlineColor; + ColorIn = g_Config.m_ClLaserFreezeInnerColor; + break; + default: + ColorOut = g_Config.m_ClLaserRifleOutlineColor; + ColorIn = g_Config.m_ClLaserRifleInnerColor; + } + + RGB = color_cast(ColorHSLA(ColorOut)); ColorRGBA OuterColor(RGB.r, RGB.g, RGB.b, 1.0f); - RGB = color_cast(ColorHSLA(g_Config.m_ClLaserRifleInnerColor)); + RGB = color_cast(ColorHSLA(ColorIn)); ColorRGBA InnerColor(RGB.r, RGB.g, RGB.b, 1.0f); int TuneZone = GameClient()->m_GameWorld.m_WorldConfig.m_UseTuneZones ? Collision()->IsTune(Collision()->GetMapIndex(From)) : 0; + bool IsOtherTeam = (pCurrent->m_ExtraInfo && pCurrent->m_Owner >= 0 && m_pClient->IsOtherTeam(pCurrent->m_Owner)); + + float Alpha = 1.f; + if(IsOtherTeam) + { + Alpha = g_Config.m_ClShowOthersAlpha / 100.0f; + } vec2 Dir; if(Len > 0) @@ -271,7 +306,7 @@ void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent, bool IsPredicted) Graphics()->QuadsBegin(); // do outline - Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f); + Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, Alpha); Out = vec2(Dir.y, -Dir.x) * (7.0f * Ia); IGraphics::CFreeformItem Freeform( @@ -283,7 +318,7 @@ void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent, bool IsPredicted) // do inner Out = vec2(Dir.y, -Dir.x) * (5.0f * Ia); - Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, 1.0f); // center + Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, Alpha); // center Freeform = IGraphics::CFreeformItem( From.x - Out.x, From.y - Out.y, @@ -300,9 +335,9 @@ void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent, bool IsPredicted) int CurParticle = (Client()->GameTick(g_Config.m_ClDummy) % 3); Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_aSpriteParticleSplat[CurParticle]); 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, Alpha); Graphics()->RenderQuadContainerAsSprite(m_ItemsQuadContainerIndex, m_aParticleSplatOffset[CurParticle], Pos.x, Pos.y); - Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, 1.0f); + Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, Alpha); Graphics()->RenderQuadContainerAsSprite(m_ItemsQuadContainerIndex, m_aParticleSplatOffset[CurParticle], Pos.x, Pos.y, 20.f / 24.f, 20.f / 24.f); } } @@ -341,8 +376,7 @@ void CItems::OnRender() auto *const pLaser = dynamic_cast(pEnt); if(!pLaser || pLaser->GetOwner() < 0 || !GameClient()->m_aClients[pLaser->GetOwner()].m_IsPredictedLocal) continue; - CNetObj_Laser Data; - pLaser->FillInfo(&Data); + CLaserData Data = pLaser->GetData(); RenderLaser(&Data, true); } for(auto *pPickup = (CPickup *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PICKUP); pPickup; pPickup = (CPickup *)pPickup->NextEntity()) @@ -419,7 +453,7 @@ void CItems::OnRender() if(pPrev) RenderPickup((const CNetObj_Pickup *)pPrev, (const CNetObj_Pickup *)pData); } - else if(Item.m_Type == NETOBJTYPE_LASER) + else if(Item.m_Type == NETOBJTYPE_LASER || Item.m_Type == NETOBJTYPE_DDNETLASER) { if(UsePredicted) { @@ -427,7 +461,16 @@ void CItems::OnRender() if(pLaser && pLaser->GetOwner() >= 0 && GameClient()->m_aClients[pLaser->GetOwner()].m_IsPredictedLocal) continue; } - CNetObj_Laser Laser = *((const CNetObj_Laser *)pData); + + CLaserData Data; + if(Item.m_Type == NETOBJTYPE_LASER) + { + Data = ExtractLaserInfo((const CNetObj_Laser *)pData, &GameClient()->m_GameWorld); + } + else + { + Data = ExtractLaserInfoDDNet((const CNetObj_DDNetLaser *)pData, &GameClient()->m_GameWorld); + } if(pEntEx) { @@ -435,31 +478,35 @@ void CItems::OnRender() { if(Inactive && BlinkingLight) continue; - Laser.m_StartTick = DraggerStartTick; + Data.m_StartTick = DraggerStartTick; + Data.m_Type = LASERTYPE_FREEZE; } if(pEntEx->m_EntityClass >= ENTITYCLASS_GUN_NORMAL && pEntEx->m_EntityClass <= ENTITYCLASS_GUN_UNFREEZE) { if(Inactive && BlinkingGun) continue; - Laser.m_StartTick = GunStartTick; + Data.m_StartTick = GunStartTick; + Data.m_Type = pEntEx->m_EntityClass == ENTITYCLASS_GUN_FREEZE ? LASERTYPE_FREEZE : LASERTYPE_DOOR; } if(pEntEx->m_EntityClass >= ENTITYCLASS_DRAGGER_WEAK && pEntEx->m_EntityClass <= ENTITYCLASS_DRAGGER_STRONG) { if(Inactive && BlinkingDragger) continue; - Laser.m_StartTick = DraggerStartTick; + Data.m_StartTick = DraggerStartTick; + Data.m_Type = LASERTYPE_DOOR; } if(pEntEx->m_EntityClass == ENTITYCLASS_DOOR) { if(Inactive || IsSuper) { - Laser.m_FromX = Laser.m_X; - Laser.m_FromY = Laser.m_Y; + Data.m_From.x = Data.m_To.x; + Data.m_From.y = Data.m_To.y; } - Laser.m_StartTick = Client()->GameTick(g_Config.m_ClDummy); + Data.m_StartTick = Client()->GameTick(g_Config.m_ClDummy); + Data.m_Type = LASERTYPE_DOOR; } } - RenderLaser(&Laser); + RenderLaser(&Data); } } diff --git a/src/game/client/components/items.h b/src/game/client/components/items.h index f3e8da74a..d7fef4d97 100644 --- a/src/game/client/components/items.h +++ b/src/game/client/components/items.h @@ -6,13 +6,14 @@ #include class CProjectileData; +class CLaserData; class CItems : public CComponent { void RenderProjectile(const CProjectileData *pCurrent, int ItemID); void RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCurrent, bool IsPredicted = false); void RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent, const CNetObj_GameData *pPrevGameData, const CNetObj_GameData *pCurGameData); - void RenderLaser(const struct CNetObj_Laser *pCurrent, bool IsPredicted = false); + void RenderLaser(const CLaserData *pCurrent, bool IsPredicted = false); int m_ItemsQuadContainerIndex; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index d79f63dd7..9e4de7a66 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -3311,7 +3311,7 @@ void CGameClient::SnapCollectEntities() const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item); if(Item.m_Type == NETOBJTYPE_ENTITYEX) vItemEx.push_back({Item, pData, 0}); - else if(Item.m_Type == NETOBJTYPE_PICKUP || Item.m_Type == NETOBJTYPE_LASER || Item.m_Type == NETOBJTYPE_PROJECTILE || Item.m_Type == NETOBJTYPE_DDNETPROJECTILE) + else if(Item.m_Type == NETOBJTYPE_PICKUP || Item.m_Type == NETOBJTYPE_LASER || Item.m_Type == NETOBJTYPE_DDNETLASER || Item.m_Type == NETOBJTYPE_PROJECTILE || Item.m_Type == NETOBJTYPE_DDNETPROJECTILE) vItemData.push_back({Item, pData, 0}); } diff --git a/src/game/client/laser_data.cpp b/src/game/client/laser_data.cpp new file mode 100644 index 000000000..c29ffa593 --- /dev/null +++ b/src/game/client/laser_data.cpp @@ -0,0 +1,40 @@ +/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ +/* If you are missing that file, acquire a complete release at teeworlds.com. */ + +#include "laser_data.h" + +#include +#include +#include + +#include + +CLaserData ExtractLaserInfo(const CNetObj_Laser *pLaser, CGameWorld *pGameWorld) +{ + CLaserData Result = {vec2(0, 0)}; + Result.m_From.x = pLaser->m_FromX; + Result.m_From.y = pLaser->m_FromY; + Result.m_To.x = pLaser->m_X; + Result.m_To.y = pLaser->m_Y; + Result.m_StartTick = pLaser->m_StartTick; + Result.m_ExtraInfo = false; + Result.m_Owner = -1; + Result.m_Type = -1; + Result.m_TuneZone = pGameWorld && pGameWorld->m_WorldConfig.m_UseTuneZones ? pGameWorld->Collision()->IsTune(pGameWorld->Collision()->GetMapIndex(Result.m_From)) : 0; + return Result; +} + +CLaserData ExtractLaserInfoDDNet(const CNetObj_DDNetLaser *pLaser, CGameWorld *pGameWorld) +{ + CLaserData Result = {vec2(0, 0)}; + Result.m_From.x = pLaser->m_FromX; + Result.m_From.y = pLaser->m_FromY; + Result.m_To.x = pLaser->m_ToX; + Result.m_To.y = pLaser->m_ToY; + Result.m_StartTick = pLaser->m_StartTick; + Result.m_ExtraInfo = true; + Result.m_Owner = pLaser->m_Owner; + Result.m_Type = pLaser->m_Type; + Result.m_TuneZone = pGameWorld && pGameWorld->m_WorldConfig.m_UseTuneZones ? pGameWorld->Collision()->IsTune(pGameWorld->Collision()->GetMapIndex(Result.m_From)) : 0; + return Result; +} diff --git a/src/game/client/laser_data.h b/src/game/client/laser_data.h new file mode 100644 index 000000000..d48576f5d --- /dev/null +++ b/src/game/client/laser_data.h @@ -0,0 +1,28 @@ +/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ +/* If you are missing that file, acquire a complete release at teeworlds.com. */ +#ifndef GAME_CLIENT_LASER_DATA_H +#define GAME_CLIENT_LASER_DATA_H + +#include + +struct CNetObj_Laser; +struct CNetObj_DDNetLaser; + +class CLaserData +{ +public: + vec2 m_From; + vec2 m_To; + int m_StartTick; + bool m_ExtraInfo; + // The rest is only set if m_ExtraInfo is true. + int m_Owner; + int m_Type; + // TuneZone is introduced locally + int m_TuneZone; +}; + +CLaserData ExtractLaserInfo(const CNetObj_Laser *pLaser, class CGameWorld *pGameWorld); +CLaserData ExtractLaserInfoDDNet(const CNetObj_DDNetLaser *pLaser, class CGameWorld *pGameWorld); + +#endif // GAME_CLIENT_LASER_DATA_H diff --git a/src/game/client/prediction/entities/laser.cpp b/src/game/client/prediction/entities/laser.cpp index 7cbd812f5..2f1c3224a 100644 --- a/src/game/client/prediction/entities/laser.cpp +++ b/src/game/client/prediction/entities/laser.cpp @@ -2,6 +2,7 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include "laser.h" #include "character.h" +#include #include #include #include @@ -185,13 +186,11 @@ void CLaser::Tick() } } -CLaser::CLaser(CGameWorld *pGameWorld, int ID, CNetObj_Laser *pLaser) : +CLaser::CLaser(CGameWorld *pGameWorld, int ID, CLaserData *pLaser) : CEntity(pGameWorld, CGameWorld::ENTTYPE_LASER) { - m_Pos.x = pLaser->m_X; - m_Pos.y = pLaser->m_Y; - m_From.x = pLaser->m_FromX; - m_From.y = pLaser->m_FromY; + m_Pos = pLaser->m_To; + m_From = pLaser->m_From; m_EvalTick = pLaser->m_StartTick; m_TuneZone = GameWorld()->m_WorldConfig.m_UseTuneZones ? Collision()->IsTune(Collision()->GetMapIndex(m_Pos)) : 0; m_Owner = -2; @@ -204,7 +203,7 @@ CLaser::CLaser(CGameWorld *pGameWorld, int ID, CNetObj_Laser *pLaser) : m_Dir = normalize(m_Dir); else m_Energy = 0; - m_Type = WEAPON_LASER; + m_Type = pLaser->m_Type == LASERTYPE_SHOTGUN ? WEAPON_SHOTGUN : WEAPON_LASER; m_PrevPos = m_From; m_ID = ID; } @@ -229,3 +228,18 @@ bool CLaser::Match(CLaser *pLaser) const float DirError = distance(normalize(OtherDiff) * length(ThisDiff), ThisDiff); return DirError <= 2.f; } + +CLaserData CLaser::GetData() const +{ + CLaserData Result; + Result.m_From.x = m_From.x; + Result.m_From.y = m_From.y; + Result.m_To.x = m_Pos.x; + Result.m_To.y = m_Pos.y; + Result.m_StartTick = m_EvalTick; + Result.m_ExtraInfo = true; + Result.m_Owner = m_Owner; + Result.m_Type = m_Type == WEAPON_SHOTGUN ? LASERTYPE_SHOTGUN : LASERTYPE_RIFLE; + Result.m_TuneZone = m_TuneZone; + return Result; +} diff --git a/src/game/client/prediction/entities/laser.h b/src/game/client/prediction/entities/laser.h index 1069edb4f..738b2d9ed 100644 --- a/src/game/client/prediction/entities/laser.h +++ b/src/game/client/prediction/entities/laser.h @@ -5,6 +5,8 @@ #include +class CLaserData; + class CLaser : public CEntity { friend class CGameWorld; @@ -17,9 +19,10 @@ public: const vec2 &GetFrom() { return m_From; } const int &GetOwner() { return m_Owner; } const int &GetEvalTick() { return m_EvalTick; } - CLaser(CGameWorld *pGameWorld, int ID, CNetObj_Laser *pLaser); + CLaser(CGameWorld *pGameWorld, int ID, CLaserData *pLaser); void FillInfo(CNetObj_Laser *pLaser); bool Match(CLaser *pLaser); + CLaserData GetData() const; protected: bool HitCharacter(vec2 From, vec2 To); diff --git a/src/game/client/prediction/gameworld.cpp b/src/game/client/prediction/gameworld.cpp index 20f4f7fe6..4eecef306 100644 --- a/src/game/client/prediction/gameworld.cpp +++ b/src/game/client/prediction/gameworld.cpp @@ -9,6 +9,7 @@ #include "entity.h" #include #include +#include #include #include #include @@ -480,9 +481,18 @@ void CGameWorld::NetObjAdd(int ObjID, int ObjType, const void *pObjData, const C CEntity *pEnt = new CPickup(NetPickup); InsertEntity(pEnt, true); } - else if(ObjType == NETOBJTYPE_LASER && m_WorldConfig.m_PredictWeapons) + else if((ObjType == NETOBJTYPE_LASER || ObjType == NETOBJTYPE_DDNETLASER) && m_WorldConfig.m_PredictWeapons) { - CLaser NetLaser = CLaser(this, ObjID, (CNetObj_Laser *)pObjData); + CLaserData Data; + if(ObjType == NETOBJTYPE_PROJECTILE) + { + Data = ExtractLaserInfo((const CNetObj_Laser *)pObjData, this); + } + else + { + Data = ExtractLaserInfoDDNet((const CNetObj_DDNetLaser *)pObjData, this); + } + CLaser NetLaser = CLaser(this, ObjID, &Data); CLaser *pMatching = 0; if(CLaser *pLaser = dynamic_cast(GetEntity(ObjID, ENTTYPE_LASER))) if(NetLaser.Match(pLaser)) @@ -632,7 +642,25 @@ CEntity *CGameWorld::FindMatch(int ObjID, int ObjType, const void *pObjData) } return 0; } - case NETOBJTYPE_LASER: FindType(ENTTYPE_LASER, CLaser, CNetObj_Laser); + case NETOBJTYPE_LASER: + case NETOBJTYPE_DDNETLASER: + { + CLaserData Data; + if(ObjType == NETOBJTYPE_LASER) + { + Data = ExtractLaserInfo((const CNetObj_Laser *)pObjData, this); + } + else + { + Data = ExtractLaserInfoDDNet((const CNetObj_DDNetLaser *)pObjData, this); + } + CLaser *pEnt = (CLaser *)GetEntity(ObjID, ENTTYPE_LASER); + if(pEnt && CLaser(this, ObjID, &Data).Match(pEnt)) + { + return pEnt; + } + return 0; + } case NETOBJTYPE_PICKUP: FindType(ENTTYPE_PICKUP, CPickup, CNetObj_Pickup); } return 0; diff --git a/src/game/server/entities/laser.cpp b/src/game/server/entities/laser.cpp index 3e5e37411..424217d4c 100644 --- a/src/game/server/entities/laser.cpp +++ b/src/game/server/entities/laser.cpp @@ -313,15 +313,33 @@ void CLaser::Snap(int SnappingClient) if(SnappingClient != SERVER_DEMO_CLIENT && !CmaskIsSet(TeamMask, SnappingClient)) return; - CNetObj_Laser *pObj = static_cast(Server()->SnapNewItem(NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser))); - if(!pObj) - return; - pObj->m_X = (int)m_Pos.x; - pObj->m_Y = (int)m_Pos.y; - pObj->m_FromX = (int)m_From.x; - pObj->m_FromY = (int)m_From.y; - pObj->m_StartTick = m_EvalTick; + if(GameServer()->GetClientVersion(SnappingClient) >= VERSION_DDNET_MULTI_LASER) + { + CNetObj_DDNetLaser *pObj = static_cast(Server()->SnapNewItem(NETOBJTYPE_DDNETLASER, GetID(), sizeof(CNetObj_DDNetLaser))); + if(!pObj) + return; + + pObj->m_ToX = (int)m_Pos.x; + pObj->m_ToY = (int)m_Pos.y; + pObj->m_FromX = (int)m_From.x; + pObj->m_FromY = (int)m_From.y; + pObj->m_StartTick = m_EvalTick; + pObj->m_Owner = m_Owner; + pObj->m_Type = m_Type == WEAPON_LASER ? LASERTYPE_RIFLE : m_Type == WEAPON_SHOTGUN ? LASERTYPE_SHOTGUN : -1; + } + else + { + CNetObj_Laser *pObj = static_cast(Server()->SnapNewItem(NETOBJTYPE_LASER, GetID(), sizeof(CNetObj_Laser))); + if(!pObj) + return; + + pObj->m_X = (int)m_Pos.x; + pObj->m_Y = (int)m_Pos.y; + pObj->m_FromX = (int)m_From.x; + pObj->m_FromY = (int)m_From.y; + pObj->m_StartTick = m_EvalTick; + } } void CLaser::SwapClients(int Client1, int Client2)