void CGhost::CheckStart() { int RaceTick = -m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer; int RenderTick = m_NewRenderTick; if(m_LastRaceTick != RaceTick && Client()->GameTick() - RaceTick < Client()->GameTickSpeed()) { if(m_Rendering && m_RenderingStartedByServer) // race restarted: stop rendering StopRender(); if(m_Recording && m_LastRaceTick != -1) // race restarted: activate restarting for local start detection so we have a smooth transition m_AllowRestart = true; if(m_LastRaceTick == -1) // no restart: reset rendering preparations m_NewRenderTick = -1; if(GhostRecorder()->IsRecording()) // race restarted: stop recording GhostRecorder()->Stop(0, -1); int StartTick = RaceTick; CServerInfo ServerInfo; Client()->GetServerInfo(&ServerInfo); if(IsDDRace(&ServerInfo)) // the client recognizes the start one tick earlier than ddrace servers StartTick--; StartRecord(StartTick); RenderTick = StartTick; } TryRenderStart(RenderTick, true); }
int CMapImages::GetEntities() { CServerInfo Info; Client()->GetServerInfo(&Info); if(m_EntitiesTextures == -1 || str_comp(m_aEntitiesGameType, Info.m_aGameType)) { // DDNet default to prevent delay in seeing entities char file[64] = "ddnet"; if(IsDDNet(&Info)) str_copy(file, "ddnet", sizeof(file)); else if(IsDDRace(&Info)) str_copy(file, "ddrace", sizeof(file)); else if(IsRace(&Info)) str_copy(file, "race", sizeof(file)); else if(IsFNG(&Info)) str_copy(file, "fng", sizeof(file)); else if(IsVanilla(&Info)) str_copy(file, "vanilla", sizeof(file)); char path[64]; str_format(path, sizeof(path), "editor/entities_clear/%s.png", file); if(m_EntitiesTextures >= 0) Graphics()->UnloadTexture(m_EntitiesTextures); m_EntitiesTextures = Graphics()->LoadTexture(path, IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0); str_copy(m_aEntitiesGameType, Info.m_aGameType, sizeof(m_aEntitiesGameType)); } return m_EntitiesTextures; }
static void ConKeyInputState(IConsole::IResult *pResult, void *pUserData) { CInputState *pState = (CInputState *)pUserData; CServerInfo Info; pState->m_pControls->GameClient()->Client()->GetServerInfo(&Info); if ((IsRace(&Info) || IsDDRace(&Info)) && pState->m_pControls->GameClient()->m_Snap.m_SpecInfo.m_Active) return; 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) { CInputState *pState = (CInputState *)pUserData; CServerInfo Info; pState->m_pControls->GameClient()->Client()->GetServerInfo(&Info); if ((IsRace(&Info) || IsDDRace(&Info)) && pState->m_pControls->GameClient()->m_Snap.m_SpecInfo.m_Active) return; int *v; if (g_Config.m_ClDummy) v = pState->m_pVariable2; else v = pState->m_pVariable1; if(((*v)&1) != pResult->GetInteger(0)) (*v)++; *v &= INPUT_STATE_MASK; }
void CControls::OnRender() { enum { JOYSTICK_RUN_DISTANCE = 65536 / 8, GAMEPAD_DEAD_ZONE = 65536 / 8, }; int64 CurTime = time_get(); bool FireWasPressed = false; if( m_Joystick ) { // Get input from left joystick int RunX = SDL_JoystickGetAxis(m_Joystick, LEFT_JOYSTICK_X); int RunY = SDL_JoystickGetAxis(m_Joystick, LEFT_JOYSTICK_Y); bool RunPressed = (RunX != 0 || RunY != 0); // Get input from right joystick int AimX = SDL_JoystickGetAxis(m_Joystick, SECOND_RIGHT_JOYSTICK_X); int AimY = SDL_JoystickGetAxis(m_Joystick, SECOND_RIGHT_JOYSTICK_Y); bool AimPressed = (AimX != 0 || AimY != 0); // Get input from another right joystick int HookX = SDL_JoystickGetAxis(m_Joystick, RIGHT_JOYSTICK_X); int HookY = SDL_JoystickGetAxis(m_Joystick, RIGHT_JOYSTICK_Y); bool HookPressed = (HookX != 0 || HookY != 0); if( m_JoystickRunPressed != RunPressed ) { if( RunPressed ) { if( m_JoystickTapTime + time_freq() > CurTime ) // Tap in less than 1 second to jump m_InputData[g_Config.m_ClDummy].m_Jump = 1; } else m_InputData[g_Config.m_ClDummy].m_Jump = 0; m_JoystickTapTime = CurTime; } m_JoystickRunPressed = RunPressed; if( RunPressed ) { m_InputDirectionLeft[g_Config.m_ClDummy] = (RunX < -JOYSTICK_RUN_DISTANCE); m_InputDirectionRight[g_Config.m_ClDummy] = (RunX > JOYSTICK_RUN_DISTANCE); } // Move 500ms in the same direction, to prevent speed bump when tapping if( !RunPressed && m_JoystickTapTime + time_freq() / 2 > CurTime ) { m_InputDirectionLeft[g_Config.m_ClDummy] = 0; m_InputDirectionRight[g_Config.m_ClDummy] = 0; } if( HookPressed ) { m_MousePos[g_Config.m_ClDummy] = vec2(HookX / 30, HookY / 30); ClampMousePos(); m_InputData[g_Config.m_ClDummy].m_Hook = 1; } else { m_InputData[g_Config.m_ClDummy].m_Hook = 0; } if( AimPressed ) { m_MousePos[g_Config.m_ClDummy] = vec2(AimX / 30, AimY / 30); ClampMousePos(); } if( AimPressed != m_JoystickFirePressed ) { // Fire when releasing joystick if( !AimPressed ) { m_InputData[g_Config.m_ClDummy].m_Fire ++; if( (bool)(m_InputData[g_Config.m_ClDummy].m_Fire % 2) != AimPressed ) m_InputData[g_Config.m_ClDummy].m_Fire ++; FireWasPressed = true; } } m_JoystickFirePressed = AimPressed; } if( m_Gamepad ) { // Get input from left joystick int RunX = SDL_JoystickGetAxis(m_Gamepad, LEFT_JOYSTICK_X); int RunY = SDL_JoystickGetAxis(m_Gamepad, LEFT_JOYSTICK_Y); if( m_UsingGamepad ) { m_InputDirectionLeft[g_Config.m_ClDummy] = (RunX < -GAMEPAD_DEAD_ZONE); m_InputDirectionRight[g_Config.m_ClDummy] = (RunX > GAMEPAD_DEAD_ZONE); } // Get input from right joystick int AimX = SDL_JoystickGetAxis(m_Gamepad, RIGHT_JOYSTICK_X); int AimY = SDL_JoystickGetAxis(m_Gamepad, RIGHT_JOYSTICK_Y); if( abs(AimX) > GAMEPAD_DEAD_ZONE || abs(AimY) > GAMEPAD_DEAD_ZONE ) { m_MousePos[g_Config.m_ClDummy] = vec2(AimX / 30, AimY / 30); ClampMousePos(); } if( !m_UsingGamepad && (abs(AimX) > GAMEPAD_DEAD_ZONE || abs(AimY) > GAMEPAD_DEAD_ZONE || abs(RunX) > GAMEPAD_DEAD_ZONE || abs(RunY) > GAMEPAD_DEAD_ZONE) ) { UI()->AndroidShowScreenKeys(false); m_UsingGamepad = true; } } CServerInfo Info; GameClient()->Client()->GetServerInfo(&Info); if( g_Config.m_ClAutoswitchWeaponsOutOfAmmo && !IsRace(&Info) && !IsDDRace(&Info) && m_pClient->m_Snap.m_pLocalCharacter ) { // Keep track of ammo count, we know weapon ammo only when we switch to that weapon, this is tracked on server and protocol does not track that m_AmmoCount[m_pClient->m_Snap.m_pLocalCharacter->m_Weapon%NUM_WEAPONS] = m_pClient->m_Snap.m_pLocalCharacter->m_AmmoCount; // Autoswitch weapon if we're out of ammo if( (m_InputData[g_Config.m_ClDummy].m_Fire % 2 != 0 || FireWasPressed) && m_pClient->m_Snap.m_pLocalCharacter->m_AmmoCount == 0 && m_pClient->m_Snap.m_pLocalCharacter->m_Weapon != WEAPON_HAMMER && m_pClient->m_Snap.m_pLocalCharacter->m_Weapon != WEAPON_NINJA ) { int w; for( w = WEAPON_RIFLE; w > WEAPON_GUN; w-- ) { if( w == m_pClient->m_Snap.m_pLocalCharacter->m_Weapon ) continue; if( m_AmmoCount[w] > 0 ) break; } if( w != m_pClient->m_Snap.m_pLocalCharacter->m_Weapon ) m_InputData[g_Config.m_ClDummy].m_WantedWeapon = w+1; } } // update target pos if(m_pClient->m_Snap.m_pGameInfoObj && !m_pClient->m_Snap.m_SpecInfo.m_Active) 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) m_TargetPos[g_Config.m_ClDummy] = m_pClient->m_Snap.m_SpecInfo.m_Position + m_MousePos[g_Config.m_ClDummy]; else m_TargetPos[g_Config.m_ClDummy] = m_MousePos[g_Config.m_ClDummy]; }
bool IsRace(const CServerInfo *pInfo) { return str_find_nocase(pInfo->m_aGameType, "race") || IsFastCap(pInfo) || IsDDRace(pInfo); }
void CEmoticon::OnRender() { if(!m_Active) { if(m_WasActive && m_SelectedEmote != -1) Emote(m_SelectedEmote); if(m_WasActive && m_SelectedEyeEmote != -1) EyeEmote(m_SelectedEyeEmote); m_WasActive = false; return; } if(m_pClient->m_Snap.m_SpecInfo.m_Active) { m_Active = false; m_WasActive = false; return; } m_WasActive = true; if (length(m_SelectorMouse) > 170.0f) m_SelectorMouse = normalize(m_SelectorMouse) * 170.0f; float SelectedAngle = GetAngle(m_SelectorMouse) + 2*pi/24; if (SelectedAngle < 0) SelectedAngle += 2*pi; m_SelectedEmote = -1; m_SelectedEyeEmote = -1; if (length(m_SelectorMouse) > 110.0f) m_SelectedEmote = (int)(SelectedAngle / (2*pi) * NUM_EMOTICONS); else if(length(m_SelectorMouse) > 40.0f) m_SelectedEyeEmote = (int)(SelectedAngle / (2*pi) * NUM_EMOTES); CUIRect Screen = *UI()->Screen(); Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h); Graphics()->BlendNormal(); Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.3f); DrawCircle(Screen.w/2, Screen.h/2, 190.0f, 64); Graphics()->QuadsEnd(); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id); Graphics()->QuadsBegin(); for (int i = 0; i < NUM_EMOTICONS; i++) { float Angle = 2*pi*i/NUM_EMOTICONS; if (Angle > pi) Angle -= 2*pi; bool Selected = m_SelectedEmote == i; float Size = Selected ? 80.0f : 50.0f; float NudgeX = 150.0f * cosf(Angle); float NudgeY = 150.0f * sinf(Angle); RenderTools()->SelectSprite(SPRITE_OOP + i); IGraphics::CQuadItem QuadItem(Screen.w/2 + NudgeX, Screen.h/2 + NudgeY, Size, Size); Graphics()->QuadsDraw(&QuadItem, 1); } Graphics()->QuadsEnd(); CServerInfo pServerInfo; Client()->GetServerInfo(&pServerInfo); if((IsDDRace(&pServerInfo) || IsDDNet(&pServerInfo) || IsPlus(&pServerInfo)) && g_Config.m_ClEyeWheel) { Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(1.0,1.0,1.0,0.3f); DrawCircle(Screen.w/2, Screen.h/2, 100.0f, 64); Graphics()->QuadsEnd(); CTeeRenderInfo *pTeeInfo = &m_pClient->m_aClients[m_pClient->m_LocalIDs[g_Config.m_ClDummy]].m_RenderInfo; Graphics()->TextureSet(pTeeInfo->m_Texture); for (int i = 0; i < NUM_EMOTES; i++) { float Angle = 2*pi*i/NUM_EMOTES; if (Angle > pi) Angle -= 2*pi; bool Selected = m_SelectedEyeEmote == i; float NudgeX = 70.0f * cosf(Angle); float NudgeY = 70.0f * sinf(Angle); pTeeInfo->m_Size = Selected ? 64.0f : 48.0f; RenderTools()->RenderTee(CAnimState::GetIdle(), pTeeInfo, i, vec2(-1,0), vec2(Screen.w/2 + NudgeX, Screen.h/2 + NudgeY)); pTeeInfo->m_Size = 64.0f; } Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.3f); DrawCircle(Screen.w/2, Screen.h/2, 30.0f, 64); Graphics()->QuadsEnd(); } else m_SelectedEyeEmote = -1; Graphics()->TextureSet(g_pData->m_aImages[IMAGE_CURSOR].m_Id); Graphics()->QuadsBegin(); Graphics()->SetColor(1,1,1,1); IGraphics::CQuadItem QuadItem(m_SelectorMouse.x+Screen.w/2,m_SelectorMouse.y+Screen.h/2,24,24); Graphics()->QuadsDrawTL(&QuadItem, 1); Graphics()->QuadsEnd(); }