No categories assigned

AI:BrainTutorialC

Creating a new brain in C++ gives you the option of extending the behavior of the default brain or completely override it. I will use the combat pet brain as an example, it is a brain designed for summoned combat pets or charmed pets. All this brain does is extend the default brain to make the pet follow its owner. This will require you to recompile your server.

Creating The New Brain

The first thing we need to do is create the new brain class and have it inherit from the default brain class.

class CombatPetBrain : public Brain {

};

Every brain needs a constructor, destructor, and think function. The constructor must take a parameter of type NPC*, this parameter tells the brain what NPC we are controlling in the game.

class CombatPetBrain : public Brain {
	CombatPetBrain(NPC* body);
	~CombatPetBrain();
	void Think();
};

That is the minimum needed to create a new brain, you can add whatever else you want to the class but those 3 functions must be there. For this brain that is all we need.

Programing The New Brain

No matter if you are just extending the default brain or making a completely new one you must call the default brain's constructor to set up some essential variables, mainly the timers and the NPC this brain will control.

CombatPetBrain::CombatPetBrain(NPC* body) : Brain(body) {

}

Notice the ": Brain(body)" after the parameters for our constructor, this will take the parameter we passed to our constructor, body, and pass it to the default constructor to set up the essential stuff. For this brain we have nothing special to add to the constructor or destructor so both will be left blank.

CombatPetBrain::~CombatPetBrain() {

}

Now we get to the Think() function. This will decide what the NPC should do and is called every 1/4 sec by default.

void CombatPetBrain::Think() {
    
}

All we want to do for this brain is extend the functionality of the default brain so this NPC follows its owner around so first thing we need to do is have the default code run.

void CombatPetBrain::Think() {
	// We are extending the base brain so make sure to call the parent Think() function.
	// If we want to override then we could remove Brain::Think()
	Brain::Think();
}

If you want to completely override the default behavior then you would just leave Brain::Think() out. Now we add the code to make the NPC follow its owner.

void CombatPetBrain::Think() {
	// We are extending the base brain so make sure to call the parent Think() function.
	// If we want to override then we could remove Brain::Think()
	Brain::Think();

	// All this Brain does is make the pet follow its owner, the combat comes from the default brain

	if (GetBody()->EngagedInCombat() || !GetBody()->IsPet() || GetBody()->IsMezzedOrStunned())
		return;
	
	LogWrite(NPC_AI__DEBUG, 7, "NPC_AI", "Pet AI code called for %s", GetBody()->GetName());

	// If owner is a player and player has stay set then return out
	if (GetBody()->GetOwner()->IsPlayer() && ((Player*)GetBody()->GetOwner())->GetInfoStruct()->pet_movement == 1)
		return;

	// Set target to owner
	Entity* target = GetBody()->GetOwner();
	GetBody()->SetTarget(target);

	// Get distance from the owner
	float distance = GetBody()->GetDistance(target);
	distance -= target->appearance.pos.collision_radius / 10;
	distance -= GetBody()->appearance.pos.collision_radius / 10;

	// If out of melee range then move closer
	if (distance > MAX_COMBAT_RANGE)
		MoveCloser(target);
}

Using The New Brain

Now that we have our brain we can assign it to a NPC.

CombatPetBrain* brain = new CombatPetBrain(npc);
npc->SetBrain(brain);