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; }
Chit* LumosChitBag::NewMonsterChit(const Vector3F& pos, const char* name, int team) { const ChitContext* context = Context(); Chit* chit = NewChit(); AddItem( name, chit, context->engine, team, 0 ); chit->Add( new RenderComponent( chit->GetItem()->ResourceName() )); chit->Add( new PathMoveComponent()); chit->Add( new AIComponent()); chit->SetPosition( pos ); chit->Add( new HealthComponent()); IString mob = chit->GetItem()->keyValues.GetIString(ISC::mob); if (ReserveBank::Instance()) { ReserveBank::Instance()->WithdrawMonster(chit->GetWallet(), mob == ISC::greater); } if (mob == ISC::greater) { // Mark this item as important with a destroyMsg: chit->GetItem()->SetSignificant(GetNewsHistory(), ToWorld2F(pos), NewsEvent::GREATER_MOB_CREATED, NewsEvent::GREATER_MOB_KILLED, 0); } chit->GetItem()->GetTraitsMutable()->Roll(chit->ID()); chit->GetItem()->FullHeal(); if (XenoAudio::Instance()) { XenoAudio::Instance()->PlayVariation(ISC::rezWAV, random.Rand(), &pos); } return chit; }
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; }
Chit* LumosChitBag::NewBadGuy(const grinliz::Vector2I& pos, const IString& name, const grinliz::IString& type, int team, int level ) { const ChitContext* context = Context(); Chit* chit = NewChit(); const GameItem& root = ItemDefDB::Instance()->Get(type.safe_str()); chit->Add( new RenderComponent(root.ResourceName())); chit->Add( new PathMoveComponent()); AddItem(root.Name(), chit, context->engine, team, level, 0, "human"); ReserveBank::Instance()->WithdrawMonster(chit->GetWallet(), true); chit->GetItem()->GetTraitsMutable()->Roll( random.Rand() ); chit->GetItem()->GetPersonalityMutable()->Roll( random.Rand(), &chit->GetItem()->Traits() ); chit->GetItem()->FullHeal(); chit->GetItem()->SetProperName(name); AIComponent* ai = new AIComponent(); chit->Add( ai ); chit->Add( new HealthComponent()); chit->SetPosition( (float)pos.x+0.5f, 0, (float)pos.y+0.5f ); for (int i = 0; i < ForgeScript::NUM_ITEM_TYPES; ++i) { ForgeScript::ForgeData forgeData; forgeData.type = i; forgeData.subType = 0; forgeData.tech = 3; forgeData.level = level; forgeData.team = team; int seed = random.Rand(); ForgeScript::BestSubItem(&forgeData, seed); TransactAmt cost; TransactAmt freeCreate; static const int CRYSTAL[NUM_CRYSTAL_TYPES] = { 3, 2, 1, 1 }; freeCreate.Set(0, CRYSTAL); GameItem* loot = ForgeScript::ForgeRandomItem(forgeData, freeCreate, &cost, seed, ReserveBank::GetWallet()); if (loot) { chit->GetItemComponent()->AddToInventory(loot); loot->SetSignificant(chit->Context()->chitBag->GetNewsHistory(), ToWorld2F(chit->Position()), NewsEvent::FORGED, NewsEvent::UN_FORGED, chit->GetItem()); } } chit->GetItem()->SetSignificant(GetNewsHistory(), ToWorld2F(pos), NewsEvent::DENIZEN_CREATED, NewsEvent::DENIZEN_KILLED, 0); if (XenoAudio::Instance()) { Vector3F pos3 = ToWorld3F(pos); XenoAudio::Instance()->PlayVariation(ISC::rezWAV, random.Rand(), &pos3); } return chit; }
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* LumosChitBag::NewDenizen( const grinliz::Vector2I& pos, int team ) { const ChitContext* context = Context(); IString itemName; switch (Team::Group(team)) { case TEAM_HOUSE: itemName = (random.Bit()) ? ISC::humanFemale : ISC::humanMale; break; case TEAM_GOB: itemName = ISC::gobman; break; case TEAM_KAMAKIRI: itemName = ISC::kamakiri; break; default: GLASSERT(0); break; } Chit* chit = NewChit(); const GameItem& root = ItemDefDB::Instance()->Get(itemName.safe_str()); chit->Add( new RenderComponent(root.ResourceName())); chit->Add( new PathMoveComponent()); const char* altName = 0; if (Team::Group(team) == TEAM_HOUSE) { altName = "human"; } AddItem(root.Name(), chit, context->engine, team, 0, 0, altName); ReserveBank::Instance()->WithdrawDenizen(chit->GetWallet()); chit->GetItem()->GetTraitsMutable()->Roll( random.Rand() ); chit->GetItem()->GetPersonalityMutable()->Roll( random.Rand(), &chit->GetItem()->Traits() ); chit->GetItem()->FullHeal(); IString nameGen = chit->GetItem()->keyValues.GetIString( "nameGen" ); if ( !nameGen.empty() ) { LumosChitBag* chitBag = chit->Context()->chitBag; if ( chitBag ) { chit->GetItem()->SetProperName(chitBag->NameGen(nameGen.c_str(), chit->ID())); } } AIComponent* ai = new AIComponent(); chit->Add( ai ); chit->Add( new HealthComponent()); chit->SetPosition( (float)pos.x+0.5f, 0, (float)pos.y+0.5f ); chit->GetItem()->SetSignificant(GetNewsHistory(), ToWorld2F(pos), NewsEvent::DENIZEN_CREATED, NewsEvent::DENIZEN_KILLED, 0); if (XenoAudio::Instance()) { Vector3F pos3 = ToWorld3F(pos); XenoAudio::Instance()->PlayVariation(ISC::rezWAV, random.Rand(), &pos3); } return chit; }
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::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::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::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::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; }
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; }
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; }
Chit* LumosChitBag::NewBuilding(const Vector2I& pos, const char* name, int team) { const ChitContext* context = Context(); Chit* chit = NewChit(); const GameItem& rootItem = ItemDefDB::Instance()->Get(name); GameItem* item = rootItem.Clone(); // Hack...how to do this better?? if (item->IResourceName() == "pyramid0") { CStr<32> str; str.Format("pyramid%d", random.Rand(3)); item->SetResource(str.c_str()); } if (item->IResourceName() == ISC::kiosk) { switch (random.Rand(4)) { case 0: item->SetResource("kiosk.n"); break; case 1: item->SetResource("kiosk.m"); break; case 2: item->SetResource("kiosk.s"); break; default:item->SetResource("kiosk.c"); break; } } int size = 1; rootItem.keyValues.Get(ISC::size, &size); int porch = 0; rootItem.keyValues.Get(ISC::porch, &porch); const int circuit = 0; // Should be pre-cleared. But recover from weird situations by clearing. // Note that water is a real problem. Rectangle2I r; r.Set(pos.x, pos.y, pos.x + size - 1, pos.y + size - 1); for (Rectangle2IIterator it(r); !it.Done(); it.Next()) { const WorldGrid& wg = context->worldMap->GetWorldGrid(it.Pos()); GLASSERT(wg.IsLand()); (void)wg; context->worldMap->SetRock(it.Pos().x, it.Pos().y, 0, false, 0); context->worldMap->SetPlant(it.Pos().x, it.Pos().y, 0, 0); } MapSpatialComponent* msc = new MapSpatialComponent(); msc->SetBuilding(size, porch != 0, circuit); msc->SetBlocks((rootItem.flags & GameItem::PATH_NON_BLOCKING) ? false : true); chit->Add(msc); MapSpatialComponent::SetMapPosition(chit, pos.x, pos.y); chit->Add(new RenderComponent(item->ResourceName())); chit->Add(new HealthComponent()); AddItem(item, chit, context->engine, team, 0); IString script = rootItem.keyValues.GetIString("script"); if (!script.empty()) { Component* s = ComponentFactory::Factory(script.c_str(), &chitContext); GLASSERT(s); chit->Add(s); } IString proc = rootItem.keyValues.GetIString("procedural"); if (!proc.empty()) { ProcRenderInfo info; AssignProcedural(chit->GetItem(), &info); chit->GetRenderComponent()->SetProcedural(0, info); } IString consumes = rootItem.keyValues.GetIString(ISC::zone); if (!consumes.empty()) { Component* s = ComponentFactory::Factory("EvalBuildingScript", &chitContext); GLASSERT(s); chit->Add(s); } IString nameGen = rootItem.keyValues.GetIString( "nameGen"); if ( !nameGen.empty() ) { IString p = Context()->chitBag->NameGen(nameGen.c_str(), chit->random.Rand()); chit->GetItem()->SetProperName( p ); } #if 0 // debugging SectorPort sp; sp.sector.Set( pos.x/SECTOR_SIZE, pos.y/SECTOR_SIZE ); sp.port = 1; worldMap->SetRandomPort( sp ); #endif 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; }