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:
bors[bot] 2020-10-20 16:19:55 +00:00 committed by GitHub
commit 3bdded3c4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 328 additions and 169 deletions

View file

@ -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;
}
// ------------------------------------

View file

@ -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);

View file

@ -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")

View file

@ -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
{

View file

@ -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);

View file

@ -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

View file

@ -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);
}
}
}
}

View file

@ -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

View file

@ -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; }

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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());

View file

@ -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;