mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
3122: Fix arithmentic problems r=def- a=Jupeyy The first three commits are safe The ones i'll add later will be inside the gamecore, so might alter behaviour. I'll see which ones are critical, but takes me some time i fixed most in #3081 3137: Add gfx debug r=def- a=Jupeyy If someone wants to try, you have to execute the client with a config that contains dbg_gfx 1 If opengl debug is supported it will show "Enabled OpenGL debug mode" in the console Co-authored-by: Jupeyy <jupjopjap@gmail.com>
This commit is contained in:
commit
3bdded3c4f
|
@ -107,23 +107,31 @@ inline vector2_base<T> normalize(const vector2_base<T> &v)
|
|||
return vector2_base<T>(v.x * l, v.y * l);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline vector2_base<T> normalize_pre_length(const vector2_base<T> &v, T len)
|
||||
{
|
||||
return vector2_base<T>(v.x / len, v.y / len);
|
||||
}
|
||||
|
||||
typedef vector2_base<float> vec2;
|
||||
typedef vector2_base<bool> bvec2;
|
||||
typedef vector2_base<int> ivec2;
|
||||
|
||||
template<typename T>
|
||||
inline vector2_base<T> closest_point_on_line(vector2_base<T> line_point0, vector2_base<T> line_point1, vector2_base<T> target_point)
|
||||
inline bool closest_point_on_line(vector2_base<T> line_point0, vector2_base<T> line_point1, vector2_base<T> target_point, vector2_base<T> &out_pos)
|
||||
{
|
||||
vector2_base<T> c = target_point - line_point0;
|
||||
vector2_base<T> v = (line_point1 - line_point0);
|
||||
v = normalize(v);
|
||||
T d = length(line_point0 - line_point1);
|
||||
T t = dot(v, c) / d;
|
||||
return mix(line_point0, line_point1, clamp(t, (T)0, (T)1));
|
||||
/*
|
||||
if (t < 0) t = 0;
|
||||
if (t > 1.0f) return 1.0f;
|
||||
return t;*/
|
||||
if(d > 0)
|
||||
{
|
||||
v = normalize_pre_length<T>(v, d);
|
||||
T t = dot(v, c) / d;
|
||||
out_pos = mix(line_point0, line_point1, clamp(t, (T)0, (T)1));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
|
|
|
@ -371,11 +371,14 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St
|
|||
}
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
if(m_Has3DTextures)
|
||||
glDisable(GL_TEXTURE_3D);
|
||||
if(m_Has2DArrayTextures)
|
||||
if(!m_HasShaders)
|
||||
{
|
||||
glDisable(m_2DArrayTarget);
|
||||
if(m_Has3DTextures)
|
||||
glDisable(GL_TEXTURE_3D);
|
||||
if(m_Has2DArrayTextures)
|
||||
{
|
||||
glDisable(m_2DArrayTarget);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_HasShaders && IsNewApi())
|
||||
|
@ -413,12 +416,14 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St
|
|||
{
|
||||
if(m_Has2DArrayTextures)
|
||||
{
|
||||
glEnable(m_2DArrayTarget);
|
||||
if(!m_HasShaders)
|
||||
glEnable(m_2DArrayTarget);
|
||||
glBindTexture(m_2DArrayTarget, m_aTextures[State.m_Texture].m_Tex2DArray);
|
||||
}
|
||||
else if(m_Has3DTextures)
|
||||
{
|
||||
glEnable(GL_TEXTURE_3D);
|
||||
if(!m_HasShaders)
|
||||
glEnable(GL_TEXTURE_3D);
|
||||
glBindTexture(GL_TEXTURE_3D, m_aTextures[State.m_Texture].m_Tex2DArray);
|
||||
}
|
||||
else
|
||||
|
@ -992,11 +997,14 @@ void CCommandProcessorFragment_OpenGL2::SetState(const CCommandBuffer::SState &S
|
|||
if(!IsNewApi())
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
if(m_Has3DTextures)
|
||||
glDisable(GL_TEXTURE_3D);
|
||||
if(m_Has2DArrayTextures)
|
||||
if(!m_HasShaders)
|
||||
{
|
||||
glDisable(m_2DArrayTarget);
|
||||
if(m_Has3DTextures)
|
||||
glDisable(GL_TEXTURE_3D);
|
||||
if(m_Has2DArrayTextures)
|
||||
{
|
||||
glDisable(m_2DArrayTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1029,7 +1037,7 @@ void CCommandProcessorFragment_OpenGL2::SetState(const CCommandBuffer::SState &S
|
|||
Slot = 0;
|
||||
if(!Use2DArrayTextures)
|
||||
{
|
||||
if(!IsNewApi())
|
||||
if(!IsNewApi() && !m_HasShaders)
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, m_aTextures[State.m_Texture].m_Tex);
|
||||
if(IsNewApi())
|
||||
|
@ -1039,7 +1047,7 @@ void CCommandProcessorFragment_OpenGL2::SetState(const CCommandBuffer::SState &S
|
|||
{
|
||||
if(!m_Has2DArrayTextures)
|
||||
{
|
||||
if(!IsNewApi())
|
||||
if(!IsNewApi() && !m_HasShaders)
|
||||
glEnable(GL_TEXTURE_3D);
|
||||
glBindTexture(GL_TEXTURE_3D, m_aTextures[State.m_Texture].m_Tex2DArray);
|
||||
if(IsNewApi())
|
||||
|
@ -1047,7 +1055,7 @@ void CCommandProcessorFragment_OpenGL2::SetState(const CCommandBuffer::SState &S
|
|||
}
|
||||
else
|
||||
{
|
||||
if(!IsNewApi())
|
||||
if(!IsNewApi() && !m_HasShaders)
|
||||
glEnable(m_2DArrayTarget);
|
||||
glBindTexture(m_2DArrayTarget, m_aTextures[State.m_Texture].m_Tex2DArray);
|
||||
if(IsNewApi())
|
||||
|
@ -1340,23 +1348,26 @@ bool CCommandProcessorFragment_OpenGL2::IsTileMapAnalysisSucceeded()
|
|||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
if(m_Has3DTextures)
|
||||
glDisable(GL_TEXTURE_3D);
|
||||
if(m_Has2DArrayTextures)
|
||||
if(!m_HasShaders)
|
||||
{
|
||||
glDisable(m_2DArrayTarget);
|
||||
}
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
if(m_Has3DTextures)
|
||||
glDisable(GL_TEXTURE_3D);
|
||||
if(m_Has2DArrayTextures)
|
||||
{
|
||||
glDisable(m_2DArrayTarget);
|
||||
}
|
||||
|
||||
if(!m_Has2DArrayTextures)
|
||||
{
|
||||
glEnable(GL_TEXTURE_3D);
|
||||
glBindTexture(GL_TEXTURE_3D, FakeTexture);
|
||||
}
|
||||
else
|
||||
{
|
||||
glEnable(m_2DArrayTarget);
|
||||
glBindTexture(m_2DArrayTarget, FakeTexture);
|
||||
if(!m_Has2DArrayTextures)
|
||||
{
|
||||
glEnable(GL_TEXTURE_3D);
|
||||
glBindTexture(GL_TEXTURE_3D, FakeTexture);
|
||||
}
|
||||
else
|
||||
{
|
||||
glEnable(m_2DArrayTarget);
|
||||
glBindTexture(m_2DArrayTarget, FakeTexture);
|
||||
}
|
||||
}
|
||||
|
||||
static_assert(sizeof(m_aStreamVertices) / sizeof(m_aStreamVertices[0]) >= 256 * 4, "Keep the number of stream vertices >= 256 * 4.");
|
||||
|
@ -2488,7 +2499,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
|
|||
m_pSpriteProgram->m_LocCenter = m_pSpriteProgram->GetUniformLoc("Center");
|
||||
m_pSpriteProgram->m_LocVertciesColor = m_pSpriteProgram->GetUniformLoc("VerticesColor");
|
||||
|
||||
m_pSpriteProgram->SetUniform(m_pSpriteProgram->m_LocRotation, 0);
|
||||
m_pSpriteProgram->SetUniform(m_pSpriteProgram->m_LocRotation, 0.0f);
|
||||
float Center[2] = {0.f, 0.f};
|
||||
m_pSpriteProgram->SetUniformVec2(m_pSpriteProgram->m_LocCenter, 1, Center);
|
||||
}
|
||||
|
@ -3760,6 +3771,55 @@ static void ParseVersionString(const GLubyte *pStr, int &VersionMajor, int &Vers
|
|||
}
|
||||
}
|
||||
|
||||
static const char *GetGLErrorName(GLenum Type)
|
||||
{
|
||||
if(Type == GL_DEBUG_TYPE_ERROR)
|
||||
return "ERROR";
|
||||
else if(Type == GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR)
|
||||
return "DEPRECATED BEHAVIOR";
|
||||
else if(Type == GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR)
|
||||
return "UNDEFINED BEHAVIOR";
|
||||
else if(Type == GL_DEBUG_TYPE_PORTABILITY)
|
||||
return "PORTABILITY";
|
||||
else if(Type == GL_DEBUG_TYPE_PERFORMANCE)
|
||||
return "PERFORMANCE";
|
||||
else if(Type == GL_DEBUG_TYPE_OTHER)
|
||||
return "OTHER";
|
||||
else if(Type == GL_DEBUG_TYPE_MARKER)
|
||||
return "MARKER";
|
||||
else if(Type == GL_DEBUG_TYPE_PUSH_GROUP)
|
||||
return "PUSH_GROUP";
|
||||
else if(Type == GL_DEBUG_TYPE_POP_GROUP)
|
||||
return "POP_GROUP";
|
||||
return "UNKNOWN";
|
||||
};
|
||||
|
||||
static const char *GetGLSeverity(GLenum Type)
|
||||
{
|
||||
if(Type == GL_DEBUG_SEVERITY_HIGH)
|
||||
return "high"; // All OpenGL Errors, shader compilation/linking errors, or highly-dangerous undefined behavior
|
||||
else if(Type == GL_DEBUG_SEVERITY_MEDIUM)
|
||||
return "medium"; // Major performance warnings, shader compilation/linking warnings, or the use of deprecated functionality
|
||||
else if(Type == GL_DEBUG_SEVERITY_LOW)
|
||||
return "low"; // Redundant state change performance warning, or unimportant undefined behavior
|
||||
else if(Type == GL_DEBUG_SEVERITY_NOTIFICATION)
|
||||
return "notification"; // Anything that isn't an error or performance issue.
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static void GLAPIENTRY
|
||||
GfxOpenGLMessageCallback(GLenum source,
|
||||
GLenum type,
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar *message,
|
||||
const void *userParam)
|
||||
{
|
||||
dbg_msg("gfx", "[%s] (importance: %s) %s", GetGLErrorName(type), GetGLSeverity(severity), message);
|
||||
}
|
||||
|
||||
void CCommandProcessorFragment_SDL::Cmd_Init(const SCommand_Init *pCommand)
|
||||
{
|
||||
m_GLContext = pCommand->m_GLContext;
|
||||
|
@ -3776,6 +3836,27 @@ void CCommandProcessorFragment_SDL::Cmd_Init(const SCommand_Init *pCommand)
|
|||
glEnable(GL_ALPHA_TEST);
|
||||
glDepthMask(0);
|
||||
|
||||
if(g_Config.m_DbgGfx)
|
||||
{
|
||||
if(GLEW_KHR_debug || GLEW_ARB_debug_output)
|
||||
{
|
||||
// During init, enable debug output
|
||||
if(GLEW_KHR_debug)
|
||||
{
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glDebugMessageCallback(GfxOpenGLMessageCallback, 0);
|
||||
}
|
||||
else if(GLEW_ARB_debug_output)
|
||||
{
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
|
||||
glDebugMessageCallbackARB(GfxOpenGLMessageCallback, 0);
|
||||
}
|
||||
dbg_msg("gfx", "Enabled OpenGL debug mode");
|
||||
}
|
||||
else
|
||||
dbg_msg("gfx", "Requested OpenGL debug mode, but the driver does not support the required extension");
|
||||
}
|
||||
|
||||
// check what this context can do
|
||||
const GLubyte *pVersionString = glGetString(GL_VERSION);
|
||||
dbg_msg("OpenGL", "Version string: %s", (const char *)pVersionString);
|
||||
|
|
|
@ -175,6 +175,7 @@ MACRO_CONFIG_INT(DbgCurl, dbg_curl, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SERVER, "D
|
|||
MACRO_CONFIG_INT(DbgPref, dbg_pref, 0, 0, 1, CFGFLAG_SERVER, "Performance outputs")
|
||||
MACRO_CONFIG_INT(DbgGraphs, dbg_graphs, 0, 0, 1, CFGFLAG_CLIENT, "Performance graphs")
|
||||
MACRO_CONFIG_INT(DbgHitch, dbg_hitch, 0, 0, 0, CFGFLAG_SERVER, "Hitch warnings")
|
||||
MACRO_CONFIG_INT(DbgGfx, dbg_gfx, 0, 0, 1, CFGFLAG_CLIENT, "Show OpenGL warnings and errors, if the GPU supports it")
|
||||
#ifdef CONF_DEBUG
|
||||
MACRO_CONFIG_INT(DbgStress, dbg_stress, 0, 0, 0, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Stress systems")
|
||||
MACRO_CONFIG_INT(DbgStressNetwork, dbg_stress_network, 0, 0, 0, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Stress network")
|
||||
|
|
|
@ -235,50 +235,56 @@ void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent, bool IsPredicted)
|
|||
ColorRGBA RGB;
|
||||
vec2 Pos = vec2(pCurrent->m_X, pCurrent->m_Y);
|
||||
vec2 From = vec2(pCurrent->m_FromX, pCurrent->m_FromY);
|
||||
vec2 Dir = normalize(Pos - From);
|
||||
|
||||
float Ticks;
|
||||
if(IsPredicted)
|
||||
Ticks = (float)(Client()->PredGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy);
|
||||
else
|
||||
Ticks = (float)(Client()->GameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->IntraGameTick(g_Config.m_ClDummy);
|
||||
float Ms = (Ticks / 50.0f) * 1000.0f;
|
||||
float a = Ms / m_pClient->m_Tuning[g_Config.m_ClDummy].m_LaserBounceDelay;
|
||||
a = clamp(a, 0.0f, 1.0f);
|
||||
float Ia = 1 - a;
|
||||
|
||||
vec2 Out, Border;
|
||||
|
||||
Graphics()->TextureClear();
|
||||
Graphics()->QuadsBegin();
|
||||
|
||||
// do outline
|
||||
float Len = distance(Pos, From);
|
||||
RGB = color_cast<ColorRGBA>(ColorHSLA(g_Config.m_ClLaserOutlineColor));
|
||||
ColorRGBA OuterColor(RGB.r, RGB.g, RGB.b, 1.0f);
|
||||
Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f);
|
||||
Out = vec2(Dir.y, -Dir.x) * (7.0f * Ia);
|
||||
|
||||
IGraphics::CFreeformItem Freeform(
|
||||
From.x - Out.x, From.y - Out.y,
|
||||
From.x + Out.x, From.y + Out.y,
|
||||
Pos.x - Out.x, Pos.y - Out.y,
|
||||
Pos.x + Out.x, Pos.y + Out.y);
|
||||
Graphics()->QuadsDrawFreeform(&Freeform, 1);
|
||||
|
||||
// do inner
|
||||
RGB = color_cast<ColorRGBA>(ColorHSLA(g_Config.m_ClLaserInnerColor));
|
||||
ColorRGBA InnerColor(RGB.r, RGB.g, RGB.b, 1.0f);
|
||||
Out = vec2(Dir.y, -Dir.x) * (5.0f * Ia);
|
||||
Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, 1.0f); // center
|
||||
|
||||
Freeform = IGraphics::CFreeformItem(
|
||||
From.x - Out.x, From.y - Out.y,
|
||||
From.x + Out.x, From.y + Out.y,
|
||||
Pos.x - Out.x, Pos.y - Out.y,
|
||||
Pos.x + Out.x, Pos.y + Out.y);
|
||||
Graphics()->QuadsDrawFreeform(&Freeform, 1);
|
||||
vec2 Dir;
|
||||
if(Len > 0)
|
||||
{
|
||||
Dir = normalize_pre_length(Pos - From, Len);
|
||||
|
||||
Graphics()->QuadsEnd();
|
||||
float Ticks;
|
||||
if(IsPredicted)
|
||||
Ticks = (float)(Client()->PredGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy);
|
||||
else
|
||||
Ticks = (float)(Client()->GameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->IntraGameTick(g_Config.m_ClDummy);
|
||||
float Ms = (Ticks / 50.0f) * 1000.0f;
|
||||
float a = Ms / m_pClient->m_Tuning[g_Config.m_ClDummy].m_LaserBounceDelay;
|
||||
a = clamp(a, 0.0f, 1.0f);
|
||||
float Ia = 1 - a;
|
||||
|
||||
vec2 Out, Border;
|
||||
|
||||
Graphics()->TextureClear();
|
||||
Graphics()->QuadsBegin();
|
||||
|
||||
// do outline
|
||||
Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f);
|
||||
Out = vec2(Dir.y, -Dir.x) * (7.0f * Ia);
|
||||
|
||||
IGraphics::CFreeformItem Freeform(
|
||||
From.x - Out.x, From.y - Out.y,
|
||||
From.x + Out.x, From.y + Out.y,
|
||||
Pos.x - Out.x, Pos.y - Out.y,
|
||||
Pos.x + Out.x, Pos.y + Out.y);
|
||||
Graphics()->QuadsDrawFreeform(&Freeform, 1);
|
||||
|
||||
// do inner
|
||||
Out = vec2(Dir.y, -Dir.x) * (5.0f * Ia);
|
||||
Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, 1.0f); // center
|
||||
|
||||
Freeform = IGraphics::CFreeformItem(
|
||||
From.x - Out.x, From.y - Out.y,
|
||||
From.x + Out.x, From.y + Out.y,
|
||||
Pos.x - Out.x, Pos.y - Out.y,
|
||||
Pos.x + Out.x, Pos.y + Out.y);
|
||||
Graphics()->QuadsDrawFreeform(&Freeform, 1);
|
||||
|
||||
Graphics()->QuadsEnd();
|
||||
}
|
||||
|
||||
// render head
|
||||
{
|
||||
|
|
|
@ -429,13 +429,22 @@ void CPlayers::RenderPlayer(
|
|||
}
|
||||
if(g_pData->m_Weapons.m_aId[iw].m_aSpriteMuzzles[IteX])
|
||||
{
|
||||
vec2 Pos1, Pos0;
|
||||
vec2 Dir;
|
||||
if(PredictLocalWeapons)
|
||||
Dir = vec2(pPlayerChar->m_X, pPlayerChar->m_Y) - vec2(pPrevChar->m_X, pPrevChar->m_Y);
|
||||
else
|
||||
Dir = 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_Prev.m_X, m_pClient->m_Snap.m_aCharacters[ClientID].m_Prev.m_Y);
|
||||
Dir = normalize(Dir);
|
||||
float HadOkenAngle = GetAngle(Dir);
|
||||
float HadOkenAngle = 0;
|
||||
if(absolute(Dir.x) > 0.0001f || absolute(Dir.y) > 0.0001f)
|
||||
{
|
||||
Dir = normalize(Dir);
|
||||
HadOkenAngle = GetAngle(Dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
Dir = vec2(1, 0);
|
||||
}
|
||||
Graphics()->QuadsSetRotation(HadOkenAngle);
|
||||
int QuadOffset = IteX * 2;
|
||||
vec2 DirY(-Dir.y, Dir.x);
|
||||
|
|
|
@ -97,8 +97,10 @@ int CSkins::LoadSkin(const char *pName, const char *pPath, int DirType, int *pGe
|
|||
aColors[2] += d[y * Pitch + x * 4 + 2];
|
||||
}
|
||||
}
|
||||
|
||||
Skin.m_BloodColor = ColorRGBA(normalize(vec3(aColors[0], aColors[1], aColors[2])));
|
||||
if(aColors[0] != 0 && aColors[1] != 0 && aColors[2] != 0)
|
||||
Skin.m_BloodColor = ColorRGBA(normalize(vec3(aColors[0], aColors[1], aColors[2])));
|
||||
else
|
||||
Skin.m_BloodColor = ColorRGBA(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
// create colorless version
|
||||
|
|
|
@ -2161,14 +2161,17 @@ int CGameClient::IntersectCharacter(vec2 HookPos, vec2 NewPos, vec2 &NewPos2, in
|
|||
if(!IsOneSuper && (!m_Teams.SameTeam(i, ownID) || IsOneSolo || OwnClientData.m_NoHookHit))
|
||||
continue;
|
||||
|
||||
vec2 ClosestPoint = closest_point_on_line(HookPos, NewPos, Position);
|
||||
if(distance(Position, ClosestPoint) < PhysSize + 2.0f)
|
||||
vec2 ClosestPoint;
|
||||
if(closest_point_on_line(HookPos, NewPos, Position, ClosestPoint))
|
||||
{
|
||||
if(ClosestID == -1 || distance(HookPos, Position) < Distance)
|
||||
if(distance(Position, ClosestPoint) < PhysSize + 2.0f)
|
||||
{
|
||||
NewPos2 = ClosestPoint;
|
||||
ClosestID = i;
|
||||
Distance = distance(HookPos, Position);
|
||||
if(ClosestID == -1 || distance(HookPos, Position) < Distance)
|
||||
{
|
||||
NewPos2 = ClosestPoint;
|
||||
ClosestID = i;
|
||||
Distance = distance(HookPos, Position);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1023,6 +1023,12 @@ CCharacter::CCharacter(CGameWorld *pGameWorld, int ID, CNetObj_Character *pChar,
|
|||
m_TeleCheckpoint = 0;
|
||||
m_StrongWeakID = 0;
|
||||
|
||||
// never intilize both to zero
|
||||
m_Input.m_TargetX = 0;
|
||||
m_Input.m_TargetY = -1;
|
||||
|
||||
m_LatestPrevInput = m_LatestInput = m_PrevInput = m_SavedInput = m_Input;
|
||||
|
||||
ResetPrediction();
|
||||
Read(pChar, pExtended, false);
|
||||
|
||||
|
@ -1221,8 +1227,8 @@ void CCharacter::Read(CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtende
|
|||
mem_zero(&m_SavedInput, sizeof(m_SavedInput));
|
||||
m_Input.m_Direction = m_SavedInput.m_Direction = m_Core.m_Direction;
|
||||
m_Input.m_Hook = m_SavedInput.m_Hook = (m_Core.m_HookState != HOOK_IDLE);
|
||||
m_Input.m_TargetX = cosf(pChar->m_Angle / 256.0f);
|
||||
m_Input.m_TargetY = sinf(pChar->m_Angle / 256.0f);
|
||||
m_Input.m_TargetX = m_SavedInput.m_TargetX = cosf(pChar->m_Angle / 256.0f) * 256.0f;
|
||||
m_Input.m_TargetY = m_SavedInput.m_TargetY = sinf(pChar->m_Angle / 256.0f) * 256.0f;
|
||||
}
|
||||
|
||||
// in most cases the reload timer can be determined from the last attack tick
|
||||
|
|
|
@ -118,7 +118,15 @@ public:
|
|||
void SetNinjaActivationTick(int ActivationTick) { m_Ninja.m_ActivationTick = ActivationTick; };
|
||||
void SetNinjaCurrentMoveTime(int CurrentMoveTime) { m_Ninja.m_CurrentMoveTime = CurrentMoveTime; };
|
||||
int GetCID() { return m_ID; }
|
||||
void SetInput(CNetObj_PlayerInput *pNewInput) { m_LatestInput = m_Input = *pNewInput; };
|
||||
void SetInput(CNetObj_PlayerInput *pNewInput)
|
||||
{
|
||||
m_LatestInput = m_Input = *pNewInput;
|
||||
// it is not allowed to aim in the center
|
||||
if(m_Input.m_TargetX == 0 && m_Input.m_TargetY == 0)
|
||||
{
|
||||
m_Input.m_TargetY = m_LatestInput.m_TargetY = -1;
|
||||
}
|
||||
};
|
||||
int GetJumped() { return m_Core.m_Jumped; }
|
||||
int GetAttackTick() { return m_AttackTick; }
|
||||
int GetStrongWeakID() { return m_StrongWeakID; }
|
||||
|
|
|
@ -227,16 +227,19 @@ CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, v
|
|||
if(CollideWith != -1 && !p->CanCollide(CollideWith))
|
||||
continue;
|
||||
|
||||
vec2 IntersectPos = closest_point_on_line(Pos0, Pos1, p->m_Pos);
|
||||
float Len = distance(p->m_Pos, IntersectPos);
|
||||
if(Len < p->m_ProximityRadius + Radius)
|
||||
vec2 IntersectPos;
|
||||
if(closest_point_on_line(Pos0, Pos1, p->m_Pos, IntersectPos))
|
||||
{
|
||||
Len = distance(Pos0, IntersectPos);
|
||||
if(Len < ClosestLen)
|
||||
float Len = distance(p->m_Pos, IntersectPos);
|
||||
if(Len < p->m_ProximityRadius + Radius)
|
||||
{
|
||||
NewPos = IntersectPos;
|
||||
ClosestLen = Len;
|
||||
pClosest = p;
|
||||
Len = distance(Pos0, IntersectPos);
|
||||
if(Len < ClosestLen)
|
||||
{
|
||||
NewPos = IntersectPos;
|
||||
ClosestLen = Len;
|
||||
pClosest = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,11 +257,14 @@ std::list<class CCharacter *> CGameWorld::IntersectedCharacters(vec2 Pos0, vec2
|
|||
if(pChr == pNotThis)
|
||||
continue;
|
||||
|
||||
vec2 IntersectPos = closest_point_on_line(Pos0, Pos1, pChr->m_Pos);
|
||||
float Len = distance(pChr->m_Pos, IntersectPos);
|
||||
if(Len < pChr->m_ProximityRadius + Radius)
|
||||
vec2 IntersectPos;
|
||||
if(closest_point_on_line(Pos0, Pos1, pChr->m_Pos, IntersectPos))
|
||||
{
|
||||
listOfChars.push_back(pChr);
|
||||
float Len = distance(pChr->m_Pos, IntersectPos);
|
||||
if(Len < pChr->m_ProximityRadius + Radius)
|
||||
{
|
||||
listOfChars.push_back(pChr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return listOfChars;
|
||||
|
@ -475,6 +481,7 @@ void CGameWorld::NetObjEnd(int LocalID)
|
|||
pHookedChar->m_Pos = pHookedChar->m_Core.m_Pos = pChar->m_Core.m_HookPos;
|
||||
pHookedChar->m_Core.m_Vel = vec2(0, 0);
|
||||
mem_zero(&pHookedChar->m_SavedInput, sizeof(pHookedChar->m_SavedInput));
|
||||
pHookedChar->m_SavedInput.m_TargetY = -1;
|
||||
pHookedChar->m_KeepHooked = true;
|
||||
pHookedChar->m_MarkedForDestroy = false;
|
||||
}
|
||||
|
|
|
@ -112,6 +112,10 @@ void CCharacterCore::Reset()
|
|||
m_HasTelegunLaser = false;
|
||||
m_FreezeEnd = 0;
|
||||
m_DeepFrozen = false;
|
||||
|
||||
// never initialize both to 0
|
||||
m_Input.m_TargetX = 0;
|
||||
m_Input.m_TargetY = -1;
|
||||
}
|
||||
|
||||
void CCharacterCore::Tick(bool UseInput)
|
||||
|
@ -271,15 +275,18 @@ void CCharacterCore::Tick(bool UseInput)
|
|||
if(!pCharCore || pCharCore == this || (!(m_Super || pCharCore->m_Super) && ((m_Id != -1 && !m_pTeams->CanCollide(i, m_Id)) || pCharCore->m_Solo || m_Solo)))
|
||||
continue;
|
||||
|
||||
vec2 ClosestPoint = closest_point_on_line(m_HookPos, NewPos, pCharCore->m_Pos);
|
||||
if(distance(pCharCore->m_Pos, ClosestPoint) < PhysSize + 2.0f)
|
||||
vec2 ClosestPoint;
|
||||
if(closest_point_on_line(m_HookPos, NewPos, pCharCore->m_Pos, ClosestPoint))
|
||||
{
|
||||
if(m_HookedPlayer == -1 || distance(m_HookPos, pCharCore->m_Pos) < Distance)
|
||||
if(distance(pCharCore->m_Pos, ClosestPoint) < PhysSize + 2.0f)
|
||||
{
|
||||
m_TriggeredEvents |= COREEVENT_HOOK_ATTACH_PLAYER;
|
||||
m_HookState = HOOK_GRABBED;
|
||||
m_HookedPlayer = i;
|
||||
Distance = distance(m_HookPos, pCharCore->m_Pos);
|
||||
if(m_HookedPlayer == -1 || distance(m_HookPos, pCharCore->m_Pos) < Distance)
|
||||
{
|
||||
m_TriggeredEvents |= COREEVENT_HOOK_ATTACH_PLAYER;
|
||||
m_HookState = HOOK_GRABBED;
|
||||
m_HookedPlayer = i;
|
||||
Distance = distance(m_HookPos, pCharCore->m_Pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -389,41 +396,44 @@ void CCharacterCore::Tick(bool UseInput)
|
|||
|
||||
// handle player <-> player collision
|
||||
float Distance = distance(m_Pos, pCharCore->m_Pos);
|
||||
vec2 Dir = normalize(m_Pos - pCharCore->m_Pos);
|
||||
|
||||
bool CanCollide = (m_Super || pCharCore->m_Super) || (pCharCore->m_Collision && m_Collision && !m_NoCollision && !pCharCore->m_NoCollision && m_pWorld->m_Tuning[g_Config.m_ClDummy].m_PlayerCollision);
|
||||
|
||||
if(CanCollide && Distance < PhysSize * 1.25f && Distance > 0.0f)
|
||||
if(Distance > 0)
|
||||
{
|
||||
float a = (PhysSize * 1.45f - Distance);
|
||||
float Velocity = 0.5f;
|
||||
vec2 Dir = normalize(m_Pos - pCharCore->m_Pos);
|
||||
|
||||
// make sure that we don't add excess force by checking the
|
||||
// direction against the current velocity. if not zero.
|
||||
if(length(m_Vel) > 0.0001)
|
||||
Velocity = 1 - (dot(normalize(m_Vel), Dir) + 1) / 2;
|
||||
bool CanCollide = (m_Super || pCharCore->m_Super) || (pCharCore->m_Collision && m_Collision && !m_NoCollision && !pCharCore->m_NoCollision && m_pWorld->m_Tuning[g_Config.m_ClDummy].m_PlayerCollision);
|
||||
|
||||
m_Vel += Dir * a * (Velocity * 0.75f);
|
||||
m_Vel *= 0.85f;
|
||||
}
|
||||
|
||||
// handle hook influence
|
||||
if(m_Hook && m_HookedPlayer == i && m_pWorld->m_Tuning[g_Config.m_ClDummy].m_PlayerHooking)
|
||||
{
|
||||
if(Distance > PhysSize * 1.50f) // TODO: fix tweakable variable
|
||||
if(CanCollide && Distance < PhysSize * 1.25f && Distance > 0.0f)
|
||||
{
|
||||
float Accel = m_pWorld->m_Tuning[g_Config.m_ClDummy].m_HookDragAccel * (Distance / m_pWorld->m_Tuning[g_Config.m_ClDummy].m_HookLength);
|
||||
float DragSpeed = m_pWorld->m_Tuning[g_Config.m_ClDummy].m_HookDragSpeed;
|
||||
float a = (PhysSize * 1.45f - Distance);
|
||||
float Velocity = 0.5f;
|
||||
|
||||
vec2 Temp;
|
||||
// add force to the hooked player
|
||||
Temp.x = SaturatedAdd(-DragSpeed, DragSpeed, pCharCore->m_Vel.x, Accel * Dir.x * 1.5f);
|
||||
Temp.y = SaturatedAdd(-DragSpeed, DragSpeed, pCharCore->m_Vel.y, Accel * Dir.y * 1.5f);
|
||||
pCharCore->m_Vel = ClampVel(pCharCore->m_MoveRestrictions, Temp);
|
||||
// add a little bit force to the guy who has the grip
|
||||
Temp.x = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.x, -Accel * Dir.x * 0.25f);
|
||||
Temp.y = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.y, -Accel * Dir.y * 0.25f);
|
||||
m_Vel = ClampVel(m_MoveRestrictions, Temp);
|
||||
// make sure that we don't add excess force by checking the
|
||||
// direction against the current velocity. if not zero.
|
||||
if(length(m_Vel) > 0.0001)
|
||||
Velocity = 1 - (dot(normalize(m_Vel), Dir) + 1) / 2;
|
||||
|
||||
m_Vel += Dir * a * (Velocity * 0.75f);
|
||||
m_Vel *= 0.85f;
|
||||
}
|
||||
|
||||
// handle hook influence
|
||||
if(m_Hook && m_HookedPlayer == i && m_pWorld->m_Tuning[g_Config.m_ClDummy].m_PlayerHooking)
|
||||
{
|
||||
if(Distance > PhysSize * 1.50f) // TODO: fix tweakable variable
|
||||
{
|
||||
float Accel = m_pWorld->m_Tuning[g_Config.m_ClDummy].m_HookDragAccel * (Distance / m_pWorld->m_Tuning[g_Config.m_ClDummy].m_HookLength);
|
||||
float DragSpeed = m_pWorld->m_Tuning[g_Config.m_ClDummy].m_HookDragSpeed;
|
||||
|
||||
vec2 Temp;
|
||||
// add force to the hooked player
|
||||
Temp.x = SaturatedAdd(-DragSpeed, DragSpeed, pCharCore->m_Vel.x, Accel * Dir.x * 1.5f);
|
||||
Temp.y = SaturatedAdd(-DragSpeed, DragSpeed, pCharCore->m_Vel.y, Accel * Dir.y * 1.5f);
|
||||
pCharCore->m_Vel = ClampVel(pCharCore->m_MoveRestrictions, Temp);
|
||||
// add a little bit force to the guy who has the grip
|
||||
Temp.x = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.x, -Accel * Dir.x * 0.25f);
|
||||
Temp.y = SaturatedAdd(-DragSpeed, DragSpeed, m_Vel.y, -Accel * Dir.y * 0.25f);
|
||||
m_Vel = ClampVel(m_MoveRestrictions, Temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -467,30 +477,33 @@ void CCharacterCore::Move()
|
|||
{
|
||||
// check player collision
|
||||
float Distance = distance(m_Pos, NewPos);
|
||||
int End = Distance + 1;
|
||||
vec2 LastPos = m_Pos;
|
||||
for(int i = 0; i < End; i++)
|
||||
if(Distance > 0)
|
||||
{
|
||||
float a = i / Distance;
|
||||
vec2 Pos = mix(m_Pos, NewPos, a);
|
||||
for(int p = 0; p < MAX_CLIENTS; p++)
|
||||
int End = Distance + 1;
|
||||
vec2 LastPos = m_Pos;
|
||||
for(int i = 0; i < End; i++)
|
||||
{
|
||||
CCharacterCore *pCharCore = m_pWorld->m_apCharacters[p];
|
||||
if(!pCharCore || pCharCore == this)
|
||||
continue;
|
||||
if((!(pCharCore->m_Super || m_Super) && (m_Solo || pCharCore->m_Solo || !pCharCore->m_Collision || pCharCore->m_NoCollision || (m_Id != -1 && !m_pTeams->CanCollide(m_Id, p)))))
|
||||
continue;
|
||||
float D = distance(Pos, pCharCore->m_Pos);
|
||||
if(D < 28.0f && D >= 0.0f)
|
||||
float a = i / Distance;
|
||||
vec2 Pos = mix(m_Pos, NewPos, a);
|
||||
for(int p = 0; p < MAX_CLIENTS; p++)
|
||||
{
|
||||
if(a > 0.0f)
|
||||
m_Pos = LastPos;
|
||||
else if(distance(NewPos, pCharCore->m_Pos) > D)
|
||||
m_Pos = NewPos;
|
||||
return;
|
||||
CCharacterCore *pCharCore = m_pWorld->m_apCharacters[p];
|
||||
if(!pCharCore || pCharCore == this)
|
||||
continue;
|
||||
if((!(pCharCore->m_Super || m_Super) && (m_Solo || pCharCore->m_Solo || !pCharCore->m_Collision || pCharCore->m_NoCollision || (m_Id != -1 && !m_pTeams->CanCollide(m_Id, p)))))
|
||||
continue;
|
||||
float D = distance(Pos, pCharCore->m_Pos);
|
||||
if(D < 28.0f && D >= 0.0f)
|
||||
{
|
||||
if(a > 0.0f)
|
||||
m_Pos = LastPos;
|
||||
else if(distance(NewPos, pCharCore->m_Pos) > D)
|
||||
m_Pos = NewPos;
|
||||
return;
|
||||
}
|
||||
}
|
||||
LastPos = Pos;
|
||||
}
|
||||
LastPos = Pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,8 @@ inline float GetAngle(vec2 Dir)
|
|||
{
|
||||
if(Dir.x == 0 && Dir.y == 0)
|
||||
return 0.0f;
|
||||
else if(Dir.x == 0)
|
||||
return Dir.y < 0 ? -pi / 2 : pi / 2;
|
||||
float a = atanf(Dir.y / Dir.x);
|
||||
if(Dir.x < 0)
|
||||
a = a + pi;
|
||||
|
|
|
@ -24,6 +24,12 @@ CCharacter::CCharacter(CGameWorld *pWorld) :
|
|||
m_Health = 0;
|
||||
m_Armor = 0;
|
||||
m_StrongWeakID = 0;
|
||||
|
||||
// never intilize both to zero
|
||||
m_Input.m_TargetX = 0;
|
||||
m_Input.m_TargetY = -1;
|
||||
|
||||
m_LatestPrevPrevInput = m_LatestPrevInput = m_LatestInput = m_PrevInput = m_SavedInput = m_Input;
|
||||
}
|
||||
|
||||
void CCharacter::Reset()
|
||||
|
@ -50,6 +56,7 @@ bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos)
|
|||
m_Pos = Pos;
|
||||
|
||||
mem_zero(&m_LatestPrevPrevInput, sizeof(m_LatestPrevPrevInput));
|
||||
m_LatestPrevPrevInput.m_TargetY = -1;
|
||||
m_SpawnTick = Server()->Tick();
|
||||
m_WeaponChangeTick = Server()->Tick();
|
||||
Antibot()->OnSpawn(m_pPlayer->GetCID());
|
||||
|
|
|
@ -315,16 +315,19 @@ CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, v
|
|||
if(CollideWith != -1 && !p->CanCollide(CollideWith))
|
||||
continue;
|
||||
|
||||
vec2 IntersectPos = closest_point_on_line(Pos0, Pos1, p->m_Pos);
|
||||
float Len = distance(p->m_Pos, IntersectPos);
|
||||
if(Len < p->m_ProximityRadius + Radius)
|
||||
vec2 IntersectPos;
|
||||
if(closest_point_on_line(Pos0, Pos1, p->m_Pos, IntersectPos))
|
||||
{
|
||||
Len = distance(Pos0, IntersectPos);
|
||||
if(Len < ClosestLen)
|
||||
float Len = distance(p->m_Pos, IntersectPos);
|
||||
if(Len < p->m_ProximityRadius + Radius)
|
||||
{
|
||||
NewPos = IntersectPos;
|
||||
ClosestLen = Len;
|
||||
pClosest = p;
|
||||
Len = distance(Pos0, IntersectPos);
|
||||
if(Len < ClosestLen)
|
||||
{
|
||||
NewPos = IntersectPos;
|
||||
ClosestLen = Len;
|
||||
pClosest = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -368,12 +371,15 @@ std::list<class CCharacter *> CGameWorld::IntersectedCharacters(vec2 Pos0, vec2
|
|||
if(pChr == pNotThis)
|
||||
continue;
|
||||
|
||||
vec2 IntersectPos = closest_point_on_line(Pos0, Pos1, pChr->m_Pos);
|
||||
float Len = distance(pChr->m_Pos, IntersectPos);
|
||||
if(Len < pChr->m_ProximityRadius + Radius)
|
||||
vec2 IntersectPos;
|
||||
if(closest_point_on_line(Pos0, Pos1, pChr->m_Pos, IntersectPos))
|
||||
{
|
||||
pChr->m_Intersection = IntersectPos;
|
||||
listOfChars.push_back(pChr);
|
||||
float Len = distance(pChr->m_Pos, IntersectPos);
|
||||
if(Len < pChr->m_ProximityRadius + Radius)
|
||||
{
|
||||
pChr->m_Intersection = IntersectPos;
|
||||
listOfChars.push_back(pChr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return listOfChars;
|
||||
|
|
Loading…
Reference in a new issue