ULTIMA1: Added armoury dialog

This commit is contained in:
Paul Gilbert 2020-01-19 21:51:23 -08:00 committed by Paul Gilbert
parent 65713e088a
commit b75958f2a1
23 changed files with 560 additions and 115 deletions

View File

@ -88,6 +88,7 @@ MODULE_OBJS += \
ultima1/spells/prayer.o \
ultima1/spells/spell.o \
ultima1/spells/steal.o \
ultima1/u1dialogs/armoury.o \
ultima1/u1dialogs/buy_sell_dialog.o \
ultima1/u1dialogs/combat.o \
ultima1/u1dialogs/dialog.o \
@ -120,7 +121,7 @@ MODULE_OBJS += \
ultima1/widgets/guard.o \
ultima1/widgets/king.o \
ultima1/widgets/merchant.o \
ultima1/widgets/merchant_armor.o \
ultima1/widgets/merchant_armour.o \
ultima1/widgets/merchant_grocer.o \
ultima1/widgets/merchant_magic.o \
ultima1/widgets/merchant_tavern.o \

View File

@ -52,11 +52,11 @@ void Character::synchronize(Common::Serializer &s) {
s.syncAsUint32LE(_food);
s.syncAsUint32LE(_coins);
s.syncAsSByte(_equippedWeapon);
s.syncAsSByte(_equippedArmor);
s.syncAsSByte(_equippedArmour);
s.syncAsSByte(_equippedSpell);
syncArray<Weapon>(_weapons, s);
syncArray<Armor>(_armor, s);
syncArray<Armour>(_armour, s);
syncArray<Spell>(_spells, s);
}

View File

@ -96,9 +96,9 @@ public:
};
/**
* Armor entry
* Armour entry
*/
class Armor : public Itemized {
class Armour : public Itemized {
public:
Common::String _name;
};
@ -155,17 +155,17 @@ public:
uint _food;
uint _coins;
int _equippedWeapon;
int _equippedArmor;
int _equippedArmour;
int _equippedSpell;
ItemArray<Weapon *> _weapons;
ItemArray<Armor *> _armor;
ItemArray<Armour *> _armour;
ItemArray<Spell *> _spells;
public:
/**
* Constructor
*/
Character() : _strength(0), _agility(0), _stamina(0), _charisma(0), _wisdom(0), _intelligence(0),
_hitPoints(0), _experience(0), _food(0), _coins(0), _equippedWeapon(0), _equippedArmor(0), _equippedSpell(0),
_hitPoints(0), _experience(0), _food(0), _coins(0), _equippedWeapon(0), _equippedArmour(0), _equippedSpell(0),
_race(0), _sex(0), _class(0) {}
/**
@ -181,7 +181,7 @@ public:
/**
* Returns true if armor is equipped
*/
bool isArmorEquipped() const { return _equippedArmor != 0; }
bool isArmourEquipped() const { return _equippedArmour != 0; }
/**
* Returns true if a spell is equipped
@ -196,7 +196,7 @@ public:
/**
* Return the equipped armor
*/
Armor *equippedArmor() const { return _armor[_equippedArmor]; }
Armour *equippedArmour() const { return _armour[_equippedArmour]; }
/**
* Return the equipped spell
@ -211,7 +211,7 @@ public:
/**
* Removes any eqipped armor
*/
void removeArmor() { _equippedArmor = 0; }
void removeArmour() { _equippedArmour = 0; }
/**
* Remove any equipped spell

View File

@ -55,12 +55,12 @@ Character::Character(Ultima1Game *game) : Shared::Character(), _game(game),
_weaponPhazor(game, this, WEAPON_PHAZOR),
_weaponBlaster(game, this, WEAPON_BLASTER),
_armorSkin(game, this, ARMOR_SKIN),
_armorLeatherArmor(game, this, ARMOR_LEATHER_ARMOR),
_armorChainMail(game, this, ARMOR_CHAIN_MAIL),
_armorPlateMail(game, this, ARMOR_PLATE_MAIL),
_armorVacuumSuit(game, this, ARMOR_VACUUM_SUIT),
_armorReflectSuit(game, this, ARMOR_REFLECT_SUIT) {
_armourSkin(game, this, ARMOR_SKIN),
_armourLeatherArmor(game, this, ARMOR_LEATHER_armour),
_armourChainMail(game, this, ARMOR_CHAIN_MAIL),
_armourPlateMail(game, this, ARMOR_PLATE_MAIL),
_armourVacuumSuit(game, this, ARMOR_VACUUM_SUIT),
_armourReflectSuit(game, this, ARMOR_REFLECT_SUIT) {
setup();
}
@ -84,12 +84,12 @@ void Character::setup() {
_weapons.push_back(&_weaponBlaster);
// Armor setup
_armor.push_back(&_armorSkin);
_armor.push_back(&_armorLeatherArmor);
_armor.push_back(&_armorChainMail);
_armor.push_back(&_armorPlateMail);
_armor.push_back(&_armorVacuumSuit);
_armor.push_back(&_armorReflectSuit);
_armour.push_back(&_armourSkin);
_armour.push_back(&_armourLeatherArmor);
_armour.push_back(&_armourChainMail);
_armour.push_back(&_armourPlateMail);
_armour.push_back(&_armourVacuumSuit);
_armour.push_back(&_armourReflectSuit);
// Spells setup
_spells.push_back(&_spellPrayer);
@ -152,7 +152,7 @@ uint Weapon::getSellCost() const {
/*-------------------------------------------------------------------*/
Armor::Armor(Ultima1Game *game, Character *c, ArmorType armorType) :
Armour::Armour(Ultima1Game *game, Character *c, ArmorType armorType) :
_game(game), _character(c), _type(armorType) {
_name = game->_res->ARMOR_NAMES[armorType];
@ -160,8 +160,13 @@ Armor::Armor(Ultima1Game *game, Character *c, ArmorType armorType) :
_quantity = 0xffff;
}
/*-------------------------------------------------------------------*/
uint Armour::getBuyCost() const {
return (200 - _character->_intelligence) / 4 * _type;
}
uint Armour::getSellCost() const {
return (_character->_charisma / 4) * _type;
}
} // End of namespace Ultima1
} // End of namespace Ultima

View File

@ -45,7 +45,7 @@ enum WeaponType {
};
enum ArmorType {
ARMOR_SKIN = 0, ARMOR_LEATHER_ARMOR = 1, ARMOR_CHAIN_MAIL = 2, ARMOR_PLATE_MAIL = 3,
ARMOR_SKIN = 0, ARMOR_LEATHER_armour = 1, ARMOR_CHAIN_MAIL = 2, ARMOR_PLATE_MAIL = 3,
ARMOR_VACUUM_SUIT = 4, ARMOR_REFLECT_SUIT = 5
};
@ -93,7 +93,7 @@ public:
/**
* Derived armor class
*/
class Armor : public Shared::Armor {
class Armour : public Shared::Armour {
private:
Ultima1Game *_game;
Character *_character;
@ -102,7 +102,7 @@ public:
/**
* Constructor
*/
Armor(Ultima1Game *game, Character *c, ArmorType armorType);
Armour(Ultima1Game *game, Character *c, ArmorType armorType);
/**
* Change the quantity by a given amount
@ -111,6 +111,16 @@ public:
if (_type != ARMOR_SKIN)
_quantity = (uint)CLIP((int)_quantity + delta, 0, 9999);
}
/**
* Gets how much the weapon can be bought for
*/
uint getBuyCost() const;
/**
* Gets how much the weapon can sell for
*/
uint getSellCost() const;
};
@ -138,12 +148,12 @@ private:
Weapon _weaponPhazor;
Weapon _weaponBlaster;
Armor _armorSkin;
Armor _armorLeatherArmor;
Armor _armorChainMail;
Armor _armorPlateMail;
Armor _armorVacuumSuit;
Armor _armorReflectSuit;
Armour _armourSkin;
Armour _armourLeatherArmor;
Armour _armourChainMail;
Armour _armourPlateMail;
Armour _armourVacuumSuit;
Armour _armourReflectSuit;
Spells::Blink _spellBlink;
Spells::Create _spellCreate;
@ -175,7 +185,7 @@ public:
/**
* Return the equipped armor
*/
Armor *equippedArmor() const { return static_cast<Armor *>(_armor[_equippedArmor]); }
Armour *equippedArmour() const { return static_cast<Armour *>(_armour[_equippedArmour]); }
/**
* Return the equipped spell

View File

@ -205,7 +205,7 @@ static const char *SRC_WEAPON_NAMES_ARTICLE[16] = {
static const byte SRC_WEAPON_DISTANCES[16] = { 1, 1, 1, 1, 0, 1, 1, 3, 0, 0, 0, 1, 3, 1, 3, 3 };
static const char *SRC_ARMOR_NAMES[6] = {
static const char *SRC_armour_NAMES[6] = {
"Skin", "Leather armor", "Chain mail", "Plate mail", "Vacuum suit", "Reflect suit"
};
@ -569,7 +569,7 @@ const char *const SRC_ENTERING = "ing...";
const char *const SRC_THE_CITY_OF = "The city of";
const char *const SRC_DUNGEON_LEVEL = " Level ";
const char *const SRC_ATTACKED_BY = "Attacked by %s!";
const char *const SRC_ARMOR_DESTROYED = "Armor destroyed!";
const char *const SRC_armour_DESTROYED = "Armor destroyed!";
const char *const SRC_GREMLIN_STOLE = "A gremlin stole some food!";
const char *const SRC_MENTAL_ATTACK = "Mental attack!";
const char *const SRC_MISSED = "Missed!";
@ -619,10 +619,10 @@ const char *const SRC_NONE_HERE = " - none here!";
const char *const SRC_SOLD = "Sold!";
const char *const SRC_CANT_AFFORD = "Thou canst not afford it!";
const char *const SRC_DONE = "Done!";
const char *const SRC_DROP_PENCE_WEAPON_ARMOR = " Pence,Weapon,Armor:";
const char *const SRC_DROP_PENCE_WEAPON_armour = " Pence,Weapon,Armor:";
const char *const SRC_DROP_PENCE = "Drop pence: ";
const char *const SRC_DROP_WEAPON = "Drop weapon: ";
const char *const SRC_DROP_ARMOR = "Drop armor: ";
const char *const SRC_DROP_armour = "Drop armor: ";
const char *const SRC_NOT_THAT_MUCH = "Thou hast not that much!";
const char *const SRC_OK = "Ok!";
const char *const SRC_SHAZAM = "Shazam!";
@ -639,8 +639,8 @@ const char *const SRC_PLAYER = "Player: %s";
const char *const SRC_PLAYER_DESC = "A Level %u %s %s %s";
const char *const SRC_PRESS_SPACE_TO_CONTINUE = "Press Space to continue: ";
const char *const SRC_MORE = " More ";
const char *const SRC_READY_WEAPON_ARMOR_SPELL = " Weapon,Armor,Spell:";
const char *const SRC_WEAPON_ARMOR_SPELL[3] = { "weapon", "armor", "spell" };
const char *const SRC_READY_WEAPON_armour_SPELL = " Weapon,Armor,Spell:";
const char *const SRC_WEAPON_armour_SPELL[3] = { "weapon", "armor", "spell" };
const char *const SRC_TRANSPORT_WEAPONS[2] = { "cannons", "lasers" };
const char *const SRC_NO_EFFECT = "Hmmmm... no effect!";
const char *const SRC_USED_UP_SPELL = "You've used up that spell!";
@ -671,6 +671,12 @@ const char *const SRC_WEAPONRY_NAMES[8] = {
"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_ARMOURY_NAMES[8] = {
"The Armour Shop of\nLord Eldric D'Charbonneux", "Max's Armoury", "The Iron Fist",
"The Hammer -n- Anvil", nullptr, "Defense Specialties Unlimited", nullptr,
"Custom Armor Works"
};
const char *const SRC_NO_ARMOUR_TO_SELL = "Thou hast no armour to sell!";
const char *const SRC_WITH_KING = " with king";
const char *const SRC_HE_IS_NOT_HERE = "He is not here!";
@ -709,7 +715,7 @@ GameResources::GameResources(Shared::Resources *resManager) : LocalResourceFile(
Common::copy(&SRC_WEAPON_NAMES_LOWERCASE[0], &SRC_WEAPON_NAMES_LOWERCASE[16], WEAPON_NAMES_LOWERCASE);
Common::copy(&SRC_WEAPON_NAMES_ARTICLE[0], &SRC_WEAPON_NAMES_ARTICLE[16], WEAPON_NAMES_ARTICLE);
Common::copy(SRC_WEAPON_DISTANCES, SRC_WEAPON_DISTANCES + 16, WEAPON_DISTANCES);
Common::copy(&SRC_ARMOR_NAMES[0], &SRC_ARMOR_NAMES[16], ARMOR_NAMES);
Common::copy(&SRC_armour_NAMES[0], &SRC_armour_NAMES[16], ARMOR_NAMES);
Common::copy(&SRC_SPELL_NAMES[0], &SRC_SPELL_NAMES[16], SPELL_NAMES);
Common::copy(SRC_SPELL_PHRASES, SRC_SPELL_PHRASES + 14, SPELL_PHRASES);
Common::copy(&SRC_GEM_NAMES[0], &SRC_GEM_NAMES[4], GEM_NAMES);
@ -723,7 +729,7 @@ GameResources::GameResources(Shared::Resources *resManager) : LocalResourceFile(
THE_CITY_OF = SRC_THE_CITY_OF;
DUNGEON_LEVEL = SRC_DUNGEON_LEVEL;
ATTACKED_BY = SRC_ATTACKED_BY;
ARMOR_DESTROYED = SRC_ARMOR_DESTROYED;
ARMOR_DESTROYED = SRC_armour_DESTROYED;
GREMLIN_STOLE = SRC_GREMLIN_STOLE;
MENTAL_ATTACK = SRC_MENTAL_ATTACK;
MISSED = SRC_MISSED;
@ -768,10 +774,10 @@ GameResources::GameResources(Shared::Resources *resManager) : LocalResourceFile(
SOLD = SRC_SOLD;
CANT_AFFORD = SRC_CANT_AFFORD;
DONE = SRC_DONE;
DROP_PENCE_WEAPON_ARMOR = SRC_DROP_PENCE_WEAPON_ARMOR;
DROP_PENCE_WEAPON_armour = SRC_DROP_PENCE_WEAPON_armour;
DROP_PENCE = SRC_DROP_PENCE;
DROP_WEAPON = SRC_DROP_WEAPON;
DROP_ARMOR = SRC_DROP_ARMOR;
DROP_armour = SRC_DROP_armour;
NOT_THAT_MUCH = SRC_NOT_THAT_MUCH;
OK = SRC_OK;
SHAZAM = SRC_SHAZAM;
@ -788,8 +794,8 @@ GameResources::GameResources(Shared::Resources *resManager) : LocalResourceFile(
PLAYER_DESC = SRC_PLAYER_DESC;
PRESS_SPACE_TO_CONTINUE = SRC_PRESS_SPACE_TO_CONTINUE;
MORE = SRC_MORE;
READY_WEAPON_ARMOR_SPELL = SRC_READY_WEAPON_ARMOR_SPELL;
Common::copy(SRC_WEAPON_ARMOR_SPELL, SRC_WEAPON_ARMOR_SPELL + 3, WEAPON_ARMOR_SPELL);
READY_WEAPON_armour_SPELL = SRC_READY_WEAPON_armour_SPELL;
Common::copy(SRC_WEAPON_armour_SPELL, SRC_WEAPON_armour_SPELL + 3, WEAPON_armour_SPELL);
Common::copy(SRC_TRANSPORT_WEAPONS, SRC_TRANSPORT_WEAPONS + 2, TRANSPORT_WEAPONS);
NO_EFFECT = SRC_NO_EFFECT;
USED_UP_SPELL = SRC_USED_UP_SPELL;
@ -811,7 +817,8 @@ GameResources::GameResources(Shared::Resources *resManager) : LocalResourceFile(
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;
Common::copy(&SRC_ARMOURY_NAMES[0], &SRC_ARMOURY_NAMES[8], ARMOURY_NAMES);
NO_ARMOUR_TO_SELL = SRC_NO_ARMOUR_TO_SELL;
WITH_KING = SRC_WITH_KING;
HE_IS_NOT_HERE = SRC_HE_IS_NOT_HERE;
@ -900,10 +907,10 @@ void GameResources::synchronize() {
syncString(SOLD);
syncString(CANT_AFFORD);
syncString(DONE);
syncString(DROP_PENCE_WEAPON_ARMOR);
syncString(DROP_PENCE_WEAPON_armour);
syncString(DROP_PENCE);
syncString(DROP_WEAPON);
syncString(DROP_ARMOR);
syncString(DROP_armour);
syncString(NOT_THAT_MUCH);
syncString(OK);
syncString(SHAZAM);
@ -920,8 +927,8 @@ void GameResources::synchronize() {
syncString(PLAYER_DESC);
syncString(PRESS_SPACE_TO_CONTINUE);
syncString(MORE);
syncString(READY_WEAPON_ARMOR_SPELL);
syncStrings(WEAPON_ARMOR_SPELL, 3);
syncString(READY_WEAPON_armour_SPELL);
syncStrings(WEAPON_armour_SPELL, 3);
syncStrings(TRANSPORT_WEAPONS, 2);
syncString(NO_EFFECT);
syncString(USED_UP_SPELL);
@ -943,6 +950,8 @@ void GameResources::synchronize() {
syncString(GROCERY_FIND_PACKS);
syncStrings(WEAPONRY_NAMES, 8);
syncString(NO_WEAPONRY_TO_SELL);
syncStrings(ARMOURY_NAMES, 8);
syncString(NO_ARMOUR_TO_SELL);
syncString(WITH_KING);
syncString(HE_IS_NOT_HERE);

View File

@ -116,10 +116,10 @@ public:
const char *SOLD;
const char *CANT_AFFORD;
const char *DONE;
const char *DROP_PENCE_WEAPON_ARMOR;
const char *DROP_PENCE_WEAPON_armour;
const char *DROP_PENCE;
const char *DROP_WEAPON;
const char *DROP_ARMOR;
const char *DROP_armour;
const char *NOT_THAT_MUCH;
const char *OK;
const char *SHAZAM;
@ -136,8 +136,8 @@ public:
const char *PLAYER_DESC;
const char *PRESS_SPACE_TO_CONTINUE;
const char *MORE;
const char *READY_WEAPON_ARMOR_SPELL;
const char *WEAPON_ARMOR_SPELL[3];
const char *READY_WEAPON_armour_SPELL;
const char *WEAPON_armour_SPELL[3];
const char *TRANSPORT_WEAPONS[2];
const char *NO_EFFECT;
const char *USED_UP_SPELL;
@ -159,6 +159,8 @@ public:
const char *GROCERY_FIND_PACKS;
const char *WEAPONRY_NAMES[8];
const char *NO_WEAPONRY_TO_SELL;
const char *ARMOURY_NAMES[8];
const char *NO_ARMOUR_TO_SELL;
const char *WITH_KING;
const char *HE_IS_NOT_HERE;

View File

@ -35,7 +35,7 @@
#include "ultima/ultima1/widgets/dungeon_coffin.h"
#include "ultima/ultima1/widgets/guard.h"
#include "ultima/ultima1/widgets/king.h"
#include "ultima/ultima1/widgets/merchant_armor.h"
#include "ultima/ultima1/widgets/merchant_armour.h"
#include "ultima/ultima1/widgets/merchant_grocer.h"
#include "ultima/ultima1/widgets/merchant_magic.h"
#include "ultima/ultima1/widgets/merchant_tavern.h"
@ -139,7 +139,7 @@ Shared::Maps::MapWidget *Ultima1Map::createWidget(Shared::Maps::MapBase *map, co
REGISTER_WIDGET(DungeonCoffin);
REGISTER_WIDGET(Guard);
REGISTER_WIDGET(King);
REGISTER_WIDGET(MerchantArmor);
REGISTER_WIDGET(MerchantArmour);
REGISTER_WIDGET(MerchantGrocer);
REGISTER_WIDGET(MerchantMagic);
REGISTER_WIDGET(MerchantTavern);

View File

@ -31,7 +31,7 @@
#include "ultima/ultima1/game.h"
#include "ultima/ultima1/spells/spell.h"
#include "ultima/ultima1/widgets/dungeon_item.h"
#include "ultima/ultima1/widgets/merchant_armor.h"
#include "ultima/ultima1/widgets/merchant_armour.h"
#include "ultima/ultima1/widgets/merchant_grocer.h"
#include "ultima/ultima1/widgets/merchant_magic.h"
#include "ultima/ultima1/widgets/merchant_tavern.h"

View File

@ -32,7 +32,7 @@
#include "ultima/ultima1/widgets/king.h"
#include "ultima/ultima1/widgets/princess.h"
#include "ultima/ultima1/widgets/wench.h"
#include "ultima/ultima1/widgets/merchant_armor.h"
#include "ultima/ultima1/widgets/merchant_armour.h"
#include "ultima/ultima1/widgets/merchant_grocer.h"
#include "ultima/ultima1/widgets/merchant_magic.h"
#include "ultima/ultima1/widgets/merchant_tavern.h"
@ -84,7 +84,7 @@ void MapCityCastle::loadWidgets() {
switch (tile._tileId) {
case 55:
person = new Widgets::MerchantArmor(_game, this, lp[3]);
person = new Widgets::MerchantArmour(_game, this, lp[3]);
break;
case 57:
person = new Widgets::MerchantGrocer(_game, this, lp[3]);
@ -166,7 +166,7 @@ Widgets::Merchant *MapCityCastle::getStealMerchant() {
// Scan for the correct merchant depending on the tile player is on
switch (tile._tileId) {
case 55:
return dynamic_cast<Widgets::MerchantArmor *>(_widgets.findByClass(Widgets::MerchantArmor::type()));
return dynamic_cast<Widgets::MerchantArmour *>(_widgets.findByClass(Widgets::MerchantArmour::type()));
break;
case 57:
return dynamic_cast<Widgets::MerchantGrocer *>(_widgets.findByClass(Widgets::MerchantGrocer::type()));
@ -186,7 +186,7 @@ Widgets::Person *MapCityCastle::getTalkPerson() {
switch (tile._tileId) {
case 54:
case 55:
return dynamic_cast<Widgets::Person *>(_widgets.findByClass(Widgets::MerchantArmor::type()));
return dynamic_cast<Widgets::Person *>(_widgets.findByClass(Widgets::MerchantArmour::type()));
case 56:
case 57:

View File

@ -0,0 +1,188 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "ultima/ultima1/u1dialogs/armoury.h"
#include "ultima/ultima1/core/party.h"
#include "ultima/ultima1/core/resources.h"
#include "ultima/ultima1/maps/map.h"
#include "ultima/ultima1/game.h"
#include "ultima/shared/engine/messages.h"
#include "ultima/shared/core/str.h"
namespace Ultima {
namespace Ultima1 {
namespace U1Dialogs {
EMPTY_MESSAGE_MAP(Armoury, BuySellDialog);
Armoury::Armoury(Ultima1Game *game, int armouryNum) : BuySellDialog(game, game->_res->ARMOURY_NAMES[armouryNum]),
_armouryNum(armouryNum) {
Maps::Ultima1Map *map = static_cast<Maps::Ultima1Map *>(game->_map);
_startIndex = 1;
_endIndex = (map->_moveCounter > 3000) ? 5 : 3;
}
void Armoury::setMode(BuySell mode) {
Shared::Character &c = *_game->_party;
switch (mode) {
case BUY: {
addInfoMsg(Common::String::format("%s%s", _game->_res->ACTION_NAMES[19], _game->_res->BUY), false, true);
_mode = BUY;
setDirty();
getKeypress();
break;
}
case SELL:
addInfoMsg(Common::String::format("%s%s", _game->_res->ACTION_NAMES[19], _game->_res->SELL), false, true);
if (c._armour.hasNothing()) {
addInfoMsg(_game->_res->NOTHING);
closeShortly();
} else {
getKeypress();
}
_mode = SELL;
setDirty();
break;
default:
BuySellDialog::setMode(mode);
break;
}
}
void Armoury::draw() {
BuySellDialog::draw();
switch (_mode) {
case BUY:
drawBuy();
break;
case SELL:
drawSell();
break;
default:
break;
}
}
void Armoury::drawBuy() {
Shared::Gfx::VisualSurface s = getSurface();
const Shared::Character &c = *_game->_party;
int titleLines = String(_title).split("\r\n").size();
Common::String line;
for (uint idx = _startIndex, yp = titleLines + 2; idx <= _endIndex; ++idx, ++yp) {
const Armour &armour = *static_cast<Armour *>(c._armour[idx]);
line = Common::String::format("%c) %s", 'a' + idx, armour._name.c_str());
s.writeString(line, TextPoint(5, yp));
line = Common::String::format("-%4u", armour.getBuyCost());
s.writeString(line, TextPoint(22, yp));
}
}
void Armoury::drawSell() {
Shared::Gfx::VisualSurface s = getSurface();
const Shared::Character &c = *_game->_party;
int lineCount = c._armour.itemsCount();
int titleLines = String(_title).split("\r\n").size();
Common::String line;
if (lineCount == 0) {
centerText(_game->_res->NO_ARMOUR_TO_SELL, titleLines + 2);
} else {
for (uint idx = 1; idx < c._armour.size(); ++idx) {
const Armour &armour = *static_cast<Armour *>(c._armour[idx]);
if (!armour.empty()) {
line = Common::String::format("%c) %s", 'a' + idx, armour._name.c_str());
s.writeString(line, TextPoint(5, idx + titleLines + 1));
line = Common::String::format("-%4u", armour.getSellCost());
s.writeString(line, TextPoint(22, idx + titleLines + 1));
}
}
}
}
bool Armoury::CharacterInputMsg(CCharacterInputMsg &msg) {
Shared::Character &c = *_game->_party;
if (_mode == BUY) {
if (msg._keyState.keycode >= (int)(Common::KEYCODE_a + _startIndex) &&
msg._keyState.keycode <= (int)(Common::KEYCODE_a + _endIndex)) {
uint armourNum = msg._keyState.keycode - Common::KEYCODE_a;
Armour &armour = *static_cast<Armour *>(c._armour[armourNum]);
if (armour.getBuyCost() <= c._coins) {
// Display the sold armour in the info area
addInfoMsg(armour._name);
// Remove coins for armour and add it to the inventory
c._coins -= armour.getBuyCost();
armour.incrQuantity();
// Show sold and close the dialog
setMode(SOLD);
return true;
}
}
nothing();
return true;
} else if (_mode == SELL && !c._armour.hasNothing()) {
if (msg._keyState.keycode >= Common::KEYCODE_b &&
msg._keyState.keycode < (Common::KEYCODE_a + (int)c._armour.size())) {
uint armourNum = msg._keyState.keycode - Common::KEYCODE_a;
Armour &armour = *static_cast<Armour *>(c._armour[armourNum]);
if (!armour.empty()) {
// Display the sold armour in the info area
addInfoMsg(armour._name);
// Give coins for armour and remove it from the inventory
c._coins += armour.getSellCost();
if (armour.decrQuantity() && (int)armourNum == c._equippedArmour)
c.removeArmour();
// Close the dialog
setMode(DONE);
return true;
}
}
nothing();
return true;
} else {
return BuySellDialog::CharacterInputMsg(msg);
}
}
} // End of namespace U1Dialogs
} // End of namespace Ultima1
} // End of namespace Ultima

View File

@ -0,0 +1,74 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ULTIMA_ULTIMA1_U1DIALOGS_ARMOURY_H
#define ULTIMA_ULTIMA1_U1DIALOGS_ARMOURY_H
#include "ultima/ultima1/u1dialogs/buy_sell_dialog.h"
namespace Ultima {
namespace Ultima1 {
namespace U1Dialogs {
/**
* Implements the buy/sell dialog for the armory
*/
class Armoury : public BuySellDialog {
DECLARE_MESSAGE_MAP;
virtual bool CharacterInputMsg(CCharacterInputMsg &msg) override;
private:
uint _armouryNum;
uint _startIndex, _endIndex;
private:
/**
* Draws the Buy dialog content
*/
void drawBuy();
/**
* Draws the Sell dialog content
*/
void drawSell();
protected:
/**
* Set the mode
*/
virtual void setMode(BuySell mode) override;
public:
CLASSDEF;
/**
* Constructor
*/
Armoury(Ultima1Game *game, int armouryNum);
/**
* Draws the visual item on the screen
*/
virtual void draw();
};
} // End of namespace U1Dialogs
} // End of namespace Ultima1
} // End of namespace Ultima
#endif

View File

@ -40,7 +40,7 @@ Drop::Drop(Ultima1Game *game) : FullScreenDialog(game), _mode(SELECT) {
}
bool Drop::ShowMsg(CShowMsg &msg) {
addInfoMsg(_game->_res->DROP_PENCE_WEAPON_ARMOR, false);
addInfoMsg(_game->_res->DROP_PENCE_WEAPON_armour, false);
getKeypress();
return true;
}
@ -58,7 +58,7 @@ bool Drop::CharacterInputMsg(CCharacterInputMsg &msg) {
setMode(DROP_WEAPON);
break;
case Common::KEYCODE_a:
setMode(DROP_ARMOR);
setMode(DROP_armour);
break;
default:
nothing();
@ -82,15 +82,15 @@ bool Drop::CharacterInputMsg(CCharacterInputMsg &msg) {
}
break;
case DROP_ARMOR:
if (msg._keyState.keycode >= Common::KEYCODE_b && msg._keyState.keycode < (Common::KEYCODE_b + (int)c._armor.size())
&& c._armor[msg._keyState.keycode - Common::KEYCODE_a]->_quantity > 0) {
case DROP_armour:
if (msg._keyState.keycode >= Common::KEYCODE_b && msg._keyState.keycode < (Common::KEYCODE_b + (int)c._armour.size())
&& c._armour[msg._keyState.keycode - Common::KEYCODE_a]->_quantity > 0) {
// Drop the armor
int armorNum = msg._keyState.keycode - Common::KEYCODE_a;
if (c._armor[armorNum]->decrQuantity() && c._equippedArmor == armorNum)
c.removeArmor();
if (c._armour[armorNum]->decrQuantity() && c._equippedArmour == armorNum)
c.removeArmour();
addInfoMsg(Common::String::format("%s%s", _game->_res->DROP_ARMOR,
addInfoMsg(Common::String::format("%s%s", _game->_res->DROP_armour,
_game->_res->ARMOR_NAMES[armorNum]), true, true);
hide();
} else {
@ -153,11 +153,11 @@ void Drop::setMode(Mode mode) {
}
break;
case DROP_ARMOR:
if (c._armor.hasNothing()) {
case DROP_armour:
if (c._armour.hasNothing()) {
nothing();
} else {
addInfoMsg(_game->_res->DROP_ARMOR, false, true);
addInfoMsg(_game->_res->DROP_armour, false, true);
getKeypress();
}
break;
@ -174,7 +174,7 @@ void Drop::nothing() {
}
void Drop::none() {
const char *DROPS[4] = { nullptr, _game->_res->DROP_PENCE, _game->_res->DROP_WEAPON, _game->_res->DROP_ARMOR };
const char *DROPS[4] = { nullptr, _game->_res->DROP_PENCE, _game->_res->DROP_WEAPON, _game->_res->DROP_armour };
addInfoMsg(Common::String::format("%s%s", DROPS[_mode], _game->_res->NONE), true, true);
hide();
@ -187,7 +187,7 @@ void Drop::draw() {
case DROP_WEAPON:
drawDropWeapon();
break;
case DROP_ARMOR:
case DROP_armour:
drawDropArmor();
break;
default:
@ -225,15 +225,15 @@ void Drop::drawDropArmor() {
// Count the number of different types of armor
const Shared::Character &c = *_game->_party;
int numLines = 0;
for (uint idx = 1; idx < c._armor.size(); ++idx) {
if (c._armor[idx]->_quantity)
for (uint idx = 1; idx < c._armour.size(); ++idx) {
if (c._armour[idx]->_quantity)
++numLines;
}
// Draw lines for armor the player has
int yp = 10 - (numLines / 2);
for (uint idx = 1; idx < c._armor.size(); ++idx) {
if (c._armor[idx]->_quantity) {
for (uint idx = 1; idx < c._armour.size(); ++idx) {
if (c._armour[idx]->_quantity) {
Common::String text = Common::String::format("%c) %s", 'a' + idx,
_game->_res->ARMOR_NAMES[idx]);
s.writeString(text, TextPoint(13, yp++));

View File

@ -43,7 +43,7 @@ class Drop : public FullScreenDialog {
bool CharacterInputMsg(CCharacterInputMsg &msg);
bool TextInputMsg(CTextInputMsg &msg);
enum Mode { SELECT, DROP_PENCE, DROP_WEAPON, DROP_ARMOR };
enum Mode { SELECT, DROP_PENCE, DROP_WEAPON, DROP_armour };
private:
Mode _mode;
private:

View File

@ -40,7 +40,7 @@ Ready::Ready(Ultima1Game *game) : FullScreenDialog(game), _mode(SELECT) {
}
bool Ready::ShowMsg(CShowMsg &msg) {
addInfoMsg(_game->_res->READY_WEAPON_ARMOR_SPELL, false);
addInfoMsg(_game->_res->READY_WEAPON_armour_SPELL, false);
getKeypress();
return true;
}
@ -55,7 +55,7 @@ bool Ready::CharacterInputMsg(CCharacterInputMsg &msg) {
setMode(READY_WEAPON);
break;
case Common::KEYCODE_a:
setMode(READY_ARMOR);
setMode(READY_armour);
break;
case Common::KEYCODE_s:
setMode(READY_SPELL);
@ -75,20 +75,20 @@ bool Ready::CharacterInputMsg(CCharacterInputMsg &msg) {
}
addInfoMsg(Common::String::format("%s %s: %s", _game->_res->ACTION_NAMES[17],
_game->_res->WEAPON_ARMOR_SPELL[0], c.equippedWeapon()->_longName.c_str()),
_game->_res->WEAPON_armour_SPELL[0], c.equippedWeapon()->_longName.c_str()),
true, true);
hide();
break;
case READY_ARMOR:
if (msg._keyState.keycode >= Common::KEYCODE_a && msg._keyState.keycode < (Common::KEYCODE_a + (int)c._armor.size())) {
case READY_armour:
if (msg._keyState.keycode >= Common::KEYCODE_a && msg._keyState.keycode < (Common::KEYCODE_a + (int)c._armour.size())) {
int index = msg._keyState.keycode - Common::KEYCODE_a;
if (!c._armor[index]->empty())
c._equippedArmor = index;
if (!c._armour[index]->empty())
c._equippedArmour = index;
}
addInfoMsg(Common::String::format("%s %s: %s", _game->_res->ACTION_NAMES[17],
_game->_res->WEAPON_ARMOR_SPELL[1], c.equippedArmor()->_name.c_str()),
_game->_res->WEAPON_armour_SPELL[1], c.equippedArmour()->_name.c_str()),
true, true);
hide();
break;
@ -101,7 +101,7 @@ bool Ready::CharacterInputMsg(CCharacterInputMsg &msg) {
}
addInfoMsg(Common::String::format("%s %s: %s", _game->_res->ACTION_NAMES[17],
_game->_res->WEAPON_ARMOR_SPELL[2], c._spells[c._equippedSpell]->_name.c_str()),
_game->_res->WEAPON_armour_SPELL[2], c._spells[c._equippedSpell]->_name.c_str()),
true, true);
hide();
break;
@ -124,24 +124,24 @@ void Ready::setMode(Mode mode) {
nothing();
} else {
addInfoMsg(Common::String::format("%s %s: ", _game->_res->ACTION_NAMES[17],
_game->_res->WEAPON_ARMOR_SPELL[0]), false, true);
_game->_res->WEAPON_armour_SPELL[0]), false, true);
getKeypress();
}
break;
case READY_ARMOR:
if (c._armor.hasNothing()) {
case READY_armour:
if (c._armour.hasNothing()) {
nothing();
} else {
addInfoMsg(Common::String::format("%s %s: ", _game->_res->ACTION_NAMES[17],
_game->_res->WEAPON_ARMOR_SPELL[1]), false, true);
_game->_res->WEAPON_armour_SPELL[1]), false, true);
getKeypress();
}
break;
case READY_SPELL:
addInfoMsg(Common::String::format("%s %s: ", _game->_res->ACTION_NAMES[17],
_game->_res->WEAPON_ARMOR_SPELL[2]), false, true);
_game->_res->WEAPON_armour_SPELL[2]), false, true);
getKeypress();
break;
@ -167,7 +167,7 @@ void Ready::draw() {
case READY_WEAPON:
drawReadyWeapon();
break;
case READY_ARMOR:
case READY_armour:
drawReadyArmor();
break;
case READY_SPELL:
@ -207,17 +207,17 @@ void Ready::drawReadyArmor() {
// Count the number of different types of weapons
const Shared::Character &c = *_game->_party;
int numLines = 0;
for (uint idx = 0; idx < c._armor.size(); ++idx) {
if (!c._armor[idx]->empty())
for (uint idx = 0; idx < c._armour.size(); ++idx) {
if (!c._armour[idx]->empty())
++numLines;
}
// Draw lines for armor the player has
int yp = 10 - (numLines / 2);
for (uint idx = 0; idx < c._armor.size(); ++idx) {
if (!c._armor[idx]->empty()) {
Common::String text = Common::String::format("%c) %s", 'a' + idx, c._armor[idx]->_name.c_str());
s.writeString(text, TextPoint(15, yp++), (int)idx == c._equippedArmor ? _game->_highlightColor : _game->_textColor);
for (uint idx = 0; idx < c._armour.size(); ++idx) {
if (!c._armour[idx]->empty()) {
Common::String text = Common::String::format("%c) %s", 'a' + idx, c._armour[idx]->_name.c_str());
s.writeString(text, TextPoint(15, yp++), (int)idx == c._equippedArmour ? _game->_highlightColor : _game->_textColor);
}
}
}

View File

@ -40,7 +40,7 @@ class Ready : public FullScreenDialog {
bool ShowMsg(CShowMsg &msg);
bool CharacterInputMsg(CCharacterInputMsg &msg);
enum Mode { SELECT, READY_WEAPON, READY_ARMOR, READY_SPELL };
enum Mode { SELECT, READY_WEAPON, READY_armour, READY_SPELL };
private:
Mode _mode;
private:

View File

@ -96,10 +96,10 @@ void Stats::load() {
_stats.push_back(StatEntry(_game->_res->STAT_NAMES[9], enemyVessels));
// Armor, weapons, & spells
for (uint idx = 1; idx < c._armor.size(); ++idx) {
if (!c._armor[idx]->empty())
_stats.push_back(StatEntry(formatStat(c._armor[idx]->_name.c_str(), c._armor[idx]->_quantity),
(int)idx == c._equippedArmor ? _game->_highlightColor : _game->_textColor));
for (uint idx = 1; idx < c._armour.size(); ++idx) {
if (!c._armour[idx]->empty())
_stats.push_back(StatEntry(formatStat(c._armour[idx]->_name.c_str(), c._armour[idx]->_quantity),
(int)idx == c._equippedArmour ? _game->_highlightColor : _game->_textColor));
}
for (uint idx = 1; idx < c._weapons.size(); ++idx) {
if (!c._weapons[idx]->empty())

View File

@ -394,8 +394,8 @@ bool ViewCharacterGeneration::save() {
_character->_experience = 0;
_character->_equippedWeapon = 1;
_character->_weapons[1]->_quantity = 1; // Dagger
_character->_equippedArmor = 1;
_character->_armor[1]->_quantity = 1; // Leather armour
_character->_equippedArmour = 1;
_character->_armour[1]->_quantity = 1; // Leather armour
_character->_equippedSpell = 0;
return g_vm->saveGame();

View File

@ -142,7 +142,7 @@ void DungeonMonster::attackParty() {
addInfoMsg(Common::String::format(game->_res->ATTACKED_BY, _name.c_str()));
_game->playFX(3);
threshold = (c._stamina / 2) + (c._equippedArmor * 8) + 56;
threshold = (c._stamina / 2) + (c._equippedArmour * 8) + 56;
if (_game->getRandomNumber(1, 255) > threshold) {
threshold = _game->getRandomNumber(1, 255);
@ -151,10 +151,10 @@ void DungeonMonster::attackParty() {
damage = _game->getRandomNumber(_widgetId + 1, 255);
}
if (_widgetId == MONSTER_GELATINOUS_CUBE && c.isArmorEquipped()) {
if (_widgetId == MONSTER_GELATINOUS_CUBE && c.isArmourEquipped()) {
addInfoMsg(game->_res->ARMOR_DESTROYED);
c._armor[c._equippedArmor]->decrQuantity();
c.removeArmor();
c._armour[c._equippedArmour]->decrQuantity();
c.removeArmour();
isHit = false;
} else if (_widgetId == MONSTER_GREMLIN) {
addInfoMsg(game->_res->GREMLIN_STOLE);

View File

@ -58,7 +58,7 @@ void Guard::attackParty() {
addInfoMsg(Common::String::format(game->_res->ATTACKED_BY, _name.c_str()));
game->playFX(7);
uint threshold = (c._stamina / 2) + (c._equippedArmor * 8) + 56;
uint threshold = (c._stamina / 2) + (c._equippedArmour * 8) + 56;
if (_game->getRandomNumber(1, 255) > threshold) {
int damage = _game->getRandomNumber(2, c._hitPoints / 128 + 15);
addInfoMsg(Common::String::format("%s...%2d %s", game->_res->HIT, damage, game->_res->DAMAGE));

View File

@ -0,0 +1,72 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "ultima/ultima1/widgets/merchant_armour.h"
#include "ultima/ultima1/maps/map_city_castle.h"
#include "ultima/ultima1/core/resources.h"
#include "ultima/ultima1/u1dialogs/armoury.h"
namespace Ultima {
namespace Ultima1 {
namespace Widgets {
EMPTY_MESSAGE_MAP(MerchantArmour, Merchant);
void MerchantArmour::get() {
Maps::MapCastle *map = dynamic_cast<Maps::MapCastle *>(_map);
assert(map);
if (map->_getCounter > 0) {
--map->_getCounter;
findArmor(false);
} else {
noKingsPermission();
}
}
void MerchantArmour::steal() {
findArmor(true);
}
void MerchantArmour::findArmor(bool checkStealing) {
Shared::Character &c = *_game->_party;
if (!checkStealing || !checkCuaghtStealing()) {
uint armorNum = _game->getRandomNumber(1, 5);
Common::String armorStr = _game->_res->ARMOR_NAMES[armorNum];
c._armour[armorNum]->incrQuantity();
if (armorNum == 5)
armorStr = Common::String::format("%s %s", _game->_res->A, armorStr.c_str());
addInfoMsg("");
addInfoMsg(Common::String::format(_game->_res->FIND, armorStr.c_str()));
}
}
void MerchantArmour::talk() {
U1Dialogs::Armoury *dialog = new U1Dialogs::Armoury(_game, _map->getMapStyle() - 2);
dialog->show();
}
} // End of namespace Widgets
} // End of namespace Ultima1
} // End of namespace Ultima

View File

@ -0,0 +1,84 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef ULTIMA_ULTIMA1_WIDGETS_MERCHANT_ARMOUR_H
#define ULTIMA_ULTIMA1_WIDGETS_MERCHANT_ARMOUR_H
#include "ultima/ultima1/widgets/merchant.h"
namespace Ultima {
namespace Ultima1 {
namespace Widgets {
/**
* Implements the armor merchant
*/
class MerchantArmour : public Merchant {
DECLARE_MESSAGE_MAP;
private:
/**
* Handles getting or stealing armor
* @param checkStealing If set, checks for stealing
*/
void findArmor(bool checkStealing);
public:
DECLARE_WIDGET(MerchantArmour)
CLASSDEF;
/**
* Constructor
*/
MerchantArmour(Ultima1Game *game, Maps::MapBase *map, int hitPoints) :
Merchant(game, map, 50, hitPoints) {}
/**
* Constructor
*/
MerchantArmour(Ultima1Game *game, Maps::MapBase *map, uint tileNum, int hitPoints) :
Merchant(game, map, tileNum, hitPoints) {}
/**
* Constructor
*/
MerchantArmour(Ultima1Game *game, Maps::MapBase *map) : Merchant(game, map, 50) {}
/**
* Does the get action
*/
virtual void get() override;
/**
* Does the steal action
*/
virtual void steal() override;
/**
* Does the talk action
*/
virtual void talk() override;
};
} // End of namespace Widgets
} // End of namespace Ultima1
} // End of namespace Ultima
#endif

View File

@ -94,7 +94,7 @@ void OverworldMonster::attackParty() {
// Calculate damage threshold
threshold = (c._stamina / 2) + (c._equippedArmor * 8) + 56;
threshold = (c._stamina / 2) + (c._equippedArmour * 8) + 56;
if (tempDiff.x == 0 && tempDiff.y == 0 && _game->getRandomNumber(1, 255) > threshold) {
hit->_position = playerPos;