mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
6684: Make server settings editor height adjustable by dragging r=heinrich5991 a=Robyt3 Same as for the envelope editor. Extract `RenderExtraEditorDragBar` function to reduce duplicate code. Fix height being changed by repeated clicking on the draggable element by also resetting `s_Operation` when `Clicked` is `true`. ## 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 (especially base/) or added coverage to integration test - [ ] Considered possible null pointers and out of bounds array indexing - [ ] Changed no physics that affect existing maps - [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional) 6685: Support dragging demo player controls to move them, fix minor related issues r=heinrich5991 a=Robyt3 Allow dragging the demo player controls anywhere on the screen. The controls can't be moved outside of the screen. Round corners are automatically disabled when the controls are on the edge of the screen. https://github.com/ddnet/ddnet/assets/23437060/72510c1f-4fd2-426b-a631-3a78db5f7b8b ## Checklist - [X] Tested the change ingame - [X] Provided screenshots if it is a visual change - [ ] Tested in combination with possibly related configuration options - [ ] Written a unit test (especially base/) or added coverage to integration test - [ ] Considered possible null pointers and out of bounds array indexing - [ ] Changed no physics that affect existing maps - [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional) 6699: Add dragger prediction r=def- a=trml ..for servers with the new ddnetlaser. Tested this locally and on Fun server, and seems to work. Also adjusted the criteria for when to send the original dragger id slightly, to improve prediction in some edge cases when going through solo/unsolo while being dragged. ## 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 (especially base/) or added coverage to integration test - [ ] Considered possible null pointers and out of bounds array indexing - [ ] Changed no physics that affect existing maps - [ ] 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: Robert Müller <robytemueller@gmail.com> Co-authored-by: trml <trml@users.noreply.github.com>
This commit is contained in:
commit
c227ed4bc5
|
@ -2260,6 +2260,8 @@ if(CLIENT)
|
|||
pickup_data.h
|
||||
prediction/entities/character.cpp
|
||||
prediction/entities/character.h
|
||||
prediction/entities/dragger.cpp
|
||||
prediction/entities/dragger.h
|
||||
prediction/entities/laser.cpp
|
||||
prediction/entities/laser.h
|
||||
prediction/entities/pickup.cpp
|
||||
|
|
|
@ -2220,14 +2220,8 @@ bool CMenus::OnCursorMove(float x, float y, IInput::ECursorType CursorType)
|
|||
|
||||
bool CMenus::OnInput(const IInput::CEvent &Event)
|
||||
{
|
||||
// special handle esc and enter for popup purposes
|
||||
if(Event.m_Flags & IInput::FLAG_PRESS && Event.m_Key == KEY_ESCAPE)
|
||||
{
|
||||
SetActive(!IsActive());
|
||||
UI()->OnInput(Event);
|
||||
return true;
|
||||
}
|
||||
if(IsActive())
|
||||
// Escape key is always handled to activate/deactivate menu
|
||||
if((Event.m_Flags & IInput::FLAG_PRESS && Event.m_Key == KEY_ESCAPE) || IsActive())
|
||||
{
|
||||
UI()->OnInput(Event);
|
||||
return true;
|
||||
|
@ -2308,6 +2302,8 @@ void CMenus::OnRender()
|
|||
|
||||
if(!IsActive())
|
||||
{
|
||||
if(UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))
|
||||
SetActive(true);
|
||||
UI()->FinishCheck();
|
||||
UI()->ClearHotkeys();
|
||||
return;
|
||||
|
@ -2359,6 +2355,9 @@ void CMenus::OnRender()
|
|||
TextRender()->TextEx(&Cursor, aBuf, -1);
|
||||
}
|
||||
|
||||
if(UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))
|
||||
SetActive(false);
|
||||
|
||||
UI()->FinishCheck();
|
||||
UI()->ClearHotkeys();
|
||||
}
|
||||
|
|
|
@ -437,6 +437,7 @@ protected:
|
|||
void UpdateMusicState();
|
||||
|
||||
// found in menus_demo.cpp
|
||||
vec2 m_DemoControlsPositionOffset = vec2(0.0f, 0.0f);
|
||||
static bool DemoFilterChat(const void *pData, int Size, void *pUser);
|
||||
bool FetchHeader(CDemoItem &Item);
|
||||
void FetchAllHeaders();
|
||||
|
|
|
@ -223,7 +223,20 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
|
|||
MainView.HSplitBottom(TotalHeight, nullptr, &DemoControls);
|
||||
DemoControls.VSplitLeft(50.0f, nullptr, &DemoControls);
|
||||
DemoControls.VSplitLeft(600.0f, &DemoControls, nullptr);
|
||||
DemoControls.Draw(ms_ColorTabbarActive, IGraphics::CORNER_T, 10.0f);
|
||||
const CUIRect DemoControlsOriginal = DemoControls;
|
||||
DemoControls.x += m_DemoControlsPositionOffset.x;
|
||||
DemoControls.y += m_DemoControlsPositionOffset.y;
|
||||
int Corners = IGraphics::CORNER_NONE;
|
||||
if(DemoControls.x > 0.0f && DemoControls.y > 0.0f)
|
||||
Corners |= IGraphics::CORNER_TL;
|
||||
if(DemoControls.x < MainView.w - DemoControls.w && DemoControls.y > 0.0f)
|
||||
Corners |= IGraphics::CORNER_TR;
|
||||
if(DemoControls.x > 0.0f && DemoControls.y < MainView.h - DemoControls.h)
|
||||
Corners |= IGraphics::CORNER_BL;
|
||||
if(DemoControls.x < MainView.w - DemoControls.w && DemoControls.y < MainView.h - DemoControls.h)
|
||||
Corners |= IGraphics::CORNER_BR;
|
||||
DemoControls.Draw(ms_ColorTabbarActive, Corners, 10.0f);
|
||||
const CUIRect DemoControlsDragRect = DemoControls;
|
||||
|
||||
CUIRect SeekBar, ButtonBar, NameBar, SpeedBar;
|
||||
DemoControls.Margin(5.0f, &DemoControls);
|
||||
|
@ -232,6 +245,45 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
|
|||
ButtonBar.HSplitBottom(NameBarHeight, &ButtonBar, &NameBar);
|
||||
NameBar.HSplitTop(4.0f, nullptr, &NameBar);
|
||||
|
||||
// handle draggable demo controls
|
||||
{
|
||||
enum EDragOperation
|
||||
{
|
||||
OP_NONE,
|
||||
OP_DRAGGING,
|
||||
OP_CLICKED
|
||||
};
|
||||
static EDragOperation s_Operation = OP_NONE;
|
||||
static vec2 s_InitialMouse = vec2(0.0f, 0.0f);
|
||||
|
||||
bool Clicked;
|
||||
bool Abrupted;
|
||||
if(int Result = UI()->DoDraggableButtonLogic(&s_Operation, 8, &DemoControlsDragRect, &Clicked, &Abrupted))
|
||||
{
|
||||
if(s_Operation == OP_NONE && Result == 1)
|
||||
{
|
||||
s_InitialMouse = UI()->MousePos();
|
||||
s_Operation = OP_CLICKED;
|
||||
}
|
||||
|
||||
if(Clicked || Abrupted)
|
||||
s_Operation = OP_NONE;
|
||||
|
||||
if(s_Operation == OP_CLICKED && length(UI()->MousePos() - s_InitialMouse) > 5.0f)
|
||||
{
|
||||
s_Operation = OP_DRAGGING;
|
||||
s_InitialMouse -= m_DemoControlsPositionOffset;
|
||||
}
|
||||
|
||||
if(s_Operation == OP_DRAGGING)
|
||||
{
|
||||
m_DemoControlsPositionOffset = UI()->MousePos() - s_InitialMouse;
|
||||
m_DemoControlsPositionOffset.x = clamp(m_DemoControlsPositionOffset.x, -DemoControlsOriginal.x, MainView.w - DemoControlsDragRect.w - DemoControlsOriginal.x);
|
||||
m_DemoControlsPositionOffset.y = clamp(m_DemoControlsPositionOffset.y, -DemoControlsOriginal.y, MainView.h - DemoControlsDragRect.h - DemoControlsOriginal.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do seekbar
|
||||
{
|
||||
const float Rounding = 5.0f;
|
||||
|
|
|
@ -30,6 +30,7 @@ void CTooltips::DoToolTip(const void *pID, const CUIRect *pNearRect, const char
|
|||
{
|
||||
uintptr_t ID = reinterpret_cast<uintptr_t>(pID);
|
||||
const auto result = m_Tooltips.emplace(ID, CTooltip{
|
||||
pID,
|
||||
*pNearRect,
|
||||
pText,
|
||||
WidthHint,
|
||||
|
@ -44,7 +45,7 @@ void CTooltips::DoToolTip(const void *pID, const CUIRect *pNearRect, const char
|
|||
|
||||
Tooltip.m_OnScreen = true;
|
||||
|
||||
if(UI()->MouseInside(&Tooltip.m_Rect))
|
||||
if(UI()->HotItem() == Tooltip.m_pID)
|
||||
{
|
||||
SetActiveTooltip(Tooltip);
|
||||
}
|
||||
|
@ -56,7 +57,7 @@ void CTooltips::OnRender()
|
|||
{
|
||||
CTooltip &Tooltip = m_ActiveTooltip.value();
|
||||
|
||||
if(!UI()->MouseInside(&Tooltip.m_Rect))
|
||||
if(UI()->HotItem() != Tooltip.m_pID)
|
||||
{
|
||||
Tooltip.m_OnScreen = false;
|
||||
ClearActiveTooltip();
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
struct CTooltip
|
||||
{
|
||||
const void *m_pID;
|
||||
CUIRect m_Rect;
|
||||
const char *m_pText;
|
||||
float m_WidthHint;
|
||||
|
|
161
src/game/client/prediction/entities/dragger.cpp
Normal file
161
src/game/client/prediction/entities/dragger.cpp
Normal file
|
@ -0,0 +1,161 @@
|
|||
/* (c) Shereef Marzouk. See "licence DDRace.txt" and the readme.txt in the root of the distribution for more information. */
|
||||
#include "dragger.h"
|
||||
#include "character.h"
|
||||
|
||||
#include <engine/shared/config.h>
|
||||
|
||||
#include <game/client/laser_data.h>
|
||||
#include <game/collision.h>
|
||||
#include <game/generated/protocol.h>
|
||||
#include <game/mapitems.h>
|
||||
|
||||
void CDragger::Tick()
|
||||
{
|
||||
if(GameWorld()->GameTick() % (int)(GameWorld()->GameTickSpeed() * 0.15f) == 0)
|
||||
{
|
||||
int Flags;
|
||||
int index = Collision()->IsMover(m_Pos.x, m_Pos.y, &Flags);
|
||||
if(index)
|
||||
{
|
||||
m_Core = Collision()->CpSpeed(index, Flags);
|
||||
}
|
||||
m_Pos += m_Core;
|
||||
|
||||
LookForPlayersToDrag();
|
||||
}
|
||||
|
||||
DraggerBeamTick();
|
||||
}
|
||||
|
||||
void CDragger::LookForPlayersToDrag()
|
||||
{
|
||||
// Create a list of players who are in the range of the dragger
|
||||
CEntity *apPlayersInRange[MAX_CLIENTS];
|
||||
mem_zero(apPlayersInRange, sizeof(apPlayersInRange));
|
||||
|
||||
int NumPlayersInRange = GameWorld()->FindEntities(m_Pos,
|
||||
g_Config.m_SvDraggerRange - CCharacterCore::PhysicalSize(),
|
||||
apPlayersInRange, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
|
||||
|
||||
// The closest player (within range) in a team is selected as the target
|
||||
int ClosestTargetId = -1;
|
||||
bool CanStillBeTeamTarget = false;
|
||||
int MinDistInTeam = 0;
|
||||
|
||||
for(int i = 0; i < NumPlayersInRange; i++)
|
||||
{
|
||||
CCharacter *pTarget = static_cast<CCharacter *>(apPlayersInRange[i]);
|
||||
const int &TargetTeam = pTarget->Team();
|
||||
|
||||
// Do not create a dragger beam for super player
|
||||
if(TargetTeam == TEAM_SUPER)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// If the dragger is disabled for the target's team, no dragger beam will be generated
|
||||
if(m_Layer == LAYER_SWITCH && m_Number > 0 &&
|
||||
!Switchers()[m_Number].m_aStatus[TargetTeam])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Dragger beams can be created only for reachable, alive players
|
||||
int IsReachable =
|
||||
m_IgnoreWalls ?
|
||||
!Collision()->IntersectNoLaserNW(m_Pos, pTarget->m_Pos, 0, 0) :
|
||||
!Collision()->IntersectNoLaser(m_Pos, pTarget->m_Pos, 0, 0);
|
||||
if(IsReachable)
|
||||
{
|
||||
const int &TargetClientId = pTarget->GetCID();
|
||||
int Distance = distance(pTarget->m_Pos, m_Pos);
|
||||
if(MinDistInTeam == 0 || MinDistInTeam > Distance)
|
||||
{
|
||||
MinDistInTeam = Distance;
|
||||
ClosestTargetId = TargetClientId;
|
||||
}
|
||||
if(TargetClientId == m_TargetId)
|
||||
{
|
||||
CanStillBeTeamTarget = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the closest player for each team as a target if the team does not have a target player yet
|
||||
if((m_TargetId != -1 && !CanStillBeTeamTarget) || m_TargetId == -1)
|
||||
{
|
||||
m_TargetId = ClosestTargetId;
|
||||
}
|
||||
}
|
||||
|
||||
void CDragger::DraggerBeamReset()
|
||||
{
|
||||
m_TargetId = -1;
|
||||
}
|
||||
|
||||
void CDragger::DraggerBeamTick()
|
||||
{
|
||||
CCharacter *pTarget = GameWorld()->GetCharacterByID(m_TargetId);
|
||||
if(!pTarget)
|
||||
{
|
||||
DraggerBeamReset();
|
||||
return;
|
||||
}
|
||||
|
||||
if(GameWorld()->GameTick() % (int)(GameWorld()->GameTickSpeed() * 0.15f) == 0)
|
||||
{
|
||||
if(m_Layer == LAYER_SWITCH && m_Number > 0 &&
|
||||
!Switchers()[m_Number].m_aStatus[pTarget->Team()])
|
||||
{
|
||||
DraggerBeamReset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// When the dragger can no longer reach the target player, the dragger beam dissolves
|
||||
int IsReachable =
|
||||
m_IgnoreWalls ?
|
||||
!Collision()->IntersectNoLaserNW(m_Pos, pTarget->m_Pos, 0, 0) :
|
||||
!Collision()->IntersectNoLaser(m_Pos, pTarget->m_Pos, 0, 0);
|
||||
if(!IsReachable || distance(pTarget->m_Pos, m_Pos) >= g_Config.m_SvDraggerRange)
|
||||
{
|
||||
DraggerBeamReset();
|
||||
return;
|
||||
}
|
||||
// In the center of the dragger a tee does not experience speed-up
|
||||
else if(distance(pTarget->m_Pos, m_Pos) > 28)
|
||||
{
|
||||
vec2 Temp = pTarget->Core()->m_Vel + (normalize(m_Pos - pTarget->m_Pos) * m_Strength);
|
||||
pTarget->Core()->m_Vel = ClampVel(pTarget->m_MoveRestrictions, Temp);
|
||||
}
|
||||
}
|
||||
|
||||
CDragger::CDragger(CGameWorld *pGameWorld, int ID, const CLaserData *pData) :
|
||||
CEntity(pGameWorld, CGameWorld::ENTTYPE_DRAGGER)
|
||||
{
|
||||
m_Core = vec2(0.f, 0.f);
|
||||
m_ID = ID;
|
||||
m_TargetId = -1;
|
||||
|
||||
m_Strength = 0;
|
||||
m_IgnoreWalls = false;
|
||||
if(0 <= pData->m_Subtype && pData->m_Subtype < NUM_LASERDRAGGERTYPES)
|
||||
{
|
||||
m_IgnoreWalls = (pData->m_Subtype & 1);
|
||||
m_Strength = (pData->m_Subtype >> 1) + 1;
|
||||
}
|
||||
m_Number = pData->m_SwitchNumber;
|
||||
m_Layer = m_Number > 0 ? LAYER_SWITCH : LAYER_GAME;
|
||||
|
||||
Read(pData);
|
||||
}
|
||||
|
||||
void CDragger::Read(const CLaserData *pData)
|
||||
{
|
||||
m_Pos = pData->m_From;
|
||||
m_TargetId = pData->m_Owner;
|
||||
}
|
||||
|
||||
bool CDragger::Match(CDragger *pDragger)
|
||||
{
|
||||
return pDragger->m_Strength == m_Strength && pDragger->m_Number == m_Number && pDragger->m_IgnoreWalls == m_IgnoreWalls;
|
||||
}
|
29
src/game/client/prediction/entities/dragger.h
Normal file
29
src/game/client/prediction/entities/dragger.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* (c) Shereef Marzouk. See "licence DDRace.txt" and the readme.txt in the root of the distribution for more information. */
|
||||
#ifndef GAME_CLIENT_PREDICTION_ENTITIES_DRAGGER_H
|
||||
#define GAME_CLIENT_PREDICTION_ENTITIES_DRAGGER_H
|
||||
|
||||
#include <game/client/prediction/entity.h>
|
||||
|
||||
class CLaserData;
|
||||
|
||||
class CDragger : public CEntity
|
||||
{
|
||||
vec2 m_Core;
|
||||
float m_Strength;
|
||||
bool m_IgnoreWalls;
|
||||
int m_TargetId;
|
||||
|
||||
void LookForPlayersToDrag();
|
||||
void DraggerBeamTick();
|
||||
void DraggerBeamReset();
|
||||
|
||||
public:
|
||||
CDragger(CGameWorld *pGameWorld, int ID, const CLaserData *pData);
|
||||
bool Match(CDragger *pDragger);
|
||||
void Read(const CLaserData *pData);
|
||||
float GetStrength() { return m_Strength; }
|
||||
|
||||
void Tick() override;
|
||||
};
|
||||
|
||||
#endif // GAME_CLIENT_PREDICTION_ENTITIES_DRAGGER_H
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "gameworld.h"
|
||||
#include "entities/character.h"
|
||||
#include "entities/dragger.h"
|
||||
#include "entities/laser.h"
|
||||
#include "entities/pickup.h"
|
||||
#include "entities/projectile.h"
|
||||
|
@ -497,37 +498,54 @@ void CGameWorld::NetObjAdd(int ObjID, int ObjType, const void *pObjData, const C
|
|||
else if((ObjType == NETOBJTYPE_LASER || ObjType == NETOBJTYPE_DDNETLASER) && m_WorldConfig.m_PredictWeapons)
|
||||
{
|
||||
CLaserData Data = ExtractLaserInfo(ObjType, pObjData, this, pDataEx);
|
||||
if((Data.m_Type >= 0 && Data.m_Type != LASERTYPE_RIFLE && Data.m_Type != LASERTYPE_SHOTGUN) || !IsLocalTeam(Data.m_Owner))
|
||||
{
|
||||
if(!IsLocalTeam(Data.m_Owner))
|
||||
return;
|
||||
}
|
||||
|
||||
CLaser NetLaser = CLaser(this, ObjID, &Data);
|
||||
CLaser *pMatching = 0;
|
||||
if(CLaser *pLaser = dynamic_cast<CLaser *>(GetEntity(ObjID, ENTTYPE_LASER)))
|
||||
if(NetLaser.Match(pLaser))
|
||||
pMatching = pLaser;
|
||||
if(!pMatching)
|
||||
if(Data.m_Type == LASERTYPE_RIFLE || Data.m_Type == LASERTYPE_SHOTGUN || Data.m_Type < 0)
|
||||
{
|
||||
for(CEntity *pEnt = FindFirst(CGameWorld::ENTTYPE_LASER); pEnt; pEnt = pEnt->TypeNext())
|
||||
{
|
||||
auto *const pLaser = dynamic_cast<CLaser *>(pEnt);
|
||||
if(pLaser && pLaser->m_ID == -1 && NetLaser.Match(pLaser))
|
||||
{
|
||||
CLaser NetLaser = CLaser(this, ObjID, &Data);
|
||||
CLaser *pMatching = 0;
|
||||
if(CLaser *pLaser = dynamic_cast<CLaser *>(GetEntity(ObjID, ENTTYPE_LASER)))
|
||||
if(NetLaser.Match(pLaser))
|
||||
pMatching = pLaser;
|
||||
pMatching->m_ID = ObjID;
|
||||
break;
|
||||
if(!pMatching)
|
||||
{
|
||||
for(CEntity *pEnt = FindFirst(CGameWorld::ENTTYPE_LASER); pEnt; pEnt = pEnt->TypeNext())
|
||||
{
|
||||
auto *const pLaser = dynamic_cast<CLaser *>(pEnt);
|
||||
if(pLaser && pLaser->m_ID == -1 && NetLaser.Match(pLaser))
|
||||
{
|
||||
pMatching = pLaser;
|
||||
pMatching->m_ID = ObjID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pMatching)
|
||||
{
|
||||
pMatching->Keep();
|
||||
if(distance(NetLaser.m_From, NetLaser.m_Pos) < distance(pMatching->m_From, pMatching->m_Pos) - 2.f)
|
||||
{
|
||||
// if the laser stopped earlier than predicted, set the energy to 0
|
||||
pMatching->m_Energy = 0.f;
|
||||
pMatching->m_Pos = NetLaser.m_Pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pMatching)
|
||||
else if(Data.m_Type == LASERTYPE_DRAGGER)
|
||||
{
|
||||
pMatching->Keep();
|
||||
if(distance(NetLaser.m_From, NetLaser.m_Pos) < distance(pMatching->m_From, pMatching->m_Pos) - 2.f)
|
||||
CDragger NetDragger = CDragger(this, ObjID, &Data);
|
||||
if(NetDragger.GetStrength() > 0)
|
||||
{
|
||||
// if the laser stopped earlier than predicted, set the energy to 0
|
||||
pMatching->m_Energy = 0.f;
|
||||
pMatching->m_Pos = NetLaser.m_Pos;
|
||||
auto *pDragger = dynamic_cast<CDragger *>(GetEntity(ObjID, ENTTYPE_DRAGGER));
|
||||
if(pDragger && NetDragger.Match(pDragger))
|
||||
{
|
||||
pDragger->Keep();
|
||||
pDragger->Read(&Data);
|
||||
return;
|
||||
}
|
||||
CEntity *pEnt = new CDragger(NetDragger);
|
||||
InsertEntity(pEnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -606,6 +624,8 @@ void CGameWorld::CopyWorld(CGameWorld *pFrom)
|
|||
pCopy = new CProjectile(*((CProjectile *)pEnt));
|
||||
else if(Type == ENTTYPE_LASER)
|
||||
pCopy = new CLaser(*((CLaser *)pEnt));
|
||||
else if(Type == ENTTYPE_DRAGGER)
|
||||
pCopy = new CDragger(*((CDragger *)pEnt));
|
||||
else if(Type == ENTTYPE_CHARACTER)
|
||||
pCopy = new CCharacter(*((CCharacter *)pEnt));
|
||||
else if(Type == ENTTYPE_PICKUP)
|
||||
|
@ -650,10 +670,21 @@ CEntity *CGameWorld::FindMatch(int ObjID, int ObjType, const void *pObjData)
|
|||
case NETOBJTYPE_DDNETLASER:
|
||||
{
|
||||
CLaserData Data = ExtractLaserInfo(ObjType, pObjData, this, nullptr);
|
||||
CLaser *pEnt = (CLaser *)GetEntity(ObjID, ENTTYPE_LASER);
|
||||
if(pEnt && CLaser(this, ObjID, &Data).Match(pEnt))
|
||||
if(Data.m_Type == LASERTYPE_RIFLE || Data.m_Type == LASERTYPE_SHOTGUN)
|
||||
{
|
||||
return pEnt;
|
||||
CLaser *pEnt = (CLaser *)GetEntity(ObjID, ENTTYPE_LASER);
|
||||
if(pEnt && CLaser(this, ObjID, &Data).Match(pEnt))
|
||||
{
|
||||
return pEnt;
|
||||
}
|
||||
}
|
||||
else if(Data.m_Type == LASERTYPE_DRAGGER)
|
||||
{
|
||||
CDragger *pEnt = (CDragger *)GetEntity(ObjID, ENTTYPE_DRAGGER);
|
||||
if(pEnt && CDragger(this, ObjID, &Data).Match(pEnt))
|
||||
{
|
||||
return pEnt;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,11 @@ public:
|
|||
{
|
||||
ENTTYPE_PROJECTILE = 0,
|
||||
ENTTYPE_LASER,
|
||||
ENTTYPE_DOOR,
|
||||
ENTTYPE_DRAGGER,
|
||||
ENTTYPE_LIGHT,
|
||||
ENTTYPE_GUN,
|
||||
ENTTYPE_PLASMA,
|
||||
ENTTYPE_PICKUP,
|
||||
ENTTYPE_FLAG,
|
||||
ENTTYPE_CHARACTER,
|
||||
|
|
|
@ -5226,6 +5226,8 @@ void CEditor::RemoveUnusedEnvelopes()
|
|||
|
||||
void CEditor::RenderEnvelopeEditor(CUIRect View)
|
||||
{
|
||||
RenderExtraEditorDragBar(View, &m_EnvelopeEditorSplit);
|
||||
|
||||
if(m_SelectedEnvelope < 0)
|
||||
m_SelectedEnvelope = 0;
|
||||
if(m_SelectedEnvelope >= (int)m_Map.m_vpEnvelopes.size())
|
||||
|
@ -5235,12 +5237,6 @@ void CEditor::RenderEnvelopeEditor(CUIRect View)
|
|||
if(m_SelectedEnvelope >= 0 && m_SelectedEnvelope < (int)m_Map.m_vpEnvelopes.size())
|
||||
pEnvelope = m_Map.m_vpEnvelopes[m_SelectedEnvelope];
|
||||
|
||||
CUIRect DragBar = {
|
||||
View.x,
|
||||
View.y - 2.0f, // use margin
|
||||
View.w,
|
||||
22.0f,
|
||||
};
|
||||
CUIRect ToolBar, CurveBar, ColorBar;
|
||||
View.HSplitTop(15.0f, &ToolBar, &View);
|
||||
View.HSplitTop(15.0f, &CurveBar, &View);
|
||||
|
@ -5249,47 +5245,6 @@ void CEditor::RenderEnvelopeEditor(CUIRect View)
|
|||
|
||||
bool CurrentEnvelopeSwitched = false;
|
||||
|
||||
// do the dragbar
|
||||
{
|
||||
enum
|
||||
{
|
||||
OP_NONE,
|
||||
OP_DRAG_HEADER,
|
||||
OP_CLICK_HEADER
|
||||
};
|
||||
static int s_Operation = 0;
|
||||
static float s_InitialMouseY = 0.0f;
|
||||
static float s_InitialMouseOffsetY = 0.0f;
|
||||
|
||||
static int s_DragBar = 0;
|
||||
bool Clicked;
|
||||
bool Abrupted;
|
||||
if(int Result = DoButton_DraggableEx(&s_DragBar, "", 8, &DragBar, &Clicked, &Abrupted, 0, "Change the size of the editor by dragging."))
|
||||
{
|
||||
if(s_Operation == OP_NONE && Result == 1)
|
||||
{
|
||||
s_InitialMouseY = UI()->MouseY();
|
||||
s_InitialMouseOffsetY = UI()->MouseY() - DragBar.y;
|
||||
s_Operation = OP_CLICK_HEADER;
|
||||
}
|
||||
|
||||
if(Abrupted)
|
||||
s_Operation = OP_NONE;
|
||||
|
||||
if(s_Operation == OP_CLICK_HEADER && absolute(UI()->MouseY() - s_InitialMouseY) > 5)
|
||||
s_Operation = OP_DRAG_HEADER;
|
||||
|
||||
if(s_Operation == OP_DRAG_HEADER)
|
||||
{
|
||||
if(Clicked)
|
||||
s_Operation = OP_NONE;
|
||||
|
||||
m_EnvelopeEditorSplit = s_InitialMouseOffsetY + View.y + View.h - UI()->MouseY();
|
||||
m_EnvelopeEditorSplit = clamp(m_EnvelopeEditorSplit, 100.0f, 400.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do the toolbar
|
||||
{
|
||||
CUIRect Button;
|
||||
|
@ -5818,6 +5773,8 @@ void CEditor::RenderEnvelopeEditor(CUIRect View)
|
|||
|
||||
void CEditor::RenderServerSettingsEditor(CUIRect View, bool ShowServerSettingsEditorLast)
|
||||
{
|
||||
RenderExtraEditorDragBar(View, &m_ServerSettingsEditorSplit);
|
||||
|
||||
static int s_CommandSelectedIndex = -1;
|
||||
|
||||
CUIRect ToolBar;
|
||||
|
@ -5963,6 +5920,47 @@ void CEditor::RenderServerSettingsEditor(CUIRect View, bool ShowServerSettingsEd
|
|||
s_ScrollRegion.End();
|
||||
}
|
||||
|
||||
void CEditor::RenderExtraEditorDragBar(CUIRect View, float *pSplit)
|
||||
{
|
||||
const CUIRect DragBar = {
|
||||
View.x,
|
||||
View.y - 2.0f, // use margin
|
||||
View.w,
|
||||
22.0f,
|
||||
};
|
||||
|
||||
enum EDragOperation
|
||||
{
|
||||
OP_NONE,
|
||||
OP_DRAGGING,
|
||||
OP_CLICKED
|
||||
};
|
||||
static EDragOperation s_Operation = OP_NONE;
|
||||
static float s_InitialMouseY = 0.0f;
|
||||
static float s_InitialMouseOffsetY = 0.0f;
|
||||
|
||||
bool Clicked;
|
||||
bool Abrupted;
|
||||
if(int Result = DoButton_DraggableEx(&s_Operation, "", 8, &DragBar, &Clicked, &Abrupted, 0, "Change the size of the editor by dragging."))
|
||||
{
|
||||
if(s_Operation == OP_NONE && Result == 1)
|
||||
{
|
||||
s_InitialMouseY = UI()->MouseY();
|
||||
s_InitialMouseOffsetY = UI()->MouseY() - DragBar.y;
|
||||
s_Operation = OP_CLICKED;
|
||||
}
|
||||
|
||||
if(Clicked || Abrupted)
|
||||
s_Operation = OP_NONE;
|
||||
|
||||
if(s_Operation == OP_CLICKED && absolute(UI()->MouseY() - s_InitialMouseY) > 5.0f)
|
||||
s_Operation = OP_DRAGGING;
|
||||
|
||||
if(s_Operation == OP_DRAGGING)
|
||||
*pSplit = clamp(s_InitialMouseOffsetY + View.y + View.h - UI()->MouseY(), 100.0f, 400.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void CEditor::RenderMenubar(CUIRect MenuBar)
|
||||
{
|
||||
CUIRect FileButton;
|
||||
|
@ -6049,7 +6047,7 @@ void CEditor::Render()
|
|||
View.HSplitBottom(m_EnvelopeEditorSplit, &View, &ExtraEditor);
|
||||
|
||||
if(m_ShowServerSettingsEditor && !m_ShowPicker)
|
||||
View.HSplitBottom(250.0f, &View, &ExtraEditor);
|
||||
View.HSplitBottom(m_ServerSettingsEditorSplit, &View, &ExtraEditor);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -810,6 +810,7 @@ public:
|
|||
m_ShowEnvelopeEditor = false;
|
||||
m_EnvelopeEditorSplit = 250.0f;
|
||||
m_ShowServerSettingsEditor = false;
|
||||
m_ServerSettingsEditorSplit = 250.0f;
|
||||
|
||||
m_ShowEnvelopePreview = SHOWENV_NONE;
|
||||
m_SelectedQuadEnvelope = -1;
|
||||
|
@ -1073,6 +1074,8 @@ public:
|
|||
|
||||
bool m_ShowEnvelopeEditor;
|
||||
float m_EnvelopeEditorSplit;
|
||||
bool m_ShowServerSettingsEditor;
|
||||
float m_ServerSettingsEditorSplit;
|
||||
|
||||
enum EShowEnvelope
|
||||
{
|
||||
|
@ -1081,7 +1084,6 @@ public:
|
|||
SHOWENV_ALL
|
||||
};
|
||||
EShowEnvelope m_ShowEnvelopePreview;
|
||||
bool m_ShowServerSettingsEditor;
|
||||
bool m_ShowPicker;
|
||||
|
||||
std::vector<int> m_vSelectedLayers;
|
||||
|
@ -1234,8 +1236,10 @@ public:
|
|||
void RenderSounds(CUIRect Toolbox);
|
||||
void RenderModebar(CUIRect View);
|
||||
void RenderStatusbar(CUIRect View);
|
||||
|
||||
void RenderEnvelopeEditor(CUIRect View);
|
||||
void RenderServerSettingsEditor(CUIRect View, bool ShowServerSettingsEditorLast);
|
||||
void RenderExtraEditorDragBar(CUIRect View, float *pSplit);
|
||||
|
||||
void RenderMenubar(CUIRect Menubar);
|
||||
void RenderFileDialog();
|
||||
|
|
|
@ -168,17 +168,17 @@ bool CDragger::WillDraggerBeamUseDraggerID(int TargetClientID, int SnappingClien
|
|||
CCharacter *pSnapChar = GameServer()->GetPlayerChar(SnappingClientID);
|
||||
if(pTargetChar && pSnapChar && m_apDraggerBeam[TargetClientID] != nullptr)
|
||||
{
|
||||
if(pSnapChar->Teams()->m_Core.GetSolo(SnappingClientID))
|
||||
const int SnapTeam = pSnapChar->Team();
|
||||
const int TargetTeam = pTargetChar->Team();
|
||||
if(SnapTeam == TargetTeam && SnapTeam < MAX_CLIENTS)
|
||||
{
|
||||
return TargetClientID == SnappingClientID;
|
||||
}
|
||||
else if(!pTargetChar->Teams()->m_Core.GetSolo(TargetClientID))
|
||||
{
|
||||
const int SnapTeam = pSnapChar->Team();
|
||||
const int TargetTeam = pTargetChar->Team();
|
||||
if(SnapTeam == TargetTeam && SnapTeam < MAX_CLIENTS && m_aTargetIdInTeam[SnapTeam] == TargetClientID)
|
||||
if(pSnapChar->Teams()->m_Core.GetSolo(SnappingClientID) || m_aTargetIdInTeam[SnapTeam] < 0)
|
||||
{
|
||||
return true;
|
||||
return SnappingClientID == TargetClientID;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_aTargetIdInTeam[SnapTeam] == TargetClientID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue