status_frame:
You use the status_frame
function to display the player's statistics (health points,
mana points, known spells, and so on) when the player's status window is
displayed.
This function handles equipping items and checking on the player's statistics.
void status_frame(void* data, long purpose)
{
if(purpose == SHUTDOWN_PURPOSE)
return;
cApp* app = (cApp*) data;
if(purpose == INIT_PURPOSE)
{
app->m_text_header.set_text("Status", COLOR_WHITE);
app->m_text_window.set_text("", COLOR_WHITE);
}
else // process a frame of status screen
{
// exit screen if ESC or right mouse button pressed
if(app->m_keyboard.get_key_state(KEY_ESC) || app->m_mouse.get_button_state(MOUSE_RBUTTON))
{
app->m_keyboard.m_locks[KEY_ESC] = true;
app->m_mouse.m_locks[MOUSE_RBUTTON] = true;
app->m_state_manager.pop(app);
return;
}
sCharDef& char_def = g_player->char_def;
// determine which item is selected with mouse
long sel = app->m_mouse.get_y_pos() - STATUS_TOP_HEIGHT;
if(sel >= 0)
sel /= STATUS_MENU_HEIGHT;
// see if click on item to use or equip
if(app->m_mouse.get_button_state(MOUSE_LBUTTON))
{
app->m_mouse.m_locks[MOUSE_LBUTTON] = true;
// see which item was clicked
if(sel >= 0 && sel < g_player->char_ics->get_num_items())
{
sCharItem* char_item = g_player->char_ics->get_item(sel);
bool is_consume = false;
bool is_equip_now;
// determine what to do with item
switch(app->m_mil[char_item->item_index].category)
{
case WEAPON: // equip/unequip weapon
is_equip_now = (char_def.weapon != char_item->item_index);
app->m_game_chars.equip(g_player, char_item->item_index, WEAPON, is_equip_now);
break;
case ARMOR: // equip/unequip armor
is_equip_now = (char_def.armor != char_item->item_index);
app->m_game_chars.equip(g_player, char_item->item_index, ARMOR, is_equip_now);
break;
case SHIELD: // equip/unequip shield
is_equip_now = (char_def.shield != char_item->item_index);
app->m_game_chars.equip(g_player, char_item->item_index, SHIELD, is_equip_now);
break;
case HEALING:
if(g_player->health_points < g_player->char_def.health_points)
{
g_player->health_points += app->m_mil[char_item->item_index].value;
if(g_player->health_points > char_def.health_points)
g_player->health_points = char_def.health_points;
is_consume = true;
}
break;
}
// reduce quantity if flagged as use once and consume flag
if(check_bit(app->m_mil[char_item->item_index].flags, USEONCE) && is_consume)
{
if(char_item->quantity == 1)
g_player->char_ics->remove(char_item);
else
char_item->quantity--;
}
app->play_sound(SOUND_BEEP);
}
} // [end] if(app->m_mouse.get_button_state(MOUSE_LBUTTON))
// render the scene
begin_display_scene();
app->render_frame(0);
app->m_text_window.render(NULL, COLOR_WHITE);
app->m_text_header.render(NULL, COLOR_WHITE);
// display inventory on left
draw_font(app->m_font, "Inventory:", 8, 96, 0, 0, D3DCOLOR_RGBA(255, 213, 191, 255), DT_LEFT);
long index = 0;
for(sCharItem* item_ptr = g_player->char_ics->get_root_item(); item_ptr != NULL; item_ptr = item_ptr->next)
{
// calculate color to draw based on mouse position
long color = ((index == sel) ? D3DCOLOR_RGBA(255, 255, 0, 255) : D3DCOLOR_RGBA(128, 128, 128, 255));
// display item name and quantity
char text[256];
sprintf(text, "%lu x %s", item_ptr->quantity, app->m_mil[item_ptr->item_index].name);
long y_pos = index * STATUS_MENU_HEIGHT + STATUS_TOP_HEIGHT;
draw_font(app->m_font, text, 32, y_pos, 0, 0, color, DT_LEFT);
// if item is equipped, then show E next to it.
if(char_def.weapon == item_ptr->item_index ||
char_def.armor == item_ptr->item_index ||
char_def.shield == item_ptr->item_index)
{
draw_font(app->m_font, "E", 16, y_pos, 0, 0, color, DT_LEFT);
}
index++; // go down one line
}
static const int x_pos = 250;
char text[256];
// display character's stats at top-right
draw_font(app->m_font, "Stats:", x_pos, 32, 0, 0,
D3DCOLOR_RGBA(255, 213, 191, 255), DT_LEFT);
sprintf(text, "HP: %ld/%ld", g_player->health_points, char_def.health_points);
draw_font(app->m_font, text, x_pos + 20, 64, 0, 0, COLOR_WHITE, DT_LEFT);
sprintf(text, "MP: %ld/%ld", g_player->mana_points, char_def.mana_points);
draw_font(app->m_font, text, x_pos + 20, 96, 0, 0, COLOR_WHITE, DT_LEFT);
sprintf(text, "Level(Max %lu): %lu", MAX_PLAYER_LEVEL, char_def.level);
draw_font(app->m_font, text, x_pos + 20, 128, 0, 0, COLOR_WHITE, DT_LEFT);
if(char_def.level < MAX_PLAYER_LEVEL)
sprintf(text, "Exp/Next: %lu/%lu", char_def.exp, g_level_up_exp[char_def.level-1]);
else
sprintf(text, "Exp/Next: %lu/99999", char_def.exp);
draw_font(app->m_font, text, x_pos + 20, 160, 0, 0, COLOR_WHITE, DT_LEFT);
sprintf(text, "$: %lu", char_def.money);
draw_font(app->m_font, text, x_pos + 20, 192, 0, 0, COLOR_LIGHT_YELLOW, DT_LEFT);
long change = 0;
// print attack
if(g_player->char_def.weapon == -1)
sprintf(text, "Attack: %lu", char_def.attack);
else
{
change = app->m_game_chars.get_attack(g_player) - char_def.attack;
sprintf(text, "Attack: %lu + %lu", char_def.attack, change);
}
draw_font(app->m_font, text, x_pos + 220, 64, 0, 0, COLOR_WHITE, DT_LEFT);
// print defense
if(char_def.armor == -1 && char_def.shield == -1)
sprintf(text, "Defense: %lu", char_def.defense);
else
{
change = app->m_game_chars.get_defense(g_player) - char_def.defense;
sprintf(text, "Defense: %lu + %lu", char_def.defense, change);
}
draw_font(app->m_font, text, x_pos + 220, 96, 0, 0, COLOR_WHITE, DT_LEFT);
sprintf(text, "Agility: %lu", char_def.agility);
draw_font(app->m_font, text, x_pos + 220, 128, 0, 0, COLOR_WHITE, DT_LEFT);
sprintf(text, "Registance: %lu", char_def.resistance);
draw_font(app->m_font, text, x_pos + 220, 160, 0, 0, COLOR_WHITE, DT_LEFT);
sprintf(text, "Mental: %lu", char_def.mental);
draw_font(app->m_font, text, x_pos + 220, 192, 0, 0, COLOR_WHITE, DT_LEFT);
sprintf(text, "ToHit: %lu", char_def.to_hit);
draw_font(app->m_font, text, x_pos + 220, 224, 0, 0, COLOR_WHITE, DT_LEFT);
// display known spells at right
draw_font(app->m_font, "Spells:", x_pos , 240, 0, 0, D3DCOLOR_RGBA(255, 213, 191, 255), DT_LEFT);
for(long i = 0; i < NUM_SPELL_DEF; i++)
{
if(char_def.magic_spell[i/32] & (1 << (i & 31)))
{
sSpell* spell = app->m_game_spells.get_spell(i);
if(i == SPELL_HEAL)
{
sprintf(text, "%lu: %s (Cost MP: %lu, Heal HP: %lu)",
i+1, spell->name, spell->cost, (long)spell->value[0]);
}
else if(i == SPELL_TELEPORT)
{
sprintf(text, "%lu: %s (Cost MP: %lu, Move to town!)", i+1, spell->name, spell->cost);
}
else
{
sprintf(text, "%lu: %s (Cost MP: %lu, Damage: %lu)",
i+1, spell->name, spell->cost, -(long)spell->value[0]);
}
draw_font(app->m_font, text, x_pos + 20, i * STATUS_MENU_HEIGHT + 272, 0, 0, COLOR_WHITE, DT_LEFT);
}
}
end_display_scene();
present_display();
}
}
barter_frame:
The last of the state
functions, barter_frame displays the store clerk's wares and allows the
player to click-and-buy those items for sale.
void barter_frame(void* data, long purpose)
{
static cCharIcs char_ics;
cApp* app = (cApp*) data;
if(purpose == INIT_PURPOSE) // initialize barter data
{
app->m_keyboard.m_locks[KEY_SPACE] = true;
app->m_keyboard.set_key_state(KEY_SPACE, false);
app->m_mouse.m_locks[MOUSE_LBUTTON] = true;
app->m_mouse.set_button_state(MOUSE_LBUTTON, false);
char_ics.load(g_barter_ics_file);
app->m_text_header.set_text("Shop", COLOR_WHITE);
app->m_text_window.set_text("\r\n\nWhat would you like to buy?", COLOR_WHITE);
}
else if(purpose == SHUTDOWN_PURPOSE)
{
char_ics.free();
}
else // process a frame of bartering
{
// exit bartering if ESC or right mouse button pressed
if(app->m_keyboard.get_key_state(KEY_ESC) || app->m_mouse.get_button_state(MOUSE_RBUTTON))
{
app->m_keyboard.m_locks[KEY_ESC] = true;
app->m_mouse.m_locks[MOUSE_RBUTTON] = true;
app->m_state_manager.pop(app);
return;
}
// dertermine which item is selected with mouse
long sel = app->m_mouse.get_y_pos() - BARTER_TOP_HEIGHT;
if(sel >= 0)
sel /= BARTER_MENU_HEIGHT;
// see if click on item to buy
if(app->m_mouse.get_button_state(MOUSE_LBUTTON))
{
app->m_mouse.m_locks[MOUSE_LBUTTON] = true;
// see which item was clicked
if(sel >= 0 && sel < char_ics.get_num_items())
{
sCharItem* char_item = char_ics.get_item(sel);
// make sure player has enough gold for item
if(g_player->char_def.money >= app->m_mil[char_item->item_index].price)
{
sCharItem* item_ptr;
// search for item alreay in inventory
for(item_ptr = g_player->char_ics->get_root_item(); item_ptr != NULL; item_ptr = item_ptr->next)
{
// increase quantity if item already in inventory
if(char_item->item_index == item_ptr->item_index)
{
item_ptr->quantity++;
break;
}
}
// add item to player's inventory if not already
if(item_ptr == NULL)
g_player->char_ics->add(char_item->item_index, 1, NULL);
g_player->char_def.money -= app->m_mil[char_item->item_index].price;
app->play_sound(SOUND_BEEP);
}
}
}
// render the bartering scene
begin_display_scene();
app->render_frame(0);
app->m_text_window.render(NULL, COLOR_WHITE);
app->m_text_header.render(NULL, COLOR_WHITE);
// display items to buy
long index = 0;
char text[256];
for(sCharItem* char_item = char_ics.get_root_item(); char_item != NULL; char_item = char_item->next)
{
// calculate color to draw based on mouse position
long color = ((index == sel) ? D3DCOLOR_RGBA(255, 255, 0, 255) : D3DCOLOR_RGBA(128, 128, 128, 255));
// display item name
long pos_y = index * BARTER_MENU_HEIGHT + BARTER_TOP_HEIGHT;
draw_font(app->m_font, app->m_mil[char_item->item_index].name, 32, pos_y, 0, 0, color, D3DFMT_UNKNOWN);
// display item price
sprintf(text, "$%lu", app->m_mil[char_item->item_index].price);
draw_font(app->m_font, text, 300, pos_y, 0, 0, color, D3DFMT_UNKNOWN);
index++;
}
// display character's gold at top-right
sprintf(text, "Money: $%lu", g_player->char_def.money);
draw_font(app->m_font, text, 320, 32, 0, 0, COLOR_WHITE, D3DFMT_UNKNOWN);
end_display_scene();
present_display();
}
}