Introduce a shop type enum and a shop class

- Shop scrollbar now only visible when needed
- Outdoor shop special node now supports junk shops
- Outdoor shop special node now uses correct title string
- Fix minor issue with framing rects
This commit is contained in:
2014-12-27 14:58:31 -05:00
parent d5575ee8fa
commit d00e44f650
14 changed files with 468 additions and 406 deletions

View File

@@ -286,6 +286,8 @@
91FCC8F118FEEDC6007026CE /* winutil.mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 919145FF18E63B70005CF3A4 /* winutil.mac.mm */; };
91FCC8F218FEEFE0007026CE /* pc.editors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91B3EF070F969BD300BF5B67 /* pc.editors.cpp */; };
91FCC8F418FF0866007026CE /* pc.appleevents.mm in Sources */ = {isa = PBXBuildFile; fileRef = 91FCC8F318FF069A007026CE /* pc.appleevents.mm */; };
91FDB57B1A4E77CA00DE5983 /* shop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91FDB5791A4E774E00DE5983 /* shop.cpp */; };
91FDB57C1A4E77CA00DE5983 /* shop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91FDB5791A4E774E00DE5983 /* shop.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -780,6 +782,8 @@
91FCC8DA18FE2CCA007026CE /* pc.menus.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pc.menus.h; sourceTree = "<group>"; };
91FCC8DB18FE2CE8007026CE /* pc.menus.mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = pc.menus.mac.mm; sourceTree = "<group>"; };
91FCC8F318FF069A007026CE /* pc.appleevents.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = pc.appleevents.mm; sourceTree = "<group>"; };
91FDB5771A4E71A900DE5983 /* shop.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = shop.hpp; sourceTree = "<group>"; };
91FDB5791A4E774E00DE5983 /* shop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shop.cpp; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -948,6 +952,7 @@
913D05BB0FA1EA0A00184C18 /* pc.cpp */,
91AC607F0FA26A3B00EEAE67 /* regtown.cpp */,
91279C580F9D1253007B0D52 /* scenario.cpp */,
91FDB5791A4E774E00DE5983 /* shop.cpp */,
91279CC60F9D1A02007B0D52 /* special.cpp */,
91597A6E1A3BEDC700BE7BF9 /* spell.cpp */,
91E5C7B70F9F619D00C21460 /* talking.cpp */,
@@ -973,6 +978,7 @@
91AC607E0FA26A3B00EEAE67 /* regtown.h */,
91279C570F9D1253007B0D52 /* scenario.h */,
912287850FD41A2300B21642 /* simpletypes.h */,
91FDB5771A4E71A900DE5983 /* shop.hpp */,
91279CC50F9D1A02007B0D52 /* special.h */,
91597A6C1A3BED2D00BE7BF9 /* spell.hpp */,
91E5C7B60F9F619D00C21460 /* talking.h */,
@@ -1606,6 +1612,7 @@
915E090A1A316EE3008BDF00 /* map_parse.cpp in Sources */,
91597A6F1A3C021400BE7BF9 /* spell.cpp in Sources */,
9179A4671A48683100FEF872 /* stack.cpp in Sources */,
91FDB57B1A4E77CA00DE5983 /* shop.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1721,6 +1728,7 @@
915E090B1A316EE4008BDF00 /* map_parse.cpp in Sources */,
91597A701A3C021600BE7BF9 /* spell.cpp in Sources */,
9179A4651A48683100FEF872 /* stack.cpp in Sources */,
91FDB57C1A4E77CA00DE5983 /* shop.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -35,6 +35,7 @@
#include "winutil.h"
#include "cursors.h"
#include "spell.hpp"
#include "shop.hpp"
rectangle bottom_buttons[7];
rectangle town_buttons[10];
@@ -76,9 +77,9 @@ short door_pc,store_drop_item;
short current_switch = 6;
cOutdoors::cWandering store_wandering_special;
long dummy;
short store_shop_type;
short store_selling_values[8] = {0,0,0,0,0,0,0,0};
extern cShop active_shop;
extern short cen_x, cen_y, stat_window,give_delays;//,pc_moves[6];
extern eGameMode overall_mode;
@@ -655,7 +656,7 @@ static void handle_switch_pc(short which_pc) {
else if(is_combat())
// TODO: Allow this, provided the chosen PC has APs; it would be equivalent to pressing space until reaching that PC
add_string_to_buf("Set active: Can't set this in combat.");
else if(univ.party[which_pc].main_status != eMainStatus::ALIVE && (overall_mode != MODE_SHOPPING || store_shop_type != 3))
else if(univ.party[which_pc].main_status != eMainStatus::ALIVE && (overall_mode != MODE_SHOPPING || active_shop.getType() != eShopType::HEALING))
add_string_to_buf("Set active: PC must be here & active.");
else {
current_pc = which_pc;
@@ -675,7 +676,7 @@ static void handle_switch_pc_items(short which_pc, bool& need_redraw) {
else {
if(!is_combat()) {
// TODO: Maybe allow this in combat, as per the above TODO note?
if(univ.party[which_pc].main_status != eMainStatus::ALIVE && (overall_mode != MODE_SHOPPING || store_shop_type != 12))
if(univ.party[which_pc].main_status != eMainStatus::ALIVE && (overall_mode != MODE_SHOPPING || active_shop.getType() != eShopType::ALCHEMY))
add_string_to_buf("Set active: PC must be here & active.");
else {
current_pc = which_pc;
@@ -687,7 +688,8 @@ static void handle_switch_pc_items(short which_pc, bool& need_redraw) {
}
set_stat_window(which_pc);
if(overall_mode == MODE_SHOPPING) {
set_up_shop_array();
if(active_shop.getType() == eShopType::HEALING)
set_up_shop_array(eShopType::HEALING, 0, 0);
draw_shop_graphics(0,item_screen_button_rects[which_pc]); // rect is dummy
}
}
@@ -1274,7 +1276,8 @@ bool handle_action(sf::Event event) {
put_pc_screen();
put_item_screen(stat_window,0);
if(overall_mode == MODE_SHOPPING) {
set_up_shop_array();
if(active_shop.getType() == eShopType::HEALING)
set_up_shop_array(eShopType::HEALING, 0, 0);
draw_shop_graphics(0,pc_buttons[0][0]);
}
}

View File

@@ -34,6 +34,7 @@
#include "pict.hpp"
#include <boost/lexical_cast.hpp>
#include "prefs.hpp"
#include "shop.hpp"
#define NUM_HINTS 30
//extern big_tr_type t_d;
@@ -93,11 +94,8 @@ extern std::vector<word_rect_t> talk_words;
// 800 + - mage spells
// 900 + - priest spells
// n000 + i - magic store n item i
short store_shop_items[30],store_shop_costs[30];
// talk_area_rect and talk_help_rect used for this too
short store_shop_min,store_shop_max,store_cost_mult;
eGameMode store_pre_shop_mode;
char store_store_name[256];
// 0 - whole area, 1 - active area 2 - graphic 3 - item name
// 4 - item cost 5 - item extra str 6 - item help button
extern rectangle shopping_rects[8][7];
@@ -107,16 +105,10 @@ rectangle shop_name_str = {44,6,56,200};
rectangle shop_frame = {62,10,352,269};
rectangle shop_done_rect = {388,212,411,275};
extern short store_shop_type;
const char* heal_types[] = {
"Heal Damage","Cure Poison","Cure Disease","Cure Paralysis",
"Uncurse Items","Cure Stoned Character","Raise Dead","Resurrection","Cure Dumbfounding"};
short heal_costs[9] = {50,30,80,100,250,500,1000,3000,100};
long cost_mult[7] = {5,7,10,13,16,20,25};
short store_scen_page_on,store_num_scen;
cShop active_shop;
/*
shop_type:
0 - weapon shop
@@ -129,30 +121,21 @@ shop_type:
11 - priest spells
12 alchemy
*/
void start_shop_mode(short shop_type,short shop_min,short shop_max,short cost_adj,const char* store_name) {
void start_shop_mode(eShopType shop_type,short shop_min,short shop_max,short cost_adj,std::string store_name) {
rectangle area_rect;
// This would be a place to hide the text box, if I add it.
if(shop_max < shop_min)
shop_max = shop_min; ////
store_cost_mult = cost_adj;
if(store_cost_mult > 6)
store_cost_mult = 6;
store_shop_type = shop_type;
store_shop_min = shop_min;
store_shop_max = shop_max;
active_shop = cShop(shop_type, cost_adj, store_name);
area_rect = talk_area_rect;
strcpy((char *) store_store_name,store_name);
talk_gworld.create(area_rect.width(), area_rect.height());
store_pre_shop_mode = overall_mode;
overall_mode = MODE_SHOPPING;
stat_screen_mode = 1;
set_up_shop_array();
set_up_shop_array(shop_type, shop_min, std::max(shop_min, shop_max));
put_background();
draw_shop_graphics(0,area_rect);
@@ -217,39 +200,42 @@ void handle_shop_event(location p) {
}
for(i = 0; i < 8; i++) {
store_what_picked = i;
if((p.in(shopping_rects[i][1])) && (store_shop_items[store_what_picked] >= 0)) {
store_what_picked = i + shop_sbar->getPosition();
if(store_what_picked >= active_shop.size()) break;
if(p.in(shopping_rects[i][1])) {
click_shop_rect(shopping_rects[i][1]);
handle_sale(store_shop_items[store_what_picked],store_shop_costs[store_what_picked]);
}
if((p.in(shopping_rects[i][6])) && (store_shop_items[store_what_picked] >= 0)
&& (store_shop_type != 3) && (store_shop_type != 4)){
handle_sale(active_shop.getItem(store_what_picked), store_what_picked);
} else if(p.in(shopping_rects[i][6]) && active_shop.getType() != eShopType::HEALING){
click_shop_rect(shopping_rects[i][6]);
handle_info_request(store_shop_items[store_what_picked]);
handle_info_request(active_shop.getItem(store_what_picked));
}
}
}
void handle_sale(short what_chosen,short cost) {
cItemRec base_item;
short what_magic_shop,what_magic_shop_item,i;
void handle_sale(cShopItem item, int i) {
cItemRec base_item = item.item;
short cost = item.cost;
rectangle dummy_rect = {0,0,0,0};
switch(what_chosen / 100) {
case 0: case 1: case 2: case 3: case 4:
base_item = get_stored_item(what_chosen);
base_item.ident = true;
//cost = (base_item.charges == 0) ? base_item.value : base_item.value * base_item.charges;
switch(item.type) {
case eShopItemType::ITEM:
switch(pc_ok_to_buy(current_pc,cost,base_item)) {
case 1: play_sound(-38); give_to_pc(current_pc,base_item,true); break;
case 1:
play_sound(-38);
give_to_pc(current_pc,base_item,true);
if(active_shop.getType() != eShopType::ITEMS) {
// Magic shops have limited stock
active_shop.clearItem(i);
shop_sbar->setMaximum(shop_sbar->getMaximum() - 1);
}
break;
case 2: ASB("Can't carry any more items."); break;
case 3: ASB("Not enough cash."); break;
case 4: ASB("Item is too heavy."); break;
case 5: ASB("You own too many of this."); break;
}
break;
case 5:
base_item = store_alchemy(what_chosen - 500);
case eShopItemType::ALCHEMY:
if(univ.party.alchemy[base_item.item_level])
ASB("You already know that recipe.");
else if(!take_gold(cost,false))
@@ -261,52 +247,53 @@ void handle_sale(short what_chosen,short cost) {
univ.party.alchemy[base_item.item_level] = true;
}
break;
case 6:
//base_item = food_types[what_chosen - 600];
//if(!take_gold(cost,false))
// ASB("Not enough gold.");
//else {
// play_sound(-38); ASB("You buy food.");
// univ.party.food += base_item.item_level;
//}
case eShopItemType::FOOD:
// TODO: This shop type is never actually used. Should it be deleted or restored?
if(!take_gold(cost,false))
ASB("Not enough gold.");
else {
play_sound(-38);
ASB("You buy food.");
univ.party.food += base_item.item_level;
}
break;
case 7:
what_chosen -= 700;
default:
if(!take_gold(cost,false))
ASB("Not enough gold.");
else {
ASB("You pay the healer.");
play_sound(68);
switch(what_chosen) {
case 0:
switch(item.type) {
case eShopItemType::HEAL_WOUNDS:
univ.party[current_pc].cur_health = univ.party[current_pc].max_health;
break;
case 1:
case eShopItemType::CURE_POISON:
univ.party[current_pc].status[eStatus::POISON] = 0;
break;
case 2:
case eShopItemType::CURE_DISEASE:
univ.party[current_pc].status[eStatus::DISEASE] = 0;
break;
case 3:
case eShopItemType::CURE_PARALYSIS:
univ.party[current_pc].status[eStatus::PARALYZED] = 0;
break;
case 4:
for(i = 0; i < 24; i++)
case eShopItemType::REMOVE_CURSE:
for(int i = 0; i < 24; i++)
if((univ.party[current_pc].equip[i]) &&
(univ.party[current_pc].items[i].cursed))
univ.party[current_pc].items[i].cursed = univ.party[current_pc].items[i].unsellable = false;
break;
case 5: case 6: case 7:
case eShopItemType::DESTONE: case eShopItemType::RAISE_DEAD: case eShopItemType::RESURRECT:
univ.party[current_pc].main_status = eMainStatus::ALIVE;
break;
case 8:
case eShopItemType::CURE_DUMBFOUNDING:
univ.party[current_pc].status[eStatus::DUMB] = 0;
break;
}
// Once you've been healed, of course you're no longer eligible for that form of healing.
active_shop.clearItem(i);
}
break;
case 8:
base_item = store_mage_spells(what_chosen - 800 - 30);
case eShopItemType::MAGE_SPELL:
if((base_item.item_level < 0) || (base_item.item_level > 61)) {
beep();
giveError("Error: The scenario tried to sell you an invalid mage spell!");
@@ -324,8 +311,7 @@ void handle_sale(short what_chosen,short cost) {
give_help(41,0);
}
break;
case 9:
base_item = store_priest_spells(what_chosen - 900 - 30);
case eShopItemType::PRIEST_SPELL:
if((base_item.item_level < 0) || (base_item.item_level > 61)) {
beep();
giveError("Error: The scenario tried to sell you an invalid priest spell!");
@@ -343,22 +329,7 @@ void handle_sale(short what_chosen,short cost) {
give_help(41,0);
}
break;
default:
what_magic_shop = (what_chosen / 1000) - 1;
what_magic_shop_item = what_chosen % 1000;
base_item = univ.party.magic_store_items[what_magic_shop][what_magic_shop_item];
base_item.ident = true;
switch(pc_ok_to_buy(current_pc,cost,base_item)) {
case 1: play_sound(-38); give_to_pc(current_pc,base_item,true);
univ.party.magic_store_items[what_magic_shop][what_magic_shop_item].variety = eItemType::NO_ITEM;
break;
case 2: ASB("Can't carry any more items."); break;
case 3: ASB("Not enough cash."); break;
case 4: ASB("Item is too heavy."); break;
}
break;
}
set_up_shop_array();
if(overall_mode != MODE_SHOPPING) {
beep();
@@ -371,159 +342,92 @@ void handle_sale(short what_chosen,short cost) {
}
void handle_info_request(short what_chosen) {
cItemRec base_item;
short what_magic_shop,what_magic_shop_item;
void handle_info_request(cShopItem item) {
cItemRec base_item = item.item;
switch(what_chosen / 100) {
case 0: case 1: case 2: case 3: case 4:
base_item = get_stored_item(what_chosen);
base_item.ident = true;
switch(item.type) {
case eShopItemType::ITEM:
case eShopItemType::FOOD:
display_pc_item(6,0, base_item,0);
break;
case 5:
case eShopItemType::ALCHEMY:
// TODO: Create a dedicated dialog for alchemy info
display_alchemy();
break;
case 8:
base_item = store_mage_spells(what_chosen - 800 - 30);
display_spells(eSkill::MAGE_SPELLS,base_item.item_level,0);
case eShopItemType::MAGE_SPELL:
display_spells(eSkill::MAGE_SPELLS,base_item.item_level - 800 - 30,0);
break;
case 9:
base_item = store_priest_spells(what_chosen - 900 - 30);
display_spells(eSkill::PRIEST_SPELLS,base_item.item_level,0);
break;
default:
what_magic_shop = (what_chosen / 1000) - 1;
what_magic_shop_item = what_chosen % 1000;
base_item = univ.party.magic_store_items[what_magic_shop][what_magic_shop_item];
base_item.ident = true;
display_pc_item(6,0, base_item,0);
case eShopItemType::PRIEST_SPELL:
display_spells(eSkill::PRIEST_SPELLS,base_item.item_level - 900 - 30,0);
break;
}
}
void set_up_shop_array() {
short i,shop_pos = 0;
void set_up_shop_array(eShopType store_shop_type, short store_shop_min, short store_shop_max) {
bool cursed_item = false;
cItemRec store_i;
long store_l;
active_shop.clear();
for(i = 0; i < 30; i++)
store_shop_items[i] = -1;
switch(store_shop_type) {
case 0: case 1: case 2:
for(i = store_shop_min; i < store_shop_max + 1; i++) {
store_shop_items[shop_pos] = i;
store_i = get_stored_item(store_shop_items[shop_pos]);
store_shop_costs[shop_pos] = (store_i.charges == 0) ?
store_i.value : store_i.value * store_i.charges;
shop_pos++;
}
case eShopType::ITEMS:
for(int i = store_shop_min; i <= store_shop_max; i++)
active_shop.addItem(get_stored_item(i));
break;
case 3:
if(univ.party[current_pc].cur_health < univ.party[current_pc].max_health) {
store_shop_items[shop_pos] = 700;
store_shop_costs[shop_pos] = heal_costs[0];
shop_pos++;
}
if(univ.party[current_pc].status[eStatus::POISON] > 0) {
store_shop_items[shop_pos] = 701;
store_shop_costs[shop_pos] = heal_costs[1];
shop_pos++;
}
if(univ.party[current_pc].status[eStatus::DISEASE] > 0) {
store_shop_items[shop_pos] = 702;
store_shop_costs[shop_pos] = heal_costs[2];
shop_pos++;
}
if(univ.party[current_pc].status[eStatus::PARALYZED] > 0) {
store_shop_items[shop_pos] = 703;
store_shop_costs[shop_pos] = heal_costs[3];
shop_pos++;
}
if(univ.party[current_pc].status[eStatus::DUMB] > 0) {
store_shop_items[shop_pos] = 708;
store_shop_costs[shop_pos] = heal_costs[8];
shop_pos++;
}
for(i = 0; i < 24; i++)
case eShopType::HEALING:
if(univ.party[current_pc].cur_health < univ.party[current_pc].max_health)
active_shop.addSpecial(eShopItemType::HEAL_WOUNDS);
if(univ.party[current_pc].status[eStatus::POISON] > 0)
active_shop.addSpecial(eShopItemType::CURE_POISON);
if(univ.party[current_pc].status[eStatus::DISEASE] > 0)
active_shop.addSpecial(eShopItemType::CURE_DISEASE);
if(univ.party[current_pc].status[eStatus::PARALYZED] > 0)
active_shop.addSpecial(eShopItemType::CURE_PARALYSIS);
if(univ.party[current_pc].status[eStatus::DUMB] > 0)
active_shop.addSpecial(eShopItemType::CURE_DUMBFOUNDING);
for(int i = 0; i < 24; i++)
if((univ.party[current_pc].equip[i]) && (univ.party[current_pc].items[i].cursed))
cursed_item = true;
if(cursed_item) {
store_shop_items[shop_pos] = 704;
store_shop_costs[shop_pos] = heal_costs[4];
shop_pos++;
}
if(univ.party[current_pc].main_status == eMainStatus::STONE) {
store_shop_items[shop_pos] = 705;
store_shop_costs[shop_pos] = heal_costs[5];
shop_pos++;
}
if(univ.party[current_pc].main_status == eMainStatus::DEAD){
store_shop_items[shop_pos] = 706;
store_shop_costs[shop_pos] = heal_costs[6];
shop_pos++;
}
if(univ.party[current_pc].main_status == eMainStatus::DUST){
store_shop_items[shop_pos] = 707;
store_shop_costs[shop_pos] = heal_costs[7];
shop_pos++;
}
if(cursed_item) active_shop.addSpecial(eShopItemType::REMOVE_CURSE);
if(univ.party[current_pc].main_status == eMainStatus::STONE)
active_shop.addSpecial(eShopItemType::DESTONE);
if(univ.party[current_pc].main_status == eMainStatus::DEAD)
active_shop.addSpecial(eShopItemType::RAISE_DEAD);
if(univ.party[current_pc].main_status == eMainStatus::DUST)
active_shop.addSpecial(eShopItemType::RESURRECT);
break;
case 4:
//for(i = store_shop_min; i < store_shop_max + 1; i++) {
// store_shop_items[shop_pos] = 600 + i;
// store_shop_costs[shop_pos] = food_types[i].value;
// shop_pos++;
//}
case eShopType::FOOD:
// TODO: This shop type is never actually used. Should it be deleted or resurrected?
for(int i = store_shop_min; i <= store_shop_max; i++)
active_shop.addSpecial(eShopItemType::FOOD, i);
break;
case 5: case 6: case 7: case 8: case 9:
for(i = 0; i < 10; i++)
if(univ.party.magic_store_items[store_shop_type - 5][i].variety != eItemType::NO_ITEM) {
store_shop_items[shop_pos] = (store_shop_type - 4) * 1000 + i;
store_i = univ.party.magic_store_items[store_shop_type - 5][i];
store_shop_costs[shop_pos] = (store_i.charges == 0) ?
store_i.value : store_i.value * store_i.charges;
shop_pos++;
}
case eShopType::MAGIC_JUNK:
active_shop.addItems(univ.party.magic_store_items[0].begin(), univ.party.magic_store_items[0].end());
break;
case 10:
for(i = store_shop_min; i < store_shop_max + 1; i++)
if(i == minmax(0,31,i)) {
store_i = store_mage_spells(i);
store_shop_costs[shop_pos] = store_i.value;
store_shop_items[shop_pos] = 800 + i;
shop_pos++;
}
case eShopType::MAGIC_LOUSY:
active_shop.addItems(univ.party.magic_store_items[1].begin(), univ.party.magic_store_items[1].end());
break;
case 11:
for(i = store_shop_min; i < store_shop_max + 1; i++)
if(i == minmax(0,31,i)) {
store_i = store_priest_spells(i);
store_shop_costs[shop_pos] = store_i.value;
store_shop_items[shop_pos] = 900 + i;
shop_pos++;
}
case eShopType::MAGIC_SO_SO:
active_shop.addItems(univ.party.magic_store_items[2].begin(), univ.party.magic_store_items[2].end());
break;
case 12:
for(i = store_shop_min; i < store_shop_max + 1; i++)
if(i == minmax(0,19,i)) {
store_i = store_alchemy(i);
store_shop_costs[shop_pos] = store_i.value;
store_shop_items[shop_pos] = 500 + i;
shop_pos++;
}
case eShopType::MAGIC_GOOD:
active_shop.addItems(univ.party.magic_store_items[3].begin(), univ.party.magic_store_items[3].end());
break;
case eShopType::MAGIC_GREAT:
active_shop.addItems(univ.party.magic_store_items[4].begin(), univ.party.magic_store_items[4].end());
break;
case eShopType::MAGE:
for(int i = store_shop_min; i <= store_shop_max && i < 62; i++)
active_shop.addSpecial(eShopItemType::MAGE_SPELL, i);
break;
case eShopType::PRIEST:
for(int i = store_shop_min; i <= store_shop_max && i < 62; i++)
active_shop.addSpecial(eShopItemType::PRIEST_SPELL, i);
break;
case eShopType::ALCHEMY:
for(int i = store_shop_min; i <= store_shop_max && i < 20; i++)
active_shop.addSpecial(eShopItemType::ALCHEMY, i);
break;
}
for(i = 0; i < 30; i++)
if(store_shop_items[i] >= 0) {
store_l = store_shop_costs[i];
store_l = (store_l * cost_mult[store_cost_mult]) / 10;
store_shop_costs[i] = (short) store_l;
}
i = max(0,shop_pos - 8);
shop_sbar->setMaximum(i);
shop_sbar->setMaximum(active_shop.size() - 8);
}
void start_talk_mode(short m_num,short personality,m_num_t monst_type,short store_face_pic) {
@@ -754,7 +658,7 @@ void handle_talk_event(location p) {
break;
case 7:
c = minmax(1,30,c);
start_shop_mode(2,b,b + c - 1,a,save_talk_str1.c_str());
start_shop_mode(eShopType::ITEMS,b,b + c - 1,a,save_talk_str1.c_str());
strnum1 = -1;
return;
case 8:
@@ -765,14 +669,24 @@ void handle_talk_event(location p) {
save_talk_str1 = "You conclude your training.";
return;
case 9: case 10: case 11:
c = minmax(1,30,c);
start_shop_mode(ttype + 1,b,b + c - 1,a,save_talk_str1.c_str());
case 9:
c = minmax(1,61,c);
start_shop_mode(eShopType::MAGE,b,b + c - 1,a,save_talk_str1.c_str());
strnum1 = -1;
return;
case 10:
c = minmax(1,61,c);
start_shop_mode(eShopType::PRIEST,b,b + c - 1,a,save_talk_str1.c_str());
strnum1 = -1;
return;
case 11:
c = minmax(1,19,c);
start_shop_mode(eShopType::ALCHEMY,b,b + c - 1,a,save_talk_str1.c_str());
strnum1 = -1;
return;
case 12: //healer
// TODO: extra1 and extra2 are actually never used! So remove them.
start_shop_mode(3,univ.town.monst[store_m_num].extra1,
start_shop_mode(eShopType::HEALING,univ.town.monst[store_m_num].extra1,
univ.town.monst[store_m_num].extra2,a,save_talk_str1.c_str());
strnum1 = -1;
return;
@@ -904,7 +818,7 @@ void handle_talk_event(location p) {
save_talk_str2 = "";
break;
case 23:
start_shop_mode(5 + b,0,
start_shop_mode(eShopType(5 + b),0,
9,a,save_talk_str1.c_str());
strnum1 = -1;
return;

View File

@@ -1,15 +1,17 @@
#ifndef BOE_GAME_DLGUTIL_H
#include <string>
#include "dialog.hpp"
#include "simpletypes.h"
#include "shop.hpp"
void start_shop_mode(short shop_type,short shop_min,short shop_max,short cost_adj,const char* store_name);
void start_shop_mode(eShopType shop_type,short shop_min,short shop_max,short cost_adj,std::string store_name);
void end_shop_mode();
void handle_shop_event(location p);
void handle_sale(short what_chosen,short cost);
void handle_info_request(short what_chosen);
void set_up_shop_array();
void handle_sale(cShopItem item, int i);
void handle_info_request(cShopItem item);
void set_up_shop_array(eShopType shop_type, short shop_min, short shop_max);
void start_talk_mode(short m_num,short personality,m_num_t monst_type,short store_face_pic);
void end_talk_mode();
void handle_talk_event(location p);

View File

@@ -919,8 +919,7 @@ static void put_item_graphics(cDialog& me, size_t& first_item_shown, short& curr
csp(987,20 + i * 4,/*3000 + 2000 + */item.graphic_num - 1000,PICT_CUSTOM + PICT_ITEM);
else csp(987,20 + i * 4,/*4800 + */item.graphic_num,PICT_ITEM);
#endif
get_item_interesting_string(item,(char *) message);
me[detail].setText(message);
me[detail].setText(get_item_interesting_string(item));
storage = item.item_weight();
sprintf ((char *) message, "Weight: %d",storage);
me[weight].setText(message);

View File

@@ -22,6 +22,7 @@
#include "scrollbar.hpp"
#include <memory>
#include "location.h"
#include "shop.hpp"
short monsters_faces[190] = {
0,1,2,3,4,5,6,7,8,9,
@@ -86,10 +87,8 @@ extern m_num_t store_monst_type;
std::vector<word_rect_t> talk_words;
// Shop vars
extern short store_shop_items[30],store_shop_costs[30];
extern short store_shop_type,store_shop_min,store_shop_max,store_cost_mult;
extern cShop active_shop;
extern eGameMode store_pre_shop_mode;
extern char store_store_name[256];
extern rectangle shopping_rects[8][7];
extern rectangle bottom_help_rects[4];
extern rectangle shop_name_str;
@@ -673,9 +672,8 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) {
rectangle face_rect = {6,6,38,38};
rectangle title_rect = {15,48,42,260};
rectangle dest_rect,help_from = {85,36,101,54};
short faces[13] = {1,1,1,42,43, 1,1,1,1,1, 44,44,44};
short i,what_chosen;
short i;
// In the 0..65535 range, these blue components were: 0, 32767, 14535, 26623, 59391
// The green components on the second line were 40959 and 24575
// TODO: The duplication of sf::Color here shouldn't be necessary...
@@ -685,9 +683,7 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) {
rectangle shopper_name = {44,6,56,260};
short current_pos;
short cur_cost,what_magic_shop,what_magic_shop_item;
char cur_name[60];
char cur_info_str[60];
short cur_cost;
static const char*const cost_strs[] = {
"Extremely Cheap","Very Reasonable","Pretty Average","Somewhat Pricey",
"Expensive","Exorbitant","Utterly Ridiculous"};
@@ -716,7 +712,12 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) {
// Place store icon
if(!pressed) {
i = faces[store_shop_type];
i = 0;
eShopType type = active_shop.getType();
if(type == eShopType::HEALING) i = 41;
else if(type == eShopType::FOOD) i = 42;
else if(type == eShopType::MAGE || type == eShopType::PRIEST || type == eShopType::ALCHEMY)
i = 43;
rectangle from_rect = {0,0,32,32};
from_rect.offset(32 * (i % 10),32 * (i / 10));
rect_draw_some_item(talkfaces_gworld, from_rect, talk_gworld, face_rect);
@@ -728,24 +729,34 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) {
style.lineHeight = 18;
dest_rect = title_rect;
dest_rect.offset(1,1);
win_draw_string(talk_gworld,dest_rect,store_store_name,eTextMode::LEFT_TOP,style);
win_draw_string(talk_gworld,dest_rect,active_shop.getName(),eTextMode::LEFT_TOP,style);
dest_rect.offset(-1,-1);
style.colour = c[4];
win_draw_string(talk_gworld,dest_rect,store_store_name,eTextMode::LEFT_TOP,style);
win_draw_string(talk_gworld,dest_rect,active_shop.getName(),eTextMode::LEFT_TOP,style);
style.font = FONT_BOLD;
style.pointSize = 12;
style.colour = c[3];
switch(store_shop_type) {
case 3: sprintf(cur_name,"Healing for %s.",univ.party[current_pc].name.c_str()); break;
case 10: sprintf(cur_name,"Mage Spells for %s.",univ.party[current_pc].name.c_str());break;
case 11: sprintf(cur_name,"Priest Spells for %s.",univ.party[current_pc].name.c_str()); break;
case 12: sprintf(cur_name,"Buying Alchemy.");break;
case 4: sprintf(cur_name,"Buying Food.");break;
default:sprintf(cur_name,"Shopping for %s.",univ.party[current_pc].name.c_str()); break;
std::ostringstream title;
switch(active_shop.getType()) {
case eShopType::HEALING:
title << "Healing for " << univ.party[current_pc].name << '.';
break;
case eShopType::MAGE:
title << "Mage Spells for " << univ.party[current_pc].name << '.';
break;
case eShopType::PRIEST:
title << "Priest Spells for " << univ.party[current_pc].name << '.';
break;
case eShopType::ALCHEMY:
title << "Buying Alchemy.";
break;
default:
title << "Shopping for " << univ.party[current_pc].name << '.';
break;
}
win_draw_string(talk_gworld,shopper_name,cur_name,eTextMode::LEFT_TOP,style);
win_draw_string(talk_gworld,shopper_name,title.str(),eTextMode::LEFT_TOP,style);
// Place help and done buttons
// TODO: Reimplement these with a cButton
@@ -767,67 +778,34 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) {
// Place all the items
for(i = 0; i < 8; i++) {
current_pos = i + shop_sbar->getPosition();
if(store_shop_items[current_pos] < 0)
break; // theoretically, this shouldn't happen
cur_cost = store_shop_costs[current_pos];
what_chosen = store_shop_items[current_pos];
cShopItem item = active_shop.getItem(i);
if(item.type == eShopItemType::EMPTY)
continue; // theoretically, this shouldn't happen
cur_cost = item.cost;
base_item = item.item;
std::string cur_name = base_item.full_name, cur_info_str;
rectangle from_rect, to_rect = shopping_rects[i][2];
sf::Texture* from_gw;
switch(what_chosen / 100) {
case 0: case 1: case 2: case 3: case 4:
base_item = get_stored_item(what_chosen);
switch(item.type) {
case eShopItemType::ITEM:
base_item.ident = true;
graf_pos_ref(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect);
rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha);
strcpy(cur_name,base_item.full_name.c_str());
get_item_interesting_string(base_item,cur_info_str);
cur_info_str = get_item_interesting_string(base_item);
break;
case 5:
base_item = store_alchemy(what_chosen - 500);
graf_pos_ref(from_gw, from_rect) = calc_item_rect(53,to_rect);
rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha);
strcpy(cur_name,base_item.full_name.c_str());
strcpy(cur_info_str,"");
case eShopItemType::ALCHEMY:
cur_info_str = "";
break;
case 6:
//base_item = food_types[what_chosen - 600];
//draw_dialog_graphic( talk_gworld, shopping_rects[i][2],633, false,1);
//strcpy(cur_name,base_item.full_name);
//get_item_interesting_string(base_item,cur_info_str);
case eShopItemType::MAGE_SPELL:
cur_info_str = "";
break;
case 7:
what_chosen -= 700;
graf_pos_ref(from_gw, from_rect) = calc_item_rect(99,to_rect);
rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha);
strcpy(cur_name,heal_types[what_chosen]);
strcpy(cur_info_str,"");
case eShopItemType::PRIEST_SPELL:
cur_info_str = "";
break;
case 8:
base_item = store_mage_spells(what_chosen - 800 - 30);
graf_pos_ref(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect);
rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha);
strcpy(cur_name,base_item.full_name.c_str());
strcpy(cur_info_str,"");
break;
case 9:
base_item = store_priest_spells(what_chosen - 900 - 30);
graf_pos_ref(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect);
rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha);
strcpy(cur_name,base_item.full_name.c_str());
strcpy(cur_info_str,"");
break;
default:
what_magic_shop = (what_chosen / 1000) - 1;
what_magic_shop_item = what_chosen % 1000;
base_item = univ.party.magic_store_items[what_magic_shop][what_magic_shop_item];
base_item.ident = true;
graf_pos_ref(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect);
rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha);
strcpy(cur_name,base_item.full_name.c_str());
get_item_interesting_string(base_item,cur_info_str);
default: // Healing
cur_info_str = "";
break;
}
graf_pos_ref(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect);
rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha);
// Now draw item shopping_rects[i][7]
// 0 - whole area, 1 - active area 2 - graphic 3 - item name
@@ -835,44 +813,41 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) {
style.pointSize = 12;
style.lineHeight = 12;
win_draw_string(talk_gworld,shopping_rects[i][3],cur_name,eTextMode::WRAP,style);
sprintf(cur_name,"Cost: %d",cur_cost);
cur_name = "Cost: " + std::to_string(cur_cost);
win_draw_string(talk_gworld,shopping_rects[i][4],cur_name,eTextMode::WRAP,style);
style.pointSize = 10;
win_draw_string(talk_gworld,shopping_rects[i][5],cur_info_str,eTextMode::WRAP,style);
if((store_shop_type != 3) && (store_shop_type != 4))
if(active_shop.getType() != eShopType::HEALING) // Draw info button
rect_draw_some_item(invenbtn_gworld,item_info_from,talk_gworld,shopping_rects[i][6],pressed ? sf::BlendNone : sf::BlendAlpha);
}
// Finally, cost info and help strs
sprintf(cur_name,"Prices here are %s.",cost_strs[store_cost_mult]);
title.str("");
title << "Prices here are " << cost_strs[active_shop.getCostAdjust()] << '.';
style.pointSize = 10;
style.lineHeight = 12;
win_draw_string(talk_gworld,bottom_help_rects[0],cur_name,eTextMode::WRAP,style);
win_draw_string(talk_gworld,bottom_help_rects[0],title.str(),eTextMode::WRAP,style);
win_draw_string(talk_gworld,bottom_help_rects[1],"Click on item name (or type 'a'-'h') to buy.",eTextMode::WRAP,style);
win_draw_string(talk_gworld,bottom_help_rects[2],"Hit done button (or Esc.) to quit.",eTextMode::WRAP,style);
if((store_shop_type != 3) && (store_shop_type != 4))
if(active_shop.getType() != eShopType::HEALING)
win_draw_string(talk_gworld,bottom_help_rects[3],"'I' button brings up description.",eTextMode::WRAP,style);
undo_clip(talk_gworld);
talk_gworld.display();
refresh_shopping();
if(shop_sbar->getMaximum() > 1)
shop_sbar->show();
shop_sbar->draw();
else shop_sbar->hide();
}
void refresh_shopping() {
// TODO: The duplication of rectangle here shouldn't be necessary...
rectangle from_rects[4] = {rectangle{0,0,62,279},rectangle{62,0,352,253},rectangle{62,269,352,279},rectangle{352,0,415,279}};
rectangle to_rect;
short i;
for(i = 0; i < 4; i++) {
to_rect = from_rects[i];
rectangle from_rect(talk_gworld);
rectangle to_rect = from_rect;
to_rect.offset(5,5);
rect_draw_some_item(talk_gworld.getTexture(),from_rects[i],to_rect,ul);
}
rect_draw_some_item(talk_gworld.getTexture(),from_rect,to_rect,ul);
shop_sbar->draw();
}
static void place_talk_face() {
@@ -914,84 +889,17 @@ void click_talk_rect(word_rect_t word) {
place_talk_face();
}
cItemRec store_mage_spells(short which_s) {
cItemRec spell('spel');// = {21,0, 0,0,0,0,0,0, 53,0,0,0,0, 0, 0,0, {0,0},"", "",0,0,0,0};
static const short cost[62] = {
// TODO: Costs for the level 1-3 spells
5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,
150,200,150,1000,1200,400,300,200,
200,250,500,1500,300, 250,125,150,
400,450, 800,600,700,600,7500, 500,
5000,3000,3500,4000,4000,4500,7000,5000
};
std::string str;
if(which_s != minmax(0,61,which_s))
which_s = 0;
spell.item_level = which_s;
spell.value = cost[which_s];
str = get_str("magic-names",which_s + 1);
spell.full_name = str.c_str();
return spell;
}
cItemRec store_priest_spells(short which_s) {
cItemRec spell('spel');// = {21,0, 0,0,0,0,0,0, 53,0,0,0,0, 0, 0,0, {0,0},"", "",0,0,0,0};
static const short cost[62] = {
// TODO: Costs for the level 1-3 spells
5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,
100,150,75,400,200, 100,80,250,
400,400,1200,600,300, 600,350,250,
500,500,600,800, 1000,900,400,600,
2500,2000,4500,4500,3000,3000,2000,2000
};
std::string str;
if(which_s != minmax(0,61,which_s))
which_s = 0;
spell.item_level = which_s;
spell.value = cost[which_s];
str = get_str("magic-names",which_s + 101);
spell.full_name = str.c_str();
return spell;
}
cItemRec store_alchemy(short which_s) {
cItemRec spell('spel');// = {21,0, 0,0,0,0,0,0, 53,0,0,0,0, 0, 0,0, {0,0},"", "",0,0,0,0};
static const short val[20] = {
50,75,30,130,100,
150, 200,200,300,250,
300, 500,600,750,700,
1000,10000,5000,7000,12000
};
std::string str;
if(which_s != minmax(0,19,which_s))
which_s = 0;
spell.item_level = which_s;
spell.value = val[which_s];
str = get_str("magic-names",which_s + 200);
spell.full_name = str.c_str();
return spell;
}
void get_item_interesting_string(cItemRec item,char *message) {
std::string get_item_interesting_string(cItemRec item) {
if(item.property) {
strcpy(message,"Not yours.");
return;
return "Not yours.";
}
if(!item.ident) {
strcpy(message,"");
return;
return "";
}
if(item.cursed) {
strcpy(message,"Cursed item.");
return;
return "Cursed item.";
}
char message[256];
switch(item.variety) {
case eItemType::ONE_HANDED:
case eItemType::TWO_HANDED:
@@ -1033,6 +941,7 @@ void get_item_interesting_string(cItemRec item,char *message) {
}
if(item.charges > 0)
sprintf(message,"Uses: %d",item.charges);
return message;
}
// color 0 - regular 1 - darker

View File

@@ -58,10 +58,7 @@ void do_explosion_anim(short sound_num,short expand);
void click_shop_rect(rectangle area_rect);
void draw_shop_graphics(bool pressed,rectangle clip_area_rect);
void refresh_shopping();
cItemRec store_mage_spells(short which_s) ;
cItemRec store_priest_spells(short which_s);
cItemRec store_alchemy(short which_s);
void get_item_interesting_string(cItemRec item,char *message);
std::string get_item_interesting_string(cItemRec item);
void click_talk_rect(word_rect_t word);
void place_talk_str(std::string str_to_place,std::string str_to_place2,short color,rectangle c_rect);
short scan_for_response(const char *str);

View File

@@ -3942,19 +3942,13 @@ void outdoor_spec(eSpecCtx which_mode,cSpecial cur_node,short cur_spec_type,
*a = 1;
break;
case eSpecType::OUT_STORE:
get_strs(str1,str2,1,spec.m1 + 10,-1);
get_strs(str1,str2,1,spec.m1,-1);
if(spec.ex2a >= 40)
spec.ex2a = 39;
if(spec.ex2a < 1)
spec.ex2a = 1;
spec.ex2b = minmax(0,6,spec.ex2b);
switch(spec.ex1b) {
case 0: start_shop_mode(0,spec.ex1a,spec.ex1a + spec.ex2a - 1,spec.ex2b,str1.c_str()); break;
case 1: start_shop_mode(10,spec.ex1a,spec.ex1a + spec.ex2a - 1,spec.ex2b,str1.c_str()); break;
case 2: start_shop_mode(11,spec.ex1a,spec.ex1a + spec.ex2a - 1 ,spec.ex2b,str1.c_str()); break;
case 3: start_shop_mode(12,spec.ex1a,spec.ex1a + spec.ex2a - 1,spec.ex2b,str1.c_str()); break;
case 4: start_shop_mode(3,spec.ex1a,spec.ex1a + spec.ex2a - 1,spec.ex2b,str1.c_str()); break;
}
start_shop_mode(eShopType(spec.ex1b), spec.ex1a, spec.ex1a + spec.ex2a - 1, spec.ex2b, str1);
*next_spec = -1;
break;
}

View File

@@ -11,6 +11,7 @@
#include <string>
#include <vector>
#include <array>
#include <map>
#include <set>
#include "vehicle.h"
@@ -82,7 +83,7 @@ public:
short in_boat;
short in_horse;
cOutdoors::cCreature out_c[10];
cItemRec magic_store_items[5][10];
std::array<std::array<cItemRec,10>,5> magic_store_items;
short imprisoned_monst[4]; // Soul Crystal?
char m_noted[256]; // has the monster been scried?
char m_seen[256]; // has the monster ever been seen? (this used to have the above meaning)

159
osx/classes/shop.cpp Normal file
View File

@@ -0,0 +1,159 @@
//
// shop.cpp
// BoE
//
// Created by Celtic Minstrel on 14-12-27.
//
//
#include "shop.hpp"
#include <numeric>
#include "mathutil.h"
#include "graphtool.h" // for get_str
static long cost_mult[7] = {5,7,10,13,16,20,25};
cShop::cShop() {}
cShop::cShop(eShopType type, int adj, std::string name) : type(type), cost_adj(adj), name(name) {}
size_t cShop::firstEmpty() {
for(size_t i = 0; i < items.size(); i++) {
if(items[i].type == eShopItemType::EMPTY)
return i;
}
return items.size();
}
size_t cShop::size() {
return std::count_if(items.begin(), items.end(), [](cShopItem& item) {
return item.type != eShopItemType::EMPTY;
});
}
void cShop::addItem(cItemRec item) {
size_t i = firstEmpty();
if(i >= items.size()) return;
if(item.variety == eItemType::NO_ITEM) return;
items[i].type = eShopItemType::ITEM;
items[i].item = item;
items[i].item.ident = true;
items[i].cost = item.value;
if(item.charges > 0)
items[i].cost *= item.charges;
items[i].cost *= cost_mult[cost_adj];
items[i].cost /= 10;
}
static cItemRec store_mage_spells(short which_s) {
cItemRec spell('spel');
static const short cost[62] = {
// TODO: Costs for the level 1-3 spells
5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,
150,200,150,1000,1200,400,300,200,
200,250,500,1500,300, 250,125,150,
400,450, 800,600,700,600,7500, 500,
5000,3000,3500,4000,4000,4500,7000,5000
};
if(which_s != minmax(0,61,which_s))
which_s = 0;
spell.item_level = which_s;
spell.value = cost[which_s];
spell.full_name = get_str("magic-names",which_s + 1);
return spell;
}
static cItemRec store_priest_spells(short which_s) {
cItemRec spell('spel');
static const short cost[62] = {
// TODO: Costs for the level 1-3 spells
5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,
100,150,75,400,200, 100,80,250,
400,400,1200,600,300, 600,350,250,
500,500,600,800, 1000,900,400,600,
2500,2000,4500,4500,3000,3000,2000,2000
};
if(which_s != minmax(0,61,which_s))
which_s = 0;
spell.item_level = which_s;
spell.value = cost[which_s];
spell.full_name = get_str("magic-names",which_s + 101);
return spell;
}
static cItemRec store_alchemy(short which_s) {
cItemRec spell('spel');
static const short val[20] = {
50,75,30,130,100,
150, 200,200,300,250,
300, 500,600,750,700,
1000,10000,5000,7000,12000
};
if(which_s != minmax(0,19,which_s))
which_s = 0;
spell.item_level = which_s;
spell.value = val[which_s];
spell.full_name = get_str("magic-names",which_s + 200);
return spell;
}
void cShop::addSpecial(eShopItemType type, int n) {
// TODO: Make this a std::map instead
static const short heal_costs[9] = {50,30,80,100,250,500,1000,3000,100};
static const char*const heal_types[] = {
"Heal Damage","Cure Poison","Cure Disease","Cure Paralysis",
"Uncurse Items","Cure Stoned Character","Raise Dead","Resurrection","Cure Dumbfounding"
};
if(type == eShopItemType::EMPTY) return;
if(type == eShopItemType::ITEM) return;
size_t i = firstEmpty();
if(i >= items.size()) return;
items[i].type = type;
if(type == eShopItemType::MAGE_SPELL)
items[i].item = store_mage_spells(n);
else if(type == eShopItemType::PRIEST_SPELL)
items[i].item = store_priest_spells(n);
else if(type == eShopItemType::ALCHEMY)
items[i].item = store_alchemy(n);
else {
items[i].item.graphic_num = 109;
items[i].item.full_name = heal_types[int(type) - 700];
}
if(type == eShopItemType::MAGE_SPELL || type == eShopItemType::PRIEST_SPELL || type == eShopItemType::ALCHEMY)
items[i].cost = items[i].item.value;
else items[i].cost = heal_costs[int(type) - 700];
items[i].cost *= cost_mult[cost_adj];
items[i].cost /= 10;
}
cShopItem cShop::getItem(size_t i) const {
return items[i];
}
eShopType cShop::getType() const {
return type;
}
int cShop::getCostAdjust() const {
return cost_adj;
}
std::string cShop::getName() const {
return name;
}
void cShop::clearItem(size_t i) {
std::copy(items.begin() + i + 1, items.end(), items.begin() + i);
items.back().type = eShopItemType::EMPTY;
}
void cShop::clear() {
std::fill(items.begin(), items.end(), cShopItem());
}

63
osx/classes/shop.hpp Normal file
View File

@@ -0,0 +1,63 @@
//
// shop.hpp
// BoE
//
// Created by Celtic Minstrel on 14-12-26.
//
//
#ifndef BoE_DATA_SHOP_HPP
#define BoE_DATA_SHOP_HPP
#include <array>
#include <string>
#include "item.h"
enum class eShopItemType {
EMPTY = 0,
ITEM = 1,
HEAL_WOUNDS = 700,
CURE_POISON = 701,
CURE_DISEASE = 702,
CURE_PARALYSIS = 703,
CURE_DUMBFOUNDING = 708,
REMOVE_CURSE = 704,
DESTONE = 705,
RAISE_DEAD = 706,
RESURRECT = 707,
MAGE_SPELL = 800,
PRIEST_SPELL = 900,
ALCHEMY = 500,
FOOD = 600,
};
struct cShopItem {
eShopItemType type = eShopItemType::EMPTY;
int cost;
cItemRec item;
};
class cShop {
std::array<cShopItem,30> items;
int cost_adj;
std::string name;
eShopType type;
size_t firstEmpty();
public:
cShop();
cShop(eShopType type, int adj, std::string name);
void addItem(cItemRec item);
void addSpecial(eShopItemType type, int n = 0);
template<typename Iter> void addItems(Iter begin, Iter end) {
while(begin != end) addItem(*begin++);
}
size_t size();
cShopItem getItem(size_t i) const;
eShopType getType() const;
int getCostAdjust() const;
std::string getName() const;
void clearItem(size_t i);
void clear();
};
#endif

View File

@@ -1035,4 +1035,18 @@ inline bool isPriest(eSpell spell) {
return code >= 100 && code < 162;
}
enum class eShopType {
ITEMS = 0,
MAGE = 1,
PRIEST = 2,
ALCHEMY = 3,
HEALING = 4,
MAGIC_JUNK = 5,
MAGIC_LOUSY = 6,
MAGIC_SO_SO = 7,
MAGIC_GOOD = 8,
MAGIC_GREAT = 9,
FOOD = 10,
};
#endif

View File

@@ -249,8 +249,7 @@ short choose_text(eStrType list, unsigned short cur_choice, cDialog* parent, con
// TODO: Generate a list of special node contexts
break;
case STRT_SHOP:
// TODO: There are actually a few more shop types than this (like junk shops)
strings = {"Items", "Mage Spells", "Priest Spells", "Alchemy", "Healing"};
strings = {"Items", "Mage Spells", "Priest Spells", "Alchemy", "Healing", "Magic Shop: Junk", "Magic Shop: Lousy", "Magic Shop: So-so", "Magic Shop: Good", "Magic Shop: Great"};
break;
case STRT_COST_ADJ:
strings = {"Extremely Cheap", "Very Reasonable", "Pretty Average", "Somewhat Pricey", "Expensive", "Exorbitant", "Utterly Ridiculous"};
@@ -612,11 +611,11 @@ static bool edit_spec_enc_value(cDialog& me, std::string item_hit, node_stack_t&
}
if(btn == '#') {
// TODO: Enumify the shop types
switch(me["x1b"].getTextAsNum()) {
case 0: btn = 'i'; break;
case 1: btn = 'A'; break;
case 2: btn = 'P'; break;
case 3: btn = 'a'; break;
switch(eShopType(me["x1b"].getTextAsNum())) {
case eShopType::ITEMS: btn = 'i'; break;
case eShopType::MAGE: btn = 'A'; break;
case eShopType::PRIEST: btn = 'P'; break;
case eShopType::ALCHEMY: btn = 'a'; break;
}
}
short val = me[field].getTextAsNum(), mode = (btn == 'S' || btn == '$') ? 0 : edit_stack.top().mode, store;

View File

@@ -1002,7 +1002,7 @@ static void frame_shape(sf::RenderTarget& target, sf::Shape& shape, int x, int y
shape.setOutlineColor(colour);
shape.setFillColor(sf::Color::Transparent);
// TODO: Determine the correct outline value; should be one pixel, not sure if it should be negative
shape.setOutlineThickness(1.0);
shape.setOutlineThickness(-1.0);
target.draw(shape);
}