Files
oboe/osx/boe.text.cpp
Celtic Minstrel c413d292a9 Tear out most of the legacy code in the game - see below for details
(PC Editor and Scenario Editor are unaffected by this commit.)

Things removed:
- All references to Carbon and QuickDraw are gone.
- No more Resource Manager; the game no longer relies on old resource files at all
- The old dialog framework (from dlogtool.c, functions usually prefixed with cd_) is no longer used.
- Files that weren't being compiled
- Boost libraries that are now in the C++ library (function, shared_ptr)
- Obsolete build settings

Replacement dependencies:
- Boost Filesystem replaces references to things like FSSpec
- SFML replaces all the QuickDraw code and most window management
- Cocoa replaces AppleEvent management, menu management, and some window management
- I wrote a resource manager interface to mimick the important aspects of the behaviour of the Mac Resource Manager
- I had to rewrite some functions that QuickDraw provided natively, such as clipping regions; not all of these are tested

Things added:
- Every referenced dialog has been converted from a DITL resource into the new XML-based dialog format.
- All referenced STR# resources have been extracted into simple text files
- Now compiles against Mac OSX 10.7 SDK and libc++
- The first item in the Help menu opens the docs on Sylae's website
- It seems all the constants for soundtool vanished somewhere, so I added them back from the original Mac source

Other changes:
- Updated to XCode 4(?) project format
- Added the xcschemes created by XCode 4; I'm not sure how important these are, but they seem like they might be important
- Added document on converting dialogs to the XML format.
- Make string formatting mismatches into errors instead of warnings
- Disable error limit
- Graphics sheets that previously used masking now have alpha transparency
- Converted all graphics sheets to 8-bit PNG
- Trimmed white border from intro image
- Converted dialogs in the resource file have their resource name set to the name of the XML file of the converted version
- Referenced string resources in the resource file have their resource name set to the name of the text file of the extracted version
- Add the black-and-white patterns from the PAT resources to the pixpats.png; at least one of them is used somewhere in the game
- Recreated the menu.xib as a Cocoa xib file instead of a Carbon xib file
- Disable GNU C++ extensions; maybe this'll make it easier to compile with cl.exe later
- Add marks to the enormous handle_action function to make it easier to navigate\
- A build step to validate the XML dialogs using xmllint (doesn't quite work properly yet but does at least catch dialogs that are not well-formed)- Fix a lot of warnings about assigning string constants to non-const char pointers
- Fixed the file and application icons (which had somehow become corrupted at some point)
- Lots of additional functions in the custom location and rectangle classes, including implicit conversion to and from SFML rects and vectors; also they now store coordinates as int instead of char
- A new enum for encounter note types
- Much tweaking of the encounter note recording mechanisms
- To ease porting, I added a simple function that converts from classic Mac ticks (about 1/60 of a second) to the SFML time type
- Python script to convert STR# resources to txt files, replacing newlines with vertical bars
- Extracted the Mac font (Dungeon Bold) from the resource file and also added the Windows font (MaidenWord)

XML Dialog Framework changes:
- Remove the static initialization object in favour of manually calling cDialog::init()
- {set,get}Format() no longer used for colour; there's a dedicated {set,get}Colour() instead
- draw() methods unprotected in the control classes so that controls can be drawn in the main window
- There's no longer a friend relationship between the dialogs and the controls
- Fixed buttons duplicating the "depressed" boolean
- Buttons now properly offset the label for tiny and push buttons, and for LEDs
- Buttons no longer assume that either none or both of "width" and "height" are given in the XML
- Add {get,set}BtnType() to cButton
- cLedGroup now overrides handleClick(), which has also been made virtual; this was necessary for LEDs within a group to properly hilite while being clicked
- Add addChoice() to cLedGroup to insert additional LED choices
- Moved the key enums and cKey to a separate file
- Add a method to get a control's attached key
- Add methods to get and set a control's rect and position
- Controls can now directly take a window as a parent rather than a dialog
- Add addLabelFor() method to cDialog which adds a static text control as a label for another control
- Remove hack for storing a dialog result of arbitrary type in favour of boost::any
- Add method to get default text colour for a dialog
- Add method to get a dialog's rect
- Add method to add the same event handler to multiple controls in a dialog
- Add concept of default button to dialogs
- Add enum for text field type (currently either number or text)
- Implement the text field without use of native controls, including somewhat decent text input and a flashing insertion point
- cPict no longer stores references to every sheet; it fetches them as needed from the resource manager
- The many draw functions in cPict are no longer static, since they need to access the window containing the pict (before they could only be static due to QuickDraw's global state)
- Add setPict() without a type argument to change the graphic without changing the type, which is a common operation
- Add a scrollbar control; the specifics aren't implemented yet
- Change signature of the record callback for cStrDlog; it will no longer be passed the strings
- Publicize the no-button constructor of cChoiceDlog; it'll assume "okay" is the only button
- Add operator-> to cPictChoice for accessing the underlying dialog
- Add constructor to cPictChoice that takes a starting and ending pic num
- Remove err parameter from giveError
- Many more keys handled, plus support for catching copy, paste, cut, and select all keyboard shortcuts
- Text input fields take priority, overriding any other keyboard shortcuts in the dialog, but they never catch help (F1), escape, or enter
- Some changes to the format itself:
-> keys go in the "def-key" attribute, but modifiers go in "key-mod"
-> "clickable" is no longer a recognized attribute
-> "title" is now a recognized text size (18pt, even larger than "large" at 12pt)
-> "defbtn" attribute on the root element
2014-04-14 13:52:01 -04:00

1635 lines
52 KiB
C++

#define LINES_IN_TEXT_WIN 11
#define TEXT_BUF_LEN 70
#include <cstdio>
#include <cstring>
//#include "item.h"
#include "boe.global.h"
#include "classes.h"
#include "boe.text.h"
#include "boe.locutils.h"
#include "boe.fields.h"
#include "mathutil.h"
#include "graphtool.h"
//#include "soundtool.h"
#include "scrollbar.h"
#include "restypes.hpp"
const char *m_mage_sp[] = {"Spark","Minor Haste","Strength","Flame Cloud","Flame",
"Minor Poison","Slow","Dumbfound","Stinking Cloud","Summon Beast",
"Conflagration","Fireball","Weak Summoning","Web","Poison",
"Ice Bolt","Slow Group","Major Haste","Firestorm","Summoning",
"Shockstorm","Major Poison","Kill","Daemon","Major Blessing",
"Major Summoning","Shockwave"};
const char *m_priest_sp[] = {"Minor Bless","Light Heal","Wrack","Stumble","Bless",
"Curse","Wound","Summon Spirit","Disease","Heal",
"Holy Scourge","Smite","Curse All","Sticks to Snakes","Martyr's Shield",
"Bless All","Major Heal","Flamestrike","Summon Host","Heal All",
"Unholy Ravaging","Summon Guardian","Pestilence","Revive All","Avatar",
"Divine Thud"};
typedef struct {
char line[50];
} buf_line;
buf_line text_buffer[TEXT_BUF_LEN];
short buf_pointer = 30, lines_to_print= 0, num_added_since_stop = 0;
//char store_string[60],store_string2[60];
short start_print_point= 0;
short mark_where_printing_long;
bool printing_long = false;
char c_str[256] = "";
bool save_mess_given = false;
RECT status_panel_clip_rect = {11, 299, 175, 495},item_panel_clip_rect = {11,297,175,463};
// TODO: The duplication of RECT here shouldn't be necessary...
RECT item_buttons_from[7] = {RECT{11,0,24,14},RECT{11,14,24,28},RECT{11,28,24,42},RECT{11,42,24,56},
RECT{24,0,36,30},RECT{24,30,36,60},RECT{36,0,48,30}};
eGameMode store_mode;
extern short had_text_freeze,stat_screen_mode;
// graphics globals
extern RECT status_panel_rect,status_panel_title_rect;
extern RECT text_panel_rect;
extern short which_combat_type,stat_window;
extern eGameMode overall_mode;
extern sf::RenderWindow mainPtr;
extern RECT more_info_button;
extern short which_item_page[6];
//extern CursHandle sword_curs;
extern std::shared_ptr<cScrollbar> text_sbar,item_sbar;
extern location store_anim_ul;
extern RECT bg[];
extern short dest_personalities[40];
extern location source_locs[6];
extern location dest_locs[40] ;
//extern piles_of_stuff_dumping_type *data_store;
extern cScenario scenario;
extern sf::Texture spec_scen_g,tiny_obj_gworld,invenbtn_gworld,status_gworld;
extern sf::Texture pc_gworld;
extern sf::RenderTexture pc_stats_gworld, item_stats_gworld, text_area_gworld;
extern short terrain_there[9][9];
// game globals
//extern party_record_type party;
//extern current_town_type univ.town;
//extern cOutdoors outdoors[2][2];
//extern town_item_list univ.town;
//extern unsigned char out[96][96];
//extern big_tr_type t_d;
extern location ul;
extern bool play_sounds,suppress_stat_screen,in_startup_mode;
extern RECT item_buttons[8][6];
// name, use, give, drip, info, sell/id
extern RECT pc_buttons[6][5];
// name, hp, sp, info, trade
extern bool item_area_button_active[8][6];
extern bool pc_area_button_active[6][5];
extern RECT item_screen_button_rects[9];
extern short spec_item_array[60];
extern short abil_chart[200];
// combat globals
extern short item_bottom_button_active[9];
extern cUniverse univ;
extern location pc_pos[6];
extern ter_num_t combat_terrain[64][64];
extern short current_pc;
extern short shop_identify_cost;
extern short store_selling_values[8];
extern short combat_posing_monster, current_working_monster; // 0-5 PC 100 + x - monster x
extern bool supressing_some_spaces;
extern location ok_space[4];
extern sf::Texture bg_gworld;
short text_pc_has_abil_equip(short pc_num,short abil)
{
short i = 0;
while (((univ.party[pc_num].items[i].variety == 0) || (univ.party[pc_num].items[i].ability != abil)
|| (univ.party[pc_num].equip[i] == false)) && (i < 24))
i++;
return i;
}
// Draws the pc area in upper right
//void win_draw_string(WindowPtr dest_window,RECT dest_rect,char *str,short mode,short line_height)
void put_pc_screen()
{
char to_draw[256];
short i = 0,j;
RECT erase_rect = {17,2,98,269},to_draw_rect,from_rect;
// TODO: The duplication of RECT here shouldn't be necessary...
RECT small_erase_rects[3] = {RECT{101,34,114,76},RECT{101,106,114,147},RECT{101,174,114,201}};
RECT info_from = {0,1,12,13};
// Now place new stuff. Just draw it all there naively. It's in a gworld, and fast, so
// who gives a shit?
pc_stats_gworld.setActive();
// First clean up gworld with pretty patterns
tileImage(pc_stats_gworld, erase_rect,bg_gworld,bg[6]);
for (i = 0; i < 3; i++)
tileImage(pc_stats_gworld, small_erase_rects[i],bg_gworld,bg[7]);
TEXT.colour = sf::Color::White;
// Put food, gold, day
sprintf((char *) to_draw, "%d", (short) univ.party.gold);
win_draw_string( pc_stats_gworld,small_erase_rects[1],to_draw,0,10);
sprintf((char *) to_draw, "%d", (short) univ.party.food);
win_draw_string( pc_stats_gworld,small_erase_rects[0],to_draw,0,10);
i = calc_day();
sprintf((char *) to_draw, "%d", i);
win_draw_string( pc_stats_gworld,small_erase_rects[2],to_draw,0,10);
for (i = 0; i < 6; i++) {
if (univ.party[i].main_status != 0) {
for (j = 0; j < 5; j++)
pc_area_button_active[i][j] = 1;
if (i == current_pc) {
TEXT.style = sf::Text::Bold | sf::Text::Italic;
TEXT.colour = sf::Color::Blue;
}
sprintf((char *) to_draw, "%d. %-20s ", i + 1, (char *) univ.party[i].name.c_str());
win_draw_string( pc_stats_gworld,pc_buttons[i][0],to_draw,0,10);
TEXT.style = sf::Text::Bold;
TEXT.colour = sf::Color::Black;
to_draw_rect = pc_buttons[i][1];
to_draw_rect.right += 20;
switch (univ.party[i].main_status) {
case 1:
if (univ.party[i].cur_health == univ.party[i].max_health)
TEXT.colour = sf::Color::Green;
else TEXT.colour = sf::Color::Red;
sprintf((char *) to_draw, "%-3d ",univ.party[i].cur_health);
win_draw_string( pc_stats_gworld,pc_buttons[i][1],to_draw,0,10);
if (univ.party[i].cur_sp == univ.party[i].max_sp)
TEXT.colour = sf::Color::Blue;
else TEXT.colour = sf::Color::Magenta;
sprintf((char *) to_draw, "%-3d ",univ.party[i].cur_sp);
win_draw_string( pc_stats_gworld,pc_buttons[i][2],to_draw,0,10);
TEXT.colour = sf::Color::Black;
draw_pc_effects(i);
break;
case 2:
sprintf((char *) to_draw, "Dead");
break;
case 3:
sprintf((char *) to_draw, "Dust");
break;
case 4:
sprintf((char *) to_draw, "Stone");
break;
case 5:
sprintf((char *) to_draw, "Fled");
break;
case 6:
sprintf((char *) to_draw, "Surface");
break;
case 7:
sprintf((char *) to_draw, "Won");
break;
default:
sprintf((char *) to_draw, "Absent");
break;
}
if (univ.party[i].main_status != 1)
win_draw_string( pc_stats_gworld,to_draw_rect,to_draw,0,10);
// Now put trade and info buttons
//rect_draw_some_item(mixed_gworld,info_from,pc_stats_gworld,pc_buttons[i][3],1,0);
//rect_draw_some_item(mixed_gworld,switch_from,pc_stats_gworld,pc_buttons[i][4],1,0);
// do faster!
to_draw_rect = pc_buttons[i][3];
to_draw_rect.right = pc_buttons[i][4].right + 1;
from_rect = info_from;
from_rect.right = from_rect.left + to_draw_rect.right - to_draw_rect.left;
rect_draw_some_item(invenbtn_gworld,from_rect,pc_stats_gworld,to_draw_rect,sf::BlendAlpha);
}
else {
for (j = 0; j < 5; j++)
pc_area_button_active[i][j] = 0;
}
}
// Now put text on window.
mainPtr.setActive();
to_draw_rect = RECT(pc_stats_gworld);
RECT oldRect = to_draw_rect;
to_draw_rect.offset(PC_WIN_UL_X,PC_WIN_UL_Y);
pc_stats_gworld.display(); // TODO: I think displaying is necessary before accessing the texture...?
rect_draw_some_item(pc_stats_gworld.getTexture(), oldRect, to_draw_rect,ul);
// Sometimes this gets called when character is slain. when that happens, if items for
// that PC are up, switch item page.
if ((current_pc < 6) && (univ.party[current_pc].main_status != 1) && (stat_window == current_pc)) {
set_stat_window(current_pc);
}
}
// Draws item area in middle right
// Screen_num is what page is visible in the item menu.
// 0 - 5 pc inventory 6 - special item 7 - missions
// Stat_screen_mode ... 0 - normal, adventuring, all buttons vis
// 1 - in shop, item info only
// 2 - in shop, identifying, shop_identify_cost is cost
// 3 - in shop, selling weapons
// 4 - in shop, selling armor
// 5 - in shop, selling all
// 6 - in shop, augmenting weapon,shop_identify_cost is type
void put_item_screen(short screen_num,short suppress_buttons)
// if suppress_buttons > 0, save time by not redrawing buttons
{
std::ostringstream sout;
short i_num,item_offset;
short i = 0,j,pc;
RECT erase_rect = {17,2,122,255},dest_rect;
RECT upper_frame_rect = {3,3,15,268};
// TODO: The duplication of RECT here shouldn't be necessary...
RECT parts_of_area_to_draw[3] = {RECT{0,0,17,271},RECT{16,0,123,256},RECT{123,0,144,271}};
// Now place new stuff. Just draw it all there naively. It's in a gworld, and fast, so
// who gives a shit?
item_stats_gworld.setActive();
// First clean up gworld with pretty patterns
tileImage(item_stats_gworld, erase_rect,bg_gworld,bg[6]);
if (suppress_buttons == 0)
for (i = 0; i < 6; i++)
tileImage(item_stats_gworld, item_screen_button_rects[i],bg_gworld,bg[7]);
tileImage(item_stats_gworld, upper_frame_rect,bg_gworld,bg[7]);
// Draw buttons at bottom
if (suppress_buttons == 0) {
for (i = 0; i < 6; i++)
tileImage(item_stats_gworld, item_screen_button_rects[i],bg_gworld,bg[7]);
}
item_offset = item_sbar->getPosition();
for (i = 0; i < 8; i++)
for (j = 0; j < 6; j++)
item_area_button_active[i][j] = false;
switch (screen_num) {
case 6: // On special items page
TEXT.style = sf::Text::Bold;
TEXT.colour = sf::Color::White;
win_draw_string(item_stats_gworld,upper_frame_rect,"Special items:",0,10);
TEXT.colour = sf::Color::Black;
for (i = 0; i < 8; i++) {
i_num = i + item_offset;
if (spec_item_array[i_num] >= 0) {
// 2nd condition above is quite kludgy, in case it gets here with array all 0's
win_draw_string(item_stats_gworld,item_buttons[i][0],scenario.scen_strs(60 + spec_item_array[i_num] * 2),0,10);
place_item_button(3,i,4,0);
if ((scenario.special_items[spec_item_array[i_num]] % 10 == 1)
&& (!(is_combat())))
place_item_button(0,i,3,0);
}
}
break;
case 7: // On jobs page
////
break;
default: // on an items page
pc = screen_num;
TEXT.colour = sf::Color::White;
sout.str("");;
sout << univ.party[pc].name << " inventory:",
win_draw_string(item_stats_gworld,upper_frame_rect,sout.str().c_str(),0,10);
TEXT.colour = sf::Color::Black;
for (i = 0; i < 8; i++) {
i_num = i + item_offset;
sout.str("");
sout << i_num + 1 << '.';
win_draw_string(item_stats_gworld,item_buttons[i][0],sout.str().c_str(),0,10);
dest_rect = item_buttons[i][0];
dest_rect.left += 36;
if (univ.party[pc].items[i_num].variety == 0) {
}
else {
if (univ.party[pc].equip[i_num] == true) {
TEXT.style = sf::Text::Italic | sf::Text::Bold;
if (univ.party[pc].items[i_num].variety < 3)
TEXT.colour = sf::Color::Magenta;
else if ((univ.party[pc].items[i_num].variety >= 12) && (univ.party[pc].items[i_num].variety <= 17))
TEXT.colour = sf::Color::Green;
else TEXT.colour = sf::Color::Blue;
} else TEXT.colour = sf::Color::Black;
////
sout.str("");
if (!univ.party[pc].items[i_num].ident)
sout << univ.party[pc].items[i_num].name << " ";
else { /// Don't place # of charges when Sell button up and space tight
sout << univ.party[pc].items[i_num].full_name << ' ';
if ((univ.party[pc].items[i_num].charges > 0) && (univ.party[pc].items[i_num].type != 2)
&& (stat_screen_mode <= 1))
sout << '(' << univ.party[pc].items[i_num].charges << ')';
}
dest_rect.left -= 2;
win_draw_string(item_stats_gworld,dest_rect,sout.str().c_str(),0,10);
TEXT.style = sf::Text::Bold;
TEXT.colour = sf::Color::Black;
// this is kludgy, awkwark, and has redundant code. Done this way to
// make go faster, and I got lazy.
if ((stat_screen_mode == 0) &&
((is_town()) || (is_out()) || ((is_combat()) && (pc == current_pc)))) { // place give and drop and use
place_item_button(0,i,0,univ.party[pc].items[i_num].graphic_num); // item_graphic
if (abil_chart[univ.party[pc].items[i_num].ability] != 4) // place use if can
place_item_button(10,i,1,0);
else place_item_button(11,i,1,0);
}
else {
place_item_button(0,i,0,univ.party[pc].items[i_num].graphic_num); // item_graphic
place_item_button(3,i,4,0); // info button
if ((stat_screen_mode == 0) &&
((is_town()) || (is_out()) || ((is_combat()) && (pc == current_pc)))) { // place give and drop and use
place_item_button(1,i,2,0);
place_item_button(2,i,3,0);
if (abil_chart[univ.party[pc].items[i_num].ability] != 4) // place use if can
place_item_button(0,i,1,0);
}
}
if (stat_screen_mode > 1) {
place_buy_button(i,pc,i_num);
}
} // end of if item is there
} // end of for (i = 0; i < 8; i++)
break;
}
place_item_bottom_buttons();
// Now put text on window.
mainPtr.setActive();
for (i = 0; i < 3; i++) {
dest_rect = parts_of_area_to_draw[i];
dest_rect.offset(ITEM_WIN_UL_X,ITEM_WIN_UL_Y);
rect_draw_some_item(item_stats_gworld.getTexture(), parts_of_area_to_draw[i], dest_rect,ul);
}
}
void place_buy_button(short position,short pc_num,short item_num)
{
RECT dest_rect,source_rect;
// TODO: The duplication of RECT here shouldn't be necessary...
RECT button_sources[3] = {RECT{24,0,36,30},RECT{36,0,48,30},RECT{48,0,60,30}};
short val_to_place;
char store_str[60];
short aug_cost[10] = {4,7,10,8, 15,15,10, 0,0,0};
if (univ.party[pc_num].items[item_num].variety == 0)
return;
dest_rect = item_buttons[position][5];
val_to_place = (univ.party[pc_num].items[item_num].charges > 0) ?
univ.party[pc_num].items[item_num].charges * univ.party[pc_num].items[item_num].value :
univ.party[pc_num].items[item_num].value;
val_to_place = val_to_place / 2;
switch (stat_screen_mode) {
case 2:
if (!univ.party[pc_num].items[item_num].ident) {
item_area_button_active[position][5] = true;
source_rect = button_sources[0];
val_to_place = shop_identify_cost;
}
break;
case 3: // sell weapons
if (((univ.party[pc_num].items[item_num].variety < 7) || (univ.party[pc_num].items[item_num].variety == 23) ||
(!univ.party[pc_num].equip[item_num]) &&
(univ.party[pc_num].items[item_num].variety == 24)) &&
(univ.party[pc_num].items[item_num].ident) && (val_to_place > 0) &&
(!univ.party[pc_num].items[item_num].unsellable)) {
item_area_button_active[position][5] = true;
source_rect = button_sources[1];
}
break;
case 4: // sell armor
if ((univ.party[pc_num].items[item_num].variety >= 12) && (univ.party[pc_num].items[item_num].variety <= 17) &&
(!univ.party[pc_num].equip[item_num]) &&
(univ.party[pc_num].items[item_num].ident) && (val_to_place > 0) &&
(!univ.party[pc_num].items[item_num].unsellable)) {
item_area_button_active[position][5] = true;
source_rect = button_sources[1];
}
break;
case 5: // sell any
if ((val_to_place > 0) && (univ.party[pc_num].items[item_num].ident) &&
(!univ.party[pc_num].equip[item_num]) &&
(!univ.party[pc_num].items[item_num].unsellable)) {
item_area_button_active[position][5] = true;
source_rect = button_sources[1];
}
break;
case 6: // augment weapons
if ((univ.party[pc_num].items[item_num].variety < 3) &&
(univ.party[pc_num].items[item_num].ident) &&
(univ.party[pc_num].items[item_num].ability == 0) &&
(!univ.party[pc_num].items[item_num].magic)) {
item_area_button_active[position][5] = true;
source_rect = button_sources[2];
val_to_place = max(aug_cost[shop_identify_cost] * 100,univ.party[pc_num].items[item_num].value * (5 + aug_cost[shop_identify_cost]));
}
break;
}
if (item_area_button_active[position][5]) {
store_selling_values[position] = val_to_place;
dest_rect = item_buttons[position][5];
dest_rect.right = dest_rect.left + 30;
rect_draw_some_item(invenbtn_gworld, source_rect, item_stats_gworld, dest_rect, sf::BlendAlpha);
sprintf((char *) store_str," %d",val_to_place);
if (val_to_place >= 10000)
TEXT.style = sf::Text::Regular;
win_draw_string(item_stats_gworld,item_buttons[position][5],store_str,2,10);
TEXT.style = sf::Text::Bold;
}
}
//extern bool item_area_button_active[8][6];
// name, use, give, drop, info, sell/id
// shortcuts - if which_button_to_put is 10, all 4 buttons now
// if which_button_to_put is 11, just right 2
void place_item_button(short which_button_to_put,short which_slot,short which_button_position,short extra_val)
{
RECT from_rect = {0,0,18,18},to_rect;
if (which_button_position == 0) { // this means put little item graphic, extra val is which_graphic
item_area_button_active[which_slot][which_button_position] = true;
from_rect.offset((extra_val % 10) * 18,(extra_val / 10) * 18);
to_rect = item_buttons[which_slot][0];
to_rect.right = to_rect.left + (to_rect.bottom - to_rect.top);
to_rect.inset(-1,-1);
to_rect.offset(20,1);
from_rect.inset(2,2);
if (extra_val >= 150) {
from_rect = get_custom_rect(extra_val - 150);
rect_draw_some_item(spec_scen_g, from_rect, item_stats_gworld, to_rect,sf::BlendAlpha);
}
else rect_draw_some_item(tiny_obj_gworld, from_rect, item_stats_gworld, to_rect, sf::BlendAlpha);
return;
}
if (which_button_to_put < 4) { // this means put a regular item button
item_area_button_active[which_slot][which_button_position] = true;
rect_draw_some_item(invenbtn_gworld, item_buttons_from[which_button_to_put], item_stats_gworld, item_buttons[which_slot][which_button_position], sf::BlendAlpha);
}
if (which_button_to_put == 10) { // this means put all 4
item_area_button_active[which_slot][1] = true;
item_area_button_active[which_slot][2] = true;
item_area_button_active[which_slot][3] = true;
item_area_button_active[which_slot][4] = true;
from_rect = item_buttons_from[0]; from_rect.right = item_buttons_from[3].right;
to_rect = item_buttons[which_slot][1];
to_rect.right = to_rect.left + from_rect.right - from_rect.left;
rect_draw_some_item(invenbtn_gworld, from_rect, item_stats_gworld, to_rect, sf::BlendAlpha);
}
if (which_button_to_put == 11) { // this means put right 3
item_area_button_active[which_slot][2] = true;
item_area_button_active[which_slot][3] = true;
item_area_button_active[which_slot][4] = true;
from_rect = item_buttons_from[1]; from_rect.right = item_buttons_from[3].right;
to_rect = item_buttons[which_slot][2];
to_rect.right = to_rect.left + from_rect.right - from_rect.left;
rect_draw_some_item(invenbtn_gworld, from_rect, item_stats_gworld, to_rect, sf::BlendAlpha);
}
}
//RECT get_custom_rect (short which_rect) ////
//{
// RECT store_rect = {0,0,36,28};
//
// OffsetRect(&store_rect,28 * (which_rect % 10),36 * (which_rect / 10));
// return store_rect;
//}
void place_item_bottom_buttons()
{
RECT pc_from_rect = {0,0,36,28},but_from_rect = {60,30,78,46},to_rect;
RECT spec_from_rect = {0,30,15,65}, job_from_rect = {15,30,15,65}, help_from_rect = {78,30,91,44};
short i;
for (i = 0; i < 6; i++) {
if (univ.party[i].main_status == 1) {
item_bottom_button_active[i] = true;
to_rect = item_screen_button_rects[i];
rect_draw_some_item(invenbtn_gworld, but_from_rect, item_stats_gworld, to_rect, sf::BlendAlpha);
pc_from_rect = calc_rect(2 * (univ.party[i].which_graphic / 8), univ.party[i].which_graphic % 8);
to_rect.inset(2,2);
rect_draw_some_item(pc_gworld, pc_from_rect, item_stats_gworld, to_rect, sf::BlendAlpha);
}
else item_bottom_button_active[i] = false;
}
to_rect = item_screen_button_rects[6];
rect_draw_some_item(invenbtn_gworld, spec_from_rect, item_stats_gworld, to_rect, sf::BlendAlpha);
to_rect = item_screen_button_rects[7];
rect_draw_some_item(invenbtn_gworld, job_from_rect, item_stats_gworld, to_rect, sf::BlendAlpha);
to_rect = item_screen_button_rects[8];
rect_draw_some_item(invenbtn_gworld, help_from_rect, item_stats_gworld, to_rect, sf::BlendAlpha);
}
void set_stat_window(short new_stat)
{
short i,array_pos = 0;
stat_window = new_stat;
if ((stat_window < 6) && (univ.party[stat_window].main_status != 1))
stat_window = first_active_pc();
switch (stat_window) {
case 6:
for (i = 0; i < 60; i++)
spec_item_array[i] = -1;
for (i = 0; i < 50; i++) ////
if (univ.party.spec_items[i] > 0) {
spec_item_array[array_pos] = i;
array_pos++;
}
array_pos = max(0,array_pos - 8);
item_sbar->setMaximum(array_pos);
break;
case 7:
item_sbar->setMaximum(2);
break;
default:
item_sbar->setMaximum(16);
break;
}
item_sbar->setPosition(0);
put_item_screen(stat_window,0);
}
short first_active_pc()
{
short i = 0;
for (i = 0; i < 6; i++)
if (univ.party[i].main_status == 1)
return i;
return 6;
}
void refresh_stat_areas(short mode)
{
short i;
sf::BlendMode x;
// TODO: The duplication of RECT here shouldn't be necessary...
RECT dest_rect,parts_of_area_to_draw[3] = {RECT{0,0,17,271},RECT{16,0,123,256},RECT{123,0,144,271}};
//x = mode * 10;
dest_rect = RECT(pc_stats_gworld);
RECT oldRect = dest_rect;
dest_rect.offset(PC_WIN_UL_X,PC_WIN_UL_Y);
if(mode == 1) x = sf::BlendAdd;
else x = sf::BlendNone;
rect_draw_some_item (pc_stats_gworld.getTexture(), oldRect, dest_rect,ul, x);
for (i = 0; i < 3; i++) {
dest_rect = parts_of_area_to_draw[i];
dest_rect.offset(ITEM_WIN_UL_X,ITEM_WIN_UL_Y);
rect_draw_some_item(item_stats_gworld.getTexture(), parts_of_area_to_draw[i], dest_rect,ul, x);
}
dest_rect = RECT(text_area_gworld);
oldRect = dest_rect;
dest_rect.offset(TEXT_WIN_UL_X,TEXT_WIN_UL_Y);
rect_draw_some_item(text_area_gworld.getTexture(),oldRect, dest_rect,ul, x);
}
////
// get job info gone
short total_encumberance(short pc_num)
{
short store = 0,i,what_val;
for (i = 0; i < 24; i++)
if (univ.party[pc_num].equip[i] == true) {
what_val = univ.party[pc_num].items[i].awkward;
store += what_val;
}
return store;
}
//short get_tnl(pc_record_type *pc)
//{
// short tnl = 100,i,store_per = 100;
// static const short rp[3] = {0,12,20};
// static const short ap[15] = {10,20,8,10,4, 6,10,7,12,15, -10,-8,-8,-20,-8};
//
// tnl = (tnl * (100 + rp[pc->race])) / 100;
// for (i = 0; i < 15; i++)
// if (pc->traits[i] == true)
// store_per = store_per + ap[i];
//
// tnl = (tnl * store_per) / 100;
//
// return tnl;
//}
void draw_pc_effects(short pc)
//short pc; // 10 + x -> draw for pc x, but on spell dialog
{
// TODO: The duplication of RECT here shouldn't be necessary...
RECT source_rects[18] = {
RECT{00,0,12,12},RECT{00,12,12,24},RECT{00,24,12,36},
RECT{12,0,24,12},RECT{12,12,24,24},RECT{12,24,24,36},
RECT{24,0,36,12},RECT{24,12,36,24},RECT{24,24,36,36},
RECT{36,0,47,12},RECT{36,12,47,24},RECT{36,24,47,36},
RECT{47,0,60,12},RECT{47,12,60,24},RECT{47,24,60,36},
RECT{60,0,72,12},RECT{60,12,72,24},RECT{60,24,72,36}
};
RECT dest_rect = {18,15,30,27},dlog_dest_rect = {66,354,78,366};
short right_limit = 250;
short dest = 0; // 0 - in gworld 2 - on dialog
short name_width;
if (pc >= 10) {return; // TODO: This is a temporary measure only!
pc -= 10;
right_limit = 490;
dest_rect = dlog_dest_rect;
dest = 2;
dest_rect.top += pc * 25 + 18;
dest_rect.bottom += pc * 25 + 18;
}
else {
name_width = string_length(univ.party[pc].name.c_str());
right_limit = pc_buttons[0][1].left - 5;
//dest_rect.left = pc_buttons[i][1].left - 16;
dest_rect.left = name_width + 33;
dest_rect.right = dest_rect.left + 12;
dest_rect.top += pc * 13;
dest_rect.bottom += pc * 13;
}
if (univ.party[pc].main_status % 10 != 1)
return;
// TODO: This used to draw the status icons in the spell dialog, but it no longer does. Fix that.
if ((univ.party[pc].status[STATUS_POISONED_WEAPON] > 0) && (dest_rect.right < right_limit)) {
rect_draw_some_item(status_gworld,source_rects[4],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if (univ.party[pc].status[STATUS_BLESS_CURSE] > 0) {
rect_draw_some_item(status_gworld,source_rects[2],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
else if (univ.party[pc].status[STATUS_BLESS_CURSE] < 0) {
rect_draw_some_item(status_gworld,source_rects[3],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if (univ.party[pc].status[STATUS_POISON] > 0) {
rect_draw_some_item(status_gworld,source_rects[(univ.party[pc].status[STATUS_POISON] > 4) ? 1 : 0],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if (univ.party[pc].status[STATUS_INVULNERABLE] > 0) {
rect_draw_some_item(status_gworld,source_rects[5],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if (univ.party[pc].status[STATUS_HASTE_SLOW] > 0) {
rect_draw_some_item(status_gworld,source_rects[6],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
else if (univ.party[pc].status[STATUS_HASTE_SLOW] < 0) {
rect_draw_some_item(status_gworld,source_rects[8],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}else{
rect_draw_some_item(status_gworld,source_rects[7],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if ((univ.party[pc].status[STATUS_MAGIC_RESISTANCE] > 0) && (dest_rect.right < right_limit)) {
rect_draw_some_item(status_gworld,source_rects[9],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if ((univ.party[pc].status[STATUS_WEBS] > 0) && (dest_rect.right < right_limit)) {
rect_draw_some_item(status_gworld,source_rects[10],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if ((univ.party[pc].status[STATUS_DISEASE] > 0) && (dest_rect.right < right_limit)){
rect_draw_some_item(status_gworld,source_rects[11],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if ((univ.party[pc].status[STATUS_INVISIBLE] > 0) && (dest_rect.right < right_limit)){
rect_draw_some_item(status_gworld,source_rects[12],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if ((univ.party[pc].status[STATUS_DUMB] > 0) && (dest_rect.right < right_limit)){
rect_draw_some_item(status_gworld,source_rects[13],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if ((univ.party[pc].status[STATUS_MARTYRS_SHIELD] > 0) && (dest_rect.right < right_limit)){
rect_draw_some_item(status_gworld,source_rects[14],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if ((univ.party[pc].status[STATUS_ASLEEP] > 0) && (dest_rect.right < right_limit)){
rect_draw_some_item(status_gworld,source_rects[15],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if ((univ.party[pc].status[STATUS_PARALYZED] > 0) && (dest_rect.right < right_limit)){
rect_draw_some_item(status_gworld,source_rects[16],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
if ((univ.party[pc].status[STATUS_ACID] > 0) && (dest_rect.right < right_limit)){
rect_draw_some_item(status_gworld,source_rects[17],pc_stats_gworld,dest_rect,sf::BlendAlpha);
dest_rect.left += 13;
dest_rect.right += 13;
}
}
void print_party_stats() {
char store_string[256];
add_string_to_buf("PARTY STATS:");
sprintf((char *) store_string, " Number of kills: %lld ", univ.party.total_m_killed);
add_string_to_buf(store_string);
if ((is_town()) || ((is_combat()) && (which_combat_type == 1))) {
sprintf((char *) store_string, " Kills in this town: %d ", univ.party.m_killed[univ.town.num]);
add_string_to_buf(store_string);
}
sprintf((char *) store_string, " Total experience: %lld ", univ.party.total_xp_gained);
add_string_to_buf(store_string);
sprintf((char *) store_string, " Total damage done: %lld ", univ.party.total_dam_done);
add_string_to_buf(store_string);
sprintf((char *) store_string, " Total damage taken: %lld ", univ.party.total_dam_taken);
add_string_to_buf(store_string);
print_buf();
}
short do_look(location space)
{
short i,j,num_items = 0;
bool gold_here = false, food_here = false, is_lit = true;
location from_where;
std::string msg;
from_where = get_cur_loc();
is_lit = pt_in_light(from_where,space);
if (((overall_mode == MODE_LOOK_OUTDOORS) && (space == univ.party.p_loc)) ||
((overall_mode == MODE_LOOK_TOWN) && (space == univ.town.p_loc)))
add_string_to_buf(" Your party");
if (overall_mode == MODE_LOOK_COMBAT)
for (i = 0; i < 6; i++)
if ((space == pc_pos[i]) && (univ.party[i].main_status == 1)
&& (is_lit == true) && (can_see(pc_pos[current_pc],space,0) < 5)) {
msg = " " + univ.party[i].name;
add_string_to_buf(msg);
}
if ((overall_mode == MODE_LOOK_TOWN) || (overall_mode == MODE_LOOK_COMBAT)) {
for (i = 0; i < univ.town->max_monst(); i++)
if ((univ.town.monst[i].active != 0) && (is_lit == true)
&& (monst_on_space(space,i) == true) &&
((overall_mode == MODE_LOOK_TOWN) || (can_see(pc_pos[current_pc],space,0) < 5))
&& (univ.town.monst[i].picture_num != 0)) {
msg = get_m_name(univ.town.monst[i].number);
if (univ.town.monst[i].health < univ.town.monst[i].m_health) {
if (univ.town.monst[i].attitude % 2 == 1)
msg = " Wounded " + msg + " (H)";
else msg = " Wounded " + msg + " (F)";
}
else {
if (univ.town.monst[i].attitude % 2 == 1)
msg = " " + msg + " (H)";
else msg = " " + msg + " (F)";
}
add_string_to_buf((char *) msg.c_str());
}
}
if (overall_mode == MODE_LOOK_OUTDOORS) {
for (i = 0; i < 10; i++) {
if ((univ.party.out_c[i].exists)
&& (space == univ.party.out_c[i].m_loc)) {
for (j = 0; j < 7; j++)
if (univ.party.out_c[i].what_monst.monst[j] != 0) {
msg = get_m_name(univ.party.out_c[i].what_monst.monst[j]);
msg = " " + msg;
add_string_to_buf((char *) msg.c_str());
j = 7;
}
}
}
if (out_boat_there(space) < 30)
add_string_to_buf(" Boat ");
if (out_horse_there(space) < 30)
add_string_to_buf(" Horse ");
}
if ((overall_mode == MODE_LOOK_TOWN) || (overall_mode == MODE_LOOK_COMBAT)) {
if (town_boat_there(space) < 30)
add_string_to_buf(" Boat ");
if (town_horse_there(space) < 30)
add_string_to_buf(" Horse ");
if (univ.town.is_web(space.x,space.y))
add_string_to_buf(" Web ");
if (univ.town.is_crate(space.x,space.y))
add_string_to_buf(" Crate ");
if (univ.town.is_barrel(space.x,space.y))
add_string_to_buf(" Barrel ");
if (univ.town.is_fire_barr(space.x,space.y))
add_string_to_buf(" Magic Barrier ");
if (univ.town.is_force_barr(space.x,space.y))
add_string_to_buf(" Magic Barrier ");
if (univ.town.is_quickfire(space.x,space.y))
add_string_to_buf(" Quickfire ");
if (univ.town.is_fire_wall(space.x,space.y))
add_string_to_buf(" Wall of Fire ");
if (univ.town.is_force_wall(space.x,space.y))
add_string_to_buf(" Wall of Force ");
if (univ.town.is_antimagic(space.x,space.y))
add_string_to_buf(" Antimagic Field ");
if (univ.town.is_scloud(space.x,space.y))
add_string_to_buf(" Stinking Cloud ");
if (univ.town.is_ice_wall(space.x,space.y))
add_string_to_buf(" Ice Wall ");
if (univ.town.is_blade_wall(space.x,space.y))
add_string_to_buf(" Blade Wall ");
if (univ.town.is_sm_blood(space.x,space.y))
add_string_to_buf(" Blood stain ");
if (univ.town.is_med_blood(space.x,space.y))
add_string_to_buf(" Blood stain ");
if (univ.town.is_lg_blood(space.x,space.y))
add_string_to_buf(" Blood stain ");
if (univ.town.is_sm_slime(space.x,space.y))
add_string_to_buf(" Smears of slime ");
if (univ.town.is_lg_slime(space.x,space.y))
add_string_to_buf(" Smears of slime ");
if (univ.town.is_ash(space.x,space.y))
add_string_to_buf(" Ashes ");
if (univ.town.is_bones(space.x,space.y))
add_string_to_buf(" Bones ");
if (univ.town.is_rubble(space.x,space.y))
add_string_to_buf(" Rubble ");
for (i = 0; i < NUM_TOWN_ITEMS; i++) {
if ((univ.town.items[i].variety != 0) && (space == univ.town.items[i].item_loc)
&& (is_lit == true)) {
if (univ.town.items[i].variety == 3)
gold_here = true;
else if (univ.town.items[i].variety == 11)
food_here = true;
else num_items++;
}
}
if (gold_here == true)
add_string_to_buf(" Gold");
if (food_here == true)
add_string_to_buf(" Food");
if (num_items > 8)
add_string_to_buf(" Many items");
else for (i = 0; i < NUM_TOWN_ITEMS; i++) {
if ((univ.town.items[i].variety != 0) && (univ.town.items[i].variety != 3) &&(univ.town.items[i].variety != 11) &&
(space == univ.town.items[i].item_loc) && (!univ.town.items[i].contained)) {
if (univ.town.items[i].ident)
msg = " " + univ.town.items[i].full_name;
else msg = " " + univ.town.items[i].name;
add_string_to_buf((char *) msg.c_str());
}
}
}
if (is_lit == false) {
add_string_to_buf(" Dark ");
return 0;
}
return print_terrain(space);
}
short town_boat_there(location where)
{
short i;
// Num boats stores highest # of boat in town
for (i = 0; i < 30; i++)
if ((univ.party.boats[i].exists) && (univ.party.boats[i].which_town == univ.town.num)
&& (where == univ.party.boats[i].loc))
return i;
return 30;
}
short out_boat_there(location where)
{
short i;
for (i = 0; i < 30; i++)
if ((univ.party.boats[i].exists) && (where == univ.party.boats[i].loc)
&& (univ.party.boats[i].which_town == 200))
return i;
return 30;
}
short town_horse_there(location where)
{
short i;
// Num boats stores highest # of boat in town
for (i = 0; i < 30; i++)
if ((univ.party.horses[i].exists) && (univ.party.horses[i].which_town == univ.town.num)
&& (where == univ.party.horses[i].loc))
return i;
return 30;
}
short out_horse_there(location where)
{
short i;
for (i = 0; i < 30; i++)
if ((univ.party.horses[i].exists) && (where == univ.party.horses[i].loc)
&& (univ.party.horses[i].which_town == 200))
return i;
return 30;
}
void notify_out_combat_began(cOutdoors::cWandering encounter,short *nums)
{
short i;
std::string msg;
add_string_to_buf((char *) "COMBAT! ");
for (i = 0; i < 6; i++)
if (encounter.monst[i] != 0) {
switch (encounter.monst[i]) {
////
default:
msg = get_m_name(encounter.monst[i]);
std::ostringstream sout;
sout << " " << nums[i] << " x " << msg << " ";
msg = sout.str();
break;
}
add_string_to_buf((char *) msg.c_str());
}
if (encounter.monst[6] != 0) {
msg = " " + get_m_name(encounter.monst[6]) + " ";
add_string_to_buf((char *) msg.c_str());
}
}
std::string get_m_name(m_num_t num)
{
////
//strcpy((char *) str,(char *) scenario.scen_monsters[num].m_name);
return scenario.scen_monsters[num].m_name;
}
std::string get_ter_name(ter_num_t num)
{
std::string store_name = "Pit";
////
if ((num == 90) && ((is_out()) || (is_town()) || ((is_combat()) && (which_combat_type == 1))));
//sprintf((char *) store_name,"Pit");
else {
store_name = scenario.ter_types[num].name;
}
return store_name;
}
void print_monst_name(m_num_t m_type)
{
std::string msg = get_m_name(m_type) + ':';
add_string_to_buf((char *) msg.c_str());
}
void print_monst_attacks(m_num_t m_type,short target)
//short target; // < 100 - pc >= 100 monst
{
//char store_string3[60];
std::string msg = get_m_name(m_type);
msg += " attacks ";
if (target < 100)
msg += univ.party[target].name;
else
msg += get_m_name(univ.town.monst[target - 100].number);
add_string_to_buf((char *) msg.c_str());
}
////
void damaged_message(short damage,short type)
{
std::ostringstream sout(" ");
sout << get_str("monster-abilities",130 + type);
sout << " for " << damage;
add_string_to_buf(sout.str().c_str());
}
// This prepares the monster's string for the text bar
std::string print_monster_going(m_num_t m_num,short ap)
{
std::ostringstream sout(get_m_name(m_num));
sout << " (ap: " << ap << ')';
return sout.str();
}
void monst_spell_note(m_num_t number,short which_mess)
{
std::string msg = get_m_name(number);
switch (which_mess) {
case 1:
msg = " " + msg + " scared. ";
break;
case 2:
msg = " " + msg + " slowed. ";
break;
case 3:
msg = " " + msg + " weakened. ";
break;
case 4:
msg = " " + msg + " poisoned. ";
break;
case 5:
msg = " " + msg + " cursed. ";
break;
case 6:
msg = " " + msg + " ravaged. ";
break;
case 7:
msg = " " + msg + " undamaged. ";
break;
case 8:
msg = " " + msg + " is stoned. ";
break;
case 9:
msg = " Gazes at " + msg + '.';
break;
case 10:
msg = " " + msg + " resists. ";
break;
case 11:
msg = " Drains " + msg + '.';
break;
case 12:
msg = " Shoots at " + msg + '.';
break;
case 13:
msg = " Throws spear at " + msg + '.';
break;
case 14:
msg = " Throws rock at " + msg + '.';
break;
case 15:
msg = " Throws razordisk at " + msg + '.';
break;
case 16:
msg = " Hits " + msg + '.';
break;
case 17:
msg = " " + msg + " disappears. ";
break;
case 18:
msg = " Misses " + msg + '.';
break;
case 19:
msg = " " + msg + " is webbed. ";
break;
case 20:
msg = " " + msg + " chokes. ";
break;
case 21:
msg = " " + msg + " summoned. ";
break;
case 22:
msg = " " + msg + " is dumbfounded. ";
break;
case 23:
msg = " " + msg + " is charmed. ";
break;
case 24:
msg = " " + msg + " is recorded. ";
break;
case 25:
msg = " " + msg + " is diseased. ";
break;
case 26:
msg = " " + msg + " is an avatar!";
break;
case 27:
msg = " " + msg + " splits!";
break;
case 28:
msg = " " + msg + " falls asleep. ";
break;
case 29:
msg = " " + msg + " wakes up. ";
break;
case 30:
msg = " " + msg + " paralyzed. ";
break;
case 31:
msg = " " + msg + " covered with acid. ";
break;
case 32:
msg = " Fires spines at " + msg + '.';
break;
case 33:
msg = " " + msg + " summons aid. ";
break;
}
if (which_mess > 0)
add_string_to_buf((char *) msg.c_str());
}
void monst_cast_spell_note(m_num_t number,short spell,short type)
//short type; // 0 - mage 1- priest
{
std::string msg = get_m_name(number);
msg += " casts:";
add_string_to_buf((char *) msg.c_str());
msg = (type == 1) ? m_priest_sp[spell - 1] : m_mage_sp[spell - 1];
msg = " " + msg;
add_string_to_buf((char *) msg.c_str());
}
void monst_breathe_note(m_num_t number)
{
std::string msg = get_m_name(number);
msg += " breathes.";
add_string_to_buf((char *) msg.c_str());
}
void monst_damaged_mes(short which_m,short how_much,short how_much_spec)
{
std::string msg = get_m_name(univ.town.monst[which_m].number);
msg = " " + msg + " takes ";
std::ostringstream sout(msg);
sout << how_much;
if (how_much_spec > 0)
sout << '+' << how_much_spec;
msg = sout.str();
add_string_to_buf((char *) msg.c_str());
}
void monst_killed_mes(short which_m)
{
std::string msg = get_m_name(univ.town.monst[which_m].number);
msg = " " + msg + " dies.";
add_string_to_buf((char *) msg.c_str());
}
void print_nums(short a,short b,short c)
{
std::ostringstream sout;
sout << "debug: " << a << ' ' << b << ' ' << c;
add_string_to_buf((char *) sout.str().c_str());
}
short print_terrain(location space)
{
ter_num_t which_terrain;
if (overall_mode == MODE_LOOK_OUTDOORS) {
which_terrain = univ.out[space.x][space.y];
}
if (overall_mode == MODE_LOOK_TOWN) {
which_terrain = univ.town->terrain(space.x,space.y);
}
if (overall_mode == MODE_LOOK_COMBAT) {
which_terrain = combat_terrain[space.x][space.y];
}
std::string msg = get_ter_name(which_terrain);
msg = " " + msg;
add_string_to_buf(msg);
return (short) which_terrain;
}
void add_string_to_buf(std::string str)
{
if (in_startup_mode == true)
return;
if(str == "") return;
text_sbar->setPosition(58); // TODO: This seems oddly specific
if (buf_pointer == mark_where_printing_long) {
printing_long = true;
print_buf();
through_sending();
}
sprintf((char *)text_buffer[buf_pointer].line, "%-49.49s", str.c_str());
// c2pstr((char *)text_buffer[buf_pointer].line);
if (buf_pointer == (TEXT_BUF_LEN - 1))
buf_pointer = 0;
else buf_pointer++;
}
void init_buf()
{
short i;
for (i = 0; i < TEXT_BUF_LEN; i++)
sprintf((char *) text_buffer[buf_pointer].line, " ");
}
void print_buf ()
{
short num_lines_printed = 0,ctrl_val;
short line_to_print;
short start_print_point;
bool end_loop = false;
RECT store_text_rect,dest_rect,erase_rect = {1,1,137,255};
// Now place new stuff. Just draw it all there naively. It's in a gworld, and fast, so
// who gives a shit?
text_area_gworld.setActive();
// First clean up gworld with pretty patterns
erase_rect.inset(1,1); ////
erase_rect.right++;
tileImage(mainPtr, erase_rect,bg_gworld,bg[6]);
ctrl_val = 58 - text_sbar->getPosition();
start_print_point = buf_pointer - LINES_IN_TEXT_WIN - ctrl_val;
if (start_print_point< 0)
start_print_point= TEXT_BUF_LEN + start_print_point;
line_to_print= start_print_point;
location moveTo;
while ((line_to_print!= buf_pointer) && (num_lines_printed < LINES_IN_TEXT_WIN)) {
moveTo = location(4, 13 + 12 * num_lines_printed);
// TODO: Determine correct parameters to this sf::Text (font, etc)
sf::Text text(text_buffer[line_to_print].line, *ResMgr::get<FontRsrc>("Geneva"));
text.setPosition(moveTo);
mainPtr.draw(text);
num_lines_printed++;
line_to_print++;
if (line_to_print== TEXT_BUF_LEN) {
line_to_print= 0;
}
if ((num_lines_printed == LINES_IN_TEXT_WIN - 1) && (printing_long == true)) {
end_loop = false;
line_to_print= buf_pointer;
}
}
store_text_rect = RECT(text_area_gworld);
dest_rect = store_text_rect;
dest_rect.offset(TEXT_WIN_UL_X,TEXT_WIN_UL_Y);
mainPtr.setActive();
rect_draw_some_item(text_area_gworld.getTexture(), store_text_rect, dest_rect,ul);
}
void restart_printing()
{
lines_to_print = 0;
//clear_text_panel();
}
void restore_mode()
{
overall_mode = store_mode;
}
void through_sending()
{
mark_where_printing_long = buf_pointer + LINES_IN_TEXT_WIN - 1;
if (mark_where_printing_long > TEXT_BUF_LEN - 1)
mark_where_printing_long -= TEXT_BUF_LEN;
printing_long = false;
}
/* Draw a bitmap in the world window. hor in 0 .. 8, vert in 0 .. 8,
object is ptr. to bitmap to be drawn, and masking is for Copybits. */
void Draw_Some_Item (sf::Texture& src_gworld, RECT src_rect, sf::RenderTarget& targ_gworld,location target, char masked, short main_win)
{
RECT destrec = {0,0,36,28};
if ((target.x < 0) || (target.y < 0) || (target.x > 8) || (target.y > 8))
return;
if ((supressing_some_spaces == true) && (target != ok_space[0]) &&
(target != ok_space[1]) && (target != ok_space[2]) && (target != ok_space[3]))
return;
terrain_there[target.x][target.y] = -1;
destrec = coord_to_rect(target.x,target.y);
if (main_win == 1) destrec.offset(ul.x + 5,ul.y + 5);
if (main_win == 0) {
if(masked == 1)
rect_draw_some_item(src_gworld, src_rect, targ_gworld, destrec, sf::BlendAlpha);
else rect_draw_some_item(src_gworld, src_rect, targ_gworld, destrec, sf::BlendNone);
} else {
if(masked == 1)
rect_draw_some_item(src_gworld, src_rect, targ_gworld, destrec, sf::BlendAlpha);
else rect_draw_some_item(src_gworld, src_rect, targ_gworld, destrec, sf::BlendNone);
}
}
//void rect_draw_some_item (GWorldPtr src_gworld, RECT src_rect, GWorldPtr targ_gworld,
//RECT targ_rect, char masked, short main_win)
//// masked; // if 10 - make AddOver
//// main_win; // if 2, drawing onto dialog
//{
// PixMapHandle test1, test2;
// const BitMap * store_dest;
// GrafPtr cur_port;
// RGBColor store_color;
//
// GetPort(&cur_port);
// if (src_gworld == NULL) {
// if (main_win == 0) {
// SetPort ( targ_gworld);
// PaintRect(&targ_rect);
// SetPort (cur_port);
// }
// else PaintRect(&targ_rect);
// return;
// }
// if (main_win == 2) {
// GetBackColor(&store_color);
// BackColor(whiteColor);
// }
//
// store_dest = GetPortBitMapForCopyBits(cur_port);
//
// test1 = GetPortPixMap(src_gworld);
//
// if (main_win == 1)
// OffsetRect(&targ_rect,ul.h,ul.v);
//
// LockPixels(test1);
// if (main_win == 0) {
// test2 = GetPortPixMap(targ_gworld);
// LockPixels(test2);
// if (masked == 1)
// CopyBits ( (BitMap *) *test1 ,
// (BitMap *) *test2 ,
// &src_rect, &targ_rect,
// transparent , NULL);
// else CopyBits ( (BitMap *) *test1 ,
// (BitMap *) *test2 ,
// &src_rect, &targ_rect,
// (masked == 10) ? addOver : 0, NULL);
// UnlockPixels(test2);
// }
// else {
// if (masked == 1)
// CopyBits ( (BitMap *) *test1 ,
// store_dest ,
// &src_rect, &targ_rect,
// transparent , NULL);
// else CopyBits ( (BitMap *) *test1 ,
// store_dest ,
// &src_rect, &targ_rect,
// (masked == 10) ? addOver : 0, NULL);
// }
// UnlockPixels(test1);
// if (main_win == 2)
// RGBBackColor(&store_color);
// SetPort(cur_port);
//}
RECT coord_to_rect(short i,short j)
{
RECT to_return;
to_return.left = 13 + BITMAP_WIDTH * i;
to_return.right = to_return.left + BITMAP_WIDTH;
to_return.top = 13 + BITMAP_HEIGHT * j;
to_return.bottom = to_return.top + BITMAP_HEIGHT;
return to_return;
}
void make_cursor_sword()
{
set_cursor(sword_curs);
}
//short string_length(char *str)
//{
// short text_len[257];
// short total_width = 0,i,len;
// char p_str[256];
//
// for (i = 0; i < 257; i++)
// text_len[i]= 0;
//
// strcpy((char *) p_str,str);
// c2pstr(p_str);
// MeasureText(256,p_str,text_len);
// len = strlen((char *)str);
//
// for (i = 0; i < 257; i++)
// if ((text_len[i] > total_width) && (i <= len))
// total_width = text_len[i];
// return total_width;
//}
//void char_win_draw_string(WindowPtr dest_window,RECT dest_rect,char *str,short mode,short line_height)
//{
// char_port_draw_string(GetWindowPort(dest_window), dest_rect, str, mode, line_height);
//}
//
//
//void char_port_draw_string(GrafPtr dest_window,RECT dest_rect,char *str,short mode,short line_height)
//{
// char store_s[256];
//
// strcpy((char *) store_s,str);
// win_draw_string( dest_window, dest_rect,store_s, mode, line_height);
//
//}
// mode: 0 - align up and left, 1 - center on one line
// str is a c string, 256 characters
// uses current font
//void win_draw_string(GrafPtr dest_window,RECT dest_rect,Str255 str,short mode,short line_height)
//{
// GrafPtr old_port;
// const char* p_str,str_to_draw,str_to_draw2,c_str;
// char null_s[256] = " ";
// short str_len,i;
// short last_line_break = 0,last_word_break = 0,on_what_line = 0;
// short text_len[257];
// short total_width = 0;
// bool force_skip = false;
// RgnHandle current_clip;
// short adjust_x = 0,adjust_y = 0;
//
// if (dest_window == GetWindowPort(mainPtr)) {
// adjust_x = ul.h; adjust_y = ul.v;
// }
// strcpy((char *) p_str,(char *) str);
// strcpy((char *) c_str,(char *) str);
// c2pstr(p_str);
// for (i = 0; i < 257; i++)
// text_len[i]= 0;
// MeasureText(256,p_str,text_len);
// str_len = (short) strlen((char *)str);
// if (str_len == 0) {
// return;
// }
//
// GetPort(&old_port);
// SetPort(dest_window);
//
// //FrameRect(&dest_rect);
//
// current_clip = NewRgn();
// GetClip(current_clip);
//
// dest_rect.bottom += 5;
// //ClipRect(&dest_rect);
// dest_rect.bottom -= 5;
//
//
// for (i = 0; i < 257; i++)
// if ((text_len[i] > total_width) && (i <= str_len))
// total_width = text_len[i];
// if ((mode == 0) && (total_width < dest_rect.right - dest_rect.left))
// mode = 2;
// for (i = 0; i < 257; i++)
// if ((i <= str_len) && (c_str[i] == '|') && (mode == 2))
// mode = 0;
//
//
// switch (mode) {
// case 0:
// MoveTo(dest_rect.left + 1 + adjust_x, dest_rect.top + 1 + line_height * on_what_line + adjust_y + 9);
// for (i = 0;text_len[i] != text_len[i + 1], i < str_len;i++) {
// if (((text_len[i] - text_len[last_line_break] > (dest_rect.right - dest_rect.left - 6))
// && (last_word_break > last_line_break)) || (c_str[i] == '|')) {
// if (c_str[i] == '|') {
// c_str[i] = ' ';
// force_skip = true;
// last_word_break = i + 1;
// }
// sprintf((char *)str_to_draw,"%s",(char *)null_s);
// strncpy ((char *) str_to_draw,(char *) c_str + last_line_break,(size_t) (last_word_break - last_line_break - 1));
// sprintf((char *)str_to_draw2," %s",str_to_draw);
// str_to_draw2[0] = (char) strlen((char *)str_to_draw);
// DrawString(str_to_draw2);
// on_what_line++;
// MoveTo(dest_rect.left + 1 + adjust_x, dest_rect.top + 1 + line_height * on_what_line + adjust_y + 9);
// last_line_break = last_word_break;
// if (force_skip == true) {
// force_skip = false;
// i++;
// //last_line_break++;
// //last_word_break++;
// }
// }
// if (c_str[i] == ' ')
// last_word_break = i + 1;
// if (on_what_line == LINES_IN_TEXT_WIN - 1)
// i = 10000;
// }
//
// if (i - last_line_break > 1) {
// strcpy((char *)str_to_draw,(char *)null_s);
// strncpy ((char *) str_to_draw,(char *) c_str + last_line_break,(size_t) (i - last_line_break));
// sprintf((char *)str_to_draw2," %s",str_to_draw);
// if (strlen((char *) str_to_draw2) > 3) {
// str_to_draw2[0] = (char) strlen((char *)str_to_draw);
// DrawString(str_to_draw2);
// }
// }
// break;
// case 1:
// MoveTo((dest_rect.right + dest_rect.left) / 2 - (4 * total_width) / 9 + adjust_x,
// (dest_rect.bottom + dest_rect.top - line_height) / 2 + 9 + adjust_y);
// DrawText(p_str,1,p_str[0]);
// //DrawString(p_str);
// break;
// case 2:
// MoveTo(dest_rect.left + 1 + adjust_x,
// dest_rect.top + 1 + adjust_y + 9);
// DrawString(p_str);
// break;
// case 3:
// MoveTo(dest_rect.left + 1 + adjust_x,
// dest_rect.top + 1 + adjust_y + 9 + (dest_rect.bottom - dest_rect.top) / 6);
// DrawString(p_str);
// break;
// }
// SetClip(current_clip);
// DisposeRgn(current_clip);
// SetPort(old_port);
//}
short calc_day()
{
return (short) ((univ.party.age) / 3700) + 1;
}
bool day_reached(unsigned char which_day, unsigned char which_event)
// which_day is day event should happen
// which_event is the univ.party.key_times value to cross reference with.
// if the key_time is reached before which_day, event won't happen
// if it's 0, event always happens
{
if (which_event > 10)
return false;
if ((which_event > 0) && (univ.party.key_times[which_event] < which_day))
return false;
if (calc_day() >= which_day)
return true;
else return false;
}