Logo Search packages:      
Sourcecode: adonthell version File versions  Download package

mapcharacter.cc

Go to the documentation of this file.
/*
   $Id: mapcharacter.cc,v 1.49 2003/02/17 19:31:21 ksterker Exp $

   Copyright (C) 1999/2000/2001/2002 Alexandre Courbot
   Part of the Adonthell Project http://adonthell.linuxgames.com

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/

/** 
 * @file mapcharacter.cc
 *
 * @author Alexandre Courbot <alexandrecourbot@linuxgames.com>
 * @brief Defines the mapcharacter class.
 */
 
#include "mapcharacter.h"
#include "map_event.h"
#include "time_event.h"
#include "event_handler.h"
#include "landmap.h"
#include "win_manager.h"

using namespace std; 


// Public methods
00033 mapcharacter::mapcharacter () : mapsquare_walkable_area (), character_base (), event_list ()
{
    submap_ = posx_ = posy_ = offx_ = offy_ = 0;
    refmap = NULL;
    anim.resize (NBR_MOVES);
    for (u_int16 i = 0; i < NBR_MOVES; i++)
        anim[i] = new animation;
    current_move = STAND_NORTH;
    previous_move = NO_MOVE;

    saying = NULL;

    schedule_activated = true;
    action_activated = true; 
    goal_reached_ = true;

    schedule_args = NULL;
    action_args = NULL;
    
    callback = NULL;
}
 
00055 mapcharacter::~mapcharacter ()
{
    clear ();
    for (u_int16 i = 0; i < anim.size (); i++)
        delete anim[i];
    anim.clear (); 
}

00063 void mapcharacter::clear ()
{
    event_list::clear ();
    
    if (saying) delete saying;

    for (u_int16 i = 0; i < anim.size (); i++)
        anim[i]->clear ();
    
    mapsquare_walkable_area::clear (); 
    
    schedule.clear (); 
    action.clear (); 
    
    filename_ = "";

    Py_XDECREF (schedule_args);
    schedule_args = NULL;
    
    Py_XDECREF (action_args);
    action_args = NULL; 
    schedule_file_ = "";
    action_file_ = "";
    
    if (callback) delete callback;
}

00090 s_int8 mapcharacter::get (igzstream& file)
{
    int i;

    for (i = 0; i < NBR_MOVES; i++)
    {
        anim[i]->get (file);
        anim[i]->stop ();
    }

    mapsquare_walkable_area::get (file); 

    return 0;
}

00105 s_int8 mapcharacter::load (string fname)
{
    string s = MAPCHAR_DIR;

    s += fname;
    igzstream file (s);
    if (!file.is_open ())
        return -1;
    
    s_int8 retvalue; 
    if (fileops::get_version (file, 1, 1, s))
        retvalue = get (file);
    file.close ();
    filename_ = fname;

    return 0;
}

00123 s_int8 mapcharacter::put (ogzstream& file) const
{
    int i;

    for (i = 0; i < NBR_MOVES; i++)
    {
        anim[i]->put (file);
    }

    mapsquare_walkable_area::put (file); 

    return 0;
}

00137 s_int8 mapcharacter::save (string fname) const
{
    string s = MAPCHAR_DIR;

    s += fname;
    ogzstream file (s);
    if (!file.is_open ())
        return -1;
    
    s_int8 retvalue; 
    fileops::put_version (file, 1); 
    retvalue = put (file);
    file.close ();

    return 0;
}

00154 s_int8 mapcharacter::get_state (igzstream& file)
{
    string t; 
    bool b;
    u_int16 current_move__; 
    s_int8 offx__, offy__; 
    
    remove_from_pos (); 
    
    t << file; 
    load (t);

    // Reads the data members
    current_move__ << file;
    previous_move << file;
    submap_ << file;
    posx_ << file;
    posy_ << file;
    offx__ << file;
    offy__ << file;

    jump_to (submap (), posx (), posy ());
    set_offset (offx__, offy__); 
    
    current_move = current_move__; 
    
    // Get the path state
    mypath.get_state (file);
    // The map must be attached manually for now! :(
    mypath.refmap = refmap; 
    
    pathindex << file; 
    goal_reached_ << file;
    
    // Schedule state
    PyObject * args; 
    t << file;
    b << file;
    args = NULL; 
    if (b) args = python::get_tuple (file); 
    set_schedule (t, args);      
    Py_XDECREF (args); 
    b << file;
    set_schedule_active (b);

    // Action state
    t << file;
    b << file; 
    args = NULL; 
    if (b) args = python::get_tuple (file); 
    set_action (t, args);      
    Py_XDECREF (args); 
    b << file;
    set_action_active (b);

    // get the events
    py_callback::instance = schedule.get_instance (false);
    return event_list::get_state (file);
}

00214 s_int8 mapcharacter::put_state (ogzstream& file) const
{
    // Write the mapcharacter's file name
    filename_ >> file;

    // Write the data members
    current_move >> file;
    previous_move >> file;
    submap_ >> file;
    posx_ >> file;
    posy_ >> file;
    offx_ >> file;
    offy_ >> file;

    // Save the path state
    mypath.put_state (file);
    pathindex >> file; 
    goal_reached_ >> file;
    
    // Save the schedule script state
    schedule_file () >> file;
    if (schedule_args) 
    {
        true >> file; 
        python::put_tuple (schedule_args, file);
    }
    else false >> file; 
    is_schedule_activated () >> file;
    
    // Save the action script state
    action_file () >> file;
    if (action_args) 
    {
        true >> file; 
        python::put_tuple (action_args, file);
    }
    else false >> file; 
    is_action_activated () >> file; 
    
    // save the events
    event_list::put_state (file);
    
    return 0;
}

00259 void mapcharacter::set_map (landmap * m) 
{
    if (mymap ()) return;

    m->mapchar.push_back (this);
    
    refmap = m;
}

00268 void mapcharacter::remove_from_map ()
{
    if (!mymap ()) return;
    
    leave_position ();
    
    vector <mapcharacter *>::iterator i;
    for (i = mymap ()->mapchar.begin (); (*i) != this; i++);
    mymap ()->mapchar.erase (i); 
    
    refmap = NULL;
}

00281 void mapcharacter::remove_from_pos ()
{
    leave_position (); 
}

00286 void mapcharacter::jump_to (u_int16 smap, u_int16 x, u_int16 y,
                      u_int16 pos)
{
    leave_position (); 
    set_pos (smap, x, y);
    set_offset (0, 0);

    switch (pos)
    {
        case STAND_NORTH:
            stand_north ();
            break;
        case STAND_SOUTH:
            stand_south ();
            break;
        case STAND_WEST:
            stand_west ();
            break;
        case STAND_EAST:
            stand_east ();
            break;
        default:
            stand ();
            break;
    }

    enter_event evt; 
    evt.submap = submap ();
    evt.x = posx ();
    evt.y = posy ();
    evt.c = this;
    evt.dir = pos; 
    event_handler::raise_event (&evt);
}

00321 void mapcharacter::stand ()
{
    if (current_move >= WALK_NORTH && current_move != NO_MOVE)
    {
        previous_move = current_move; 
        current_move -= WALK_NORTH;
    }
}

00330 void mapcharacter::stand_north ()
{
    previous_move = current_move; 
    current_move = STAND_NORTH;
}

00336 void mapcharacter::stand_south ()
{
    previous_move = current_move; 
    current_move = STAND_SOUTH;
}

00342 void mapcharacter::stand_east ()
{
    previous_move = current_move; 
    current_move = STAND_EAST;
}

00348 void mapcharacter::stand_west ()
{
    previous_move = current_move; 
    current_move = STAND_WEST;
}

00354 bool mapcharacter::can_go_north () const
{
    if (!posy ())
        return false;
    u_int16 i, j;
    u_int16 sx = (posx () - base_x ()  < 0) ? 0 : posx () - base_x ();
    u_int16 sy = (posy () - base_y ()  < 0) ? 0 : posy () - base_y ();
    s_int16 ax = sx - (posx () - base_x ());
    s_int16 ay = sy - (posy () - base_y ());
    u_int16 ex =
        (posx () - base_x () + area_length () >
         refmap->submap[submap ()]->area_length ()) ? refmap->submap[submap ()]->area_length ()
        : posx () - base_x () + area_length ();
    u_int16 ey =
        (posy () - base_y () + area_height () >
         refmap->submap[submap ()]->area_height ()) ? refmap->submap[submap ()]->area_height ()
        : posy () - base_y () + area_height ();

    for (j = sy; j < ey; j++)
        for (i = sx; i < ex; i++)
        {
            if (get_square (i - sx + ax, j - sy + ay)->get_walkable ())
                continue;
            if (!j)
                continue;
            if (!(refmap->submap[submap ()]->area[i][j].is_walkable_north () &&
                  refmap->submap[submap ()]->area[i][j - 1].is_walkable_south ()
                  && refmap->submap[submap ()]->area[i][j - 1].is_free ()))
                return false;
        }
    return true;
}

00387 bool mapcharacter::can_go_south () const
{
    if (posy () == refmap->submap[submap ()]->area_height () - 1)
        return false;
    u_int16 i, j;
    u_int16 sx = (posx () - base_x () < 0) ? 0 : posx () - base_x ();
    u_int16 sy = (posy () - base_y () < 0) ? 0 : posy () - base_y ();
    s_int16 ax = sx - (posx () - base_x ());
    s_int16 ay = sy - (posy () - base_y ());
    u_int16 ex =
        (posx () - base_x () + area_length () >=
         refmap->submap[submap ()]->area_length ()) ? refmap->submap[submap ()]->area_length ()
        : posx () - base_x () + area_length ();
    u_int16 ey =
        (posy () - base_y () + area_height () >=
         refmap->submap[submap ()]->area_height ()) ? refmap->submap[submap ()]->area_height ()
        : posy () - base_y () + area_height ();

    for (j = sy; j < ey; j++)
        for (i = sx; i < ex; i++)
        {
            if (get_square (i - sx + ax, j - sy + ay)->get_walkable ())
                continue;
            if (j == refmap->submap[submap ()]->area_height () - 1)
                continue;
            if (!(refmap->submap[submap ()]->area[i][j].is_walkable_south () &&
                  refmap->submap[submap ()]->area[i][j +
                                                  1].is_walkable_north ()
                  && refmap->submap[submap ()]->area[i][j + 1].is_free ()))
                return false;
        }
    return true;
}

00421 bool mapcharacter::can_go_east () const
{
    if (posx () == refmap->submap[submap ()]->area_length () - 1)
        return false;
    u_int16 i, j;
    u_int16 sx = (posx () - base_x () < 0) ? 0 : posx () - base_x ();
    u_int16 sy = (posy () - base_y () < 0) ? 0 : posy () - base_y ();
    s_int16 ax = sx - (posx () - base_x ());
    s_int16 ay = sy - (posy () - base_y ());
    u_int16 ex =
        (posx () - base_x () + area_length () >=
         refmap->submap[submap ()]->area_length ()) ? refmap->submap[submap ()]->area_length ()
        : posx () - base_x () + area_length ();
    u_int16 ey =
        (posy () - base_y () + area_height () >=
         refmap->submap[submap ()]->area_height ()) ? refmap->submap[submap ()]->area_height ()
        : posy () - base_y () + area_height ();

    for (j = sy; j < ey; j++)
        for (i = sx; i < ex; i++)
        {
            if (get_square (i - sx + ax, j - sy + ay)->get_walkable ())
                continue;
            if (i == refmap->submap[submap ()]->area_length () - 1)
                continue;
            if (!(refmap->submap[submap ()]->area[i][j].is_walkable_east () &&
                  refmap->submap[submap ()]->area[i + 1][j].is_walkable_west ()
                  && refmap->submap[submap ()]->area[i + 1][j].is_free ()))
                return false;
        }
    return true;
}

00454 bool mapcharacter::can_go_west () const
{
    if (!posx ())
        return false;
    u_int16 i, j;
    u_int16 sx = (posx () - base_x () < 0) ? 0 : posx () - base_x ();
    u_int16 sy = (posy () - base_y () < 0) ? 0 : posy () - base_y ();
    s_int16 ax = sx - (posx () - base_x ());
    s_int16 ay = sy - (posy () - base_y ());
    u_int16 ex =
        (posx () - base_x () + area_length () >
         refmap->submap[submap ()]->area_length ()) ? refmap->submap[submap ()]->area_length ()
        : posx () - base_x () + area_length ();
    u_int16 ey =
        (posy () - base_y () + area_height () >
         refmap->submap[submap ()]->area_height ()) ? refmap->submap[submap ()]->area_height ()
        : posy () - base_y () + area_height ();

    for (j = sy; j < ey; j++)
        for (i = sx; i < ex; i++)
        {
            if (get_square (i - sx + ax, j - sy + ay)->get_walkable ())
                continue;
            if (!i)
                continue;
            if (!(refmap->submap[submap ()]->area[i][j].is_walkable_west () &&
                  refmap->submap[submap ()]->area[i - 1][j].is_walkable_east ()
                  && refmap->submap[submap ()]->area[i - 1][j].is_free ()))
                return false;
        }
    return true;
}

00487 bool mapcharacter::go_north ()
{
    if (current_move < WALK_NORTH)
    {
        bool ret = can_go_north ();
        previous_move = current_move;  
        if (ret) 
            current_move = WALK_NORTH;
        else current_move = STAND_NORTH;
        return ret; 
    }
    return false; 
}

00501 bool mapcharacter::go_south ()
{
    if (current_move < WALK_NORTH)
    {
        bool ret = can_go_south (); 
        previous_move = current_move;
        if (ret) 
            current_move = WALK_SOUTH;
        else current_move = STAND_SOUTH; 
        return ret; 
    }
    return false; 
}

00515 bool mapcharacter::go_east ()
{
    if (current_move < WALK_NORTH)
    {
        bool ret = can_go_east (); 
        previous_move = current_move;
        if (ret) 
            current_move = WALK_EAST;
        else current_move = STAND_EAST; 
        return ret; 
    }
    return false; 
}

00529 bool mapcharacter::go_west ()
{
    if (current_move < WALK_NORTH)
    {
        bool ret = can_go_west (); 
        previous_move = current_move;
        if (ret) 
            current_move = WALK_WEST;
        else current_move = STAND_WEST; 
        return ret; 
    }
    return false; 
}

bool mapcharacter::set_goal (u_int16 x, u_int16 y, u_int16 dir)
{
    mypath.refmap = mymap ();
    mypath.submap = submap (); 
    mypath.start.x = posx ();
    mypath.start.y = posy (); 
    mypath.goal.x = x;
    mypath.goal.y = y;
    mypath.dir = dir;
    pathindex = 0; 
    goal_reached_ = false;
    
    return mypath.calculate (); 
}

void mapcharacter::set_callback (PyObject *cb, PyObject *args)
{
    if (callback) delete callback;
    callback = new py_callback (cb, args);
}

void mapcharacter::time_callback (string delay, PyObject *cb, PyObject *args)
{
    time_event *ev = new time_event (delay);
    ev->set_callback (cb, args);
    add_event (ev);
}

void mapcharacter::time_callback_string (string delay, string cb, PyObject *args)
{
    PyObject *instance = schedule.get_instance (false);

    // check that we have a valid instance that contains our callback
    if (instance == NULL)
    {
        fprintf (stderr, "*** error: mapcharacter::time_callback: Invalid instance!");
        return;
    }
     
    PyObject *callback = PyObject_GetAttrString (instance, (char *) cb.c_str ());

    if (!PyCallable_Check (callback))
    {
        fprintf (stderr, "*** error: mapcharacter::time_callback: Setting callback ' %s' failed!", cb.c_str ());
    }
    else
    {
        time_event *ev = new time_event (delay);
        ev->set_callback (callback, args);
        add_event (ev);
    }
    
    Py_XDECREF (callback);
}

bool mapcharacter::follow_path () 
{
    //  If a movment is engaged, let it finish first.
    if (offx () || offy ()) 
        return false;
    
    // If the goal isn't reached yet.
    if (pathindex < mypath.nbr_moves ())
    {
        u_int16 dir = mypath.get_move (pathindex);
        u_int8 success = 0; 

        // Try to follow the direction
        switch (dir) 
        {
            case WALK_NORTH:
                if (go_north ()) success = 1; 
                break;

            case WALK_SOUTH:
                if (go_south ()) success = 1; 
                break;
                
            case WALK_WEST:
                if (go_west ()) success = 1; 
                break;
                
            case WALK_EAST:
                if (go_east ()) success = 1; 
                break;
        }
                 
        // Who the fuck is on my way!!?@! I have to find a new path now!
        if (!success) 
        {
            mypath.start.x = posx ();
            mypath.start.y = posy ();
            mypath.submap = submap ();
            mypath.calculate ();
            pathindex = 0; 
        }
        else pathindex++; 
    }
    else
    {
        switch (mypath.dir)
        {
            case STAND_NORTH:
                stand_north ();
                break;
            case STAND_SOUTH:
                stand_south ();
                break;
            case STAND_WEST:
                stand_west ();
                break;
            case STAND_EAST:
                stand_east ();
                break;
        }

        // goal reached -> notify script (as the script might immediately
        // set the next goal, we gotta set goal_reached_ before that)
        goal_reached_ = true;
        if (callback) callback->callback_func0 ();
        return true;
    }
    return false;
}

void mapcharacter::stop_moving ()
{
    set_goal (posx (), posy ());
}

bool mapcharacter::goal_reached () 
{ 
    return goal_reached_;
}

00678 void mapcharacter::look_invert (u_int16 p)
{
    switch (p)
    {
        case STAND_NORTH:
            stand_south ();
            break;
        case STAND_SOUTH:
            stand_north ();
            break;
        case STAND_EAST:
            stand_west ();
            break;
        case STAND_WEST:
            stand_east ();
            break;
    }
}

00697 mapcharacter *mapcharacter::whosnext () const
{
    switch (current_move)
    {
        case STAND_NORTH:
            if (posy () == 0)
                return NULL;
            return refmap->submap[submap ()]->area[posx ()][posy () - 1].whoshere ();
            break;
        case STAND_SOUTH:
            if (posy () == refmap->submap[submap ()]->area_height () - 1)
                return NULL;
            return refmap->submap[submap ()]->area[posx ()][posy () + 1].whoshere ();
            break;
        case STAND_WEST:
            if (posx () == 0)
                return NULL;
            return refmap->submap[submap ()]->area[posx () - 1][posy ()].whoshere ();
            break;
        case STAND_EAST:
            if (posx () == refmap->submap[submap ()]->area_length () - 1)
                return NULL;
            return refmap->submap[submap ()]->area[posx () + 1][posy ()].whoshere ();
            break;
    }
    return NULL;
}

00725 bool mapcharacter::do_stuff (string method, PyObject *args)
{
    if (!schedule.has_attribute (method)) return false;
    else schedule.call_method (method, args);
    
    return true;
}

00733 void mapcharacter::set_schedule (string file, PyObject * args)
{     
    // Clears the schedule
    schedule.clear ();
    Py_XDECREF (schedule_args);
    schedule_args = NULL;

    // Set new schedule
    if (file != "")
    {
        Py_XINCREF (args); 
        schedule_args = args; 
        u_int16 argssize = args == NULL ? 1 : PyTuple_Size (args) + 1; 
        PyObject * theargs;
        
        theargs = PyTuple_New (argssize);
        
        // We can pass_instance directly 'cause PyTuple_SetItem steals a
        // reference to the result of pass_instance.
        PyTuple_SetItem (theargs, 0, python::pass_instance (this, "mapcharacter"));
        for (u_int16 i = 1; i < argssize; i++)
        {
            PyObject * intref = PyTuple_GetItem (args, i - 1);
            Py_INCREF (intref); 
            PyTuple_SetItem (theargs, i, intref); 
        }
        schedule.create_instance ("schedules.mapcharacters." + file, file, theargs);
        Py_DECREF (theargs);
        
        if (!schedule.has_attribute ("run"))
            set_schedule_active (false);
    }
    schedule_file_ = file;
}

00768 void mapcharacter::set_action (string file, PyObject * args)
{     
    // Clears the action script
    action.clear ();
    Py_XDECREF (action_args);
    action_args = NULL;

    if (file != "")
    {
        Py_XINCREF (args);
        action_args = args; 
        u_int16 argssize = args == NULL ? 1 : PyTuple_Size (args) + 1; 
        PyObject * theargs;
        
        theargs = PyTuple_New (argssize);
        
        // We can pass_instance directly 'cause PyTuple_SetItem steals a
        // reference to the result of pass_instance.
        PyTuple_SetItem (theargs, 0, python::pass_instance (this, "mapcharacter"));
        for (u_int16 i = 1; i < argssize; i++)
        {
            PyObject * intref = PyTuple_GetItem (args, i - 1);
            Py_INCREF (intref); 
            PyTuple_SetItem (theargs, i, intref); 
        }
        action.create_instance ("actions." + file, file, theargs);
        Py_DECREF (theargs); 
    }
    action_file_ = file;
}
 
00799 bool mapcharacter::update ()
{
    update_move ();

    if (is_schedule_activated ()) 
        schedule.run ();

    // if we have a goal, then go there!
    if (!goal_reached ()) 
        follow_path ();

    if (previous_move != NO_MOVE && previous_move != current_move) 
    {
        anim[previous_move]->stop ();
        anim[previous_move]->rewind ();
        anim[current_move]->play (); 
    }
    
    if (saying && !saying->update ())
    {
        delete saying;
        saying = NULL; 
    }
        
    return true;
}

00826 void mapcharacter::launch_action (mapcharacter * requester)
{
    PyObject *args = PyTuple_New (1);
    PyTuple_SetItem (args, 0, python::pass_instance (requester, "mapcharacter"));      
    if (is_action_activated ()) action.run (args); 
    Py_DECREF (args);
}

00834 void mapcharacter::draw (s_int16 x, s_int16 y, const drawing_area * da_opt, surface * target) const
{
    anim[current_move]->draw (x, y, da_opt, target);
}

void mapcharacter::draw_bubble (s_int16 x, s_int16 y, const drawing_area * da_opt,
                                surface * target) const
{
    if (saying) 
    {
        s_int16 dx = x - (saying->drawing_area::length () >> 1) + (anim[current_move]->length () >> 1); 
        s_int16 dy = y - (saying->drawing_area::height ()) + 5;

        if (dx < 4) dx = 4;
        else if (dx + saying->drawing_area::length () > da_opt->x () + da_opt->length () - 4)
            dx = da_opt->x () + da_opt->length () - saying->drawing_area::length () - 4; 
        
        saying->move (dx, dy);
        saying->assign_drawing_area (da_opt);
        saying->draw ();
        saying->detach_drawing_area (); 
    }     
}

00858 mapcharacter & mapcharacter::operator = (const mapcharacter & src)
{
    u_int16 i;

    clear (); 

    (mapsquare_walkable_area&) (*this) = (mapsquare_walkable_area&) src;
    (character_base&) (*this) = (character_base&) src;
    
    for (i = 0; i < NBR_MOVES; i++)
        (*anim[i]) = (*src.anim[i]);

    schedule = src.schedule;

    action = src.action;

    current_move = src.currentmove ();
    if (src.mymap ())
    {
        set_map (src.mymap ());
        set_pos (src.submap (), src.posx (), src.posy ());
        set_offset (src.offx (), src.offy ()); 
    }

    filename_ = src.filename_;
    
    return *this;
}



// Private methods


00892 void mapcharacter::occupy (u_int16 smap, u_int16 px, u_int16 py)
{
    mapsquare_char mschar;

    list <mapsquare_char>::iterator it;
    u_int16 sx = (px - base_x () < 0) ? 0 : px - base_x ();
    u_int16 sy = (py - base_y () < 0) ? 0 : py - base_y ();
    u_int16 ex = (sx + area_length () > refmap->submap[smap]->area_length ()) ?
        refmap->submap[smap]->area_length () : sx + area_length ();
    u_int16 ey = (sy + area_height () > refmap->submap[smap]->area_height ()) ?
        refmap->submap[smap]->area_height () : sy + area_height ();
    u_int16 i, j;

    // Placing the base tile first
    mschar.mchar = this;
    mschar.is_base = true;
    mschar.x = px;
    mschar.y = py;
    mschar.walkable =
        get_square (base_x (), base_y ())->get_walkable ()  == ALL_WALKABLE;
    
    refmap->submap[smap]->area[px][py].mapchars.push_back (mschar);
    it = --refmap->submap[smap]->area[px][py].mapchars.end ();
    it->base_tile = it;
    mschar.base_tile = it;
    mschar.is_base = false;
    
    // Ready to place the rest now
    for (i = sx; i < ex; i++)
        for (j = sy; j < ey; j++)
            if (i != px || j != py)
            {
                mschar.x = i;
                mschar.y = j;
                mschar.walkable =
                    get_square (sx + base_x () - px, sy + base_y () - py)->
                    get_walkable () == ALL_WALKABLE;
                refmap->submap[smap]->area[i][j].mapchars.push_back (mschar);
            }
} 

00933 void mapcharacter::leave (u_int16 smap, u_int16 px, u_int16 py)
{
    list <mapsquare_char>::iterator it;
    list <mapsquare_char>::iterator e;

    u_int16 sx = (px - base_x () < 0) ? 0 : px - base_x ();
    u_int16 sy = (py - base_y () < 0) ? 0 : py - base_y ();
    u_int16 ex = (sx + area_length () > refmap->submap[smap]->area_length ()) ?
        refmap->submap[smap]->area_length () : sx + area_length ();
    u_int16 ey = (sy + area_height () > refmap->submap[smap]->area_height ()) ?
        refmap->submap[smap]->area_height () : sy + area_height ();
    u_int16 i, j;


    for (i = sx; i < ex; i++)
        for (j = sy; j < ey; j++)
        {
            it = refmap->submap[smap]->area[i][j].mapchars.begin ();
            e = refmap->submap[smap]->area[i][j].mapchars.end ();

            while (it != e && it->mchar != this)
                it++;
            if (it != e)
                refmap->submap[smap]->area[px][py].mapchars.erase (it);
        }
}

void mapcharacter::leave_position () 
{
    leave (submap (), posx (), posy ());
    switch (current_move) 
    {
        case WALK_NORTH: 
        case WALK_SOUTH:
            leave (submap (), posx (), posy () - 1);
            break;
            
        case WALK_WEST:
        case WALK_EAST:
            leave (submap (), posx () - 1, posy ());
            break;
    }
}

00977 void mapcharacter::set_pos (u_int16 smap, u_int16 x, u_int16 y)
{
    // update character position
    submap_ = smap;
    posx_ = x;
    posy_ = y;

    // mark the character's place as occupied
    occupy (submap (), posx (), posy ()); 
}

00988 void mapcharacter::update_move ()
{
    if (refmap)
        switch (currentmove ())
        {
            case WALK_NORTH:
                if (!offy ())
                {
                    if (!can_go_north ())
                    {
                        stand_north ();
                        break;
                    }
                    leave_event evt;
                    
                    evt.submap = submap ();
                    evt.x = posx ();
                    evt.y = posy ();
                    evt.c = this;
                    evt.dir = WALK_NORTH; 
                    event_handler::raise_event (&evt);
                    
                    occupy (submap (), posx (), posy () - 1);
                    set_offset (offx (), offy () - 1);
                }
                
                set_offset (offx (), offy () - 1);

                if (offy () == -MAPSQUARE_SIZE)
                {
                    leave (submap (), posx (), posy ());
                    leave (submap (), posx (), posy () - 1);
                    set_pos (submap (), posx (), posy () - 1);
                    set_offset (offx (), 0); 
                    stand_north ();
                    
                    enter_event evt;

                    evt.submap = submap ();
                    evt.x = posx ();
                    evt.y = posy ();
                    evt.c = this;
                    evt.dir = WALK_NORTH; 
                    event_handler::raise_event (&evt);
                }
                break;
            case WALK_SOUTH:
                if (!offy ())
                {
                    if (!can_go_south ())
                    {
                        stand_south ();
                        break;
                    }
                    leave_event evt;

                    evt.submap = submap ();
                    evt.x = posx ();
                    evt.y = posy ();
                    evt.c = this;
                    evt.dir = WALK_SOUTH; 
                    event_handler::raise_event (&evt);

                    leave (submap (), posx (), posy ());
                    occupy (submap (), posx (), posy ());
                    set_pos (submap (), posx (), posy () + 1);
                    set_offset (0, -(MAPSQUARE_SIZE - 1));
                 }
                else
                {
                    set_offset (offx (), offy () + 1);

                    if (!offy ())
                    {
                        leave (submap (), posx (), posy () - 1);
                        stand_south ();

                        enter_event evt; 
                        evt.submap = submap ();
                        evt.x = posx ();
                        evt.y = posy ();
                        evt.c = this;
                        evt.dir = WALK_SOUTH; 
                        event_handler::raise_event (&evt);
                    }
                }
                break;
            case WALK_WEST:
                if (!offx ())
                {
                    if (!can_go_west ())
                    {
                        stand_west ();
                        break;
                    }
                    leave_event evt;

                    evt.submap = submap ();
                    evt.x = posx ();
                    evt.y = posy ();
                    evt.c = this;
                    evt.dir = WALK_WEST; 
                    event_handler::raise_event (&evt);

                    occupy (submap (), posx () - 1, posy ()); 
                }
                set_offset (offx () -1, offy ());  
                if (offx () == -MAPSQUARE_SIZE)
                {
                    leave (submap (), posx (), posy ());
                    leave (submap (), posx () - 1, posy ());
                    set_pos (submap (), posx () - 1, posy ());
                    set_offset (0, offy ());  
                    stand_west ();
                    
                    enter_event evt; 
                    evt.submap = submap ();
                    evt.x = posx ();
                    evt.y = posy ();
                    evt.c = this;
                    evt.dir = WALK_WEST; 
                    event_handler::raise_event (&evt);
                }
                break;
            case WALK_EAST:
                if (!offx ())
                {
                    if (!can_go_east ())
                    {
                        stand_east ();
                        break;
                    }
                    leave_event evt;
                    
                    evt.submap = submap ();
                    evt.x = posx ();
                    evt.y = posy ();
                    evt.c = this;
                    evt.dir = WALK_EAST; 
                    event_handler::raise_event (&evt);

                    leave (submap (), posx (), posy ());
                    occupy (submap (), posx (), posy ());
                    set_pos (submap (), posx () + 1, posy ());
                    set_offset (-(MAPSQUARE_SIZE - 1), 0);  
                }
                else
                {
                    set_offset (offx () + 1, offy ());  
                    if (!offx ())
                    {
                        leave (submap (), posx () - 1, posy ());
                        stand_east ();
                        
                        enter_event evt; 
                        evt.submap = submap ();
                        evt.x = posx ();
                        evt.y = posy ();
                        evt.c = this;
                        evt.dir = WALK_EAST; 
                        event_handler::raise_event (&evt);
                    }
                }
                break;
        }
    anim[current_move]->update ();     
}

void mapcharacter::speak (const string & text)
{
    if (saying)
        delete saying;

    string col; 
    switch (get_color ()) 
    { 
        case 1: col = "yellow"; break; 
        case 2: col = "red"; break; 
        case 3: col = "violet"; break; 
        case 4: col = "blue"; break; 
        case 5: col = "green"; break;
        default: col = "white"; break; 
    } 
    
    saying = new text_bubble (text, col, "original"); 
}

Generated by  Doxygen 1.6.0   Back to index