CPlanet* CSPCharacter::GetNearestPlanet(findplanet_t eFindPlanet) { if (GameServer()->GetGameTime() > m_flNextPlanetCheck) { CPlanet* pNearestPlanet = FindNearestPlanet(); CScalableFloat flDistance = (pNearestPlanet->GetGlobalOrigin() - GetGlobalOrigin()).Length() - pNearestPlanet->GetRadius(); if (flDistance < pNearestPlanet->GetAtmosphereThickness()) m_hNearestPlanet = pNearestPlanet; else m_hNearestPlanet = NULL; m_flNextPlanetCheck = GameServer()->GetGameTime() + 0.3f; } if (eFindPlanet != FINDPLANET_INATMOSPHERE) { if (m_hNearestPlanet != NULL) return m_hNearestPlanet; CPlanet* pNearestPlanet = FindNearestPlanet(); if (eFindPlanet == FINDPLANET_ANY) return pNearestPlanet; CScalableFloat flDistance = (pNearestPlanet->GetGlobalOrigin() - GetGlobalOrigin()).Length() - pNearestPlanet->GetRadius(); if (eFindPlanet == FINDPLANET_CLOSEORBIT && flDistance > pNearestPlanet->GetCloseOrbit()) return NULL; else return pNearestPlanet; } return m_hNearestPlanet; }
void CCharacter::FindGroundEntity() { TVector vecVelocity = GetGlobalVelocity(); if (vecVelocity.Dot(GetUpVector()) > JumpStrength()/2.0f) { SetGroundEntity(NULL); SetSimulated(true); return; } TVector vecUp = GetUpVector() * m_flMaxStepSize; size_t iMaxEntities = GameServer()->GetMaxEntities(); for (size_t j = 0; j < iMaxEntities; j++) { CBaseEntity* pEntity = CBaseEntity::GetEntity(j); if (!pEntity) continue; if (pEntity->IsDeleted()) continue; if (!pEntity->ShouldCollide()) continue; if (pEntity == this) continue; TVector vecPoint, vecNormal; if (GetMoveParent() == pEntity) { TMatrix mGlobalToLocal = GetMoveParent()->GetGlobalToLocalTransform(); Vector vecUpLocal = mGlobalToLocal.TransformNoTranslate(GetUpVector()) * m_flMaxStepSize; if (pEntity->CollideLocal(GetLocalOrigin(), GetLocalOrigin() - vecUpLocal, vecPoint, vecNormal)) { SetGroundEntity(pEntity); SetSimulated(false); return; } } else { if (pEntity->Collide(GetGlobalOrigin(), GetGlobalOrigin() - vecUp, vecPoint, vecNormal)) { SetGroundEntity(pEntity); SetSimulated(false); return; } } } SetGroundEntity(NULL); SetSimulated(true); }
void CCharacter::ShowPlayerVectors() const { TMatrix m = GetGlobalTransform(); Vector vecUp = GetUpVector(); Vector vecRight = m.GetForwardVector().Cross(vecUp).Normalized(); Vector vecForward = vecUp.Cross(vecRight).Normalized(); m.SetColumn(0, vecForward); m.SetColumn(1, vecUp); m.SetColumn(2, vecRight); CCharacter* pLocalCharacter = Game()->GetLocalPlayer()->GetCharacter(); TVector vecEyeHeight = GetUpVector() * EyeHeight(); CRenderingContext c(GameServer()->GetRenderer()); c.Translate((GetGlobalOrigin() - pLocalCharacter->GetGlobalOrigin())); c.SetColor(Color(255, 255, 255)); c.BeginRenderDebugLines(); c.Vertex(Vector(0,0,0)); c.Vertex((float)EyeHeight() * vecUp); c.EndRender(); if (!GetGlobalVelocity().IsZero()) { c.BeginRenderDebugLines(); c.Vertex(vecEyeHeight); c.Vertex(vecEyeHeight + GetGlobalVelocity()); c.EndRender(); } c.SetColor(Color(255, 0, 0)); c.BeginRenderDebugLines(); c.Vertex(vecEyeHeight); c.Vertex(vecEyeHeight + vecForward); c.EndRender(); c.SetColor(Color(0, 255, 0)); c.BeginRenderDebugLines(); c.Vertex(vecEyeHeight); c.Vertex(vecEyeHeight + vecRight); c.EndRender(); c.SetColor(Color(0, 0, 255)); c.BeginRenderDebugLines(); c.Vertex(vecEyeHeight); c.Vertex(vecEyeHeight + vecUp); c.EndRender(); TVector vecPoint, vecNormal; if (Game()->TraceLine(GetGlobalOrigin(), GetGlobalOrigin() - GetUpVector()*100, vecPoint, vecNormal, NULL)) { c.Translate(vecPoint - GetGlobalOrigin()); c.Scale(0.1f, 0.1f, 0.1f); c.SetColor(Color(255, 255, 255)); c.RenderSphere(); } }
void CLaser::ClientSpawn() { BaseClass::ClientSpawn(); if (DigitanksGame()->GetCurrentLocalDigitanksPlayer()->GetVisibilityAtPoint(GetGlobalOrigin()) < 0.1f) { if (DigitanksGame()->GetCurrentLocalDigitanksPlayer()->GetVisibilityAtPoint(GetGlobalOrigin() + AngleVector(GetGlobalAngles())*LaserLength()) < 0.1f) m_bShouldRender = false; } }
void CSupplier::OnTeamChange() { if (!GetPlayerOwner()) { for (size_t i = 0; i < m_ahChildren.size(); i++) { if (!m_ahChildren[i]) continue; m_ahChildren[i]->SetSupplier(NULL); CStructure* pStructure = dynamic_cast<CStructure*>(m_ahChildren[i].GetPointer()); if (!pStructure) continue; if (pStructure->GetPlayerOwner()) { pStructure->GetPlayerOwner()->RemoveUnit(pStructure); DigitanksGame()->OnDisabled(pStructure, NULL, NULL); } } } BaseClass::OnTeamChange(); UpdateTendrils(); // This happens in UpdateTendrils() but do it again here anyway because UpdateTendrils only does it if there's a new tendril created. DigitanksGame()->GetTerrain()->DirtyChunkTexturesWithinDistance(GetGlobalOrigin(), GetDataFlowRadius() + GetBoundingRadius()); }
void CMenuMarcher::Think() { BaseClass::Think(); Speak(); Vector vecNewOrigin = GetGlobalOrigin() + Vector(0, 5, 0) * (float)GameServer()->GetFrameTime(); if (vecNewOrigin.y > 80) vecNewOrigin.y -= 160; vecNewOrigin.z = vecNewOrigin.z + GetGlobalVelocity().z * (float)GameServer()->GetFrameTime(); float flNewHoverHeight = FindHoverHeight(vecNewOrigin) + 2; if (vecNewOrigin.z > flNewHoverHeight) { SetGlobalVelocity(Vector(0, 0, GetGlobalVelocity().z - 5 * (float)GameServer()->GetFrameTime())); } else { vecNewOrigin.z = flNewHoverHeight; SetGlobalVelocity(Vector(0, 0, Approach(0, GetGlobalVelocity().z, 1 * (float)GameServer()->GetFrameTime()))); } SetGlobalOrigin(vecNewOrigin); }
CPlanet* CSPCharacter::FindNearestPlanet() const { CPlanet* pNearestPlanet = NULL; CScalableFloat flNearestDistance; for (size_t i = 0; i < GameServer()->GetMaxEntities(); i++) { CPlanet* pPlanet = dynamic_cast<CPlanet*>(CBaseEntity::GetEntity(i)); if (!pPlanet) continue; CScalableFloat flDistance = (pPlanet->GetGlobalOrigin() - GetGlobalOrigin()).Length(); flDistance -= pPlanet->GetRadius(); if (pNearestPlanet == NULL) { pNearestPlanet = pPlanet; flNearestDistance = flDistance; continue; } if (flDistance > flNearestDistance) continue; pNearestPlanet = pPlanet; flNearestDistance = flDistance; } return pNearestPlanet; }
void CSPCharacter::Think() { BaseClass::Think(); CPlanet* pPlanet = GetNearestPlanet(); if (pPlanet && !HasMoveParent()) { m_flLastEnteredAtmosphere = GameServer()->GetGameTime(); m_flRollFromSpace = GetGlobalAngles().r; } SetMoveParent(pPlanet); if (pPlanet) { // Estimate this planet's mass given things we know about earth. Assume equal densities. double flEarthVolume = 1097509500000000000000.0; // cubic meters double flEarthMass = 5974200000000000000000000.0; // kilograms // 4/3 * pi * r^3 = volume of a sphere CScalableFloat flPlanetVolume = pPlanet->GetRadius()*pPlanet->GetRadius()*pPlanet->GetRadius()*(M_PI*4/3); double flPlanetMass = RemapVal(flPlanetVolume, CScalableFloat(), CScalableFloat(flEarthVolume, SCALE_METER), 0, flEarthMass); double flG = 0.0000000000667384; // Gravitational constant CScalableVector vecDistance = (pPlanet->GetGlobalOrigin() - GetGlobalOrigin()); CScalableFloat flDistance = vecDistance.Length(); CScalableFloat flGravity = CScalableFloat(flPlanetMass*flG, SCALE_METER)/(flDistance*flDistance); CScalableVector vecGravity = vecDistance * flGravity / flDistance; SetGlobalGravity(vecGravity); } }
float CDigitanksEntity::VisibleRange() const { // Don't use GetGlobalOrigin because CDigitank::GetGlobalOrigin() can be expensive and we really don't want what it does. if (TreesReduceVisibility() && DigitanksGame()->GetTerrain()->IsPointInTrees(GetGlobalOrigin())) return BaseVisibleRange()/2; return BaseVisibleRange(); }
TVector CSPCharacter::GetUpVector() const { CPlanet* pNearestPlanet = GetNearestPlanet(); if (pNearestPlanet) return (GetGlobalOrigin() - pNearestPlanet->GetGlobalOrigin()).Normalized(); return Vector(0, 1, 0); }
Vector CMenuMarcher::GetRenderOrigin() const { float flLerp = 0; float flOscillate = Oscillate((float)GameServer()->GetGameTime()+m_flBobOffset, 4); flLerp = Gain(flOscillate, 0.2f); return GetGlobalOrigin() + Vector(0, 0, 1 + flLerp*0.5f); }
void CDigitanksEntity::InterceptSupplyLines() { // Haha... no. if (dynamic_cast<CSupplyLine*>(this)) return; if (!GetPlayerOwner()) return; for (size_t i = 0; i < GameServer()->GetMaxEntities(); i++) { CBaseEntity* pEntity = CBaseEntity::GetEntity(i); if (!pEntity) continue; CSupplyLine* pSupplyLine = dynamic_cast<CSupplyLine*>(pEntity); if (!pSupplyLine) continue; if (pSupplyLine->GetPlayerOwner() == GetPlayerOwner()) continue; if (!pSupplyLine->GetPlayerOwner()) continue; if (!pSupplyLine->GetSupplier() || !pSupplyLine->GetEntity()) continue; Vector vecEntity = GetGlobalOrigin(); vecEntity.z = 0; Vector vecSupplier = pSupplyLine->GetSupplier()->GetGlobalOrigin(); vecSupplier.z = 0; Vector vecUnit = pSupplyLine->GetEntity()->GetGlobalOrigin(); vecUnit.z = 0; if (DistanceToLineSegment(vecEntity, vecSupplier, vecUnit) > GetBoundingRadius()+4) continue; bool bFound = false; for (size_t j = 0; j < m_ahSupplyLinesIntercepted.size(); j++) { if (pSupplyLine == m_ahSupplyLinesIntercepted[j]) { bFound = true; break; } } if (!bFound) { pSupplyLine->Intercept(0.2f); m_ahSupplyLinesIntercepted.push_back(pSupplyLine); } } }
void CCPU::StartTurn() { BaseClass::StartTurn(); if (m_bProducing) { m_iTurnsToProduceRogue -= (size_t)1; if (m_iTurnsToProduceRogue == (size_t)0) { if (GameNetwork()->IsHost()) { CDigitank* pTank = GameServer()->Create<CScout>("CScout"); pTank->SetGlobalOrigin(GetGlobalOrigin()); pTank->CalculateVisibility(); GetDigitanksPlayer()->AddUnit(pTank); for (size_t x = 0; x < UPDATE_GRID_SIZE; x++) { for (size_t y = 0; y < UPDATE_GRID_SIZE; y++) { if (GetDigitanksPlayer()->HasDownloadedUpdate(x, y)) pTank->DownloadComplete(x, y); } } // Face him toward the center. pTank->Move(pTank->GetGlobalOrigin() + -GetGlobalOrigin().Normalized()*15); pTank->Turn(VectorAngles(-GetGlobalOrigin().Normalized())); pTank->StartTurn(); } m_bProducing = false; GetDigitanksPlayer()->AppendTurnInfo("Production finished on Rogue"); GetDigitanksPlayer()->AddActionItem(this, ACTIONTYPE_UNITREADY); } else { GetDigitanksPlayer()->AppendTurnInfo(tsprintf(tstring("Producing Rogue (%d turns left)"), m_iTurnsToProduceRogue.Get())); } } }
void CDigitanksEntity::RenderVisibleArea() { if (VisibleRange() == 0) return; CGameRenderingContext c(GameServer()->GetRenderer(), true); c.Translate(GetGlobalOrigin()); c.Scale(VisibleRange(), VisibleRange(), VisibleRange()); c.RenderSphere(); }
size_t CStructure::GetTurnsToUpgrade() { size_t iTurns = 1; if (GetUpgradeType() == STRUCTURE_PSU) iTurns = 2; if (GetUpgradeType() == STRUCTURE_BUFFER) iTurns = 1; // Location location location! if (DigitanksGame()->GetTerrain()->IsPointInTrees(GetGlobalOrigin())) iTurns = (size_t)(iTurns*1.5f); else if (DigitanksGame()->GetTerrain()->IsPointOverWater(GetGlobalOrigin())) iTurns = (size_t)(iTurns*2.0f); else if (DigitanksGame()->GetTerrain()->IsPointOverLava(GetGlobalOrigin())) iTurns = (size_t)(iTurns*2.5f); return iTurns; }
float CDigitanksEntity::GetVisibility() { CDigitanksGame* pGame = DigitanksGame(); if (!pGame) return 0; if (!m_bVisibilityDirty) return m_flVisibility; float flOldVisibility = m_flVisibility; CDigitanksPlayer* pLocalPlayer = pGame->GetCurrentLocalDigitanksPlayer(); m_flVisibility = GetVisibility(pLocalPlayer); Vector vecOrigin = GetGlobalOrigin(); // Find the nearest entity in the local team. If he's close enough, reduce this unit's concealment. CDigitanksEntity* pOther = this; while (true) { pOther = CBaseEntity::FindClosest<CDigitanksEntity>(vecOrigin, pOther); if (!pOther) break; if (pOther->Distance(vecOrigin) > 20) break; if (pOther == this) continue; if (pOther->GetDigitanksPlayer() != pLocalPlayer) continue; m_flVisibility = 1 - ((1-m_flVisibility)/2); break; } bool bBecameVisible = (flOldVisibility < 0.25f && m_flVisibility >= 0.25f); bool bBecameFullyVisible = (flOldVisibility < 1.0f && m_flVisibility >= 1.0f); if (bBecameFullyVisible) CallOutput("OnBecomeFullyVisible"); if (bBecameVisible) CallOutput("OnBecomeVisible"); m_bVisibilityDirty = false; return m_flVisibility; }
void CMenuMarcher::Spawn() { BaseClass::Spawn(); SetModel("models/digitanks/digitank-body.toy"); m_iTurretModel = CModelLibrary::Get()->FindModel("models/digitanks/digitank-turret.toy"); m_hHoverParticles.SetSystem("tank-hover", GetGlobalOrigin()); m_hHoverParticles.FollowEntity(this); m_flBobOffset = RandomFloat(0, 10); m_flNextSpeech = RandomFloat(0, 10); m_hHoverParticles.SetActive(true); }
void CStructure::PostRender() const { BaseClass::PostRender(); if (GameServer()->GetRenderer()->IsRenderingTransparent() && (m_flConstructionStartTime > 0) && GetVisibility() > 0) { CGameRenderingContext c(GameServer()->GetRenderer(), true); c.Translate(GetGlobalOrigin()); c.Scale(m_flScaffoldingSize, m_flScaffoldingSize, m_flScaffoldingSize); c.SetBlend(BLEND_ADDITIVE); c.SetAlpha(GetVisibility() * 0.2f * RemapValClamped((float)(GameServer()->GetGameTime() - m_flConstructionStartTime), 0.0f, 3.0f, 0.0f, 1.0f)); c.SetDepthMask(false); c.SetBackCulling(false); c.RenderModel(m_iScaffolding); } }
void CSPCharacter::StandOnNearestPlanet() { CPlanet* pPlanet = GetNearestPlanet(FINDPLANET_ANY); if (!pPlanet) return; CScalableVector vecPlanetOrigin = pPlanet->GetGlobalOrigin(); CScalableVector vecCharacterOrigin = GetGlobalOrigin(); CScalableVector vecCharacterDirection = (vecCharacterOrigin - vecPlanetOrigin).Normalized(); SetMoveParent(pPlanet); TVector vecPoint, vecNormal; pPlanet->CollideLocal(vecCharacterDirection * (pPlanet->GetRadius()*2.0f), TVector(), vecPoint, vecNormal); SetLocalOrigin(vecPoint); }
CPlanet* CSPCharacter::GetNearestPlanet(findplanet_t eFindPlanet) const { if (eFindPlanet != FINDPLANET_INATMOSPHERE) { if (m_hNearestPlanet != NULL) return m_hNearestPlanet; CPlanet* pNearestPlanet = FindNearestPlanet(); if (eFindPlanet == FINDPLANET_ANY) return pNearestPlanet; CScalableFloat flDistance = (pNearestPlanet->GetGlobalOrigin() - GetGlobalOrigin()).Length() - pNearestPlanet->GetRadius(); if (eFindPlanet == FINDPLANET_CLOSEORBIT && flDistance > pNearestPlanet->GetCloseOrbit()) return NULL; else return pNearestPlanet; } return m_hNearestPlanet; }
void CDigitanksEntity::Spawn() { BaseClass::Spawn(); m_bTakeDamage = true; m_flTotalHealth = TotalHealth(); m_flHealth = m_flTotalHealth; m_flVisibility = 0; m_bVisibilityDirty = true; m_flNextDirtyArea = 0; m_flNextDirtyOrigin = 0; m_bImprisoned = false; m_bObjective = false; m_iCageModel = CModelLibrary::Get()->FindModel("models/cage.toy"); m_hCageParticles.SetSystem("cage-aura", GetGlobalOrigin()); m_hCageParticles.FollowEntity(this); }
void CDigitanksEntity::RenderAvailableArea(int iArea) { float flAvailableArea = AvailableArea(iArea); if (flAvailableArea == 0) return; float flScoutScale = 1.0f; // Scouts have very tall ones so we can see them underneath on the ground. if (GetUnitType() == UNIT_SCOUT) flScoutScale = 10; if (dynamic_cast<CStructure*>(this) && DigitanksGame()->GetControlMode() == MODE_AIM) flScoutScale = 10; CGameRenderingContext c(GameServer()->GetRenderer(), true); c.Translate(GetGlobalOrigin()); c.Scale(flAvailableArea, flAvailableArea*flScoutScale, flAvailableArea); c.RenderSphere(); }
void CSupplier::CalculateDataFlow() { if (IsConstructing()) return; if (m_hSupplier != NULL) { // Use the radius of a circle with the area of the given data flow // so the flow doesn't get huge when you're close to a source. m_flBonusDataFlow = sqrt(m_hSupplier->GetDataFlow(GetGlobalOrigin())/M_PI); } else m_flBonusDataFlow = 0; for (size_t i = 0; i < m_ahChildren.size(); i++) { CSupplier* pSupplier = dynamic_cast<CSupplier*>(m_ahChildren[i].GetPointer()); if (pSupplier) pSupplier->CalculateDataFlow(); } }
void CStructure::FindGround() { float flHeight = DigitanksGame()->GetTerrain()->GetHeight(GetGlobalOrigin().x, GetGlobalOrigin().y); float flCornerHeight; flCornerHeight = DigitanksGame()->GetTerrain()->GetHeight(GetGlobalOrigin().x + GetBoundingRadius(), GetGlobalOrigin().y + GetBoundingRadius()); if (flCornerHeight > flHeight) flHeight = flCornerHeight; flCornerHeight = DigitanksGame()->GetTerrain()->GetHeight(GetGlobalOrigin().x + GetBoundingRadius(), GetGlobalOrigin().y - GetBoundingRadius()); if (flCornerHeight > flHeight) flHeight = flCornerHeight; flCornerHeight = DigitanksGame()->GetTerrain()->GetHeight(GetGlobalOrigin().x - GetBoundingRadius(), GetGlobalOrigin().y + GetBoundingRadius()); if (flCornerHeight > flHeight) flHeight = flCornerHeight; flCornerHeight = DigitanksGame()->GetTerrain()->GetHeight(GetGlobalOrigin().x - GetBoundingRadius(), GetGlobalOrigin().y - GetBoundingRadius()); if (flCornerHeight > flHeight) flHeight = flCornerHeight; SetGlobalOrigin(Vector(GetGlobalOrigin().x, GetGlobalOrigin().y, flHeight + GetBoundingRadius()/2 + 2)); }
float CDigitanksEntity::GetVisibility(CDigitanksPlayer* pPlayer) const { CDigitanksGame* pGame = DigitanksGame(); CTerrain* pTerrain = pGame->GetTerrain(); float flConceal = 0.0f; if (GetsConcealmentBonus() && pTerrain) { if (pTerrain->GetBit(CTerrain::WorldToArraySpace(GetGlobalOrigin().x), CTerrain::WorldToArraySpace(GetGlobalOrigin().y), TB_TREE)) flConceal = 0.7f; } float flCloak = GetCloakConcealment(); if (flCloak > flConceal) flConceal = flCloak; if (HasLostConcealment()) flConceal = 0; if (pPlayer && pPlayer == GetDigitanksPlayer()) return 1 - flConceal/2; if (!pGame->ShouldRenderFogOfWar()) { if (pPlayer && pPlayer->IsHumanControlled()) return 1 - flConceal; } if (!pPlayer) return 0; float flVisibility = pPlayer->GetEntityVisibility(GetHandle()) - flConceal; if (flVisibility < 0) return 0; return flVisibility; }
void CMiniBuffer::UpgradeComplete() { if (!GameNetwork()->IsHost()) return; CBuffer* pBuffer = GameServer()->Create<CBuffer>("CBuffer"); pBuffer->SetConstructing(false); pBuffer->SetGlobalOrigin(GetGlobalOrigin()); GetPlayerOwner()->AddUnit(pBuffer); pBuffer->SetSupplier(GetSupplier()); GetSupplier()->AddChild(pBuffer); pBuffer->GiveDataStrength(pBuffer->InitialDataStrength() - InitialDataStrength()); // Give the difference pBuffer->GiveDataStrength(m_iDataStrength - InitialDataStrength()); // Give what I've earned so far pBuffer->AddFleetPoints(pBuffer->InitialFleetPoints() - InitialFleetPoints()); pBuffer->AddBandwidth(pBuffer->InitialBandwidth() - InitialBandwidth()); pBuffer->AddEnergyBonus(pBuffer->InitialEnergyBonus() - InitialEnergyBonus()); pBuffer->AddRechargeBonus(pBuffer->InitialRechargeBonus() - InitialRechargeBonus()); pBuffer->CalculateVisibility(); for (size_t x = 0; x < UPDATE_GRID_SIZE; x++) { for (size_t y = 0; y < UPDATE_GRID_SIZE; y++) { if (GetDigitanksPlayer()->HasDownloadedUpdate(x, y)) pBuffer->InstallUpdate(x, y); } } for (size_t i = 0; i < m_ahChildren.size(); i++) { m_ahChildren[i]->SetSupplier(pBuffer); pBuffer->AddChild(m_ahChildren[i]); } Delete(); GetDigitanksPlayer()->AddActionItem(pBuffer, ACTIONTYPE_UPGRADE); }
bool CStructure::IsAvailableAreaActive(int iArea) const { if (iArea != 0) return BaseClass::IsAvailableAreaActive(iArea); if (!GetDigitanksPlayer()) return false; if (!GetDigitanksPlayer()->GetPrimaryCPU()) return false; if (DigitanksGame()->GetCurrentLocalDigitanksPlayer() == GetDigitanksPlayer()) return false; if (DigitanksGame()->GetControlMode() != MODE_AIM) return false; CDigitank* pTank = DigitanksGame()->GetCurrentLocalDigitanksPlayer()->GetPrimarySelectionTank(); if (!pTank) return false; if (!pTank->IsInsideMaxRange(GetGlobalOrigin())) return false; if (GetVisibility(pTank->GetDigitanksPlayer()) < 0.1f) return false; if (pTank->FiringCone() < 360 && fabs(AngleDifference(pTank->GetGlobalAngles().y, VectorAngles((GetGlobalOrigin() - pTank->GetGlobalOrigin()).Normalized()).y)) > pTank->FiringCone()) return false; if (pTank->GetCurrentWeapon() == PROJECTILE_TREECUTTER) return false; return true; }
void CDigitanksEntity::Think() { BaseClass::Think(); if (m_flNextDirtyOrigin > 0 && GameServer()->GetGameTime() > m_flNextDirtyOrigin) { DirtyVisibility(); m_flNextDirtyOrigin = 0; } if (m_flNextDirtyArea > 0 && GameServer()->GetGameTime() > m_flNextDirtyArea) { CDigitanksEntity* pOther = this; while (true) { pOther = CBaseEntity::FindClosest<CDigitanksEntity>(GetGlobalOrigin(), pOther); if (!pOther) break; if (pOther == this) continue; if (pOther->Distance(GetGlobalOrigin()) > VisibleRange() + DigitanksGame()->FogPenetrationDistance()) break; pOther->DirtyVisibility(); } m_flNextDirtyArea = 0; } if (GameNetwork()->IsHost() && !IsAlive() && GameServer()->GetGameTime() > m_flTimeKilled + 1.0f) { GameServer()->Delete(this); if (DigitanksGame()->GetTerrain()->IsPointOverHole(GetGlobalOrigin())) { CWreckage* pWreckage = CreateWreckage(); if (pWreckage) { pWreckage->FellIntoHole(); if (DigitanksGame()->GetGameType() == GAMETYPE_ARTILLERY) pWreckage->SetScale(2); } } else if (DigitanksGame()->GetGameType() == GAMETYPE_ARTILLERY) { switch (RandomInt(0, 8)) { case 0: case 6: case 7: case 8: default: { for (size_t i = 0; i < 8; i++) { CDebris* pDebris = GameServer()->Create<CDebris>("CDebris"); pDebris->SetGlobalOrigin(GetGlobalOrigin()); } CWreckage* pWreckage = CreateWreckage(); pWreckage->SetScale(2); DigitanksGame()->GetOverheadCamera()->Shake(GetGlobalOrigin(), 3); break; } case 1: { CProjectile* pProjectile = GameServer()->Create<CLargeShell>("CLargeShell"); pProjectile->SetOwner(NULL); pProjectile->SetGlobalOrigin(GetGlobalOrigin()); pProjectile->Explode(); break; } case 2: { CProjectile* pProjectile = GameServer()->Create<CAOEShell>("CAOEShell"); pProjectile->SetOwner(NULL); pProjectile->SetGlobalOrigin(GetGlobalOrigin()); pProjectile->Explode(); break; } case 3: { CProjectile* pProjectile = GameServer()->Create<CClusterBomb>("CClusterBomb"); pProjectile->SetOwner(NULL); pProjectile->SetGlobalOrigin(GetGlobalOrigin()); pProjectile->Explode(); break; } case 4: { CProjectile* pProjectile = GameServer()->Create<CEarthshaker>("CEarthshaker"); pProjectile->SetOwner(NULL); pProjectile->SetGlobalOrigin(GetGlobalOrigin()); pProjectile->Explode(); break; } case 5: { CProjectile* pProjectile = GameServer()->Create<CTractorBomb>("CTractorBomb"); pProjectile->SetOwner(NULL); pProjectile->SetGlobalOrigin(GetGlobalOrigin()); pProjectile->Explode(); break; } } } else { // Strategy mode CreateWreckage(); } } m_hCageParticles.SetActive(IsImprisoned() && GetVisibility() > 0.1f); }
void CDigitanksEntity::OnRender(CGameRenderingContext* pContext) const { BaseClass::OnRender(pContext); if (GameServer()->GetRenderer()->IsRenderingTransparent() && IsImprisoned()) { CGameRenderingContext c(GameServer()->GetRenderer(), true); c.SetBackCulling(false); c.SetBlend(BLEND_ADDITIVE); c.Scale(GetBoundingRadius(), GetBoundingRadius(), GetBoundingRadius()); c.Rotate((float)GameServer()->GetGameTime() * 90, Vector(0, 0, 1)); float flVisibility = GetVisibility() * 0.6f; c.UseProgram("scroll"); c.SetUniform("iTexture", 0); c.SetUniform("flAlpha", flVisibility); c.SetUniform("flTime", (float)-GameServer()->GetGameTime()); c.SetUniform("flSpeed", 1.0f); c.RenderModel(m_iCageModel, this); } if (GameServer()->GetRenderer()->IsRenderingTransparent() && IsImprisoned()) { CGameRenderingContext c(GameServer()->GetRenderer(), true); c.SetBackCulling(false); c.SetBlend(BLEND_ADDITIVE); c.Scale(GetBoundingRadius()+1, GetBoundingRadius()+1, GetBoundingRadius()+1); c.Rotate(-(float)GameServer()->GetGameTime() * 90, Vector(0, 0, 1)); float flVisibility = GetVisibility() * 0.6f; c.UseProgram("scroll"); c.SetUniform("iTexture", 0); c.SetUniform("flAlpha", flVisibility); c.SetUniform("flTime", (float)-GameServer()->GetGameTime()); c.SetUniform("flSpeed", 1.0f); c.RenderModel(m_iCageModel); } if (!GameServer()->GetRenderer()->IsRenderingTransparent()) return; if (!DigitanksGame()->GetTerrain()->GetBit(CTerrain::WorldToArraySpace(GetGlobalOrigin().x), CTerrain::WorldToArraySpace(GetGlobalOrigin().y), TB_TREE)) return; if (GetVisibility() < 0.6f) return; CGameRenderingContext c(GameServer()->GetRenderer(), true); c.SetBlend(BLEND_NONE); c.SetAlpha(1); c.BindTexture(0); TStubbed("Tank outlines in trees"); /* // Draw outlines of objects in trees. glPushAttrib( GL_ALL_ATTRIB_BITS ); glDisable( GL_TEXTURE_2D ); glEnable( GL_POLYGON_OFFSET_FILL ); glPolygonOffset( -3.5f, -3.5f ); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(true); glEnable(GL_DEPTH_TEST); pContext->RenderModel(GetModel()); glDisable( GL_POLYGON_OFFSET_FILL ); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(false); glEnable(GL_DEPTH_TEST); glLineWidth( 2.0f ); glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); glColor3ubv( Color(0, 0, 0) ); pContext->RenderModel(GetModel()); glPopAttrib(); */ }
void CCharacter::MoveThink() { if (!GetGroundEntity()) return; if (m_vecGoalVelocity.LengthSqr()) m_vecGoalVelocity.Normalize(); m_vecMoveVelocity.x = Approach(m_vecGoalVelocity.x, m_vecMoveVelocity.x, GameServer()->GetFrameTime()*4); m_vecMoveVelocity.y = 0; m_vecMoveVelocity.z = Approach(m_vecGoalVelocity.z, m_vecMoveVelocity.z, GameServer()->GetFrameTime()*4); if (m_vecMoveVelocity.LengthSqr() > 0) { TMatrix m = GetLocalTransform(); Vector vecUp = GetUpVector(); if (HasMoveParent()) { TMatrix mGlobalToLocal = GetMoveParent()->GetGlobalToLocalTransform(); vecUp = mGlobalToLocal.TransformNoTranslate(vecUp); } Vector vecRight = m.GetForwardVector().Cross(vecUp).Normalized(); Vector vecForward = vecUp.Cross(vecRight).Normalized(); m.SetColumn(0, vecForward); m.SetColumn(1, vecUp); m.SetColumn(2, vecRight); TVector vecMove = m_vecMoveVelocity * CharacterSpeed(); TVector vecLocalVelocity = m.TransformNoTranslate(vecMove); SetLocalVelocity(vecLocalVelocity); } else SetLocalVelocity(TVector()); eastl::vector<CEntityHandle<CBaseEntity> > apCollisionList; size_t iMaxEntities = GameServer()->GetMaxEntities(); for (size_t j = 0; j < iMaxEntities; j++) { CBaseEntity* pEntity2 = CBaseEntity::GetEntity(j); if (!pEntity2) continue; if (pEntity2->IsDeleted()) continue; if (pEntity2 == this) continue; if (!pEntity2->ShouldCollide()) continue; apCollisionList.push_back(pEntity2); } TMatrix mGlobalToLocalRotation; if (HasMoveParent()) { mGlobalToLocalRotation = GetMoveParent()->GetGlobalToLocalTransform(); mGlobalToLocalRotation.SetTranslation(TVector()); } float flSimulationFrameTime = 0.01f; // Break simulations up into consistent small steps to preserve accuracy. for (; m_flMoveSimulationTime < GameServer()->GetGameTime(); m_flMoveSimulationTime += flSimulationFrameTime) { TVector vecVelocity = GetLocalVelocity(); TVector vecLocalOrigin = GetLocalOrigin(); TVector vecGlobalOrigin = GetGlobalOrigin(); vecVelocity = vecVelocity * flSimulationFrameTime; TVector vecLocalDestination = vecLocalOrigin + vecVelocity; TVector vecGlobalDestination = vecLocalDestination; if (GetMoveParent()) vecGlobalDestination = GetMoveParent()->GetGlobalTransform() * vecLocalDestination; TVector vecNewLocalOrigin = vecLocalDestination; size_t iTries = 0; while (true) { iTries++; TVector vecPoint, vecNormal; TVector vecLocalCollisionPoint, vecGlobalCollisionPoint; bool bContact = false; for (size_t i = 0; i < apCollisionList.size(); i++) { CBaseEntity* pEntity2 = apCollisionList[i]; if (GetMoveParent() == pEntity2) { if (pEntity2->CollideLocal(vecLocalOrigin, vecLocalDestination, vecPoint, vecNormal)) { bContact = true; Touching(pEntity2); vecLocalCollisionPoint = vecPoint; vecGlobalCollisionPoint = GetMoveParent()->GetGlobalTransform() * vecPoint; } } else { if (pEntity2->Collide(vecGlobalOrigin, vecGlobalDestination, vecPoint, vecNormal)) { bContact = true; Touching(pEntity2); vecGlobalCollisionPoint = vecPoint; if (GetMoveParent()) { vecLocalCollisionPoint = GetMoveParent()->GetGlobalToLocalTransform() * vecPoint; vecNormal = GetMoveParent()->GetGlobalToLocalTransform().TransformNoTranslate(vecNormal); } else vecLocalCollisionPoint = vecGlobalCollisionPoint; } } } if (bContact) { vecNewLocalOrigin = vecLocalCollisionPoint; vecVelocity -= vecLocalCollisionPoint - vecLocalOrigin; } if (!bContact) break; if (iTries > 4) break; vecLocalOrigin = vecLocalCollisionPoint; vecGlobalOrigin = vecGlobalCollisionPoint; // Clip the velocity to the surface normal of whatever we hit. TFloat flDistance = vecVelocity.Dot(vecNormal); vecVelocity = vecVelocity - vecNormal * flDistance; // Do it one more time just to make sure we're not headed towards the plane. TFloat flAdjust = vecVelocity.Dot(vecNormal); if (flAdjust < 0.0f) vecVelocity -= (vecNormal * flAdjust); vecLocalDestination = vecLocalOrigin + vecVelocity; if (GetMoveParent()) vecGlobalDestination = GetMoveParent()->GetGlobalTransform() * vecLocalDestination; else vecGlobalDestination = vecLocalDestination; SetLocalVelocity(vecVelocity.Normalized() * GetLocalVelocity().Length()); } SetLocalOrigin(vecNewLocalOrigin); // Try to keep the player on the ground. // Untested. /*TVector vecStart = GetGlobalOrigin() + GetGlobalTransform().GetUpVector()*m_flMaxStepSize; TVector vecEnd = GetGlobalOrigin() - GetGlobalTransform().GetUpVector()*m_flMaxStepSize; // First go up a bit TVector vecHit, vecNormal; Game()->TraceLine(GetGlobalOrigin(), vecStart, vecHit, vecNormal, NULL); vecStart = vecHit; // Now see if there's ground underneath us. bool bHit = Game()->TraceLine(vecStart, vecEnd, vecHit, vecNormal, NULL); if (bHit && vecNormal.y >= TFloat(0.7f)) SetGlobalOrigin(vecHit);*/ m_flMoveSimulationTime += flSimulationFrameTime; } }