예제 #1
0
RESULT 
BehaviorManager::PushBehaviorOnToGameObject( IN HBehavior hBehavior, IN HGameObject hGameObject, IN StateMachineQueue queue )
{
    RESULT rval           = S_OK;
    string gameObjectName = "";
    
    Behavior* pBehavior = GetObjectPointer( hBehavior );
    if (pBehavior)
    {
        GOMan.GetName( hGameObject, &gameObjectName );
        
        RETAILMSG(ZONE_STATEMACHINE | ZONE_VERBOSE, "BehaviorManager::PushBehaviorOnToGameObject( \"%s\", \"%s\", queue: %d )", 
            pBehavior->GetName().c_str(),
            gameObjectName.c_str(),
            queue);

        CHR(pBehavior->BindToGameObject( hGameObject, queue ));
    }
    else 
    {
        rval = E_FAIL;
    }

Exit:
    if (FAILED(rval))
    {
        RETAILMSG(ZONE_ERROR, "ERROR: BehaviorManager::PushBehaviorOnToGameObject( \"%s\", \"%s\" ): Behavior or GO not found", 
            pBehavior ? pBehavior->GetName().c_str() : "NULL",
            gameObjectName.c_str());
    }
    
    return rval;
}
예제 #2
0
파일: Object.cpp 프로젝트: mateerladnam/GD
void Object::UnserializeFrom(gd::Project & project, const SerializerElement & element)
{
    //Name and type are already loaded.
    objectVariables.UnserializeFrom(element.GetChild("variables", 0, "Variables"));

    //Compatibility with GD <= 3.3
    if (element.HasChild("Automatism"))
    {
        for (std::size_t i = 0; i < element.GetChildrenCount("Automatism"); ++i)
        {
            SerializerElement & behaviorElement = element.GetChild("Automatism", i);

            gd::String autoType = behaviorElement.GetStringAttribute("type", "", "Type")
                .FindAndReplace("Automatism", "Behavior");
            gd::String autoName = behaviorElement.GetStringAttribute("name", "", "Name");

            Behavior* behavior = project.CreateBehavior(autoType);
            if ( behavior != NULL )
            {
                behavior->SetName(autoName);
                behavior->UnserializeFrom(behaviorElement);
                behaviors[behavior->GetName()] = behavior;
            }
            else
                std::cout << "WARNING: Unknown behavior " << autoType << std::endl;
        }
    }
    //End of compatibility code
    else
    {
        SerializerElement & behaviorsElement = element.GetChild("behaviors", 0, "automatisms");
        behaviorsElement.ConsiderAsArrayOf("behavior", "automatism");
        for (std::size_t i = 0; i < behaviorsElement.GetChildrenCount(); ++i)
        {
            SerializerElement & behaviorElement = behaviorsElement.GetChild(i);

            gd::String autoType = behaviorElement.GetStringAttribute("type")
                .FindAndReplace("Automatism", "Behavior"); //Compatibility with GD <= 4
            gd::String autoName = behaviorElement.GetStringAttribute("name");

            Behavior* behavior = project.CreateBehavior(autoType);
            if ( behavior != NULL )
            {
                behavior->SetName(autoName);
                behavior->UnserializeFrom(behaviorElement);
                behaviors[behavior->GetName()] = behavior;
            }
            else
                std::cout << "WARNING: Unknown behavior " << autoType << std::endl;
        }
    }

    DoUnserializeFrom(project, element);
}
예제 #3
0
파일: Object.cpp 프로젝트: mateerladnam/GD
gd::Behavior * Object::AddNewBehavior(gd::Project & project, const gd::String & type, const gd::String & name)
{
    Behavior * behavior = project.GetCurrentPlatform().CreateBehavior(type);

    if ( behavior != NULL ) {
        behavior->SetName(name);
        behaviors[behavior->GetName()] = behavior;
    }

    return behavior;
}
예제 #4
0
RESULT
BehaviorManager::Init( IN const string& settingsFilename )
{
    RETAILMSG(ZONE_INFO, "BehaviorManager::Init( %s )", settingsFilename.c_str());

    RESULT rval = S_OK;
    char   path[MAX_PATH];
    
    //
    // Create a Settings object and load the file.
    //
    Settings mySettings;
    if ( FAILED(mySettings.Read( settingsFilename )) )
    {
        RETAILMSG(ZONE_ERROR, "ERROR: BehaviorManager::Init( %s ): failed to load settings file", settingsFilename.c_str() );
        return E_UNEXPECTED;
    }
    

    //
    // Create each Behavior.
    //
    UINT32 numBehaviors = mySettings.GetInt("/Behaviors.NumBehaviors");

    for (int i = 0; i < numBehaviors; ++i)
    {
        sprintf(path, "/Behaviors/Behavior%d", i);
        //DEBUGMSG(ZONE_INFO, "Loading [%s]", path);

        Behavior *pBehavior = NULL;
        CreateBehavior( &mySettings, path, &pBehavior );
        if (!pBehavior)
        {
            RETAILMSG(ZONE_ERROR, "ERROR: BehaviorManager::Init( %s ): failed to create Behavior", path);
            // Continue loading other Behaviors rather than aborting.
            continue;
        }
        
        //DEBUGMSG(ZONE_Behavior, "Created Behavior [%s]", pBehavior->GetName().c_str());
        CHR(Add(pBehavior->GetName(), pBehavior));
    }
    
Exit:
    return rval;
}
예제 #5
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;
}
예제 #6
0
bool NPCType::Load(iResultRow &row)
{
    csString parents = row.GetString("parents");
    if(!parents.IsEmpty()) // this npctype is a subclass of another npctype
    {
        csArray<csString> parent = psSplit(parents,',');
        for(size_t i = 0; i < parent.GetSize(); i++)
        {
            NPCType *superclass = npcclient->FindNPCType(parent[i]);
            if(superclass)
            {
                DeepCopy(*superclass);  // This pulls everything from the parent into this one.
            }
            else
            {
                Error2("Specified parent npctype '%s' could not be found.",
                       parent[i].GetDataSafe());
                return false;
            }
        }
    }

    name = row.GetString("name");
    if(name.Length() == 0)
    {
        Error1("NPCType has no name attribute. Error in DB");
        return false;
    }

    ang_vel = row.GetFloat("ang_vel");

    csString velStr = row.GetString("vel");
    velStr.Upcase();

    if(velStr.IsEmpty())
    {
        // Do nothing. Use velSource from constructor default value
        // or as inherited from superclass.
    }
    else if(velStr == "$WALK")
    {
        velSource = VEL_WALK;
    }
    else if (velStr == "$RUN")
    {
        velSource = VEL_RUN;
    }
    else if(row.GetFloat("vel"))
    {
        velSource = VEL_USER;
        vel = row.GetFloat("vel");
    }

    collisionPerception   = row.GetString("collision");
    outOfBoundsPerception = row.GetString("out_of_ounds");
    inBoundsPerception    = row.GetString("in_bounds");
    fallingPerception     = row.GetString("falling");

    csRef<iDocumentSystem> xml = csPtr<iDocumentSystem>(new csTinyDocumentSystem);
    csRef<iDocument> doc = xml->CreateDocument();
    const char* error = doc->Parse(row.GetString("script"));
    if(error)
    {
        Error3("NPCType script parsing error:%s in %s", error, name.GetData());
        return false;
    }
    csRef<iDocumentNode> node = doc->GetRoot();
    if(!node)
    {
        Error2("No XML root in npc type script of %s", name.GetData());
        return false;
    }
    
    // Now read in behaviors and reactions
    csRef<iDocumentNodeIterator> iter = node->GetNodes();

    while(iter->HasNext())
    {
        csRef<iDocumentNode> node = iter->Next();
        if(node->GetType() != CS_NODE_ELEMENT)
            continue;

        // This is a widget so read it's factory to create it.
        if(strcmp(node->GetValue(), "behavior") == 0)
        {
            Behavior *b = new Behavior;
            if(!b->Load(node))
            {
                Error3("Could not load behavior '%s'. Error in DB XML in node '%s'.",
                       b->GetName(),node->GetValue());
                delete b;
                return false;
            }
            behaviors.Add(b);
            Debug3(LOG_STARTUP,0, "Added behavior '%s' to type %s.\n",b->GetName(),name.GetData() );
        }
        else if(strcmp( node->GetValue(), "react" ) == 0)
        {
            Reaction *r = new Reaction;
            if(!r->Load(node,behaviors))
            {
                Error1("Could not load reaction. Error in DB XML");
                delete r;
                return false;
            }
            // check for duplicates and keeps the last one
            for(size_t i=0; i<reactions.GetSize(); i++)
            {
                // Same event with same type
                if(!strcmp(reactions[i]->GetEventType(),r->GetEventType())&&
                    (reactions[i]->type == r->type)&&
                    (reactions[i]->values == r->values))
                {
                    // Check if there is a mach in affected
                    for(size_t k=0; k< r->affected.GetSize(); k++)
                    {
                        for(size_t j=0; j< reactions[i]->affected.GetSize(); j++)
                        {
                            if(!strcmp(r->affected[k]->GetName(),reactions[i]->affected[j]->GetName()))
                            {
                                // Should probably delete and clear out here
                                // to allow for overiding of event,affected pairs.
                                // Though now give error, until needed.
                                Error4("Reaction of type '%s' already connected to '%s' in '%s'",
                                       r->GetEventType(),reactions[i]->affected[j]->GetName(), name.GetDataSafe());
                                return false;
                                // delete reactions[i];
                                //reactions.DeleteIndex(i);
                                //break;
                            }
                        }
                    }
                }
            }

            reactions.Insert(0,r);  // reactions get inserted at beginning so subclass ones take precedence over superclass.
        }
        else
        {
            Error1("Node under NPCType is not 'behavior' or 'react'. Error in DB XML");
            return false;
        }
    }
    return true; // success
}
예제 #7
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;
            }
        }
    }
}