bool CoreScript::IsSquaddieOnMission(int chitID, int* squadID, Vector2I* wantToConquer) { if (!CitizenFilter(chitID)) { return false; } for (int i = 0; i < MAX_SQUADS; ++i) { if (squads[i].Find(chitID) >= 0) { if (squadID) { *squadID = i; } if (wantToConquer) { wantToConquer->Zero(); if (!waypoints[i].Empty()) { Vector2I waypoint2i = waypoints[i][waypoints[i].Size() - 1]; Vector2I waypointSector = ToSector(waypoint2i); const SectorData& sd = Context()->worldMap->GetSectorData(waypointSector); if (sd.CoreLoc() == waypoint2i) { *wantToConquer = waypointSector; } } } Chit* chit = Context()->chitBag->GetChit(chitID); return !waypoints[i].Empty() || (ToSector(chit->Position()) != ToSector(ParentChit()->Position())); } } return false; }
void CoreScript::OnChitMsg(Chit* chit, const ChitMsg& msg) { // Logic split between Sim::OnChitMsg and CoreScript::OnChitMsg if (msg.ID() == ChitMsg::CHIT_DESTROYED && (chit == parentChit)) { while (!citizens.Empty()) { int citizenID = citizens.Pop(); Chit* citizen = Context()->chitBag->GetChit(citizenID); if (citizen && citizen->GetItem()) { // Set to rogue team. citizen->GetItem()->SetRogue(); } } Vector2I pos2i = ToWorld2I(chit->Position()); Vector2I sector = ToSector(pos2i); if (Team::Instance()->IsController(chit->Team())) { NewsEvent news(NewsEvent::SUPERTEAM_DELETED, ToWorld2F(pos2i), chit->GetItemID(), 0); Context()->chitBag->GetNewsHistory()->Add(news); } int controllerTeam = 0; if (Team::Instance()->IsControlled(chit->Team(), &controllerTeam)) { CoreScript* controller = CoreScript::GetCoreFromTeam(controllerTeam); GLASSERT(controller); if (controller) { NewsEvent news(NewsEvent::SUBTEAM_DELETED, ToWorld2F(pos2i), chit->GetItemID(), controller->ParentChit()->GetItemID()); Context()->chitBag->GetNewsHistory()->Add(news); } } int deleterID = chit->GetItemComponent() ? chit->GetItemComponent()->LastDamageID() : 0; Chit* deleter = Context()->chitBag->GetChit(deleterID); int superTeam = 0; if (deleter && (deleter->Team() == Team::Instance()->SuperTeam(deleter->Team())) && Team::IsDenizen(deleter->Team()) && Team::IsDenizen(chit->Team())) { superTeam = deleter->Team(); } if (chit->Team() != TEAM_NEUTRAL) { if (superTeam) { LumosChitBag::CreateCoreData data = { sector, true, chit->Team(), deleter ? deleter->Team() : 0 }; Context()->chitBag->coreCreateList.Push(data); } else { LumosChitBag::CreateCoreData data = { sector, false, chit->Team(), deleter ? deleter->Team() : 0 }; Context()->chitBag->coreCreateList.Push(data); } } else { // Neutral cores are taken over by wandering over them // with enough friend units to have critical mass. LumosChitBag::CreateCoreData data = { sector, false, 0, 0 }; Context()->chitBag->coreCreateList.Push(data); } Team::Instance()->CoreDestroyed(parentChit->Team()); } }
int CoreScript::Citizens(CChitArray* arr) { int i=0; while (i < citizens.Size()) { int id = citizens[i]; Chit* chit = CitizenFilter(id); if (chit) { // check for team change, throw out of citizens. if (arr) arr->Push(chit); ++i; } else { // Dead and gone. citizens.SwapRemove(i); // Reset the timer so that there is a little time // between a dead citizen and re-spawn spawnTick.Reset(); } } #if 0 // This is annoying: seeing if cranking down the spawn rate and not // destroying the sleep tube achieves success. // Also, destroy a sleeptube, so it costs something to replace, and towns can fall. if ( sc ) { Vector2F pos2 = sc->GetPosition2D(); Vector2I sector = ToSector( ToWorld2I( pos2 )); Chit* bed = scriptContext->chitBag->FindBuilding( ISC::bed, sector, &pos2, LumosChitBag::RANDOM_NEAR, 0, 0 ); if ( bed && bed->GetItem() ) { bed->GetItem()->hp = 0; bed->SetTickNeeded(); } } #endif return citizens.Size(); }
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; }
int CameraComponent::DoTick(U32 delta) { float EASE = 0.2f; switch (mode) { case PAN: { Vector3F d = (dest - camera->PosWC()); Vector3F c = camera->PosWC(); if (d.Length() < 0.01f) { camera->SetPosWC(dest.x, dest.y, dest.z); mode = DONE; } else { camera->SetPosWC(c.x + EASE*d.x, c.y + EASE*d.y, c.z + EASE*d.z); } } break; case TRACK: { Chit* chit = Context()->chitBag->GetChit(targetChitID); if (chit) { Vector3F pos = chit->Position(); pos.y = 0; // Scoot the camera to always focus on the target. Removes // errors that occur from rotation, drift, etc. const Vector3F* eye3 = camera->EyeDir3(); Vector3F at; int result = IntersectRayPlane(camera->PosWC(), eye3[0], 1, 0.0f, &at); if (result == INTERSECT) { Vector3F t = (camera->PosWC() - at); //camera->SetPosWC( pos + t ); Vector3F c = camera->PosWC(); Vector3F d = (pos + t) - c; // If grid moving, the EASE contributes to jitter. if (GET_SUB_COMPONENT(chit, MoveComponent, GridMoveComponent)) { EASE = 1.0f; } camera->SetPosWC(c.x + EASE*d.x, pos.y + t.y, c.z + EASE*d.z); } } } break; case DONE: break; default: GLASSERT(0); } return 0; }
Chit* CoreScript::CitizenFilter(int chitID) { Chit* chit = Context()->chitBag->GetChit(chitID); if (chit && (chit->Team() == parentChit->Team())) { return chit; } return 0; }
Chit* LumosChitBag::NewGoldChit( const grinliz::Vector3F& pos, Wallet* src ) { GLASSERT(src); if (src->Gold() == 0) return 0; const ChitContext* context = Context(); Vector2F v2 = { pos.x, pos.z }; ItemNameFilter goldFilter( ISC::gold); this->QuerySpatialHash( &chitList, v2, 1.0f, 0, &goldFilter ); Chit* chit = 0; // Evil bug this: adding gold to a wallet just before // deletion. I'm a little concerned where else // this could be a problem. Would be nice to make // deletion immediate. for (int i = 0; i < chitList.Size(); ++i) { Chit* c = chitList[i]; if (c && !IsQueuedForDelete(c) && c->GetWallet() && !c->GetWallet()->Closed()) { chit = chitList[i]; break; } } if ( !chit ) { chit = this->NewChit(); AddItem( "gold", chit, context->engine, 0, 0 ); chit->Add( new RenderComponent( chit->GetItem()->ResourceName() )); chit->SetPosition( pos ); chit->Add(new GameMoveComponent()); } chit->GetWallet()->Deposit(src, src->Gold()); return chit; }
int CoreScript::CorePower() { int power = 0; for (int i = 0; i < citizens.Size(); ++i) { Chit* chit = Context()->chitBag->GetChit(citizens[i]); if (chit && chit->GetItemComponent()) { power += chit->GetItemComponent()->PowerRating(true); } } return power; }
CameraComponent* LumosChitBag::GetCamera() const { Chit* chit = GetNamedChit(ISC::Camera); if (chit) { GLASSERT(chit); CameraComponent* cc = (CameraComponent*) chit->GetComponent("CameraComponent"); GLASSERT(cc); return cc; } return 0; }
bool CoreScript::IsCitizenItemID(int id) { for (int i = 0; i < citizens.Size(); ++i) { int citizenID = citizens[i]; Chit* chit = CitizenFilter(citizenID); if (chit && chit->GetItemID() == id) { return true; } } return false; }
void CoreScript::NewWaypointChits(int id) { for (int i = 0; i < waypoints[id].Size(); ++i) { Vector2I v = waypoints[id][i]; Chit* chit = Context()->chitBag->NewChit(); chit->Add(new RenderComponent("flag")); FlagScript* flagScript = new FlagScript(); flagScript->Attach(ToSector(parentChit->Position()), id); chit->Add(flagScript); chit->SetPosition(ToWorld3F(v)); } }
Chit* CoreScript::PrimeCitizen() { for (int i = 0; i < citizens.Size(); ++i) { int id = citizens[i]; Chit* chit = CitizenFilter(id); if (chit && chit->GetItem()) { if (chit->GetItem()->keyValues.Has(ISC::prime)) { return chit; } } } return 0; }
void CoreScript::RemoveFlag(const Vector2I& pos) { Flag f = { pos, 0 }; int i = flags.Find(f); if (i >= 0) { if (flags[i].chitID) { Chit* chit = Context()->chitBag->GetChit(flags[i].chitID); if (chit) { chit->QueueDelete(); } flags[i].chitID = 0; } flags.Remove(i); } }
void LumosChitBag::HandleBolt( const Bolt& bolt, const ModelVoxel& mv ) { const ChitContext* context = Context(); Chit* chitShooter = GetChit( bolt.chitID ); // may be null int shooterTeam = -1; if ( chitShooter && chitShooter->GetItemComponent() ) { shooterTeam = chitShooter->GetItemComponent()->GetItem()->Team(); } int explosive = bolt.effect & GameItem::EFFECT_EXPLOSIVE; if ( !explosive ) { if ( mv.Hit() ) { Chit* chitHit = mv.ModelHit() ? mv.model->userData : 0; DamageDesc dd( bolt.damage, bolt.effect ); if ( chitHit ) { GLASSERT( GetChit( chitHit->ID() ) == chitHit ); if ( chitHit->GetItemComponent() && chitHit->GetItemComponent()->GetItem()->Team() == shooterTeam ) { // do nothing. don't shoot own team. } else { ChitDamageInfo info( dd ); info.originID = bolt.chitID; info.awardXP = true; info.isMelee = false; info.isExplosion = false; info.originOfImpact = mv.at; ChitMsg msg( ChitMsg::CHIT_DAMAGE, 0, &info ); chitHit->SendMessage( msg, 0 ); } } else if ( mv.VoxelHit() ) { context->worldMap->VoxelHit( mv.voxel, dd ); } } } else { // How it used to work. Now only uses radius: // Here don't worry about the chit hit. Just ray cast to see // who is in range of the explosion and takes damage. // Back up the origin of the bolt just a bit, so it doesn't keep // intersecting the model it hit. Then do ray checks around to // see what gets hit by the explosion. float rewind = Min( 0.1f, 0.5f*bolt.len ); GLASSERT( Equal( bolt.dir.Length(), 1.f, 0.001f )); Vector3F origin = mv.at - bolt.dir * rewind; DamageDesc dd( bolt.damage, bolt.effect ); BattleMechanics::GenerateExplosion( dd, origin, bolt.chitID, context->engine, this, context->worldMap ); } }
bool CoreScript::SquadAtRest(int squadID) { GLASSERT(squadID >= 0 && squadID < MAX_SQUADS); if (!waypoints[squadID].Empty()) { return false; } Vector2I sector = ToSector(ParentChit()->Position()); for (int i = 0; i < squads[squadID].Size(); ++i) { int chitID = squads[squadID][i]; Chit* chit = Context()->chitBag->GetChit(chitID); if (chit && ToSector(chit->Position()) != sector) { return false; } } return true; }
void CoreScript::AddFlag(const Vector2I& _pos) { Vector2I pos = _pos; // A little UI fixup: set the flag to a porch // if we click on the switch. Chit* building = Context()->chitBag->QueryBuilding(IString(), pos, 0); if (building && (building->GetItem()->IName() == ISC::switchOn || building->GetItem()->IName() == ISC::switchOff)) { MapSpatialComponent* msc = GET_SUB_COMPONENT(building, SpatialComponent, MapSpatialComponent); if (msc) { pos = msc->PorchPos().min; } } Flag f = { pos, 0 }; if (flags.Find(f) < 0) { Chit* chit = Context()->chitBag->NewChit(); RenderComponent* rc = new RenderComponent("flag"); chit->Add(rc); ProcRenderInfo info; AssignProcedural(ISC::team, false, ParentChit()->GetItem()->ID(), ParentChit()->Team(), false, 0, 0, &info); rc->SetProcedural(0, info); chit->SetPosition(ToWorld3F(pos)); f.chitID = chit->ID(); flags.Push(f); } }
Chit* LumosChitBag::NewVisitor( int visitorIndex, const Web& web) { const ChitContext* context = Context(); if (web.Empty()) return 0; Vector2I startSector = { NUM_SECTORS / 2, NUM_SECTORS / 2 }; CoreScript* cs = CoreScript::GetCore(startSector); if (!cs) return 0; // cores get deleted, web is cached, etc. Vector3F pos = cs->ParentChit()->Position(); Chit* chit = NewChit(); const GameItem& rootItem = ItemDefDB::Instance()->Get( "visitor" ); chit->Add( new RenderComponent( rootItem.ResourceName() )); AIComponent* ai = new AIComponent(); chit->Add( ai ); GLASSERT( visitorIndex >= 0 && visitorIndex < Visitors::NUM_VISITORS ); ai->SetVisitorIndex( visitorIndex ); Visitors::Instance()->visitorData[visitorIndex].Connect(); // initialize. // Visitors start at world center, with gridMove, and go from there. chit->SetPosition( pos ); PathMoveComponent* pmc = new PathMoveComponent(); chit->Add(pmc); AddItem( rootItem.Name(), chit, context->engine, TEAM_VISITOR, 0 ); chit->Add( new HealthComponent()); //chit->Add( new VisitorStateComponent()); return chit; }
bool CoreScript::RecruitNeutral() { Vector2I sector = ToSector(parentChit->Position()); Rectangle2I inner = InnerSectorBounds(sector); MOBKeyFilter filter; filter.value = ISC::denizen; CChitArray arr; Context()->chitBag->QuerySpatialHash(&arr, ToWorld2F(inner), 0, &filter); for (int i = 0; i < arr.Size(); ++i) { Chit* chit = arr[i]; if (Team::Instance()->GetRelationship(chit, parentChit) != ERelate::ENEMY) { if (this->IsCitizen(chit)) continue; if (!chit->GetItem()) continue; if (Team::IsRogue(chit->Team())) { // ronin! denizen without a core. this->AddCitizen( chit ); GLASSERT(chit->GetItem()->Significant()); NewsEvent news(NewsEvent::ROGUE_DENIZEN_JOINS_TEAM, ToWorld2F(chit->Position()), chit->GetItemID(), 0); Context()->chitBag->GetNewsHistory()->Add(news); return true; } } } return false; }
SectorPort Visitors::ChooseDestination(int index, const Web& web, ChitBag* chitBag, WorldMap* map ) { GLASSERT( instance ); GLASSERT( index >=0 && index <NUM_VISITORS ); VisitorData* visitor = &visitorData[index]; Chit* visitorChit = chitBag->GetChit(visitor->id); SectorPort sectorPort; if (!visitorChit) return sectorPort; Vector2I thisSector = ToSector(visitorChit->Position()); const MinSpanTree::Node* node = web.FindNode(thisSector); if (!node || node->firstChild == 0) return sectorPort; int nChildren = web.CountChildren(*node); int which = random.Rand(nChildren); const MinSpanTree::Node* child = web.ChildNode(*node, which); Vector2I sector = child->pos; const SectorData& sd = map->GetSectorData( sector ); GLASSERT(sd.ports); if (!sd.ports) return sectorPort; int ports[4] = { 1, 2, 4, 8 }; int port = 0; random.ShuffleArray( ports, 4 ); for( int i=0; i<4; ++i ) { if ( sd.ports & ports[i] ) { port = ports[i]; break; } } sectorPort.sector = sector; sectorPort.port = port; return sectorPort; }
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; } } } }
void CoreScript::SetWaypoints(int squadID, const grinliz::Vector2I& dest) { GLASSERT(squadID >= 0 && squadID < MAX_SQUADS); waypoints[squadID].Clear(); if (dest.IsZero()) { return; } // Use the first chit to choose the starting location: bool startInSameSector = true; Vector2I startSector = { 0, 0 }; CChitArray chitArr; Squaddies(squadID, &chitArr); if (chitArr.Empty()) return; for (int i = 0; i<chitArr.Size(); ++i) { Chit* chit = chitArr[i]; if (startSector.IsZero()) startSector = ToSector(chit->Position()); else if (startSector != ToSector(chit->Position())) startInSameSector = false; } Vector2I destSector = ToSector(dest); // - Current port // - grid travel (implies both sector and target port) // - dest port (regroup) // - destination GLOUTPUT(("SetWaypoints: #chits=%d squadID=%d:", chitArr.Size(), squadID)); if (startSector != destSector) { Chit* chit = chitArr[0]; SectorPort sectorPort; if (startInSameSector) { // All together, so meet at the STARTING port. sectorPort = Context()->worldMap->NearestPort(ToWorld2F(chit->Position()), &ToWorld2F(dest)); } else { // Dispersed; meet at the DESTINATION port. sectorPort = Context()->worldMap->NearestPort(ToWorld2F(dest), &ToWorld2F(chit->Position())); } if (!sectorPort.IsValid()) { GLOUTPUT(("SetWaypoints: no path.\n")); return; } SectorData sectorData = Context()->worldMap->GetSectorData(sectorPort.sector); Vector2I p0 = sectorData.GetPortLoc(sectorPort.port).Center(); waypoints[squadID].Push(p0); GLOUTPUT(("%d,%d [s%c%d] ", p0.x, p0.y, 'A' + p0.x / SECTOR_SIZE, 1 + p0.y / SECTOR_SIZE)); } GLOUTPUT(("%d,%d [s%c%d]\n", dest.x, dest.y, 'A' + dest.x/SECTOR_SIZE, 1 + dest.y/SECTOR_SIZE)); waypoints[squadID].Push(dest); NewWaypointChits(squadID); }
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; }
Chit* LumosChitBag::NewItemChit( const grinliz::Vector3F& _pos, GameItem* orphanItem, bool fuzz, bool onGround, int selfDestructTimer ) { GLASSERT( !orphanItem->Intrinsic() ); GLASSERT( !orphanItem->IResourceName().empty() ); Vector3F pos = _pos; if ( fuzz ) { pos.x = floorf(pos.x) + random.Uniform(); pos.z = floorf(pos.z) + random.Uniform(); } Chit* chit = this->NewChit(); chit->Add( new ItemComponent( orphanItem )); chit->Add( new RenderComponent( orphanItem->ResourceName() )); chit->Add(new GameMoveComponent()); if ( onGround ) { const ModelResource* res = chit->GetRenderComponent()->MainResource(); Rectangle3F aabb = res->AABB(); pos.y = -aabb.min.y; if ( aabb.SizeY() < 0.1f ) { pos.y += 0.1f; } } chit->SetPosition( pos ); chit->Add( new HealthComponent()); if (!selfDestructTimer && orphanItem->keyValues.Has(ISC::selfDestruct)) { orphanItem->keyValues.Get("selfDestruct", &selfDestructTimer); selfDestructTimer *= 1000; } if ( selfDestructTimer ) { chit->Add( new CountDownScript( selfDestructTimer )); } return chit; }
Chit* LumosChitBag::NewLawnOrnament(const Vector2I& pos, const char* name, int team) { const ChitContext* context = Context(); Chit* chit = NewChit(); GameItem* rootItem = ItemDefDB::Instance()->Get(name).Clone(); // Hack...how to do this better?? if (rootItem->IResourceName() == "ruins1.0") { CStr<32> str; str.Format("ruins1.%d", random.Rand(2)); rootItem->SetResource(str.c_str()); } int size = 1; rootItem->keyValues.Get(ISC::size, &size); MapSpatialComponent* msc = new MapSpatialComponent(); msc->SetBuilding(size, false, 0); msc->SetBlocks((rootItem->flags & GameItem::PATH_NON_BLOCKING) ? false : true); chit->Add(msc); MapSpatialComponent::SetMapPosition(chit, pos.x, pos.y); chit->Add(new RenderComponent(rootItem->ResourceName())); chit->Add(new HealthComponent()); AddItem(rootItem, chit, context->engine, team, 0); IString proc = rootItem->keyValues.GetIString("procedural"); if (!proc.empty()) { ProcRenderInfo info; AssignProcedural(chit->GetItem(), &info); chit->GetRenderComponent()->SetProcedural(0, info); } context->engine->particleSystem->EmitPD(ISC::constructiondone, ToWorld3F(pos), V3F_UP, 0); if (XenoAudio::Instance()) { Vector3F pos3 = ToWorld3F(pos); XenoAudio::Instance()->PlayVariation(ISC::rezWAV, random.Rand(), &pos3); } return chit; }
Chit* LumosChitBag::NewWorkerChit( const Vector3F& pos, int team ) { const ChitContext* context = Context(); Chit* chit = NewChit(); const GameItem& rootItem = ItemDefDB::Instance()->Get( "worker" ); chit->Add( new RenderComponent( rootItem.ResourceName() )); chit->Add( new PathMoveComponent()); chit->Add( new AIComponent()); chit->SetPosition( pos ); AddItem( rootItem.Name(), chit, context->engine, team, 0 ); chit->Add( new HealthComponent()); //chit->Add( new DebugStateComponent()); if (XenoAudio::Instance()) { XenoAudio::Instance()->PlayVariation(ISC::rezWAV, random.Rand(), &pos); } return chit; }
Chit* LumosChitBag::NewWildFruit(const grinliz::Vector2I& pos) { Vector3F pos3 = ToWorld3F(pos); pos3.x = floorf(pos3.x) + random.Uniform(); pos3.z = floorf(pos3.z) + random.Uniform(); const GameItem& root = ItemDefDB::Instance()->Get("fruit"); GameItem* item = root.Clone(); item->SetProperName(ISC::wildFruit); Chit* chit = this->NewChit(); chit->Add(new ItemComponent(item)); chit->Add(new RenderComponent(item->ResourceName())); chit->Add(new GameMoveComponent()); chit->Add(new HealthComponent()); chit->SetPosition(pos3); return chit; }
Chit* LumosChitBag::NewCrystalChit( const grinliz::Vector3F& _pos, Wallet* src, bool fuzz ) { Vector3F pos = _pos; if ( fuzz ) { pos.x = floorf(_pos.x) + random.Uniform(); pos.z = floorf(_pos.z) + random.Uniform(); } int crystal = -1; for (int i = 0; i < NUM_CRYSTAL_TYPES; ++i) { if (src->Crystal(i)) { crystal = i; break; } } if (crystal == -1) return 0; // done const char* name = 0; switch ( crystal ) { case CRYSTAL_GREEN: name="crystal_green"; break; case CRYSTAL_RED: name="crystal_red"; break; case CRYSTAL_BLUE: name="crystal_blue"; break; case CRYSTAL_VIOLET: name="crystal_violet"; break; } const ChitContext* context = Context(); Chit* chit = this->NewChit(); AddItem( name, chit, context->engine, 0, 0 ); chit->Add( new RenderComponent( chit->GetItem()->ResourceName() )); chit->Add(new GameMoveComponent()); chit->SetPosition( pos ); int c[NUM_CRYSTAL_TYPES] = { 0 }; c[crystal] = 1; chit->GetWallet()->Deposit(src, 0, c); return chit; }
void CoreScript::AssignToSquads() { // First, how many do we actually have? // Filter out everyone that has gone away. for (int i = 0; i < MAX_SQUADS; ++i) { //GL_ARRAY_FILTER(squads[i], (this->IsCitizen(ele))); squads[i].Filter(this, [](CoreScript* cs, int id) { return cs->IsCitizen(id); }); if (squads[i].Empty()) { // Flush out dead squads so they don't have // control flags laying around. waypoints[i].Clear(); } } int nSquaddies = 0; for (int i = 0; i < MAX_SQUADS; ++i) { nSquaddies += squads[i].Size(); } CChitArray recruits; int nCitizens = Citizens(&recruits); int nExpected = nCitizens - CITIZEN_BASE; if (nSquaddies >= nExpected) return; struct FilterData { CoreScript* cs; Chit* avatar;; }; FilterData fd = { this, Context()->chitBag->GetAvatar() }; // Filter to: not in squad AND not player controlled recruits.Filter(fd, [](const FilterData& ffd, Chit* chit) { return (ffd.cs->SquadID(chit->ID()) < 0 && chit != ffd.avatar); }); // Sort the best recruits to the end. // FIXME: better if there was a (working) power approximation recruits.Sort([](Chit* a, Chit* b) { const GameItem* itemA = a->GetItem(); const GameItem* itemB = b->GetItem(); int scoreA = itemA->Traits().Level() * (itemA->GetPersonality().Fighting() == Personality::LIKES ? 2 : 1); int scoreB = itemB->Traits().Level() * (itemB->GetPersonality().Fighting() == Personality::LIKES ? 2 : 1); // Reverse order. Best at end. return scoreA > scoreB; }); for (int n = nExpected - nSquaddies; n > 0; --n) { for (int i = 0; i < MAX_SQUADS; ++i) { if ( (squads[i].Size() < SQUAD_SIZE) && SquadAtRest(i)) { Chit* chit = recruits.Pop(); squads[i].Push(chit->ID()); ++nSquaddies; break; } } } }
void FluidTestScene::Tap3D(const grinliz::Vector2F& view, const grinliz::Ray& world) { Vector3F at = { 0, 0, 0 }; float t = 0; int result = IntersectRayAAPlane(world.origin, world.direction, 1, 0, &at, &t); if (result == INTERSECT) { Vector2I pos2i = ToWorld2I(at); Vector2I sector = { 0, 0 }; CircuitSim* circuitSim = context.physicsSims->GetCircuitSim(sector); if (context.worldMap->Bounds().Contains(pos2i)) { bool trigger = false; if (!buildButton[BUTTON_DELETE].Down() && !buildButton[BUTTON_ROTATE].Down()) { Chit* building = context.chitBag->QueryPorch(pos2i); if (!building) { building = context.chitBag->QueryBuilding(IString(), pos2i, 0); } if (building) { if (building->GetItem()->IName() == ISC::detector) { circuitSim->TriggerDetector(pos2i); trigger = true; } else if (building->GetItem()->IName() == ISC::switchOn || building->GetItem()->IName() == ISC::switchOff) { circuitSim->TriggerSwitch(pos2i); trigger = true; } } } int id = -1; if (!trigger) { for (int i = 0; i < NUM_BUTTONS; ++i) { if (buildButton[i].Down()) { id = i; break; } } } if (id >= 0) { Chit* chit = 0; switch (id) { case BUTTON_ROCK0: case BUTTON_ROCK1: case BUTTON_ROCK2: case BUTTON_ROCK3: context.worldMap->SetRock(pos2i.x, pos2i.y, id - BUTTON_ROCK0, false, WorldGrid::ROCK); break; case BUTTON_SWITCH_ON: chit = context.chitBag->NewBuilding(pos2i, "switchOn", TEAM_HOUSE); break; case BUTTON_SWITCH_OFF: chit = context.chitBag->NewBuilding(pos2i, "switchOff", TEAM_HOUSE); break; case BUTTON_TEMPLE: chit = context.chitBag->NewBuilding(pos2i, "temple", TEAM_HOUSE); break; case BUTTON_GATE: chit = context.chitBag->NewBuilding(pos2i, "gate", TEAM_HOUSE); break; case BUTTON_TIMED_GATE: chit = context.chitBag->NewBuilding(pos2i, "timedGate", TEAM_HOUSE); break; case BUTTON_DETECTOR: chit = context.chitBag->NewBuilding(pos2i, "detector", TEAM_HOUSE); break; case BUTTON_TURRET: chit = context.chitBag->NewBuilding(pos2i, "turret", TEAM_HOUSE); break; case BUTTON_DELETE: { Chit* building = context.chitBag->QueryBuilding(IString(), pos2i, 0); if (building) { building->QueueDelete(); } } break; case BUTTON_ROTATE: { Chit* building = context.chitBag->QueryBuilding(IString(), pos2i, 0); if (building) { Matrix4 m; building->Rotation().ToMatrix(&m); float r = m.CalcRotationAroundAxis(1); r = NormalizeAngleDegrees(r + 90.0f); building->SetRotation(Quaternion::MakeYRotation(r)); } } break; } if (chit) { MapSpatialComponent* msc = GET_SUB_COMPONENT(chit, SpatialComponent, MapSpatialComponent); if (msc) msc->SetNeedsCorePower(false); } } } } }
CoreScript* CoreScript::CreateCore( const Vector2I& sector, int team, const ChitContext* context) { // Destroy the existing core. // Create a new core, attached to the player. CoreScript* cs = CoreScript::GetCore(sector); if (cs) { Chit* core = cs->ParentChit(); GLASSERT(core); CDynArray< Chit* > queryArr; // Tell all the AIs the core is going away. ChitHasAIComponent filter; Rectangle2F b = ToWorld2F(InnerSectorBounds(sector)); context->chitBag->QuerySpatialHash(&queryArr, b, 0, &filter); for (int i = 0; i < queryArr.Size(); ++i) { queryArr[i]->GetAIComponent()->ClearTaskList(); } //context.chitBag->QueueDelete(core); // QueueDelete is safer, but all kinds of asserts fire (correctly) // if 2 cores are in the same place. This may cause an issue // if CreateCore is called during the DoTick() // Setting the hp to 0 and then calling DoTick() // is a sleazy trick to clean up. core->GetItem()->hp = 0; if (core->GetHealthComponent()) { core->GetHealthComponent()->DoTick(1); } context->chitBag->DeleteChit(core); } const SectorData& sd = context->worldMap->GetSectorData(sector); if (sd.HasCore()) { int group = 0, id = 0; Team::SplitID(team, &group, &id); // Lots of trouble with this code. Used to assert, // but always seemed to be another case. White list // groups that *can* take over a core. if (team == TEAM_NEUTRAL || team == TEAM_TROLL || Team::IsDeity(team) || Team::IsDenizen(team)) { // Okay! take over. GLASSERT(!Team::IsDenizen(team) || id); // make sure rogues got filtered out. } else { team = group = id = 0; } Chit* chit = context->chitBag->NewBuilding(sd.core, "core", team); // 'in use' instead of blocking. MapSpatialComponent* ms = GET_SUB_COMPONENT(chit, SpatialComponent, MapSpatialComponent); GLASSERT(ms); ms->SetBlocks(false); CoreScript* cs = new CoreScript(); chit->Add(cs); GLASSERT(CoreScript::GetCore(ToSector(sd.core)) == cs); if (Team::IsDeity(team)) chit->GetItem()->SetProperName(Team::Instance()->TeamName(team)); else chit->GetItem()->SetProperName(sd.name); if (team != TEAM_NEUTRAL) { chit->GetItem()->SetSignificant(context->chitBag->GetNewsHistory(), ToWorld2F(chit->Position()), NewsEvent::DOMAIN_CREATED, NewsEvent::DOMAIN_DESTROYED, 0); // Make the dwellers defend the core. chit->Add(new GuardScript()); // Make all buildings to be this team. CDynArray<Chit*> buildings; Vector2I buildingSector = ToSector(chit->Position()); context->chitBag->FindBuilding(IString(), buildingSector, 0, LumosChitBag::EFindMode::NEAREST, &buildings, 0); for (int i = 0; i < buildings.Size(); ++i) { Chit* c = buildings[i]; if (c->GetItem() && c->GetItem()->IName() != ISC::core) { c->GetItem()->SetTeam(team); } } } return cs; } return 0; }