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
}