#include "PrecompiledHeader.h" #include "TowerSystem.h" #include "World.h" void Systems::TowerSystem::RegisterComponents( ComponentFactory* cf ) { cf->Register([]() { return new Components::Tower(); }); cf->Register([]() { return new Components::Turret(); }); cf->Register([]() {return new Components::TurretShot(); }); cf->Register([]() {return new Components::TowerDebris(); }); } void Systems::TowerSystem::Initialize() { //EVENT_SUBSCRIBE_MEMBER(m_eDamage, &Systems::TowerSystem::Damage); EVENT_SUBSCRIBE_MEMBER(m_ECollision, &Systems::TowerSystem::OnCollision); EVENT_SUBSCRIBE_MEMBER(m_eDamage, &Systems::TowerSystem::Damage); Temp_m_TimeSinceLastShot = 0; } void Systems::TowerSystem::Update( double dt ) { } bool Systems::TowerSystem::Damage( const Events::Damage &event ) { auto debrisComponent = m_World->GetComponent(event.Entity); if(!debrisComponent) { return false; } LOG_INFO("TowerSystem::Damage"); // Change to damage model auto wallhealthcomponent = m_World->GetComponent(event.Entity); if(wallhealthcomponent->Amount > 0) { return false; } LOG_INFO("Entity %i is dead", event.Entity); auto entitytransform = m_World->GetComponent(event.Entity); if(!entitytransform) return false; //auto transformComponent = m_World->GetComponent(event.Entity); Components::Transform transformComponent = m_World->GetSystem()->AbsoluteTransform(event.Entity); // Spawn debris for(auto d : debrisComponent->TowerDebrisIDs) { auto debris = m_World->CloneEntity(d); auto transform = m_World->GetComponent(debris); Components::Transform absolutetransformComponent = m_World->GetSystem()->AbsoluteTransform(debris); transform->Orientation = transform->Orientation * transformComponent.Orientation; transform->Position = transform->Orientation * transform->Position + transformComponent.Position; //DO STUFF! :D float distance = glm::distance(transform->Position, transformComponent.Position); float radius = 15.f; float strength = (1.f - pow(distance / radius, 2)) * 2000.f; glm::vec3 direction = glm::normalize(transformComponent.Position - transform->Position); Events::ApplyPointImpulse e; e.Entity = debris; e.Impulse = direction * strength; e.Position = transformComponent.Position; EventBroker->Publish(e); } entitytransform->Position = glm::vec3(0.f, -50000000.f, 0.f); return true; } void Systems::TowerSystem::UpdateEntity( double dt, EntityID entity, EntityID parent ) { auto towerComponent = m_World->GetComponent(entity); if(!towerComponent) return; Components::Transform absoluteTowerGunTransform = m_World->GetSystem()->AbsoluteTransform(towerComponent->Gun); auto towerGunTransformComponent = m_World->GetComponent(towerComponent->Gun); if(!towerGunTransformComponent) return; auto towerGunBaseTransformComponent = m_World->GetComponent(towerComponent->GunBase); if(!towerGunBaseTransformComponent) return; auto turretComponent = m_World->GetComponent(entity); if(!turretComponent) return; auto players = m_World->GetComponentsOfType(); if (!players) return; for(auto player : *players) { auto playerComponent = std::dynamic_pointer_cast(player); if(towerComponent->ID == playerComponent->ID) //!= betyder att den bara targetar sitt eget lag, == fienden. continue; auto playerTransform = m_World->GetComponent(player->Entity); if(!playerTransform) continue; Components::Transform absolutePlayerTransform = m_World->GetSystem()->AbsoluteTransform(player->Entity); if(glm::distance(absolutePlayerTransform.Position, absoluteTowerGunTransform.Position) > 45.f) continue; //Rotate the turret towards the enemy player glm::quat baseLookAt = glm::inverse(glm::quat_cast(glm::lookAt(absoluteTowerGunTransform.Position, glm::vec3(absolutePlayerTransform.Position.x, absoluteTowerGunTransform.Position.y, absolutePlayerTransform.Position.z), glm::vec3(0, 1, 0)))); glm::quat gunLookAt = glm::inverse(glm::quat_cast(glm::lookAt(absoluteTowerGunTransform.Position, glm::vec3(absolutePlayerTransform.Position.x, absolutePlayerTransform.Position.y, absolutePlayerTransform.Position.z ), glm::vec3(0, 1, 0)))); towerGunTransformComponent->Orientation = glm::inverse(baseLookAt) * gunLookAt; towerGunBaseTransformComponent->Orientation = baseLookAt; #pragma region GetShotDirectionAndLaunchShot Temp_m_TimeSinceLastShot += dt; if(Temp_m_TimeSinceLastShot > 1) { { //Shoot code EntityID clone = m_World->CloneEntity(turretComponent->ShotTemplate); auto templateAbsoluteTransform = m_World->GetSystem()->AbsoluteTransform(turretComponent->ShotTemplate); auto cloneTransform = m_World->GetComponent(clone); cloneTransform->Orientation = templateAbsoluteTransform.Orientation; cloneTransform->Position = templateAbsoluteTransform.Position - (cloneTransform->Orientation* glm::vec3(0.97163f, 0.f, 0.f)); Events::SetVelocity eSetVelocity; eSetVelocity.Entity = clone; eSetVelocity.Velocity = gunLookAt * glm::vec3(0.f, 0.f, -1.f) * turretComponent->ShotSpeed; EventBroker->Publish(eSetVelocity); { Events::CreateExplosion e; e.LifeTime = 1.5; e.ParticleScale.push_back(0.6); e.ParticleScale.push_back(1.8); e.ParticlesToSpawn = 1; e.Position = cloneTransform->Position; e.RelativeUpOrientation = glm::angleAxis(glm::pi() / 2, glm::vec3(1,0,0)); e.Speed = 1.7; e.SpreadAngle = glm::pi()/100; e.spritePath = "Textures/Sprites/Smoke1.png"; e.Emitting = true; e.SpawnFrequency = 0.2; e.Color = glm::vec4(0.6,0.6,0.6,1); EventBroker->Publish(e); } { Events::CreateExplosion e; e.LifeTime = 0.2; e.ParticleScale.push_back(1); //e.ParticleScale.push_back(2); e.ParticlesToSpawn = 1; e.Position = cloneTransform->Position; e.Speed = 0; e.SpreadAngle = glm::pi(); e.spritePath = "Textures/Sprites/MuzzleFlash.png"; e.Color = glm::vec4(2, 2, 2, 0.2); EventBroker->Publish(e); } } { EntityID clone = m_World->CloneEntity(turretComponent->ShotTemplate); auto templateAbsoluteTransform = m_World->GetSystem()->AbsoluteTransform(turretComponent->ShotTemplate); auto cloneTransform = m_World->GetComponent(clone); cloneTransform->Orientation = templateAbsoluteTransform.Orientation; cloneTransform->Position = templateAbsoluteTransform.Position + (cloneTransform->Orientation * glm::vec3(0.97163f, 0.f, 0.f)); Events::SetVelocity eSetVelocity; eSetVelocity.Entity = clone; eSetVelocity.Velocity = gunLookAt * glm::vec3(0.f, 0.f, -1.f) * turretComponent->ShotSpeed; EventBroker->Publish(eSetVelocity); { Events::CreateExplosion e; e.LifeTime = 1.5; e.ParticleScale.push_back(0.6); e.ParticleScale.push_back(1.8); e.ParticlesToSpawn = 1; e.Position = cloneTransform->Position; e.RelativeUpOrientation = glm::angleAxis(glm::pi() / 2, glm::vec3(1,0,0)); e.Speed = 1.7; e.SpreadAngle = glm::pi()/100; e.spritePath = "Textures/Sprites/Smoke1.png"; e.Emitting = true; e.SpawnFrequency = 0.2; e.Color = glm::vec4(0.6,0.6,0.6,1); EventBroker->Publish(e); } { Events::CreateExplosion e; e.LifeTime = 0.2; e.ParticleScale.push_back(1); //e.ParticleScale.push_back(2); e.ParticlesToSpawn = 1; e.Position = cloneTransform->Position; e.Speed = 0; e.SpreadAngle = glm::pi(); e.spritePath = "Textures/Sprites/MuzzleFlash.png"; e.Color = glm::vec4(2, 2, 2, 0.2); EventBroker->Publish(e); } } Temp_m_TimeSinceLastShot = 0; #pragma endregion } } } bool Systems::TowerSystem::OnCollision(const Events::Collision &e) { if(m_World->ValidEntity(e.Entity1) && m_World->ValidEntity(e.Entity2)) { auto tankShell1 = m_World->GetComponent(e.Entity1); auto tankShell2 = m_World->GetComponent(e.Entity2); EntityID shellEntity = 0; Components::TurretShot* shellComponent; EntityID otherEntity = 0; if (tankShell1) { shellEntity = e.Entity1; otherEntity = e.Entity2; shellComponent = tankShell1; } else if (tankShell2) { shellEntity = e.Entity2; otherEntity = e.Entity1; shellComponent = tankShell2; } else { return false; } if(m_World->GetComponent(shellEntity)) return false; //auto physicsComponents = m_World->GetComponentsOfType(); auto shellTransform = m_World->GetComponent(shellEntity); //auto otherTransform = m_World->GetComponent(otherEntity); { Events::CreateExplosion e; e.LifeTime = 2; e.ParticleScale.push_back(3); e.ParticlesToSpawn = 10; e.Position = shellTransform->Position; e.RelativeUpOrientation = glm::angleAxis(glm::pi() / 2, glm::vec3(1, 0, 0)); e.Speed = 3; e.SpreadAngle = glm::pi(); e.spritePath = "Textures/Sprites/Smoke1.png"; e.Color = glm::vec4(0.6, 0.6, 0.6, 0.1); EventBroker->Publish(e); e.LifeTime = 0.7; e.ParticleScale.push_back(5); e.ParticlesToSpawn = 10; e.Position = shellTransform->Position; e.RelativeUpOrientation = glm::angleAxis(glm::pi() / 2, glm::vec3(1, 0, 0)); e.Speed = 17; e.SpreadAngle = glm::pi(); e.spritePath = "Textures/Sprites/Fire.png"; EventBroker->Publish(e); e.LifeTime = 0.2; e.ParticleScale.push_back(1); e.ParticleScale.push_back(5); e.ParticlesToSpawn = 5; e.Position = shellTransform->Position; e.RelativeUpOrientation = glm::angleAxis(glm::pi() / 2, glm::vec3(1, 0, 0)); e.Speed = 6; e.SpreadAngle = glm::pi(); e.spritePath = "Textures/Sprites/Blast1.png"; e.Color = glm::vec4(2, 2, 2, 0.2); EventBroker->Publish(e); } //{ // Events::CreateExplosion e; // e.LifeTime = 1.5; // e.ParticleScale.push_back(1); // e.ParticleScale.push_back(6); // e.ParticlesToSpawn = 20; // e.Position = shellTransform->Position; // e.SpreadAngle = glm::radians(180) / 4; // e.RelativeUpOrientation = glm::angleAxis(glm::radians(90), glm::vec3(1,0,0)); // e.UseGoalVector = true; // e.GoalVelocity = glm::vec3(0,-12,0); // e.Speed = 12; // e.spritePath = "Textures/Sprites/Splash.png"; // e.Color = glm::vec4(5.f,5.f,5.f,1); // EventBroker->Publish(e); // e.LifeTime = 1.5; // e.ParticleScale.push_back(1); // e.ParticleScale.push_back(6); // e.ParticlesToSpawn = 20; // e.Position = shellTransform->Position; // e.SpreadAngle = glm::radians(180)/ 4; // e.RelativeUpOrientation = glm::angleAxis(glm::radians(90), glm::vec3(1,0,0)); // e.UseGoalVector = true; // e.GoalVelocity = glm::vec3(0,-12,0); // e.Speed = 12; // e.spritePath = "Textures/Sprites/Splash.png"; // e.Color = glm::vec4(1.f,1.f,1.f,1); // EventBroker->Publish(e); //} //{ // Events::PlaySFX e; // e.MinDistance = 150.f; // e.Position = shellTransform->Position; // e.Resource = "Sounds/SFX/Explosion.wav"; // EventBroker->Publish(e); //} // Direct damage auto health = m_World->GetComponent(otherEntity); if (health) { Events::Damage d; d.Entity = otherEntity; d.Amount = shellComponent->Damage; EventBroker->Publish(d); } // Splash damage //for (auto &physComponent : *physicsComponents) //{ // EntityID physicsEntity = physComponent->Entity; // // No splash damage to the direct hit target // if (physicsEntity == otherEntity) // continue; // auto physEntityTransform = m_World->GetSystem()->AbsoluteTransform(physicsEntity); // float distance = glm::distance(physEntityTransform.Position, shellTransform->Position); // if (distance <= shellComponent->ExplosionRadius) // { // // DO STUFF! :D // float radius = shellComponent->ExplosionRadius; // float strength = (1.f - pow(distance / radius, 2)) * shellComponent->ExplosionStrength; // glm::vec3 direction = glm::normalize(physEntityTransform.Position - shellTransform->Position); // Events::ApplyPointImpulse e; // e.Entity = physicsEntity; // e.Impulse = direction * strength; // e.Position = physEntityTransform.Position; // EventBroker->Publish(e); // auto health = m_World->GetComponent(physicsEntity); // if (health && health->VulnerableToSplash) // { // Events::Damage d; // d.Entity = physicsEntity; // d.Amount = (1.f - pow(distance / radius, 2)) * shellComponent->Damage; // EventBroker->Publish(d); // } // // // } //} m_World->RemoveEntity(shellEntity); } return true; }