Feature: Separate inputs for dummy and player

This commit is contained in:
def 2014-05-10 14:31:00 +02:00
parent 0d5790b8cd
commit 5b1c866b35
8 changed files with 137 additions and 117 deletions

View file

@ -305,7 +305,8 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD
m_CurrentServerInfoRequestTime = -1; m_CurrentServerInfoRequestTime = -1;
m_CurrentInput = 0; m_CurrentInput[0] = 0;
m_CurrentInput[1] = 0;
m_LastDummy = 0; m_LastDummy = 0;
m_LastDummy2 = 0; m_LastDummy2 = 0;
m_LocalIDs[0] = 0; m_LocalIDs[0] = 0;
@ -440,7 +441,7 @@ void CClient::SendInput()
return; return;
// fetch input // fetch input
int Size = GameClient()->OnSnapInput(m_aInputs[m_CurrentInput].m_aData); int Size = GameClient()->OnSnapInput(m_aInputs[g_Config.m_ClDummy][m_CurrentInput[g_Config.m_ClDummy]].m_aData);
if(Size) if(Size)
{ {
@ -450,22 +451,22 @@ void CClient::SendInput()
Msg.AddInt(m_PredTick[g_Config.m_ClDummy]); Msg.AddInt(m_PredTick[g_Config.m_ClDummy]);
Msg.AddInt(Size); Msg.AddInt(Size);
m_aInputs[m_CurrentInput].m_Tick = m_PredTick[g_Config.m_ClDummy]; m_aInputs[g_Config.m_ClDummy][m_CurrentInput[g_Config.m_ClDummy]].m_Tick = m_PredTick[g_Config.m_ClDummy];
m_aInputs[m_CurrentInput].m_PredictedTime = m_PredictedTime.Get(Now); m_aInputs[g_Config.m_ClDummy][m_CurrentInput[g_Config.m_ClDummy]].m_PredictedTime = m_PredictedTime.Get(Now);
m_aInputs[m_CurrentInput].m_Time = Now; m_aInputs[g_Config.m_ClDummy][m_CurrentInput[g_Config.m_ClDummy]].m_Time = Now;
// pack it // pack it
for(int i = 0; i < Size/4; i++) for(int i = 0; i < Size/4; i++)
Msg.AddInt(m_aInputs[m_CurrentInput].m_aData[i]); Msg.AddInt(m_aInputs[g_Config.m_ClDummy][m_CurrentInput[g_Config.m_ClDummy]].m_aData[i]);
m_CurrentInput++; m_CurrentInput[g_Config.m_ClDummy]++;
m_CurrentInput%=200; m_CurrentInput[g_Config.m_ClDummy]%=200;
SendMsgEx(&Msg, MSGFLAG_FLUSH); SendMsgEx(&Msg, MSGFLAG_FLUSH);
if(m_LastDummy != g_Config.m_ClDummy) if(m_LastDummy != g_Config.m_ClDummy)
{ {
mem_copy(&DummyInput, &m_aInputs[(m_CurrentInput+200-2)%200], sizeof(DummyInput)); mem_copy(&DummyInput, &m_aInputs[!g_Config.m_ClDummy][(m_CurrentInput[!g_Config.m_ClDummy]+200-2)%200], sizeof(DummyInput));
m_LastDummy = g_Config.m_ClDummy; m_LastDummy = g_Config.m_ClDummy;
} }
} }
@ -544,12 +545,12 @@ int *CClient::GetInput(int Tick)
int Best = -1; int Best = -1;
for(int i = 0; i < 200; i++) for(int i = 0; i < 200; i++)
{ {
if(m_aInputs[i].m_Tick <= Tick && (Best == -1 || m_aInputs[Best].m_Tick < m_aInputs[i].m_Tick)) if(m_aInputs[g_Config.m_ClDummy][i].m_Tick <= Tick && (Best == -1 || m_aInputs[g_Config.m_ClDummy][Best].m_Tick < m_aInputs[g_Config.m_ClDummy][i].m_Tick))
Best = i; Best = i;
} }
if(Best != -1) if(Best != -1)
return (int *)m_aInputs[Best].m_aData; return (int *)m_aInputs[g_Config.m_ClDummy][Best].m_aData;
return 0; return 0;
} }
@ -577,8 +578,12 @@ void CClient::OnEnterGame()
// reset input // reset input
int i; int i;
for(i = 0; i < 200; i++) for(i = 0; i < 200; i++)
m_aInputs[i].m_Tick = -1; {
m_CurrentInput = 0; m_aInputs[0][i].m_Tick = -1;
m_aInputs[1][i].m_Tick = -1;
}
m_CurrentInput[0] = 0;
m_CurrentInput[1] = 0;
// reset snapshots // reset snapshots
m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] = 0; m_aSnapshots[g_Config.m_ClDummy][SNAP_CURRENT] = 0;
@ -1508,9 +1513,9 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
int64 Target = 0; int64 Target = 0;
for(int k = 0; k < 200; k++) for(int k = 0; k < 200; k++)
{ {
if(m_aInputs[k].m_Tick == InputPredTick) if(m_aInputs[g_Config.m_ClDummy][k].m_Tick == InputPredTick)
{ {
Target = m_aInputs[k].m_PredictedTime + (Now - m_aInputs[k].m_Time); Target = m_aInputs[g_Config.m_ClDummy][k].m_PredictedTime + (Now - m_aInputs[g_Config.m_ClDummy][k].m_Time);
Target = Target - (int64)(((TimeLeft-PREDICTION_MARGIN)/1000.0f)*time_freq()); Target = Target - (int64)(((TimeLeft-PREDICTION_MARGIN)/1000.0f)*time_freq());
break; break;
} }

View file

@ -142,9 +142,9 @@ class CClient : public IClient, public CDemoPlayer::IListner
int m_Tick; // the tick that the input is for int m_Tick; // the tick that the input is for
int64 m_PredictedTime; // prediction latency when we sent this input int64 m_PredictedTime; // prediction latency when we sent this input
int64 m_Time; int64 m_Time;
} m_aInputs[200]; } m_aInputs[2][200];
int m_CurrentInput; int m_CurrentInput[2];
bool m_LastDummy; bool m_LastDummy;
bool m_LastDummy2; bool m_LastDummy2;
CNetObj_PlayerInput DummyInput; CNetObj_PlayerInput DummyInput;

View file

@ -31,11 +31,11 @@ void CCamera::OnRender()
{ {
if(m_CamType != CAMTYPE_SPEC) if(m_CamType != CAMTYPE_SPEC)
{ {
m_pClient->m_pControls->m_MousePos = m_PrevCenter; m_pClient->m_pControls->m_MousePos[g_Config.m_ClDummy] = m_PrevCenter;
m_pClient->m_pControls->ClampMousePos(); m_pClient->m_pControls->ClampMousePos();
m_CamType = CAMTYPE_SPEC; m_CamType = CAMTYPE_SPEC;
} }
m_Center = m_pClient->m_pControls->m_MousePos; m_Center = m_pClient->m_pControls->m_MousePos[g_Config.m_ClDummy];
} }
else else
{ {
@ -47,14 +47,14 @@ void CCamera::OnRender()
vec2 CameraOffset(0, 0); vec2 CameraOffset(0, 0);
float l = length(m_pClient->m_pControls->m_MousePos); float l = length(m_pClient->m_pControls->m_MousePos[g_Config.m_ClDummy]);
if(l > 0.0001f) // make sure that this isn't 0 if(l > 0.0001f) // make sure that this isn't 0
{ {
float DeadZone = g_Config.m_ClMouseDeadzone; float DeadZone = g_Config.m_ClMouseDeadzone;
float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f; float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f;
float OffsetAmount = max(l-DeadZone, 0.0f) * FollowFactor; float OffsetAmount = max(l-DeadZone, 0.0f) * FollowFactor;
CameraOffset = normalize(m_pClient->m_pControls->m_MousePos)*OffsetAmount; CameraOffset = normalize(m_pClient->m_pControls->m_MousePos[g_Config.m_ClDummy])*OffsetAmount;
} }
if(m_pClient->m_Snap.m_SpecInfo.m_Active) if(m_pClient->m_Snap.m_SpecInfo.m_Active)

View file

@ -25,17 +25,17 @@ CControls::CControls()
void CControls::OnReset() void CControls::OnReset()
{ {
m_LastData.m_Direction = 0; m_LastData[g_Config.m_ClDummy].m_Direction = 0;
//m_LastData.m_Hook = 0; //m_LastData.m_Hook = 0;
// simulate releasing the fire button // simulate releasing the fire button
if((m_LastData.m_Fire&1) != 0) if((m_LastData[g_Config.m_ClDummy].m_Fire&1) != 0)
m_LastData.m_Fire++; m_LastData[g_Config.m_ClDummy].m_Fire++;
m_LastData.m_Fire &= INPUT_STATE_MASK; m_LastData[g_Config.m_ClDummy].m_Fire &= INPUT_STATE_MASK;
m_LastData.m_Jump = 0; m_LastData[g_Config.m_ClDummy].m_Jump = 0;
m_InputData = m_LastData; m_InputData[g_Config.m_ClDummy] = m_LastData[g_Config.m_ClDummy];
m_InputDirectionLeft = 0; m_InputDirectionLeft[g_Config.m_ClDummy] = 0;
m_InputDirectionRight = 0; m_InputDirectionRight[g_Config.m_ClDummy] = 0;
} }
void CControls::OnRelease() void CControls::OnRelease()
@ -45,17 +45,34 @@ void CControls::OnRelease()
void CControls::OnPlayerDeath() void CControls::OnPlayerDeath()
{ {
m_LastData.m_WantedWeapon = m_InputData.m_WantedWeapon = 0; m_LastData[g_Config.m_ClDummy].m_WantedWeapon = m_InputData[g_Config.m_ClDummy].m_WantedWeapon = 0;
} }
struct CInputState
{
CControls *m_pControls;
int *m_pVariable1;
int *m_pVariable2;
};
static void ConKeyInputState(IConsole::IResult *pResult, void *pUserData) static void ConKeyInputState(IConsole::IResult *pResult, void *pUserData)
{ {
((int *)pUserData)[0] = pResult->GetInteger(0); CInputState *pState = (CInputState *)pUserData;
if (g_Config.m_ClDummy)
*pState->m_pVariable2 = pResult->GetInteger(0);
else
*pState->m_pVariable1 = pResult->GetInteger(0);
} }
static void ConKeyInputCounter(IConsole::IResult *pResult, void *pUserData) static void ConKeyInputCounter(IConsole::IResult *pResult, void *pUserData)
{ {
int *v = (int *)pUserData; CInputState *pState = (CInputState *)pUserData;
int *v;
if (g_Config.m_ClDummy)
v = pState->m_pVariable2;
else
v = pState->m_pVariable1;
if(((*v)&1) != pResult->GetInteger(0)) if(((*v)&1) != pResult->GetInteger(0))
(*v)++; (*v)++;
*v &= INPUT_STATE_MASK; *v &= INPUT_STATE_MASK;
@ -64,7 +81,8 @@ static void ConKeyInputCounter(IConsole::IResult *pResult, void *pUserData)
struct CInputSet struct CInputSet
{ {
CControls *m_pControls; CControls *m_pControls;
int *m_pVariable; int *m_pVariable1;
int *m_pVariable2;
int m_Value; int m_Value;
}; };
@ -72,34 +90,39 @@ static void ConKeyInputSet(IConsole::IResult *pResult, void *pUserData)
{ {
CInputSet *pSet = (CInputSet *)pUserData; CInputSet *pSet = (CInputSet *)pUserData;
if(pResult->GetInteger(0)) if(pResult->GetInteger(0))
*pSet->m_pVariable = pSet->m_Value; {
if (g_Config.m_ClDummy)
*pSet->m_pVariable2 = pSet->m_Value;
else
*pSet->m_pVariable1 = pSet->m_Value;
}
} }
static void ConKeyInputNextPrevWeapon(IConsole::IResult *pResult, void *pUserData) static void ConKeyInputNextPrevWeapon(IConsole::IResult *pResult, void *pUserData)
{ {
CInputSet *pSet = (CInputSet *)pUserData; CInputSet *pSet = (CInputSet *)pUserData;
ConKeyInputCounter(pResult, pSet->m_pVariable); ConKeyInputCounter(pResult, pSet);
pSet->m_pControls->m_InputData.m_WantedWeapon = 0; pSet->m_pControls->m_InputData[g_Config.m_ClDummy].m_WantedWeapon = 0;
} }
void CControls::OnConsoleInit() void CControls::OnConsoleInit()
{ {
// game commands // game commands
Console()->Register("+left", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputDirectionLeft, "Move left"); { static CInputState s_State = {this, &m_InputDirectionLeft[0], &m_InputDirectionLeft[1]}; Console()->Register("+left", "", CFGFLAG_CLIENT, ConKeyInputState, (void *)&s_State, "Move left"); }
Console()->Register("+right", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputDirectionRight, "Move right"); { static CInputState s_State = {this, &m_InputDirectionRight[0], &m_InputDirectionRight[1]}; Console()->Register("+right", "", CFGFLAG_CLIENT, ConKeyInputState, (void *)&s_State, "Move right"); }
Console()->Register("+jump", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputData.m_Jump, "Jump"); { static CInputState s_State = {this, &m_InputData[0].m_Jump, &m_InputData[1].m_Jump}; Console()->Register("+jump", "", CFGFLAG_CLIENT, ConKeyInputState, (void *)&s_State, "Jump"); }
Console()->Register("+hook", "", CFGFLAG_CLIENT, ConKeyInputState, &m_InputData.m_Hook, "Hook"); { static CInputState s_State = {this, &m_InputData[0].m_Hook, &m_InputData[1].m_Hook}; Console()->Register("+hook", "", CFGFLAG_CLIENT, ConKeyInputState, (void *)&s_State, "Hook"); }
Console()->Register("+fire", "", CFGFLAG_CLIENT, ConKeyInputCounter, &m_InputData.m_Fire, "Fire"); { static CInputState s_State = {this, &m_InputData[0].m_Fire, &m_InputData[1].m_Fire}; Console()->Register("+fire", "", CFGFLAG_CLIENT, ConKeyInputCounter, (void *)&s_State, "Fire"); }
Console()->Register("+showhookcoll", "", CFGFLAG_CLIENT, ConKeyInputState, &m_ShowHookColl, "Show Hook Collision"); { static CInputState s_State = {this, &m_ShowHookColl[0], &m_ShowHookColl[1]}; Console()->Register("+showhookcoll", "", CFGFLAG_CLIENT, ConKeyInputState, (void *)&s_State, "Show Hook Collision"); }
{ static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 1}; Console()->Register("+weapon1", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to hammer"); } { static CInputSet s_Set = {this, &m_InputData[0].m_WantedWeapon, &m_InputData[0].m_WantedWeapon, 1}; Console()->Register("+weapon1", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to hammer"); }
{ static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 2}; Console()->Register("+weapon2", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to gun"); } { static CInputSet s_Set = {this, &m_InputData[0].m_WantedWeapon, &m_InputData[0].m_WantedWeapon, 2}; Console()->Register("+weapon2", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to gun"); }
{ static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 3}; Console()->Register("+weapon3", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to shotgun"); } { static CInputSet s_Set = {this, &m_InputData[0].m_WantedWeapon, &m_InputData[0].m_WantedWeapon, 3}; Console()->Register("+weapon3", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to shotgun"); }
{ static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 4}; Console()->Register("+weapon4", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to grenade"); } { static CInputSet s_Set = {this, &m_InputData[0].m_WantedWeapon, &m_InputData[0].m_WantedWeapon, 4}; Console()->Register("+weapon4", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to grenade"); }
{ static CInputSet s_Set = {this, &m_InputData.m_WantedWeapon, 5}; Console()->Register("+weapon5", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to rifle"); } { static CInputSet s_Set = {this, &m_InputData[0].m_WantedWeapon, &m_InputData[0].m_WantedWeapon, 5}; Console()->Register("+weapon5", "", CFGFLAG_CLIENT, ConKeyInputSet, (void *)&s_Set, "Switch to rifle"); }
{ static CInputSet s_Set = {this, &m_InputData.m_NextWeapon, 0}; Console()->Register("+nextweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to next weapon"); } { static CInputSet s_Set = {this, &m_InputData[0].m_NextWeapon, &m_InputData[0].m_NextWeapon, 0}; Console()->Register("+nextweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to next weapon"); }
{ static CInputSet s_Set = {this, &m_InputData.m_PrevWeapon, 0}; Console()->Register("+prevweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to previous weapon"); } { static CInputSet s_Set = {this, &m_InputData[0].m_PrevWeapon, &m_InputData[0].m_PrevWeapon, 0}; Console()->Register("+prevweapon", "", CFGFLAG_CLIENT, ConKeyInputNextPrevWeapon, (void *)&s_Set, "Switch to previous weapon"); }
} }
void CControls::OnMessage(int Msg, void *pRawMsg) void CControls::OnMessage(int Msg, void *pRawMsg)
@ -108,7 +131,7 @@ void CControls::OnMessage(int Msg, void *pRawMsg)
{ {
CNetMsg_Sv_WeaponPickup *pMsg = (CNetMsg_Sv_WeaponPickup *)pRawMsg; CNetMsg_Sv_WeaponPickup *pMsg = (CNetMsg_Sv_WeaponPickup *)pRawMsg;
if(g_Config.m_ClAutoswitchWeapons) if(g_Config.m_ClAutoswitchWeapons)
m_InputData.m_WantedWeapon = pMsg->m_Weapon+1; m_InputData[g_Config.m_ClDummy].m_WantedWeapon = pMsg->m_Weapon+1;
} }
} }
@ -119,29 +142,29 @@ int CControls::SnapInput(int *pData)
// update player state // update player state
if(m_pClient->m_pChat->IsActive()) if(m_pClient->m_pChat->IsActive())
m_InputData.m_PlayerFlags = PLAYERFLAG_CHATTING; m_InputData[g_Config.m_ClDummy].m_PlayerFlags = PLAYERFLAG_CHATTING;
else if(m_pClient->m_pMenus->IsActive()) else if(m_pClient->m_pMenus->IsActive())
m_InputData.m_PlayerFlags = PLAYERFLAG_IN_MENU; m_InputData[g_Config.m_ClDummy].m_PlayerFlags = PLAYERFLAG_IN_MENU;
else else
m_InputData.m_PlayerFlags = PLAYERFLAG_PLAYING; m_InputData[g_Config.m_ClDummy].m_PlayerFlags = PLAYERFLAG_PLAYING;
if(m_pClient->m_pScoreboard->Active()) if(m_pClient->m_pScoreboard->Active())
m_InputData.m_PlayerFlags |= PLAYERFLAG_SCOREBOARD; m_InputData[g_Config.m_ClDummy].m_PlayerFlags |= PLAYERFLAG_SCOREBOARD;
if (m_pClient->m_pControls->m_ShowHookColl) if (m_pClient->m_pControls->m_ShowHookColl[g_Config.m_ClDummy])
m_InputData.m_PlayerFlags |= PLAYERFLAG_AIM; m_InputData[g_Config.m_ClDummy].m_PlayerFlags |= PLAYERFLAG_AIM;
if(m_LastData.m_PlayerFlags != m_InputData.m_PlayerFlags) if(m_LastData[g_Config.m_ClDummy].m_PlayerFlags != m_InputData[g_Config.m_ClDummy].m_PlayerFlags)
Send = true; Send = true;
m_LastData.m_PlayerFlags = m_InputData.m_PlayerFlags; m_LastData[g_Config.m_ClDummy].m_PlayerFlags = m_InputData[g_Config.m_ClDummy].m_PlayerFlags;
// we freeze the input if chat or menu is activated // we freeze the input if chat or menu is activated
if(!(m_InputData.m_PlayerFlags&PLAYERFLAG_PLAYING)) if(!(m_InputData[g_Config.m_ClDummy].m_PlayerFlags&PLAYERFLAG_PLAYING))
{ {
OnReset(); OnReset();
mem_copy(pData, &m_InputData, sizeof(m_InputData)); mem_copy(pData, &m_InputData[g_Config.m_ClDummy], sizeof(m_InputData[0]));
// send once a second just to be sure // send once a second just to be sure
if(time_get() > LastSendTime + time_freq()) if(time_get() > LastSendTime + time_freq())
@ -150,82 +173,74 @@ int CControls::SnapInput(int *pData)
else else
{ {
m_InputData.m_TargetX = (int)m_MousePos.x; m_InputData[g_Config.m_ClDummy].m_TargetX = (int)m_MousePos[g_Config.m_ClDummy].x;
m_InputData.m_TargetY = (int)m_MousePos.y; m_InputData[g_Config.m_ClDummy].m_TargetY = (int)m_MousePos[g_Config.m_ClDummy].y;
if(!m_InputData.m_TargetX && !m_InputData.m_TargetY) if(!m_InputData[g_Config.m_ClDummy].m_TargetX && !m_InputData[g_Config.m_ClDummy].m_TargetY)
{ {
m_InputData.m_TargetX = 1; m_InputData[g_Config.m_ClDummy].m_TargetX = 1;
m_MousePos.x = 1; m_MousePos[g_Config.m_ClDummy].x = 1;
} }
// set direction // set direction
m_InputData.m_Direction = 0; m_InputData[g_Config.m_ClDummy].m_Direction = 0;
if(m_InputDirectionLeft && !m_InputDirectionRight) if(m_InputDirectionLeft[g_Config.m_ClDummy] && !m_InputDirectionRight[g_Config.m_ClDummy])
m_InputData.m_Direction = -1; m_InputData[g_Config.m_ClDummy].m_Direction = -1;
if(!m_InputDirectionLeft && m_InputDirectionRight) if(!m_InputDirectionLeft[g_Config.m_ClDummy] && m_InputDirectionRight[g_Config.m_ClDummy])
m_InputData.m_Direction = 1; m_InputData[g_Config.m_ClDummy].m_Direction = 1;
// stress testing // stress testing
if(g_Config.m_DbgStress) if(g_Config.m_DbgStress)
{ {
float t = Client()->LocalTime(); float t = Client()->LocalTime();
mem_zero(&m_InputData, sizeof(m_InputData)); mem_zero(&m_InputData[g_Config.m_ClDummy], sizeof(m_InputData[0]));
m_InputData.m_Direction = ((int)t/2)&1; m_InputData[g_Config.m_ClDummy].m_Direction = ((int)t/2)&1;
m_InputData.m_Jump = ((int)t); m_InputData[g_Config.m_ClDummy].m_Jump = ((int)t);
m_InputData.m_Fire = ((int)(t*10)); m_InputData[g_Config.m_ClDummy].m_Fire = ((int)(t*10));
m_InputData.m_Hook = ((int)(t*2))&1; m_InputData[g_Config.m_ClDummy].m_Hook = ((int)(t*2))&1;
m_InputData.m_WantedWeapon = ((int)t)%NUM_WEAPONS; m_InputData[g_Config.m_ClDummy].m_WantedWeapon = ((int)t)%NUM_WEAPONS;
m_InputData.m_TargetX = (int)(sinf(t*3)*100.0f); m_InputData[g_Config.m_ClDummy].m_TargetX = (int)(sinf(t*3)*100.0f);
m_InputData.m_TargetY = (int)(cosf(t*3)*100.0f); m_InputData[g_Config.m_ClDummy].m_TargetY = (int)(cosf(t*3)*100.0f);
}
if (g_Config.m_ClDummy != m_LastDummy)
{
int tmp = m_OtherFire;
m_OtherFire = m_InputData.m_Fire;
m_InputData.m_Fire = tmp;
m_LastDummy = g_Config.m_ClDummy;
} }
// check if we need to send input // check if we need to send input
if(m_InputData.m_Direction != m_LastData.m_Direction) Send = true; if(m_InputData[g_Config.m_ClDummy].m_Direction != m_LastData[g_Config.m_ClDummy].m_Direction) Send = true;
else if(m_InputData.m_Jump != m_LastData.m_Jump) Send = true; else if(m_InputData[g_Config.m_ClDummy].m_Jump != m_LastData[g_Config.m_ClDummy].m_Jump) Send = true;
else if(m_InputData.m_Fire != m_LastData.m_Fire) Send = true; else if(m_InputData[g_Config.m_ClDummy].m_Fire != m_LastData[g_Config.m_ClDummy].m_Fire) Send = true;
else if(m_InputData.m_Hook != m_LastData.m_Hook) Send = true; else if(m_InputData[g_Config.m_ClDummy].m_Hook != m_LastData[g_Config.m_ClDummy].m_Hook) Send = true;
else if(m_InputData.m_WantedWeapon != m_LastData.m_WantedWeapon) Send = true; else if(m_InputData[g_Config.m_ClDummy].m_WantedWeapon != m_LastData[g_Config.m_ClDummy].m_WantedWeapon) Send = true;
else if(m_InputData.m_NextWeapon != m_LastData.m_NextWeapon) Send = true; else if(m_InputData[g_Config.m_ClDummy].m_NextWeapon != m_LastData[g_Config.m_ClDummy].m_NextWeapon) Send = true;
else if(m_InputData.m_PrevWeapon != m_LastData.m_PrevWeapon) Send = true; else if(m_InputData[g_Config.m_ClDummy].m_PrevWeapon != m_LastData[g_Config.m_ClDummy].m_PrevWeapon) Send = true;
// send at at least 10hz // send at at least 10hz
if(time_get() > LastSendTime + time_freq()/25) if(time_get() > LastSendTime + time_freq()/25)
Send = true; Send = true;
if(m_pClient->m_Snap.m_pLocalCharacter && m_pClient->m_Snap.m_pLocalCharacter->m_Weapon == WEAPON_NINJA if(m_pClient->m_Snap.m_pLocalCharacter && m_pClient->m_Snap.m_pLocalCharacter->m_Weapon == WEAPON_NINJA
&& (m_InputData.m_Direction || m_InputData.m_Jump || m_InputData.m_Hook)) && (m_InputData[g_Config.m_ClDummy].m_Direction || m_InputData[g_Config.m_ClDummy].m_Jump || m_InputData[g_Config.m_ClDummy].m_Hook))
Send = true; Send = true;
} }
// copy and return size // copy and return size
m_LastData = m_InputData; m_LastData[g_Config.m_ClDummy] = m_InputData[g_Config.m_ClDummy];
if(!Send) if(!Send)
return 0; return 0;
LastSendTime = time_get(); LastSendTime = time_get();
mem_copy(pData, &m_InputData, sizeof(m_InputData)); mem_copy(pData, &m_InputData[g_Config.m_ClDummy], sizeof(m_InputData[0]));
return sizeof(m_InputData); return sizeof(m_InputData[0]);
} }
void CControls::OnRender() void CControls::OnRender()
{ {
// update target pos // update target pos
if(m_pClient->m_Snap.m_pGameInfoObj && !m_pClient->m_Snap.m_SpecInfo.m_Active) if(m_pClient->m_Snap.m_pGameInfoObj && !m_pClient->m_Snap.m_SpecInfo.m_Active)
m_TargetPos = m_pClient->m_LocalCharacterPos + m_MousePos; m_TargetPos[g_Config.m_ClDummy] = m_pClient->m_LocalCharacterPos + m_MousePos[g_Config.m_ClDummy];
else if(m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_Snap.m_SpecInfo.m_UsePosition) else if(m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_Snap.m_SpecInfo.m_UsePosition)
m_TargetPos = m_pClient->m_Snap.m_SpecInfo.m_Position + m_MousePos; m_TargetPos[g_Config.m_ClDummy] = m_pClient->m_Snap.m_SpecInfo.m_Position + m_MousePos[g_Config.m_ClDummy];
else else
m_TargetPos = m_MousePos; m_TargetPos[g_Config.m_ClDummy] = m_MousePos[g_Config.m_ClDummy];
} }
bool CControls::OnMouseMove(float x, float y) bool CControls::OnMouseMove(float x, float y)
@ -234,7 +249,7 @@ bool CControls::OnMouseMove(float x, float y)
(m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_pChat->IsActive())) (m_pClient->m_Snap.m_SpecInfo.m_Active && m_pClient->m_pChat->IsActive()))
return false; return false;
m_MousePos += vec2(x, y); // TODO: ugly m_MousePos[g_Config.m_ClDummy] += vec2(x, y); // TODO: ugly
ClampMousePos(); ClampMousePos();
return true; return true;
@ -244,8 +259,8 @@ void CControls::ClampMousePos()
{ {
if(m_pClient->m_Snap.m_SpecInfo.m_Active && !m_pClient->m_Snap.m_SpecInfo.m_UsePosition) if(m_pClient->m_Snap.m_SpecInfo.m_Active && !m_pClient->m_Snap.m_SpecInfo.m_UsePosition)
{ {
m_MousePos.x = clamp(m_MousePos.x, 200.0f, Collision()->GetWidth()*32-200.0f); m_MousePos[g_Config.m_ClDummy].x = clamp(m_MousePos[g_Config.m_ClDummy].x, 200.0f, Collision()->GetWidth()*32-200.0f);
m_MousePos.y = clamp(m_MousePos.y, 200.0f, Collision()->GetHeight()*32-200.0f); m_MousePos[g_Config.m_ClDummy].y = clamp(m_MousePos[g_Config.m_ClDummy].y, 200.0f, Collision()->GetHeight()*32-200.0f);
} }
else else
@ -254,7 +269,7 @@ void CControls::ClampMousePos()
float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f; float FollowFactor = g_Config.m_ClMouseFollowfactor/100.0f;
float MouseMax = min(CameraMaxDistance/FollowFactor + g_Config.m_ClMouseDeadzone, (float)g_Config.m_ClMouseMaxDistance); float MouseMax = min(CameraMaxDistance/FollowFactor + g_Config.m_ClMouseDeadzone, (float)g_Config.m_ClMouseMaxDistance);
if(length(m_MousePos) > MouseMax) if(length(m_MousePos[g_Config.m_ClDummy]) > MouseMax)
m_MousePos = normalize(m_MousePos)*MouseMax; m_MousePos[g_Config.m_ClDummy] = normalize(m_MousePos[g_Config.m_ClDummy])*MouseMax;
} }
} }

View file

@ -8,14 +8,14 @@
class CControls : public CComponent class CControls : public CComponent
{ {
public: public:
vec2 m_MousePos; vec2 m_MousePos[2];
vec2 m_TargetPos; vec2 m_TargetPos[2];
CNetObj_PlayerInput m_InputData; CNetObj_PlayerInput m_InputData[2];
CNetObj_PlayerInput m_LastData; CNetObj_PlayerInput m_LastData[2];
int m_InputDirectionLeft; int m_InputDirectionLeft[2];
int m_InputDirectionRight; int m_InputDirectionRight[2];
int m_ShowHookColl; int m_ShowHookColl[2];
int m_LastDummy; int m_LastDummy;
int m_OtherFire; int m_OtherFire;

View file

@ -400,7 +400,7 @@ void CHud::RenderCursor()
// render cursor // render cursor
RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[m_pClient->m_Snap.m_pLocalCharacter->m_Weapon%NUM_WEAPONS].m_pSpriteCursor); RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[m_pClient->m_Snap.m_pLocalCharacter->m_Weapon%NUM_WEAPONS].m_pSpriteCursor);
float CursorSize = 64; float CursorSize = 64;
RenderTools()->DrawSprite(m_pClient->m_pControls->m_TargetPos.x, m_pClient->m_pControls->m_TargetPos.y, CursorSize); RenderTools()->DrawSprite(m_pClient->m_pControls->m_TargetPos[g_Config.m_ClDummy].x, m_pClient->m_pControls->m_TargetPos[g_Config.m_ClDummy].y, CursorSize);
Graphics()->QuadsEnd(); Graphics()->QuadsEnd();
} }

View file

@ -35,7 +35,7 @@ void CNamePlates::RenderNameplate(
{ {
float a = 1; float a = 1;
if(g_Config.m_ClNameplatesAlways == 0) if(g_Config.m_ClNameplatesAlways == 0)
a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos, Position)/200.0f,16.0f), 0.0f, 1.0f); a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos[g_Config.m_ClDummy], Position)/200.0f,16.0f), 0.0f, 1.0f);
const char *pName = m_pClient->m_aClients[pPlayerInfo->m_ClientID].m_aName; const char *pName = m_pClient->m_aClients[pPlayerInfo->m_ClientID].m_aName;
float tw = TextRender()->TextWidth(0, FontSize, pName, -1); float tw = TextRender()->TextWidth(0, FontSize, pName, -1);

View file

@ -410,7 +410,7 @@ void CPlayers::RenderPlayer(
if(pInfo.m_Local && Client()->State() != IClient::STATE_DEMOPLAYBACK) if(pInfo.m_Local && Client()->State() != IClient::STATE_DEMOPLAYBACK)
{ {
// just use the direct input if it's local player we are rendering // just use the direct input if it's local player we are rendering
Angle = GetAngle(m_pClient->m_pControls->m_MousePos); Angle = GetAngle(m_pClient->m_pControls->m_MousePos[g_Config.m_ClDummy]);
} }
else else
{ {
@ -544,7 +544,7 @@ void CPlayers::RenderPlayer(
vec2 ExDirection = Direction; vec2 ExDirection = Direction;
if (pPlayerInfo->m_Local && Client()->State() != IClient::STATE_DEMOPLAYBACK) if (pPlayerInfo->m_Local && Client()->State() != IClient::STATE_DEMOPLAYBACK)
ExDirection = normalize(vec2(m_pClient->m_pControls->m_InputData.m_TargetX, m_pClient->m_pControls->m_InputData.m_TargetY)); ExDirection = normalize(vec2(m_pClient->m_pControls->m_InputData[g_Config.m_ClDummy].m_TargetX, m_pClient->m_pControls->m_InputData[g_Config.m_ClDummy].m_TargetY));
Graphics()->TextureSet(-1); Graphics()->TextureSet(-1);
vec2 initPos = Position; vec2 initPos = Position;
@ -878,7 +878,7 @@ void CPlayers::RenderPlayer(
{ {
float a = 1; float a = 1;
if(g_Config.m_ClNameplatesAlways == 0) if(g_Config.m_ClNameplatesAlways == 0)
a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos, Position)/200.0f,16.0f), 0.0f, 1.0f); a = clamp(1-powf(distance(m_pClient->m_pControls->m_TargetPos[g_Config.m_ClDummy], Position)/200.0f,16.0f), 0.0f, 1.0f);
const char *pName = m_pClient->m_aClients[pPlayerInfo->m_ClientID].m_aName; const char *pName = m_pClient->m_aClients[pPlayerInfo->m_ClientID].m_aName;
float tw = TextRender()->TextWidth(0, FontSize, pName, -1); float tw = TextRender()->TextWidth(0, FontSize, pName, -1);