summaryrefslogblamecommitdiff
path: root/src/graphic/graphic.cpp
blob: 43768f54dfed9d56afb5dfc404ad8d6047e43da4 (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

		By ElvenProgrammer aka Eugenio Favalli (umperio@users.sourceforge.net)

*/

#include "graphic.h"

#define TILESET_W 480
#define TILESET_H 320

#ifdef WIN32
#pragma warning (disable:4312)
#endif

#include <allegro.h>
#include "../game.h"
#include "../map.h"
#include "../being.h"
#include "../gui/chat.h"
#include "../gui/inventory.h"
#include "../gui/shop.h"
#include "../../data/graphic/gfx_data.h"

BITMAP *buffer, *double_buffer, *chat_background;
DATAFILE *tileset;
char page_num;
int map_x, map_y, camera_x, camera_y;
DIALOG_PLAYER *chat_player, *npc_player, *skill_player, *buy_sell_player, *buy_player, *sell_player;
char speech[255] = "";
char npc_text[1000] = "";
TmwInventory inventory;
Chat chatlog("./docs/chatlog.txt", 20);
int show_npc_dialog = 0;
bool show_skill_dialog = false;

DIALOG npc_dialog[] = {
   /* (dialog proc)     (x)   (y)   (w)   (h)   (fg)  (bg)  (key) (flags)  (d1)                    (d2)  (dp)              (dp2) (dp3) */
   { tmw_dialog_proc,     300,  200,  260,  150,  0,    0,    0,    0,       0,                0,    (char *)"NPC",             NULL, NULL  },
   { tmw_button_proc,     508,  326,  50,   20,   255,  0,    'c',  D_EXIT,  0,                0,    (char *)"&Close",         NULL, NULL  },
   { tmw_textbox_proc,    304,  224,  252,  100,  0,    0,    0,    0,       0,                0,    npc_text,         NULL, NULL  },
   { NULL,                0,    0,    0,    0,    0,    0,    0,    0,       0,                0,    NULL,             NULL, NULL  }
};

DIALOG buy_sell_dialog[] = {
   /* (dialog proc)     (x)   (y)   (w)   (h)   (fg)  (bg)  (key) (flags)  (d1)                    (d2)  (dp)              (dp2) (dp3) */
   { tmw_dialog_proc,     350,  200,  100,  80,   0,    0,    0,    0,       0,                0,    (char *)"Shop",   NULL, NULL  },
   { tmw_button_proc,     360,  225,  80,   20,   255,  0,    0,    D_EXIT,  0,                0,    (char *)"&BUY",   NULL, NULL  },
	 { tmw_button_proc,     360,  250,  80,   20,   255,  0,    0,    D_EXIT,  0,                0,    (char *)"&SELL",  NULL, NULL  },
   { NULL,                0,    0,    0,    0,    0,    0,    0,    0,       0,                0,    NULL,             NULL, NULL  }
};

DIALOG buy_dialog[] = {
   /* (dialog proc)     (x)   (y)   (w)   (h)   (fg)  (bg)  (key) (flags)  (d1)                    (d2)  (dp)              (dp2) (dp3) */
   { tmw_dialog_proc,     300,  200,  260,  150,  0,    0,    0,    0,       0,                0,    (char *)"Buy",     NULL, NULL  },
   { tmw_button_proc,     450,  326,  50,   20,   255,  0,    'o',  D_EXIT,  0,                0,    (char *)"&Ok",     NULL, NULL  },
	 { tmw_button_proc,     508,  326,  50,   20,   255,  0,    'c',  D_EXIT,  0,                0,    (char *)"&Cancel", NULL, NULL  },
   { tmw_list_proc,       304,  224,  252,  100,  0,    0,    0,    0,       0,                0,    (char *)shop_list, NULL, NULL  },
	 { tmw_text_proc,       304,  326,  180,  100,  0,    0,    0,    0,       0,                0,    NULL,              NULL, NULL  },
   { NULL,                0,    0,    0,    0,    0,    0,    0,    0,       0,                0,    NULL,              NULL, NULL  }
};

DIALOG sell_dialog[] = {
   /* (dialog proc)     (x)   (y)   (w)   (h)   (fg)  (bg)  (key) (flags)  (d1)                    (d2)  (dp)              (dp2) (dp3) */
   { tmw_dialog_proc,     300,  200,  260,  150,  0,    0,    0,    0,       0,                0,    (char *)"Sell",    NULL, NULL  },
   { tmw_button_proc,     450,  326,  50,   20,   255,  0,    'o',  D_EXIT,  0,                0,    (char *)"&Ok",     NULL, NULL  },
	 { tmw_button_proc,     508,  326,  50,   20,   255,  0,    'c',  D_EXIT,  0,                0,    (char *)"&Cancel", NULL, NULL  },
   { tmw_list_proc,       304,  224,  252,  100,  0,    0,    0,    0,       0,                0,    (char *)shop_list, NULL, NULL  },
   { NULL,                0,    0,    0,    0,    0,    0,    0,    0,       0,                0,    NULL,              NULL, NULL  }
};

DIALOG chat_dialog[] = {
   /* (dialog proc)         (x)   (y)   (w)  (h) (fg) (bg)  (key) (flags)   (d1)               (d2)           (dp)         (dp2) (dp3) */
   { tmw_edit_proc,          0,  574,  592,  25,  0,    0,    'c',  0,       90,               0,           speech,        NULL, NULL  },
   { NULL,                   0,    0,    0,   0,  0,    0,    0,    0,       0,                0,             NULL,        NULL, NULL  }
};

int get_x_offset(NODE *node) {
	int offset = 0;
	char direction = get_direction(node->coordinates);
	if(node->action==WALK) {
		if(direction==WEST || direction==EAST) {
      offset = node->frame + 1;
      if(offset==5)offset = 0;
      offset *= 4;
			if(direction==WEST) {
				offset = -offset;
				offset += 16;
			} else offset -= 16;
		}
	}
	return offset;
}

int get_y_offset(NODE *node) {
	int offset = 0;
	char direction = get_direction(node->coordinates);
	if(node->action==WALK) {
		if(direction==SOUTH || direction==NORTH) {
      offset = node->frame + 1;
      if(offset==5)offset = 0;
      offset *= 4;
			if(direction==NORTH) {
				offset = -offset;
				offset += 16;
			} else offset -= 16;
		}
	}
	return offset;
}

void init_graphic() {
	tileset = load_datafile("./data/graphic/village.dat");
	if(!tileset)error("Unable to load tileset datafile");
	//if(!(gfx_capabilities & GFX_HW_VRAM_BLIT))allegro_message("Not supporting HW accelerated blit");
	buffer = create_bitmap(SCREEN_W/2, SCREEN_H/2);
	double_buffer = create_bitmap(SCREEN_W, SCREEN_H);

  alfont_set_font_size(gui_font, 16);
	clear_bitmap(screen);
  chat_background = create_bitmap(592, 100);
  clear_to_color(chat_background, makecol(0,0,0));

	// Initialize gui
  chat_player = init_dialog(chat_dialog, -1);
  npc_player = init_dialog(npc_dialog, -1);
	position_dialog(npc_dialog, 300, 200);
	skill_player = init_dialog(skill_dialog, -1);
	buy_sell_player = init_dialog(buy_sell_dialog, -1);
	buy_player = init_dialog(buy_dialog, -1);
	sell_player = init_dialog(sell_dialog, -1);
  gui_bitmap = double_buffer;
	alfont_text_mode(-1);
	inventory.create(100, 100);
}

void do_graphic(void) {

	map_x = (get_x(player_node->coordinates)-13)*16+get_x_offset(player_node);
	map_y = (get_y(player_node->coordinates)-9)*16+get_y_offset(player_node);

  camera_x = map_x >> 4;
	camera_y = map_y >> 4;

  int offset_x = map_x & 15;
	int offset_y = map_y & 15;

	sort();

	for(int j=0;j<20;j++)
		for(int i=0;i<26;i++) {
			if( /* get_tile(i+camera_x, j+camera_y, 0) >= 0 && */  get_tile(i+camera_x, j+camera_y, 0) < 600)
				draw_rle_sprite(buffer, (RLE_SPRITE *)tileset[get_tile(i+camera_x, j+camera_y, 0)].dat, i*16-offset_x, j*16-offset_y);
			if( get_tile(i+camera_x, j+camera_y, 1) > 0 && get_tile(i+camera_x, j+camera_y, 1)<600)
				draw_rle_sprite(buffer, (RLE_SPRITE *)tileset[get_tile(i+camera_x, j+camera_y, 1)].dat, i*16-offset_x, j*16-offset_y);
		}

	NODE *node = get_head();
	NODE *old_node = NULL;
	while(node) {
    if((node->job>=100)&&(node->job<=110)) { // Draw a NPC
			masked_blit((BITMAP *)graphic[NPCSET_BMP].dat, buffer, (get_direction(node->coordinates)/2+4*(node->job-100))*25, 0, (get_x(node->coordinates)-camera_x)*16-4-offset_x, (get_y(node->coordinates)-camera_y)*16-24-offset_y, 25, 40);  
		} else if(node->job<10) { // Draw a player
			node->text_x = (get_x(node->coordinates)-camera_x)*16-34+get_x_offset(node)-offset_x;
			node->text_y = (get_y(node->coordinates)-camera_y)*16-36+get_y_offset(node)-offset_y;
			masked_blit((BITMAP *)graphic[PLAYERSET_BMP].dat, buffer, 80*(get_direction(node->coordinates)/2), 60*(node->frame+node->action), node->text_x, node->text_y, 80, 60);

			if(node->emotion!=0) {
        draw_sprite(buffer, (BITMAP *)emotions[node->emotion-1].dat, (get_x(node->coordinates)-camera_x)*16-5+get_x_offset(node)-offset_x, (get_y(node->coordinates)-camera_y)*16-45+get_y_offset(node)-offset_y);
        node->emotion_time--;
        if(node->emotion_time==0)
          node->emotion = 0;
			}

			if(node->action!=STAND && node->action!=SIT) {
				node->frame = (get_elapsed_time(node->tick_time)*4)/(node->speed);
	      if(node->frame>=4) {
          node->frame = 0;
					node->action = STAND;
//					node->tick_time;
					if(node->id==player_node->id)
            walk_status = 0;          
				}
			}

		} else if(node->job==45) { // Draw a warp
      //rectfill(buffer, (get_x(node->coordinates)-map_x)*16-player_x-get_x_offset(node->frame, get_direction(node->coordinates)), (get_y(node->coordinates)-map_y)*16-player_y-get_y_offset(node->frame, get_direction(node->coordinates)), (get_x(node->coordinates)-map_x)*16-player_x-get_x_offset(node->frame, get_direction(node->coordinates))+16, (get_y(node->coordinates)-map_y)*16-player_y-get_y_offset(node->frame, get_direction(node->coordinates))+16, makecol(0,0,255));
    } else { // Draw a monster
      
			node->text_x = (get_x(node->coordinates)-camera_x)*16-20+get_x_offset(node)-offset_x;
			node->text_y = (get_y(node->coordinates)-camera_y)*16-25+get_y_offset(node)-offset_y;

      if(node->action==MONSTER_DEAD)node->frame = 0;
			masked_blit((BITMAP *)graphic[MOBSET_BMP].dat, buffer, (get_direction(node->coordinates)/2)*60, 60*(node->frame+node->action), node->text_x, node->text_y, 60, 60);
      if(node->action!=STAND) {
        node->frame = (get_elapsed_time(node->tick_time)*4)/(node->speed);
        if(node->frame>=4) {
          if(node->action!=MONSTER_DEAD) {
            if(node->path  && node->action!=MONSTER_DEAD) {
              PATH_NODE *old = node->path;
              set_coordinates(node->coordinates, node->path->x, node->path->y, 0);
              node->path = node->path->next;
              if(old!=NULL)
                free(old);
            } else node->action = STAND;
            if(node->action!=MONSTER_DEAD)node->frame = 0;
            node->tick_time = tick_time;
					}
        }
      }
    }
		old_node = node;
    node = node->next;
		if(old_node->action==MONSTER_DEAD && old_node->frame>=4)
			remove_node(old_node->id);
	}

	for(int j=0;j<20;j++)
		for(int i=0;i<26;i++) {
			if(get_tile(i+camera_x, j+camera_y, 2)>0 && get_tile(i+camera_x, j+camera_y, 2)<600)draw_rle_sprite(buffer, (RLE_SPRITE *)tileset[get_tile(i+camera_x, j+camera_y, 2)].dat, i*16-offset_x, j*16-offset_y);
		}

	stretch_blit(buffer, double_buffer, 0, 0, 400, 300, 0, 0, 800, 600);

	// Draw player speech
  node = get_head();
  while(node) {
		if(node->speech!=NULL) {
			if(node->speech_color==makecol(255,255,255))
        alfont_textprintf_aa(double_buffer, gui_font, node->text_x*2+90-alfont_text_length(gui_font, node->speech)/2, node->text_y*2, node->speech_color, "%s", node->speech);
			else
				alfont_textprintf_aa(double_buffer, gui_font, node->text_x*2+60-alfont_text_length(gui_font, node->speech)/2, node->text_y*2, node->speech_color, "%s", node->speech);
			      
      node->speech_time--;
      if(node->speech_time==0) {
        free(node->speech);
        node->speech = NULL;
      }
    }
    node = node->next;
  }	

	inventory.draw(double_buffer);

	set_trans_blender(0, 0, 0, 110);
  draw_trans_sprite(double_buffer, chat_background, 0, SCREEN_H-125);
  
  chatlog.chat_draw(double_buffer, 8, gui_font);
  gui_update(chat_player);

	switch(show_npc_dialog) {
		case 1:
      dialog_message(npc_dialog, MSG_DRAW, 0, 0);
      if(!(show_npc_dialog = gui_update(npc_player)))strcpy(npc_text, "");
			break;
		case 2:
			dialog_message(buy_sell_dialog, MSG_DRAW, 0, 0);
			if(!gui_update(buy_sell_player)) {
				show_npc_dialog = shutdown_dialog(buy_sell_player);
				if(show_npc_dialog==1 || show_npc_dialog==2) {
          WFIFOW(0) = net_w_value(0x00c5);
          WFIFOL(2) = net_l_value(current_npc);
          WFIFOB(6) = net_b_value(show_npc_dialog-1);
					WFIFOSET(7);
				}
				show_npc_dialog = 0;
				buy_sell_player = init_dialog(buy_sell_dialog, -1);
			}
			break;
		case 3:
			char money[20];
			sprintf(money, "%i gp", char_info->zeny);
			buy_dialog[4].dp = &money;
			dialog_message(buy_dialog, MSG_DRAW, 0, 0);
			if(!gui_update(buy_player)) {
				show_npc_dialog = shutdown_dialog(buy_player);
        if(show_npc_dialog==1) {
          WFIFOW(0) = net_w_value(0x00c8);
          WFIFOW(2) = net_w_value(8);
          WFIFOW(4) = net_w_value(1);
          WFIFOW(6) = net_w_value(get_item_id(buy_dialog[3].d1));
          WFIFOSET(8);
				}
				show_npc_dialog = 0;
        buy_player = init_dialog(buy_dialog, -1);
				close_shop();
			}
			break;
			case 4:
			dialog_message(sell_dialog, MSG_DRAW, 0, 0);
			if(!gui_update(sell_player)) {
				show_npc_dialog = shutdown_dialog(sell_player);
        if(show_npc_dialog==1) {
          WFIFOW(0) = net_w_value(0x00c9);
          WFIFOW(2) = net_w_value(8);
          WFIFOW(4) = net_w_value(1);
          WFIFOW(6) = net_w_value(get_item_id(sell_dialog[3].d1));
          WFIFOSET(8);
				}
				show_npc_dialog = 0;
        sell_player = init_dialog(sell_dialog, -1);
				close_shop();
			}
			break;
  }

	if(show_skill_dialog) {
		update_skill_dialog();
    if(gui_update(skill_player)==0)show_skill_dialog = false;
	}
  
	alfont_textprintf(double_buffer, gui_font, 0, 0, MAKECOL_WHITE, "FPS:%i", fps);

	blit(double_buffer, screen, 0, 0, 0, 0, 800, 600);

	frame++;
}

void exit_graphic() {
	shutdown_dialog(npc_player);
  shutdown_dialog(chat_player);
	shutdown_dialog(skill_player);
}