/**
* The standard base for all the npc goals. This should be inherited into
* every goal. The methods can be overridden is specific behaviour of some
* sort is required.
* @author Pinkfish
* @started Thu Jul 30 18:17:35 PDT 1998
*/
#include <npc/goals.h>
private mapping _default_plans;
private int _default_priority;
#define GOAL_PLAN_ARRAY_SIZE 1
#define GOAL_PLAN_PLAN 0
/** @ignore yes */
void setup() {
} /* setup() */
void create() {
_default_plans = ([ ]);
_default_priority = GOAL_INVALID_PRIORITY;
setup();
} /* create() */
/**
* This method initialises all the plans associated with this goal. It
* should be overridden by the higher level objects to allow them to
* initialise the plans and stuff.
* @param npc the npc the goal is on
* @param goal_name the name of the goal
* @param control the control data
*/
void initialise_plans(object npc,
string goal_name,
mixed data) {
} /* initialise_plans() */
/**
* This method initialises the goal. It sets up all the call back
* events and anything that needs to be done at startup. This method will
* also call the initialise_plan() method to setup all the default
* plan information for this goal.
* @param npc the npc to initialise
* @param goal_name the name of the goal
* @param control the control data
*/
void initialise(object npc,
string goal_name,
class goal_control control) {
string name;
foreach (name in keys(_default_plans)) {
tell_creator("pinkfish", "Adding event hook for %O\n", name);
npc->add_goal_event(base_name(this_object()), name);
}
foreach (name in keys(control->extra_plans)) {
npc->add_goal_event(base_name(this_object()), name);
}
initialise_plans(npc, goal_name, control->data);
} /* initialise() */
/**
* This method returns the current plan associated with the goal control
* for this goal.
* @param npc the npc the goal is operating on
* @param control the goal control class
*/
string query_current_plan(object npc,
class goal_control control) {
return control->current_plan;
} /* query_current_plan() */
/**
* This method is used to create the plan specific data.
* @param npc the npc that the goal is being setup on
* @param goal_name the noralised name of the goal
* @param stuff the information passed in when the goal was created
* @return the data used by the goal
*/
mixed create_goal_data(object npc,
string goal_name,
mixed stuff) {
return stuff;
} /* create_goal_data() */
/**
* This method creats a goal control class with any of the extra bits that are
* required. The extra plans are a mapping which is indexed on the event
* name and contains values which are the plans to use for that goal.
* @param npc the npc creating the goal
* @param extra_plans the extra plans needed for this npc
* @param stuff the startup goal data
* @return the class to use as an initial argument to the goal
*/
void add_goal_to_npc(object npc,
mapping extra_plans,
mixed stuff) {
class goal_control frog;
mixed value;
string goal_name;
tell_creator("pinkfish", "Adding goal %O to npc(%O).\n", base_name(this_object()), stuff);
if (!mappingp(extra_plans)) {
extra_plans = ([ ]);
}
goal_name = base_name(this_object());
frog = new(class goal_control);
frog->extra_plans = extra_plans;
frog->current_plan = 0;
frog->priority = GOAL_DEFAULT_PRIORITY;
frog->data = create_goal_data(npc, goal_name, stuff);
frog->plan_info = ([ ]);
npc->add_goal(goal_name, frog);
} /* add_goal_to_npc() */
/**
* This method returns the current priority for the goal.
* @param npc the npc the goal is linked to
* @param control the control information for the goal
* @return the priority of the goal
*/
int query_priority(object npc,
class goal_control control) {
if (control->priority != GOAL_DEFAULT_PRIORITY) {
return control->priority;
}
return _default_priority;
} /* query_priority() */
/**
* This method returns the default priority for the goal.
* @return the default priority
*/
int query_default_priority() {
return _default_priority;
} /* query_default_priority() */
/**
* This method sets the default priority for the goal.
* @param priority the new default priority
*/
protected void set_default_priority(int priority) {
_default_priority = priority;
} /* set_default_priority() */
/**
* This method handles an incoming event and will see which of the
* possible plans might need to be setup to run.
* @param event_name the name of the event
* @return notification of the event handling
*/
int notify_of_event(object npc,
class goal_control control,
string event,
mixed *data) {
int value;
string plan;
int max_value;
string max_plan;
mixed max_data;
int i;
mixed info;
/* Check the extra known plans for sutability. */
if (control->extra_plans[event]) {
for (i = 0; i < sizeof(control->extra_plans[event]);
i += GOAL_PLAN_ARRAY_SIZE) {
plan = control->extra_plans[event][i + GOAL_PLAN_PLAN];
info = control->plan_info[plan];
if (plan->pre_condition(npc,
base_name(this_object()),
info,
event,
data)) {
value = plan->query_sutability(npc,
base_name(this_object()),
info,
event,
data);
if (value > max_value) {
max_value = value;
max_plan = plan;
max_data = plan->query_data(npc,
base_name(this_object()),
info,
event,
data);
}
}
}
}
/* Check the default plans for sutability. */
if (_default_plans[event]) {
for (i = 0;
i < sizeof(_default_plans[event]);
i += GOAL_PLAN_ARRAY_SIZE) {
plan = _default_plans[event][i + GOAL_PLAN_PLAN];
info = control->plan_info[plan];
if (plan->pre_condition(npc,
base_name(this_object()),
info,
event,
data)) {
value = plan->query_sutability(npc,
base_name(this_object()),
info,
event,
data);
if (value > max_value) {
max_value = value;
max_plan = plan;
max_data = plan->query_data(npc,
base_name(this_object()),
info,
event,
data);
}
}
}
}
/* If we found a plan to activate, activate it. */
if (max_plan) {
// Allow plans to modify their priority up and down a bit.
return npc->activate_plan(max_plan,
base_name(this_object()),
query_priority(npc, control) +
max_plan->query_priority_offset(),
max_data);
}
return GOAL_EVENT_NOT_HANDLED;
} /* notify_of_event() */
/**
* This method returns the known set of default plans for the goal.
* @return the default known plans
*/
mapping query_default_plans() {
return _default_plans;
} /* query_default_plans() */
/**
* This method adds a default plan to the currently known list of plans.
* @param event_name the name of the event to trigger the plan on
* @param plan the name of the plan to add
* @param activate the function pointer to create the data for the plan
*/
protected void add_default_plan(string event_name,
string plan) {
if (!_default_plans[event_name]) {
_default_plans[event_name] = ({ plan });
} else if (member_array(plan, _default_plans[event_name]) == -1) {
_default_plans[event_name] += ({ plan });
}
} /* add_default_plan() */
/**
* This method changes the data associated with the plan for the particular
* npc and goal.
* @param npc the npc that the goal is on
* @param control the data associated with the goal
* @param plan the name of the plan to setup
* @param plan_data the data to set for the plan
*/
void set_plan_data(object npc,
class goal_control control,
string plan,
mixed plan_data) {
control->plan_info[plan] = plan_data;
} /* set_plan_data() */
/**
* This method returns the data associated withthe plan for the particular
* npc and goal.
* @param npc the npc the goal is on
* @param control the control data for the goal
* @param plan the name of the plan to setup
* @param plan_data the data to set for the plan
*/
mixed query_plan_data(object npc,
class goal_control control,
string plan) {
return control->plan_info[plan];
} /* query_plan_data() */