Chit* LumosChitBag::FindBuilding( const grinliz::IString& name, const grinliz::Vector2I& sector, const grinliz::Vector2F* pos, LumosChitBag::EFindMode flags, CDynArray<Chit*>* arr, IChitAccept* filter ) { CDynArray<Chit*>& match = arr ? *arr : findMatch; // sleazy reference trick to point to either passed in or local. match.Clear(); findWeight.Clear(); for( MapSpatialComponent* it = mapSpatialHash[sector.y*NUM_SECTORS+sector.x]; it; it = it->nextBuilding ) { Chit* chit = it->ParentChit(); GLASSERT( chit ); if ( filter && !filter->Accept( chit )) { // if a filter, check it. continue; } const GameItem* item = chit->GetItem(); if ( item && ( name.empty() || item->IName() == name )) { // name, if empty, matches everything match.Push( chit ); } } // If we found nothing, or we don't care about the position, return early. // Else deal with choice / sorting / etc. below. if ( match.Empty() ) return 0; if ( !pos ) return match[0]; // NEAREST scans and finds the closest one. // RANDOM_NEAR chooses one at random, but weighted by the (inverse) of the distance if ( flags == EFindMode::NEAREST ) { float closest = ( ToWorld2F(match[0]->Position()) - *pos ).LengthSquared(); int ci = 0; for( int i=1; i<match.Size(); ++i ) { float len2 = ( ToWorld2F(match[i]->Position()) - *pos ).LengthSquared(); if ( len2 < closest ) { closest = len2; ci = i; } } return match[ci]; } if ( flags == EFindMode::RANDOM_NEAR ) { for( int i=0; i<match.Size(); ++i ) { float len = ( ToWorld2F(match[i]->Position()) - *pos ).Length(); if (len < 1) len = 1; findWeight.Push( 1.0f/len ); } int index = random.Select( findWeight.Mem(), findWeight.Size() ); return match[index]; } // Bad flag? Something didn't return? GLASSERT( 0 ); return 0; }
Chit* LumosChitBag::QueryPorch( const grinliz::Vector2I& pos ) { Vector2I sector = ToSector(pos); for( MapSpatialComponent* it = mapSpatialHash[SectorIndex(sector)]; it; it = it->nextBuilding ) { if ( it->PorchPos().Contains( pos )) { return it->ParentChit(); } } return 0; }
void LumosChitBag::BuildingCounts(const Vector2I& sector, int* counts, int n) { BuildScript buildScript; for( MapSpatialComponent* it = mapSpatialHash[sector.y*NUM_SECTORS+sector.x]; it; it = it->nextBuilding ) { Chit* chit = it->ParentChit(); GLASSERT( chit ); const GameItem* item = chit->GetItem(); if (!item) continue; const IString& name = item->IName(); int id = 0; if (!name.empty()) { buildScript.GetDataFromStructure(name, &id); if (id < n) { counts[id] += 1; } } } }
Chit* LumosChitBag::QueryBuilding( const IString& name, const grinliz::Rectangle2I& bounds, CChitArray* arr ) { GLASSERT( MAX_BUILDING_SIZE == 2 ); // else adjust logic Vector2I sector = ToSector( bounds.min ); for( MapSpatialComponent* it = mapSpatialHash[SectorIndex(sector)]; it; it = it->nextBuilding ) { if ( it->Bounds().Intersect( bounds )) { Chit* chit = it->ParentChit(); if (name.empty() || (chit->GetItem() && chit->GetItem()->IName() == name)) { if (!arr) { return chit; } if (arr->HasCap()) { arr->Push(chit); } } } } if (arr && !arr->Empty()) { return (*arr)[0]; } return 0; }