Add new shop type and enhance existing ones a little

- Shops can now sell skill upgrades without skill point costs (currently available only through special node, not through dialogue)
- Spell shops now show level and spell point cost
- Alchemy shops now show ingredients
- Make use of the constants defined for indexing the shop rects
- Support for arbitrary quantities of items in shops, rather than simply infinite for normal shops and one for magic shops (there's no hook for this yet, though, so it can't be used)
This commit is contained in:
2015-01-23 22:02:36 -05:00
parent fd41f2fb20
commit d77baefcb5
10 changed files with 149 additions and 85 deletions

View File

@@ -123,6 +123,7 @@
913D05BD0FA1EA0A00184C18 /* pc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 913D05BB0FA1EA0A00184C18 /* pc.cpp */; };
913D05BE0FA1EA0A00184C18 /* pc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 913D05BB0FA1EA0A00184C18 /* pc.cpp */; };
913D6C050FC57A8E00E12527 /* boeresources.icns in Resources */ = {isa = PBXBuildFile; fileRef = 913D6C040FC57A8E00E12527 /* boeresources.icns */; };
914698F81A73434400F20F5E /* shop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91FDB5791A4E774E00DE5983 /* shop.cpp */; };
914701A718F62ABF008A6DC9 /* dungeon.ttf in Copy Fonts */ = {isa = PBXBuildFile; fileRef = 914701A418F629D4008A6DC9 /* dungeon.ttf */; };
914701A818F62AC0008A6DC9 /* maidenword.ttf in Copy Fonts */ = {isa = PBXBuildFile; fileRef = 914701A518F629D4008A6DC9 /* maidenword.ttf */; };
914B2AA318E7E507007B6799 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AA118E7E500007B6799 /* Cocoa.framework */; };
@@ -1545,6 +1546,7 @@
915E090C1A317E2E008BDF00 /* map_parse.cpp in Sources */,
9179A4661A48683100FEF872 /* stack.cpp in Sources */,
91222FC11A72366D008413A5 /* spell.cpp in Sources */,
914698F81A73434400F20F5E /* shop.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -119,8 +119,6 @@ cCreature save_monster_type;
short wand_loc_count = 0;
short monst_place_count = 0; // 1 - standard place 2 - place last
// 0 - whole area, 1 - active area 2 - graphic 3 - item name
// 4 - item cost 5 - item extra str 6 - item help button
rectangle shopping_rects[8][7];
std::queue<pending_special_type> special_queue;
bool end_scenario = false;
@@ -138,7 +136,8 @@ void init_screen_locs() {
shopping_rects[0][SHOPRECT_ITEM_NAME].top += 4;
shopping_rects[0][SHOPRECT_ITEM_NAME].left += 28;
shopping_rects[0][SHOPRECT_ITEM_COST].top += 20;
shopping_rects[0][SHOPRECT_ITEM_COST].left += 154;
// TODO: Might need to put this back to what it was (I was trying to make more room for alchemy info)
shopping_rects[0][SHOPRECT_ITEM_COST].left += 170;//154;
shopping_rects[0][SHOPRECT_ITEM_EXTRA].top += 20;
shopping_rects[0][SHOPRECT_ITEM_EXTRA].left += 34;
shopping_rects[0][SHOPRECT_ITEM_HELP].top += 3;
@@ -1624,8 +1623,8 @@ bool handle_keystroke(sf::Event& event){
}
for(i = 0; i < 8; i++)
if(chr2 == shop_chars[i]) {
pass_point.x = shopping_rects[i][1].left + 9 + ul.x;
pass_point.y = shopping_rects[i][1].top + 9 + ul.y;
pass_point.x = shopping_rects[i][SHOPRECT_ACTIVE_AREA].left + 9 + ul.x;
pass_point.y = shopping_rects[i][SHOPRECT_ACTIVE_AREA].top + 9 + ul.y;
pass_event.mouseButton.x = pass_point.x;
pass_event.mouseButton.y = pass_point.y;
are_done = handle_action(pass_event);

View File

@@ -53,6 +53,7 @@ extern sf::RenderWindow mini_map;
extern bool game_run_before,skip_boom_delay;
extern cUniverse univ;
extern sf::Texture pc_gworld;
extern std::map<eSkill,short> skill_max;
extern cScenarioList scen_headers;
@@ -88,8 +89,6 @@ extern std::vector<word_rect_t> talk_words;
// n000 + i - magic store n item i
// talk_area_rect and talk_help_rect used for this too
eGameMode store_pre_shop_mode;
// 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];
// TODO: The duplication of rectangle here shouldn't be necessary...
rectangle bottom_help_rects[4] = {rectangle{356,6,368,250},rectangle{374,6,386,270},rectangle{386,6,398,250},rectangle{398,6,410,250}};
@@ -194,11 +193,11 @@ void handle_shop_event(location p) {
for(i = 0; i < 8; i++) {
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]);
if(p.in(shopping_rects[i][SHOPRECT_ACTIVE_AREA])) {
click_shop_rect(shopping_rects[i][SHOPRECT_ACTIVE_AREA]);
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]);
} else if(p.in(shopping_rects[i][SHOPRECT_ITEM_HELP]) && active_shop.getType() != eShopType::HEALING){
click_shop_rect(shopping_rects[i][SHOPRECT_ITEM_HELP]);
handle_info_request(active_shop.getItem(store_what_picked));
}
}
@@ -208,6 +207,7 @@ void handle_sale(cShopItem item, int i) {
cItem base_item = item.item;
short cost = item.cost;
rectangle dummy_rect = {0,0,0,0};
size_t size_before = active_shop.size();
switch(item.type) {
case eShopItemType::ITEM:
@@ -216,11 +216,10 @@ void handle_sale(cShopItem item, int i) {
play_sound(-38);
take_gold(cost,true);
univ.party[current_pc].give_item(base_item,true);
if(active_shop.getType() != eShopType::ITEMS) {
// Magic shops have limited stock
active_shop.clearItem(i);
// Magic shops have limited stock
active_shop.takeOne(i);
if(active_shop.size() != size_before)
shop_sbar->setMaximum(shop_sbar->getMaximum() - 1);
}
break;
case eBuyStatus::NO_SPACE: ASB("Can't carry any more items."); break;
case eBuyStatus::NEED_GOLD: ASB("Not enough cash."); break;
@@ -325,6 +324,27 @@ void handle_sale(cShopItem item, int i) {
give_help(41,0);
}
break;
case eShopItemType::SKILL:
if(base_item.item_level < 0 || base_item.item_level > 18) {
beep();
giveError("Error: The scenario tried to sell you an invalid skill!");
break;
}
eSkill skill = eSkill(base_item.item_level);
if(univ.party[current_pc].skills[skill] >= skill_max[skill])
ASB("You're already an expert in this skill.");
else if(!take_gold(cost, false))
ASB("Not enough gold.");
else {
// TODO: No idea what's a good sound here.
play_sound(62);
ASB("You learn a little...");
active_shop.takeOne(i);
if(active_shop.size() != size_before)
shop_sbar->setMaximum(shop_sbar->getMaximum() - 1);
univ.party[current_pc].skills[skill]++;
}
break;
}
if(overall_mode != MODE_SHOPPING) {
@@ -356,6 +376,9 @@ void handle_info_request(cShopItem item) {
case eShopItemType::PRIEST_SPELL:
display_spells(eSkill::PRIEST_SPELLS,base_item.item_level - 900 - 30,0);
break;
case eShopItemType::SKILL:
display_skills(eSkill(base_item.item_level), nullptr);
break;
}
}
@@ -366,7 +389,7 @@ void set_up_shop_array(eShopType store_shop_type, short store_shop_min, short st
switch(store_shop_type) {
case eShopType::ITEMS:
for(int i = store_shop_min; i <= store_shop_max; i++)
active_shop.addItem(get_stored_item(i));
active_shop.addItem(get_stored_item(i), cShop::INFINITE);
break;
case eShopType::HEALING:
if(univ.party[current_pc].cur_health < univ.party[current_pc].max_health)
@@ -396,19 +419,19 @@ void set_up_shop_array(eShopType store_shop_type, short store_shop_min, short st
active_shop.addSpecial(eShopItemType::FOOD, i);
break;
case eShopType::MAGIC_JUNK:
active_shop.addItems(univ.party.magic_store_items[0].begin(), univ.party.magic_store_items[0].end());
active_shop.addItems(univ.party.magic_store_items[0].begin(), univ.party.magic_store_items[0].end(), 1);
break;
case eShopType::MAGIC_LOUSY:
active_shop.addItems(univ.party.magic_store_items[1].begin(), univ.party.magic_store_items[1].end());
active_shop.addItems(univ.party.magic_store_items[1].begin(), univ.party.magic_store_items[1].end(), 1);
break;
case eShopType::MAGIC_SO_SO:
active_shop.addItems(univ.party.magic_store_items[2].begin(), univ.party.magic_store_items[2].end());
active_shop.addItems(univ.party.magic_store_items[2].begin(), univ.party.magic_store_items[2].end(), 1);
break;
case eShopType::MAGIC_GOOD:
active_shop.addItems(univ.party.magic_store_items[3].begin(), univ.party.magic_store_items[3].end());
active_shop.addItems(univ.party.magic_store_items[3].begin(), univ.party.magic_store_items[3].end(), 1);
break;
case eShopType::MAGIC_GREAT:
active_shop.addItems(univ.party.magic_store_items[4].begin(), univ.party.magic_store_items[4].end());
active_shop.addItems(univ.party.magic_store_items[4].begin(), univ.party.magic_store_items[4].end(), 1);
break;
case eShopType::MAGE:
for(int i = store_shop_min; i <= store_shop_max && i < 62; i++)
@@ -422,6 +445,10 @@ void set_up_shop_array(eShopType store_shop_type, short store_shop_min, short st
for(int i = store_shop_min; i <= store_shop_max && i < 20; i++)
active_shop.addSpecial(eShopItemType::ALCHEMY, i);
break;
case eShopType::SKILLS:
for(int i = max(0,store_shop_min); i <= min(18,store_shop_max); i++)
active_shop.addSpecial(eShopItemType::SKILL, i);
break;
}
shop_sbar->setMaximum(active_shop.size() - 8);
}

View File

@@ -21,6 +21,7 @@
#include <memory>
#include "location.h"
#include "shop.hpp"
#include "spell.hpp"
short monsters_faces[190] = {
0,1,2,3,4,5,6,7,8,9,
@@ -67,6 +68,9 @@ extern short store_talk_face_pic;
extern cUniverse univ;
extern cCustomGraphics spec_scen_g;
extern bool fog_lifted;
extern const short alch_difficulty[20];
extern const eItemAbil alch_ingred1[20];
extern const eItemAbil alch_ingred2[20];
// Talk vars
extern eGameMode store_pre_talk_mode;
@@ -765,12 +769,13 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) {
for(i = 0; i < 8; i++) {
current_pos = i + shop_sbar->getPosition();
cShopItem item = active_shop.getItem(i);
eSpell spell; eSkill skill;
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];
rectangle from_rect, to_rect = shopping_rects[i][SHOPRECT_GRAPHIC];
sf::Texture* from_gw;
switch(item.type) {
case eShopItemType::ITEM:
@@ -778,13 +783,21 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) {
cur_info_str = get_item_interesting_string(base_item);
break;
case eShopItemType::ALCHEMY:
cur_info_str = "";
cur_info_str = get_str("item-abilities", int(alch_ingred1[base_item.item_level]) + 1);
if(alch_ingred2[base_item.item_level] != eItemAbil::NONE) {
cur_info_str += " and " + get_str("item-abilities", int(alch_ingred2[base_item.item_level]) + 1);
}
break;
case eShopItemType::MAGE_SPELL:
cur_info_str = "";
spell = cSpell::fromNum(eSkill::MAGE_SPELLS, base_item.item_level);
cur_info_str = "Level: " + std::to_string((*spell).level) + " SP: " + std::to_string((*spell).cost);
break;
case eShopItemType::PRIEST_SPELL:
cur_info_str = "";
spell = cSpell::fromNum(eSkill::PRIEST_SPELLS, base_item.item_level);
cur_info_str = "Level: " + std::to_string((*spell).level) + " SP: " + std::to_string((*spell).cost);
break;
case eShopItemType::SKILL:
cur_info_str = "Increase skill by 1";
break;
default: // Healing
cur_info_str = "";
@@ -793,18 +806,16 @@ void draw_shop_graphics(bool pressed,rectangle clip_area_rect) {
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
// 4 - item cost 5 - item extra str 6 - item help button
// Now draw item
style.pointSize = 12;
style.lineHeight = 12;
win_draw_string(talk_gworld,shopping_rects[i][3],cur_name,eTextMode::WRAP,style);
win_draw_string(talk_gworld,shopping_rects[i][SHOPRECT_ITEM_NAME],cur_name,eTextMode::WRAP,style);
cur_name = "Cost: " + std::to_string(cur_cost);
win_draw_string(talk_gworld,shopping_rects[i][4],cur_name,eTextMode::WRAP,style);
win_draw_string(talk_gworld,shopping_rects[i][SHOPRECT_ITEM_COST],cur_name,eTextMode::WRAP,style);
style.pointSize = 10;
win_draw_string(talk_gworld,shopping_rects[i][5],cur_info_str,eTextMode::WRAP,style);
win_draw_string(talk_gworld,shopping_rects[i][SHOPRECT_ITEM_EXTRA],cur_info_str,eTextMode::WRAP,style);
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);
rect_draw_some_item(invenbtn_gworld,item_info_from,talk_gworld,shopping_rects[i][SHOPRECT_ITEM_HELP],pressed ? sf::BlendNone : sf::BlendAlpha);
}

View File

@@ -2310,21 +2310,11 @@ void start_town_targeting(eSpell s_num,short who_c,bool freebie,eSpellPat pat) {
}
}
extern short alch_difficulty[20];
extern const short alch_difficulty[20];
extern const eItemAbil alch_ingred1[20];
extern const eItemAbil alch_ingred2[20];
void do_alchemy() {
static const eItemAbil ingred1_needed[20] = {
eItemAbil::HOLLY,eItemAbil::COMFREY,eItemAbil::HOLLY,eItemAbil::COMFREY,eItemAbil::WORMGRASS,
eItemAbil::NETTLE,eItemAbil::NETTLE,eItemAbil::WORMGRASS,eItemAbil::GRAYMOLD,eItemAbil::WORMGRASS,
eItemAbil::GRAYMOLD,eItemAbil::ASPTONGUE,eItemAbil::GRAYMOLD,eItemAbil::MANDRAKE,eItemAbil::EMBERF,
eItemAbil::MANDRAKE,eItemAbil::MANDRAKE,eItemAbil::NETTLE,eItemAbil::GRAYMOLD,eItemAbil::MANDRAKE,
};
static const eItemAbil ingred2_needed[20] = {
eItemAbil::NONE,eItemAbil::NONE,eItemAbil::NONE,eItemAbil::WORMGRASS,eItemAbil::NONE,
eItemAbil::NONE,eItemAbil::NONE,eItemAbil::NETTLE,eItemAbil::NONE,eItemAbil::ASPTONGUE,
eItemAbil::HOLLY,eItemAbil::NONE,eItemAbil::COMFREY,eItemAbil::NONE,eItemAbil::NONE,
eItemAbil::ASPTONGUE,eItemAbil::EMBERF,eItemAbil::EMBERF,eItemAbil::ASPTONGUE,eItemAbil::EMBERF,
};
static const short fail_chance[20] = {
50,40,30,20,10,
8,6,4,2,0,
@@ -2347,19 +2337,19 @@ void do_alchemy() {
return;
}
if((which_item = univ.party[pc_num].has_abil(ingred1_needed[which_p])) == 24) {
if((which_item = univ.party[pc_num].has_abil(alch_ingred1[which_p])) == 24) {
add_string_to_buf("Alchemy: Don't have ingredients.");
return;
}
if(ingred2_needed[which_p] != eItemAbil::NONE) {
if(univ.party[pc_num].has_abil(ingred2_needed[which_p]) == 24) {
if(alch_ingred2[which_p] != eItemAbil::NONE) {
if(univ.party[pc_num].has_abil(alch_ingred2[which_p]) == 24) {
add_string_to_buf("Alchemy: Don't have ingredients.");
return;
}
univ.party[pc_num].remove_charge(which_item);
// We call this twice because remove_charge might move the item and change its index
which_item2 = univ.party[pc_num].has_abil(ingred2_needed[which_p]);
which_item2 = univ.party[pc_num].has_abil(alch_ingred2[which_p]);
univ.party[pc_num].remove_charge(which_item2);
} else univ.party[pc_num].remove_charge(which_item);

View File

@@ -11,6 +11,34 @@
#include "mathutil.hpp"
#include "graphtool.hpp" // for get_str
std::map<eSkill,short> skill_cost = {
{eSkill::STRENGTH,3}, {eSkill::DEXTERITY,3}, {eSkill::INTELLIGENCE,3},
{eSkill::EDGED_WEAPONS,2}, {eSkill::BASHING_WEAPONS,2}, {eSkill::POLE_WEAPONS,2},
{eSkill::THROWN_MISSILES,1}, {eSkill::ARCHERY,2}, {eSkill::DEFENSE,2},
{eSkill::MAGE_SPELLS,6}, {eSkill::PRIEST_SPELLS,5}, {eSkill::MAGE_LORE,1},
{eSkill::ALCHEMY,2}, {eSkill::ITEM_LORE,4}, {eSkill::DISARM_TRAPS,2},
{eSkill::LOCKPICKING,1}, {eSkill::ASSASSINATION,4}, {eSkill::POISON,2},
{eSkill::LUCK,5},
};
std::map<eSkill,short> skill_max = {
{eSkill::STRENGTH,20}, {eSkill::DEXTERITY,20}, {eSkill::INTELLIGENCE,20},
{eSkill::EDGED_WEAPONS,20}, {eSkill::BASHING_WEAPONS,20}, {eSkill::POLE_WEAPONS,20},
{eSkill::THROWN_MISSILES,20}, {eSkill::ARCHERY,20}, {eSkill::DEFENSE,20},
{eSkill::MAGE_SPELLS,7}, {eSkill::PRIEST_SPELLS,7}, {eSkill::MAGE_LORE,20},
{eSkill::ALCHEMY,20}, {eSkill::ITEM_LORE,10}, {eSkill::DISARM_TRAPS,20},
{eSkill::LOCKPICKING,20}, {eSkill::ASSASSINATION,20}, {eSkill::POISON,20},
{eSkill::LUCK,20},
};
std::map<eSkill,short> skill_g_cost = {
{eSkill::STRENGTH,50}, {eSkill::DEXTERITY,503}, {eSkill::INTELLIGENCE,50},
{eSkill::EDGED_WEAPONS,40}, {eSkill::BASHING_WEAPONS,40}, {eSkill::POLE_WEAPONS,40},
{eSkill::THROWN_MISSILES,30}, {eSkill::ARCHERY,50}, {eSkill::DEFENSE,40},
{eSkill::MAGE_SPELLS,250}, {eSkill::PRIEST_SPELLS,250}, {eSkill::MAGE_LORE,25},
{eSkill::ALCHEMY,100}, {eSkill::ITEM_LORE,200}, {eSkill::DISARM_TRAPS,30},
{eSkill::LOCKPICKING,20}, {eSkill::ASSASSINATION,100}, {eSkill::POISON,80},
{eSkill::LUCK,0},
};
static long cost_mult[7] = {5,7,10,13,16,20,25};
cShop::cShop() {}
@@ -31,7 +59,7 @@ size_t cShop::size() {
});
}
void cShop::addItem(cItem item) {
void cShop::addItem(cItem item, size_t quantity) {
size_t i = firstEmpty();
if(i >= items.size()) return;
if(item.variety == eItemType::NO_ITEM) return;
@@ -43,6 +71,7 @@ void cShop::addItem(cItem item) {
items[i].cost *= item.charges;
items[i].cost *= cost_mult[cost_adj];
items[i].cost /= 10;
items[i].quantity = quantity;
}
static cItem store_mage_spells(short which_s) {
@@ -122,15 +151,21 @@ void cShop::addSpecial(eShopItemType type, int n) {
items[i].item = store_priest_spells(n);
else if(type == eShopItemType::ALCHEMY)
items[i].item = store_alchemy(n);
else {
else if(type == eShopItemType::SKILL) {
items[i].item.graphic_num = 108;
items[i].item.full_name = get_str("skills", n * 2 + 1);
} 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 if(type == eShopItemType::SKILL)
items[i].cost = skill_g_cost[eSkill(n)] * 1.5;
else items[i].cost = heal_costs[int(type) - 700];
items[i].cost *= cost_mult[cost_adj];
items[i].cost /= 10;
items[i].quantity = 0;
}
cShopItem cShop::getItem(size_t i) const {
@@ -149,6 +184,13 @@ std::string cShop::getName() const {
return name;
}
void cShop::takeOne(size_t i) {
if(items[i].quantity == 1)
clearItem(i);
else if(items[i].quantity > 0)
items[i].quantity--;
}
void cShop::clearItem(size_t i) {
std::copy(items.begin() + i + 1, items.end(), items.begin() + i);
items.back().type = eShopItemType::EMPTY;

View File

@@ -29,11 +29,13 @@ enum class eShopItemType {
PRIEST_SPELL = 900,
ALCHEMY = 500,
FOOD = 600,
SKILL = 1000,
};
struct cShopItem {
eShopItemType type = eShopItemType::EMPTY;
int cost;
size_t quantity;
cItem item;
};
@@ -44,18 +46,20 @@ class cShop {
eShopType type;
size_t firstEmpty();
public:
static const size_t INFINITE = 0;
cShop();
cShop(eShopType type, int adj, std::string name);
void addItem(cItem item);
void addItem(cItem item, size_t quantity);
void addSpecial(eShopItemType type, int n = 0);
template<typename Iter> void addItems(Iter begin, Iter end) {
while(begin != end) addItem(*begin++);
template<typename Iter> void addItems(Iter begin, Iter end, size_t quantity) {
while(begin != end) addItem(*begin++, quantity);
}
size_t size();
cShopItem getItem(size_t i) const;
eShopType getType() const;
int getCostAdjust() const;
std::string getName() const;
void takeOne(size_t i);
void clearItem(size_t i);
void clear();
};

View File

@@ -1002,6 +1002,7 @@ enum class eShopType {
MAGIC_GOOD = 8,
MAGIC_GREAT = 9,
FOOD = 10,
SKILLS = 11,
};
enum class eAlchemy {

View File

@@ -41,34 +41,10 @@ extern short which_pc_displayed;
cPlayer *store_pc;
sf::Texture button_num_gworld;
std::map<eSkill,short> skill_cost = {
{eSkill::STRENGTH,3}, {eSkill::DEXTERITY,3}, {eSkill::INTELLIGENCE,3},
{eSkill::EDGED_WEAPONS,2}, {eSkill::BASHING_WEAPONS,2}, {eSkill::POLE_WEAPONS,2},
{eSkill::THROWN_MISSILES,1}, {eSkill::ARCHERY,2}, {eSkill::DEFENSE,2},
{eSkill::MAGE_SPELLS,6}, {eSkill::PRIEST_SPELLS,5}, {eSkill::MAGE_LORE,1},
{eSkill::ALCHEMY,2}, {eSkill::ITEM_LORE,4}, {eSkill::DISARM_TRAPS,2},
{eSkill::LOCKPICKING,1}, {eSkill::ASSASSINATION,4}, {eSkill::POISON,2},
{eSkill::LUCK,5},
};
std::map<eSkill,short> skill_max = {
{eSkill::STRENGTH,20}, {eSkill::DEXTERITY,20}, {eSkill::INTELLIGENCE,20},
{eSkill::EDGED_WEAPONS,20}, {eSkill::BASHING_WEAPONS,20}, {eSkill::POLE_WEAPONS,20},
{eSkill::THROWN_MISSILES,20}, {eSkill::ARCHERY,20}, {eSkill::DEFENSE,20},
{eSkill::MAGE_SPELLS,7}, {eSkill::PRIEST_SPELLS,7}, {eSkill::MAGE_LORE,20},
{eSkill::ALCHEMY,20}, {eSkill::ITEM_LORE,10}, {eSkill::DISARM_TRAPS,20},
{eSkill::LOCKPICKING,20}, {eSkill::ASSASSINATION,20}, {eSkill::POISON,20},
{eSkill::LUCK,20},
};
std::map<eSkill,short> skill_g_cost = {
{eSkill::STRENGTH,50}, {eSkill::DEXTERITY,503}, {eSkill::INTELLIGENCE,50},
{eSkill::EDGED_WEAPONS,40}, {eSkill::BASHING_WEAPONS,40}, {eSkill::POLE_WEAPONS,40},
{eSkill::THROWN_MISSILES,30}, {eSkill::ARCHERY,50}, {eSkill::DEFENSE,40},
{eSkill::MAGE_SPELLS,250}, {eSkill::PRIEST_SPELLS,250}, {eSkill::MAGE_LORE,25},
{eSkill::ALCHEMY,100}, {eSkill::ITEM_LORE,200}, {eSkill::DISARM_TRAPS,30},
{eSkill::LOCKPICKING,20}, {eSkill::ASSASSINATION,100}, {eSkill::POISON,80},
{eSkill::LUCK,0},
};
// The index here is the skill's level, not the skill itself; thus 20 is the max index since no spell can go above 20.
extern std::map<eSkill,short> skill_cost;
extern std::map<eSkill,short> skill_max;
extern std::map<eSkill,short> skill_g_cost;
// The index here is the skill's level, not the skill itself; thus 20 is the max index since no skill can go above 20.
short skill_bonus[21] = {
-3,-3,-2,-1,0,0,1,1,1,2,
2,2,3,3,3,3,4,4,4,5,5};
@@ -238,12 +214,24 @@ void pick_race_abil(cPlayer *pc,short mode) {
pickAbil.run();
}
short alch_difficulty[20] = {
extern const short alch_difficulty[20] = {
1,1,1,3,3,
4,5,5,7,9,
9,10,12,12,9,
14,19,10,16,20
};
extern const eItemAbil alch_ingred1[20] = {
eItemAbil::HOLLY,eItemAbil::COMFREY,eItemAbil::HOLLY,eItemAbil::COMFREY,eItemAbil::WORMGRASS,
eItemAbil::NETTLE,eItemAbil::NETTLE,eItemAbil::WORMGRASS,eItemAbil::GRAYMOLD,eItemAbil::WORMGRASS,
eItemAbil::GRAYMOLD,eItemAbil::ASPTONGUE,eItemAbil::GRAYMOLD,eItemAbil::MANDRAKE,eItemAbil::EMBERF,
eItemAbil::MANDRAKE,eItemAbil::MANDRAKE,eItemAbil::NETTLE,eItemAbil::GRAYMOLD,eItemAbil::MANDRAKE,
};
extern const eItemAbil alch_ingred2[20] = {
eItemAbil::NONE,eItemAbil::NONE,eItemAbil::NONE,eItemAbil::WORMGRASS,eItemAbil::NONE,
eItemAbil::NONE,eItemAbil::NONE,eItemAbil::NETTLE,eItemAbil::NONE,eItemAbil::ASPTONGUE,
eItemAbil::HOLLY,eItemAbil::NONE,eItemAbil::COMFREY,eItemAbil::NONE,eItemAbil::NONE,
eItemAbil::ASPTONGUE,eItemAbil::EMBERF,eItemAbil::EMBERF,eItemAbil::ASPTONGUE,eItemAbil::EMBERF,
};
void display_alchemy(bool allowEdit) {
short i;

View File

@@ -252,7 +252,7 @@ short choose_text(eStrType list, unsigned short cur_choice, cDialog* parent, con
strings = *ResMgr::get<StringRsrc>("special-contexts");
break;
case STRT_SHOP:
strings = {"Items", "Mage Spells", "Priest Spells", "Alchemy", "Healing", "Magic Shop: Junk", "Magic Shop: Lousy", "Magic Shop: So-so", "Magic Shop: Good", "Magic Shop: Great"};
strings = {"Items", "Mage Spells", "Priest Spells", "Alchemy", "Healing", "Magic Shop: Junk", "Magic Shop: Lousy", "Magic Shop: So-so", "Magic Shop: Good", "Magic Shop: Great", "Skill Shop"};
break;
case STRT_COST_ADJ:
strings = {"Extremely Cheap", "Very Reasonable", "Pretty Average", "Somewhat Pricey", "Expensive", "Exorbitant", "Utterly Ridiculous"};
@@ -660,12 +660,12 @@ static bool edit_spec_enc_value(cDialog& me, std::string item_hit, node_stack_t&
else btn = 's';
}
if(btn == '#') {
// TODO: Enumify the shop types
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;
case eShopType::SKILLS: btn = 'k'; break;
}
}
short val = me[field].getTextAsNum(), mode = (btn == 'S' || btn == '$') ? 0 : edit_stack.top().mode, store;