Browse Source

load starting loadout dynamically

pull/6601/head^2
ephphatha 3 years ago committed by Anders Jenbo
parent
commit
4e6517e54c
  1. 58
      Source/items.cpp
  2. 21
      Source/player.cpp
  3. 31
      Source/playerdat.cpp
  4. 31
      Source/playerdat.hpp

58
Source/items.cpp

@ -3004,40 +3004,40 @@ void CreatePlrItems(Player &player)
item.clear(); item.clear();
} }
switch (player._pClass) { const PlayerStartingLoadoutData &loadout = GetPlayerStartingLoadoutForClass(player._pClass);
case HeroClass::Warrior:
for (_item_indexes itemData : { IDI_WARRIOR, IDI_WARRSHLD, IDI_WARRCLUB, IDI_HEAL, IDI_HEAL }) if (loadout.spell != SpellID::Null && loadout.spellLevel > 0) {
CreateStartingItem(player, itemData); player._pMemSpells = GetSpellBitmask(loadout.spell);
break; player._pRSplType = SpellType::Spell;
case HeroClass::Rogue: player._pRSpell = loadout.spell;
for (_item_indexes itemData : { IDI_ROGUE, IDI_HEAL, IDI_HEAL }) player._pSplLvl[static_cast<unsigned>(loadout.spell)] = loadout.spellLevel;
CreateStartingItem(player, itemData); } else {
break; player._pMemSpells = 0;
case HeroClass::Sorcerer: }
for (_item_indexes itemData : { gbIsHellfire ? IDI_SORCERER : IDI_SORCERER_DIABLO, gbIsHellfire ? IDI_HEAL : IDI_MANA, gbIsHellfire ? IDI_HEAL : IDI_MANA })
CreateStartingItem(player, itemData); if (loadout.skill != SpellID::Null) {
break; player._pAblSpells = GetSpellBitmask(loadout.skill);
case HeroClass::Monk: if (player._pRSplType == SpellType::Invalid) {
for (_item_indexes itemData : { IDI_SHORTSTAFF, IDI_HEAL, IDI_HEAL }) player._pRSplType = SpellType::Skill;
CreateStartingItem(player, itemData); player._pRSpell = loadout.skill;
break; }
case HeroClass::Bard: }
for (_item_indexes itemData : { IDI_BARDSWORD, IDI_BARDDAGGER, IDI_HEAL, IDI_HEAL })
CreateStartingItem(player, itemData); for (auto &itemChoice : loadout.items) {
break; _item_indexes itemData = gbIsHellfire && itemChoice.hellfire != _item_indexes::IDI_NONE ? itemChoice.hellfire : itemChoice.diablo;
case HeroClass::Barbarian: if (itemData != _item_indexes::IDI_NONE)
for (_item_indexes itemData : { IDI_BARBARIAN, IDI_WARRSHLD, IDI_HEAL, IDI_HEAL })
CreateStartingItem(player, itemData); CreateStartingItem(player, itemData);
break;
} }
Item &goldItem = player.InvList[player._pNumInv]; if (loadout.gold > 0) {
MakeGoldStack(goldItem, 100); Item &goldItem = player.InvList[player._pNumInv];
MakeGoldStack(goldItem, loadout.gold);
player._pNumInv++; player._pNumInv++;
player.InvGrid[30] = player._pNumInv; player.InvGrid[30] = player._pNumInv;
player._pGold = goldItem._ivalue; player._pGold = goldItem._ivalue;
}
CalcPlrItemVals(player, false); CalcPlrItemVals(player, false);
} }

21
Source/player.cpp

@ -2310,28 +2310,12 @@ void CreatePlayer(Player &player, HeroClass c)
player._pLightRad = 10; player._pLightRad = 10;
player._pInfraFlag = false; player._pInfraFlag = false;
player._pRSplType = SpellType::Skill;
SpellID s = player.getPlayerData().skill;
player._pAblSpells = GetSpellBitmask(s);
player._pRSpell = s;
if (c == HeroClass::Sorcerer) {
player._pMemSpells = GetSpellBitmask(SpellID::Firebolt);
player._pRSplType = SpellType::Spell;
player._pRSpell = SpellID::Firebolt;
} else {
player._pMemSpells = 0;
}
for (uint8_t &spellLevel : player._pSplLvl) { for (uint8_t &spellLevel : player._pSplLvl) {
spellLevel = 0; spellLevel = 0;
} }
player._pSpellFlags = SpellFlag::None; player._pSpellFlags = SpellFlag::None;
player._pRSplType = SpellType::Invalid;
if (player._pClass == HeroClass::Sorcerer) {
player._pSplLvl[static_cast<int8_t>(SpellID::Firebolt)] = 2;
}
// Initializing the hotkey bindings to no selection // Initializing the hotkey bindings to no selection
std::fill(player._pSplHotKey, player._pSplHotKey + NumHotkeys, SpellID::Invalid); std::fill(player._pSplHotKey, player._pSplHotKey + NumHotkeys, SpellID::Invalid);
@ -2517,8 +2501,7 @@ void InitPlayer(Player &player, bool firstTime)
ActivateVision(player.position.tile, player._pLightRad, player.getId()); ActivateVision(player.position.tile, player._pLightRad, player.getId());
} }
SpellID s = player.getPlayerData().skill; player._pAblSpells = GetSpellBitmask(GetPlayerStartingLoadoutForClass(player._pClass).skill);
player._pAblSpells = GetSpellBitmask(s);
player._pInvincible = false; player._pInvincible = false;

31
Source/playerdat.cpp

@ -249,18 +249,30 @@ void LoadClassesAttributes()
/** Contains the data related to each player class. */ /** Contains the data related to each player class. */
const PlayerData PlayersData[] = { const PlayerData PlayersData[] = {
// clang-format off // clang-format off
// HeroClass className, skill // HeroClass className
// TRANSLATORS: Player Block start // TRANSLATORS: Player Block start
/* HeroClass::Warrior */ { N_("Warrior"), SpellID::ItemRepair }, /* HeroClass::Warrior */ { N_("Warrior"), },
/* HeroClass::Rogue */ { N_("Rogue"), SpellID::TrapDisarm }, /* HeroClass::Rogue */ { N_("Rogue"), },
/* HeroClass::Sorcerer */ { N_("Sorcerer"), SpellID::StaffRecharge }, /* HeroClass::Sorcerer */ { N_("Sorcerer"), },
/* HeroClass::Monk */ { N_("Monk"), SpellID::Search }, /* HeroClass::Monk */ { N_("Monk"), },
/* HeroClass::Bard */ { N_("Bard"), SpellID::Identify }, /* HeroClass::Bard */ { N_("Bard"), },
// TRANSLATORS: Player Block end // TRANSLATORS: Player Block end
/* HeroClass::Barbarian */ { N_("Barbarian"), SpellID::Rage }, /* HeroClass::Barbarian */ { N_("Barbarian"), },
// clang-format on // clang-format on
}; };
const std::array<PlayerStartingLoadoutData, enum_size<HeroClass>::value> PlayersStartingLoadoutData { {
// clang-format off
// HeroClass skill, spell, spellLevel, items[0].diablo, items[0].hellfire, items[1].diablo, items[1].hellfire, items[2].diablo, items[2].hellfire, items[3].diablo, items[3].hellfire, items[4].diablo, items[4].hellfire, gold,
/* HeroClass::Warrior */ { SpellID::ItemRepair, SpellID::Null, 0, { { { IDI_WARRIOR, IDI_WARRIOR, }, { IDI_WARRSHLD, IDI_WARRSHLD, }, { IDI_WARRCLUB, IDI_WARRCLUB, }, { IDI_HEAL, IDI_HEAL, }, { IDI_HEAL, IDI_HEAL, }, }, }, 100, },
/* HeroClass::Rogue */ { SpellID::TrapDisarm, SpellID::Null, 0, { { { IDI_ROGUE, IDI_ROGUE, }, { IDI_HEAL, IDI_HEAL, }, { IDI_HEAL, IDI_HEAL, }, { IDI_NONE, IDI_NONE, }, { IDI_NONE, IDI_NONE, }, }, }, 100, },
/* HeroClass::Sorcerer */ { SpellID::StaffRecharge, SpellID::Fireball, 2, { { { IDI_SORCERER_DIABLO, IDI_SORCERER, }, { IDI_MANA, IDI_HEAL, }, { IDI_MANA, IDI_HEAL, }, { IDI_NONE, IDI_NONE, }, { IDI_NONE, IDI_NONE, }, }, }, 100, },
/* HeroClass::Monk */ { SpellID::Search, SpellID::Null, 0, { { { IDI_SHORTSTAFF, IDI_SHORTSTAFF, }, { IDI_HEAL, IDI_HEAL, }, { IDI_HEAL, IDI_HEAL, }, { IDI_NONE, IDI_NONE, }, { IDI_NONE, IDI_NONE, }, }, }, 100, },
/* HeroClass::Bard */ { SpellID::Identify, SpellID::Null, 0, { { { IDI_BARDSWORD, IDI_BARDSWORD, }, { IDI_BARDDAGGER, IDI_BARDDAGGER, }, { IDI_HEAL, IDI_HEAL, }, { IDI_HEAL, IDI_HEAL, }, { IDI_NONE, IDI_NONE, }, }, }, 100, },
/* HeroClass::Barbarian */ { SpellID::Rage, SpellID::Null, 0, { { { IDI_BARBARIAN, IDI_BARBARIAN, }, { IDI_WARRSHLD, IDI_WARRSHLD, }, { IDI_HEAL, IDI_HEAL, }, { IDI_HEAL, IDI_HEAL, }, { IDI_NONE, IDI_NONE, }, }, }, 100, }
// clang-format on
} };
} // namespace } // namespace
const ClassAttributes &GetClassAttributes(HeroClass playerClass) const ClassAttributes &GetClassAttributes(HeroClass playerClass)
@ -305,6 +317,11 @@ const PlayerCombatData &GetPlayerCombatDataForClass(HeroClass clazz)
return PlayersCombatData[static_cast<size_t>(clazz)]; return PlayersCombatData[static_cast<size_t>(clazz)];
} }
const PlayerStartingLoadoutData &GetPlayerStartingLoadoutForClass(HeroClass clazz)
{
return PlayersStartingLoadoutData[static_cast<size_t>(clazz)];
}
/** Contains the data related to each player class. */ /** Contains the data related to each player class. */
const PlayerSpriteData PlayersSpriteData[] = { const PlayerSpriteData PlayersSpriteData[] = {
// clang-format off // clang-format off

31
Source/playerdat.hpp

@ -8,6 +8,7 @@
#include <cstdint> #include <cstdint>
#include "effects.h" #include "effects.h"
#include "itemdat.h"
#include "spelldat.h" #include "spelldat.h"
namespace devilution { namespace devilution {
@ -78,6 +79,35 @@ struct PlayerCombatData {
uint8_t baseMagicToHit; uint8_t baseMagicToHit;
}; };
/**
* @brief Data used to set known skills and provide initial equipment when starting a new game
*
* Items will be created in order starting with item 1, 2, etc. If the item can be equipped it
* will be placed in the first available slot, otherwise if it fits on the belt it will be
* placed in the first free space, finally being placed in the first free inventory position.
*
* The active game mode at the time we're creating a new character controls the choice of item
* type. ItemType.hellfire is used if we're in Hellfire mode, ItemType.diablo otherwise.
*/
struct PlayerStartingLoadoutData {
/* Class Skill */
SpellID skill;
/* Starting Spell (if any) */
SpellID spell;
/* Initial level of the starting spell */
uint8_t spellLevel;
struct ItemType {
_item_indexes diablo;
_item_indexes hellfire;
};
std::array<ItemType, 5> items;
/* Initial gold amount, up to a single stack (5000 gold) */
uint16_t gold;
};
struct PlayerSpriteData { struct PlayerSpriteData {
/* Class Directory Path */ /* Class Directory Path */
const char *classPath; const char *classPath;
@ -170,6 +200,7 @@ uint32_t GetNextExperienceThresholdForLevel(unsigned level);
uint8_t GetMaximumCharacterLevel(); uint8_t GetMaximumCharacterLevel();
const PlayerData &GetPlayerDataForClass(HeroClass clazz); const PlayerData &GetPlayerDataForClass(HeroClass clazz);
const PlayerCombatData &GetPlayerCombatDataForClass(HeroClass clazz); const PlayerCombatData &GetPlayerCombatDataForClass(HeroClass clazz);
const PlayerStartingLoadoutData &GetPlayerStartingLoadoutForClass(HeroClass clazz);
extern const PlayerSpriteData PlayersSpriteData[]; extern const PlayerSpriteData PlayersSpriteData[];
extern const PlayerAnimData PlayersAnimData[]; extern const PlayerAnimData PlayersAnimData[];

Loading…
Cancel
Save