www.pudn.com > SimpleMUD.rar > Player.cpp
// MUD Programming // Ron Penton // (C)2003 // Player.cpp - The class defining Players in the SimpleMUD // // #include#include #include #include #include "SimpleMUDLogs.h" #include "Player.h" #include "Item.h" namespace SimpleMUD { Player::Player() { m_pass = "UNDEFINED"; m_rank = REGULAR; m_connection = 0; m_loggedin = false; m_active = false; m_newbie = true; m_experience = 0; m_level = 1; m_room = 1; m_money = 0; m_nextattacktime = 0; m_baseattributes[STRENGTH] = 1; m_baseattributes[HEALTH] = 1; m_baseattributes[AGILITY] = 1; m_items = 0; m_weapon = -1; m_armor = -1; m_statpoints = 18; RecalculateStats(); m_hitpoints = GetAttr( MAXHITPOINTS ); } int Player::NeedForNextLevel() { // how much more experience to the next level return NeedForLevel( m_level + 1 ) - m_experience; } bool Player::Train() { if( NeedForNextLevel() <= 0 ) { m_statpoints += 2; m_baseattributes[MAXHITPOINTS] += m_level; m_level++; RecalculateStats(); return true; } else { return false; } } void Player::RecalculateStats() { m_attributes[MAXHITPOINTS] = 10 + ( (int)(m_level * ( GetAttr( HEALTH ) / 1.5 )) ); m_attributes[HPREGEN] = ( GetAttr( HEALTH ) / 5 ) + m_level; m_attributes[ACCURACY] = GetAttr( AGILITY ) * 3; m_attributes[DODGING] = GetAttr( AGILITY ) * 3; m_attributes[DAMAGEABSORB] = GetAttr( STRENGTH ) / 5; m_attributes[STRIKEDAMAGE] = GetAttr( STRENGTH ) / 5; // make sure the hitpoints don't overflow if your max goes down if( m_hitpoints > GetAttr( MAXHITPOINTS ) ) m_hitpoints = GetAttr( MAXHITPOINTS ); if( Weapon() != 0 ) AddDynamicBonuses( Weapon() ); if( Armor() != 0 ) AddDynamicBonuses( Armor() ); } void Player::AddDynamicBonuses( item p_item ) { if( p_item == 0 ) return; Item& i = *p_item; for( int x = 0; x < NUMATTRIBUTES; x++ ) m_attributes[x] += i.GetAttr( x ); } void Player::SetBaseAttr( int p_attr, int p_val ) { m_baseattributes[p_attr] = p_val; RecalculateStats(); } void Player::AddToBaseAttr( int p_attr, int p_val ) { m_baseattributes[p_attr] += p_val; RecalculateStats(); } void Player::AddHitpoints( int p_hitpoints ) { SetHitpoints( m_hitpoints + p_hitpoints ); } void Player::SetHitpoints( int p_hitpoints ) { m_hitpoints = p_hitpoints; if( m_hitpoints < 0 ) m_hitpoints = 0; if( m_hitpoints > GetAttr( MAXHITPOINTS ) ) m_hitpoints = GetAttr( MAXHITPOINTS ); } bool Player::PickUpItem( item p_item ) { if( m_items < MaxItems() ) { // find the first open index to put the item in. item* itr = m_inventory; while( *itr != 0 ) ++itr; // insert the item *itr = p_item; m_items++; return true; } return false; } bool Player::DropItem( int p_index ) { if( m_inventory[p_index] != 0 ) { // remove the weapon or armor if needed if( m_weapon == p_index ) RemoveWeapon(); if( m_armor == p_index ) RemoveArmor(); m_inventory[p_index] = 0; m_items--; return true; } return false; } void Player::AddBonuses( item p_item ) { if( p_item == 0 ) return; Item& itm = *p_item; for( int i = 0; i < NUMATTRIBUTES; i++ ) m_baseattributes[i] += itm.GetAttr( i ); RecalculateStats(); } void Player::RemoveWeapon() { m_weapon = -1; RecalculateStats(); } void Player::RemoveArmor() { m_armor = -1; RecalculateStats(); } void Player::UseWeapon( int p_index ) { RemoveWeapon(); m_weapon = p_index; RecalculateStats(); } void Player::UseArmor( int p_index ) { RemoveArmor(); m_armor = p_index; RecalculateStats(); } // ------------------------------------------------------------------------ // This gets the index of an item within the players inventory given a // name. // ------------------------------------------------------------------------ int Player::GetItemIndex( const std::string& p_name ) { item* i = double_find_if( m_inventory, m_inventory + MaxItems(), matchentityfull( p_name ), matchentity( p_name ) ); if( i == m_inventory + MaxItems() ) return -1; return (int)(i - m_inventory); } // ------------------------------------------------------------------------ // This sends a string to the players connection. // ------------------------------------------------------------------------ void Player::SendString( const std::string& p_string ) { using namespace SocketLib; if( Conn() == 0 ) { ERRORLOG.Log( "Trying to send string to player " + Name() + " but player is not connected." ); return; } // send the string, newline included. Conn()->Protocol().SendString( *Conn(), p_string + newline ); if( Active() ) { PrintStatbar(); } } // ------------------------------------------------------------------------ // This prints up the players "statbar", ie: his hitpoints. // ------------------------------------------------------------------------ void Player::PrintStatbar( bool p_update ) { using namespace SocketLib; using namespace BasicLib; // if this is a statusbar update and the user is currently typing something, // then do nothing. if( p_update && Conn()->Protocol().Buffered() > 0 ) return; string statbar = white + bold + "["; int ratio = 100 * HitPoints() / GetAttr( MAXHITPOINTS ); // color code your hitpoints so that they are red if low, // yellow if medium, and green if high. if( ratio < 33 ) statbar += red; else if( ratio < 67 ) statbar += yellow; else statbar += green; statbar += tostring( HitPoints() ) + white + "/" + tostring( GetAttr( MAXHITPOINTS ) ) + "] "; Conn()->Protocol().SendString( *Conn(), clearline + "\r" + statbar + reset ); } // -------------------------------------------------------------------- // Inserts an item in text form into a stream // -------------------------------------------------------------------- ostream& operator<<( ostream& p_stream, const Player& p ) { p_stream << "[NAME] " << p.m_name << "\n"; p_stream << "[PASS] " << p.m_pass << "\n"; p_stream << "[RANK] " << GetRankString( p.m_rank ) << "\n"; p_stream << "[STATPOINTS] " << p.m_statpoints << "\n"; p_stream << "[EXPERIENCE] " << p.m_experience << "\n"; p_stream << "[LEVEL] " << p.m_level << "\n"; p_stream << "[ROOM] " << p.m_room << "\n"; p_stream << "[MONEY] " << p.m_money << "\n"; p_stream << "[HITPOINTS] " << p.m_hitpoints << "\n"; p_stream << "[NEXTATTACKTIME] "; insert( p_stream, p.m_nextattacktime ); p_stream << "\n"; p_stream << p.m_baseattributes; p_stream << "[INVENTORY] "; for( int i = 0; i < p.MaxItems(); i++ ) { p_stream << p.m_inventory[i] << " "; } p_stream << "\n"; p_stream << "[WEAPON] " << p.m_weapon << "\n"; p_stream << "[ARMOR] " << p.m_armor << "\n"; return p_stream; } // -------------------------------------------------------------------- // Extracts an item in text form from a stream // -------------------------------------------------------------------- istream& operator>>( istream& p_stream, Player& p ) { std::string temp; p_stream >> temp >> std::ws; std::getline( p_stream, p.m_name ); p_stream >> temp >> p.m_pass; p_stream >> temp >> temp; p.m_rank = GetRank( temp ); p_stream >> temp >> p.m_statpoints; p_stream >> temp >> p.m_experience; p_stream >> temp >> p.m_level; p_stream >> temp >> p.m_room; p_stream >> temp >> p.m_money; p_stream >> temp >> p.m_hitpoints; p_stream >> temp; extract( p_stream, p.m_nextattacktime ); p_stream >> p.m_baseattributes; p_stream >> temp; p.m_items = 0; for( int i = 0; i < p.MaxItems(); i++ ) { p_stream >> p.m_inventory[i]; if( p.m_inventory[i] != 0 ) p.m_items++; } p_stream >> temp >> p.m_weapon; p_stream >> temp >> p.m_armor; p.RecalculateStats(); return p_stream; } } // end namespace SimpleMUD