ULTIMA1: Added sell portion of Weaponry dialog

This commit is contained in:
Paul Gilbert 2020-01-19 21:42:38 -08:00 committed by Paul Gilbert
parent b409b36454
commit a1bda3d5f1
10 changed files with 116 additions and 15 deletions

View File

@ -112,16 +112,25 @@ class Spell : public Itemized, public NamedItem {
template<class T>
class ItemArray : public Common::Array<T> {
public:
/**
* Returns the number of distinct types of items in the array, not counting
* the slot 0 "nothing" slot
*/
size_t itemsCount() const {
uint total = 0;
for (uint idx = 1; idx < this->size(); ++idx) {
if (!(*this)[idx]->empty())
++total;
}
return total;
}
/**
* Returns true if the character has no items
*/
bool hasNothing() const {
for (uint idx = 1; idx < this->size(); ++idx) {
if ((*this)[idx]->_quantity != 0)
return false;
}
return true;
return itemsCount() == 0;
}
};

View File

@ -142,6 +142,10 @@ uint Weapon::getMagicDamage() const {
return damage;
}
uint Weapon::getSellCost() const {
return ((_character->_intelligence + 40) * _type * _type) / 256 + 1;
}
/*-------------------------------------------------------------------*/
Armor::Armor(Ultima1Game *game, Character *c, ArmorType armorType) :

View File

@ -78,6 +78,11 @@ public:
* Gets the magic damage a given weapon does
*/
uint getMagicDamage() const;
/**
* Gets how much the weapon can sell for
*/
uint getSellCost() const;
};
/**

View File

@ -669,6 +669,7 @@ const char *const SRC_WEAPONRY_NAMES[8] = {
"The Razor's Edge", "Cold Steel Creations", "The Bloody Blade",
"The Duelo Shop", "Weaponry Supply", "Cold Steel Creations"
};
const char *const SRC_NO_WEAPONRY_TO_SELL = "Thou hast no weaponry to sell!";
const char *const SRC_WITH_KING = " with king";
const char *const SRC_HE_IS_NOT_HERE = "He is not here!";
@ -807,6 +808,8 @@ GameResources::GameResources(Shared::Resources *resManager) : LocalResourceFile(
GROCERY_PACKS_FOOD = SRC_GROCERY_PACKS_FOOD;
GROCERY_FIND_PACKS = SRC_GROCERY_FIND_PACKS;
Common::copy(&SRC_WEAPONRY_NAMES[0], &SRC_WEAPONRY_NAMES[8], WEAPONRY_NAMES);
NO_WEAPONRY_TO_SELL = SRC_NO_WEAPONRY_TO_SELL;
WITH_KING = SRC_WITH_KING;
HE_IS_NOT_HERE = SRC_HE_IS_NOT_HERE;
@ -936,6 +939,7 @@ void GameResources::synchronize() {
syncString(GROCERY_PACKS_FOOD);
syncString(GROCERY_FIND_PACKS);
syncStrings(WEAPONRY_NAMES, 8);
syncString(NO_WEAPONRY_TO_SELL);
syncString(WITH_KING);
syncString(HE_IS_NOT_HERE);

View File

@ -157,6 +157,7 @@ public:
const char *GROCERY_PACKS_FOOD;
const char *GROCERY_FIND_PACKS;
const char *WEAPONRY_NAMES[8];
const char *NO_WEAPONRY_TO_SELL;
const char *WITH_KING;
const char *HE_IS_NOT_HERE;

View File

@ -136,7 +136,7 @@ void BuySellDialog::setMode(BuySell mode) {
if (_mode == SOLD || _mode == CANT_AFFORD)
// Start dialog close countdown
_closeCounter = 1;
closeShortly();
}
void BuySellDialog::nothing() {

View File

@ -75,6 +75,11 @@ protected:
* Switches the dialog to displaying a can't afford message
*/
void cantAfford() { setMode(CANT_AFFORD); }
/**
* Sets the dialog to close after a brief pause
*/
void closeShortly() { _closeCounter = 1; }
public:
CLASSDEF;

View File

@ -52,7 +52,7 @@ void Grocery::setMode(BuySell mode) {
addInfoMsg(Common::String::format("%s%s", _game->_res->ACTION_NAMES[19], _game->_res->SELL), false, true);
_mode = SELL;
_closeCounter = 1;
closeShortly();
setDirty();
break;

View File

@ -21,9 +21,11 @@
*/
#include "ultima/ultima1/u1dialogs/weaponry.h"
#include "ultima/ultima1/core/party.h"
#include "ultima/ultima1/core/resources.h"
#include "ultima/ultima1/game.h"
#include "ultima/shared/engine/messages.h"
#include "ultima/shared/core/str.h"
namespace Ultima {
namespace Ultima1 {
@ -31,27 +33,37 @@ namespace U1Dialogs {
EMPTY_MESSAGE_MAP(Weaponry, BuySellDialog);
Weaponry::Weaponry(Ultima1Game *game, int weaponryNum) : BuySellDialog(game, game->_res->WEAPONRY_NAMES[weaponryNum]) {
Shared::Character &c = *game->_party;
_weaponsPresent.resize(c._weapons.size());
Weaponry::Weaponry(Ultima1Game *game, int weaponryNum) : BuySellDialog(game, game->_res->WEAPONRY_NAMES[weaponryNum]),
_weaponryNum(weaponryNum) {
}
void Weaponry::setMode(BuySell mode) {
Shared::Character &c = *_game->_party;
switch (mode) {
case BUY:
case BUY: {
addInfoMsg(Common::String::format("%s%s", _game->_res->ACTION_NAMES[19], _game->_res->BUY), false, true);
_mode = BUY;
setDirty();
// Set up a flag list of which weapons the store sells
_weaponsPresent.resize(c._weapons.size());
getInput(true, 3);
break;
}
case SELL:
addInfoMsg(Common::String::format("%s%s", _game->_res->ACTION_NAMES[19], _game->_res->SELL), false, true);
if (c._weapons.hasNothing()) {
addInfoMsg(_game->_res->NOTHING);
closeShortly();
} else {
getKeypress();
}
_mode = SELL;
_closeCounter = 1;
setDirty();
break;
@ -71,7 +83,7 @@ void Weaponry::draw() {
break;
case SELL:
// centerText(game->_res->Weaponry_SELL, 4);
drawSell();
break;
default:
@ -79,6 +91,60 @@ void Weaponry::draw() {
}
}
void Weaponry::drawSell() {
Shared::Gfx::VisualSurface s = getSurface();
const Shared::Character &c = *_game->_party;
int lineCount = c._weapons.itemsCount();
int titleLines = String(_title).split("\r\n").size();
Common::String line;
if (lineCount == 0) {
centerText(_game->_res->NO_WEAPONRY_TO_SELL, titleLines + 2);
} else {
for (uint idx = 1; idx < c._weapons.size(); ++idx) {
const Weapon &weapon = *static_cast<Weapon *>(c._weapons[idx]);
if (!weapon.empty()) {
line = Common::String::format("%c) %s", 'a' + idx, weapon._longName.c_str());
s.writeString(line, TextPoint(5, idx + titleLines + 1));
line = Common::String::format("-%4u", weapon.getSellCost());
s.writeString(line, TextPoint(22, idx + titleLines + 1));
}
}
}
}
bool Weaponry::CharacterInputMsg(CCharacterInputMsg &msg) {
Shared::Character &c = *_game->_party;
if (_mode == SELL && !c._weapons.hasNothing()) {
if (msg._keyState.keycode >= Common::KEYCODE_b &&
msg._keyState.keycode < (Common::KEYCODE_a + (int)c._weapons.size())) {
uint weaponNum = msg._keyState.keycode - Common::KEYCODE_a;
if (!c._weapons[weaponNum]->empty()) {
// Display the sold weapon in the info area
Weapon &weapon = *static_cast<Weapon *>(c._weapons[weaponNum]);
addInfoMsg(weapon._longName);
// Give coins for weapon and remove it from the inventory
c._coins += weapon.getSellCost();
if (weapon.decrQuantity() && (int)weaponNum == c._equippedWeapon)
c.removeWeapon();
// Close the dialog
_game->endOfTurn();
hide();
return true;
}
}
nothing();
return true;
} else {
return BuySellDialog::CharacterInputMsg(msg);
}
}
} // End of namespace U1Dialogs
} // End of namespace Ultima1
} // End of namespace Ultima

View File

@ -34,8 +34,15 @@ namespace U1Dialogs {
*/
class Weaponry : public BuySellDialog {
DECLARE_MESSAGE_MAP;
virtual bool CharacterInputMsg(CCharacterInputMsg &msg) override;
private:
uint _weaponryNum;
Common::Array<bool> _weaponsPresent;
private:
/**
* Draws the Sell dialog
*/
void drawSell();
protected:
/**
* Set the mode