summaryrefslogblamecommitdiff
path: root/src/game-server/monster.h
blob: 600196f7900741340bf7445a07dd3cab39730c15 (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 MONSTER_H
#define MONSTER_H

#include "game-server/being.h"
#include "game-server/eventlistener.h"
#include "common/defines.h"
#include "scripting/script.h"
#include "utils/string.h"

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

class ItemClass;
class Script;

/**
 * Structure containing an item class and its probability to be dropped
 * (unit: 1/10000).
 */
struct MonsterDrop
{
    ItemClass *item;
    int probability;
};

typedef std::vector< MonsterDrop > MonsterDrops;

/**
 * Structure containing different attack types of a monster type
 */
struct MonsterAttack
{
    unsigned id;
    int priority;
    float damageFactor;
    Element element;
    DamageType type;
    int preDelay;
    int aftDelay;
    int range;
    std::string scriptEvent;
};

/**
 * Class describing the characteristics of a generic monster.
 */
class MonsterClass
{
    public:
        MonsterClass(int id):
            mId(id),
            mName("unnamed"),
            mGender(GENDER_UNSPECIFIED),
            mSpeed(1),
            mSize(16),
            mExp(-1),
            mAggressive(false),
            mTrackRange(1),
            mStrollRange(0),
            mMutation(0),
            mAttackDistance(0),
            mOptimalLevel(0)
        {}

        ~MonsterClass();

        /**
         * Returns monster type. This is the Id of the monster class.
         */
        int getId() const
        { return mId; }

        /**
         * Returns the name of the monster type
         */
        const std::string &getName() const
        { return mName; }

        /**
         * Sets the name of the monster type
         */
        void setName(const std::string &name)
        { mName = name; }

        void setGender(BeingGender gender)
        { mGender = gender; }

        BeingGender getGender() const
        { return mGender; }

        /**
         * Sets monster drops. These are the items the monster drops when it
         * dies.
         */
        void setDrops(const MonsterDrops &v)
        { mDrops = v; }

        /**
         * Sets a being base attribute.
         */
        void setAttribute(int attribute, double value)
        { mAttributes[attribute] = value; }

        /**
         * Returns a being base attribute.
         */
        double getAttribute(int attribute) const
        { return mAttributes.at(attribute); }

        /**
         * Returns whether the monster has got the attribute.
         */
        bool hasAttribute(int attribute) const
        { return (mAttributes.find(attribute) != mAttributes.end()); }

        /** Sets collision circle radius. */
        void setSize(int size) { mSize = size; }

        /** Returns collision circle radius. */
        int getSize() const { return mSize; }

        /** Sets experience reward for killing the monster. */
        void setExp(int exp) { mExp = exp; }

        /** Returns experience reward for killing the monster. */
        int getExp() const { return mExp; }

        /** Gets maximum skill level after which exp reward is reduced */
        void setOptimalLevel(int level) { mOptimalLevel = level; }

        /** Sets maximum skill level after which exp reward is reduced. */
        int getOptimalLevel() const { return mOptimalLevel; }

        /** Sets if the monster attacks without being attacked first. */
        void setAggressive(bool aggressive) { mAggressive = aggressive; }

        /** Returns if the monster attacks without being attacked first. */
        bool isAggressive() const { return mAggressive; }

        /** Sets range in tiles in which the monster searches for enemies. */
        void setTrackRange(unsigned range){ mTrackRange = range; }

        /**
         * Returns range in tiles in which the monster searches for enemies.
         */
        unsigned getTrackRange() const { return mTrackRange; }

        /** Sets range in pixels in which the monster moves around when idle. */
        void setStrollRange(unsigned range) { mStrollRange = range; }

        /**
         * Returns range in pixels in which the monster moves around when idle.
         */
        unsigned getStrollRange() const { return mStrollRange; }

        /** Sets mutation factor in percent. */
        void setMutation(unsigned factor) { mMutation = factor; }

        /** Returns mutation factor in percent. */
        unsigned getMutation() const { return mMutation; }

        /** Sets preferred combat distance in pixels. */
        void setAttackDistance(unsigned distance)
        { mAttackDistance = distance; }

        /** Returns preferred combat distance in pixels. */
        unsigned getAttackDistance() const { return mAttackDistance; }

        /** Adds an attack to the monsters repertoire. */
        void addAttack(AttackInfo *info) { mAttacks.push_back(info); }

        /** Returns all attacks of the monster. */
        std::vector<AttackInfo *> &getAttackInfos() { return mAttacks; }

        /** sets the script file for the monster */
        void setScript(const std::string &filename) { mScript = filename; }

        /** Returns script filename */
        const std::string &getScript() const { return mScript; }

        void setUpdateCallback(Script *script)
        { script->assignCallback(mUpdateCallback); }

        void setDamageCallback(Script *script)
        { script->assignCallback(mDamageCallback); }

        Script::Ref getUpdateCallback() const
        { return mUpdateCallback; }

        Script::Ref getDamageCallback() const
        { return mDamageCallback; }

    private:
        unsigned short mId;
        std::string mName;
        BeingGender mGender;

        MonsterDrops mDrops;
        std::map<int, double> mAttributes; /**< Base attributes of the monster. */
        float mSpeed; /**< The monster class speed in tiles per second */
        int mSize;
        int mExp;

        bool mAggressive;
        int mTrackRange;
        int mStrollRange;
        int mMutation;
        int mAttackDistance;
        int mOptimalLevel;
        std::vector<AttackInfo *> mAttacks;
        std::string mScript;

        /**
         * A reference to the script function that is called each update.
         */
        Script::Ref mUpdateCallback;

        /**
         * A reference to the script that is called when a mob takes damage.
         */
        Script::Ref mDamageCallback;

        friend class MonsterManager;
        friend class Monster;
};

/**
 * Structure holding possible positions relative to the target from which
 * the monster can attack
 */
struct AttackPosition
{
    AttackPosition(int posX, int posY, BeingDirection dir):
        x(posX),
        y(posY),
        direction(dir)
    {}

    int x;
    int y;
    BeingDirection direction;
};

/**
 * The class for a fightable monster with its own AI
 */
class Monster : public Being
{
    public:
        /** Time in game ticks until ownership of a monster can change. */
        static const int KILLSTEAL_PROTECTION_TIME = 100;

        Monster(MonsterClass *);
        ~Monster();

        /**
         * Returns monster specy.
         */
        MonsterClass *getSpecy() const
        { return mSpecy; }

        /**
         * Performs one step of controller logic.
         */
        void update();

        void refreshTarget();

        /**
         * Performs an attack
         */
        virtual void processAttack(Attack &attack);

        /**
         * Loads a script file for this monster
         */
        void loadScript(const std::string &scriptName);

        /**
         * Kills the being.
         */
        void died();

        /**
         * Alters hate for the monster
         */
        void changeAnger(Actor *target, int amount);

        const std::map<Being *, int> &getAngerList() const
        { return mAnger; }

        /**
         * Calls the damage function in Being and updates the aggro list
         */
        virtual int damage(Actor *source, const Damage &damage);

        /**
         * Removes a being from the anger list.
         */
        void forgetTarget(Entity *being);

        /**
         * Called when an attribute modifier is changed.
         * Recalculate the base value of an attribute and update derived
         *     attributes if it has changed.
         * @returns Whether it was changed.
         */
        virtual bool recalculateBaseAttribute(unsigned int);

    protected:
        /**
         * Returns the way the actor blocks pathfinding for other objects.
         */
        virtual BlockType getBlockType() const
        { return BLOCKTYPE_MONSTER; }

    private:
        static const int DECAY_TIME = 50;

        int calculatePositionPriority(Point position, int targetPriority);

        MonsterClass *mSpecy;

        /** Aggression towards other beings. */
        std::map<Being *, int> mAnger;

        /** Listener for updating the anger list. */
        EventListener mTargetListener;

        /**
         * Character who currently owns this monster (killsteal protection).
         */
        Character *mOwner;

        /** Factor for damage mutation */
        unsigned mDamageMutation;

        /** List of characters and their skills that attacked this monster. */
        std::map<Character *, std::set <size_t> > mExpReceivers;

        /**
         * List of characters who are entitled to receive exp (killsteal
         * protection).
         */
        std::set<Character *> mLegalExpReceivers;

        /**
         * Set positions relative to target from which the monster can attack.
         */
        std::list<AttackPosition> mAttackPositions;

        /** Time until monster strolls to new location */
        Timeout mStrollTimeout;
        /** Kill steal protection time */
        Timeout mKillStealProtectedTimeout;
        /** Time until dead monster is removed */
        Timeout mDecayTimeout;

        friend struct MonsterTargetEventDispatch;
};

#endif // MONSTER_H