uint32 EquipImprove::cost(GameItem* item) { uint32 coststonenum=0; uint32 costmoney=100; uint32 money = m_owner->getMoney(MoneyType_Money); if(coststonenum != 0) { GameItem *stone = m_owner->m_pack_manager.m_commom_pack.getItemByBaseID(100001); CheckCondition(stone,ERR_STONE); CheckCondition(stone->getItemNumber()>coststonenum,ERR_STONE); } CheckCondition(money>=costmoney,ERR_MONEY); m_owner->subMoney(MoneyType_Money,costmoney,DelMoneyAction_EquipImprove); if(coststonenum != 0) { m_owner->m_pack_manager.reduceItemNumByBaseID(100001,coststonenum,DelItemAction_Improve); } return ERR_SUCCESS; }
void GameCore::createItem(int itemID,ItemType::ItemTypes itemType,std::string meshName,std::string materialName,Ogre::Vector3 meshScale,Ogre::Vector3 position) { GameItem* item = new GameItem(itemID, itemType); item->createVisual(sceneManager, meshName, materialName, meshScale, position); item->createPhysics(dynamics); itemMap[itemID] = item; }
void CoreScript::UpdateScore(int n) { static const double FACTOR = 0.002; if (n) { // Tuned - somewhat sleazily - that basic 4 unit, 0 temple is one point. double score = CivTech() * double(n) * double(scoreTicker.Period()) * FACTOR; achievement.civTechScore += Min(1, int(score)); int team = ParentChit()->Team(); CDynArray<int> subTeams; if (Team::Instance()->IsController(team, &subTeams)) { for (int i = 0; i < subTeams.Size(); ++i) { CoreScript* subCore = CoreScript::GetCoreFromTeam(subTeams[i]); if (subCore) { score += 0.5 * subCore->CivTech() * double(n) * double(scoreTicker.Period()) * FACTOR; } } } // Push this to the GameItem, so it can be recorded in the history + census. GameItem* gi = ParentChit()->GetItem(); if (gi) { // Score is a 16 bit quantity... int s = achievement.civTechScore; if (s > 65535) s = 65535; gi->keyValues.Set(ISC::score, s); gi->UpdateHistory(); } } if (ParentChit()->GetItem()) { achievement.gold = Max(achievement.gold, ParentChit()->GetItem()->wallet.Gold()); achievement.population = Max(achievement.population, citizens.Size()); } }
void MainWindow::createBird(Bird_type type){ if(birdNum<=0){ return; } if(type == random){ srand(time(NULL)); int ran=rand()%4; switch (ran) { case 0: type=original; break; case 1: type=yellow; break; case 2: type=black; break; case 3: type=blue; break; default: break; } } nowHoldState=release; GameItem *birdie; switch (type) { case original: birdie = new Bird_original(3.3f,2.7f,0.5f,&timer,QPixmap(":/bird.png").scaled(height()/15.0,height()/15.0),world,scene); nowBird=original; break; case yellow: birdie = new Bird_yellow(3.3f,2.7f,0.5f,&timer,QPixmap(":/image/yellow.png").scaled(height()/15.0,height()/15.0),world,scene); birdie->inWaterD=-0.5; nowBird=yellow; break; case black: birdie = new Bird_black(3.3f,2.7f,0.5f,&timer,QPixmap(":/image/black.png").scaled(height()/15.0,height()/12.0),world,scene); nowBird=black; birdie->inWaterD=0; break; case blue: birdie = new Bird_blue(3.3f,2.7f,0.5f,&timer,QPixmap(":/image/blue.png").scaled(height()/15.0,height()/15.0),world,scene,birdList); nowBird=blue; birdie->inWaterD=-2; break; default: break; } birdie->getBody().SetGravityScale(0); birdList.push_back(birdie); birdNum--; mousePoint.setX(120); mousePoint.setY(580); pos_x=120;pos_y=580; timer_waiter.stop(); }
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; }
bool BuildingRepairFilter::Accept(Chit* chit) { MapSpatialComponent* msc = GET_SUB_COMPONENT(chit, SpatialComponent, MapSpatialComponent); if (msc ) { //&& msc->Building()) { GameItem* item = chit->GetItem(); if (item && item->HPFraction() < 0.9f) { return true; } } return false; }
CoreScript* LumosChitBag::TakeOverCore(const Vector2I& sector, Chit* conquerer) { int conqueringTeam = conquerer->Team(); int teamID = Team::Instance()->GenTeam(Team::Group(conqueringTeam)); bool isSubDomain = !Team::IsRogue(conqueringTeam); if (isSubDomain) { Team::Instance()->AddSubteam(conqueringTeam, teamID); } CoreScript* newCore = CoreScript::CreateCore(sector, teamID, Context()); GLASSERT(CoreScript::GetCore(sector) == newCore); newCore->ParentChit()->Add(DomainAI::Factory(teamID)); CDynArray<Chit*> arr; // After takeover, all the citizens are rogue and buildings are neutral. // As a first pass, simply takeover everything that meets that criteria. ChitAcceptAll filter; BuildingFilter buildingFilter; Context()->chitBag->QuerySpatialHash(&arr, InnerSectorBounds(sector), 0, &filter); for (Chit* c : arr) { if (c->PlayerControlled()) continue; GameItem* mainItem = c->GetItem(); if (!mainItem) continue; if (mainItem->IsDenizen() && Team::IsRogue(mainItem->Team())) { newCore->AddCitizen(c); } else if (buildingFilter.Accept(c) && mainItem->IName() != ISC::core) { c->GetItem()->SetTeam(teamID); } } // Finally, give this new core a chance. // Transfer money from Conquering domain. CoreScript* conqueringCore = CoreScript::GetCoreFromTeam(conquerer->Team()); if (conqueringCore) { int gold = conqueringCore->ParentChit()->GetWallet()->Gold() / 4; gold = Min(gold, GOLD_XFER_TAKEOVER); newCore->ParentChit()->GetWallet()->Deposit(conqueringCore->ParentChit()->GetWallet(), gold); } NewsEvent news(isSubDomain ? NewsEvent::DOMAIN_CONQUER : NewsEvent::DOMAIN_TAKEOVER, ToWorld2F(newCore->ParentChit()->Position()), newCore->ParentChit()->GetItemID(), conquerer->GetItemID()); Context()->chitBag->GetNewsHistory()->Add(news); return newCore; }
bool MOBIshFilter::Accept(Chit* chit) { // If it can move and has a team...? // Mostly a good metric. Doesn't account for dummy targets. PathMoveComponent* pmc = GET_SUB_COMPONENT(chit, MoveComponent, PathMoveComponent); if (pmc && chit->Team()) { return RelationshipFilter::Accept(chit); } GameItem* item = chit->GetItem(); if (item && item->IName() == ISC::dummyTarget) { return RelationshipFilter::Accept(chit); } return false; }
GameItem* LumosChitBag::AddItem(const char* name, Chit* chit, Engine* engine, int team, int level, const char* altRes, const char* altName) { ItemDefDB* itemDefDB = ItemDefDB::Instance(); ItemDefDB::GameItemArr itemDefArr; itemDefDB->Get(name, &itemDefArr); GLASSERT(itemDefArr.Size() > 0); GameItem* item = itemDefArr[0]->Clone(); if (altName) { item->SetName(altName); } if (altRes) { item->SetResource(altRes); } item->Roll(team, item->Traits().Get()); item->GetTraitsMutable()->SetExpFromLevel( level ); item->FullHeal(); if ( !chit->GetItemComponent() ) { ItemComponent* ic = new ItemComponent( item ); chit->Add( ic ); for( int i=1; i<itemDefArr.Size(); ++i ) { GameItem* gi = itemDefArr[i]->Clone(); ic->AddToInventory(gi); } } else { GLASSERT( itemDefArr.Size() == 1 ); chit->GetItemComponent()->AddToInventory(item); } return item; }
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; }
void RebuildAIComponent::OnChitMsg(Chit* chit, const ChitMsg& msg) { if ( msg.ID() == ChitMsg::CHIT_DESTROYED && (chit != ParentChit()) && ToSector(chit->Position()) == ToSector(ParentChit()->Position()) && chit->Team() == this->ParentChit()->Team()) { BuildingFilter buildingFilter; if (buildingFilter.Accept(chit)) { GameItem* gi = chit->GetItem(); WorkItem* wi = workItems.PushArr(1); wi->structure = gi->IName(); MapSpatialComponent* msc = GET_SUB_COMPONENT(chit, SpatialComponent, MapSpatialComponent); if (msc) { wi->pos = msc->Bounds().min; wi->rot = LRint(YRotation(chit->Rotation())); GLOUTPUT(("ReBuild: Structure %s at %d,%d r=%d to rebuild queue.\n", wi->structure.safe_str(), wi->pos.x, wi->pos.y, int(wi->rot))); } } } super::OnChitMsg(chit, msg); }
void EventController::stepTest() { CollectableGameItem* it; if (game->getInput()->keyReleased(Input::kN1)) { MapLocation m; m.id = 0; m.screenX = -1; m.screenY = -1; m.positionX = -1; m.positionY = -1; controller->teleportTo(m, controller->getPlayer(0), FADE, false); } else if (game->getInput()->keyReleased(Input::kN2)) { MapLocation m; m.id = 1; m.screenX = -1; m.screenY = -1; m.positionX = -1; m.positionY = -1; controller->teleportTo(m, controller->getPlayer(0), FADE, false); } else if (game->getInput()->keyReleased(Input::kN3)) { MapLocation m; m.id = 2; m.screenX = -1; m.screenY = -1; m.positionX = -1; m.positionY = -1; controller->teleportTo(m, controller->getPlayer(0), FADE, false); } else if (game->getInput()->keyReleased(Input::kN5)) { MapLocation m; m.id = controller->getData()->getMapNumber()-1; m.screenX = -1; m.screenY = -1; m.positionX = -1; m.positionY = -1; controller->teleportTo(m, controller->getPlayer(0), FADE, false); }; if (game->getInput()->keyPressed(Input::kI)) { GameItem* it = new GameItem(224/2, 224/2, game, world); it->init("data/gfx/grass.png", GameItem::ieKEYITEM, 1); controller->gamePlayState->add(it); } }
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; }
void GameRoom::AddItem(GameItem& newWObject) { string key(newWObject.GetName()); (this->items)[key] = newWObject; }
void MainWindow::handleContact() { // One hurt if(myContactListener->contactType == 0){ // set health GameItem* item = (GameItem*)myContactListener->bodyInfo_1->GetUserData(); float healthLeft = (item->getHealth()) - (myContactListener->impInfo); item->setHealth(healthLeft); // add score scorePoint += (myContactListener->impInfo)*3; // change image and delete if no health if(item->getType() == 'o'){ // for obstacle(boxes) if(healthLeft >=300 && healthLeft < 600){ QPixmap *Pixmap_box2 = new QPixmap(QPixmap(":/image/box_2.png").scaled(45,45)); item->g_pixmap.setPixmap(*Pixmap_box2); if(item->g_size == QSize(11,1)){ QPixmap *Pixmap_bar2 = new QPixmap(QPixmap(":/image/bar_2.png").scaled(165,15)); item->g_pixmap.setPixmap(*Pixmap_bar2); } } if(healthLeft >=0 && healthLeft < 300){ QPixmap *Pixmap_box3 = new QPixmap(QPixmap(":/image/box_3.png").scaled(45,45)); item->g_pixmap.setPixmap(*Pixmap_box3); if(item->g_size == QSize(11,1)){ QPixmap *Pixmap_bar3 = new QPixmap(QPixmap(":/image/bar_3.png").scaled(165,15)); item->g_pixmap.setPixmap(*Pixmap_bar3); } } if(healthLeft < 0){ scene->removeItem(&(item->g_pixmap)); item->getBody()->DestroyFixture(item->getBody()->GetFixtureList()); } } if(item->getType() == 'e'){ //for enemy(pigs) if(healthLeft >=300 && healthLeft < 600){ QPixmap *Pixmap_pig2 = new QPixmap(QPixmap(":/image/pig_2.png").scaled(45,45)); item->g_pixmap.setPixmap(*Pixmap_pig2); } if(healthLeft >=0 && healthLeft < 300){ QPixmap *Pixmap_pig3 = new QPixmap(QPixmap(":/image/pig_3.png").scaled(45,45)); item->g_pixmap.setPixmap(*Pixmap_pig3); } if(healthLeft < 0){ scene->removeItem(&(item->g_pixmap)); item->getBody()->DestroyFixture(item->getBody()->GetFixtureList()); pigLeft -= 1; if(pigLeft == 0){ mySceneManager->buildWinScene(); this->buildEndButton(); } } } } // Two hurt if(myContactListener->contactType == 1){ // set health GameItem* item1 = (GameItem*)myContactListener->bodyInfo_1->GetUserData(); GameItem* item2 = (GameItem*)myContactListener->bodyInfo_2->GetUserData(); float healthLeft1 = (item1->getHealth()) - (myContactListener->impInfo); item1->setHealth(healthLeft1); float healthLeft2 = (item2->getHealth()) - (myContactListener->impInfo); item2->setHealth(healthLeft2); // add score scorePoint += (myContactListener->impInfo)*6; // change image and delete if no health if(item1->getType() == 'o' && item2->getType() == 'e'){ if(healthLeft1 >=300 && healthLeft1 < 600){ QPixmap *Pixmap_box2 = new QPixmap(QPixmap(":/image/box_2.png").scaled(45,45)); item1->g_pixmap.setPixmap(*Pixmap_box2); if(item1->g_size == QSize(11,1)){ QPixmap *Pixmap_bar2 = new QPixmap(QPixmap(":/image/bar_2.png").scaled(165,15)); item1->g_pixmap.setPixmap(*Pixmap_bar2); } } if(healthLeft1 >=0 && healthLeft1 < 300){ QPixmap *Pixmap_box3 = new QPixmap(QPixmap(":/image/box_3.png").scaled(45,45)); item1->g_pixmap.setPixmap(*Pixmap_box3); if(item1->g_size == QSize(11,1)){ QPixmap *Pixmap_bar3 = new QPixmap(QPixmap(":/image/bar_3.png").scaled(165,15)); item1->g_pixmap.setPixmap(*Pixmap_bar3); } } if(healthLeft1 < 0){ scene->removeItem(&(item1->g_pixmap)); item1->getBody()->DestroyFixture(item1->getBody()->GetFixtureList()); } if(healthLeft2 >=300 && healthLeft2 < 600){ QPixmap *Pixmap_pig2 = new QPixmap(QPixmap(":/image/pig_2.png").scaled(45,45)); item2->g_pixmap.setPixmap(*Pixmap_pig2); } if(healthLeft2 >=0 && healthLeft2 < 300){ QPixmap *Pixmap_pig3 = new QPixmap(QPixmap(":/image/pig_3.png").scaled(45,45)); item2->g_pixmap.setPixmap(*Pixmap_pig3); } if(healthLeft2 < 0){ scene->removeItem(&(item2->g_pixmap)); item2->getBody()->DestroyFixture(item2->getBody()->GetFixtureList()); pigLeft -= 1; if(pigLeft == 0){ mySceneManager->buildWinScene(); this->buildEndButton(); } } } if(item2->getType() == 'o' && item1->getType() == 'e'){ if(healthLeft2 >=300 && healthLeft2 < 600){ QPixmap *Pixmap_box2 = new QPixmap(QPixmap(":/image/box_2.png").scaled(45,45)); item2->g_pixmap.setPixmap(*Pixmap_box2); if(item2->g_size == QSize(11,1)){ QPixmap *Pixmap_bar2 = new QPixmap(QPixmap(":/image/bar_2.png").scaled(165,15)); item2->g_pixmap.setPixmap(*Pixmap_bar2); } } if(healthLeft2 >=0 && healthLeft2 < 300){ QPixmap *Pixmap_box3 = new QPixmap(QPixmap(":/image/box_3.png").scaled(45,45)); item2->g_pixmap.setPixmap(*Pixmap_box3); if(item2->g_size == QSize(11,1)){ QPixmap *Pixmap_bar3 = new QPixmap(QPixmap(":/image/bar_3.png").scaled(165,15)); item2->g_pixmap.setPixmap(*Pixmap_bar3); } } if(healthLeft2 < 0){ scene->removeItem(&(item2->g_pixmap)); item2->getBody()->DestroyFixture(item2->getBody()->GetFixtureList()); } if(healthLeft1 >=300 && healthLeft1 < 600){ QPixmap *Pixmap_pig2 = new QPixmap(QPixmap(":/image/pig_2.png").scaled(45,45)); item1->g_pixmap.setPixmap(*Pixmap_pig2); } if(healthLeft1 >=0 && healthLeft1 < 300){ QPixmap *Pixmap_pig3 = new QPixmap(QPixmap(":/image/pig_3.png").scaled(45,45)); item1->g_pixmap.setPixmap(*Pixmap_pig3); } if(healthLeft1 < 0){ scene->removeItem(&(item1->g_pixmap)); item1->getBody()->DestroyFixture(item1->getBody()->GetFixtureList()); pigLeft -= 1; if(pigLeft == 0){ mySceneManager->buildWinScene(); this->buildEndButton(); } } } } }