Things are winding down with
the controller at this point. You use the following
functions to equip, use, and drop an item:
bool cCharController::equip(sCharacter* character, long item_index, long equip_type, bool equip_now)
{
if(m_mil == NULL || character == NULL)
return false;
// make sure allow equiping of item
if(! check_bit(m_mil[item_index].usage, character->char_def.class_index))
return false;
// remove current item first and equip new one
switch(equip_type)
{
case WEAPON:
character->char_def.weapon = -1;
character->weapon_mesh.free();
if(equip_now && m_mil[item_index].category == WEAPON)
{
character->char_def.weapon = item_index;
if(m_mil[item_index].mesh_filename)
{
char path[MAX_PATH];
sprintf(path, "%s%s", m_weapon_mesh_path, m_mil[item_index].mesh_filename);
character->weapon_mesh.load(path, m_texture_path);
character->weapon_object.create(&character->weapon_mesh);
character->weapon_object.attach_to_object(&character->object, "WeaponHand");
}
}
break;
case ARMOR:
character->char_def.armor = -1;
if(equip_now && m_mil[item_index].category == ARMOR)
character->char_def.armor = item_index;
break;
case SHIELD:
character->char_def.shield = -1;
if(equip_now && m_mil[item_index].category == SHIELD)
character->char_def.shield = item_index;
break;
case ACCESSORY:
character->char_def.accessory = -1;
if(equip_now && m_mil[item_index].category == ACCESSORY)
character->char_def.accessory = item_index;
break;
default:
return false;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void cCharController::use_item(sCharacter* owner, sCharacter* target,
long item_index, sCharItem* char_item)
{
if(owner == NULL || target == NULL || m_mil == NULL)
return;
sItem* item = &m_mil[item_index];
// make sure allow to use of item
if(! check_bit(item->usage, target->char_def.class_index))
return;
// use specified item
switch(item->category)
{
case EDIBLE:
case HEALING: // alter health
target->health_points += item->value;
break;
}
// decrease quantity and remove object if needed
if(check_bit(item->flags, USEONCE) && char_item)
{
char_item->quantity--;
if(char_item->quantity <= 0 && owner->char_ics)
owner->char_ics->remove(char_item);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
bool cCharController::drop(sCharacter* character, sCharItem* char_item, long quantity)
{
if(char_item == NULL || m_mil == NULL || character == NULL)
return false;
// make sure item can be dropped
if(! check_bit(m_mil[char_item->item_index].flags, CANDROP))
return false;
char_item->quantity -= quantity;
// remove item from ics if no more left
if(char_item->quantity <= 0 && character->char_ics)
character->char_ics->remove(char_item);
return true;
}
With equip, you must specify the
character to modify and the item number (from
the MIL) of the item being equipped. You use the equip_type argument to specify
which
item type to equip (WEAPON, ARMOR, SHIELD, or ACCESSORY) and the equip_now flag
to tell the
controller to equip the specified item (set equip_now to true) or just to
unequip the currently
used item (by setting equip_now to false).
As for the use item function (use_item),
two characters are required: the owner of the
item and the character on which the item is being used. In that way, one
character
can use a healing potion on another character. Specify the MIL item number being
used, as well as a pointer to the owner’s ICS char_item structure so that the
quantity
of the item can be decreased.
The next function is required
to process the teleport spell effect on PCs. Whenever a
teleport spell is used on a PC, the character controller calls the following
function to
handle the effects. Both the pointer to the target character and spell structure
are
passed:
virtual bool
pc_teleport(sCharacter* character, const sSpell* spell)
{
return true;
}
Finishing up the character
controller class functions is the one that is responsible
for preparing a character to perform an action. You use this function mostly
when
controlling your PC via the pc_update function:
void set_char_action(sCharacter* character, long action, long action_timer)
{
if(character == NULL)
return;
// make sure attack, spell, and item supporting charge.
if(action == CHAR_ATTACK || action == CHAR_SPELL || action == CHAR_ITEM)
{
if(character->charge < 100.0f)
return;
}
character->action = action;
play_action_sound(character);
long mesh_index = character->char_def.mesh_index;
// set action timer
if(action_timer == -1)
character->action_timer = 1;
else
{
ulong anim_length = m_mesh_anim[mesh_index].anim.get_time_length(m_char_anim[action].name);
character->action_timer = action_timer + anim_length * 30;
}
}
When a PC (or any character for
that matter) does something, a matching action is
performed. Walking is an action, attacking is an action, and so on. Previously,
actions
were defined as CHAR_IDLE, CHAR_MOVE, CHAR_ATTACK, and so on, for example. You
need to
set the action argument to one of those values in order to initiate a character
action.
For each action
that a character can perform, there is a matching animation in the
sCharAnimInfo structure array used to initialize the controller. When a
character
performs an action, the appropriate animation is set, as well as the action
timer
used to count down the time until the animation is complete. Remember that no
further actions can be performed until the current action is complete.
The last argument in the list,
add_timer, is used to add additional milliseconds to the
action timer. Specifying a value of -1 for add_timer, forces set_char_action to
not use the
action timer, which means that the action clears on the next update.