Example #1
0
bool Tribe::CheckMembers(const csString &type, int number)
{

    // Handle special case where name is 'number'
    if(type == "number")
    {
        // Check if total number is correct (we don't care if their idle or not
        if(number < 0 || (size_t)number <= members.GetSize())
        {
            return true;
        }

        return false;
    }

    for(size_t i=0; i<members.GetSize(); i++)
    {
        NPC* member = members[i];

        if(!member->GetCurrentBehavior())
        {
            // Discard Members with no Behavior
            // This shouldn't happen but... ermm just in case
            continue;
        }

        if((member->GetTribeMemberType() != type) && (type != "any"))
        {
            // Just skip any members of wrong type.
            continue;
        }


        if(strcasecmp(member->GetCurrentBehavior()->GetName(), npcIdleBehavior.GetDataSafe()) == 0)
        {
            number--;
        }

        if(number <= 0)
        {
            return true;
        }
    }

    // We don't have enough members
    return false;
}
Example #2
0
csArray<NPC*> Tribe::SelectNPCs(const csString &type, const char* number)
{
    int           count = atoi(number);
    csArray<NPC*> npcs;

    bool selectAny = type.CompareNoCase("any");

    // Loop all members. Check for type and if they are idle.
    for(size_t i=0; i<members.GetSize(); i++)
    {
        NPC* member = members[i];

        if((member->GetTribeMemberType() != type) && !selectAny)
        {
            // Just skip any members of wrong type.
            continue;
        }

        Behavior* currentBehavior = member->GetCurrentBehavior();
        if(!currentBehavior)
        {
            // Newly created NPC or some malfunction.
            // Just skip and try this npc next loop.
            continue;
        }

        if(strcasecmp(currentBehavior->GetName(),npcIdleBehavior.GetDataSafe())==0)
        {
            count--;
            npcs.Push(member);
        }

        // Check if we found the number requested
        if(count == 0)
            return npcs;

    }

    // Return what we found
    return npcs;
}
Example #3
0
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;
            }
        }
    }
}