mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Add antiping for weapons (by nuborn)
This commit is contained in:
parent
a0bfc5a083
commit
48e66a2ab3
|
@ -104,6 +104,7 @@ enum
|
|||
VERSION_DDNET_GOODHOOK = 221,
|
||||
VERSION_DDNET_EXTRATUNES = 302,
|
||||
VERSION_DDNET_RCONPROTECT = 408,
|
||||
VERSION_DDNET_ANTIPING_PROJECTILE = 600
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -49,8 +49,10 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID)
|
|||
if(Ct < 0)
|
||||
return; // projectile havn't been shot yet
|
||||
|
||||
vec2 StartPos(pCurrent->m_X, pCurrent->m_Y);
|
||||
vec2 StartVel(pCurrent->m_VelX/100.0f, pCurrent->m_VelY/100.0f);
|
||||
vec2 StartPos, StartVel;
|
||||
ExtractInfo(pCurrent, &StartPos, &StartVel);
|
||||
//vec2 StartPos(pCurrent->m_X, pCurrent->m_Y);
|
||||
//vec2 StartVel(pCurrent->m_VelX/100.00000f, pCurrent->m_VelY/100.00000f);
|
||||
vec2 Pos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct);
|
||||
vec2 PrevPos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct-0.001f);
|
||||
|
||||
|
|
|
@ -440,6 +440,9 @@ void CGameClient::OnReset()
|
|||
m_DDRaceMsgSent[1] = false;
|
||||
m_ShowOthers[0] = -1;
|
||||
m_ShowOthers[1] = -1;
|
||||
|
||||
for(int i=0; i<64; i++)
|
||||
m_aLocalProjectiles[i].Deactivate();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1161,6 +1164,9 @@ void CGameClient::OnNewSnapshot()
|
|||
|
||||
void CGameClient::OnPredict()
|
||||
{
|
||||
float PhysSize = 28.0f;
|
||||
float ProximityRadius = PhysSize;
|
||||
|
||||
// store the previous values so we can detect prediction errors
|
||||
CCharacterCore BeforePrevChar = m_PredictedPrevChar;
|
||||
CCharacterCore BeforeChar = m_PredictedChar;
|
||||
|
@ -1202,6 +1208,41 @@ void CGameClient::OnPredict()
|
|||
g_GameClient.m_aClients[i].m_Predicted.m_ActiveWeapon = m_Snap.m_aCharacters[i].m_Cur.m_Weapon;
|
||||
}
|
||||
|
||||
class CLocalProjectile TempProjectiles[64];
|
||||
int NumProjectiles = 0;
|
||||
|
||||
if(g_Config.m_ClAntiPingWeapons)
|
||||
{
|
||||
for(int Index=0; Index<64; Index++)
|
||||
TempProjectiles[Index].Deactivate();
|
||||
int Num = Client()->SnapNumItems(IClient::SNAP_CURRENT);
|
||||
for(int Index = 0; Index < Num && NumProjectiles < 64; Index++)
|
||||
{
|
||||
IClient::CSnapItem Item;
|
||||
const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item);
|
||||
if(Item.m_Type == NETOBJTYPE_PROJECTILE)
|
||||
{
|
||||
const CNetObj_Projectile *pInfo = (const CNetObj_Projectile *)pData;
|
||||
|
||||
TempProjectiles[NumProjectiles].Init(this, &World, Collision(), (const CNetObj_Projectile *)pData);
|
||||
|
||||
int Index = TempProjectiles[NumProjectiles].m_StartTick % 64;
|
||||
if(m_aLocalProjectiles[Index].m_Active)
|
||||
if(m_aLocalProjectiles[Index].m_StartTick == TempProjectiles[NumProjectiles].m_StartTick)
|
||||
if(distance(m_aLocalProjectiles[Index].m_Pos, TempProjectiles[NumProjectiles].m_Pos) < 3)
|
||||
TempProjectiles[NumProjectiles] = m_aLocalProjectiles[Index];
|
||||
NumProjectiles++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ReloadTimer;
|
||||
if(World.m_apCharacters[m_Snap.m_LocalClientID]->m_ActiveWeapon == WEAPON_HAMMER)
|
||||
ReloadTimer = SERVER_TICK_SPEED / 3 - (Client()->GameTick() - m_Snap.m_aCharacters[m_Snap.m_LocalClientID].m_Cur.m_AttackTick);
|
||||
else
|
||||
ReloadTimer = g_pData->m_Weapons.m_aId[World.m_apCharacters[m_Snap.m_LocalClientID]->m_ActiveWeapon].m_Firedelay * SERVER_TICK_SPEED / 1000 - (Client()->GameTick() - m_Snap.m_aCharacters[m_Snap.m_LocalClientID].m_Cur.m_AttackTick);
|
||||
ReloadTimer = max(ReloadTimer, 0);
|
||||
|
||||
// predict
|
||||
for(int Tick = Client()->GameTick()+1; Tick <= Client()->PredGameTick(); Tick++)
|
||||
{
|
||||
|
@ -1209,7 +1250,6 @@ void CGameClient::OnPredict()
|
|||
if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalClientID])
|
||||
m_PredictedPrevChar = *World.m_apCharacters[m_Snap.m_LocalClientID];
|
||||
|
||||
// first calculate where everyone should move
|
||||
for(int c = 0; c < MAX_CLIENTS; c++)
|
||||
{
|
||||
if(!World.m_apCharacters[c])
|
||||
|
@ -1217,19 +1257,150 @@ void CGameClient::OnPredict()
|
|||
|
||||
if(g_Config.m_ClAntiPing && Tick == Client()->PredGameTick())
|
||||
g_GameClient.m_aClients[c].m_PrevPredicted = *World.m_apCharacters[c];
|
||||
}
|
||||
|
||||
// input
|
||||
CNetObj_PlayerInput Input;
|
||||
CNetObj_PlayerInput PrevInput;
|
||||
for(int c = 0; c < MAX_CLIENTS; c++)
|
||||
{
|
||||
if(!World.m_apCharacters[c])
|
||||
continue;
|
||||
|
||||
mem_zero(&World.m_apCharacters[c]->m_Input, sizeof(World.m_apCharacters[c]->m_Input));
|
||||
if(m_Snap.m_LocalClientID == c)
|
||||
{
|
||||
// apply player input
|
||||
mem_zero(&Input, sizeof(Input));
|
||||
mem_zero(&PrevInput, sizeof(PrevInput));
|
||||
int *pInput = Client()->GetInput(Tick);
|
||||
if(pInput)
|
||||
{
|
||||
World.m_apCharacters[c]->m_Input = *((CNetObj_PlayerInput*)pInput);
|
||||
Input = *((CNetObj_PlayerInput*)pInput);
|
||||
}
|
||||
int *pPrevInput = Client()->GetInput(Tick-1);
|
||||
if(pPrevInput)
|
||||
PrevInput = *((CNetObj_PlayerInput*)pPrevInput);
|
||||
}
|
||||
}
|
||||
|
||||
// handle weapons
|
||||
{
|
||||
if(!g_Config.m_ClAntiPingWeapons)
|
||||
break;
|
||||
if(ReloadTimer)
|
||||
break;
|
||||
if(!World.m_apCharacters[m_Snap.m_LocalClientID])
|
||||
break;
|
||||
CCharacterCore *Local = World.m_apCharacters[m_Snap.m_LocalClientID];
|
||||
|
||||
//DoWeaponSwitch();
|
||||
|
||||
bool FullAuto = false;
|
||||
if(Local->m_ActiveWeapon == WEAPON_GRENADE || Local->m_ActiveWeapon == WEAPON_SHOTGUN || Local->m_ActiveWeapon == WEAPON_RIFLE)
|
||||
FullAuto = true;
|
||||
|
||||
bool WillFire = false;
|
||||
|
||||
if(CountInput(PrevInput.m_Fire, Input.m_Fire).m_Presses)
|
||||
WillFire = true;
|
||||
if(FullAuto && (Input.m_Fire&1))
|
||||
WillFire = true;
|
||||
if(!WillFire)
|
||||
break;
|
||||
//if(!m_pControls->m_AmmoCount[Local->m_ActiveWeapon%NUM_WEAPONS]) break;
|
||||
vec2 Direction = normalize(vec2(Input.m_TargetX, Input.m_TargetY));
|
||||
vec2 Pos = Local->m_Pos;
|
||||
vec2 ProjStartPos = Pos + Direction * ProximityRadius * 0.75f;
|
||||
|
||||
ReloadTimer = g_pData->m_Weapons.m_aId[Local->m_ActiveWeapon].m_Firedelay * SERVER_TICK_SPEED / 1000;
|
||||
switch(Local->m_ActiveWeapon)
|
||||
{
|
||||
case WEAPON_GRENADE:
|
||||
{
|
||||
TempProjectiles[NumProjectiles].Init(
|
||||
this, &World, Collision(),
|
||||
Direction, //StartDir
|
||||
ProjStartPos, //StartPos
|
||||
Tick-1, //StartTick
|
||||
WEAPON_GRENADE, //Type
|
||||
m_Snap.m_LocalClientID, //Owner
|
||||
WEAPON_GRENADE, //Weapon
|
||||
1000, //LifeSpan
|
||||
1, 0, 0, 1); //Explosive, Bouncing, Freeze, ExtraInfo
|
||||
m_aLocalProjectiles[(Tick-1)%64] = TempProjectiles[NumProjectiles];
|
||||
NumProjectiles++;
|
||||
} break;
|
||||
|
||||
case WEAPON_HAMMER:
|
||||
{
|
||||
vec2 ProjPos = ProjStartPos;
|
||||
float Radius = ProximityRadius*0.5f;
|
||||
|
||||
int Hits = 0;
|
||||
bool OwnerCanProbablyHitOthers = (m_Tuning[g_Config.m_ClDummy].m_PlayerCollision || m_Tuning[g_Config.m_ClDummy].m_PlayerHooking);
|
||||
if(!OwnerCanProbablyHitOthers)
|
||||
break;
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if(!World.m_apCharacters[i])
|
||||
continue;
|
||||
if(i == m_Snap.m_LocalClientID)
|
||||
continue;
|
||||
if(!(distance(World.m_apCharacters[i]->m_Pos, ProjPos) < Radius+ProximityRadius))
|
||||
continue;;
|
||||
|
||||
CCharacterCore *pTarget = World.m_apCharacters[i];
|
||||
|
||||
if(m_aClients[i].m_Active && !m_Teams.CanCollide(i, m_Snap.m_LocalClientID))
|
||||
continue;
|
||||
|
||||
vec2 Dir;
|
||||
if (length(pTarget->m_Pos - Pos) > 0.0f)
|
||||
Dir = normalize(pTarget->m_Pos - Pos);
|
||||
else
|
||||
Dir = vec2(0.f, -1.f);
|
||||
|
||||
float Strength;
|
||||
Strength = World.m_Tuning[g_Config.m_ClDummy].m_HammerStrength;
|
||||
|
||||
vec2 Temp = pTarget->m_Vel + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f;
|
||||
|
||||
Temp -= pTarget->m_Vel;
|
||||
pTarget->TakeDamage((vec2(0.f, -1.0f) + Temp) * Strength);
|
||||
Hits++;
|
||||
}
|
||||
// if we Hit anything, we have to wait for the reload
|
||||
//if(Hits)
|
||||
//ReloadTimer = SERVER_TICK_SPEED/3;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ReloadTimer)
|
||||
ReloadTimer--;
|
||||
|
||||
// projectiles
|
||||
if(g_Config.m_ClAntiPingWeapons)
|
||||
for(int g = 0; g < 64; g++)
|
||||
if(TempProjectiles[g].m_Active)
|
||||
TempProjectiles[g].Tick(Tick, Client()->GameTickSpeed(), m_Snap.m_LocalClientID);
|
||||
|
||||
// first calculate where everyone should move
|
||||
for(int c = 0; c < MAX_CLIENTS; c++)
|
||||
{
|
||||
if(!World.m_apCharacters[c])
|
||||
continue;
|
||||
|
||||
if(m_Snap.m_LocalClientID == c)
|
||||
{
|
||||
World.m_apCharacters[c]->Tick(true, true);
|
||||
}
|
||||
else
|
||||
World.m_apCharacters[c]->Tick(false, true);
|
||||
|
||||
}
|
||||
|
||||
// move all players and quantize their data
|
||||
|
@ -1268,6 +1439,7 @@ void CGameClient::OnPredict()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if(Tick == Client()->PredGameTick() && World.m_apCharacters[m_Snap.m_LocalClientID])
|
||||
{
|
||||
m_PredictedChar = *World.m_apCharacters[m_Snap.m_LocalClientID];
|
||||
|
@ -1285,6 +1457,7 @@ void CGameClient::OnPredict()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if(g_Config.m_Debug && g_Config.m_ClPredict && m_PredictedTick == Client()->PredGameTick())
|
||||
{
|
||||
CNetObj_CharacterCore Before = {0}, Now = {0}, BeforePrev = {0}, NowPrev = {0};
|
||||
|
@ -1479,6 +1652,7 @@ IGameClient *CreateGameClient()
|
|||
return &g_GameClient;
|
||||
}
|
||||
|
||||
|
||||
int CGameClient::IntersectCharacter(vec2 HookPos, vec2 NewPos, vec2& NewPos2, int ownID)
|
||||
{
|
||||
float PhysSize = 28.0f;
|
||||
|
@ -1510,6 +1684,214 @@ int CGameClient::IntersectCharacter(vec2 HookPos, vec2 NewPos, vec2& NewPos2, in
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ClosestID;
|
||||
}
|
||||
|
||||
int CGameClient::IntersectCharacter(vec2 OldPos, vec2 NewPos, float Radius, vec2 *NewPos2, int ownID, CWorldCore *World)
|
||||
{
|
||||
|
||||
float PhysSize = 28.0f;
|
||||
float Distance = 0.0f;
|
||||
int ClosestID = -1;
|
||||
|
||||
if(!World)
|
||||
return ClosestID;
|
||||
|
||||
for (int i=0; i<MAX_CLIENTS; i++)
|
||||
{
|
||||
if(!World->m_apCharacters[i])
|
||||
continue;
|
||||
CClientData cData = m_aClients[i];
|
||||
|
||||
if(!cData.m_Active || i == ownID || !m_Teams.CanCollide(i, ownID))
|
||||
continue;
|
||||
vec2 Position = World->m_apCharacters[i]->m_Pos;
|
||||
vec2 ClosestPoint = closest_point_on_line(OldPos, NewPos, Position);
|
||||
if(distance(Position, ClosestPoint) < PhysSize+Radius)
|
||||
{
|
||||
if(ClosestID == -1 || distance(OldPos, Position) < Distance)
|
||||
{
|
||||
*NewPos2 = ClosestPoint;
|
||||
ClosestID = i;
|
||||
Distance = distance(OldPos, Position);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ClosestID;
|
||||
}
|
||||
|
||||
void CLocalProjectile::Init(CGameClient *pGameClient, CWorldCore *pWorld, CCollision *pCollision, const CNetObj_Projectile *pProj)
|
||||
{
|
||||
m_Active = 1;
|
||||
m_pGameClient = pGameClient;
|
||||
m_pWorld = pWorld;
|
||||
m_pCollision = pCollision;
|
||||
m_StartTick = pProj->m_StartTick;
|
||||
m_Type = pProj->m_Type;
|
||||
m_Weapon = m_Type;
|
||||
|
||||
ExtractInfo(pProj, &m_Pos, &m_Direction);
|
||||
|
||||
if(HasExtraInfo(pProj))
|
||||
{
|
||||
ExtractExtraInfo(pProj, &m_Owner, &m_LifeSpan, &m_Explosive, &m_Bouncing, &m_Freeze);
|
||||
m_ExtraInfo = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Owner = -1;
|
||||
m_Explosive = (m_Type == WEAPON_GRENADE ? true : false);
|
||||
m_Bouncing = 0;
|
||||
m_Freeze = 0;
|
||||
m_LifeSpan = -2;
|
||||
m_ExtraInfo = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CLocalProjectile::Init(CGameClient *pGameClient, CWorldCore *pWorld, CCollision *pCollision, vec2 Direction, vec2 Pos, int StartTick, int Type, int Owner, int Weapon, int LifeSpan, bool Explosive, int Bouncing, bool Freeze, bool ExtraInfo)
|
||||
{
|
||||
m_Active = 1;
|
||||
m_pGameClient = pGameClient;
|
||||
m_pWorld = pWorld;
|
||||
m_pCollision = pCollision;
|
||||
m_Direction = Direction;
|
||||
m_Pos = Pos;
|
||||
m_StartTick = StartTick;
|
||||
m_Type = Type;
|
||||
m_Weapon = Weapon;
|
||||
m_LifeSpan = LifeSpan;
|
||||
m_Owner = Owner;
|
||||
m_Explosive = Explosive;
|
||||
m_Bouncing = Bouncing;
|
||||
m_Freeze = Freeze;
|
||||
m_ExtraInfo = ExtraInfo;
|
||||
}
|
||||
|
||||
vec2 CLocalProjectile::GetPos(float Time)
|
||||
{
|
||||
float Curvature = 0;
|
||||
float Speed = 0;
|
||||
|
||||
switch(m_Type)
|
||||
{
|
||||
case WEAPON_GRENADE:
|
||||
Curvature = m_pWorld->m_Tuning[g_Config.m_ClDummy].m_GrenadeCurvature;
|
||||
Speed = m_pWorld->m_Tuning[g_Config.m_ClDummy].m_GrenadeSpeed;
|
||||
break;
|
||||
|
||||
case WEAPON_SHOTGUN:
|
||||
Curvature = m_pWorld->m_Tuning[g_Config.m_ClDummy].m_ShotgunCurvature;
|
||||
Speed = m_pWorld->m_Tuning[g_Config.m_ClDummy].m_ShotgunSpeed;
|
||||
break;
|
||||
|
||||
case WEAPON_GUN:
|
||||
Curvature = m_pWorld->m_Tuning[g_Config.m_ClDummy].m_GunCurvature;
|
||||
Speed = m_pWorld->m_Tuning[g_Config.m_ClDummy].m_GunSpeed;
|
||||
break;
|
||||
}
|
||||
|
||||
return CalcPos(m_Pos, m_Direction, Curvature, Speed, Time);
|
||||
}
|
||||
|
||||
bool CLocalProjectile::GameLayerClipped(vec2 CheckPos)
|
||||
{
|
||||
return round_to_int(CheckPos.x)/32 < -200 || round_to_int(CheckPos.x)/32 > m_pCollision->GetWidth()+200 ||
|
||||
round_to_int(CheckPos.y)/32 < -200 || round_to_int(CheckPos.y)/32 > m_pCollision->GetHeight()+200 ? true : false;
|
||||
}
|
||||
|
||||
|
||||
void CLocalProjectile::Tick(int CurrentTick, int GameTickSpeed, int LocalClientID)
|
||||
{
|
||||
if(!m_pWorld)
|
||||
return;
|
||||
float Pt = (CurrentTick-m_StartTick-1)/(float)GameTickSpeed;
|
||||
float Ct = (CurrentTick-m_StartTick)/(float)GameTickSpeed;
|
||||
|
||||
vec2 PrevPos = GetPos(Pt);
|
||||
vec2 CurPos = GetPos(Ct);
|
||||
vec2 ColPos;
|
||||
vec2 NewPos;
|
||||
int Collide = 0;
|
||||
if(m_pCollision)
|
||||
Collide = m_pCollision->IntersectLine(PrevPos, CurPos, &ColPos, &NewPos, false);
|
||||
int Target = m_pGameClient->IntersectCharacter(PrevPos, ColPos, m_Freeze ? 1.0f : 6.0f, &ColPos, m_Owner, m_pWorld);
|
||||
|
||||
if(m_LifeSpan > -1)
|
||||
m_LifeSpan--;
|
||||
|
||||
bool isWeaponCollide = false;
|
||||
if
|
||||
(
|
||||
m_Owner >= 0 &&
|
||||
Target >= 0 &&
|
||||
m_pGameClient->m_aClients[m_Owner].m_Active &&
|
||||
m_pGameClient->m_aClients[Target].m_Active &&
|
||||
!m_pGameClient->m_Teams.CanCollide(m_Owner, Target)
|
||||
)
|
||||
isWeaponCollide = true;
|
||||
|
||||
bool OwnerCanProbablyHitOthers = (m_pWorld->m_Tuning[g_Config.m_ClDummy].m_PlayerCollision || m_pWorld->m_Tuning[g_Config.m_ClDummy].m_PlayerHooking);
|
||||
|
||||
if(((Target >= 0 && (m_Owner >= 0 ? OwnerCanProbablyHitOthers : 1 || Target == m_Owner)) || Collide || GameLayerClipped(CurPos)) && !isWeaponCollide)
|
||||
{
|
||||
if(m_Explosive && (Target < 0 || (Target >= 0 && (!m_Freeze || (m_Weapon == WEAPON_SHOTGUN && Collide)))))
|
||||
CreateExplosion(ColPos, m_Owner);
|
||||
if(Collide && m_Bouncing != 0)
|
||||
{
|
||||
m_StartTick = CurrentTick;
|
||||
m_Pos = NewPos+(-(m_Direction*4));
|
||||
if (m_Bouncing == 1)
|
||||
m_Direction.x = -m_Direction.x;
|
||||
else if(m_Bouncing == 2)
|
||||
m_Direction.y =- m_Direction.y;
|
||||
if (fabs(m_Direction.x) < 1e-6)
|
||||
m_Direction.x = 0;
|
||||
if (fabs(m_Direction.y) < 1e-6)
|
||||
m_Direction.y = 0;
|
||||
m_Pos += m_Direction;
|
||||
}
|
||||
else if(!m_Bouncing)
|
||||
Deactivate();
|
||||
}
|
||||
//if(m_LifeSpan == -1)
|
||||
//{
|
||||
//if(m_Explosive)
|
||||
//{
|
||||
//CreateExplosion(ColPos, LocalClientID);
|
||||
//}
|
||||
//Deactivate();
|
||||
//}
|
||||
}
|
||||
|
||||
void CLocalProjectile::CreateExplosion(vec2 Pos, int LocalClientID)
|
||||
{
|
||||
if(!m_pWorld)
|
||||
return;
|
||||
float Radius = 135.0f;
|
||||
float InnerRadius = 48.0f;
|
||||
|
||||
bool OwnerCanProbablyHitOthers = (m_pWorld->m_Tuning[g_Config.m_ClDummy].m_PlayerCollision || m_pWorld->m_Tuning[g_Config.m_ClDummy].m_PlayerHooking);
|
||||
|
||||
for(int c = 0; c < MAX_CLIENTS; c++)
|
||||
{
|
||||
if(!m_pWorld->m_apCharacters[c])
|
||||
continue;
|
||||
if(m_Owner >= 0 && c >= 0)
|
||||
if(m_pGameClient->m_aClients[c].m_Active && !m_pGameClient->m_Teams.CanCollide(c, m_Owner))
|
||||
continue;
|
||||
if(c != LocalClientID && !OwnerCanProbablyHitOthers)
|
||||
continue;
|
||||
vec2 Diff = m_pWorld->m_apCharacters[c]->m_Pos - Pos;
|
||||
vec2 ForceDir(0,1);
|
||||
float l = length(Diff);
|
||||
if(l)
|
||||
ForceDir = normalize(Diff);
|
||||
l = 1-clamp((l-InnerRadius)/(Radius-InnerRadius), 0.0f, 1.0f);
|
||||
|
||||
float Strength = m_pWorld->m_Tuning[g_Config.m_ClDummy].m_ExplosionStrength;
|
||||
float Dmg = Strength * l;
|
||||
|
||||
if((int)Dmg)
|
||||
m_pWorld->m_apCharacters[c]->TakeDamage(ForceDir*Dmg*2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,39 @@
|
|||
: \
|
||||
((x) >= (z) ? (x) : (z)))
|
||||
|
||||
class CGameClient;
|
||||
|
||||
class CLocalProjectile
|
||||
{
|
||||
public:
|
||||
int m_Active;
|
||||
CGameClient *m_pGameClient;
|
||||
CWorldCore *m_pWorld;
|
||||
CCollision *m_pCollision;
|
||||
|
||||
vec2 m_Direction;
|
||||
vec2 m_Pos;
|
||||
int m_StartTick;
|
||||
int m_Type;
|
||||
|
||||
int m_Owner;
|
||||
int m_Weapon;
|
||||
int m_LifeSpan;
|
||||
bool m_Explosive;
|
||||
int m_Bouncing;
|
||||
bool m_Freeze;
|
||||
bool m_ExtraInfo;
|
||||
|
||||
vec2 GetPos(float Time);
|
||||
void CreateExplosion(vec2 Pos, int LocalClientID);
|
||||
void Tick(int CurrentTick, int GameTickSpeed, int LocalClientID);
|
||||
void Init(CGameClient *pGameClient, CWorldCore *pWorld, CCollision *pCollision, const CNetObj_Projectile *pProj);
|
||||
void Init(CGameClient *pGameClient, CWorldCore *pWorld, CCollision *pCollision, vec2 Direction, vec2 Pos, int StartTick, int Type, int Owner, int Weapon, int LifeSpan, bool Explosive, int Bouncing, bool Freeze, bool ExtraInfo);
|
||||
|
||||
bool GameLayerClipped(vec2 CheckPos);
|
||||
void Deactivate() { m_Active = 0; }
|
||||
};
|
||||
|
||||
class CGameClient : public IGameClient
|
||||
{
|
||||
class CStack
|
||||
|
@ -283,6 +316,9 @@ public:
|
|||
class CTeamsCore m_Teams;
|
||||
|
||||
int IntersectCharacter(vec2 Pos0, vec2 Pos1, vec2& NewPos, int ownID);
|
||||
int IntersectCharacter(vec2 OldPos, vec2 NewPos, float Radius, vec2* NewPos2, int ownID, CWorldCore *World);
|
||||
|
||||
class CLocalProjectile m_aLocalProjectiles[64];
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -697,6 +697,61 @@ void CCharacterCore::Quantize()
|
|||
|
||||
// DDRace
|
||||
|
||||
bool HasExtraInfo(const CNetObj_Projectile *pProj)
|
||||
{
|
||||
return ((abs(pProj->m_VelY) & (1<<9)) != 0);
|
||||
}
|
||||
|
||||
void ExtractInfo(const CNetObj_Projectile *pProj, vec2 *StartPos, vec2 *StartVel)
|
||||
{
|
||||
if(!StartPos || !StartVel)
|
||||
return;
|
||||
if(!HasExtraInfo(pProj))
|
||||
{
|
||||
StartPos->x = pProj->m_X + 0.5f * sign(pProj->m_X);
|
||||
StartPos->y = pProj->m_Y + 0.5f * sign(pProj->m_Y);
|
||||
StartVel->x = pProj->m_VelX + 0.5f *sign(pProj->m_VelX);
|
||||
StartVel->y = pProj->m_VelY + 0.5f *sign(pProj->m_VelY);
|
||||
//StartVel->x = pProj->m_VelX/100.0f;
|
||||
//StartVel->y = pProj->m_VelY/100.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
StartPos->x = (pProj->m_X + 0.5f * sign(pProj->m_X))/1000.0f;
|
||||
StartPos->y = (pProj->m_Y + 0.5f * sign(pProj->m_Y))/1000.0f;
|
||||
float Angle = (pProj->m_VelX + 0.5f * sign(pProj->m_VelX))/1000000.0f;
|
||||
StartVel->x = sin(-Angle);
|
||||
StartVel->y = cos(-Angle);
|
||||
}
|
||||
*StartVel = normalize(*StartVel);
|
||||
}
|
||||
|
||||
void ExtractExtraInfo(const CNetObj_Projectile *pProj, int *Owner, int *LifeSpan, bool *Explosive, int *Bouncing = 0, bool *Freeze = 0)
|
||||
{
|
||||
if(!HasExtraInfo(pProj))
|
||||
return;
|
||||
int Data = pProj->m_VelY;
|
||||
if(Owner)
|
||||
{
|
||||
*Owner = Data & 255;
|
||||
if((Data>>8) & 1)
|
||||
*Owner = -(*Owner);
|
||||
}
|
||||
// HasExtraInfo = ((Data>>9) & 1);
|
||||
if(LifeSpan)
|
||||
{
|
||||
*LifeSpan = (Data>>10) & 255;
|
||||
if((Data >> 18) & 1)
|
||||
*LifeSpan = -(*LifeSpan);
|
||||
}
|
||||
if(Explosive)
|
||||
*Explosive = (Data>>19) & 1;
|
||||
if(Bouncing)
|
||||
*Bouncing = (Data>>20) & 3;
|
||||
if(Freeze)
|
||||
*Freeze = (Data>>22) & 1;
|
||||
}
|
||||
|
||||
bool CCharacterCore::IsRightTeam(int MapIndex)
|
||||
{
|
||||
if(Collision()->m_pSwitchers)
|
||||
|
@ -704,3 +759,18 @@ bool CCharacterCore::IsRightTeam(int MapIndex)
|
|||
return Collision()->m_pSwitchers[Collision()->GetDTileNumber(MapIndex)].m_Status[m_pTeams->Team(m_Id)];
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CCharacterCore::TakeDamage(vec2 Force)
|
||||
{
|
||||
vec2 Temp = m_Vel + Force;
|
||||
if(Temp.x > 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_270) || (m_TileIndexL == TILE_STOP && m_TileFlagsL == ROTATION_270) || (m_TileIndexL == TILE_STOPS && (m_TileFlagsL == ROTATION_90 || m_TileFlagsL ==ROTATION_270)) || (m_TileIndexL == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_270) || (m_TileFIndexL == TILE_STOP && m_TileFFlagsL == ROTATION_270) || (m_TileFIndexL == TILE_STOPS && (m_TileFFlagsL == ROTATION_90 || m_TileFFlagsL == ROTATION_270)) || (m_TileFIndexL == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_270) || (m_TileSIndexL == TILE_STOP && m_TileSFlagsL == ROTATION_270) || (m_TileSIndexL == TILE_STOPS && (m_TileSFlagsL == ROTATION_90 || m_TileSFlagsL == ROTATION_270)) || (m_TileSIndexL == TILE_STOPA)))
|
||||
Temp.x = 0;
|
||||
if(Temp.x < 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_90) || (m_TileIndexR == TILE_STOP && m_TileFlagsR == ROTATION_90) || (m_TileIndexR == TILE_STOPS && (m_TileFlagsR == ROTATION_90 || m_TileFlagsR == ROTATION_270)) || (m_TileIndexR == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_90) || (m_TileFIndexR == TILE_STOP && m_TileFFlagsR == ROTATION_90) || (m_TileFIndexR == TILE_STOPS && (m_TileFFlagsR == ROTATION_90 || m_TileFFlagsR == ROTATION_270)) || (m_TileFIndexR == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_90) || (m_TileSIndexR == TILE_STOP && m_TileSFlagsR == ROTATION_90) || (m_TileSIndexR == TILE_STOPS && (m_TileSFlagsR == ROTATION_90 || m_TileSFlagsR == ROTATION_270)) || (m_TileSIndexR == TILE_STOPA)))
|
||||
Temp.x = 0;
|
||||
if(Temp.y < 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_180) || (m_TileIndexB == TILE_STOP && m_TileFlagsB == ROTATION_180) || (m_TileIndexB == TILE_STOPS && (m_TileFlagsB == ROTATION_0 || m_TileFlagsB == ROTATION_180)) || (m_TileIndexB == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_180) || (m_TileFIndexB == TILE_STOP && m_TileFFlagsB == ROTATION_180) || (m_TileFIndexB == TILE_STOPS && (m_TileFFlagsB == ROTATION_0 || m_TileFFlagsB == ROTATION_180)) || (m_TileFIndexB == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_180) || (m_TileSIndexB == TILE_STOP && m_TileSFlagsB == ROTATION_180) || (m_TileSIndexB == TILE_STOPS && (m_TileSFlagsB == ROTATION_0 || m_TileSFlagsB == ROTATION_180)) || (m_TileSIndexB == TILE_STOPA)))
|
||||
Temp.y = 0;
|
||||
if(Temp.y > 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_0) || (m_TileIndexT == TILE_STOP && m_TileFlagsT == ROTATION_0) || (m_TileIndexT == TILE_STOPS && (m_TileFlagsT == ROTATION_0 || m_TileFlagsT == ROTATION_180)) || (m_TileIndexT == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_0) || (m_TileFIndexT == TILE_STOP && m_TileFFlagsT == ROTATION_0) || (m_TileFIndexT == TILE_STOPS && (m_TileFFlagsT == ROTATION_0 || m_TileFFlagsT == ROTATION_180)) || (m_TileFIndexT == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_0) || (m_TileSIndexT == TILE_STOP && m_TileSFlagsT == ROTATION_0) || (m_TileSIndexT == TILE_STOPS && (m_TileSFlagsT == ROTATION_0 || m_TileSFlagsT == ROTATION_180)) || (m_TileSIndexT == TILE_STOPA)))
|
||||
Temp.y = 0;
|
||||
m_Vel = Temp;
|
||||
}
|
||||
|
|
|
@ -233,6 +233,8 @@ public:
|
|||
int m_Colliding;
|
||||
bool m_LeftWall;
|
||||
|
||||
void TakeDamage(vec2 Force);
|
||||
|
||||
private:
|
||||
|
||||
CTeamsCore* m_pTeams;
|
||||
|
@ -269,4 +271,35 @@ private:
|
|||
bool IsRightTeam(int MapIndex);
|
||||
};
|
||||
|
||||
bool HasExtraInfo(const CNetObj_Projectile *pProj);
|
||||
void ExtractInfo(const CNetObj_Projectile *pProj, vec2 *StartPos, vec2 *StartVel);
|
||||
void ExtractExtraInfo(const CNetObj_Projectile *pProj, int *Owner, int *m_LifeSpan, bool *Explosive, int *Bouncing, bool *Freeze);
|
||||
|
||||
//input count
|
||||
struct CInputCount
|
||||
{
|
||||
int m_Presses;
|
||||
int m_Releases;
|
||||
};
|
||||
|
||||
inline CInputCount CountInput(int Prev, int Cur)
|
||||
{
|
||||
CInputCount c = {0, 0};
|
||||
Prev &= INPUT_STATE_MASK;
|
||||
Cur &= INPUT_STATE_MASK;
|
||||
int i = Prev;
|
||||
|
||||
while(i != Cur)
|
||||
{
|
||||
i = (i+1)&INPUT_STATE_MASK;
|
||||
if(i&1)
|
||||
c.m_Presses++;
|
||||
else
|
||||
c.m_Releases++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,33 +16,6 @@
|
|||
#include <game/server/score.h>
|
||||
#include "light.h"
|
||||
|
||||
//input count
|
||||
struct CInputCount
|
||||
{
|
||||
int m_Presses;
|
||||
int m_Releases;
|
||||
};
|
||||
|
||||
CInputCount CountInput(int Prev, int Cur)
|
||||
{
|
||||
CInputCount c = {0, 0};
|
||||
Prev &= INPUT_STATE_MASK;
|
||||
Cur &= INPUT_STATE_MASK;
|
||||
int i = Prev;
|
||||
|
||||
while(i != Cur)
|
||||
{
|
||||
i = (i+1)&INPUT_STATE_MASK;
|
||||
if(i&1)
|
||||
c.m_Presses++;
|
||||
else
|
||||
c.m_Releases++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
MACRO_ALLOC_POOL_ID_IMPL(CCharacter, MAX_CLIENTS)
|
||||
|
||||
// Character, "physical" player's part
|
||||
|
@ -372,7 +345,6 @@ void CCharacter::FireWeapon()
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 ProjStartPos = m_Pos+Direction*m_ProximityRadius*0.75f;
|
||||
|
||||
switch(m_Core.m_ActiveWeapon)
|
||||
|
@ -550,6 +522,9 @@ void CCharacter::FireWeapon()
|
|||
|
||||
// pack the Projectile and send it to the client Directly
|
||||
CNetObj_Projectile p;
|
||||
if(m_pPlayer && m_pPlayer->m_ClientVersion >= VERSION_DDNET_ANTIPING_PROJECTILE)
|
||||
pProj->FillExtraInfo(&p);
|
||||
else
|
||||
pProj->FillInfo(&p);
|
||||
|
||||
CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
|
||||
|
@ -613,7 +588,7 @@ void CCharacter::HandleWeapons()
|
|||
}
|
||||
|
||||
// fire Weapon, if wanted
|
||||
FireWeapon();
|
||||
//FireWeapon();
|
||||
/*
|
||||
// ammo regen
|
||||
int AmmoRegenTime = g_pData->m_Weapons.m_aId[m_Core.m_ActiveWeapon].m_Ammoregentime;
|
||||
|
@ -843,6 +818,8 @@ void CCharacter::TickDefered()
|
|||
m_Core.m_pReset = false;
|
||||
}
|
||||
}
|
||||
|
||||
FireWeapon();
|
||||
}
|
||||
|
||||
void CCharacter::TickPaused()
|
||||
|
|
|
@ -232,6 +232,33 @@ void CProjectile::FillInfo(CNetObj_Projectile *pProj)
|
|||
pProj->m_Type = m_Type;
|
||||
}
|
||||
|
||||
void CProjectile::FillExtraInfo(CNetObj_Projectile *pProj)
|
||||
{
|
||||
//Send additional/modified info, by modifiying the fields of the netobj
|
||||
float Angle = -atan2f(m_Direction.x, m_Direction.y);
|
||||
|
||||
int Data = 0;
|
||||
Data |= (abs(m_Owner) & 255);
|
||||
if(m_Owner < 0)
|
||||
Data |= 1 << 8;
|
||||
Data |= 1<<9; //This bit tells the client to use the extra info
|
||||
Data |= ((abs(m_LifeSpan) <= 255 ? abs(m_LifeSpan) : 255) & 255) << 10;
|
||||
if(m_LifeSpan < 0)
|
||||
Data |= 1 << 18;
|
||||
if(m_Explosive)
|
||||
Data |= (1 << 19);
|
||||
Data |= (m_Bouncing & 3) << 20;
|
||||
if(m_Freeze)
|
||||
Data |= (1 << 22);
|
||||
|
||||
pProj->m_X = (int)(m_Pos.x * 1000.0f);
|
||||
pProj->m_Y = (int)(m_Pos.y * 1000.0f);
|
||||
pProj->m_VelX = (int)(Angle * 1000000.0f);
|
||||
pProj->m_VelY = Data;
|
||||
pProj->m_StartTick = m_StartTick;
|
||||
pProj->m_Type = m_Type;
|
||||
}
|
||||
|
||||
void CProjectile::Snap(int SnappingClient)
|
||||
{
|
||||
float Ct = (Server()->Tick()-m_StartTick)/(float)Server()->TickSpeed();
|
||||
|
@ -258,7 +285,12 @@ void CProjectile::Snap(int SnappingClient)
|
|||
|
||||
CNetObj_Projectile *pProj = static_cast<CNetObj_Projectile *>(Server()->SnapNewItem(NETOBJTYPE_PROJECTILE, m_ID, sizeof(CNetObj_Projectile)));
|
||||
if(pProj)
|
||||
{
|
||||
if (SnappingClient > -1 && GameServer()->m_apPlayers[SnappingClient] && GameServer()->m_apPlayers[SnappingClient]->m_ClientVersion >= VERSION_DDNET_ANTIPING_PROJECTILE)
|
||||
FillExtraInfo(pProj);
|
||||
else
|
||||
FillInfo(pProj);
|
||||
}
|
||||
}
|
||||
|
||||
// DDRace
|
||||
|
|
|
@ -25,6 +25,7 @@ public:
|
|||
|
||||
vec2 GetPos(float Time);
|
||||
void FillInfo(CNetObj_Projectile *pProj);
|
||||
void FillExtraInfo(CNetObj_Projectile *pProj);
|
||||
|
||||
virtual void Reset();
|
||||
virtual void Tick();
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
MACRO_CONFIG_INT(ClPredict, cl_predict, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Predict client movements")
|
||||
MACRO_CONFIG_INT(ClAntiPing, cl_antiping, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Antiping (predict other players' movements)")
|
||||
MACRO_CONFIG_INT(ClAntiPingGrenade, cl_antiping_grenade, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Antiping (predict grenades)")
|
||||
MACRO_CONFIG_INT(ClAntiPingWeapons, cl_antiping_weapons, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Antiping (predict weapons)")
|
||||
MACRO_CONFIG_INT(ClNameplates, cl_nameplates, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show name plates")
|
||||
MACRO_CONFIG_INT(ClNameplatesAlways, cl_nameplates_always, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Always show name plates disregarding of distance")
|
||||
MACRO_CONFIG_INT(ClNameplatesTeamcolors, cl_nameplates_teamcolors, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Use team colors for name plates")
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#ifndef GAME_VERSION_H
|
||||
#define GAME_VERSION_H
|
||||
#include "generated/nethash.cpp"
|
||||
#define GAME_VERSION "0.6.2, 5.3"
|
||||
#define GAME_VERSION "0.6.2, 6.0"
|
||||
#define GAME_NETVERSION "0.6 626fce9a778df4d4"
|
||||
static const char GAME_RELEASE_VERSION[8] = "5.3";
|
||||
#define CLIENT_VERSIONNR 503
|
||||
static const char GAME_RELEASE_VERSION[8] = "6.0";
|
||||
#define CLIENT_VERSIONNR 600
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue