void CAutoBase::FreezeCargo(bool bFreeze) { CObject* pObj; CPhysics* physics; Math::Vector oPos; float dist; int i; for ( i=0 ; i<1000000 ; i++ ) { pObj = static_cast<CObject*>(m_iMan->SearchInstance(CLASS_OBJECT, i)); if ( pObj == 0 ) break; pObj->SetCargo(false); if ( pObj == m_object ) continue; // yourself? if ( pObj->GetTruck() != 0 ) continue; // transport object? oPos = pObj->GetPosition(0); dist = Math::DistanceProjected(m_pos, oPos); if ( dist < 32.0f ) { if ( bFreeze ) { pObj->SetCargo(true); } physics = pObj->GetPhysics(); if ( physics != 0 ) { physics->SetFreeze(bFreeze); } } } }
bool CAutoFactory::CreateVehicle() { CObject* vehicle; Math::Matrix* mat; CPhysics* physics; Math::Vector pos; float angle; char* name; int i; angle = m_object->GetAngleY(0); mat = m_object->GetWorldMatrix(0); if ( m_type == OBJECT_MOBILErt || m_type == OBJECT_MOBILErc || m_type == OBJECT_MOBILErr || m_type == OBJECT_MOBILErs ) { pos = Math::Vector(2.0f, 0.0f, 0.0f); } else { pos = Math::Vector(4.0f, 0.0f, 0.0f); } pos = Transform(*mat, pos); vehicle = new CObject(); if ( !vehicle->CreateVehicle(pos, angle, m_type, -1.0f, false, false) ) { delete vehicle; m_displayText->DisplayError(ERR_TOOMANY, m_object); return false; } vehicle->UpdateMapping(); vehicle->SetLock(true); // not usable vehicle->SetRange(30.0f); physics = vehicle->GetPhysics(); if ( physics != 0 ) { physics->SetFreeze(true); // it doesn't move } for ( i=0 ; i<10 ; i++ ) { name = m_main->GetNewScriptName(m_type, i); if ( name == 0 ) break; vehicle->ReadProgram(i, name); } return true; }
CObject* CAutoTower::SearchTarget(Math::Vector &impact) { CObject* pObj; CObject* pBest = 0; CPhysics* physics; Math::Vector iPos, oPos; ObjectType oType; float distance, min, radius, speed; iPos = m_object->GetPosition(0); min = 1000000.0f; for(auto it : CObjectManager::GetInstancePointer()->GetAllObjects()) { pObj = it.second; oType = pObj->GetType(); if ( oType != OBJECT_MOTHER && oType != OBJECT_ANT && oType != OBJECT_SPIDER && oType != OBJECT_BEE && oType != OBJECT_WORM ) continue; if ( !pObj->GetActif() ) continue; // inactive? //? if ( g_researchDone & RESEARCH_QUICK ) if ( false ) { physics = pObj->GetPhysics(); if ( physics != 0 ) { speed = fabs(physics->GetLinMotionX(MO_REASPEED)); if ( speed > 20.0f ) continue; // moving too fast? } } if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue; distance = Math::Distance(oPos, iPos); if ( distance > TOWER_SCOPE ) continue; // too far if ( distance < min ) { min = distance; pBest = pObj; } } if ( pBest == 0 ) return 0; impact = pBest->GetPosition(0); return pBest; }
CObject* CAutoTower::SearchTarget(Math::Vector &impact) { Math::Vector iPos = m_object->GetPosition(); float min = 1000000.0f; CObject* best = nullptr; for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects()) { int oTeam=obj->GetTeam(); int myTeam=m_object->GetTeam(); ObjectType oType = obj->GetType(); if ( oType != OBJECT_MOTHER && oType != OBJECT_ANT && oType != OBJECT_SPIDER && oType != OBJECT_BEE && oType != OBJECT_WORM && (oTeam == myTeam || oTeam == 0) ) continue; if ( !obj->GetDetectable() ) continue; // inactive? //? if ( g_researchDone & RESEARCH_QUICK ) if ( false ) { if ( obj->Implements(ObjectInterfaceType::Movable) ) { CPhysics* physics = dynamic_cast<CMovableObject*>(obj)->GetPhysics(); float speed = fabs(physics->GetLinMotionX(MO_REASPEED)); if ( speed > 20.0f ) continue; // moving too fast? } } if (obj->GetCrashSphereCount() == 0) continue; Math::Vector oPos = obj->GetFirstCrashSphere().sphere.pos; float distance = Math::Distance(oPos, iPos); if ( distance > TOWER_SCOPE ) continue; // too far if ( distance < min ) { min = distance; best = obj; } } if ( best == nullptr ) return nullptr; impact = best->GetPosition(); return best; }
bool CAutoFactory::CreateVehicle() { float angle = m_object->GetRotationY(); Math::Vector pos; if ( m_type == OBJECT_MOBILErt || m_type == OBJECT_MOBILErc || m_type == OBJECT_MOBILErr || m_type == OBJECT_MOBILErs ) { pos = Math::Vector(2.0f, 0.0f, 0.0f); } else { pos = Math::Vector(4.0f, 0.0f, 0.0f); } Math::Matrix* mat = m_object->GetWorldMatrix(0); pos = Transform(*mat, pos); ObjectCreateParams params; params.pos = pos; params.angle = angle; params.type = m_type; params.team = m_object->GetTeam(); CObject* vehicle = CObjectManager::GetInstancePointer()->CreateObject(params); vehicle->SetLock(true); // not usable assert(vehicle->Implements(ObjectInterfaceType::Movable)); CPhysics* physics = dynamic_cast<CMovableObject*>(vehicle)->GetPhysics(); physics->SetFreeze(true); // it doesn't move if (vehicle->Implements(ObjectInterfaceType::ProgramStorage)) { CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(vehicle); for ( int i=0 ; ; i++ ) { std::string name = m_main->GetNewScriptName(m_type, i); if (name.empty()) break; Program* prog = programStorage->GetOrAddProgram(i); programStorage->ReadProgram(prog, InjectLevelPathsForCurrentLevel(name)); prog->readOnly = true; prog->filename = name; } } return true; }
bool CTaskFire::EventProcess(const Event &event) { CPhysics* physics; Math::Matrix* mat; Math::Vector pos, speed, dir, vib; ObjectType type; Math::Point dim; float energy, fire; int i, channel; if ( m_engine->GetPause() ) return true; if ( event.type != EVENT_FRAME ) return true; if ( m_bError ) return false; m_time += event.rTime; m_lastSound -= event.rTime; m_progress += event.rTime*m_speed; CPowerContainerObject* power = nullptr; if (m_object->GetPower() != nullptr && m_object->GetPower()->Implements(ObjectInterfaceType::PowerContainer)) { power = dynamic_cast<CPowerContainerObject*>(m_object->GetPower()); energy = power->GetEnergy(); if ( m_bOrganic ) fire = ENERGY_FIREi; else if ( m_bRay ) fire = ENERGY_FIREr; else fire = ENERGY_FIRE; energy -= event.rTime*fire; power->SetEnergy(energy); } if ( m_lastParticle+0.05f <= m_time ) { m_lastParticle = m_time; if ( m_bOrganic ) { mat = m_object->GetWorldMatrix(1); // insect-cannon for ( i=0 ; i<6 ; i++ ) { pos = Math::Vector(0.0f, 2.5f, 0.0f); pos = Math::Transform(*mat, pos); speed = Math::Vector(200.0f, 0.0f, 0.0f); physics = m_object->GetPhysics(); if ( physics != nullptr ) { speed += physics->GetLinMotion(MO_REASPEED); } speed.x += (Math::Rand()-0.5f)*10.0f; speed.y += (Math::Rand()-0.5f)*20.0f; speed.z += (Math::Rand()-0.5f)*30.0f; speed = Math::Transform(*mat, speed); speed -= pos; dim.x = Math::Rand()*0.5f+0.5f; dim.y = dim.x; channel = m_particle->CreateParticle(pos, speed, dim, Gfx::PARTIGUN4, 0.8f, 0.0f, 0.0f); m_particle->SetObjectFather(channel, m_object); } } else if ( m_bRay ) { mat = m_object->GetWorldMatrix(2); // cannon for ( i=0 ; i<4 ; i++ ) { pos = Math::Vector(4.0f, 0.0f, 0.0f); pos.y += (rand()%3-1)*1.5f; pos.z += (rand()%3-1)*1.5f; pos = Math::Transform(*mat, pos); speed = Math::Vector(200.0f, 0.0f, 0.0f); speed.x += (Math::Rand()-0.5f)*6.0f; speed.y += (Math::Rand()-0.5f)*12.0f; speed.z += (Math::Rand()-0.5f)*12.0f; speed = Math::Transform(*mat, speed); speed -= pos; dim.x = 1.0f; dim.y = dim.x; channel = m_particle->CreateTrack(pos, speed, dim, Gfx::PARTITRACK11, 2.0f, 200.0f, 0.5f, 1.0f); m_particle->SetObjectFather(channel, m_object); speed = Math::Vector(5.0f, 0.0f, 0.0f); speed.x += (Math::Rand()-0.5f)*1.0f; speed.y += (Math::Rand()-0.5f)*2.0f; speed.z += (Math::Rand()-0.5f)*2.0f; speed = Math::Transform(*mat, speed); speed -= pos; speed.y += 5.0f; dim.x = 2.0f; dim.y = dim.x; m_particle->CreateParticle(pos, speed, dim, Gfx::PARTISMOKE2, 2.0f, 0.0f, 0.5f); } } else { type = m_object->GetType(); if ( type == OBJECT_MOBILErc ) { mat = m_object->GetWorldMatrix(2); // cannon } else { mat = m_object->GetWorldMatrix(1); // cannon } for ( i=0 ; i<3 ; i++ ) { if ( type == OBJECT_MOBILErc ) { pos = Math::Vector(0.0f, 0.0f, 0.0f); } else { pos = Math::Vector(3.0f, 1.0f, 0.0f); } pos.y += (Math::Rand()-0.5f)*1.0f; pos.z += (Math::Rand()-0.5f)*1.0f; pos = Math::Transform(*mat, pos); speed = Math::Vector(200.0f, 0.0f, 0.0f); physics = m_object->GetPhysics(); if ( physics != nullptr ) { speed += physics->GetLinMotion(MO_REASPEED); } speed.x += (Math::Rand()-0.5f)*3.0f; speed.y += (Math::Rand()-0.5f)*6.0f; speed.z += (Math::Rand()-0.5f)*6.0f; speed = Math::Transform(*mat, speed); speed -= pos; dim.x = Math::Rand()*0.7f+0.7f; dim.y = dim.x; channel = m_particle->CreateParticle(pos, speed, dim, Gfx::PARTIGUN1, 0.8f, 0.0f, 0.0f); m_particle->SetObjectFather(channel, m_object); } if ( type != OBJECT_MOBILErc && m_progress > 0.3f ) { pos = Math::Vector(-1.0f, 1.0f, 0.0f); pos.y += (Math::Rand()-0.5f)*0.4f; pos.z += (Math::Rand()-0.5f)*0.4f; pos = Math::Transform(*mat, pos); speed = Math::Vector(-4.0f, 0.0f, 0.0f); speed.x += (Math::Rand()-0.5f)*2.0f; speed.y += (Math::Rand()-0.2f)*4.0f; speed.z += (Math::Rand()-0.5f)*4.0f; speed = Math::Transform(*mat, speed); speed -= pos; dim.x = Math::Rand()*1.2f+1.2f; dim.y = dim.x; m_particle->CreateParticle(pos, speed, dim, Gfx::PARTICRASH, 2.0f, 0.0f, 0.0f); //? m_particle->CreateParticle(pos, speed, dim, PARTISMOKE2, 4.0f, 0.0f, 0.0f); } } dir = Math::Vector(0.0f, 0.0f, 0.0f); if ( m_progress < 0.1f ) { dir.z = (Math::PI*0.04f)*(m_progress*10.0f); } else if ( m_progress < 0.9f ) { dir.z = (Math::PI*0.04f); } else { dir.z = (Math::PI*0.04f)*(1.0f-(m_progress-0.9f)*10.0f); } m_object->SetTilt(dir); vib.x = (Math::Rand()-0.5f)*0.01f; vib.y = (Math::Rand()-0.5f)*0.02f; vib.z = (Math::Rand()-0.5f)*0.02f; m_object->SetCirVibration(vib); vib.x = (Math::Rand()-0.5f)*0.20f; vib.y = (Math::Rand()-0.5f)*0.05f; vib.z = (Math::Rand()-0.5f)*0.20f; m_object->SetLinVibration(vib); } if ( m_bRay && m_lastSound <= 0.0f ) { m_lastSound = Math::Rand()*0.4f+0.4f; m_sound->Play(SOUND_FIREp, m_object->GetPosition()); } return true; }
bool CAutoFactory::EventProcess(const Event &event) { ObjectType type; CObject* fret; CObject* vehicle; Math::Matrix* mat; CPhysics* physics; Math::Vector pos, speed; Math::Point dim; float zoom, angle, prog; int i; CAuto::EventProcess(event); if ( m_engine->GetPause() ) return true; if ( m_object->GetSelect() ) // factory selected? { if ( event.type == EVENT_UPDINTERFACE ) { CreateInterface(true); } type = OBJECT_NULL; if ( event.type == EVENT_OBJECT_FACTORYwa ) type = OBJECT_MOBILEwa; if ( event.type == EVENT_OBJECT_FACTORYta ) type = OBJECT_MOBILEta; if ( event.type == EVENT_OBJECT_FACTORYfa ) type = OBJECT_MOBILEfa; if ( event.type == EVENT_OBJECT_FACTORYia ) type = OBJECT_MOBILEia; if ( event.type == EVENT_OBJECT_FACTORYws ) type = OBJECT_MOBILEws; if ( event.type == EVENT_OBJECT_FACTORYts ) type = OBJECT_MOBILEts; if ( event.type == EVENT_OBJECT_FACTORYfs ) type = OBJECT_MOBILEfs; if ( event.type == EVENT_OBJECT_FACTORYis ) type = OBJECT_MOBILEis; if ( event.type == EVENT_OBJECT_FACTORYwc ) type = OBJECT_MOBILEwc; if ( event.type == EVENT_OBJECT_FACTORYtc ) type = OBJECT_MOBILEtc; if ( event.type == EVENT_OBJECT_FACTORYfc ) type = OBJECT_MOBILEfc; if ( event.type == EVENT_OBJECT_FACTORYic ) type = OBJECT_MOBILEic; if ( event.type == EVENT_OBJECT_FACTORYwi ) type = OBJECT_MOBILEwi; if ( event.type == EVENT_OBJECT_FACTORYti ) type = OBJECT_MOBILEti; if ( event.type == EVENT_OBJECT_FACTORYfi ) type = OBJECT_MOBILEfi; if ( event.type == EVENT_OBJECT_FACTORYii ) type = OBJECT_MOBILEii; if ( event.type == EVENT_OBJECT_FACTORYrt ) type = OBJECT_MOBILErt; if ( event.type == EVENT_OBJECT_FACTORYrc ) type = OBJECT_MOBILErc; if ( event.type == EVENT_OBJECT_FACTORYrr ) type = OBJECT_MOBILErr; if ( event.type == EVENT_OBJECT_FACTORYrs ) type = OBJECT_MOBILErs; if ( event.type == EVENT_OBJECT_FACTORYsa ) type = OBJECT_MOBILEsa; Error err = StartAction(type); if( err != ERR_OK && err != ERR_GENERIC ) m_displayText->DisplayError(err, m_object); if( err != ERR_GENERIC ) return false; } if ( event.type != EVENT_FRAME ) return true; m_progress += event.rTime*m_speed; EventProgress(event.rTime); if ( m_phase == AFP_WAIT ) { if ( m_progress >= 1.0f ) { m_phase = AFP_WAIT; // still waiting ... m_progress = 0.0f; m_speed = 1.0f/2.0f; } } if ( m_phase == AFP_CLOSE_S ) { if ( m_progress < 1.0f ) { for ( i=0 ; i<9 ; i++ ) { zoom = 0.30f+(m_progress-0.5f+i/16.0f)*2.0f*0.70f; if ( zoom < 0.30f ) zoom = 0.30f; if ( zoom > 1.00f ) zoom = 1.00f; m_object->SetZoomZ( 1+i, zoom); m_object->SetZoomZ(10+i, zoom); } } else { for ( i=0 ; i<9 ; i++ ) { m_object->SetZoomZ( 1+i, 1.0f); m_object->SetZoomZ(10+i, 1.0f); } SoundManip(2.0f, 1.0f, 1.2f); m_phase = AFP_CLOSE_T; m_progress = 0.0f; m_speed = 1.0f/2.0f; } } if ( m_phase == AFP_CLOSE_T ) { if ( m_progress < 1.0f ) { for ( i=0 ; i<9 ; i++ ) { angle = -m_progress*(Math::PI/2.0f)+Math::PI/2.0f; m_object->SetAngleZ( 1+i, angle); m_object->SetAngleZ(10+i, -angle); } } else { for ( i=0 ; i<9 ; i++ ) { m_object->SetAngleZ( 1+i, 0.0f); m_object->SetAngleZ(10+i, 0.0f); } m_channelSound = m_sound->Play(SOUND_FACTORY, m_object->GetPosition(0), 0.0f, 1.0f, true); m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE); m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 11.0f, SOPER_CONTINUE); m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP); m_phase = AFP_BUILD; m_progress = 0.0f; m_speed = 1.0f/15.0f; } } if ( m_phase == AFP_BUILD ) { if ( m_progress == 0.0f ) { if ( !CreateVehicle() ) { fret = SearchFret(); // transform metal? if ( fret != 0 ) { fret->SetLock(false); // metal usable again } if ( m_channelSound != -1 ) { m_sound->FlushEnvelope(m_channelSound); m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP); m_channelSound = -1; } m_phase = AFP_OPEN_T; m_progress = 0.0f; m_speed = 1.0f/2.0f; return true; } } if ( m_progress < 1.0f ) { if ( m_type == OBJECT_MOBILErt || m_type == OBJECT_MOBILErc || m_type == OBJECT_MOBILErr || m_type == OBJECT_MOBILErs ) { prog = 1.0f-m_progress*1.5f; if ( prog < 0.0f ) prog = 0.0f; } else { prog = 1.0f-m_progress; } angle = powf(prog*10.0f, 2.0f)+m_object->GetAngleY(0); vehicle = SearchVehicle(); if ( vehicle != 0 ) { vehicle->SetAngleY(0, angle+Math::PI); vehicle->SetZoom(0, m_progress); } fret = SearchFret(); // transform metal? if ( fret != 0 ) { fret->SetZoom(0, 1.0f-m_progress); } if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time ) { m_lastParticle = m_time; #if 0 pos = m_fretPos; pos.x += (Math::Rand()-0.5f)*20.0f; pos.z += (Math::Rand()-0.5f)*20.0f; pos.y += 1.0f; speed.x = (Math::Rand()-0.5f)*12.0f; speed.z = (Math::Rand()-0.5f)*12.0f; speed.y = Math::Rand()*12.0f; dim.x = Math::Rand()*12.0f+10.0f; dim.y = dim.x; m_particle->CreateParticle(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f); #else mat = m_object->GetWorldMatrix(0); pos = Math::Vector(-12.0f, 20.0f, -4.0f); // position of chimney pos = Math::Transform(*mat, pos); pos.y += 2.0f; pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f; speed.x = 0.0f; speed.z = 0.0f; speed.y = 6.0f+Math::Rand()*6.0f; dim.x = Math::Rand()*1.5f+1.0f; dim.y = dim.x; m_particle->CreateParticle(pos, speed, dim, Gfx::PARTISMOKE3, 4.0f); #endif } } else { m_displayText->DisplayError(INFO_FACTORY, m_object); SoundManip(2.0f, 1.0f, 1.2f); fret = SearchFret(); // transform metal? if ( fret != 0 ) { fret->DeleteObject(); // removes the metal delete fret; } m_vehicle = vehicle = SearchVehicle(); if ( vehicle != 0 ) { physics = vehicle->GetPhysics(); if ( physics != 0 ) { physics->SetFreeze(false); // can move } vehicle->SetLock(false); // vehicle useable //? vehicle->GetPhysics()->GetBrain()->StartTaskAdvance(16.0f); vehicle->SetAngleY(0, m_object->GetAngleY(0)+Math::PI); vehicle->SetZoom(0, 1.0f); } m_main->CreateShortcuts(); m_phase = AFP_OPEN_T; m_progress = 0.0f; m_speed = 1.0f/2.0f; } } if ( m_phase == AFP_OPEN_T ) { if ( m_progress < 1.0f ) { for ( i=0 ; i<9 ; i++ ) { angle = -(1.0f-m_progress)*(Math::PI/2.0f)+Math::PI/2.0f; m_object->SetAngleZ( 1+i, angle); m_object->SetAngleZ(10+i, -angle); } if ( m_lastParticle+m_engine->ParticleAdapt(0.1f) <= m_time ) { m_lastParticle = m_time; pos = m_fretPos; pos.x += (Math::Rand()-0.5f)*10.0f; pos.z += (Math::Rand()-0.5f)*10.0f; pos.y += Math::Rand()*10.0f; speed = Math::Vector(0.0f, 0.0f, 0.0f); dim.x = 2.0f; dim.y = dim.x; m_particle->CreateParticle(pos, speed, dim, Gfx::PARTIGLINT, 2.0f, 0.0f, 0.0f); } } else { for ( i=0 ; i<9 ; i++ ) { m_object->SetAngleZ( 1+i, Math::PI/2.0f); m_object->SetAngleZ(10+i, -Math::PI/2.0f); } SoundManip(3.0f, 1.0f, 0.5f); m_phase = AFP_OPEN_S; m_progress = 0.0f; m_speed = 1.0f/3.0f; } } if ( m_phase == AFP_OPEN_S ) { if ( m_progress < 1.0f ) { for ( i=0 ; i<9 ; i++ ) { zoom = 0.30f+((1.0f-m_progress)-0.5f+i/16.0f)*2.0f*0.70f; if ( zoom < 0.30f ) zoom = 0.30f; if ( zoom > 1.00f ) zoom = 1.00f; m_object->SetZoomZ( 1+i, zoom); m_object->SetZoomZ(10+i, zoom); } if ( m_lastParticle+m_engine->ParticleAdapt(0.1f) <= m_time ) { m_lastParticle = m_time; pos = m_fretPos; pos.x += (Math::Rand()-0.5f)*10.0f; pos.z += (Math::Rand()-0.5f)*10.0f; pos.y += Math::Rand()*10.0f; speed = Math::Vector(0.0f, 0.0f, 0.0f); dim.x = 2.0f; dim.y = dim.x; m_particle->CreateParticle(pos, speed, dim, Gfx::PARTIGLINT, 2.0f, 0.0f, 0.0f); } } else { for ( i=0 ; i<9 ; i++ ) { m_object->SetZoomZ( 1+i, 0.30f); m_object->SetZoomZ(10+i, 0.30f); } if ( m_program != nullptr ) { CBrain* brain = m_vehicle->GetBrain(); if ( brain != nullptr ) { brain->SendProgram(0, const_cast<const char*>(m_program)); brain->SetScriptRun(0); brain->RunProgram(0); } } SetBusy(false); UpdateInterface(); m_phase = AFP_WAIT; m_progress = 0.0f; m_speed = 1.0f/2.0f; } } return true; }
CObject* CObjectManager::Radar(CObject* pThis, Math::Vector thisPosition, float thisAngle, std::vector<ObjectType> type, float angle, float focus, float minDist, float maxDist, bool furthest, RadarFilter filter, bool cbotTypes) { CObject *pObj, *pBest; Math::Vector iPos, oPos; float best, iAngle, d, a; ObjectType oType; minDist *= g_unit; maxDist *= g_unit; iPos = thisPosition; iAngle = thisAngle+angle; iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI int filter_team = filter & 0xFF; RadarFilter filter_flying = static_cast<RadarFilter>(filter & (FILTER_ONLYLANDING | FILTER_ONLYFLYING)); RadarFilter filter_enemy = static_cast<RadarFilter>(filter & (FILTER_FRIENDLY | FILTER_ENEMY | FILTER_NEUTRAL)); if ( !furthest ) best = 100000.0f; else best = 0.0f; pBest = nullptr; for ( auto it = m_objects.begin() ; it != m_objects.end() ; ++it ) { pObj = it->second.get(); if ( pObj == pThis ) continue; // pThis may be nullptr but it doesn't matter if (pObj == nullptr) continue; if (IsObjectBeingTransported(pObj)) continue; if ( !pObj->GetDetectable() ) continue; if ( pObj->GetProxyActivate() ) continue; oType = pObj->GetType(); if (cbotTypes) { // TODO: handle this differently (new class describing types? CObjectType::GetBaseType()?) if ( oType == OBJECT_RUINmobilew2 || oType == OBJECT_RUINmobilet1 || oType == OBJECT_RUINmobilet2 || oType == OBJECT_RUINmobiler1 || oType == OBJECT_RUINmobiler2 ) { oType = OBJECT_RUINmobilew1; // any ruin } if ( oType == OBJECT_BARRIER2 || oType == OBJECT_BARRIER3 ) // barriers? { oType = OBJECT_BARRIER1; // any barrier } // END OF TODO } if ( std::find(type.begin(), type.end(), oType) == type.end() && type.size() > 0 ) continue; if ( (oType == OBJECT_TOTO || oType == OBJECT_CONTROLLER) && type.size() == 0 ) continue; // allow OBJECT_TOTO and OBJECT_CONTROLLER only if explicitly asked in type parameter if ( filter_flying == FILTER_ONLYLANDING ) { if ( pObj->Implements(ObjectInterfaceType::Movable) ) { CPhysics* physics = dynamic_cast<CMovableObject*>(pObj)->GetPhysics(); if ( physics != nullptr ) { if ( !physics->GetLand() ) continue; } } } if ( filter_flying == FILTER_ONLYFLYING ) { if ( !pObj->Implements(ObjectInterfaceType::Movable) ) continue; CPhysics* physics = dynamic_cast<CMovableObject*>(pObj)->GetPhysics(); if ( physics == nullptr ) continue; if ( physics->GetLand() ) continue; } if ( filter_team != 0 && pObj->GetTeam() != filter_team ) continue; if( pThis != nullptr ) { RadarFilter enemy = FILTER_NONE; if ( pObj->GetTeam() == 0 ) enemy = static_cast<RadarFilter>(enemy | FILTER_NEUTRAL); if ( pObj->GetTeam() != 0 && pObj->GetTeam() == pThis->GetTeam() ) enemy = static_cast<RadarFilter>(enemy | FILTER_FRIENDLY); if ( pObj->GetTeam() != 0 && pObj->GetTeam() != pThis->GetTeam() ) enemy = static_cast<RadarFilter>(enemy | FILTER_ENEMY); if ( filter_enemy != 0 && (filter_enemy & enemy) == 0 ) continue; } oPos = pObj->GetPosition(); d = Math::DistanceProjected(iPos, oPos); if ( d < minDist || d > maxDist ) continue; // too close or too far? a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! if ( Math::TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) || focus >= Math::PI*2.0f ) { if ( (!furthest && d < best) || (furthest && d > best) ) { best = d; pBest = pObj; } } } return pBest; }
// main void PhysicsWorld::Step(float dt, unsigned char velocityIterations, unsigned char positionIterations) { const TimeStep timeStep(dt, velocityIterations, positionIterations, mParams, mStats); Stopwatch timer; mStats.Clear(); // update rigid bodies const float linearDampFactor = 1.0f - Clamp(mParams.linearDamping * timeStep.dt, 0.0f, 1.0f); const float angularDampFactor = 1.0f - Clamp(mParams.angularDamping * timeStep.dt, 0.0f, 1.0f); timer.Start(); for (auto &body : mRigidBodies) { // TODOKai mass if (!body.CollidersValid()) body.ValidateColliders(); // update body.UpdateMassAndLocalCentroid(); body.UpdateOrientation(); body.UpdatePositionFromGlobalCentroid(); body.UpdateGlobalInverseInertiaTensor(); body.UpdateProxies(); timeStep.stats.colliders += body.mColliders.size(); } timeStep.stats.rigidBodies = mRigidBodies.size(); timeStep.stats.integration += timer.Stop(); // broadphase timer.Start(); auto &pairList = mBroadphase->ComputePairs(); timeStep.stats.broadphasePairs = pairList.size(); timeStep.stats.broadphase += timer.Stop(); // narrowphase timer.Start(); mContactManager.PreNarrowphase(); for (ColliderPair &pair : pairList) { Collider *colliderA = pair.mCollider1; Collider *colliderB = pair.mCollider2; RigidBody &bodyA = *colliderA->mParent; RigidBody &bodyB = *colliderB->mParent; CPhysics* cphyA = bodyA.mParent->cphy; CPhysics* cphyB = bodyB.mParent->cphy; if (!bodyA.CanCollide(bodyB) || !colliderA->CanBeCollide(*colliderB)) continue; // collision table check if (!cphyA->gameObject->GetState()->GetCollisionTable()->GetDoesIDsCollide(cphyA->GetCOllisionID(), cphyB->GetCOllisionID())) continue; // make sure colliderA is always less than colliderB in memory address for consistency if (colliderA > colliderB) { std::swap(colliderA, colliderB); auto temp = cphyA; cphyA = cphyB; cphyB = temp; } ContactManifold *manifold = new (mManifoldAllocator.Allocate()) ContactManifold(); manifold->colliderA = colliderA; manifold->colliderB = colliderB; //TODO manifold->isColliding = Collide(*manifold, *colliderA->mGeometry, *colliderB->mGeometry, mContactAllocator); if (!manifold->isColliding || !mContactManager.Add(*manifold, mParams.contactPersistenceThreshold * mParams.contactPersistenceThreshold)) { // manifold not colliding OR persistent manifold already exists, delete manifold->~ContactManifold(); mManifoldAllocator.Free(manifold); } else { //these will be deleted by the script subsystem CollisionData* dataA = new CollisionData(); CollisionData* dataB = new CollisionData(); // send manifold to OnCollide function { dataA->isA = true; dataA->collidedObj = cphyB->gameObject; dataA->selfCPhy = cphyA; dataA->collidedObjCPhy = cphyB; dataA->numContacts = manifold->numContacts; for (int i = 0; i < dataA->numContacts; ++i) { dataA->normals.push_back(manifold->contacts[i]->normal); } ScriptSubsystem::getInstance()->QueueEvent<CollisionData>(cphyA->gameObject, "OnCollisionEnter", dataA); } { dataB->isA = false; dataB->collidedObj = cphyA->gameObject; dataB->selfCPhy = cphyB; dataB->collidedObjCPhy = cphyA; dataB->numContacts = manifold->numContacts; for (int i = 0; i < dataB->numContacts; ++i) { dataB->normals.push_back(manifold->contacts[i]->normal); } ScriptSubsystem::getInstance()->QueueEvent<CollisionData>(cphyB->gameObject, "OnCollisionEnter", dataB); } if (cphyA->mIsTriggered || cphyB->mIsTriggered) { manifold->~ContactManifold(); mManifoldAllocator.Free(manifold); } } } mContactManager.PostNarrowphase(); timeStep.stats.narrowphase += timer.Stop(); SimulateIslands(timeStep); // update broadphase after position integration mBroadphase->Update(timeStep); mContactManager.Draw(); }
bool CAutoFactory::EventProcess(const Event &event) { ObjectType type; CObject* cargo; CObject* vehicle; Math::Matrix* mat; CPhysics* physics; Math::Vector pos, speed; Math::Point dim; float zoom, angle, prog; int i; CAuto::EventProcess(event); if ( m_engine->GetPause() ) return true; if ( m_object->GetSelect() ) // factory selected? { if ( event.type == EVENT_UPDINTERFACE ) { CreateInterface(true); } type = ObjectTypeFromFactoryButton(event.type); Error err = StartAction(type); if( err != ERR_OK && err != ERR_UNKNOWN ) m_main->DisplayError(err, m_object); if( err != ERR_UNKNOWN ) return false; } if ( event.type != EVENT_FRAME ) return true; m_progress += event.rTime*m_speed; EventProgress(event.rTime); if ( m_phase == AFP_WAIT ) { if ( m_progress >= 1.0f ) { m_phase = AFP_WAIT; // still waiting ... m_progress = 0.0f; m_speed = 1.0f/2.0f; } } if ( m_phase == AFP_CLOSE_S ) { if ( m_progress < 1.0f ) { for ( i=0 ; i<9 ; i++ ) { zoom = 0.30f+(m_progress-0.5f+i/16.0f)*2.0f*0.70f; if ( zoom < 0.30f ) zoom = 0.30f; if ( zoom > 1.00f ) zoom = 1.00f; m_object->SetPartScaleZ( 1+i, zoom); m_object->SetPartScaleZ(10+i, zoom); } } else { for ( i=0 ; i<9 ; i++ ) { m_object->SetPartScaleZ( 1+i, 1.0f); m_object->SetPartScaleZ(10+i, 1.0f); } SoundManip(2.0f, 1.0f, 1.2f); m_phase = AFP_CLOSE_T; m_progress = 0.0f; m_speed = 1.0f/2.0f; } } if ( m_phase == AFP_CLOSE_T ) { if ( m_progress < 1.0f ) { for ( i=0 ; i<9 ; i++ ) { angle = -m_progress*(Math::PI/2.0f)+Math::PI/2.0f; m_object->SetPartRotationZ( 1+i, angle); m_object->SetPartRotationZ(10+i, -angle); } } else { for ( i=0 ; i<9 ; i++ ) { m_object->SetPartRotationZ( 1+i, 0.0f); m_object->SetPartRotationZ(10+i, 0.0f); } m_channelSound = m_sound->Play(SOUND_FACTORY, m_object->GetPosition(), 0.0f, 1.0f, true); m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE); m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 11.0f, SOPER_CONTINUE); m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP); m_phase = AFP_BUILD; m_progress = 0.0f; m_speed = 1.0f/15.0f; } } if ( m_phase == AFP_BUILD ) { if ( m_progress == 0.0f ) { if ( !CreateVehicle() ) { cargo = SearchCargo(); // transform metal? if ( cargo != nullptr ) { cargo->SetLock(false); // metal usable again } if ( m_channelSound != -1 ) { m_sound->FlushEnvelope(m_channelSound); m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP); m_channelSound = -1; } m_phase = AFP_OPEN_T; m_progress = 0.0f; m_speed = 1.0f/2.0f; return true; } } if ( m_progress < 1.0f ) { if ( m_type == OBJECT_MOBILErt || m_type == OBJECT_MOBILErc || m_type == OBJECT_MOBILErr || m_type == OBJECT_MOBILErs ) { prog = 1.0f-m_progress*1.5f; if ( prog < 0.0f ) prog = 0.0f; } else { prog = 1.0f-m_progress; } angle = powf(prog*10.0f, 2.0f)+m_object->GetRotationY(); vehicle = SearchVehicle(); if ( vehicle != nullptr ) { vehicle->SetRotationY(angle+Math::PI); vehicle->SetScale(m_progress); } cargo = SearchCargo(); // transform metal? if ( cargo != nullptr ) { cargo->SetScale(1.0f-m_progress); } if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time ) { m_lastParticle = m_time; mat = m_object->GetWorldMatrix(0); pos = Math::Vector(-12.0f, 20.0f, -4.0f); // position of chimney pos = Math::Transform(*mat, pos); pos.y += 2.0f; pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f; speed.x = 0.0f; speed.z = 0.0f; speed.y = 6.0f+Math::Rand()*6.0f; dim.x = Math::Rand()*1.5f+1.0f; dim.y = dim.x; m_particle->CreateParticle(pos, speed, dim, Gfx::PARTISMOKE3, 4.0f); } } else { m_main->DisplayError(INFO_FACTORY, m_object); SoundManip(2.0f, 1.0f, 1.2f); cargo = SearchCargo(); // transform metal? if ( cargo != nullptr ) { CObjectManager::GetInstancePointer()->DeleteObject(cargo); } vehicle = SearchVehicle(); if ( vehicle != nullptr ) { assert(vehicle->Implements(ObjectInterfaceType::Movable)); physics = dynamic_cast<CMovableObject*>(vehicle)->GetPhysics(); physics->SetFreeze(false); // can move vehicle->SetLock(false); // vehicle useable vehicle->SetRotationY(m_object->GetRotationY()+Math::PI); vehicle->SetScale(1.0f); if ( !m_program.empty() ) { if (vehicle->Implements(ObjectInterfaceType::Programmable) && vehicle->Implements(ObjectInterfaceType::ProgramStorage)) { Program* program = dynamic_cast<CProgramStorageObject*>(vehicle)->AddProgram(); if (boost::regex_search(m_program, boost::regex("^[A-Za-z0-9_]+$"))) // Public function name? { std::string code = "extern void object::Start_"+m_program+"()\n{\n\t\n\t//Automatically generated by object.factory()\n\t"+m_program+"();\n\t\n}\n"; program->script->SendScript(code.c_str()); } else if (boost::regex_search(m_program, boost::regex("\\.txt$"))) // File name (with .txt extension)? { program->script->ReadScript(m_program.c_str()); } else // Program code? { program->script->SendScript(m_program.c_str()); } dynamic_cast<CProgrammableObject*>(vehicle)->RunProgram(program); } } } m_main->CreateShortcuts(); m_phase = AFP_OPEN_T; m_progress = 0.0f; m_speed = 1.0f/2.0f; } } if ( m_phase == AFP_OPEN_T ) { if ( m_progress < 1.0f ) { for ( i=0 ; i<9 ; i++ ) { angle = -(1.0f-m_progress)*(Math::PI/2.0f)+Math::PI/2.0f; m_object->SetPartRotationZ( 1+i, angle); m_object->SetPartRotationZ(10+i, -angle); } if ( m_lastParticle+m_engine->ParticleAdapt(0.1f) <= m_time ) { m_lastParticle = m_time; pos = m_cargoPos; pos.x += (Math::Rand()-0.5f)*10.0f; pos.z += (Math::Rand()-0.5f)*10.0f; pos.y += Math::Rand()*10.0f; speed = Math::Vector(0.0f, 0.0f, 0.0f); dim.x = 2.0f; dim.y = dim.x; m_particle->CreateParticle(pos, speed, dim, Gfx::PARTIGLINT, 2.0f, 0.0f, 0.0f); } } else { for ( i=0 ; i<9 ; i++ ) { m_object->SetPartRotationZ( 1+i, Math::PI/2.0f); m_object->SetPartRotationZ(10+i, -Math::PI/2.0f); } SoundManip(3.0f, 1.0f, 0.5f); m_phase = AFP_OPEN_S; m_progress = 0.0f; m_speed = 1.0f/3.0f; } } if ( m_phase == AFP_OPEN_S ) { if ( m_progress < 1.0f ) { for ( i=0 ; i<9 ; i++ ) { zoom = 0.30f+((1.0f-m_progress)-0.5f+i/16.0f)*2.0f*0.70f; if ( zoom < 0.30f ) zoom = 0.30f; if ( zoom > 1.00f ) zoom = 1.00f; m_object->SetPartScaleZ( 1+i, zoom); m_object->SetPartScaleZ(10+i, zoom); } if ( m_lastParticle+m_engine->ParticleAdapt(0.1f) <= m_time ) { m_lastParticle = m_time; pos = m_cargoPos; pos.x += (Math::Rand()-0.5f)*10.0f; pos.z += (Math::Rand()-0.5f)*10.0f; pos.y += Math::Rand()*10.0f; speed = Math::Vector(0.0f, 0.0f, 0.0f); dim.x = 2.0f; dim.y = dim.x; m_particle->CreateParticle(pos, speed, dim, Gfx::PARTIGLINT, 2.0f, 0.0f, 0.0f); } } else { for ( i=0 ; i<9 ; i++ ) { m_object->SetPartScaleZ( 1+i, 0.30f); m_object->SetPartScaleZ(10+i, 0.30f); } SetBusy(false); UpdateInterface(); m_phase = AFP_WAIT; m_progress = 0.0f; m_speed = 1.0f/2.0f; } } return true; }