summaryrefslogblamecommitdiff
path: root/src/being.cpp
blob: 504c5ab454da4be9599b7a8c1725ad6e7ff603a1 (plain) (tree)



















                                                                             
        
   

                  
                  
 
                 



                     
                              
 
                    
 
                             


                                           
 

 

                                              
                                
                         
                    
                 
                                
              
            

                    
               
                               

                   

                                         
 
                

 

               
                
                 
 
 
                                                      
 



                                                    

 

                       
                  

 
                                     
 
                 
 
                                         



                              

 
                                      
 
                      
                                                        


                      

 
                                      
 
                      
                                                    




                      

                                                      

                  

                            

 

                                            
 






                                       

                            

 

                       
 












                                                

 

                 
 
               
 
                      
     
                       
               
     
 

                                   
 








                           
 


                  
                                 

 

              
 


                                                         

                           
 
                                                         
                                             
     
                           

     



                               


                        






                                

 







                                                              
                                                               

 
    






                                                                      
                                                         




                                 
                                                                     
 


                           
                                   

                   
                                      
                                                                            
     



                                   




                                             
                                      





                                           

         
                                                     

                                                      
 
                                                                      
                                  


                                                                            


                                                      
     
 
 
                                  
 
                   
 
 
                                        




























                                                         
                                              
 

                                                             

                 
 
                                                                 
 





                                                           

                                                        
                         



                  
/*
 *  The Mana World
 *  Copyright 2004 The Mana World Development Team
 *
 *  This file is part of The Mana World.
 *
 *  The Mana World 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 World 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 World; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  $Id$
 */
#include "being.h"

#include <sstream>

#include "game.h"
#include "graphics.h"
#include "log.h"
#include "map.h"

#include "graphic/spriteset.h"

#include "gui/gui.h"

extern Spriteset *emotionset;

PATH_NODE::PATH_NODE(Uint16 iX, Uint16 iY):
    x(iX), y(iY)
{
}

Being::Being(Uint32 id, Uint16 job, Map *map):
    job(job),
    x(0), y(0), direction(DOWN),
    action(0), mFrame(0),
    speech_color(0),
    walk_time(0),
    emotion(0), emotion_time(0),
    aspd(350),
    mId(id),
    mWeapon(0),
    mWalkSpeed(150),
    mMap(NULL),
    hairStyle(1), hairColor(1),
    speech_time(0),
    damage_time(0),
    showSpeech(false), showDamage(false),
    mSpriteset(NULL), mSpriteFrame(0)
{
    setMap(map);
}

Being::~Being()
{
    clearPath();
    setMap(NULL);
}

void Being::setDestination(Uint16 destX, Uint16 destY)
{
    if (mMap)
    {
        setPath(mMap->findPath(x, y, destX, destY));
    }
}

void Being::clearPath()
{
    mPath.clear();
}

void Being::setPath(const Path &path)
{
    mPath = path;

    if (action != WALK && action != DEAD)
    {
        nextStep();
        walk_time = tick_time;
    }
}

void Being::setHairColor(Uint16 color)
{
    hairColor = color;
    if (hairColor < 1 || hairColor > NR_HAIR_COLORS + 1)
    {
        hairColor = 1;
    }
}

void Being::setHairStyle(Uint16 style)
{
    hairStyle = style;
    if (hairStyle < 1 || hairStyle > NR_HAIR_STYLES)
    {
        hairStyle = 1;
    }
}

void
Being::setSpeech(const std::string &text, Uint32 time)
{
    speech = text;
    speech_time = tick_time;
    showSpeech = true;
}

void
Being::setDamage(Sint16 amount, Uint32 time)
{
    if (!amount) {
        damage = "miss";
    } else {
        std::stringstream damageString;
        damageString << amount;
        damage = damageString.str();
    }
    damage_time = tick_time;
    showDamage = true;
}

void
Being::setMap(Map *map)
{
    // Remove sprite from potential previous map
    if (mMap != NULL)
    {
        mMap->removeSprite(mSpriteIterator);
    }

    mMap = map;

    // Add sprite to potential new map
    if (mMap != NULL)
    {
        mSpriteIterator = mMap->addSprite(this);
    }
}

void
Being::nextStep()
{
    mFrame = 0;

    if (mPath.empty())
    {
        action = STAND;
        return;
    }

    PATH_NODE node = mPath.front();
    mPath.pop_front();

    direction = 0;
    if (node.x > x)
        direction |= RIGHT;
    else if (node.x < x)
        direction |= LEFT;
    if (node.y > y)
        direction |= DOWN;
    else if (node.y < y)
        direction |= UP;

    x = node.x;
    y = node.y;
    action = WALK;
    walk_time += mWalkSpeed / 10;
}

void
Being::logic()
{
    // Determine whether speech should still be displayed
    if (get_elapsed_time(speech_time) > 5000)
    {
        showSpeech = false;
    }

    // Determine whether damage should still be displayed
    if (get_elapsed_time(damage_time) > 3000)
    {
        showDamage = false;
    }

    // Update pixel coordinates
    mPx = x * 32;
    mPy = y * 32;

    mPy += getYOffset();
    mPx += getXOffset();

    if (emotion != 0)
    {
        emotion_time--;
        if (emotion_time == 0) {
            emotion = 0;
        }
    }
}

void Being::draw(Graphics *graphics, int offsetX, int offsetY)
{
    if (!mSpriteset)
        return;

    int px = mPx + offsetX;
    int py = mPy + offsetY;

    graphics->drawImage(mSpriteset->get(mSpriteFrame), px, py);
}

void
Being::drawEmotion(Graphics *graphics, Sint32 offsetX, Sint32 offsetY)
{
    int px = mPx + offsetX;
    int py = mPy + offsetY;

    if (emotion)
    {
        graphics->drawImage(emotionset->get(emotion - 1),
                px + 3, py - 60);
    }
}

void
Being::drawSpeech(Graphics *graphics, Sint32 offsetX, Sint32 offsetY)
{
    int px = mPx + offsetX;
    int py = mPy + offsetY;

    // Draw speech above this being
    if (showSpeech)
    {
        graphics->setFont(speechFont);
        graphics->drawText(speech, px + 18, py - 60, gcn::Graphics::CENTER);
    }

    // Draw damage above this being
    if (showDamage)
    {
        // Selecting the right color
        if (damage == "miss")
        {
            graphics->setFont(hitYellowFont);
        }
        else if (getType() == MONSTER)
        {
            graphics->setFont(hitBlueFont);
        }
        else
        {
            graphics->setFont(hitRedFont);
        }

        int textY = (getType() == MONSTER) ? 32 : 70;
        int ft = get_elapsed_time(damage_time) - 1500;
        float a = (ft > 0) ? 1.0 - ft / 1500.0 : 1.0;

        graphics->setColor(gcn::Color(255, 255, 255, (int)(255 * a)));
        graphics->drawText(damage,
                           px + 16,
                           py - textY - get_elapsed_time(damage_time) / 100,
                           gcn::Graphics::CENTER);

        // Reset alpha value
        graphics->setColor(gcn::Color(255, 255, 255));
    }
}

Being::Type Being::getType() const
{
    return UNKNOWN;
}

void Being::setWeaponById(Uint16 weapon)
{
    switch (weapon)
    {
    case 529: // iron arrows
    case 1199: // arrows
        break;

    case 1200: // bow
    case 530: // short bow
    case 545: // forest bow
        setWeapon(2);
        break;

    case 521: // sharp knife
    case 522: // dagger
    case 536: // short sword
    case 1201: // knife
        setWeapon(1);
        break;

    case 0: // unequip
        setWeapon(0);
        break;

    default:
        logger->log("unknown item equiped : %d", weapon);
    }
}

int Being::getOffset(char pos, char neg) const
{
    // Check whether we're walking in the requested direction
    if (action != WALK || !(direction & (pos | neg))) {
        return 0;
    }

    int offset = (get_elapsed_time(walk_time) * 32) / mWalkSpeed;

    // We calculate the offset _from_ the _target_ location
    offset -= 32;
    if (offset > 0) {
        offset = 0;
    }

    // Going into negative direction? Invert the offset.
    if (direction & pos) {
        offset = -offset;
    }

    return offset;
}