/* ....[@@@..[@@@..............[@.................. MUD++ is a written from ....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and ....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++. ....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing ....[@......[@..[@@@@@..[@@@@@.................. development project. All ................................................ contributions are welcome. ....Copyright(C).1995.Melvin.Smith.............. Enjoy. ------------------------------------------------------------------------------ Melvin Smith (aka Fusion) msmith@falcon.mercer.peachnet.edu MUD++ development mailing list mudpp-list@spice.com ------------------------------------------------------------------------------ char.cc */ #include "config.h" #include "io.h" #include "string.h" #include "llist.h" #include "indexable.h" #include "room.h" #include "affect.h" #include "spell.h" #include "char.h" #include "global.h" Char::~Char() { Object *obj; Affect *aff; Attack *att; while( ( obj = inv.remove() ) ) { obj->fromWorld(); delete obj; } while( ( obj = wearlist.remove() ) ) { obj->fromWorld(); delete obj; } while( ( aff = affects.remove() ) ) delete aff; while( ( att = attacks.remove() ) ) delete att; } Object *Char::getObjInv( const String & arg ) { Object *obj; inv.reset(); while( ( obj = inv.peek() ) ) { inv.next(); if( obj->wearPos() ) continue; if( obj->isName( arg ) ) return obj; } return 0; } Object *Char::getSecondObjInv( const String & arg ) { Object *obj; inv.reset(); while( ( obj = inv.peek() ) ) { inv.next(); if( obj->wearPos() ) continue; if( obj->isName( arg ) ) while( ( obj = inv.peek() ) ) { inv.next(); if( obj->wearPos() ) continue; if( obj->isName( arg ) ) return obj; } } return 0; } void Char::addObjInv( Object * obj ) { obj->toChar( this ); carried_weight += obj->getWeight(); carried_count++; inv.add( obj ); } void Char::rmObjInv( Object * obj ) { obj->fromChar(); carried_weight -= obj->getWeight(); carried_count--; inv.remove( obj ); } Object *Char::getObjWear( const String & arg ) { Object *obj; inv.reset(); while( ( obj = inv.peek() ) ) { inv.next(); if( !obj->wearPos() ) continue; if( obj->isName( arg ) ) return obj; } return 0; } Object *Char::getObjWear( int pos ) { if( !IS_SET( eq_bits, pos ) ) return 0; Object *obj; inv.reset(); while( ( obj = inv.peek() ) ) { inv.next(); if( obj->wearPos() == pos ) return obj; } return 0; } int Char::canWear( Object *item, int pos ) { switch( pos ) { default: return 0; case EQ_HEAD: return item->wearBit( WEAR_HEAD ); case EQ_FACE: return item->wearBit( WEAR_FACE ); case EQ_NECK_2: case EQ_NECK_1: return item->wearBit( WEAR_NECK ); case EQ_BACK: return item->wearBit( WEAR_BACK ); case EQ_BODY: return item->wearBit( WEAR_BODY ); case EQ_ARMS: return item->wearBit( WEAR_ARMS ); case EQ_WRIST_L: case EQ_WRIST_R: return item->wearBit( WEAR_WRIST ); case EQ_HANDS: return item->wearBit( WEAR_HANDS ); case EQ_HOLD_L: case EQ_HOLD_R: return item->wearBit( WEAR_HOLD ); case EQ_FINGER_L: case EQ_FINGER_R: return item->wearBit( WEAR_FINGER ); case EQ_WAIST: return item->wearBit( WEAR_WAIST ); case EQ_LEGS: return item->wearBit( WEAR_LEGS ); case EQ_FEET: return item->wearBit( WEAR_FEET ); case EQ_SHIELD_L: case EQ_SHIELD_R: return item->wearBit( WEAR_SHIELD ); case EQ_WIELD_L: case EQ_WIELD_R: return item->wearBit( WEAR_WIELD ); } } void Char::wear( Object *obj, int pos ) { Modifier *mod; if( obj->wearPos() ) { Cout<< "Wear( item ) : item already worn\n"; return; } // Do eq mods on character, if any obj->mods.reset(); while( ( mod = obj->mods.peek() ) ) { obj->mods.next(); modify( mod, true ); } SET_BIT( eq_bits, pos ); obj->setWearPos( pos ); } void Char::equip( Object *obj, int bit ) { switch( bit ) { case WEAR_HEAD: if( !IS_SET( eq_bits, EQ_HEAD ) ) wear( obj, EQ_HEAD ); return; case WEAR_NECK: if( !IS_SET( eq_bits, EQ_NECK_1 ) ) wear( obj, EQ_NECK_1 ); else if( !IS_SET( eq_bits, EQ_NECK_2 ) ) wear( obj, EQ_NECK_2 ); return; case WEAR_BACK: if( !IS_SET( eq_bits, EQ_BACK ) ) wear( obj, EQ_BACK ); return; case WEAR_BODY: if( !IS_SET( eq_bits, EQ_BODY ) ) wear( obj, EQ_BODY ); return; case WEAR_ARMS: if( !IS_SET( eq_bits, EQ_ARMS ) ) wear( obj, EQ_ARMS ); return; case WEAR_WRIST: if( !IS_SET( eq_bits, EQ_WRIST_L ) ) wear( obj, EQ_WRIST_L ); else if( !IS_SET( eq_bits, EQ_WRIST_R ) ) wear( obj, EQ_WRIST_R ); return; case WEAR_HANDS: if( !IS_SET( eq_bits, EQ_HANDS ) ) wear( obj, EQ_HANDS ); return; case WEAR_HOLD: if( !IS_SET( eq_bits, EQ_HOLD_L ) ) wear( obj, EQ_HOLD_L ); else if( !IS_SET( eq_bits, EQ_HOLD_R ) ) wear( obj, EQ_HOLD_R ); return; case WEAR_FINGER: if( !IS_SET( eq_bits, EQ_FINGER_L ) ) wear( obj, EQ_FINGER_L ); else if( !IS_SET( eq_bits, EQ_FINGER_R ) ) wear( obj, EQ_FINGER_R ); return; case WEAR_WAIST: if( !IS_SET( eq_bits, EQ_WAIST ) ) wear( obj, EQ_WAIST ); return; case WEAR_LEGS: if( !IS_SET( eq_bits, EQ_LEGS ) ) wear( obj, EQ_LEGS ); return; case WEAR_FEET: if( !IS_SET( eq_bits, EQ_FEET ) ) wear( obj, EQ_FEET ); return; // Add checks here for hold/shield/wield combos case WEAR_SHIELD: if( !IS_SET( eq_bits, EQ_SHIELD_L ) ) wear( obj, EQ_SHIELD_L ); else if( !IS_SET( eq_bits, EQ_SHIELD_R ) ) wear( obj, EQ_SHIELD_R ); return; case WEAR_WIELD: if( !IS_SET( eq_bits, EQ_WIELD_R ) ) wear( obj, EQ_WIELD_R ); else if( !IS_SET( eq_bits, EQ_WIELD_L) ) wear( obj, EQ_WIELD_L ); return; default: return; } } void Char::wield( Object * obj, int leftright ) { // incomplete equip( obj, WEAR_WIELD ); } void Char::remove( Object *obj ) { Modifier *mod; if( !obj->wearPos() ) return; // Negate eq mods on character, if any obj->mods.reset(); while( ( mod = obj->mods.peek() ) ) { obj->mods.next(); modify( mod, false ); } CLEAR_BIT( eq_bits, obj->wearPos() ); obj->setWearPos( 0 ); } void Char::put( Object * obj, Object * container ) { obj->fromChar(); inv.remove( obj ); container->addObjInv( obj ); } int Char::getStr () const { return strength; } int Char::getInt () const { return intel; } int Char::getWis () const { return wis; } int Char::getCon () const { return con; } int Char::getDex () const { return dex; } int Char::getSpd () const { return speed; } void Char::get( Object *obj ) { String str; in_room->rmObjInv( obj ); if( obj->isGold() ) { str << "\n\r" << shortdesc << " gets " << obj->getShort() << ".\n\r"; in_room->outAllCharExcept( str, this, 0 ); gold += obj->getValue(); obj->extract(); delete obj; return; } addObjInv( obj ); } void Char::drop( Object *obj ) { rmObjInv( obj ); in_room->addObjInv( obj ); } bool Char::open( Exit * door ) { char buf[ 256 ]; // Incomplete: add other side if( door->isOpen() ) return true; door->rmIsClosed(); sprintf( buf, "%s opens the door.\n\r" ); in_room->outAllCharExcept( buf, this, 0 ); return true; } bool Char::close( Exit * door ) { char buf[ 256 ]; // Incomplete: add other side if( door->isClosed() ) return true; door->setIsClosed(); sprintf( buf, "%s closes the door.\n\r" ); in_room->outAllCharExcept( buf, this, 0 ); return true; } bool Char::moveDir( int dir ) { if( dir >= MAX_DIR || !in_room || !in_room->getExit( dir ) ) return false; char buf[BUF]; const Exit *door = in_room->getExit( dir ); if( ! door ) return false; Room *to = door->toRoom(); if( ! to ) return false; if( door->isClosed() ) { out( "The door is closed.\n\r" ); return false; } sprintf( buf, "\n\r%s walks %s.\n\r", shortdesc.chars(), getDirName( dir ) ); in_room->outAllCharExcept( buf, this, 0 ); sprintf( buf, "\n\r%s has arrived.\n\r", shortdesc.chars() ); in_room->rmCharInv( this ); to->addCharInv( this ); in_room->outAllCharExcept( buf, this, 0 ); return true; } void Char::fromRoom() { in_room = 0; } void Char::toRoom( Room *to ) { in_room = to; } void Char::addAffect( Affect *paf ) { Modifier * mod; paf->mods.reset(); while( ( mod = paf->mods.peek() ) ) { modify( mod, true ); paf->mods.next(); } SET_BIT( aff_bits, paf->getType() ); affects.add( paf ); } void Char::rmAffect( int aftype ) { Affect * paf; Modifier * mod; affects.reset(); while( ( paf = affects.peek() ) ) { if( paf->getType() != aftype ) { affects.next(); continue; } affects.remove(); CLEAR_BIT( aff_bits, aftype ); paf->mods.reset(); while( ( mod = paf->mods.peek() ) ) { modify( mod, false ); paf->mods.next(); } } } void Char::modify( Modifier * mod, bool add ) { int amt = mod->getAmt(); if( !add ) { amt = amt * -1; } switch( mod->getType() ) { case MOD_STR: strength += amt; return; case MOD_DEX: dex += amt; return; case MOD_INT: intel += amt; return; case MOD_WIS: wis += amt; return; case MOD_CON: con += amt; return; case MOD_SPEED: speed += amt; return; case MOD_HP: max_hp += amt; return; case MOD_ARMOR: armor += amt; return; case MOD_DAMROLL: damroll += amt; return; case MOD_HITROLL: hitroll += amt; return; default: return; } } void Char::pulse() { int hpgain = max_hp / 10; int managain = max_mana / 8; if( !affected( AFF_POISON ) ) { hp += hpgain; mana += managain; } else { hp -= hpgain; mana -= managain; } // Update conditions if( hp > max_hp ) hp = max_hp; else if( hp <= 0 ) { out( "You have DIED from poisoning!!!\n\r" ); } if( mana > max_mana ) mana = max_mana; else if( mana < 0 ) mana = 0; // Update affects Affect *paf; affects.reset(); while( ( paf = affects.peek() ) ) { if( paf->pulse() <= 0 ) { // remove affect affects.remove(); Modifier * mod; paf->mods.reset(); while( ( mod = paf->mods.peek() ) ) { // remove the modifier (false = negate) modify( mod, false ); paf->mods.next(); } CLEAR_BIT( aff_bits, paf->getType() ); const Spell *spell = paf->getSpell(); if( spell ) { out( "The affects of " ); out( spell->getName() ); out( " wear off.\n\r" ); } delete paf; } affects.next(); } } void Char::addAttack() { Attack * pattack = new Attack(); attacks.reset(); attacks.add( pattack ); } void Char::rmAttack() { Attack * pattack; attacks.reset(); pattack = attacks.peek( ); attacks.remove(); delete pattack; } void Char::cast( const Spell * spell, Thing * target ) { spell->cast( this, target ); } int Char::gainExp( int x ) { exp += x; return exp; }