summaryrefslogblamecommitdiff
path: root/src/game-server/character.h
blob: 8b015f98755f594a3d8ca8fd0c222b89b268729d (plain) (tree)
1
2
3
4
5
6
7
8
9
10
  
                   
                                                            
  
                                         
  



                                                                           
  



                                                                      
  

                                                                            

   

                   
 
                           
                                 
                                     
 
                              

                                       
                             
 
                         
 
              
              


                 
              

                 
                 
            
            
 
                   
 
                                      



                                                                

      

                           
                                                   

  
   

                               
                                                    

   

                                                                
                              

           
           


                                                                       
                                  
 

                     
           



                                                                        
                              

           




                                                                           


                                      

           






                                                                      

                                      
                                                     

           

                                                         
















                                                                                

           











                                                                                 
                                 

           











                                     
                                               
           
                                                 


                                
                                               



                                     
           
                                                              
           











                                                                


                                                              
                                      
           











                                                    
 
          

                              
                                                               

           

                                                         
 

                                                            
 

                                                            
 

                                                    
 

                                                             
 

                                                 
                          




                                                 
           

                                                                  
           
                          

           

                                                           
           
                             

           

                                                           
           
                           
 
           
                                                  
           
                                    

           




                                                                         




                                                                     
           
                                               
 
           




                                                 




                                                                            



                                                                         
                                                                            
 




                                                                      
 


                                                                    
           
                                            










                                                                             
                                        













                                                                          
                                      



                                    
                                                                

                                     
                                                              


                                   
                                                

                                          
                                                   

           
                                                

                                                
                                                                       

           
                                                                          



                                                 
                                                                            
           
                                                

           




                                                                 




                                            










                                                                   

                                                                          
 

                                                                            
 
 



















                                                                             


                                            

                                                      
                                           

                            
                                           
 


                                





                                                            




                                                    
                                             
 
                                               
 

                                                            
            

                                                      




                                                                 

                                                
 


                                                                                                      
                                                 








                                                          




                                                
           

                                                        
                                             



                                                        
                                          





                                           




                                                                        


                                                   
                                                       






                                                           

                                                                       
 
                                                                           
 
                                                     


                                             
                                                                                   
 
                             
                                                                             
                                                                                           
                                                                                    
                                  
 
                                                                     

                                                                         

                                                                              



                                                                                                      
                                                                       
                                                                      
                                                                                                 
                                                                                                      

                                                                                                 
                                                                                            
 

                                                                                         

                                       

                                                  
                                          
 


                                                                           

  
                     
/*
 *  The Mana Server
 *  Copyright (C) 2004-2010  The Mana World Development Team
 *
 *  This file is part of The Mana Server.
 *
 *  The Mana Server is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  The Mana Server is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with The Mana Server.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef CHARACTER_H
#define CHARACTER_H

#include "common/defines.h"
#include "common/inventorydata.h"
#include "common/manaserv_protocol.h"

#include "game-server/being.h"
#include "game-server/specialmanager.h"

#include "scripting/script.h"

#include "utils/logger.h"

#include <map>
#include <set>
#include <string>
#include <vector>

class BuySell;
class GameClient;
class MessageIn;
class MessageOut;
class Point;
class Trade;

struct SpecialValue
{
    SpecialValue(unsigned currentMana,
                 const SpecialManager::SpecialInfo *specialInfo)
        : currentMana(currentMana)
        , rechargeSpeed(specialInfo->defaultRechargeSpeed)
        , specialInfo(specialInfo)
    {}

    unsigned currentMana;
    unsigned rechargeSpeed;
    const SpecialManager::SpecialInfo *specialInfo;
};

/**
 * Stores specials by their id.
 */
typedef std::map<unsigned, SpecialValue> SpecialMap;

/**
 * The representation of a player's character in the game world.
 */
class Character : public Being
{
    public:
        /**
         * Utility constructor for creating a Character from a received
         * characterdata message.
         */
        Character(MessageIn &msg);

        ~Character();

        /**
         * recalculates the level when necessary and calls Being::update
         */
        void update();

        void processAttacks();

        /**
         * Executes the global die script and calls the base class function
         */
        virtual void died();

        /**
         * makes the character respawn
         */
        void respawn();

        /**
         * makes the character perform a special action on a being
         * when it is allowed to do so
         */
        void useSpecialOnBeing(int id, Being *b);

        /**
         * makes the character perform a special action on a map point
         * when it is allowed to do so
         */
        void useSpecialOnPoint(int id, int x, int y);

        /**
         * Allows a character to perform a special action
         */
        bool giveSpecial(int id, int currentMana = 0);

        /**
         * Sets new current mana + makes sure that the client will get informed.
         */
        bool setSpecialMana(int id, int mana);

        /**
         * Gets the special value by id
         */
        SpecialMap::iterator findSpecial(int id)
        { return mSpecials.find(id); }

        /**
         * Sets recharge speed of a special
         */
        bool setSpecialRechargeSpeed(int id, int speed);

        /**
         * Removes all specials from character
         */
        void clearSpecials();

        /**
         * Checks if a character knows a special action
         */
        bool hasSpecial(int id) { return mSpecials.find(id) != mSpecials.end(); }

        /**
         * Removes an available special action
         */
        bool takeSpecial(int id);

        /**
         * Gets client computer.
         */
        GameClient *getClient() const
        { return mClient; }

        /**
         * Sets client computer.
         */
        void setClient(GameClient *c)
        { mClient = c; }

        /**
         * Gets a reference to the possessions.
         */
        const Possessions &getPossessions() const
        { return mPossessions; }

        /**
         * Gets a reference to the possessions.
         */
        Possessions &getPossessions()
        { return mPossessions; }

        /**
         * Gets the Trade object the character is involved in.
         */
        Trade *getTrading() const;

        /**
         * Sets the Trade object the character is involved in.
         * Cancels other transactions.
         */
        void setTrading(Trade *t);

        /**
         * Gets the BuySell object the character is involved in.
         */
        BuySell *getBuySell() const;

        /**
         * Sets the trade object the character is involved in.
         * Cancels other transactions.
         */
        void setBuySell(BuySell *t);

        /**
         * Cancels current transaction.
         */
        void cancelTransaction();

        /**
         * Gets transaction status of the character.
         */
        bool isBusy() const
        { return mTransaction != TRANS_NONE; }

        /*
         * Character data:
         * Get and set methods
         * Most of this should be accessed directly as a friend
         */

        int getDatabaseID() const { return mDatabaseID; }
        void setDatabaseID(int id) { mDatabaseID = id; }

        int getHairStyle() const { return mHairStyle; }
        void setHairStyle(int style) { mHairStyle = style; }

        int getHairColor() const { return mHairColor; }
        void setHairColor(int color) { mHairColor = color; }

        int getLevel() const { return mLevel; }
        void setLevel(int level) { mLevel = level; }

        int getAccountLevel() const { return mAccountLevel; }
        void setAccountLevel(int l) { mAccountLevel = l; }

        /** Gets the party id of the character */
        int getParty() const
        { return mParty; }

        /** Sets the party id of the character */
        void setParty(int party)
        { mParty = party; }

        /**
         * Sends a message that informs the client about attribute
         * modified since last call.
         */
        void sendStatus();

        /**
         * Gets the ID of the map that the character is on.
         * For serialization purpose only.
         */
        int getMapId() const;

        /**
         * Sets the ID of the map that the character is on.
         * For serialization purpose only.
         */
        void setMapId(int);

        /**
         * Marks all attributes as being modified.
         */
        void modifiedAllAttribute();

        /**
          * Recalculate the base value of an attribute and update derived
          *     attributes if it has changed.
          */
         void recalculateBaseAttribute(unsigned);


        /**
         * Attribute has changed, recalculate base value of dependant
         *     attributes (and handle other actions for the modified
         *     attribute)
         */
        void updateDerivedAttributes(unsigned);

        /**
         * Calls all the "disconnected" listener.
         */
        void disconnected();

        /**
         * Associative array containing all the quest variables known by the
         * server.
         */
        std::map< std::string, std::string > questCache;

        /**
         * Gives a skill a specific amount of exp and checks if a levelup
         * occured.
         */
        void receiveExperience(int skill, int experience, int optimalLevel);

        int getSkillSize() const
        { return mExperience.size(); }

        const std::map<int, int>::const_iterator getSkillBegin() const
        { return mExperience.begin(); }

        const std::map<int, int>::const_iterator getSkillEnd() const
        { return mExperience.end(); }

        /**
         * Used to serialize status effects.
         */
        int getStatusEffectSize() const
        { return mStatusEffects.size(); }

        const std::map<int, int>::const_iterator getStatusEffectBegin() const
        { return mStatusEffects.begin(); }

        const std::map<int, int>::const_iterator getStatusEffectEnd() const
        { return mStatusEffects.end(); }

        /**
         * Used to serialize kill count.
         */
        int getKillCountSize() const
        { return mKillCount.size(); }

        const std::map<int, int>::const_iterator getKillCountBegin() const
        { return mKillCount.begin(); }

        const std::map<int, int>::const_iterator getKillCountEnd() const
        { return mKillCount.end(); }

        void setKillCount(int monsterId, int kills)
        { mKillCount[monsterId] = kills; }

        /**
         * Used to serialize specials.
         */
        int getSpecialSize() const
        { return mSpecials.size(); }

        const SpecialMap::const_iterator getSpecialBegin() const
        { return mSpecials.begin(); }

        const SpecialMap::const_iterator getSpecialEnd() const
        { return mSpecials.end(); }

        /**
         * Gets total accumulated exp for skill.
         */
        int getExperience(int skill) const
        { return mExperience.find(skill)->second; }

        /**
         * Sets total accumulated exp for skill.
         */
        void setExperience(int skill, int value)
        { mExperience[skill] = 0; receiveExperience(skill, value, 0); }

        /**
         * Adds one kill of the monster type to the characters kill count.
         */
        void incrementKillCount(int monsterType);

        /**
         * Gets the number of monsters the character killed of a given type.
         */
        int getKillCount(int monsterType) const;

        /**
         * Returns the exp needed to reach a specific skill level
         */
        static int expForLevel(int level);

        /**
         * Returns the level for a given exp
         */
        static int levelForExp(int exp);

        /**
         * Tries to use a character point to increase a
         * basic attribute
         */
        AttribmodResponseCode useCharacterPoint(size_t attribute);

        /**
         * Tries to use a correction point to reduce a
         * basic attribute and regain a character point
         */
        AttribmodResponseCode useCorrectionPoint(size_t attribute);

        void setCharacterPoints(int points) { mCharacterPoints = points; }
        int getCharacterPoints() const { return mCharacterPoints; }

        void setCorrectionPoints(int points) { mCorrectionPoints = points; }
        int getCorrectionPoints() const { return mCorrectionPoints; }


        /**
         * Starts the given NPC thread.
         *
         * Should be called immediately after creating the thread and pushing
         * the NPC function and its parameters.
         */
        void startNpcThread(Script::Thread *thread, int npcId);

        /**
         * Resumes the given NPC thread of this character and sends the NPC
         * close message to the player when the script is done.
         *
         * Should be called after preparing the current Script instance for
         * resuming the thread and pushing the parameters the script expects.
         */
        void resumeNpcThread();

        /**
         * Returns the NPC thread in use by this character, if any.
         */
        Script::Thread *getNpcThread() const
        { return mNpcThread; }

        /** Makes it impossible to chat for a while */
        void mute(int seconds)
        { mMuteTimeout.set(seconds * 10); }

        bool isMuted() const
        { return !mMuteTimeout.expired(); }

        bool isConnected() const
        { return mConnected; }

        static void setDeathCallback(Script *script)
        { script->assignCallback(mDeathCallback); }

        static void setDeathAcceptedCallback(Script *script)
        { script->assignCallback(mDeathAcceptedCallback); }

        static void setLoginCallback(Script *script)
        { script->assignCallback(mLoginCallback); }

        void triggerLoginCallback();

        void attackAdded(Attack &attackInfo);

        void attackRemoved(Attack &attackInfo);

        sigc::signal<void, Character *> signal_disconnected;

    private:
        bool specialUseCheck(SpecialMap::iterator it);

        double getAttrBase(AttributeMap::const_iterator it) const
        { return it->second.getBase(); }
        double getAttrMod(AttributeMap::const_iterator it) const
        { return it->second.getModifiedAttribute(); }

        Character(const Character &);
        Character &operator=(const Character &);

        static const float EXPCURVE_EXPONENT;
        static const float EXPCURVE_FACTOR;
        static const float LEVEL_SKILL_PRECEDENCE_FACTOR; // I am taking suggestions for a better name
        static const float EXP_LEVEL_FLEXIBILITY;
        static const int CHARPOINTS_PER_LEVELUP = 5;
        static const int CORRECTIONPOINTS_PER_LEVELUP = 2;
        static const int CORRECTIONPOINTS_MAX = 10;

        /**
         * Advances the character by one level;
         */
        void levelup();

        /**
         * Marks attribute as recently modified.
         */
        void flagAttribute(int);

        /**
         * Returns the exp needed for next skill levelup
         */
        int getExpNeeded(size_t skill) const;

        /**
         * Returns the exp collected on this skill level
         */
        int getExpGot(size_t skill) const;

        /**
         * Recalculates the character level
         */
        void recalculateLevel();

        /**
         * Informs the client about his characters special charge status
         */
        void sendSpecialUpdate();

        enum TransactionType
        { TRANS_NONE, TRANS_TRADE, TRANS_BUYSELL };

        GameClient *mClient;   /**< Client computer. */

        /**
         * Tells whether the character client is connected.
         * Useful when dealing with enqueued events.
         */
        bool mConnected;

        /** Handler of the transaction the character is involved in. */
        void *mTransactionHandler;

        Possessions mPossessions;    /**< Possesssions of the character. */

        /** Attributes modified since last update. */
        std::set<size_t> mModifiedAttributes;
        std::set<size_t> mModifiedExperience;

        std::map<int, int> mExperience; /**< experience collected for each skill.*/

        SpecialMap mSpecials;
        std::map<int, int> mStatusEffects; /**< only used by select functions
                                                to make it easier to make the accountserver
                                                do not modify or use anywhere else*/
        bool mSpecialUpdateNeeded;

        int mDatabaseID;             /**< Character's database ID. */
        unsigned char mHairStyle;    /**< Hair Style of the character. */
        unsigned char mHairColor;    /**< Hair Color of the character. */
        int mLevel;                  /**< Level of the character. */
        int mLevelProgress;          /**< progress to next level in percent */
        int mCharacterPoints;        /**< Unused attribute points that can be distributed */
        int mCorrectionPoints;       /**< Unused attribute correction points */
        bool mUpdateLevelProgress;   /**< Flag raised when percent to next level changed */
        bool mRecalculateLevel;      /**< Flag raised when the character level might have increased */
        unsigned char mAccountLevel; /**< Account level of the user. */
        int mParty;                  /**< Party id of the character */
        TransactionType mTransaction; /**< Trade/buy/sell action the character is involved in. */
        std::map<int, int> mKillCount;  /**< How many monsters the character has slain of each type */

        int mTalkNpcId;              /**< Public ID of NPC the character is talking to, if any */
        Script::Thread *mNpcThread;  /**< Script thread executing NPC interaction, if any */

        Timeout mMuteTimeout;        /**< Time until the character is no longer muted  */

        AttackInfo *mKnuckleAttackInfo;

        static Script::Ref mDeathCallback;
        static Script::Ref mDeathAcceptedCallback;
        static Script::Ref mLoginCallback;

        // Set as a friend, but still a lot of redundant accessors. FIXME.
        template< class T >
        friend void serializeCharacterData(const T &data, MessageOut &msg);
};

#endif // CHARACTER_H