int Tribe::AliveCount() const { int count = 0; for(size_t i=0; i < members.GetSize(); i++) { NPC* npc = members[i]; if(npc->IsAlive()) count++; } return count; }
void Tribe::Advance(csTicks when, EventManager* eventmgr) { int delta = when - lastAdvance; if(delta < 0) // Handle wrappover of tick { delta = 250; // We just set it to the event timer. } lastAdvance = when; // Manage Wealth if(when - lastGrowth > 1000) { float growth; // We need to help tribes that have no members with some resources // so that they can spawn the first entity if(AliveCount() <= 0 && CountResource(wealthResourceName) < reproductionCost) { growth = wealthResourceGrowth; } else if(CountResource(wealthResourceName) < wealthResourceGrowthActiveLimit) { // Some tribes need constant growth in wealth, though capped to a limit // to prevent tribes with no strain on the resources to grow // infinit in wealth growth = wealthResourceGrowthActive; } else { growth = 0; } // Now calculate the growth. Adding what part that wasn't added // the last time this code where run. accWealthGrowth += growth* ((when - lastGrowth)/1000.0); int amount = int(floor(accWealthGrowth)); accWealthGrowth -= amount; if(amount != 0) AddResource(wealthResourceName, amount); lastGrowth = when; } else if(when - lastGrowth < 0) // Handle wrappoer of tick { lastGrowth = when; } // And manage tribe assignments csString perc; int decreaseValue = delta; // Set it to change the scale on recipe wait times // Manage cyclic recipes for(size_t i=0; i<cyclicRecipes.GetSize(); i++) { cyclicRecipes[i].timeLeft -= decreaseValue; if(cyclicRecipes[i].timeLeft <= 0) { // Add the recipe and reset counter RecipeTreeNode* newNode = new RecipeTreeNode(cyclicRecipes[i].recipe, 0); tribalRecipe->AddChild(newNode); newNode->priority = CYCLIC_RECIPE_PRIORITY; cyclicRecipes[i].timeLeft = cyclicRecipes[i].timeTotal; } } // Manage standard recipes for(size_t i=0; i < members.GetSize(); i++) { NPC* npc = members[i]; Behavior* behavior = npc->GetCurrentBehavior(); // For dead npcs just resurrect them if(!npc->IsAlive()) { // Issue the resurrect perception if we have enough // resources perc = "tribe:resurrect"; Perception pcpt(perc); if(AliveCount() == 0 && (CountResource(wealthResourceName) >= 10 * reproductionCost)) { AddResource(wealthResourceName, -10*reproductionCost); npc->TriggerEvent(&pcpt); } else if(CanGrow()) { AddResource(wealthResourceName,-reproductionCost); npc->TriggerEvent(&pcpt); } continue; } // If we have any npcs with no assignments then // we can parse recipes and send them to work if(behavior && strcasecmp(behavior->GetName(),npcIdleBehavior.GetDataSafe())==0) { RDebug(this, 5, "*** Found Idle NPC %s(%s) checking recipes ***", npc->GetName(),ShowID(npc->GetEID())); // Update recipes wait times UpdateRecipeData(decreaseValue); // Get best recipe. (highest level, no wait time) RecipeTreeNode* bestRecipe = tribalRecipe->GetNextRecipe(); if(!bestRecipe) { // Something went wrong... it should never re-parse the tribal recipe // High chances to be a scripting error break; } if(bestRecipe->wait <= 0) { RDebug(this, 5, "Applying recipe %s.", bestRecipe->recipe->GetName().GetDataSafe()); bestRecipe->nextStep = recipeManager->ApplyRecipe( bestRecipe, this, bestRecipe->nextStep); } // If nextStep is -1 => Recipe is Completed if(bestRecipe->nextStep == -1) { // TODO -- Remove TimeStamp csString rName = bestRecipe->recipe->GetName(); if(rName != "do nothing") { RDebug(this, 5, "Recipe %s completed.", rName.GetData()); } tribalRecipe->RemoveChild(bestRecipe->recipe); } // If nextStep is -2, the recipe has unmet requirements else if(bestRecipe->nextStep == -2) { bestRecipe->nextStep = 0; } } } }