From 79541c8f8448595d62ad20c4d5b24a11e54bce2d Mon Sep 17 00:00:00 2001 From: Tom Hicks Date: Tue, 25 Apr 2023 11:43:23 -0700 Subject: [PATCH] Refactors a lot of stuff out of sbf. --- sbf-cpp/BUILD | 30 +- sbf-cpp/Character.cpp | 32 +- sbf-cpp/Character.h | 15 +- sbf-cpp/CharacterGenerator.cpp | 514 ++++++ sbf-cpp/CharacterGenerator.h | 24 + sbf-cpp/CharacterGenerator_test.cpp | 25 + sbf-cpp/Menus.cpp | 124 ++ sbf-cpp/Menus.h | 42 +- sbf-cpp/Questions.md | 54 +- sbf-cpp/sbf.cpp | 477 +----- sbf-cpp/sbf.h | 2398 --------------------------- 11 files changed, 829 insertions(+), 2906 deletions(-) create mode 100644 sbf-cpp/CharacterGenerator.cpp create mode 100644 sbf-cpp/CharacterGenerator.h create mode 100644 sbf-cpp/CharacterGenerator_test.cpp diff --git a/sbf-cpp/BUILD b/sbf-cpp/BUILD index ee79c23..595a5ff 100644 --- a/sbf-cpp/BUILD +++ b/sbf-cpp/BUILD @@ -183,6 +183,28 @@ cc_test( ], ) +cc_library( + name = "character_generator", + srcs = ["CharacterGenerator.cpp"], + hdrs = ["CharacterGenerator.h"], + deps = [ + "archetypes", + "character", + "freebies", + "genders", + "menus", + ], +) + +cc_test( + name = "character_generator_test", + srcs = ["CharacterGenerator_test.cpp"], + deps = [ + ":character_generator", + ":tinytest", + ], +) + # cc_library( # name = "main", # srcs = ["main.cpp"], @@ -255,13 +277,7 @@ cc_binary( "sbf.h", ], deps = [ - ":abilities", - ":archetypes", - ":attributes", - ":backgrounds", - ":character", - ":clans", - ":genders", + ":character_generator", ":menus", ], ) diff --git a/sbf-cpp/Character.cpp b/sbf-cpp/Character.cpp index ecd4989..8bce92c 100644 --- a/sbf-cpp/Character.cpp +++ b/sbf-cpp/Character.cpp @@ -28,11 +28,12 @@ CharacterType::CharacterType() { natureId = 0; demeanorId = 0; generation = 3; - roadName = ""; - roadValue = 0; + road_name = ""; + road_value = 0; willpower = 0; bloodPool = 0; derangementId = -1; + freebie_points = 15; // Virtues selfControl = 1; @@ -250,10 +251,9 @@ int CharacterType::GetVirtueValue(int id) const { } void CharacterType::FillVirtueValues(std::vector& values) const { - // TODO: This method sucks, but was needed in QBasic. values.clear(); for (int id = 0; id <= kVirtuesCount; id++) { - values[id] = GetVirtueValue(id); + values.push_back(GetVirtueValue(id)); } } @@ -756,4 +756,28 @@ string CharacterType::GetAllDerangementsLine() const { } return ""; } + +int CharacterType::GetFreebiePoints() const { + return freebie_points; +} + +void CharacterType::SetFreebiePoints(int value) { + freebie_points = value; +} + +string CharacterType::GetRoadName() const { + return road_name; +} + +void CharacterType::SetRoadName(string name) { + road_name = name; +} + +int CharacterType::GetRoadValue() const { + return road_value; +} + +void CharacterType::SetRoadValue(int value) { + road_value = value; +} } // End namespace SBF diff --git a/sbf-cpp/Character.h b/sbf-cpp/Character.h index 37596e7..7191284 100644 --- a/sbf-cpp/Character.h +++ b/sbf-cpp/Character.h @@ -30,6 +30,7 @@ int GetAttributePointsForRank(int rank_id); int GetBackgroundPoints(); int GetDisciplinePoints(); int GetVirtuePoints(); +const int kInitialGeneration = 13; class CharacterType { public: @@ -47,9 +48,12 @@ class CharacterType { std::vector GetBackgroundValues() const; int GetDisciplineValue(int id) const; std::vector GetDisciplineValues() const; + int GetFreebiePoints() const; int GetKnowledgeValue(int id) const; int GetMentalAttributeValue(int id) const; int GetPhysicalAttributeValue(int id) const; + std::string GetRoadName() const; + int GetRoadValue() const; int GetSkillValue(int id) const; int GetSocialAttributeValue(int id) const; int GetTalentValue(int id) const; @@ -59,13 +63,17 @@ class CharacterType { void SetAttributeValue(int group_id, int id, int value); void SetBackgroundValue(int id, int value); void SetDisciplineValue(int id, int value); + void SetFreebiePoints(int value); void SetKnowledgeValue(int id, int value); void SetMentalAttributeValue(int id, int value); void SetPhysicalAttributeValue(int id, int value); + void SetRoadName(std::string name); + void SetRoadValue(int value); void SetSkillValue(int id, int value); void SetSocialAttributeValue(int id, int value); void SetTalentValue(int id, int value); void SetVirtueValue(int id, int value); + std::string name; std::string player; std::string chronicle; @@ -80,13 +88,16 @@ class CharacterType { int selfControl; int courage; int generation; - std::string roadName; - int roadValue; int willpower; int bloodPool; int derangementId; private: + // Scalars + int freebie_points; + std::string road_name; + int road_value; + // Disciplines int discipline_animalism; int discipline_auspex; diff --git a/sbf-cpp/CharacterGenerator.cpp b/sbf-cpp/CharacterGenerator.cpp new file mode 100644 index 0000000..3b4795e --- /dev/null +++ b/sbf-cpp/CharacterGenerator.cpp @@ -0,0 +1,514 @@ +#include "CharacterGenerator.h" + +#include +#include +#include + +#include "Archetypes.h" +#include "Character.h" +#include "Freebies.h" +#include "Genders.h" +#include "Menus.h" +#include "Random.h" +#include "Utils.h" + +namespace SBF { +namespace { +using std::cout; +using std::endl; +using std::string; +using std::to_string; +using std::vector; +} // End namespace + +void CGGetHeader(CharacterType& ch) { + MaybeClearScreen(); + MenuStyle ms; + ch.name = GetString("What is the character's name?"); + ch.player = GetString("Who is the player?"); + ch.chronicle = GetString("What chronicle is the character going to be used for?"); + ch.haven = GetString("What is the character's Haven?"); + ch.concept = GetString("What is the character's concept?"); + ch.age = GetString("How old is the character?"); + vector genders; + FillGenderLabels(genders); + ch.genderId = ChooseStringId(genders, ms, "What is the character's gender?"); + vector clans; + FillClanLabels(clans); + ch.clanId = ChooseStringId(clans, ms, "What clan is the character from?"); + vector archetypes; + FillArchetypeLabels(archetypes); + ch.natureId = ChooseStringId(archetypes, ms, "What is the character's nature?"); + ch.demeanorId = ChooseStringId(archetypes, ms, "What is the character's demeanor?"); +} + +void CGGetDisciplines(CharacterType& ch) { + MenuStyle ms; + int discipline_points = GetDisciplinePoints(); + vector discipline_values; + vector discipline_labels; + FillDisciplineLabels(discipline_labels); + while (discipline_points > 0) { + MaybeClearScreen(); + discipline_values = ch.GetDisciplineValues(); + int discipline_id = ChooseStringIdWithValues( + discipline_labels, + discipline_values, + ms, + "Which discipline do you want to spend 1 of your " + to_string(discipline_points) + " points on?"); + ch.SetDisciplineValue(discipline_id, ch.GetDisciplineValue(discipline_id) + 1); + discipline_points--; + } +} + +void CGGetAttributes(CharacterType& ch) { + MenuStyle ms_without_values; + MenuStyle ms_with_values; + // indexed by group_id - 1 holds the rank_id + vector attribute_ranks(kAttributeGroupsCount); + + // Attribute groups menu (physical/social/mental) + vector attribute_groups_menu_items; + for (size_t i = 1; i <= kAttributeGroupsCount; i++) { + attribute_groups_menu_items.push_back(MenuItem(GetAttributeGroupLabel(i), i)); + } + + // Choose attribute group priorities. + int group_sum = 0; + int rank_sum = 1; + for (size_t i = 1; i < kAttributeGroupsCount; i++) { + int next_group_id = ChooseMenuItemId(attribute_groups_menu_items, + ms_without_values, + "Choose your " + ToLower(GetRank(i).label) + " attribute?", + true); + int next_group_index = next_group_id - 1; + attribute_groups_menu_items.at(next_group_index).is_visible = false; + attribute_ranks[next_group_index] = i; + rank_sum += i + 1; + group_sum += next_group_id; + } + + // General formula for last choice given 1 to count based indexing is this. (Sum from 1 to count) - (Sum of all + // previous choice IDs). Sum(1..AllAttributesCount)-Sum(Choice[1..Choice[AllAttributesCount-1]). + int last_group = rank_sum - group_sum; + attribute_ranks[last_group - 1] = kAttributeGroupsCount; + + // Spend attribute points + for (int group_id = 1; group_id <= kAttributeGroupsCount; group_id++) { + int group_index = group_id - 1; + vector attribute_labels = GetAttributeLabelsInGroup(group_id); + int rank_id = attribute_ranks.at(group_index); + int attribute_points = GetAttributePointsForRank(rank_id); + while (attribute_points > 0) { + vector values = ch.GetAttributeValuesInGroup(group_id); + string prompt = "Which " + ToLower(GetAttributeGroupLabel(group_id)) + + " attribute do you want to spend 1 of your " + to_string(attribute_points) + " points on?"; + int attribute_id = ChooseStringIdWithValues(attribute_labels, values, ms_with_values, prompt); + ch.SetAttributeValue(group_id, attribute_id, ch.GetAttributeValue(group_id, attribute_id) + 1); + attribute_points--; + } + } +} + +void CGGetBackgrounds(CharacterType& ch) { + // Spend background points + MenuStyle ms; + int background_points = GetBackgroundPoints(); + vector background_labels = GetBackgroundLabels(); + while (background_points > 0) { + MaybeClearScreen(); + vector background_values = ch.GetBackgroundValues(); + int background_id = ChooseStringIdWithValues( + background_labels, + background_values, + ms, + "Which background do you want to spend 1 of your " + to_string(background_points) + " points on?"); + ch.SetBackgroundValue(background_id, ch.GetBackgroundValue(background_id) + 1); + background_points--; + } +} + +void CGGetRoad(CharacterType& ch) { + // TODO: Update this to actually pick a road for VtDA. + ch.SetRoadName("Humanity"); +} + +void CGSpendVirtuePoints(CharacterType& ch) { + // Spend virtue points + MenuStyle ms; + int virtue_points = GetVirtuePoints(); + vector labels = GetVirtueLabels(); + while (virtue_points > 0) { + vector values = ch.GetVirtueValues(); + int virtue_id = ChooseStringIdWithValues( + labels, values, ms, "Which virtue do you want to spend 1 of your " + to_string(virtue_points) + " points on?"); + ch.SetVirtueValue(virtue_id, ch.GetVirtueValue(virtue_id) + 1); + virtue_points--; + } +} + +void CGGetDerangement(CharacterType& ch) { + if (ch.clanId == kClanMalkavian) { + // If the clan is malkavian then pick a derangement. + MenuStyle ms; + ms.use_colors = true; + ch.derangementId = + ChooseStringIdWithColors(GetDerangementLabels(), GetDerangementColors(), ms, "Which derangement do you want?"); + } +} + +void CGSpendFreebiePoints(CharacterType& ch) { + int freebie_points = ch.GetFreebiePoints(); + MenuStyle ms; + while (freebie_points > 0) { + MaybeClearScreen(); + // Build the menu + vector available_freebies = GetAvailableFreebies(freebie_points); + vector menu_items; + for (int freebie_index = 0; freebie_index < available_freebies.size(); freebie_index++) { + FreebieType freebie = available_freebies.at(freebie_index); + MenuItem mi(freebie.label, freebie.id); + if (freebie_index + 1 == kFreebieShowCharacterSheetId) { + mi.include_in_random = false; + } + menu_items.push_back(mi); + } + string prompt = "You have " + to_string(freebie_points) + + " freebie points remaining. What would you like to spend the points on?"; + int id = ChooseMenuItemId(menu_items, ms, prompt, true); + switch (id) { + case kFreebieDisciplineId: + CGSpendDisciplinePoint(ch); + break; + case kFreebieAttributeId: + CGSpendAttributePoint(ch); + break; + case kFreebieAbilityId: + CGSpendAbilityPoint(ch); + break; + case kFreebieVirtueId: + CGSpendVirtuePoint(ch); + break; + case kFreebieHumanityId: + CGSpendHumanityPoint(ch); + break; + case kFreebieBackgroundId: + CGSpendBackgroundPoint(ch); + break; + case kFreebieShowCharacterSheetId: + ShowCharacterSheet(ch); + break; + } + freebie_points = ch.GetFreebiePoints(); + } +} + +void CGSpendDisciplinePoint(CharacterType& ch) { + MaybeClearScreen(); + MenuStyle ms; + ms.show_cancel = true; + ms.cancel_item_id = kDisciplinesCount + 1; + vector values = ch.GetDisciplineValues(); + vector labels; + FillDisciplineLabels(labels); + string prompt = "Which discipline would you like to add 1 dot to?"; + int discipline_id = ChooseStringIdWithValues(labels, values, ms, prompt); + if (discipline_id != ms.cancel_item_id) { + ch.SetDisciplineValue(discipline_id, ch.GetDisciplineValue(discipline_id) + 1); + ch.SetFreebiePoints(ch.GetFreebiePoints() - kFreebieDisciplineCost); + } +} + +struct GroupedStatReference { + int id; + int group_id; + int item_id; +}; + +void CGSpendAttributePoint(CharacterType& ch) { + MaybeClearScreen(); + MenuStyle ms; + ms.show_cancel = true; + int num_attributes = 0; + vector num_attributes_in_group; + for (int group_id = 1; group_id <= kAttributeGroupsCount; group_id++) { + int count = GetNumAttributesInGroup(group_id); + num_attributes_in_group.push_back(count); + num_attributes += count; + } + + vector attribute_refs; + vector labels; + vector values; + + int attribute_id = 1; + for (int attribute_group_id = 1; attribute_group_id <= kAttributeGroupsCount; attribute_group_id++) { + int attribute_group_index = attribute_group_id - 1; + for (int id = 1; id <= num_attributes_in_group.at(attribute_group_index); id++) { + GroupedStatReference attribute_ref = {attribute_id, attribute_group_id, id}; + attribute_refs.push_back(attribute_ref); + labels.push_back(GetAttributeLabel(attribute_group_id, id)); + values.push_back(ch.GetAttributeValue(attribute_group_id, id)); + attribute_id++; + } + } + + string prompt = "Which attribute do you want to add one dot to?"; + ms.cancel_item_id = num_attributes + 1; + int id = ChooseStringIdWithValues(labels, values, ms, prompt); + if (id == ms.cancel_item_id) { + return; + } + GroupedStatReference ref = attribute_refs.at(id - 1); + ch.SetAttributeValue(ref.group_id, ref.item_id, ch.GetAttributeValue(ref.group_id, ref.item_id) + 1); + ch.SetFreebiePoints(ch.GetFreebiePoints() - kFreebieAttributeCost); +} + +void CGSpendAbilityPoint(CharacterType& ch) { + MenuStyle ms; + ms.show_cancel = true; + bool done = false; + while (!done) { + MaybeClearScreen(); + ms.cancel_item_id = kAbilitiesCount; + int ability_group_id = + ChooseStringId(GetAbilityGroupPluralLabels(), ms, "What kind of ability would you like to add 1 dot to?"); + if (ability_group_id == ms.cancel_item_id) { + return; + } + AbilityType ability = GetAbility(ability_group_id); + + vector labels = GetAbilityLabelsForAbilityGroup(ability_group_id); + ms.cancel_item_id = labels.size() + 1; + int ability_id = + ChooseStringId(labels, ms, "What " + ToLower(ability.singular) + " would you like to add 1 dot to?"); + if (ability_id != ms.cancel_item_id) { + ch.SetAbilityValue(ability_group_id, ability_id, ch.GetAbilityValue(ability_group_id, ability_id) + 1); + ch.SetFreebiePoints(ch.GetFreebiePoints() - kFreebieAbilityCost); + } + } +} + +void CGSpendVirtuePoint(CharacterType& ch) { + MenuStyle ms; + ms.show_cancel = true; + ms.cancel_item_id = kVirtuesCount + 1; + string prompt = "What virtue would you like to add 1 dot to?"; + int id = ChooseStringIdWithValues(GetVirtueLabels(), ch.GetVirtueValues(), ms, prompt); + if (id != ms.cancel_item_id) { + ch.SetVirtueValue(id, ch.GetVirtueValue(id) + 1); + ch.SetFreebiePoints(ch.GetFreebiePoints() - kFreebieVirtueCost); + } +} + +void CGSpendHumanityPoint(CharacterType& ch) { + vector labels = {"Yes", "No"}; + string prompt = "Are you sure you want to add a dot to your " + ch.GetRoadName() + "?"; + MenuStyle ms; + ms.show_random = false; + if (ChooseYesOrNo(prompt)) { + ch.SetRoadValue(ch.GetRoadValue() - 1); + ch.SetFreebiePoints(ch.GetFreebiePoints() - kFreebieHumanityCost); + } +} + +void CGSpendBackgroundPoint(CharacterType& ch) { + MenuStyle ms; + ms.show_cancel = true; + vector labels = GetBackgroundLabels(); + ms.cancel_item_id = labels.size() + 1; + string prompt = "Which background would you like to add 1 dot to?"; + int id = ChooseStringId(labels, ms, prompt); + if (id != ms.cancel_item_id) { + ch.SetBackgroundValue(id, ch.GetBackgroundValue(id) + 1); + ch.SetFreebiePoints(ch.GetFreebiePoints() - kFreebieBackgroundCost); + } +} + +string FormatAttributeValue(const string& label, int value) { + return MakeFitC(label + MakeFitL(to_string(value), 2), 12); +} + +string FormatAbilityWithValue(const string& label, int value) { + return MakeFitC(MakeFitL(label + ":", 14) + to_string(value), 24); +} + +void SaveCharacterSheet(CharacterType& ch) { + // TODO: Fill this in. + cout << "// TODO: SaveCharacterSheet(CharacterType&)" << endl; +} + +void ShowCharacterSheet(CharacterType& ch) { + const int kLeftColumnWidth = 36; + const int kRightColumnWidth = 37; + vector discipline_strings; + size_t index; + for (index = 1; index <= kDisciplinesCount; index++) { + int value = ch.GetDisciplineValue(index); + if (value > 0) { + string suffix = ""; + if (value > 1) { + suffix = " x" + to_string(value); + } + discipline_strings.push_back(GetDisciplineLabel(index) + suffix); + } + } + while (discipline_strings.size() <= 3) { + discipline_strings.push_back(RepeatChar(kLeftColumnWidth, '_')); + } + vector background_strings(5); + for (index = 1; index <= kBackgroundsCount; index++) { + int value = ch.GetBackgroundValue(index); + if (value > 0) { + string suffix = ""; + if (value > 1) { + suffix = " x" + to_string(value); + } + background_strings.push_back(GetBackgroundLabel(index) + suffix); + } + } + while (background_strings.size() <= 5) { + background_strings.push_back(RepeatChar(kLeftColumnWidth, '_')); + } + string all_derangements_line = ch.GetAllDerangementsLine(); + vector derangement_strings = WordWrap(all_derangements_line, kLeftColumnWidth); + while (derangement_strings.size() <= 5) { + derangement_strings.push_back(RepeatChar(kLeftColumnWidth, '_')); + } + MaybeClearScreen(); + cout << "╔══════════════════════════════════════╦═══════════════════════════════════════╗" << endl; + cout << "║ Name: " << MakeFitL(ch.name, 30) << " ║ Gender: " << MakeFitL(GetGenderLabel(ch.genderId), 14) + << " Generation: " << MakeFitR(to_string(ch.generation), 2) << " ║" << endl; + cout << "║ Clan: " << MakeFitL(GetClanLabel(ch.clanId), 30) << " ║ Age: " << MakeFitL(ch.age, 32) << " ║" << endl; + cout << "╠══════════════════════════════════════╣ Player: " << MakeFitL(ch.player, 29) << " ║" << endl; + cout << "║ Attributes ║ Chronicle: " << MakeFitL(ch.chronicle, 26) << " ║" << endl; + cout << "║ " << MakeFitC("Physical", 12) << MakeFitC("Social", 12) << MakeFitC("Mental", 12) + << " ║ Haven: " << MakeFitL(ch.haven, 30) + " ║" << endl; + cout << "║ " << FormatAttributeValue("Str. ", ch.GetPhysicalAttributeValue(kPhysicalAttributeStrengthId)) + << FormatAttributeValue("App. ", ch.GetSocialAttributeValue(kSocialAttributeAppearanceId)) + << FormatAttributeValue("Int. ", ch.GetMentalAttributeValue(kMentalAttributeIntelligenceId)) + << " ║ Concept: " << MakeFitL(ch.concept, 28) << " ║" << endl; + cout << "║ " << FormatAttributeValue("Dex. ", ch.GetPhysicalAttributeValue(kPhysicalAttributeDexterityId)) + << FormatAttributeValue("Cha. ", ch.GetSocialAttributeValue(kSocialAttributeCharismaId)) + << FormatAttributeValue("Per. ", ch.GetMentalAttributeValue(kMentalAttributePerceptionId)) + << " ╠═══════════════════════════════════════╣" << endl; + cout << "║ " << FormatAttributeValue("Sta. ", ch.GetPhysicalAttributeValue(kPhysicalAttributeStaminaId)) + << FormatAttributeValue("Man. ", ch.GetSocialAttributeValue(kSocialAttributeManipulationId)) + << FormatAttributeValue("Wit. ", ch.GetMentalAttributeValue(kMentalAttributeWitsId)) + << " ║ Derangements: ║" << endl; + cout << "╠══════════════════════════════════════╣ " << MakeFitL(derangement_strings[0], kRightColumnWidth, '_') + << " ║" << endl; + cout << "║ Disciplines: ║ " << MakeFitL(derangement_strings[1], kRightColumnWidth, '_') + << " ║" << endl; + cout << "║ " << MakeFitL(discipline_strings[0], kLeftColumnWidth) << " ║ " + << MakeFitL(derangement_strings[2], kRightColumnWidth, '_') << " ║" << endl; + cout << "║ " << MakeFitL(discipline_strings[1], kLeftColumnWidth) << " ║ " + << MakeFitL(derangement_strings[3], kRightColumnWidth, '_') << " ║" << endl; + cout << "║ " << MakeFitL(discipline_strings[2], kLeftColumnWidth) << " ║ " + << MakeFitL(derangement_strings[4], kRightColumnWidth, '_') << " ║" << endl; + cout << "╠══════════════════════════════════════╬═══════════════════════════════════════╣" << endl; + cout << "║ " << MakeFitL(ch.GetRoadName() + ": " + to_string(ch.GetRoadValue()), kLeftColumnWidth) + << " ║ Nature: " << MakeFitL(GetArchetypeLabel(ch.natureId), 29) << " ║" << endl; + cout << "║ Willpower: " << MakeFitL(to_string(ch.willpower), 25) + << " ║ Demeanor: " << MakeFitL(GetArchetypeLabel(ch.demeanorId), 27) << " ║" << endl; + cout << "╠══════════════════════════════════════╩═══════════════════════════════════════╣" << endl; + cout << "║ ║" << endl; + cout << "║ ║" << endl; + cout << "║ ║" << endl; + cout << "║ <> ║" << endl; + cout << "╚══════════════════════════════════════════════════════════════════════════════╝" << endl; + WaitForKeypress(); + cout << "╔══════════════════════════════════════════════════════════════════════════════╗" << endl; + cout << "║ " << MakeFitC("Abilities", 76) << " ║" << endl; + cout << "║ " << MakeFitC("Talents", 24) << MakeFitC("Skills", 24) << MakeFitC("Knowledges", 24) << " ║" << endl; + for (index = 1; index <= 10; index++) { + cout << "║ " << FormatAbilityWithValue(GetTalentLabel(index), ch.GetTalentValue(index)) + << FormatAbilityWithValue(GetSkillLabel(index), ch.GetSkillValue(index)) + << FormatAbilityWithValue(GetKnowledgeLabel(index), ch.GetKnowledgeValue(index)) << " ║" << endl; + } + cout << "╠══════════════════════════════════════╦═══════════════════════════════════════╣" << endl; + cout << "║ " << MakeFitL("Backgrounds:", kLeftColumnWidth) << " ║ " << MakeFitL("Virtues:", kRightColumnWidth) << " ║" + << endl; + cout << "║ " << MakeFitL(background_strings[0], kLeftColumnWidth) << " ║ " + << MakeFitB("Conscience:", to_string(ch.conscience), kRightColumnWidth) << " ║" << endl; + cout << "║ " << MakeFitL(background_strings[1], kLeftColumnWidth) << " ║ " + << MakeFitB("Self-Control:", to_string(ch.selfControl), kRightColumnWidth) << " ║" << endl; + cout << "║ " << MakeFitL(background_strings[2], kLeftColumnWidth) << " ║ " + << MakeFitB("Courage:", to_string(ch.courage), kRightColumnWidth) << " ║" << endl; + cout << "║ " << MakeFitL(background_strings[3], kLeftColumnWidth) << " ║ " << MakeFitL("", kRightColumnWidth) << " ║" + << endl; + cout << "║ " << MakeFitL(background_strings[4], kLeftColumnWidth) << " ║ " << MakeFitL("", kRightColumnWidth) << " ║" + << endl; + cout << "╠══════════════════════════════════════╩═══════════════════════════════════════╣" << endl; + cout << "║ <> ║" << endl; + cout << "╚══════════════════════════════════════════════════════════════════════════════╝" << endl; + WaitForKeypress(); + /* + ╔══════════════════════════════════════╦═══════════════════════════════════════╗ + ║ Name: Ted ║ Gender: Female Generation: 13 ║ + ║ Clan: Ventrue ║ Age: 35 ║ + ╠══════════════════════════════════════╣ Player: Jeff ║ + ║ Attributes ║ Chronicle: Somesuch ║ + ║ Physical Social Mental ║ Haven: Mom's basement ║ + ║ Str. 1 App. 1 Int. 1 ║ Concept: Asshole ║ + ║ Dex. 1 Cha. 1 Per. 1 ╠═══════════════════════════════════════╣ + ║ Sta. 1 Man. 1 Wit. 1 ║ Derangements: ║ + ╠══════════════════════════════════════╣ _____________________________________ ║ + ║ Disciplines: ║ _____________________________________ ║ + ║ ____________________________________ ║ _____________________________________ ║ + ║ ____________________________________ ║ _____________________________________ ║ + ║ ____________________________________ ║ _____________________________________ ║ + ╠══════════════════════════════════════╬═══════════════════════════════════════╣ + ║ : 2 ║ Nature: Tyrant ║ + ║ Willpower: 1 ║ Demeanor: Traditionalist ║ + ╠══════════════════════════════════════╩═══════════════════════════════════════╣ + ║ ║ + ║ ║ + ║ ║ + ║ <> ║ + ╚══════════════════════════════════════════════════════════════════════════════╝ + ╔══════════════════════════════════════════════════════════════════════════════╗ + ║ Abilities ║ + ║ Talents Skills Knowledges ║ + ║ Acting: 0 Animal Ken: 0 Bureaucracy: 0 ║ + ║ Alertness: 0 Drive: 0 Computer: 0 ║ + ║ Athletics: 0 Etiquette: 0 Finance: 0 ║ + ║ Brawl: 0 Firearms: 0 Investigation:0 ║ + ║ Dodge: 0 Melee: 0 Law: 0 ║ + ║ Empathy: 0 Music: 0 Linguistics: 0 ║ + ║ Intimidation: 0 Repair: 0 Medicine: 0 ║ + ║ Leadership: 0 Security: 0 Occult: 0 ║ + ║ Streetwise: 0 Stealth: 0 Politics: 0 ║ + ║ Subterfuge: 0 Survival: 0 Science: 0 ║ + ╠══════════════════════════════════════╦═══════════════════════════════════════╣ + ║ Backgrounds: ║ Virtues: ║ + ║ ║ Conscience: 1 ║ + ║ ║ Self-Control: 1 ║ + ║ ║ Courage: 1 ║ + ║ ║ ║ + ║ ║ ║ + ╠══════════════════════════════════════╩═══════════════════════════════════════╣ + ║ <> ║ + ╚══════════════════════════════════════════════════════════════════════════════╝ + */ +} + +void CharacterGenerator() { + CharacterType ch; + CGGetHeader(ch); + CGGetDisciplines(ch); + CGGetAttributes(ch); + CGGetBackgrounds(ch); + CGGetRoad(ch); + CGSpendVirtuePoints(ch); + CGGetDerangement(ch); + ch.generation = kInitialGeneration - ch.GetBackgroundValue(kBackgroundGenerationId); + ch.willpower = ch.courage; + ch.SetRoadValue(ch.conscience + ch.selfControl); + ch.bloodPool = GetRandomInt(1, 10); + CGSpendFreebiePoints(ch); + SaveCharacterSheet(ch); + ShowCharacterSheet(ch); +} + +} // End namespace SBF diff --git a/sbf-cpp/CharacterGenerator.h b/sbf-cpp/CharacterGenerator.h new file mode 100644 index 0000000..2d004e9 --- /dev/null +++ b/sbf-cpp/CharacterGenerator.h @@ -0,0 +1,24 @@ +#ifndef CHARACTERGENERATOR_H__ +#define CHARACTERGENERATOR_H__ +#include "Character.h" + +namespace SBF { +void CGGetAttributes(CharacterType& ch); +void CGGetBackgrounds(CharacterType& ch); +void CGGetDerangement(CharacterType& ch); +void CGGetDisciplines(CharacterType& ch); +void CGGetHeader(CharacterType& ch); +void CGGetRoad(CharacterType& ch); +void CGSpendAbilityPoint(CharacterType& ch); +void CGSpendAttributePoint(CharacterType& ch); +void CGSpendBackgroundPoint(CharacterType& ch); +void CGSpendDisciplinePoint(CharacterType& ch); +void CGSpendFreebiePoints(CharacterType& ch); +void CGSpendHumanityPoint(CharacterType& ch); +void CGSpendVirtuePoint(CharacterType& ch); +void CGSpendVirtuePoints(CharacterType& ch); +void CharacterGenerator(); +void ShowCharacterSheet(CharacterType& ch); +void SaveCharacterSheet(CharacterType& ch); +} // namespace SBF +#endif // End !defined(CHARACTERGENERATOR_H__) diff --git a/sbf-cpp/CharacterGenerator_test.cpp b/sbf-cpp/CharacterGenerator_test.cpp new file mode 100644 index 0000000..d666cf9 --- /dev/null +++ b/sbf-cpp/CharacterGenerator_test.cpp @@ -0,0 +1,25 @@ +#include "CharacterGenerator.h" + +#include +#include +#include +#include +#include + +#include "test.h" + +namespace { +using namespace SBF; +using namespace Test; +using std::cout; +} // End namespace + +int main(int argc, char* argv[]) { + TestResults results; + + results.skip("// TODO: SBF::CharacterGenerator::*"); + + PrintResults(cout, results); + + return results.failed() + results.errors(); +} diff --git a/sbf-cpp/Menus.cpp b/sbf-cpp/Menus.cpp index a48b998..e9473c7 100644 --- a/sbf-cpp/Menus.cpp +++ b/sbf-cpp/Menus.cpp @@ -12,10 +12,12 @@ namespace SBF { namespace { +using std::cin; using std::cout; using std::endl; using std::ostream; using std::pair; +using std::string; using std::to_string; using std::vector; } // End namespace @@ -289,4 +291,126 @@ bool MenuItem::operator!=(const MenuItem& other) { return !(*this == other); } +int GetChoice(int min, int max) { + int choice; + do { + choice = GetChoice(); + } while (choice < min || choice > max); + return choice; +} + +int GetChoice() { + int choice; + string line; + bool has_error; + do { + has_error = false; + getline(cin, line); + try { + if (line.empty()) { + return 0; + } + choice = stoi(line); + } catch (...) { + has_error = true; + } + } while (has_error); + return choice; +} + +int GetMenuChoice(vector menu_items, MenuStyle style) { + int choice; + while (true) { + choice = GetChoice(); + if (style.show_random && choice == style.random_item_id) { + return choice; + } + if (style.show_cancel && choice == style.cancel_item_id) { + return choice; + } + for (MenuItem item : menu_items) { + if (item.id == choice) { + return choice; + } + } + } +} + +string GetString(string prompt) { + cout << prompt << endl; + string response; + getline(cin, response); + return response; +} + +int ChooseStringId(vector labels, MenuStyle style, const string& prompt) { + MaybeClearScreen(); + vector menu_items = BuildMenu(labels); + style.Adjust(menu_items); + cout << prompt << endl; + PrintMenu(cout, menu_items, style); + int choice = GetMenuChoice(menu_items, style); + if (choice == style.random_item_id) { + choice = GetRandomMenuItemId(menu_items); + } + return choice; +} + +bool ChooseYesOrNo(string prompt) { + MenuStyle style; + style.show_random = false; + vector menu_items = BuildMenu({"Yes", "No"}); + style.Adjust(menu_items, true); + cout << prompt << endl; + PrintMenu(cout, menu_items, style); + int choice = GetMenuChoice(menu_items, style); + if (choice == style.random_item_id) { + choice = GetRandomMenuItemId(menu_items); + } + return choice == 1; +} + +int ChooseStringIdWithValues(vector labels, vector values, MenuStyle style, const string& prompt) { + MaybeClearScreen(); + vector menu_items = BuildMenuWithValues(labels, values); + style.Adjust(menu_items, false); + cout << prompt << endl; + PrintMenu(cout, menu_items, style); + int choice = GetMenuChoice(menu_items, style); + if (choice == style.random_item_id) { + choice = GetRandomMenuItemId(menu_items); + } + return choice; +} + +int ChooseStringIdWithColors(vector labels, vector colors, MenuStyle style, const string& prompt) { + MaybeClearScreen(); + // Check array bounds + vector menu_items = BuildMenuWithColors(labels, colors); + style.Adjust(menu_items); + cout << prompt << endl; + PrintMenu(cout, menu_items, style); + int choice = GetMenuChoice(menu_items, style); + if (choice == style.random_item_id) { + choice = GetRandomMenuItemId(menu_items); + } + return choice; +} + +int ChooseMenuItemId(vector menu_items, MenuStyle style, const string& prompt, bool ignore_value) { + MaybeClearScreen(); + style.Adjust(menu_items, ignore_value); + cout << prompt << endl; + PrintMenu(cout, menu_items, style); + int choice = GetMenuChoice(menu_items, style); + if (choice == style.random_item_id) { + choice = GetRandomMenuItemId(menu_items); + } + return choice; +} + +void WaitForKeypress() { + // TODO: Make this press any key to continue. +} + } // End namespace SBF diff --git a/sbf-cpp/Menus.h b/sbf-cpp/Menus.h index fec2c93..33a85fe 100644 --- a/sbf-cpp/Menus.h +++ b/sbf-cpp/Menus.h @@ -27,8 +27,6 @@ class MenuItem; * @{ */ namespace SBF { -using std::string; - class MenuStyleBuilder { public: MenuStyleBuilder(); @@ -59,15 +57,15 @@ class MenuStyle { int label_width; int value_width; int screen_width; - string random_item_name; + std::string random_item_name; int random_item_id; uint8_t random_item_color; - string cancel_item_name; + std::string cancel_item_name; int cancel_item_id; uint8_t cancel_item_color; - string id_label_separator; - string label_value_separator; - string menu_item_spacer; + std::string id_label_separator; + std::string label_value_separator; + std::string menu_item_spacer; bool show_random; bool show_cancel; bool use_colors; @@ -82,7 +80,7 @@ class MenuItem { friend std::ostream& operator<<(std::ostream& os, const MenuItem& item); bool operator==(const MenuItem& other); bool operator!=(const MenuItem& other); - string label; + std::string label; int id; int value; uint8_t color; @@ -92,19 +90,41 @@ class MenuItem { // TODO: Make a menu class to hold GetRandomMenuItemId, the various BuildMenu* methods, and possibly PrintMenu. int GetRandomMenuItemId(std::vector items); -std::vector BuildMenu(std::vector labels); +std::vector BuildMenu(std::vector labels); std::vector BuildMenuWithValues(std::vector> items); std::vector BuildMenuWithValues(std::vector labels, std::vector values); std::vector BuildMenuWithColors(std::vector> items); std::vector BuildMenuWithColors(std::vector labels, std::vector colors); std::ostream& PrintMenu(std::ostream& os, std::vector items, MenuStyle style); -string GetTitle(MenuItem item, MenuStyle style); -string GetTitleWithoutValue(MenuItem item, MenuStyle style); +std::string GetTitle(MenuItem item, MenuStyle style); +std::string GetTitleWithoutValue(MenuItem item, MenuStyle style); std::ostream& PrintWithMaybeColor(std::ostream& os, const std::string& text, uint8_t text_color = kColorDefaultForeground, bool use_colors = false); +int ChooseStringId(std::vector labels, MenuStyle style, const std::string& prompt); +bool ChooseYesOrNo(std::string prompt); +int GetChoice(int min, int max); +int GetChoice(); +int GetMenuChoice(std::vector menu_items, MenuStyle style); +std::string GetString(std::string prompt); +int ChooseStringIdWithValues(std::vector labels, + std::vector values, + MenuStyle style, + const std::string& prompt); +int ChooseMenuItemId(std::vector menu_items, MenuStyle style, const std::string& prompt, bool ignore_value); +int ChooseStringIdWithColors(std::vector labels, + std::vector colors, + MenuStyle style, + const std::string& prompt); +void WaitForKeypress(); +/// Clears the screen if not a debug build. +inline void MaybeClearScreen() { +#if !defined(DEBUG) + cout << "\033[1;1H\033[2J"; +#endif +} } // End namespace SBF /** @}*/ diff --git a/sbf-cpp/Questions.md b/sbf-cpp/Questions.md index 09a59b3..6b6d823 100644 --- a/sbf-cpp/Questions.md +++ b/sbf-cpp/Questions.md @@ -1,18 +1,48 @@ -## Why do I have to cast std::nullopt to a specific optional type when calling a templated function i.e. - -```c++ -template -void DoSomething(std::optional = std::nullopt, bool report_errors = false); -``` - -```text -DoSomething() works fine. -DoSomething(std::nullopt, true) no matching function for call to 'DoSomething' Do_Something, bool>( -``` - ## Which is uglier ```c++ (*after_each)() after_each->operator()() after_each.value()(); ``` + +## What do all of these command line args do and which do I really want? +```bash +clang \ + -xc++ \ + -D_FORTIFY_SOURCE=1 \ + -fstack-protector \ + -fcolor-diagnostics \ + -Wall \ + -Wthread-safety \ + -Wself-assign \ + -fno-omit-frame-pointer \ + -O0 \ + -DDEBUG \ + -std=c++11 \ + -iquote \ + . \ + -iquote \ + bazel-out/darwin_arm64-fastbuild/bin \ + -MD \ + -MF \ + bazel-out/darwin_arm64-fastbuild/bin/sbf-cpp/_objs/menus/Menus.d \ + -DBAZEL_CURRENT_REPOSITORY="" \ + -frandom-seed=bazel-out/darwin_arm64-fastbuild/bin/sbf-cpp/_objs/menus/Menus.o \ + -isysroot \ + /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk \ + -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks \ + -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks \ + -no-canonical-prefixes \ + -pthread \ + -no-canonical-prefixes \ + -Wno-builtin-macro-redefined \ + -D__DATE__="redacted" \ + -D__TIMESTAMP__="redacted" \ + -D__TIME__="redacted" \ + -target \ + arm64-apple-macosx13.3 \ + -c \ + sbf-cpp/Menus.cpp \ + -o \ + bazel-out/darwin_arm64-fastbuild/bin/sbf-cpp/_objs/menus/Menus.o +``` diff --git a/sbf-cpp/sbf.cpp b/sbf-cpp/sbf.cpp index cb2b9cd..21749ba 100644 --- a/sbf-cpp/sbf.cpp +++ b/sbf-cpp/sbf.cpp @@ -1,4 +1,5 @@ -#include "sbf-cpp/Virtues.h" +#include "sbf.h" + #define _XOPEN_SOURCE_EXTENDED #include #include @@ -10,53 +11,33 @@ #include "Attributes.h" #include "Backgrounds.h" #include "Character.h" +#include "CharacterGenerator.h" #include "Clans.h" #include "Disciplines.h" +#include "Freebies.h" #include "Genders.h" #include "Menus.h" #include "Random.h" #include "Utils.h" -#include "sbf.h" +#include "Virtues.h" #define KEY_ESCAPE 0033 namespace { using namespace SBF; -using std::cin; using std::cout; using std::endl; -using std::to_string; -using std::vector; } // namespace -void CGGetAttributes(CharacterType& ch); -void CGGetBackgrounds(CharacterType& ch); -void CGGetDerangement(CharacterType& ch); -void CGGetDisciplines(CharacterType& ch); -void CGGetHeader(CharacterType& ch); -void CGGetRoad(CharacterType& ch); -void CGSpendFreebiePoints(CharacterType& ch); -void CGSpendVirtuePoints(CharacterType& ch); -void CharacterGenerator(); void CharacterGeneratorForDummies(); -int ChooseStringId(vector labels, MenuStyle style, const string& prompt); void CombatComputer(); void DiceRoller(); -int GetChoice(int min, int max); -int GetChoice(); -int GetMenuChoice(vector menu_items, MenuStyle style); -string GetString(string prompt); void MainMenu(); -void MaybeClearScreen(); void RandomCharacterGenerator(); void SaveCharacterSheet(CharacterType& ch); void ShowCharacterSheet(CharacterType& ch); void ShowSplashScreen(); void VehicleGenerator(); -void WaitForKeypress(); -int ChooseStringIdWithValues(vector labels, vector values, MenuStyle style, const string& prompt); -int ChooseMenuItemId(vector menu_items, MenuStyle style, const string& prompt, bool ignore_value); -int ChooseStringIdWithColors(vector labels, vector colors, MenuStyle style, const string& prompt); int main(int argc, char* argv[]) { setlocale(LC_ALL, ""); @@ -65,33 +46,6 @@ int main(int argc, char* argv[]) { return 0; } -int GetChoice(int min, int max) { - int choice; - do { - choice = GetChoice(); - } while (choice < min || choice > max); - return choice; -} - -int GetChoice() { - int choice; - string line; - bool has_error; - do { - has_error = false; - getline(cin, line); - try { - if (line.empty()) { - return 0; - } - choice = stoi(line); - } catch (...) { - has_error = true; - } - } while (has_error); - return choice; -} - void MainMenu() { int choice = 0; do { @@ -143,13 +97,6 @@ void MainMenu() { } while (choice != 0); } -/// Clears the screen if not a debug build. -inline void MaybeClearScreen() { -#if !defined(DEBUG) - cout << "\033[1;1H\033[2J"; -#endif -} - void ShowSplashScreen() { cout << "Welcome to Tom's Storyteller's Best Friend. This is a program that is meant to" << endl << "aid storytellers in running Vampire: the Masquerade Chronicles and Vampire: the" << endl @@ -160,28 +107,6 @@ void ShowSplashScreen() { WaitForKeypress(); } -void WaitForKeypress() { - // TODO: Make this press any key to continue. -} - -void CharacterGenerator() { - CharacterType ch; - CGGetHeader(ch); - CGGetDisciplines(ch); - CGGetAttributes(ch); - CGGetBackgrounds(ch); - CGGetRoad(ch); - CGSpendVirtuePoints(ch); - CGGetDerangement(ch); - ch.generation = kInitialGeneration - ch.GetBackgroundValue(kBackgroundGenerationId); - ch.willpower = ch.courage; - ch.roadValue = ch.conscience + ch.selfControl; - ch.bloodPool = GetRandomInt(1, 10); - CGSpendFreebiePoints(ch); - SaveCharacterSheet(ch); - ShowCharacterSheet(ch); -} - void CharacterGeneratorForDummies() { // TODO: Fill in this function. cout << "// TODO: CharacterGeneratorForDummies()" << endl; @@ -206,395 +131,3 @@ void VehicleGenerator() { // TODO: Fill in this function. cout << "// TODO: VehicleGenerator()" << endl; } - -void CGGetHeader(CharacterType& ch) { - MaybeClearScreen(); - MenuStyle ms; - ch.name = GetString("What is the character's name?"); - ch.player = GetString("Who is the player?"); - ch.chronicle = GetString("What chronicle is the character going to be used for?"); - ch.haven = GetString("What is the character's Haven?"); - ch.concept = GetString("What is the character's concept?"); - ch.age = GetString("How old is the character?"); - vector genders; - FillGenderLabels(genders); - ch.genderId = ChooseStringId(genders, ms, "What is the character's gender?"); - vector clans; - FillClanLabels(clans); - ch.clanId = ChooseStringId(clans, ms, "What clan is the character from?"); - vector archetypes; - FillArchetypeLabels(archetypes); - ch.natureId = ChooseStringId(archetypes, ms, "What is the character's nature?"); - ch.demeanorId = ChooseStringId(archetypes, ms, "What is the character's demeanor?"); -} - -void CGGetDisciplines(CharacterType& ch) { - MenuStyle ms; - int discipline_points = GetDisciplinePoints(); - vector discipline_values; - vector discipline_labels; - FillDisciplineLabels(discipline_labels); - while (discipline_points > 0) { - MaybeClearScreen(); - discipline_values = ch.GetDisciplineValues(); - int discipline_id = ChooseStringIdWithValues( - discipline_labels, - discipline_values, - ms, - "Which discipline do you want to spend 1 of your " + to_string(discipline_points) + " points on?"); - ch.SetDisciplineValue(discipline_id, ch.GetDisciplineValue(discipline_id) + 1); - discipline_points--; - } -} - -void CGGetAttributes(CharacterType& ch) { - MenuStyle ms_without_values; - MenuStyle ms_with_values; - // indexed by group_id - 1 holds the rank_id - vector attribute_ranks(kAttributeGroupsCount); - - // Attribute groups menu (physical/social/mental) - vector attribute_groups_menu_items; - for (size_t i = 1; i <= kAttributeGroupsCount; i++) { - attribute_groups_menu_items.push_back(MenuItem(GetAttributeGroupLabel(i), i)); - } - - // Choose attribute group priorities. - int group_sum = 0; - int rank_sum = 1; - for (size_t i = 1; i < kAttributeGroupsCount; i++) { - int next_group_id = ChooseMenuItemId(attribute_groups_menu_items, - ms_without_values, - "Choose your " + ToLower(GetRank(i).label) + " attribute?", - true); - int next_group_index = next_group_id - 1; - attribute_groups_menu_items.at(next_group_index).is_visible = false; - attribute_ranks[next_group_index] = i; - rank_sum += i + 1; - group_sum += next_group_id; - } - - // General formula for last choice given 1 to count based indexing is this. (Sum from 1 to count) - (Sum of all - // previous choice IDs). Sum(1..AllAttributesCount)-Sum(Choice[1..Choice[AllAttributesCount-1]). - int last_group = rank_sum - group_sum; - attribute_ranks[last_group - 1] = kAttributeGroupsCount; - - // Spend attribute points - for (int group_id = 1; group_id <= kAttributeGroupsCount; group_id++) { - int group_index = group_id - 1; - vector attribute_labels = GetAttributeLabelsInGroup(group_id); - int rank_id = attribute_ranks.at(group_index); - int attribute_points = GetAttributePointsForRank(rank_id); - while (attribute_points > 0) { - vector values = ch.GetAttributeValuesInGroup(group_id); - string prompt = "Which " + ToLower(GetAttributeGroupLabel(group_id)) - + " attribute do you want to spend 1 of your " + to_string(attribute_points) + " points on?"; - int attribute_id = ChooseStringIdWithValues(attribute_labels, values, ms_with_values, prompt); - ch.SetAttributeValue(group_id, attribute_id, ch.GetAttributeValue(group_id, attribute_id) + 1); - attribute_points--; - } - } -} - -void CGGetBackgrounds(CharacterType& ch) { - // Spend background points - MenuStyle ms; - int background_points = GetBackgroundPoints(); - vector background_labels = GetBackgroundLabels(); - while (background_points > 0) { - MaybeClearScreen(); - vector background_values = ch.GetBackgroundValues(); - int background_id = ChooseStringIdWithValues( - background_labels, - background_values, - ms, - "Which background do you want to spend 1 of your " + to_string(background_points) + " points on?"); - ch.SetBackgroundValue(background_id, ch.GetBackgroundValue(background_id) + 1); - background_points--; - } -} - -void CGGetRoad(CharacterType& ch) { - // TODO: Update this to actually pick a road for VtDA. - ch.roadName = "Humanity"; -} - -void CGSpendVirtuePoints(CharacterType& ch) { - // Spend virtue points - MenuStyle ms; - int virtue_points = GetVirtuePoints(); - vector labels = GetVirtueLabels(); - while (virtue_points > 0) { - vector values = ch.GetVirtueValues(); - int virtue_id = ChooseStringIdWithValues( - labels, values, ms, "Which virtue do you want to spend 1 of your " + to_string(virtue_points) + " points on?"); - ch.SetVirtueValue(virtue_id, ch.GetVirtueValue(virtue_id) + 1); - virtue_points--; - } -} - -void CGGetDerangement(CharacterType& ch) { - if (ch.clanId == kClanMalkavian) { - // If the clan is malkavian then pick a derangement. - MenuStyle ms; - ms.use_colors = true; - ch.derangementId = - ChooseStringIdWithColors(GetDerangementLabels(), GetDerangementColors(), ms, "Which derangement do you want?"); - } -} - -void CGSpendFreebiePoints(CharacterType& ch) { - // TODO: Fill this in. - cout << "// TODO: CGSpendFreebiePoints(CharacterType&)" << endl; -} - -string FormatAttributeValue(const string& label, int value) { - return MakeFitC(label + MakeFitL(to_string(value), 2), 12); -} - -string FormatAbilityWithValue(const string& label, int value) { - return MakeFitC(MakeFitL(label + ":", 14) + to_string(value), 24); -} - -void SaveCharacterSheet(CharacterType& ch) { - // TODO: Fill this in. - cout << "// TODO: SaveCharacterSheet(CharacterType&)" << endl; -} - -void ShowCharacterSheet(CharacterType& ch) { - const int kLeftColumnWidth = 36; - const int kRightColumnWidth = 37; - vector discipline_strings; - size_t index; - for (index = 1; index <= kDisciplinesCount; index++) { - int value = ch.GetDisciplineValue(index); - if (value > 0) { - string suffix = ""; - if (value > 1) { - suffix = " x" + to_string(value); - } - discipline_strings.push_back(GetDisciplineLabel(index) + suffix); - } - } - while (discipline_strings.size() <= 3) { - discipline_strings.push_back(RepeatChar(kLeftColumnWidth, '_')); - } - vector background_strings(5); - for (index = 1; index <= kBackgroundsCount; index++) { - int value = ch.GetBackgroundValue(index); - if (value > 0) { - string suffix = ""; - if (value > 1) { - suffix = " x" + to_string(value); - } - background_strings.push_back(GetBackgroundLabel(index) + suffix); - } - } - while (background_strings.size() <= 5) { - background_strings.push_back(RepeatChar(kLeftColumnWidth, '_')); - } - string all_derangements_line = ch.GetAllDerangementsLine(); - vector derangement_strings = WordWrap(all_derangements_line, kLeftColumnWidth); - while (derangement_strings.size() <= 5) { - derangement_strings.push_back(RepeatChar(kLeftColumnWidth, '_')); - } - MaybeClearScreen(); - cout << "╔══════════════════════════════════════╦═══════════════════════════════════════╗" << endl; - cout << "║ Name: " << MakeFitL(ch.name, 30) << " ║ Gender: " << MakeFitL(GetGenderLabel(ch.genderId), 14) - << " Generation: " << MakeFitR(to_string(ch.generation), 2) << " ║" << endl; - cout << "║ Clan: " << MakeFitL(GetClanLabel(ch.clanId), 30) << " ║ Age: " << MakeFitL(ch.age, 32) << " ║" << endl; - cout << "╠══════════════════════════════════════╣ Player: " << MakeFitL(ch.player, 29) << " ║" << endl; - cout << "║ Attributes ║ Chronicle: " << MakeFitL(ch.chronicle, 26) << " ║" << endl; - cout << "║ " << MakeFitC("Physical", 12) << MakeFitC("Social", 12) << MakeFitC("Mental", 12) - << " ║ Haven: " << MakeFitL(ch.haven, 30) + " ║" << endl; - cout << "║ " << FormatAttributeValue("Str. ", ch.GetPhysicalAttributeValue(kPhysicalAttributeStrengthId)) - << FormatAttributeValue("App. ", ch.GetSocialAttributeValue(kSocialAttributeAppearanceId)) - << FormatAttributeValue("Int. ", ch.GetMentalAttributeValue(kMentalAttributeIntelligenceId)) - << " ║ Concept: " << MakeFitL(ch.concept, 28) << " ║" << endl; - cout << "║ " << FormatAttributeValue("Dex. ", ch.GetPhysicalAttributeValue(kPhysicalAttributeDexterityId)) - << FormatAttributeValue("Cha. ", ch.GetSocialAttributeValue(kSocialAttributeCharismaId)) - << FormatAttributeValue("Per. ", ch.GetMentalAttributeValue(kMentalAttributePerceptionId)) - << " ╠═══════════════════════════════════════╣" << endl; - cout << "║ " << FormatAttributeValue("Sta. ", ch.GetPhysicalAttributeValue(kPhysicalAttributeStaminaId)) - << FormatAttributeValue("Man. ", ch.GetSocialAttributeValue(kSocialAttributeManipulationId)) - << FormatAttributeValue("Wit. ", ch.GetMentalAttributeValue(kMentalAttributeWitsId)) - << " ║ Derangements: ║" << endl; - cout << "╠══════════════════════════════════════╣ " << MakeFitL(derangement_strings[0], kRightColumnWidth, '_') - << " ║" << endl; - cout << "║ Disciplines: ║ " << MakeFitL(derangement_strings[1], kRightColumnWidth, '_') - << " ║" << endl; - cout << "║ " << MakeFitL(discipline_strings[0], kLeftColumnWidth) << " ║ " - << MakeFitL(derangement_strings[2], kRightColumnWidth, '_') << " ║" << endl; - cout << "║ " << MakeFitL(discipline_strings[1], kLeftColumnWidth) << " ║ " - << MakeFitL(derangement_strings[3], kRightColumnWidth, '_') << " ║" << endl; - cout << "║ " << MakeFitL(discipline_strings[2], kLeftColumnWidth) << " ║ " - << MakeFitL(derangement_strings[4], kRightColumnWidth, '_') << " ║" << endl; - cout << "╠══════════════════════════════════════╬═══════════════════════════════════════╣" << endl; - cout << "║ " << MakeFitL(ch.roadName + ": " + to_string(ch.roadValue), kLeftColumnWidth) - << " ║ Nature: " << MakeFitL(GetArchetypeLabel(ch.natureId), 29) << " ║" << endl; - cout << "║ Willpower: " << MakeFitL(to_string(ch.willpower), 25) - << " ║ Demeanor: " << MakeFitL(GetArchetypeLabel(ch.demeanorId), 27) << " ║" << endl; - cout << "╠══════════════════════════════════════╩═══════════════════════════════════════╣" << endl; - cout << "║ ║" << endl; - cout << "║ ║" << endl; - cout << "║ ║" << endl; - cout << "║ <> ║" << endl; - cout << "╚══════════════════════════════════════════════════════════════════════════════╝" << endl; - WaitForKeypress(); - cout << "╔══════════════════════════════════════════════════════════════════════════════╗" << endl; - cout << "║ " << MakeFitC("Abilities", 76) << " ║" << endl; - cout << "║ " << MakeFitC("Talents", 24) << MakeFitC("Skills", 24) << MakeFitC("Knowledges", 24) << " ║" << endl; - for (index = 1; index <= 10; index++) { - cout << "║ " << FormatAbilityWithValue(GetTalentLabel(index), ch.GetTalentValue(index)) - << FormatAbilityWithValue(GetSkillLabel(index), ch.GetSkillValue(index)) - << FormatAbilityWithValue(GetKnowledgeLabel(index), ch.GetKnowledgeValue(index)) << " ║" << endl; - } - cout << "╠══════════════════════════════════════╦═══════════════════════════════════════╣" << endl; - cout << "║ " << MakeFitL("Backgrounds:", kLeftColumnWidth) << " ║ " << MakeFitL("Virtues:", kRightColumnWidth) << " ║" - << endl; - cout << "║ " << MakeFitL(background_strings[0], kLeftColumnWidth) << " ║ " - << MakeFitB("Conscience:", to_string(ch.conscience), kRightColumnWidth) << " ║" << endl; - cout << "║ " << MakeFitL(background_strings[1], kLeftColumnWidth) << " ║ " - << MakeFitB("Self-Control:", to_string(ch.selfControl), kRightColumnWidth) << " ║" << endl; - cout << "║ " << MakeFitL(background_strings[2], kLeftColumnWidth) << " ║ " - << MakeFitB("Courage:", to_string(ch.courage), kRightColumnWidth) << " ║" << endl; - cout << "║ " << MakeFitL(background_strings[3], kLeftColumnWidth) << " ║ " << MakeFitL("", kRightColumnWidth) << " ║" - << endl; - cout << "║ " << MakeFitL(background_strings[4], kLeftColumnWidth) << " ║ " << MakeFitL("", kRightColumnWidth) << " ║" - << endl; - cout << "╠══════════════════════════════════════╩═══════════════════════════════════════╣" << endl; - cout << "║ <> ║" << endl; - cout << "╚══════════════════════════════════════════════════════════════════════════════╝" << endl; - WaitForKeypress(); - /* - ╔══════════════════════════════════════╦═══════════════════════════════════════╗ - ║ Name: Ted ║ Gender: Female Generation: 13 ║ - ║ Clan: Ventrue ║ Age: 35 ║ - ╠══════════════════════════════════════╣ Player: Jeff ║ - ║ Attributes ║ Chronicle: Somesuch ║ - ║ Physical Social Mental ║ Haven: Mom's basement ║ - ║ Str. 1 App. 1 Int. 1 ║ Concept: Asshole ║ - ║ Dex. 1 Cha. 1 Per. 1 ╠═══════════════════════════════════════╣ - ║ Sta. 1 Man. 1 Wit. 1 ║ Derangements: ║ - ╠══════════════════════════════════════╣ _____________________________________ ║ - ║ Disciplines: ║ _____________________________________ ║ - ║ ____________________________________ ║ _____________________________________ ║ - ║ ____________________________________ ║ _____________________________________ ║ - ║ ____________________________________ ║ _____________________________________ ║ - ╠══════════════════════════════════════╬═══════════════════════════════════════╣ - ║ : 2 ║ Nature: Tyrant ║ - ║ Willpower: 1 ║ Demeanor: Traditionalist ║ - ╠══════════════════════════════════════╩═══════════════════════════════════════╣ - ║ ║ - ║ ║ - ║ ║ - ║ <> ║ - ╚══════════════════════════════════════════════════════════════════════════════╝ - ╔══════════════════════════════════════════════════════════════════════════════╗ - ║ Abilities ║ - ║ Talents Skills Knowledges ║ - ║ Acting: 0 Animal Ken: 0 Bureaucracy: 0 ║ - ║ Alertness: 0 Drive: 0 Computer: 0 ║ - ║ Athletics: 0 Etiquette: 0 Finance: 0 ║ - ║ Brawl: 0 Firearms: 0 Investigation:0 ║ - ║ Dodge: 0 Melee: 0 Law: 0 ║ - ║ Empathy: 0 Music: 0 Linguistics: 0 ║ - ║ Intimidation: 0 Repair: 0 Medicine: 0 ║ - ║ Leadership: 0 Security: 0 Occult: 0 ║ - ║ Streetwise: 0 Stealth: 0 Politics: 0 ║ - ║ Subterfuge: 0 Survival: 0 Science: 0 ║ - ╠══════════════════════════════════════╦═══════════════════════════════════════╣ - ║ Backgrounds: ║ Virtues: ║ - ║ ║ Conscience: 1 ║ - ║ ║ Self-Control: 1 ║ - ║ ║ Courage: 1 ║ - ║ ║ ║ - ║ ║ ║ - ╠══════════════════════════════════════╩═══════════════════════════════════════╣ - ║ <> ║ - ╚══════════════════════════════════════════════════════════════════════════════╝ - // TODO: ShowCharacterSheet(CharacterType&) - */ -} - -int GetRandomInt(int min, int max) { - // TODO: Fill this in. - return 0; -} - -string GetString(string prompt) { - cout << prompt << endl; - string response; - getline(cin, response); - return response; -} - -int ChooseStringId(vector labels, MenuStyle style, const string& prompt) { - MaybeClearScreen(); - vector menu_items = BuildMenu(labels); - style.Adjust(menu_items); - cout << prompt << endl; - PrintMenu(cout, menu_items, style); - int choice = GetMenuChoice(menu_items, style); - if (choice == style.random_item_id) { - choice = GetRandomMenuItemId(menu_items); - } - return choice; -} - -int GetMenuChoice(vector menu_items, MenuStyle style) { - int choice; - while (true) { - choice = GetChoice(); - if (style.show_random && choice == style.random_item_id) { - return choice; - } - if (style.show_cancel && choice == style.cancel_item_id) { - return choice; - } - for (MenuItem item : menu_items) { - if (item.id == choice) { - return choice; - } - } - } -} - -int ChooseStringIdWithValues(vector labels, vector values, MenuStyle style, const string& prompt) { - MaybeClearScreen(); - vector menu_items = BuildMenuWithValues(labels, values); - style.Adjust(menu_items, false); - cout << prompt << endl; - PrintMenu(cout, menu_items, style); - int choice = GetMenuChoice(menu_items, style); - if (choice == style.random_item_id) { - choice = GetRandomMenuItemId(menu_items); - } - return choice; -} - -int ChooseStringIdWithColors(vector labels, vector colors, MenuStyle style, const string& prompt) { - MaybeClearScreen(); - // Check array bounds - vector menu_items = BuildMenuWithColors(labels, colors); - style.Adjust(menu_items); - cout << prompt << endl; - PrintMenu(cout, menu_items, style); - int choice = GetMenuChoice(menu_items, style); - if (choice == style.random_item_id) { - choice = GetRandomMenuItemId(menu_items); - } - return choice; -} - -int ChooseMenuItemId(vector menu_items, MenuStyle style, const string& prompt, bool ignore_value) { - MaybeClearScreen(); - style.Adjust(menu_items, ignore_value); - cout << prompt << endl; - PrintMenu(cout, menu_items, style); - int choice = GetMenuChoice(menu_items, style); - if (choice == style.random_item_id) { - choice = GetRandomMenuItemId(menu_items); - } - return choice; -} diff --git a/sbf-cpp/sbf.h b/sbf-cpp/sbf.h index ffe0607..96acf4d 100644 --- a/sbf-cpp/sbf.h +++ b/sbf-cpp/sbf.h @@ -10,603 +10,12 @@ ***************************************************************************************/ #include -#include "Character.h" -#include "Colors.h" -#include "Menus.h" - /** \addtogroup Unsorted * @{ */ namespace SBF { using std::string; - -const int kInitialGeneration = 13; - /* - -$Debug -' Setup -Randomize Timer - -Const FALSE = 0 -Const TRUE = Not FALSE -Const isDebugging = TRUE - -Const INITIAL_GENERATION = 13 - -Const COLOR_DARK_BLACK = 0 -Const COLOR_DARK_BLUE = 1 -Const COLOR_DARK_GREEN = 2 -Const COLOR_DARK_CYAN = 3 -Const COLOR_DARK_RED = 4 -Const COLOR_DARK_MAGENTA = 5 -Const COLOR_DARK_ORANGE = 6 -Const COLOR_DARK_YELLOW = 6 -Const COLOR_DARK_WHITE = 7 -Const COLOR_BRIGHT_BLACK = 8 -Const COLOR_BRIGHT_BLUE = 9 -Const COLOR_BRIGHT_GREEN = 10 -Const COLOR_BRIGHT_CYAN = 11 -Const COLOR_BRIGHT_RED = 12 -Const COLOR_BRIGHT_MAGENTA = 13 -Const COLOR_BRIGHT_ORANGE = 14 -Const COLOR_BRIGHT_YELLOW = 14 -Const COLOR_BRIGHT_WHITE = 15 - -Const COLOR_FOREGROUND_DEFAULT = COLOR_DARK_WHITE -Const COLOR_BACKGROUND_DEFAULT = COLOR_DARK_BLACK - -Dim Shared ScreenColor As Integer -ScreenColor = COLOR_FOREGROUND_DEFAULT - -Type MenuStyle - idWidth As Integer - labelWidth As Integer - valueWidth As Integer - screenWidth As Integer - randomItemName As String - randomItemId As Integer - randomItemColor as integer - cancelItemName As String - cancelItemId As Integer - cancelItemColor as integer - idLabelSeparator As String - labelValueSeparator As String - menuItemSpacer As String - showRandom As Integer - showCancel as integer - useColors As Integer -End Type - -Type MenuItem - label As String - id As Integer - value As Integer - color As Integer - isVisible As Integer - includeInRandom as integer -End Type - -' Each set of these index constants "NAME_*" should start at 1 and go up to NAMES_COUNT without leaving any holes. -' This also goes the same for sub indexes like NAME_GROUP_SUBGROUP_* each NAME_GROUP_* set should have -GetNumNamesInGroup(NAME_GROUP) items. Const CLAN_ANARCH = 1 Const CLAN_ASSAMITE = 2 Const CLAN_BAALI = 3 Const -CLAN_BRUJAH = 4 Const CLAN_CAITIFF = 5 Const CLAN_CAPPADOCIAN = 6 Const CLAN_GANGREL = 7 Const CLAN_GIOVANNI = 8 Const -CLAN_INCONNU = 9 Const CLAN_LASOMBRA = 10 Const CLAN_MALKAVIAN = 11 Const CLAN_NOSFERATU = 12 Const CLAN_RAVANOS = 13 -Const CLAN_SETTITE = 14 -Const CLAN_TREMERE = 15 -Const CLAN_TOREADOR = 16 -Const CLAN_TZISMICE = 17 -Const CLAN_VENTRUE = 18 -Const CLANS_COUNT = 18 -Dim Shared Clans(1 To CLANS_COUNT) As String - -Const ARCHETYPE_ARCHITECT = 1 -Const ARCHETYPE_AUTOCRAT = 2 -Const ARCHETYPE_BARBARIAN = 3 -Const ARCHETYPE_BON_VIVANT = 4 -Const ARCHETYPE_BRAVO = 5 -Const ARCHETYPE_CAREGIVER = 6 -Const ARCHETYPE_CARETAKER = 7 -Const ARCHETYPE_CELEBRANT = 8 -Const ARCHETYPE_CHILD = 9 -Const ARCHETYPE_CONFORMIST = 10 -Const ARCHETYPE_CONNIVER = 11 -Const ARCHETYPE_CURMUDGEON = 12 -Const ARCHETYPE_DEFENDER = 13 -Const ARCHETYPE_DEVIANT = 14 -Const ARCHETYPE_DIRECTOR = 15 -Const ARCHETYPE_FANATIC = 16 -Const ARCHETYPE_GALLANT = 17 -Const ARCHETYPE_INNOVATOR = 18 -Const ARCHETYPE_JESTER = 19 -Const ARCHETYPE_JUDGE = 20 -Const ARCHETYPE_LONER = 21 -Const ARCHETYPE_MARTYR = 22 -Const ARCHETYPE_MONSTER = 23 -Const ARCHETYPE_PENITENT = 24 -Const ARCHETYPE_REBEL = 25 -Const ARCHETYPE_ROGUE = 26 -Const ARCHETYPE_SURVIVOR = 27 -Const ARCHETYPE_TRADITIONALIST = 28 -Const ARCHETYPE_TYRANT = 29 -Const ARCHETYPE_VISIONARY = 30 -Const ARCHETYPES_COUNT = 30 -Dim Shared Archetypes(1 To ARCHETYPES_COUNT) As String - -Const DISCIPLINE_POINTS = 3 -Const DISCIPLINE_ANIMALISM = 1 -Const DISCIPLINE_AUSPEX = 2 -Const DISCIPLINE_BARDO = 3 -Const DISCIPLINE_CELERITY = 4 -Const DISCIPLINE_CHIMESTRY = 5 -Const DISCIPLINE_DEMENTATION = 6 -Const DISCIPLINE_DOMINATE = 7 -Const DISCIPLINE_FORTITUDE = 8 -Const DISCIPLINE_MELPOMINEE = 9 -Const DISCIPLINE_MORTIS = 10 -Const DISCIPLINE_MYTHERCERIA = 11 -Const DISCIPLINE_NECROMANCY = 12 -Const DISCIPLINE_OBEAH = 13 -Const DISCIPLINE_OBFUSCATE = 14 -Const DISCIPLINE_OBTENEBRATION = 15 -Const DISCIPLINE_POTENCE = 16 -Const DISCIPLINE_PRESENCE = 17 -Const DISCIPLINE_PROTEAN = 18 -Const DISCIPLINE_QUIETUS = 19 -Const DISCIPLINE_SERPENTIS = 20 -Const DISCIPLINE_SPIRITUS = 21 -Const DISCIPLINE_THANANTOSIS = 22 -Const DISCIPLINE_THAUMATURGY = 23 -Const DISCIPLINE_VICISSITUDE = 24 -Const DISCIPLINES_COUNT = 24 -Dim Shared Disciplines(1 To DISCIPLINES_COUNT) As String - -' Virtues -Const VIRTUE_POINTS = 7 -Const VIRTUE_SELF_CONTROL = 1 -Const VIRTUE_COURAGE = 2 -Const VIRTUE_CONSCIENCE = 3 -Const VIRTUES_COUNT = 3 -Dim Shared Virtues(1 To VIRTUES_COUNT) As String - -' These should probably be renamed like PHYSICAL_ATTRIBUTE_STRENGTH instead. -Const ATTRIBUTE_STRENGTH = 1 -Const ATTRIBUTE_DEXTERITY = 2 -Const ATTRIBUTE_STAMINA = 3 -Const PHYSICAL_ATTRIBUTES_COUNT = 3 -Dim Shared PhysicalAttributes(1 To PHYSICAL_ATTRIBUTES_COUNT) As String -Dim Shared PhysicalAttributeAbbreviations(1 To PHYSICAL_ATTRIBUTES_COUNT) As String - -Const ATTRIBUTE_CHARISMA = 1 -Const ATTRIBUTE_MANIPULATION = 2 -Const ATTRIBUTE_APPEARANCE = 3 -Const SOCIAL_ATTRIBUTES_COUNT = 3 -Dim Shared SocialAttributes(1 To SOCIAL_ATTRIBUTES_COUNT) As String -Dim Shared SocialAttributeAbbreviations(1 To SOCIAL_ATTRIBUTES_COUNT) As String - -Const ATTRIBUTE_INTELLIGENCE = 1 -Const ATTRIBUTE_PERCEPTION = 2 -Const ATTRIBUTE_WITS = 3 -Const MENTAL_ATTRIBUTES_COUNT = 3 -Dim Shared MentalAttributes(1 To MENTAL_ATTRIBUTES_COUNT) As String -Dim Shared MentalAttributeAbbreviations(1 To MENTAL_ATTRIBUTES_COUNT) As String - -Const ATTRIBUTE_GROUP_PHYSICAL = 1 -Const ATTRIBUTE_GROUP_SOCIAL = 2 -Const ATTRIBUTE_GROUP_MENTAL = 3 -Const ATTRIBUTE_GROUPS_COUNT = 3 -Dim Shared AttributeGroups(1 To ATTRIBUTE_GROUPS_COUNT) As String - -Const ABILITY_GROUP_TALENTS = 1 -Const ABILITY_GROUP_SKILLS = 2 -Const ABILITY_GROUP_KNOWLEDGES = 3 -Const ABILITY_GROUPS_COUNT = 3 -Dim Shared AbilityGroups(1 To ABILITY_GROUPS_COUNT) As String - -Const TALENT_ACTING = 1 -Const TALENT_ALERTNESS = 2 -Const TALENT_ATHLETICS = 3 -Const TALENT_BRAWL = 4 -Const TALENT_DODGE = 5 -Const TALENT_EMPATHY = 6 -Const TALENT_INTIMIDATION = 7 -Const TALENT_LEADERSHIP = 8 -Const TALENT_STREETWISE = 9 -Const TALENT_SUBTERFUGE = 10 -Const TALENTS_COUNT = 10 -Dim Shared Talents(1 To TALENTS_COUNT) As String - -Const SKILL_ANIMAL_KEN = 1 -Const SKILL_DRIVE = 2 -Const SKILL_ETIQUETTE = 3 -Const SKILL_FIREARMS = 4 -Const SKILL_MELEE = 5 -Const SKILL_MUSIC = 6 -Const SKILL_REPAIR = 7 -Const SKILL_SECURITY = 8 -Const SKILL_STEALTH = 9 -Const SKILL_SURVIVAL = 10 -Const SKILLS_COUNT = 10 -Dim Shared Skills(1 To SKILLS_COUNT) As String - -Const KNOWLEDGE_BUREAUCRACY = 1 -Const KNOWLEDGE_COMPUTER = 2 -Const KNOWLEDGE_FINANCE = 3 -Const KNOWLEDGE_INVESTIGATION = 4 -Const KNOWLEDGE_LAW = 5 -Const KNOWLEDGE_LINGUISTICS = 6 -Const KNOWLEDGE_MEDICINE = 7 -Const KNOWLEDGE_OCCULT = 8 -Const KNOWLEDGE_POLITICS = 9 -Const KNOWLEDGE_SCIENCE = 10 -Const KNOWLEDGES_COUNT = 10 -Dim Shared Knowledges(1 To KNOWLEDGES_COUNT) As String - -Const BACKGROUND_POINTS = 5 -Const BACKGROUND_ALLIES = 1 -Const BACKGROUND_CONTACTS = 2 -Const BACKGROUND_FAME = 3 -Const BACKGROUND_GENERATION = 4 -Const BACKGROUND_HERD = 5 -Const BACKGROUND_INFLUENCE = 6 -Const BACKGROUND_MENTOR = 7 -Const BACKGROUND_RESOURCES = 8 -Const BACKGROUND_RETAINERS = 9 -Const BACKGROUND_STATUS = 10 -Const BACKGROUNDS_COUNT = 10 -Dim Shared Backgrounds(1 To BACKGROUNDS_COUNT) As String - -Const GENDER_MALE = 1 -Const GENDER_FEMALE = 2 -Const GENDER_TRANS_MALE = 3 -Const GENDER_TRANS_FEMALE = 4 -Const GENDER_NON_BINARY = 5 -Const GENDERS_COUNT = 5 -Dim Shared Genders(1 To GENDERS_COUNT) As String - -Const DERANGEMENTS_COUNT = 10 -Const DERANGEMENT_ID_AMNESIA = 1 -Const DERANGEMENT_ID_DELUSIONS_OF_GRANDEUR = 2 -Const DERANGEMENT_ID_FANTASY = 3 -Const DERANGEMENT_ID_MANIC_DEPRESSION = 4 -Const DERANGEMENT_ID_MULTIPLE_PERSONALITIES = 5 -Const DERANGEMENT_ID_OBSESSION = 6 -Const DERANGEMENT_ID_OVERCOMPENSATION = 7 -Const DERANGEMENT_ID_PARANOIA = 8 -Const DERANGEMENT_ID_PERFECTION = 9 -Const DERANGEMENT_ID_REGRESSION = 10 -Dim Shared Derangements(1 To DERANGEMENTS_COUNT) As DerangementType - -Const DERANGEMENT_COLOR_AMNESIA = COLOR_DARK_RED -Const DERANGEMENT_COLOR_DELUSIONS_OF_GRANDEUR = COLOR_DARK_MAGENTA -Const DERANGEMENT_COLOR_FANTASY = COLOR_DARK_ORANGE -Const DERANGEMENT_COLOR_MANIC_DEPRESSION = COLOR_DARK_WHITE -Const DERANGEMENT_COLOR_MULTIPLE_PERSONALITIES = COLOR_DARK_BLUE -Const DERANGEMENT_COLOR_OBSESSION = COLOR_BRIGHT_GREEN -Const DERANGEMENT_COLOR_OVERCOMPENSATION = COLOR_BRIGHT_CYAN -Const DERANGEMENT_COLOR_PARANOIA = COLOR_BRIGHT_RED -Const DERANGEMENT_COLOR_PERFECTION = COLOR_BRIGHT_MAGENTA -Const DERANGEMENT_COLOR_REGRESSION = COLOR_BRIGHT_YELLOW -Dim Shared DerangementColors(1 To DERANGEMENTS_COUNT) As Integer - -Dim Shared DerangementLabels(1 To DERANGEMENTS_COUNT) As String -Const DERANGEMENT_LABEL_AMNESIA = "Amnesia" -Const DERANGEMENT_LABEL_DELUSIONS_OF_GRANDEUR = "Delusions of Grandeur" -Const DERANGEMENT_LABEL_FANTASY = "Fantasy" -Const DERANGEMENT_LABEL_MANIC_DEPRESSION = "Manic-Depression" -Const DERANGEMENT_LABEL_MULTIPLE_PERSONALITIES = "Multiple Personalities" -Const DERANGEMENT_LABEL_OBSESSION = "Obsession" -Const DERANGEMENT_LABEL_OVERCOMPENSATION = "Overcompensation" -Const DERANGEMENT_LABEL_PARANOIA = "Paranoia" -Const DERANGEMENT_LABEL_PERFECTION = "Perfection" -Const DERANGEMENT_LABEL_REGRESSION = "Regression" - -Dim Shared DerangementDescriptions(1 To DERANGEMENTS_COUNT) As String -Const DERANGEMENT_DESCRIPTION_AMNESIA = "You forget a segment of your past. Additionally in some cases a character can -forget abilities and be unable to use them for the duration." Const DERANGEMENT_DESCRIPTION_DELUSIONS_OF_GRA = "You -imagine you are better than you are." Const DERANGEMENT_DESCRIPTION_FANTASY = "You enter a self-created world where you -are the forgotten hero." Const DERANGEMENT_DESCRIPTION_MANIC_DEPRESSION = "You sink into deep and fitful depressions, -showing no interest in anything which used to captivate your interests. You will go along with others rather than use -the energy to resist. Occasional fits of great energy grab hold of you, and you will work for hours or even days on your -projects. During this time you will resist even the need for sleep as you burn up blood and Willpower on your schemes." -Const DERANGEMENT_DESCRIPTION_MULTIPLE_PERSONA = "You possess a number of new personalities. You have amore than one -Mature, and will switch between them. Thus you regain Willpower points in defferent ways at defferent times" Const -DERANGEMENT_DESCRIPTION_OBSESSION = "You become obsessed with some interest or fetish." Const -DERANGEMENT_DESCRIPTION_OVERCOMPENSATION = "You make up for your moral weaknesses by playing up your strengths to an -extreme. You don't think you can frenzy and won't stop it." Const DERANGEMENT_DESCRIPTION_PARANOIA = "You are convinced -that you are being hunted. You hold even your closest Friends under suspicion." Const DERANGEMENT_DESCRIPTION_PERFECTION -= "All your energy is directed toward preventing anything from going wong. When it does you must make a self-control -roll or frenzy." Const DERANGEMENT_DESCRIPTION_REGRESSION = "You become childlike retreating to an earlier time when -less was expected of you Willpower is regained inthe way a Child's is." - -Const FREEBIES_COUNT = 7 -Dim Shared FreebieCosts(1 To FREEBIES_COUNT) As Integer -Dim Shared FreebieLabels(1 To FREEBIES_COUNT) As String -Dim Shared FreebieNames(1 to FREEBIES_COUNT) As String -Dim Shared Freebies(1 To FREEBIES_COUNT) As FreebieType -Const FREEBIE_DISCIPLINE_ID = 1 -Const FREEBIE_DISCIPLINE_COST = 7 -Const FREEBIE_DISCIPLINE_NAME = "Discipline" -Const FREEBIE_DISCIPLINE_LABEL = "Add a discipline dot 7 points" - -Const FREEBIE_ATTRIBUTE_ID = 2 -Const FREEBIE_ATTRIBUTE_COST = 5 -Const FREEBIE_ATTRIBUTE_NAME = "Attribute" -Const FREEBIE_ATTRIBUTE_LABEL = "Add an attribute dot 5 points" - -Const FREEBIE_ABILITY_ID = 3 -Const FREEBIE_ABILITY_COST = 2 -Const FREEBIE_ABILITY_NAME = "Ability" -Const FREEBIE_ABILITY_LABEL = "Add an ability dot 2 points" - -Const FREEBIE_VIRTUE_ID = 4 -Const FREEBIE_VIRTUE_COST = 2 -Const FREEBIE_VIRTUE_NAME = "Virtue" -Const FREEBIE_VIRTUE_LABEL = "Add a virtue dot 2 points" - -' TODO: Make this configurable for VtDA -Const FREEBIE_HUMANITY_ID = 5 -Const FREEBIE_HUMANITY_COST = 1 -Const FREEBIE_HUMANITY_NAME = "Humanity" -Const FREEBIE_HUMANITY_LABEL = "Add a humanity dot 1 point" - -Const FREEBIE_BACKGROUND_ID = 6 -Const FREEBIE_BACKGROUND_COST = 1 -Const FREEBIE_BACKGROUND_NAME = "Background" -Const FREEBIE_BACKGROUND_LABEL = "Add a background dot 1 point" - -Const FREEBIE_SHOW_CHARACTER_SHEET_ID = 7 -Const FREEBIE_SHOW_CHARACTER_SHEET_COST = 0 -Const FREEBIE_SHOW_CHARACTER_SHEET_NAME = "Show character sheet" -Const FREEBIE_SHOW_CHARACTER_SHEET_LABEL = FREEBIE_SHOW_CHARACTER_SHEET_NAME - -Type CharacterType - name As String - player As String - chronicle As String - haven As String - concept As String - age As String - gender As Integer - clan As Integer - nature As Integer - demeanor As Integer - conscience As Integer - selfControl As Integer - courage As Integer - generation As Integer - roadName As String - roadValue As Integer - willpower As Integer - bloodPool As Integer - derangementId As Integer - freebiePoints As Integer - ' Disciplines - discipline_animalism As Integer - discipline_auspex As Integer - discipline_bardo As Integer - discipline_celerity As Integer - discipline_chimestry As Integer - discipline_dementation As Integer - discipline_dominate As Integer - discipline_fortitude As Integer - discipline_melpominee As Integer - discipline_mortis As Integer - discipline_mytherceria As Integer - discipline_necromancy As Integer - discipline_obeah As Integer - discipline_obfuscate As Integer - discipline_obtenebration As Integer - discipline_potence As Integer - discipline_presence As Integer - discipline_protean As Integer - discipline_quietus As Integer - discipline_serpentis As Integer - discipline_spiritus As Integer - discipline_thanantosis As Integer - discipline_thaumaturgy As Integer - discipline_vicissitude As Integer - ' Attributes - attr_strength As Integer - attr_dexterity As Integer - attr_stamina As Integer - attr_appearance As Integer - attr_charisma As Integer - attr_manipulation As Integer - attr_intelligence As Integer - attr_perception As Integer - attr_wits As Integer - ' Talents - talent_acting As Integer - talent_alertness As Integer - talent_athletics As Integer - talent_brawl As Integer - talent_dodge As Integer - talent_empathy As Integer - talent_intimidation As Integer - talent_leadership As Integer - talent_streetwise As Integer - talent_subterfuge As Integer - ' Skills - skill_animalKen As Integer - skill_drive As Integer - skill_etiquette As Integer - skill_firearms As Integer - skill_melee As Integer - skill_music As Integer - skill_repair As Integer - skill_security As Integer - skill_stealth As Integer - skill_survival As Integer - ' Knowledges - knowledge_bureaucracy As Integer - knowledge_computer As Integer - knowledge_finance As Integer - knowledge_investigation As Integer - knowledge_law As Integer - knowledge_linguistics As Integer - knowledge_medicine As Integer - knowledge_occult As Integer - knowledge_politics As Integer - knowledge_science As Integer - ' Backgrounds - background_allies As Integer - background_contacts As Integer - background_fame As Integer - background_generation As Integer - background_herd As Integer - background_influence As Integer - background_mentor As Integer - background_resources As Integer - background_retainers As Integer - background_status As Integer -End Type - -Type DerangementType - id As Integer - label As String - description As String - textColor As Integer -End Type - -Type FreebieType - id As Integer - cost As Integer - name As String * 32 - label As String * 32 -End Type - -Const RANK_PRIMARY = 1 -Const RANK_PRIMARY_LABEL = "Primary" -Const RANK_SECONDARY = 2 -Const RANK_SECONDARY_LABEL = "Secondary" -Const RANK_TERTIARY = 3 -Const RANK_TERTIARY_LABEL = "Tertiary" -Const RANKS_COUNT = 3 - -Type RankType - id As Integer - label As String -End Type -Dim Shared Ranks(1 To RANKS_COUNT) As RankType - -Type AbilityType - id As Integer - singular As String - plural As String -End Type - -Const ABILITY_TALENTS_ID = 1 -Const ABILITY_TALENTS_SINGULAR = "Talent" -Const ABILITY_TALENTS_PLURAL = "Talents" -Const ABILITY_SKILLS_ID = 2 -Const ABILITY_SKILLS_SINGULAR = "Skill" -Const ABILITY_SKILLS_PLURAL = "Skills" -Const ABILITY_KNOWLEDGES_ID = 3 -Const ABILITY_KNOWLEDGES_SINGULAR = "Knowledge" -Const ABILITY_KNOWLEDGES_PLURAL = "Knowledges" -Const ABILITIES_COUNT = 3 -Dim Shared Abilities(1 To ABILITIES_COUNT) As AbilityType - -Call InitializeMemory - -' Run "tests" at startup. Uncomment the end instruction to see the output and not run the rest of the program. -Call Test -Call SplashScreen -Call MainMenu - -' This initializes shared variables. -Sub InitializeMemory - Call Initialize_Character_Lib - - Dim rank As RankType - Call NewRank(rank, RANK_PRIMARY, RANK_PRIMARY_LABEL) - Ranks(RANK_PRIMARY) = rank - Call NewRank(rank, RANK_SECONDARY, RANK_SECONDARY_LABEL) - Ranks(RANK_SECONDARY) = rank - Call NewRank(rank, RANK_TERTIARY, RANK_TERTIARY_LABEL) - Ranks(RANK_TERTIARY) = rank - - Dim ability As AbilityType - Call NewAbility(ability, ABILITY_TALENTS_ID, ABILITY_TALENTS_SINGULAR, ABILITY_TALENTS_PLURAL) - Abilities(ABILITY_TALENTS_ID) = ability - Call NewAbility(ability, ABILITY_SKILLS_ID, ABILITY_SKILLS_SINGULAR, ABILITY_SKILLS_PLURAL) - Abilities(ABILITY_SKILLS_ID) = ability - Call NewAbility(ability, ABILITY_KNOWLEDGES_ID, ABILITY_SKILLS_SINGULAR, ABILITY_SKILLS_PLURAL) - Abilities(ABILITY_KNOWLEDGES_ID) = ability -End Sub - -Sub NewAbility (ability As AbilityType, id As Integer, singular As String, plural As String) - ability.id = id - ability.singular = singular - ability.plural = plural -End Sub - -Sub NewRank (rank As RankType, id As Integer, label As String) - rank.id = id - rank.label = label -End Sub - -Sub SplashScreen - ' Splash screen - MaybeCls - ' " " - Print "Welcome to Tom's Storyteller's Best Friend. This is a program that is meant to" - Print "aid storytellers in running Vampire: the Masquerade Chronicles and Vampire: the" - Print "Dark Ages Chronicles. This program could aid in running campaigns for other" - Print "role-playing games especially those from White Wolf(tm). If you would like" - Print "anything added please open a github issue. https://github.com/headhunter45/sbf" - Print " Press any key to continue" - While InKey$ = "" - Wend -End Sub - -Sub MainMenu - ' Main menu - choice = 0 - Do - MaybeCls - Print "╔══════════════════════════════════════════════════════════════════════════════╗" - Print "║ What are you going to do? ║" - Print "║ 1 = Character Generator ║" - Print "║ 2 = Character Generator for Dummies ║" - Print "║ 3 = Combat Computer ║" - Print "║ 4 = Dice Roller ║" - Print "║ 5 = Random Character Generator ║" - Print "║ 6 = ║" - Print "║ 7 = Vehicle Generator ║" - Print "║ ║" - Print "║ ║" - Print "║ ║" - Print "║ ║" - Print "║ ║" - Print "║ ║" - Print "║ ║" - Print "║ ║" - Print "║ ║" - Print "║ ║" - Print "║ ║" - Print "║ 0 = End ║" - Print "║ ║" - Print "╚══════════════════════════════════════════════════════════════════════════════╝" - choice = GetChoice(0, 7) - Select Case choice - Case 1 - CharacterGenerator - Case 2 - CharacterGeneratorForDummies - Case 3 - CombatComputer - Case 4 - DiceRoller - Case 5 - RandomCharacterGenerator - Case 7 - VehicleGenerator - End Select - Loop Until choice = 0 -End Sub - ' This sub is not called. It is here so it can be copied whenever I need to make a new bordered screen. Sub BlankScreen Print "╔══════════════════════════════════════════════════════════════════════════════╗" @@ -634,423 +43,6 @@ Sub BlankScreen Print "╚══════════════════════════════════════════════════════════════════════════════╝" End Sub -Function GetChoice (min As Integer, max As Integer) - Dim choice - Do - Input choice - Loop Until choice <= max And choice >= min - GetChoice = choice -End Function - -Function GetMenuChoice (items() As MenuItem, style As MenuStyle, count As Integer) - ' Only allow random id or an id from a visible menuitem. - choice = -1 - acceptChoice = FALSE - Do - Input choice - If style.showRandom And choice = style.randomItemId Then acceptChoice = TRUE - If style.showCancel And choice = style.cancelItemId Then acceptChoice = TRUE - For i = 1 To count - If choice = items(i).id And items(i).isVisible Then - acceptChoice = TRUE - Exit For - End If - Next - Loop Until acceptChoice - GetMenuChoice = choice -End Function - -Function GetRandomInt (min As Integer, max As Integer) - GetRandomInt = Int(Rnd * (max - min + 1)) + min -End Function - -Function MaxI (val1 As Integer, val2 As Integer) - If (val1 > val2) Then - MaxI = val1 - Else - MaxI = val2 - End If -End Function - -Function ChooseStringId (labels() As String, style As MenuStyle, count As Integer, prompt As String) - MaybeCls - ReDim mnuItems(1 To count) As MenuItem - Call BuildMenu(mnuItems(), labels(), count) - Call AdjustMenuStyle(style, mnuItems(), count, TRUE) - Print prompt - Call PrintMenu(mnuItems(), count, style) - choice = GetMenuChoice(mnuItems(), style, count) - If choice = style.randomItemId Then choice = GetRandomMenuItemId(mnuItems(), count) - ChooseStringId = choice -End Function - -Function ChooseStringIdWithValues (labels() As String, values() As Integer, style As MenuStyle, count As Integer, prompt -As String) MaybeCls Dim mnuItems(1 To count) As MenuItem Call BuildMenuWithValues(mnuItems(), labels(), values(), count) - Call AdjustMenuStyle(style, mnuItems(), count, FALSE) - Print prompt - Call PrintMenu(mnuItems(), count, style) - choice = GetMenuChoice(mnuItems(), style, count) - If choice = style.randomItemId Then choice = GetRandomMenuItemId(mnuItems(), count) - ChooseStringIdWithValues = choice -End Function - -Function ChooseStringIdWithColors (labels() As String, colors() As Integer, style As MenuStyle, prompt As String) - MaybeCls - ' Check array bounds - If LBound(labels) <> 1 Or LBound(colors) <> 1 Or UBound(labels) <> UBound(colors) Then - ChooseStringIdWithColors = -1 - End - End If - - count = UBound(labels) - Dim mnuItems(1 To count) As MenuItem - Call BuildMenuWithColors(mnuItems(), labels(), colors()) - Call AdjustMenuStyle(style, mnuItems(), count, TRUE) - Print prompt - Call PrintMenu(mnuItems(), count, style) - choice = GetMenuChoice(mnuItems(), style, count) - If choice = style.randomItemId Then choice = GetRandomMenuItemId(mnuItems(), count) - ChooseStringIdWithColors = choice -End Function - -Function ChooseMenuItemId (items() As MenuItem, style As MenuStyle, count As Integer, prompt As String, ignoreValue As -Integer) MaybeCls Call AdjustMenuStyle(style, items(), count, ignoreValue) Print prompt Call PrintMenu(items(), count, -style) choice = GetMenuChoice(items(), style, count) If choice = style.randomItemId Then choice = -GetRandomMenuItemId(items(), count) ChooseMenuItemId = choice End Function - -Sub CGGetHeader (ch As CharacterType) - MaybeCls - Dim ms As MenuStyle - Call NewMenuStyle(ms) - Input "What is the character's name? ", ch.name - Input "Who is the player? ", ch.player - Input "What chronicle is the character going to be used for? ", ch.chronicle - Input "What is the character's Haven? ", ch.haven - Input "What is the character's concept? ", ch.concept - Input "How old is the character? ", ch.age - ch.gender = ChooseStringId(Genders(), ms, GENDERS_COUNT, "What is the character's gender?") - ch.clan = ChooseStringId(Clans(), ms, CLANS_COUNT, "What clan is the character from?") - ch.nature = ChooseStringId(Archetypes(), ms, ARCHETYPES_COUNT, "What is the character's nature?") - ch.demeanor = ChooseStringId(Archetypes(), ms, ARCHETYPES_COUNT, "What is the character's demeanor?") -End Sub - -Sub CGGetDisciplines (ch As CharacterType) - ' Spend discipline points. - Dim ms As MenuStyle - Call NewMenuStyle(ms) - disciplinePoints = GetDisciplinePoints - Dim disciplineValues(1 To DISCIPLINES_COUNT) As Integer - While disciplinePoints > 0 - MaybeCls - Call FillDisciplines(ch, disciplineValues()) - discipline = ChooseStringIdWithValues(Disciplines(), disciplineValues(), ms, DISCIPLINES_COUNT, "Which -discipline do you want to spend 1 of your " + itos$(disciplinePoints) + " points on?") Call SetDiscipline(ch, -discipline, GetDiscipline(ch, discipline) + 1) disciplinePoints = disciplinePoints - 1 Wend End Sub - -Sub CGGetAttributes (ch As CharacterType) - Dim msWithoutValues As MenuStyle - Call NewMenuStyle(msWithoutValues) - Dim msWithValues As MenuStyle - Call NewMenuStyle(msWithValues) - Dim attributeRanks(1 To ATTRIBUTE_GROUPS_COUNT) As Integer - - ' Attribute groups menu (physical/social/mental) - Dim mnuAttributeGroups(1 To ATTRIBUTE_GROUPS_COUNT) As MenuItem - Dim mi As MenuItem - For i = 1 To ATTRIBUTE_GROUPS_COUNT - Call NewMenuItem(mi, AttributeGroups(i), i) - mnuAttributeGroups(i) = mi - Next - - ' Choose attribute group priorities. - groupSum = 0 - rankSum = 1 - For i = 1 To ATTRIBUTE_GROUPS_COUNT - 1 - nextGroup = ChooseMenuItemId(mnuAttributeGroups(), msWithoutValues, ATTRIBUTE_GROUPS_COUNT, "Choose your " + -LCase$(Ranks(i).label) + " attribute?", TRUE) mnuAttributeGroups(nextGroup).isVisible = FALSE attributeRanks(nextGroup) -= i rankSum = rankSum + i + 1 groupSum = groupSum + nextGroup Next ' General formula for last choice given 1 to count -based indexing is this ' (Sum from 1 to count) - (Sum of all previous choice IDs) ' -Sum(1..AllAttributesCount)-Sum(Choice[1]..Choice[AllAttributesCount-1]) lastGroup = rankSum - groupSum - attributeRanks(lastGroup) = ATTRIBUTE_GROUPS_COUNT - - ' Spend attribute points - For group = 1 To ATTRIBUTE_GROUPS_COUNT - count = GetNumAttributesInGroup(group) - ReDim attributes(1 To count) As String - Call FillAttributesInGroup(group, attributes()) - rank = attributeRanks(group) - ReDim values(1 To count) As Integer - For attrPoints = GetAttributePointsForRank(rank) To 1 Step -1 - Call FillAttributeValues(ch, values(), group) - attribute = ChooseStringIdWithValues(attributes(), values(), msWithValues, count, "Which " + -LCase$(AttributeGroups(group)) + " attribute do you want to spend 1 of your " + itos$(attrPoints) + " points on?") Call -SetAttributeValue(ch, group, attribute, GetAttributeValue(ch, group, attribute) + 1) Next Next End Sub - -Sub CGGetAbilities (ch As CharacterType) - Dim msWithoutValues As MenuStyle - Call NewMenuStyle(msWithoutValues) - Dim msWithValues As MenuStyle - Call NewMenuStyle(msWithValues) - Dim abilityRanks(1 To ABILITY_GROUPS_COUNT) As Integer - - ' Ability groups menu (talents/skills/knowledges) - Dim mnuAbilityGroups(1 To ABILITY_GROUPS_COUNT) As MenuItem - Dim mi As MenuItem - For i = 1 To ABILITY_GROUPS_COUNT - Call NewMenuItem(mi, AbilityGroups(i), i) - mnuAbilityGroups(i) = mi - Next - - ' Choose ability group priorities - groupSum = 0 - rankSum = 1 - For i = 1 To ABILITY_GROUPS_COUNT - 1 - nextAbility = ChooseMenuItemId(mnuAbilityGroups(), msWithoutValues, ABILITY_GROUPS_COUNT, "Choose your " + -LCase$(Ranks(i).label) + " ability?", TRUE) mnuAbilityGroups(nextAbility).isVisible = FALSE abilityRanks(nextAbility) = -i rankSum = rankSum + i + 1 groupSum = groupSum + nextAbility Next ' General formula for last choice given 1 to count -based indexing is this ' (Sum from 1 to count) - (Sum of all previous choice IDs) ' -Sum(1..AllAttributesCount)-Sum(Choice[1]..Choice[AllAttributesCount-1]) lastGroup = rankSum - groupSum - abilityRanks(lastGroup) = ABILITY_GROUPS_COUNT - - ' Spend ability points - For group = 1 To ABILITY_GROUPS_COUNT - count = GetNumItemsForAbilityGroup(group) - ReDim abilityNames(1 To count) As String - Call FillAbilitiesForAbilityGroup(group, abilityNames()) - rank = abilityRanks(group) - ReDim values(1 To count) As Integer - For abilityPoints = GetAbilityPointsForRank(rank) To 1 Step -1 - Call FillAbilityValues(ch, values(), group) - ability = ChooseStringIdWithValues(abilityNames(), values(), msWithValues, count, "Which " + -LCase$(Abilities(i).singular) + " would you like to spend 1 of your " + itos$(abilityPoints) + " points on?") Call -SetAbilityValue(ch, group, ability, GetAbilityValue(ch, group, ability) + 1) Next Next End Sub - -Sub CGGetBackgrounds (ch As CharacterType) - ' Spend background points - Dim ms As MenuStyle - Call NewMenuStyle(ms) - backgroundPoints = GetBackgroundPoints - Dim backgroundValues(1 To BACKGROUNDS_COUNT) As Integer - While backgroundPoints > 0 - MaybeCls - Call FillBackgrounds(ch, backgroundValues()) - background = ChooseStringIdWithValues(Backgrounds(), backgroundValues(), ms, BACKGROUNDS_COUNT, "Which -background do you want to spend 1 of your " + itos$(backgroundPoints) + " points on?") Call SetBackground(ch, -background, GetBackground(ch, background) + 1) backgroundPoints = backgroundPoints - 1 Wend End Sub - -Sub CGGetRoad (ch As CharacterType) - ch.roadName = "Humanity" -End Sub - -Sub CGSpendVirtuePoints (ch As CharacterType) - ' Spend virtue points - Dim ms As MenuStyle - Call NewMenuStyle(ms) - virtuePoints = GetVirtuePoints - - Dim values(1 To VIRTUES_COUNT) As Integer - While virtuePoints > 0 - Call FillVirtues(ch, values()) - virtue = ChooseStringIdWithValues(Virtues(), values(), ms, VIRTUES_COUNT, "Which virtue do you want to spend 1 -of your " + itos$(virtuePoints) + " points on?") Call SetVirtue(ch, virtue, GetVirtue(ch, virtue) + 1) virtuePoints = -virtuePoints - 1 Wend End Sub - -Sub CGGetDerangement (ch As CharacterType) - If ch.clan = CLAN_MALKAVIAN Then - ' If the clan is malkavian then pick a derangement. - Dim ms As MenuStyle - Call NewMenuStyle(ms) - ms.useColors = TRUE - - ch.derangementId = ChooseStringIdWithColors(DerangementLabels(), DerangementColors(), ms, "Which derangement do -you want?") End If End Sub - -Sub CGSpendFreebiePoints (ch As CharacterType) - freebiePoints = GetFreebiePoints(ch) - Dim ms As MenuStyle - Call NewMenuStyle(ms) - While (freebiePoints > 0) - MaybeCls - Call MaybePrint("freebiePoints = " + itos$(freebiePoints)) - ' Build the menu - ReDim availableFreebies(1 To FREEBIES_COUNT) As FreebieType - numAvailableFreebies = 0 - For index = 1 To FREEBIES_COUNT - If Freebies(index).cost <= freebiePoints Then - numAvailableFreebies = numAvailableFreebies + 1 - availableFreebies(numAvailableFreebies) = Freebies(index) - End If - Next - - ReDim menuItems(1 To numAvailableFreebies) As MenuItem - For index = 1 To numAvailableFreebies - Dim mi As MenuItem - Call NewMenuItem(mi, availableFreebies(index).label, availableFreebies(index).id) - If index = FREEBIE_SHOW_CHARACTER_SHEET_ID Then mi.includeInRandom = FALSE - menuItems(index) = mi - Next - - prompt$ = "You have " + itos$(freebiePoints) + " freebie points remaining what would you like to spend the -points on?" id = ChooseMenuItemId(menuItems(), ms, numAvailableFreebies, prompt$, TRUE) - - Select Case id - Case FREEBIE_DISCIPLINE_ID - Call CGSpendDisciplinePoint(ch) - Case FREEBIE_ATTRIBUTE_ID - Call CGSpendAttributePoint(ch) - Case FREEBIE_ABILITY_ID - Call CGSpendAbilityPoint(ch) - Case FREEBIE_VIRTUE_ID - Call CGSpendVirtuePoint(ch) - Case FREEBIE_HUMANITY_ID - Call CGSpendHumanityPoint(ch) - Case FREEBIE_BACKGROUND_ID - Call CGSpendBackgroundPoint(ch) - Case FREEBIE_SHOW_CHARACTER_SHEET_ID - Call ShowCharacterSheet(ch) - End Select - - freebiePoints = GetFreebiePoints(ch) - Call MaybePrint("Auspex: " + itos$(GetDiscipline(ch, DISCIPLINE_AUSPEX))) - Call MaybePrint("Strength: " + itos$(GetAttributeValue(ch, ATTRIBUTE_GROUP_PHYSICAL, ATTRIBUTE_STRENGTH))) - Call MaybePrint("Acting: " + itos$(GetAbilityValue(ch, ABILITY_TALENTS_ID, TALENT_ACTING))) - Call MaybePrint("Conscience: " + itos$(GetVirtue(ch, VIRTUE_CONSCIENCE))) - Call MaybePrint("Humanity: " + itos$(GetRoadValue(ch))) - Call MaybePrint("Generation (Background): " + itos$(GetBackground(ch, BACKGROUND_GENERATION))) - Call MaybePrint("Generation: " + itos$(GetGeneration(ch))) - Wend -End Sub - -Sub CGSpendDisciplinePoint (ch As CharacterType) - MaybeCls - Dim ms As MenuStyle - Call NewMenuStyle(ms) - ms.showCancel = TRUE - ms.cancelItemId = DISCIPLINES_COUNT + 1 - Dim disciplineValues(1 To DISCIPLINES_COUNT) As Integer - Call FillDisciplines(ch, disciplineValues()) - prompt$ = "Which discipline do you want to spend 1 of your " + itos$(disciplinePoints) + " points on?" - id = ChooseStringIdWithValues(Disciplines(), disciplineValues(), ms, DISCIPLINES_COUNT, prompt$) - If id <> ms.cancelItemId Then - Call SetDiscipline(ch, id, GetDiscipline(ch, id) + 1) - Call SetFreebiePoints(ch, GetFreebiePoints(ch) - FREEBIE_DISCIPLINE_COST) - End If -End Sub - -Type GroupedStatReference - id As Integer - groupIndex As Integer - itemIndex As Integer -End Type - -Sub NewGroupedStatReference (ref As GroupedStatReference, id As Integer, groupIndex As Integer, itemIndex As Integer) - ref.id = id - ref.groupIndex = groupIndex - ref.itemIndex = itemIndex -End Sub - -Sub CGSpendAttributePoint (ch As CharacterType) - MaybeCls - Dim ms As MenuStyle - Call NewMenuStyle(ms) - ms.showCancel = TRUE - numAttributes = 0 - Dim numAttributesInGroup(1 To ATTRIBUTE_GROUPS_COUNT) As Integer - - For attributeGroupIndex = 1 To ATTRIBUTE_GROUPS_COUNT - numAttributesInGroup(attributeGroupIndex) = GetNumAttributesInGroup(attributeGroupIndex) - numAttributes = numAttributes + numAttributesInGroup(attributeGroupIndex) - Next - - Dim attributes(1 To numAttributes) As GroupedStatReference - Dim labels(1 To numAttributes) As String - Dim values(1 To numAttributes) As Integer - - attributeIndex = 1 - For attributeGroupIndex = 1 To ATTRIBUTE_GROUPS_COUNT - For index = 1 To numAttributesInGroup(attributeGroupIndex) - Dim attribute As GroupedStatReference - Call NewGroupedStatReference(attribute, attributeIndex, attributeGroupIndex, index) - attributes(attributeIndex) = attribute - labels(attributeIndex) = GetAttributeName$(attributeGroupIndex, index) - values(attributeIndex) = GetAttributeValue(ch, attributeGroupIndex, index) - attributeIndex = attributeIndex + 1 - Next - Next - - ' TODO: Make this show values. - prompt$ = "Which attribute do you want to add one dot to?" - ms.cancelItemId = numAttributes + 1 - id = ChooseStringIdWithValues(labels(), values(), ms, numAttributes, prompt$) - If id <> ms.cancelItemId Then - Dim attr As GroupedStatReference - attr = attributes(id) - Call SetAttributeValue(ch, attr.groupIndex, attr.itemIndex, GetAttributeValue(ch, attr.groupIndex, -attr.itemIndex) + 1) Call SetFreebiePoints(ch, GetFreebiePoints(ch) - FREEBIE_ATTRIBUTE_COST) End If End Sub - -Sub CGSpendAbilityPoint (ch As CharacterType) - Dim ms As MenuStyle - Call NewMenuStyle(ms) - ms.showCancel = TRUE - done = FALSE - While Not done - MaybeCls - ms.cancelItemId = ABILITY_GROUPS_COUNT + 1 - abilityGroupIndex = ChooseStringId(AbilityGroups(), ms, ABILITY_GROUPS_COUNT, "What kind of ability would you -like to add 1 dot to?") If abilityGroupIndex = ms.cancelItemId Then Exit Sub - - numAbilities = GetNumItemsForAbilityGroup(abilityGroupIndex) - Dim labels(1 To numAbilities) As String - Call FillAbilitiesForAbilityGroup(abilityGroupIndex, labels()) - ms.cancelItemId = numAbilities + 1 - abilityIndex = ChooseStringId(labels(), ms, numAbilities, "What ability would you like to add 1 dot to?") - If abilityIndex <> ms.cancelItemId Then - Call SetAbilityValue(ch, abilityGroupIndex, abilityIndex, GetAbilityValue(ch, abilityGroupIndex, -abilityIndex) + 1) Call SetFreebiePoints(ch, GetFreebiePoints(ch) - FREEBIE_ABILITY_COST) done = TRUE End If Wend End -Sub - -Sub CGSpendVirtuePoint (ch As CharacterType) - Dim ms As MenuStyle - Call NewMenuStyle(ms) - ms.showCancel = TRUE - ms.cancelItemId = VIRTUES_COUNT + 1 - prompt$ = "What virtue would you like to add 1 dot to?" - id = ChooseStringId(Virtues(), ms, VIRTUES_COUNT, prompt$) - If id <> ms.cancelItemId Then - Call SetVirtue(ch, id, GetVirtue(ch, id) + 1) - Call SetFreebiePoints(ch, GetFreebiePoints(ch) - FREEBIE_ABILITY_COST) - End If -End Sub - -Sub CGSpendHumanityPoint (ch As CharacterType) - numLabels = 2 - Dim labels(1 To numLabels) As String - labels(1) = "Yes" - labels(2) = "No" - Dim ms As MenuStyle - Call NewMenuStyle(ms) - ms.showRandom = FALSE - prompt$ = "Are you sure you want to add a dot to " + GetRoadName$(ch) + "?" - id = ChooseStringId(labels(), ms, numLabels, prompt$) - If id = 1 Then - Call SetRoadValue(ch, GetRoadValue(ch) + 1) - Call SetFreebiePoints(ch, GetFreebiePoints(ch) - FREEBIE_HUMANITY_COST) - End If -End Sub - -Sub CGSpendBackgroundPoint (ch As CharacterType) - Dim ms As MenuStyle - Call NewMenuStyle(ms) - ms.showCancel = TRUE - ms.cancelItemId = BACKGROUNDS_COUNT + 1 - prompt$ = "Which background would you like to add 1 dot to?" - id = ChooseStringId(Backgrounds(), ms, BACKGROUNDS_COUNT, prompt$) - If id <> ms.cancelItemId Then - Call SetBackground(ch, id, GetBackground(ch, id) + 1) - Call SetFreebiePoints(ch, GetFreebiePoints(ch) - FREEBIE_BACKGROUND_COST) - End If -End Sub - Sub SaveCharacterSheet (ch As CharacterType) Call MaybePrint("TODO: Fill in SaveCharacterSheet") Call MaybePrint(ch.name) @@ -1213,12 +205,6 @@ Sub CharacterGenerator () Call ShowCharacterSheet(ch) End Sub -Sub ShowCharacterSheet (ch As CharacterType) - Dim disciplineValues(1 To DISCIPLINES_COUNT) As Integer - Call FillDisciplines(ch, disciplineValues()) - - Dim backgroundValues(1 To BACKGROUNDS_COUNT) As Integer - Call FillBackgrounds(ch, backgroundValues()) '... 0123456789 '160 áíóúñѪº¿⌐ @@ -1230,80 +216,6 @@ Sub ShowCharacterSheet (ch As CharacterType) '220 ▄▌▐▀αßΓπΣσσ '230 µτΦΘΩδ2∞φε∩ ' enquote forms s/^([╔║╚═╠].*[╗║╝╣])$/print "$1"/g - - Dim disciplineStrings(3) As String - disciplineStringsIndex = 0 - For index = 1 To DISCIPLINES_COUNT - If disciplineValues(index) > 0 Then - suffix$ = "" - If disciplineValues(index) > 1 Then - suffix$ = " x" + itos$(disciplineValues(index)) - End If - disciplineStrings(disciplineStringsIndex) = Disciplines(index) + suffix$ - disciplineStringsIndex = disciplineStringsIndex + 1 - End If - Next - - Dim backgroundStrings(5) As String - backgroundStringsIndex = 0 - For index = 1 To BACKGROUNDS_COUNT - If backgroundValues(index) > 0 Then - suffix$ = "" - If backgroundValues(index) > 1 Then - suffix$ = " x" + itos$(backgroundValues(index)) - End If - backgroundStrings$(backgroundStringsIndex) = Backgrounds(index) + suffix$ - backgroundStringsIndex = backgroundStringsIndex + 1 - End If - Next - Dim derangementStrings(5) As String - allDerangementsLine$ = GetAllDerangementsLine$(ch) - - Call MakeWrapLines(derangementStrings(), allDerangementsLine$, 37, 5) - - MaybeCls - Print "╔══════════════════════════════════════╦═══════════════════════════════════════╗" - Print "║ Name: " + MakeFitL$(ch.name, 30, " ") + " ║ Gender: " + MakeFitL$(Genders(ch.gender), 14, " ") + " -Generation: " + MakeFitR$(itos$(ch.generation), 2, " ") + " ║" Print "║ Clan: " + MakeFitL$(Clans(ch.clan), 30, " ") + " -║ Age: " + MakeFitL$(ch.age$, 32, " ") + " ║" Print "╠══════════════════════════════════════╣ Player: " + -MakeFitL$(ch.player$, 29, " ") + " ║" Print "║ Attributes ║ Chronicle: " + -MakeFitL$(ch.chronicle$, 26, " ") + " ║" Print "║ Physical Social Mental ║ Haven: " + MakeFitL$(ch.haven$, -30, " ") + " ║" Print "║ Str. " + MakeFitL$(itos$(ch.attr_strength), 7, " ") + " App. " + -MakeFitL$(itos$(ch.attr_appearance), 7, " ") + " Int. " + MakeFitL$(itos$(ch.attr_intelligence), 5, " ") + " ║ Concept: -" + MakeFitL$(ch.concept$, 28, " ") + " ║" Print "║ Dex. " + MakeFitL$(itos$(ch.attr_dexterity), 7, " ") + " Cha. " + -MakeFitL$(itos$(ch.attr_charisma), 7, " ") + " Per. " + MakeFitL$(itos$(ch.attr_perception), 5, " ") + " -╠═══════════════════════════════════════╣" Print "║ Sta. " + MakeFitL$(itos$(ch.attr_stamina), 7, " ") + " Man. " + -MakeFitL$(itos$(ch.attr_manipulation), 7, " ") + " Wit. " + MakeFitL$(itos$(ch.attr_wits), 5, " ") + " ║ Derangements: -║" Print "╠══════════════════════════════════════╣ " + derangementStrings(0) + " ║" Print "║ Disciplines: ║ " + -derangementStrings(1) + " ║" Print "║ " + MakeFitL$(disciplineStrings(0), 36, " ") + " ║ " + -MakeFitL$(derangementStrings(2), 37, "_") + " ║" Print "║ " + MakeFitL$(disciplineStrings(1), 36, " ") + " ║ " + -MakeFitL$(derangementStrings(3), 37, "_") + " ║" Print "║ " + MakeFitL$(disciplineStrings(2), 36, " ") + " ║ " + -MakeFitL$(derangementStrings(4), 37, "_") + " ║" Print -"╠══════════════════════════════════════╬═══════════════════════════════════════╣" Print "║ " + MakeFitL$(ch.roadName + -": " + itos$(ch.roadValue), 36, " ") + " ║ Nature: " + MakeFitL$(Archetypes(ch.nature), 29, " ") + " ║" Print "║ -Willpower: " + MakeFitL$(itos$(ch.willpower), 25, " ") + " ║ Demeanor: " + MakeFitL$(Archetypes(ch.demeanor), 27, " ") + -" ║" Print "╠══════════════════════════════════════╩═══════════════════════════════════════╣" Print "║ ║" Print "║ ║" - Print "║ ║" - Print "║ <> ║" - Print "╚══════════════════════════════════════════════════════════════════════════════╝" - Call PressAnyKeyToContinue - - Print "╔══════════════════════════════════════════════════════════════════════════════╗" - Print "║ " + MakeFitC$("Abilities", 76, " ") + " ║" - Print "║ " + MakeFitC$("Talents", 25, " ") + " " + MakeFitC$("Skills", 25, " ") + " " + MakeFitC$("Knowledges", 24, -" ") + " ║" For index = 1 To 10 Print "║ " + MakeFitC(MakeFitL$(Talents(index) + ":", 14, " ") + itos$(GetTalent(ch, -index)), 25, " ") + " " + MakeFitC(MakeFitL$(Skills(index) + ":", 14, " ") + itos$(GetSkill(ch, index)), 25, " ") + " " -+ MakeFitC(MakeFitL$(Knowledges(index) + ":", 14, " ") + itos$(GetKnowledge(ch, index)), 24, " ") + " ║" Next Print -"╠══════════════════════════════════════╦═══════════════════════════════════════╣" Print "║ Backgrounds: ║ Virtues: ║" - Print "║ " + MakeFitL$(backgroundStrings(0), 36, " ") + " ║ " + MakeFitB$("Conscience:", itos$(ch.conscience), 37, " -") + " ║" Print "║ " + MakeFitL$(backgroundStrings(1), 36, " ") + " ║ " + MakeFitB$("Self-Control:", -itos$(ch.selfControl), 37, " ") + " ║" Print "║ " + MakeFitL$(backgroundStrings(2), 36, " ") + " ║ " + -MakeFitB$("Courage:", itos$(ch.courage), 37, " ") + " ║" Print "║ " + MakeFitL$(backgroundStrings(3), 36, " ") + " ║ " + -MakeFitL$("", 37, " ") + " ║" Print "║ " + MakeFitL$(backgroundStrings(4), 36, " ") + " ║ " + MakeFitL$("", 37, " ") + " -║" Print "╠══════════════════════════════════════╩═══════════════════════════════════════╣" Print "║ <> ║" Print -"╚══════════════════════════════════════════════════════════════════════════════╝" Call PressAnyKeyToContinue End Sub - ' Simpler character generator with fewer questions and more things done randomly without asking. Sub CharacterGeneratorForDummies Call MaybePrint("CharacterGeneratorForDummies") @@ -1334,1320 +246,10 @@ End Sub ' Like the character generator but for vehicles. Much simpler with fewer questions. Prints a vehicle sheet when done. Never finished and crashes mid way through currently. Sub VehicleGenerator Call MaybePrint("VehicleGenerator") End Sub -Sub PressAnyKeyToContinue () - While InKey$ = "": Wend -End Sub - -' String functions -Function itos$ (num As Integer) - itos$ = LTrim$(Str$(num)) -End Function - -Function MakeFitL$ (text As String, length As Integer, pad As String) - MakeFitL = Left$(text + String$(length, pad), length) -End Function - -Function MakeFitC$ (text As String, length As Integer, pad As String) - TextLength = Len(text) - LeftPadLength = MaxI(0, length - TextLength) \ 2 - RightPadLength = MaxI(0, length - TextLength - LeftPadLength) - LeftPad$ = String$(LeftPadLength, pad) - RightPad$ = String$(RightPadLength, pad) - TotalChop = MaxI(0, TextLength - length) - LeftChop = TotalChop \ 2 + 1 - MakeFitC = LeftPad$ + Mid$(text, LeftChop, length) + RightPad$ -End Function - -Function MakeFitR$ (text As String, length As Integer, pad As String) - MakeFitR = Right$(String$(length, pad) + text, length) -End Function - -Function MakeFitB$ (prefix As String, suffix As String, length As Integer, pad As String) - MakeFitB$ = MakeFitL$(MakeFitL$(prefix, length - Len(suffix), pad) + suffix, length, pad) -End Function - -Function GetIndexOf (fullString As String, targetString As String, startIndex As Integer) - GetIndexOf = -1 - targetLength = Len(targetString) - If targetLength <= 0 Then - GetIndexOf = startIndex - Exit Function - End If - - position = startIndex + 1 - length = Len(fullString) - Do - currString$ = Mid$(fullString, position, targetLength) - position = position + 1 - Loop While position <= length And currString$ <> targetString - If currString$ = targetString Then GetIndexOf = position - 2 -End Function - -Function GetCharAt$ (text As String, index As Integer) - length = Len(text) - If length <= 0 Or index < 0 Or index >= length Then - GetCharAt$ = "" - Exit Function - End If - GetCharAt$ = Mid$(text, index + 1, 1) -End Function - -Function GetSubstring$ (text As String, start As Integer, length As Integer) - GetSubstring$ = Mid$(text, start + 1, length) -End Function - -Sub MakeWrapLines (lines() As String, text As String, maxWidth As Integer, maxLines As Integer) - ReDim lines(maxLines) As String - lineCount = 0 - thisLine$ = "" - nextChunk$ = "" - thisLineStartPosition = 0 - thisLineCurrentPosition = 0 - nextSpace = -1 - textLength = Len(text) - - While (lineCount < maxLines) - nextSpace = GetIndexOf(text, " ", thisLineCurrentPosition) - If nextSpace < 0 Then nextSpace = textLength - nextChunk$ = GetSubstring(text, thisLineCurrentPosition, nextSpace - thisLineCurrentPosition) - nextChunkLength = Len(nextChunk$) - If nextChunkLength > 0 Then - needsSpace = Len(thisLine$) > 0 - If needsSpace Then - thisLine$ = thisLine$ + " " - End If - thisLineLength = Len(thisLine$) - If nextChunkLength > maxWidth Then - nextChunk$ = GetSubstring(text, thisLineCurrentPosition, maxWidth - thisLineLength) - nextSpace = thisLineStartPosition + maxWidth - thisLine$ = thisLine$ + nextChunk$ - thisLineCurrentPosition = nextSpace - ElseIf thisLineLength + nextChunkLength > maxWidth Then - thisLine$ = MakeFitL$(thisLine$, maxWidth, " ") - Else - thisLine$ = thisLine$ + nextChunk$ - thisLineCurrentPosition = nextSpace + 1 - End If - thisLineLength = Len(thisLine$) - Else - thisLineCurrentPosition = nextSpace + 1 - End If - If thisLineLength >= maxWidth Or thisLineCurrentPosition > textLength Then - thisLine$ = MakeFitL$(thisLine$, maxWidth, "_") - lines(lineCount) = thisLine$ - lineCount = lineCount + 1 - thisLine$ = "" - thisLineLength = Len(thisLine$) - thisLineStartPosition = thisLineCurrentPosition - End If - Wend -End Sub - -Sub MaybeCls () - If Not isDebugging Then Cls -End Sub - Sub MaybePrint (message As String) If isDebugging Then Print message End Sub -Sub SetColor (c As Integer) - ScreenColor = c - Color c -End Sub - -Function GetColor () - GetColor = ScreenColor -End Function - -Sub PrintWithMaybeColor (message As String, textColor As Integer, useColors As Integer) - Dim oldColor As Integer - If useColors = TRUE Then - oldColor = GetColor - SetColor (textColor) - End If - Print message - If useColors = TRUE Then - SetColor (oldColor) - End If -End Sub - -Function GetRandomMenuItemId (items() As MenuItem, count As Integer) - numVisibleItems = 0 - Dim visibleItems(count) As Integer - For i = 1 To count - If items(i).isVisible and items(i).includeinrandom Then - visibleItems(numVisibleItems) = i - numVisibleItems = numVisibleItems + 1 - End If - Next - i = GetRandomInt(0, numVisibleItems - 1) - GetRandomMenuItemId = visibleItems(i) -End Function - -Sub BuildMenu (items() As MenuItem, labels() As String, count As Integer) - For i = 1 To count - Dim mi As MenuItem - Call NewMenuItem(mi, labels(i), i) - items(i) = mi - Next -End Sub - -Sub BuildMenuWithValues (items() As MenuItem, labels() As String, values() As Integer, count As Integer) - For i = 1 To count - Dim mi As MenuItem - Call NewMenuItemWithValue(mi, labels(i), i, values(i)) - items(i) = mi - Next -End Sub - -Sub BuildMenuWithColors (items() As MenuItem, labels() As String, colors() As Integer) - ' Check array bounds - If LBound(items) <> 1 Or LBound(colors) <> 1 Or UBound(items) <> UBound(colors) Then End - - count = UBound(items) - For i = 1 To count - Dim mi As MenuItem - Call NewMenuItemWithColor(mi, labels(i), colors(i), i) - items(i) = mi - Next -End Sub - -Sub AdjustMenuStyle (style As MenuStyle, items() As MenuItem, count As Integer, ignoreValue As Integer) - maxIdWidth = 0 - maxItemWidth = 0 - maxValueWidth = 0 - - For i = 1 To count - If items(i).isVisible Then - maxIdWidth = MaxI(maxIdWidth, Len(itos$(items(i).id))) - maxItemWidth = MaxI(maxItemWidth, Len(items(i).label + style.labelValueSeparator)) - maxValueWidth = MaxI(maxValueWidth, Len(itos$(items(i).value))) - End If - Next - If style.showRandom Then - maxIdWidth = MaxI(maxIdWidth, Len(itos$(style.randomItemId))) - maxItemWidth = MaxI(maxItemWidth, Len(style.randomItemName)) - End If - If style.showCancel Then - maxIdWidth = MaxI(maxIdWidth, Len(itos$(style.cancelItemId))) - maxItemWidth = MaxI(maxItemWidth, Len(style.cancelItemName)) - End If - style.idWidth = maxIdWidth - style.labelWidth = maxItemWidth - If Not ignoreValue Then style.valueWidth = maxValueWidth Else style.valueWidth = 0 -End Sub - -Sub PrintMenu (items() As MenuItem, count As Integer, style As MenuStyle) - Dim randomItem As MenuItem - Call NewMenuItemWithColor(randomItem, style.randomItemName, style.randomItemColor, style.randomItemId) - Dim cancelItem As MenuItem - Call NewMenuItemWithColor(cancelItem, style.cancelItemName, style.cancelItemColor, style.cancelItemId) - actualCount = count - If style.showCancel = TRUE Then actualCount = actualCount + 1 - If style.showRandom = TRUE Then actualCount = actualCount + 1 - If actualCount <= 10 Then - For i = 1 To count - If items(i).isVisible Then - title$ = GetTitle$(items(i), style) - Call PrintWithMaybeColor(title$, items(i).color, style.useColors) - End If - Next - If style.showCancel Then - cancelLabel$ = GetTitleWithoutValue$(cancelItem, style) - Call PrintWithMaybeColor(cancelLabel$, cancelItem.color, style.useColors) - End If - If style.showRandom Then - randomLabel$ = GetTitleWithoutValue$(randomItem, style) - Call PrintWithMaybeColor(randomLabel$, randomItem.color, style.useColors) - End If - Else - Dim emptyItem As MenuItem - Call NewMenuItem(emptyItem, "", 0) - itemWidth = Len(GetTitle$(emptyItem, style)) - itemsPerRow = style.screenWidth \ (itemWidth + Len(style.menuItemSpacer)) - columnWidth = style.screenWidth \ itemsPerRow - - column = 0 - For i = 1 To count - If items(i).isVisible Then - itemText$ = GetTitle$(items(i), style) - If column <> (itemsPerRow - 1) Then - If i <> count Or style.showRandom Then - textLength = Len(itemText$) - itemText$ = MakeFitL$(RTrim$(itemText$) + style.menuItemSpacer, textLength + -Len(style.menuItemSpacer), " ") End If End If label$ = MakeFitC$(itemText$, columnWidth, " ") Call -PrintWithMaybeColor(label$, items(i).color, style.useColors) End If column = (column + 1) Mod itemsPerRow If column = 0 -Then Print "" Next If style.showCancel Then cancelLabel$ = MakeFitC$(GetTitleWithoutValue$(cancelItem, style), -columnWidth, " ") Call PrintWithMaybeColor(cancelLabel$, cancelItem.color, style.useColors) End If If style.showRandom -Then randomLabel$ = MakeFitC$(GetTitleWithoutValue$(randomItem, style), columnWidth, " ") Call -PrintWithMaybeColor(randomLabel$, randomItem.color, style.useColors) End If End If End Sub - -Function GetTitle$ (mi As MenuItem, ms As MenuStyle) - id$ = itos$(mi.id) - label$ = mi.label - If ms.valueWidth > 0 Then label$ = label$ + ms.labelValueSeparator - value$ = itos$(mi.value) - GetTitle$ = MakeFitR$(id$, ms.idWidth, " ") + ms.idLabelSeparator + MakeFitL$(label$, ms.labelWidth, " ") + -MakeFitR$(value$, ms.valueWidth, " ") End Function - -Function GetTitleWithoutValue$ (mi As MenuItem, ms As MenuStyle) - GetTitleWithoutValue$ = MakeFitR$(itos$(mi.id), ms.idWidth, " ") + ms.idLabelSeparator + MakeFitL$(mi.label, -ms.labelWidth + ms.valueWidth + Len(ms.labelValueSeparator), " ") End Function - -Sub NewMenuStyle (ms As MenuStyle) - ms.idWidth = 0 - ms.labelWidth = 0 - ms.valueWidth = 0 - ms.screenWidth = 80 - ms.randomItemName = "Random" - ms.randomItemId = 0 - ms.randomItemColor = COLOR_FOREGROUND_DEFAULT - ms.cancelItemName = "Cancel" - ms.cancelItemId = -1 - ms.cancelItemColor = COLOR_FOREGROUND_DEFAULT - ms.idLabelSeparator = " = " - ms.labelValueSeparator = ": " - ms.menuItemSpacer = ", " - ms.showRandom = TRUE - ms.showCancel = false - ms.useColors = FALSE -End Sub - -Sub NewMenuItem (mi As MenuItem, label As String, id As Integer) - mi.id = id - mi.label = label - mi.value = 0 - mi.color = COLOR_DEFAULT - mi.isVisible = TRUE - mi.includeInRandom = true -End Sub - -Sub NewMenuItemWithValue (mi As MenuItem, label As String, id As Integer, value As Integer) - mi.id = id - mi.label = label - mi.value = value - mi.color = COLOR_DEFAULT - mi.isVisible = TRUE - mi.includeInRandom = true -End Sub - -Sub NewMenuItemWithColor (mi As MenuItem, label As String, textColor As Integer, id As Integer) - mi.id = id - mi.label = label - mi.value = 0 - mi.color = textColor - mi.isVisible = TRUE -End Sub - -$Debug -Sub Initialize_Character_Lib - ' For all of these lookup tables they should look something like this to know the mapping is correct - ' Names(NAME_ITEM1) = "Item1" - ' The index constants should start at 1 and go up to NAMES_COUNT without leaving any holes. - - ' Clans - Clans(CLAN_ANARCH) = "Anarch" - Clans(CLAN_ASSAMITE) = "Assamite" - Clans(CLAN_BAALI) = "Baali" - Clans(CLAN_BRUJAH) = "Brujah" - Clans(CLAN_CAITIFF) = "Caitiff" - Clans(CLAN_CAPPADOCIAN) = "Cappadocian" - Clans(CLAN_GANGREL) = "Gangrel" - Clans(CLAN_GIOVANNI) = "Giovanni" - Clans(CLAN_INCONNU) = "Inconnu" - Clans(CLAN_LASOMBRA) = "Lasombra" - Clans(CLAN_MALKAVIAN) = "Malkavian" - Clans(CLAN_NOSFERATU) = "Nosferatu" - Clans(CLAN_RAVANOS) = "Ravanos" - Clans(CLAN_SETTITE) = "Settite" - Clans(CLAN_TREMERE) = "Tremere" - Clans(CLAN_TOREADOR) = "Toreador" - Clans(CLAN_TZISMICE) = "Tzismice" - Clans(CLAN_VENTRUE) = "Ventrue" - - ' Archetypes - Archetypes(ARCHETYPE_ARCHITECT) = "Architect" - Archetypes(ARCHETYPE_AUTOCRAT) = "Autocrat" - Archetypes(ARCHETYPE_BARBARIAN) = "Barbarian" - Archetypes(ARCHETYPE_BON_VIVANT) = "Bon Vivant" - Archetypes(ARCHETYPE_BRAVO) = "Bravo" - Archetypes(ARCHETYPE_CAREGIVER) = "Caregiver" - Archetypes(ARCHETYPE_CARETAKER) = "Caretaker" - Archetypes(ARCHETYPE_CELEBRANT) = "Celebrant" - Archetypes(ARCHETYPE_CHILD) = "Child" - Archetypes(ARCHETYPE_CONFORMIST) = "Conformist" - Archetypes(ARCHETYPE_CONNIVER) = "Conniver" - Archetypes(ARCHETYPE_CURMUDGEON) = "Curmudgeon" - Archetypes(ARCHETYPE_DEFENDER) = "Defender" - Archetypes(ARCHETYPE_DEVIANT) = "Deviant" - Archetypes(ARCHETYPE_DIRECTOR) = "Director" - Archetypes(ARCHETYPE_FANATIC) = "Fanatic" - Archetypes(ARCHETYPE_GALLANT) = "Gallant" - Archetypes(ARCHETYPE_INNOVATOR) = "Innovator" - Archetypes(ARCHETYPE_JESTER) = "Jester" - Archetypes(ARCHETYPE_JUDGE) = "Judge" - Archetypes(ARCHETYPE_LONER) = "Loner" - Archetypes(ARCHETYPE_MARTYR) = "Martyr" - Archetypes(ARCHETYPE_MONSTER) = "Monster" - Archetypes(ARCHETYPE_PENITENT) = "Penitent" - Archetypes(ARCHETYPE_REBEL) = "Rebel" - Archetypes(ARCHETYPE_ROGUE) = "Rogue" - Archetypes(ARCHETYPE_SURVIVOR) = "Survivor" - Archetypes(ARCHETYPE_TRADITIONALIST) = "Traditionalist" - Archetypes(ARCHETYPE_TYRANT) = "Tyrant" - Archetypes(ARCHETYPE_VISIONARY) = "Visionary" - - ' Disciplines - Disciplines(DISCIPLINE_ANIMALISM) = "Animalism" - Disciplines(DISCIPLINE_AUSPEX) = "Auspex" - Disciplines(DISCIPLINE_BARDO) = "Bardo" - Disciplines(DISCIPLINE_CELERITY) = "Celerity" - Disciplines(DISCIPLINE_CHIMESTRY) = "Chimestry" - Disciplines(DISCIPLINE_DEMENTATION) = "Dementation" - Disciplines(DISCIPLINE_DOMINATE) = "Dominate" - Disciplines(DISCIPLINE_FORTITUDE) = "Fortitude" - Disciplines(DISCIPLINE_MELPOMINEE) = "Melpominee" - Disciplines(DISCIPLINE_MORTIS) = "Mortis" - Disciplines(DISCIPLINE_MYTHERCERIA) = "Mytherceria" - Disciplines(DISCIPLINE_NECROMANCY) = "Necromancy" - Disciplines(DISCIPLINE_OBEAH) = "Obeah" - Disciplines(DISCIPLINE_OBFUSCATE) = "Obfuscate" - Disciplines(DISCIPLINE_OBTENEBRATION) = "Obtenebration" - Disciplines(DISCIPLINE_POTENCE) = "Potence" - Disciplines(DISCIPLINE_PRESENCE) = "Presence" - Disciplines(DISCIPLINE_PROTEAN) = "Protean" - Disciplines(DISCIPLINE_QUIETUS) = "Quietus" - Disciplines(DISCIPLINE_SERPENTIS) = "Serpentis" - Disciplines(DISCIPLINE_SPIRITUS) = "Spiritus" - Disciplines(DISCIPLINE_THANANTOSIS) = "Thanantosis" - Disciplines(DISCIPLINE_THAUMATURGY) = "Thaumaturgy" - Disciplines(DISCIPLINE_VICISSITUDE) = "Vicissitude" - - ' Virtues - Virtues(VIRTUE_SELF_CONTROL) = "Self-Control" - Virtues(VIRTUE_COURAGE) = "Courage" - Virtues(VIRTUE_CONSCIENCE) = "Conscience" - - ' Physical Attributes - PhysicalAttributes(ATTRIBUTE_STRENGTH) = "Strength" - PhysicalAttributeAbbreviations(ATTRIBUTE_STRENGTH) = "Str." - PhysicalAttributes(ATTRIBUTE_DEXTERITY) = "Dexterity" - PhysicalAttributeAbbreviations(ATTRIBUTE_DEXTERITY) = "Dex." - PhysicalAttributes(ATTRIBUTE_STAMINA) = "Stamina" - PhysicalAttributeAbbreviations(ATTRIBUTE_STAMINA) = "Sta." - - ' Social Attributes - SocialAttributes(ATTRIBUTE_CHARISMA) = "Charisma" - SocialAttributeAbbreviations(ATTRIBUTE_CHARISMA) = "Cha." - SocialAttributes(ATTRIBUTE_MANIPULATION) = "Manipulation" - SocialAttributeAbbreviations(ATTRIBUTE_MANIPULATION) = "Man." - SocialAttributes(ATTRIBUTE_APPEARANCE) = "Appearance" - SocialAttributeAbbreviations(ATTRIBUTE_APPEARANCE) = "App." - - ' Mental Attributes - MentalAttributes(ATTRIBUTE_INTELLIGENCE) = "Intelligence" - MentalAttributeAbbreviations(ATTRIBUTE_INTELLIGENCE) = "Int." - MentalAttributes(ATTRIBUTE_PERCEPTION) = "Perception" - MentalAttributeAbbreviations(ATTRIBUTE_PERCEPTION) = "Per." - MentalAttributes(ATTRIBUTE_WITS) = "Wits" - MentalAttributeAbbreviations(ATTRIBUTE_WITS) = "Wits" - - ' Attribute Groups - AttributeGroups(ATTRIBUTE_GROUP_PHYSICAL) = "Physical" - AttributeGroups(ATTRIBUTE_GROUP_SOCIAL) = "Social" - AttributeGroups(ATTRIBUTE_GROUP_MENTAL) = "Mental" - - ' Abilities - AbilityGroups(ABILITY_GROUP_TALENTS) = "Talents" - AbilityGroups(ABILITY_GROUP_SKILLS) = "Skills" - AbilityGroups(ABILITY_GROUP_KNOWLEDGES) = "Knowledges" - - ' Talents - Talents(TALENT_ACTING) = "Acting" - Talents(TALENT_ALERTNESS) = "Alertness" - Talents(TALENT_ATHLETICS) = "Athletics" - Talents(TALENT_BRAWL) = "Brawl" - Talents(TALENT_DODGE) = "Dodge" - Talents(TALENT_EMPATHY) = "Empathy" - Talents(TALENT_INTIMIDATION) = "Intimidation" - Talents(TALENT_LEADERSHIP) = "Leadership" - Talents(TALENT_STREETWISE) = "Streetwise" - Talents(TALENT_SUBTERFUGE) = "Subterfuge" - - ' Skills - Skills(SKILL_ANIMAL_KEN) = "Animal Ken" - Skills(SKILL_DRIVE) = "Drive" - Skills(SKILL_ETIQUETTE) = "Etiquette" - Skills(SKILL_FIREARMS) = "Firearms" - Skills(SKILL_MELEE) = "Melee" - Skills(SKILL_MUSIC) = "Music" - Skills(SKILL_REPAIR) = "Repair" - Skills(SKILL_SECURITY) = "Security" - Skills(SKILL_STEALTH) = "Stealth" - Skills(SKILL_SURVIVAL) = "Survival" - - ' Knowwledges - Knowledges(KNOWLEDGE_BUREAUCRACY) = "Bureaucracy" - Knowledges(KNOWLEDGE_COMPUTER) = "Computer" - Knowledges(KNOWLEDGE_FINANCE) = "Finance" - Knowledges(KNOWLEDGE_INVESTIGATION) = "Investigation" - Knowledges(KNOWLEDGE_LAW) = "Law" - Knowledges(KNOWLEDGE_LINGUISTICS) = "Linguistics" - Knowledges(KNOWLEDGE_MEDICINE) = "Medicine" - Knowledges(KNOWLEDGE_OCCULT) = "Occult" - Knowledges(KNOWLEDGE_POLITICS) = "Politics" - Knowledges(KNOWLEDGE_SCIENCE) = "Science" - - ' Backgrounds - Backgrounds(BACKGROUND_ALLIES) = "Allies" - Backgrounds(BACKGROUND_CONTACTS) = "Contacts" - Backgrounds(BACKGROUND_FAME) = "Fame" - Backgrounds(BACKGROUND_GENERATION) = "Generation" - Backgrounds(BACKGROUND_HERD) = "Herd" - Backgrounds(BACKGROUND_INFLUENCE) = "Influence" - Backgrounds(BACKGROUND_MENTOR) = "Mentor" - Backgrounds(BACKGROUND_RESOURCES) = "Resources" - Backgrounds(BACKGROUND_RETAINERS) = "Retainers" - Backgrounds(BACKGROUND_STATUS) = "Status" - - ' Genders - Genders(GENDER_MALE) = "Male" - Genders(GENDER_FEMALE) = "Female" - Genders(GENDER_TRANS_MALE) = "Trans-Male" - Genders(GENDER_TRANS_FEMALE) = "Trans-Female" - Genders(GENDER_NON_BINARY) = "Non-Binary" - - ' Derangements - DerangementColors(DERANGEMENT_ID_AMNESIA) = DERANGEMENT_COLOR_AMNESIA - DerangementColors(DERANGEMENT_ID_DELUSIONS_OF_GRANDEUR) = DERANGEMENT_COLOR_DELUSIONS_OF_GRANDEUR - DerangementColors(DERANGEMENT_ID_FANTASY) = DERANGEMENT_COLOR_FANTASY - DerangementColors(DERANGEMENT_ID_MANIC_DEPRESSION) = DERANGEMENT_COLOR_MANIC_DEPRESSION - DerangementColors(DERANGEMENT_ID_MULTIPLE_PERSONALITIES) = DERANGEMENT_COLOR_MULTIPLE_PERSONALITIES - DerangementColors(DERANGEMENT_ID_OBSESSION) = DERANGEMENT_COLOR_OBSESSION - DerangementColors(DERANGEMENT_ID_OVERCOMPENSATION) = DERANGEMENT_COLOR_OVERCOMPENSATION - DerangementColors(DERANGEMENT_ID_PARANOIA) = DERANGEMENT_COLOR_PARANOIA - DerangementColors(DERANGEMENT_ID_PERFECTION) = DERANGEMENT_COLOR_PERFECTION - DerangementColors(DERANGEMENT_ID_REGRESSION) = DERANGEMENT_COLOR_REGRESSION - - DerangementLabels(DERANGEMENT_ID_AMNESIA) = DERANGEMENT_LABEL_AMNESIA - DerangementLabels(DERANGEMENT_ID_DELUSIONS_OF_GRANDEUR) = DERANGEMENT_LABEL_DELUSIONS_OF_GRANDEUR - DerangementLabels(DERANGEMENT_ID_FANTASY) = DERANGEMENT_LABEL_FANTASY - DerangementLabels(DERANGEMENT_ID_MANIC_DEPRESSION) = DERANGEMENT_LABEL_MANIC_DEPRESSION - DerangementLabels(DERANGEMENT_ID_MULTIPLE_PERSONALITIES) = DERANGEMENT_LABEL_MULTIPLE_PERSONALITIES - DerangementLabels(DERANGEMENT_ID_OBSESSION) = DERANGEMENT_LABEL_OBSESSION - DerangementLabels(DERANGEMENT_ID_OVERCOMPENSATION) = DERANGEMENT_LABEL_OVERCOMPENSATION - DerangementLabels(DERANGEMENT_ID_PARANOIA) = DERANGEMENT_LABEL_PARANOIA - DerangementLabels(DERANGEMENT_ID_PERFECTION) = DERANGEMENT_LABEL_PERFECTION - DerangementLabels(DERANGEMENT_ID_REGRESSION) = DERANGEMENT_LABEL_REGRESSION - - DerangementDescriptions(DERANGEMENT_ID_AMNESIA) = DERANGEMENT_DESCRIPTION_AMNESIA - DerangementDescriptions(DERANGEMENT_ID_DELUSIONS_OF_GRANDEUR) = DERANGEMENT_DESCRIPTION_DELUSIONS_OF_GRA - DerangementDescriptions(DERANGEMENT_ID_FANTASY) = DERANGEMENT_DESCRIPTION_FANTASY - DerangementDescriptions(DERANGEMENT_ID_MANIC_DEPRESSION) = DERANGEMENT_DESCRIPTION_MANIC_DEPRESSION - DerangementDescriptions(DERANGEMENT_ID_MULTIPLE_PERSONALITIES) = DERANGEMENT_DESCRIPTION_MULTIPLE_PERSONA - DerangementDescriptions(DERANGEMENT_ID_OBSESSION) = DERANGEMENT_DESCRIPTION_OBSESSION - DerangementDescriptions(DERANGEMENT_ID_OVERCOMPENSATION) = DERANGEMENT_DESCRIPTION_OVERCOMPENSATION - DerangementDescriptions(DERANGEMENT_ID_PARANOIA) = DERANGEMENT_DESCRIPTION_PARANOIA - DerangementDescriptions(DERANGEMENT_ID_PERFECTION) = DERANGEMENT_DESCRIPTION_PERFECTION - DerangementDescriptions(DERANGEMENT_ID_REGRESSION) = DERANGEMENT_DESCRIPTION_REGRESSION - - For i = LBound(Derangements) To UBound(Derangements) - Call NewDerangement(Derangements(i), i, DerangementLabels(i), DerangementColors(i), DerangementDescriptions(i)) - Next - - ' Freebies - FREEBIECOSTS(FREEBIE_DISCIPLINE_ID) = FREEBIE_DISCIPLINE_COST - FREEBIENAMES(FREEBIE_DISCIPLINE_ID) = FREEBIE_DISCIPLINE_NAME - FREEBIELABELS(FREEBIE_DISCIPLINE_ID) = FREEBIE_DISCIPLINE_LABEL - Call NewFreebie(Freebies(FREEBIE_DISCIPLINE_ID), FREEBIE_DISCIPLINE_ID, FREEBIE_DISCIPLINE_COST, -FREEBIE_DISCIPLINE_NAME, FREEBIE_DISCIPLINE_LABEL) - - FREEBIECOSTS(FREEBIE_ATTRIBUTE_ID) = FREEBIE_ATTRIBUTE_COST - FREEBIENAMES(FREEBIE_ATTRIBUTE_ID) = FREEBIE_ATTRIBUTE_NAME - FREEBIELABELS(FREEBIE_ATTRIBUTE_ID) = FREEBIE_ATTRIBUTE_LABEL - Call NewFreebie(Freebies(FREEBIE_ATTRIBUTE_ID), FREEBIE_ATTRIBUTE_ID, FREEBIE_ATTRIBUTE_COST, -FREEBIE_ATTRIBUTE_NAME, FREEBIE_ATTRIBUTE_LABEL) - - FREEBIECOSTS(FREEBIE_ABILITY_ID) = FREEBIE_ABILITY_COST - FREEBIENAMES(FREEBIE_ABILITY_ID) = FREEBIE_ABILITY_NAME - FREEBIELABELS(FREEBIE_ABILITY_ID) = FREEBIE_ABILITY_LABEL - Call NewFreebie(Freebies(FREEBIE_ABILITY_ID), FREEBIE_ABILITY_ID, FREEBIE_ABILITY_COST, FREEBIE_ABILITY_NAME, -FREEBIE_ABILITY_LABEL) - - FREEBIECOSTS(FREEBIE_VIRTUE_ID) = FREEBIE_VIRTUE_COST - FREEBIENAMES(FREEBIE_VIRTUE_ID) = FREEBIE_VIRTUE_NAME - FREEBIELABELS(FREEBIE_VIRTUE_ID) = FREEBIE_VIRTUE_LABEL - Call NewFreebie(Freebies(FREEBIE_VIRTUE_ID), FREEBIE_VIRTUE_ID, FREEBIE_VIRTUE_COST, FREEBIE_VIRTUE_NAME, -FREEBIE_VIRTUE_LABEL) - - FREEBIECOSTS(FREEBIE_HUMANITY_ID) = FREEBIE_HUMANITY_COST - FREEBIENAMES(FREEBIE_HUMANITY_ID) = FREEBIE_HUMANITY_NAME - FREEBIELABELS(FREEBIE_HUMANITY_ID) = FREEBIE_HUMANITY_LABEL - Call NewFreebie(Freebies(FREEBIE_HUMANITY_ID), FREEBIE_HUMANITY_ID, FREEBIE_HUMANITY_COST, FREEBIE_HUMANITY_NAME, -FREEBIE_HUMANITY_LABEL) - - FREEBIECOSTS(FREEBIE_BACKGROUND_ID) = FREEBIE_BACKGROUND_COST - FREEBIENAMES(FREEBIE_BACKGROUND_ID) = FREEBIE_BACKGROUND_NAME - FREEBIELABELS(FREEBIE_BACKGROUND_ID) = FREEBIE_BACKGROUND_LABEL - Call NewFreebie(Freebies(FREEBIE_BACKGROUND_ID), FREEBIE_BACKGROUND_ID, FREEBIE_BACKGROUND_COST, -FREEBIE_BACKGROUND_NAME, FREEBIE_BACKGROUND_LABEL) - - FREEBIECOSTS(FREEBIE_SHOW_CHARACTER_SHEET_ID) = FREEBIE_SHOW_CHARACTER_SHEET_COST - FREEBIENAMES(FREEBIE_SHOW_CHARACTER_SHEET_ID) = FREEBIE_SHOW_CHARACTER_SHEET_NAME - FREEBIELABELS(FREEBIE_SHOW_CHARACTER_SHEET_ID) = FREEBIE_SHOW_CHARACTER_SHEET_LABEL - Call NewFreebie(Freebies(FREEBIE_SHOW_CHARACTER_SHEET_ID), FREEBIE_SHOW_CHARACTER_SHEET_ID, -FREEBIE_SHOW_CHARACTER_SHEET_COST, FREEBIE_SHOW_CHARACTER_SHEET_NAME, FREEBIE_SHOW_CHARACTER_SHEET_LABEL) End Sub - -' Character - -Sub NewCharacter (ch As CharacterType) - ' Scalars - ch.name = "" - ch.player = "" - ch.chronicle = "" - ch.haven = "" - ch.concept = "" - ch.age = "" - ch.gender = 0 - ch.clan = 0 - ch.nature = 0 - ch.demeanor = 0 - ch.generation = 13 - ch.roadName = "" - ch.roadValue = 0 - ch.willpower = 0 - ch.bloodPool = 0 - ch.derangementId = -1 - ch.freebiePoints = 15 - ' Virtues - ch.selfControl = 1 - ch.courage = 1 - ch.conscience = 1 - - ' Arrays/Objects - ' Abilities (Talents/Skills/Knowledges) - For groupIndex = 1 To ABILITY_GROUPS_COUNT - For index = 1 To GetNumItemsForAbilityGroup(groupIndex) - Call SetAbilityValue(ch, groupIndex, index, 0) - Next - Next - ' Attributes - For groupIndex = 1 To ATTRIBUTE_GROUPS_COUNT - For index = 1 To GetNumAttributesInGroup(groupIndex) - Call SetAttributeValue(ch, groupIndex, index, 1) - Next - Next - ' Backgrounds - For index = 1 To BACKGROUNDS_COUNT - Call SetBackground(ch, index, 0) - Next - ' Disciplines - For index = 1 To DISCIPLINES_COUNT - Call SetDiscipline(ch, index, 0) - Next -End Sub - -' Disciplines - -Function GetDisciplinePoints () - GetDisciplinePoints = DISCIPLINE_POINTS -End Function - -Sub SetDiscipline (ch As CharacterType, index As Integer, value As Integer) - Select Case index - Case DISCIPLINE_ANIMALISM - ch.discipline_animalism = value - Case DISCIPLINE_AUSPEX - ch.discipline_auspex = value - Case DISCIPLINE_BARDO - ch.discipline_bardo = value - Case DISCIPLINE_CELERITY - ch.discipline_celerity = value - Case DISCIPLINE_CHIMESTRY - ch.discipline_chimestry = value - Case DISCIPLINE_DEMENTATION - ch.discipline_dementation = value - Case DISCIPLINE_DOMINATE - ch.discipline_dominate = value - Case DISCIPLINE_FORTITUDE - ch.discipline_fortitude = value - Case DISCIPLINE_MELPOMINEE - ch.discipline_melpominee = value - Case DISCIPLINE_MORTIS - ch.discipline_mortis = value - Case DISCIPLINE_MYTHERCERIA - ch.discipline_mytherceria = value - Case DISCIPLINE_NECROMANCY - ch.discipline_necromancy = value - Case DISCIPLINE_OBEAH - ch.discipline_obeah = value - Case DISCIPLINE_OBFUSCATE - ch.discipline_obfuscate = value - Case DISCIPLINE_OBTENEBRATION - ch.discipline_obtenebration = value - Case DISCIPLINE_POTENCE - ch.discipline_potence = value - Case DISCIPLINE_PRESENCE - ch.discipline_presence = value - Case DISCIPLINE_PROTEAN - ch.discipline_protean = value - Case DISCIPLINE_QUIETUS - ch.discipline_quietus = value - Case DISCIPLINE_SERPENTIS - ch.discipline_serpentis = value - Case DISCIPLINE_SPIRITUS - ch.discipline_spiritus = value - Case DISCIPLINE_THANANTOSIS - ch.discipline_thanantosis = value - Case DISCIPLINE_THAUMATURGY - ch.discipline_thaumaturgy = value - Case DISCIPLINE_VICISSITUDE - ch.discipline_vicissitude = value - End Select -End Sub - -Function GetDiscipline (ch As CharacterType, index As Integer) - Select Case index - Case DISCIPLINE_ANIMALISM - GetDiscipline = ch.discipline_animalism - Case DISCIPLINE_AUSPEX - GetDiscipline = ch.discipline_auspex - Case discipline_barde - GetDiscipline = ch.discipline_bardo - Case DISCIPLINE_CELERITY - GetDiscipline = ch.discipline_celerity - Case DISCIPLINE_CHIMESTRY - GetDiscipline = ch.discipline_chimestry - Case DISCIPLINE_DEMENTATION - GetDiscipline = ch.discipline_dementation - Case DISCIPLINE_DOMINATE - GetDiscipline = ch.discipline_dominate - Case DISCIPLINE_FORTITUDE - GetDiscipline = ch.discipline_fortitude - Case DISCIPLINE_MELPOMINEE - GetDiscipline = ch.discipline_melpominee - Case DISCIPLINE_MORTIS - GetDiscipline = ch.discipline_mortis - Case DISCIPLINE_MYTHERCERIA - GetDiscipline = ch.discipline_mytherceria - Case DISCIPLINE_NECROMANCY - GetDiscipline = ch.discipline_necromancy - Case DISCIPLINE_OBEAH - GetDiscipline = ch.discipline_obeah - Case DISCIPLINE_OBFUSCATE - GetDiscipline = ch.discipline_obfuscate - Case DISCIPLINE_OBTENEBRATION - GetDiscipline = ch.discipline_obtenebration - Case DISCIPLINE_POTENCE - GetDiscipline = ch.discipline_potence - Case DISCIPLINE_PRESENCE - GetDiscipline = ch.discipline_presence - Case DISCIPLINE_PROTEAN - GetDiscipline = ch.discipline_protean - Case DISCIPLINE_QUIETUS - GetDiscipline = ch.discipline_quietus - Case DISCIPLINE_SERPENTIS - GetDiscipline = ch.discipline_serpentis - Case DISCIPLINE_SPIRITUS - GetDiscipline = ch.discipline_spiritus - Case DISCIPLINE_THANANTOSIS - GetDiscipline = ch.discipline_thanantosis - Case DISCIPLINE_THAUMATURGY - GetDiscipline = ch.discipline_thaumaturgy - Case DISCIPLINE_VICISSITUDE - GetDiscipline = ch.discipline_vicissitude - End Select -End Function - -Sub FillDisciplines (ch As CharacterType, disciplines() As Integer) - ReDim disciplines(1 To DISCIPLINES_COUNT) As Integer - For index = 1 To DISCIPLINES_COUNT - disciplines(index) = GetDiscipline(ch, index) - Next -End Sub - -' Virtues - -Function GetVirtuePoints () - GetVirtuePoints = VIRTUE_POINTS -End Function - -Sub SetVirtue (ch As CharacterType, index As Integer, value As Integer) - Select Case index - Case VIRTUE_SELF_CONTROL - ch.selfControl = value - Case VIRTUE_COURAGE - ch.courage = value - Case VIRTUE_CONSCIENCE - ch.conscience = value - End Select -End Sub - -Function GetVirtue (ch As CharacterType, index As Integer) - value = 0 - Select Case index - Case VIRTUE_SELF_CONTROL - value = ch.selfControl - Case VIRTUE_COURAGE - value = ch.courage - Case VIRTUE_CONSCIENCE - value = ch.conscience - End Select - GetVirtue = value -End Function - -Sub FillVirtues (ch As CharacterType, values() As Integer) - ReDim values(1 To VIRTUES_COUNT) As Integer - For index = 1 To VIRTUES_COUNT - values(index) = GetVirtue(ch, index) - Next -End Sub - -Function GetFreebiePoints(ch As CharacterType) - GetFreebiePoints = ch.freebiePoints -End Function - -Sub SetFreebiePoints(ch As CharacterType, points As Integer) - ch.freebiepoints = points -End Sub - -' Attributes - -Sub FillAttributeValues (ch As CharacterType, values() As Integer, groupIndex As Integer) - count = GetNumAttributesInGroup(groupIndex) - ReDim values(1 To count) As Integer - For i = 1 To count - values(i) = GetAttributeValue(ch, groupIndex, i) - Next -End Sub - -Function GetNumAttributesInGroup (index As Integer) - Select Case index - Case ATTRIBUTE_GROUP_PHYSICAL - count = PHYSICAL_ATTRIBUTES_COUNT - Case ATTRIBUTE_GROUP_SOCIAL - count = SOCIAL_ATTRIBUTES_COUNT - Case ATTRIBUTE_GROUP_MENTAL - count = MENTAL_ATTRIBUTES_COUNT - Case Else - count = 0 - End Select - GetNumAttributesInGroup = count -End Function - -Function GetAttributeName$ (groupIndex As Integer, attributeIndex As Integer) - attributeName$ = "" - Select Case groupIndex - Case ATTRIBUTE_GROUP_PHYSICAL - attributeName$ = PhysicalAttributes(attributeIndex) - Case ATTRIBUTE_GROUP_SOCIAL - attributeName$ = SocialAttributes(attributeIndex) - Case ATTRIBUTE_GROUP_MENTAL - attributeName$ = MentalAttributes(attributeIndex) - End Select - GetAttributeName = attributeName$ -End Function - -Sub FillAttributesInGroup (group As Integer, attributes() As String) - count = GetNumAttributesInGroup(group) - If count > 0 Then - ReDim attributes(1 To count) As String - Else - ReDim attributes(0) As String - End If - Select Case group - Case ATTRIBUTE_GROUP_PHYSICAL - For i = 1 To count - attributes(i) = PhysicalAttributes(i) - Next - Case ATTRIBUTE_GROUP_SOCIAL - For i = 1 To count - attributes(i) = SocialAttributes(i) - Next - Case ATTRIBUTE_GROUP_MENTAL - For i = 1 To count - attributes(i) = MentalAttributes(i) - Next - End Select -End Sub - -Sub FillAttributeAbbreviationsInGroup (group As Integer, abbreviations() As String, count As Integer) - count = GetNumAttributesInGroup(group) - If count > 0 Then - ReDim abbreviations(1 To count) As String - Else - ReDim abbreviations(0) As String - End If - Select Case group - Case ATTRIBUTE_GROUP_PHYSICAL - For i = 1 To count - abbreviations(i) = PhysicalAttributeAbbreviations(i) - Next - Case ATTRIBUTE_GROUP_SOCIAL - For i = 1 To count - abbreviations(i) = SocialAttributeAbbreviations(i) - Next - Case ATTRIBUTE_GROUP_MENTAL - For i = 1 To count - abbreviations(i) = MentalAttributeAbbreviations(i) - Next - End Select -End Sub - -Sub SetAttributeValue (ch As CharacterType, AttributeGroupIndex As Integer, AttributeIndex As Integer, Value As Integer) - Select Case AttributeGroupIndex - Case ATTRIBUTE_GROUP_PHYSICAL - Select Case AttributeIndex - Case ATTRIBUTE_STRENGTH - ch.attr_strength = Value - Case ATTRIBUTE_DEXTERITY - ch.attr_dexterity = Value - Case ATTRIBUTE_STAMINA - ch.attr_stamina = Value - End Select - Case ATTRIBUTE_GROUP_SOCIAL - Select Case AttributeIndex - Case ATTRIBUTE_CHARISMA - ch.attr_charisma = Value - Case ATTRIBUTE_MANIPULATION - ch.attr_manipulation = Value - Case ATTRIBUTE_APPEARANCE - ch.attr_appearance = Value - End Select - Case ATTRIBUTE_GROUP_MENTAL - Select Case AttributeIndex - Case ATTRIBUTE_INTELLIGENCE - ch.attr_intelligence = Value - Case ATTRIBUTE_PERCEPTION - ch.attr_perception = Value - Case ATTRIBUTE_WITS - ch.attr_wits = Value - End Select - End Select -End Sub - -Function GetAttributeValue (ch As CharacterType, attributeGroupIndex As Integer, attributeIndex As Integer) - GetAttributeValue = 0 - Select Case attributeGroupIndex - Case ATTRIBUTE_GROUP_PHYSICAL - Select Case attributeIndex - Case ATTRIBUTE_STRENGTH - GetAttributeValue = ch.attr_strength - Case ATTRIBUTE_DEXTERITY - GetAttributeValue = ch.attr_dexterity - Case ATTRIBUTE_STAMINA - GetAttributeValue = ch.attr_stamina - End Select - Case ATTRIBUTE_GROUP_SOCIAL - Select Case attributeIndex - Case ATTRIBUTE_CHARISMA - GetAttributeValue = ch.attr_charisma - Case ATTRIBUTE_MANIPULATION - GetAttributeValue = ch.attr_manipulation - Case ATTRIBUTE_APPEARANCE - GetAttributeValue = ch.attr_appearance - End Select - Case ATTRIBUTE_GROUP_MENTAL - Select Case attributeIndex - Case ATTRIBUTE_INTELLIGENCE - GetAttributeValue = ch.attr_intelligence - Case ATTRIBUTE_PERCEPTION - GetAttributeValue = ch.attr_perception - Case ATTRIBUTE_WITS - GetAttributeValue = ch.attr_wits - End Select - End Select -End Function - -Function GetAttributePointsForRank (rank As Integer) - GetAttributePointsForRank = 0 - Select Case rank - Case 1 - GetAttributePointsForRank = 7 - Case 2 - GetAttributePointsForRank = 5 - Case 3 - GetAttributePointsForRank = 3 - End Select -End Function - -' Abilities - -Sub SetAbilityValue (ch As CharacterType, groupIndex As Integer, index As Integer, value As Integer) - Select Case groupIndex - Case ABILITY_GROUP_TALENTS - Call SetTalent(ch, index, value) - Case ABILITY_GROUP_SKILLS - Call SetSkill(ch, index, value) - Case ABILITY_GROUP_KNOWLEDGES - Call SetKnowledge(ch, index, value) - End Select -End Sub - -Function GetAbilityValue (ch As CharacterType, abilityIndex As Integer, itemIndex As Integer) - GetAbilityValue = 0 - Select Case abilityIndex - Case ABILITY_GROUP_TALENTS - GetAbilityValue = GetTalent(ch, itemIndex) - Case ABILITY_GROUP_SKILLS - GetAbilityValue = GetSkill(ch, itemIndex) - Case ABILITY_GROUP_KNOWLEDGES - GetAbilityValue = GetKnowledge(ch, itemIndex) - End Select -End Function - -Function GetAbilityPointsForRank (rank As Integer) - GetAbilityPointsForRank = 0 - Select Case rank - Case 1 - GetAbilityPointsForRank = 13 - Case 2 - GetAbilityPointsForRank = 9 - Case 3 - GetAbilityPointsForRank = 5 - End Select -End Function - -Sub FillAbilityValues (ch As CharacterType, values() As Integer, groupIndex As Integer) - count = GetNumItemsForAbilityGroup(groupIndex) - ReDim values(1 To count) As Integer - For i = 1 To count - values(i) = GetAbilityValue(ch, groupIndex, i) - Next -End Sub - -Function GetNumItemsForAbilityGroup (index As Integer) - Select Case index - Case ABILITY_GROUP_TALENTS - count = TALENTS_COUNT - Case ABILITY_GROUP_SKILLS - count = SKILLS_COUNT - Case ABILITY_GROUP_KNOWLEDGES - count = KNOWLEDGES_COUNT - Case Else - count = 0 - End Select - GetNumItemsForAbilityGroup = count -End Function - -Function GetAbilityName$ (groupIndex As Integer, abilityIndex As Integer) - abilityName$ = "" - Select Case groupIndex - Case ABILITY_GROUP_TALENTS - abilityName$ = Talents(abilityIndex) - Case ABILITY_GROUP_SKILLS - abilityName$ = Skills(abilityIndex) - Case ABILITY_GROUP_KNOWLEDGES - abilityName$ = Knowledges(abilityIndex) - End Select - GetAbilityName = abilityName$ -End Function - -Sub FillAbilitiesForAbilityGroup (ability As Integer, items() As String) - count = GetNumItemsForAbilityGroup(ability) - If count > 0 Then - ReDim items(1 To count) As String - Else - ReDim items(0) As String - End If - Select Case ability - Case ABILITY_GROUP_TALENTS - For i = 1 To count - items(i) = Talents(i) - Next - Case ABILITY_GROUP_SKILLS - For i = 1 To count - items(i) = Skills(i) - Next - Case ABILITY_GROUP_KNOWLEDGES - For i = 1 To count - items(i) = Knowledges(i) - Next - End Select -End Sub - -' Ability - Talents - -Sub SetTalent (ch As CharacterType, index As Integer, value As Integer) - Select Case index - Case TALENT_ACTING - ch.talent_acting = value - Case TALENT_ALERTNESS - ch.talent_alertness = value - Case TALENT_ATHLETICS - ch.talent_athletics = value - Case TALENT_BRAWL - ch.talent_brawl = value - Case TALENT_DODGE - ch.talent_dodge = value - Case TALENT_EMPATHY - ch.talent_empathy = value - Case TALENT_INTIMIDATION - ch.talent_intimidation = value - Case TALENT_LEADERSHIP - ch.talent_leadership = value - Case TALENT_STREETWISE - ch.talent_streetwise = value - Case TALENT_SUBTERFUGE - ch.talent_subterfuge = value - End Select -End Sub - -Function GetTalent (ch As CharacterType, index As Integer) - Select Case index - Case TALENT_ACTING - GetTalent = ch.talent_acting - Case TALENT_ALERTNESS - GetTalent = ch.talent_alertness - Case TALENT_ATHLETICS - GetTalent = ch.talent_athletics - Case TALENT_BRAWL - GetTalent = ch.talent_brawl - Case TALENT_DODGE - GetTalent = ch.talent_dodge - Case TALENT_EMPATHY - GetTalent = ch.talent_empathy - Case TALENT_INTIMIDATION - GetTalent = ch.talent_intimidation - Case TALENT_LEADERSHIP - GetTalent = ch.talent_leadership - Case TALENT_STREETWISE - GetTalent = ch.talent_streetwise - Case TALENT_SUBTERFUGE - GetTalent = ch.talent_subterfuge - End Select -End Function - -' Ability - Skills - -Sub SetSkill (ch As CharacterType, index As Integer, value As Integer) - Select Case index - Case SKILL_ANIMAL_KEN - ch.skill_animalKen = value - Case SKILL_DRIVE - ch.skill_drive = value - Case SKILL_ETIQUETTE - ch.skill_etiquette = value - Case SKILL_FIREARMS - ch.skill_firearms = value - Case SKILL_MELEE - ch.skill_melee = value - Case SKILL_MUSIC - ch.skill_music = value - Case SKILL_REPAIR - ch.skill_repair = value - Case SKILL_SECURITY - ch.skill_security = value - Case SKILL_STEALTH - ch.skill_stealth = value - Case SKILL_SURVIVAL - ch.skill_survival = value - End Select -End Sub - -Function GetSkill (ch As CharacterType, index As Integer) - Select Case index - Case SKILL_ANIMAL_KEN - GetSkill = ch.skill_animalKen - Case SKILL_DRIVE - GetSkill = ch.skill_drive - Case SKILL_ETIQUETTE - GetSkill = ch.skill_etiquette - Case SKILL_FIREARMS - GetSkill = ch.skill_firearms - Case SKILL_MELEE - GetSkill = ch.skill_melee - Case SKILL_MUSIC - GetSkill = ch.skill_music - Case SKILL_REPAIR - GetSkill = ch.skill_repair - Case SKILL_SECURITY - GetSkill = ch.skill_security - Case SKILL_STEALTH - GetSkill = ch.skill_stealth - Case SKILL_SURVIVAL - GetSkill = ch.skill_survival - End Select -End Function - -' Ability - Knowledges - -Sub SetKnowledge (ch As CharacterType, index As Integer, value As Integer) - Select Case index - Case KNOWLEDGE_BUREAUCRACY - ch.knowledge_bureaucracy = value - Case KNOWLEDGE_COMPUTER - ch.knowledge_computer = value - Case KNOWLEDGE_FINANCE - ch.knowledge_finance = value - Case KNOWLEDGE_INVESTIGATION - ch.knowledge_investigation = value - Case KNOWLEDGE_LAW - ch.knowledge_law = value - Case KNOWLEDGE_LINGUISTICS - ch.knowledge_linguistics = value - Case KNOWLEDGE_MEDICINE - ch.knowledge_medicine = value - Case KNOWLEDGE_OCCULT - ch.knowledge_occult = value - Case KNOWLEDGE_POLITICS - ch.knowledge_politics = value - Case KNOWLEDGE_SCIENCE - ch.knowledge_science = value - End Select -End Sub - -Function GetKnowledge (ch As CharacterType, index As Integer) - Select Case index - Case KNOWLEDGE_BUREAUCRACY - GetKnowledge = ch.knowledge_bureaucracy - Case KNOWLEDGE_COMPUTER - GetKnowledge = ch.knowledge_computer - Case KNOWLEDGE_FINANCE - GetKnowledge = ch.knowledge_finance - Case KNOWLEDGE_INVESTIGATION - GetKnowledge = ch.knowledge_investigation - Case KNOWLEDGE_LAW - GetKnowledge = ch.knowledge_law - Case KNOWLEDGE_LINGUISTICS - GetKnowledge = ch.knowledge_linguistics - Case KNOWLEDGE_MEDICINE - GetKnowledge = ch.knowledge_medicine - Case KNOWLEDGE_OCCULT - GetKnowledge = ch.knowledge_occult - Case KNOWLEDGE_POLITICS - GetKnowledge = ch.knowledge_politics - Case KNOWLEDGE_SCIENCE - GetKnowledge = ch.knowledge_science - End Select -End Function - -' Backgrounds - -Sub SetBackground (ch As CharacterType, index As Integer, value As Integer) - Select Case index - Case BACKGROUND_ALLIES - ch.background_allies = value - Case BACKGROUND_CONTACTS - ch.background_contacts = value - Case BACKGROUND_FAME - ch.background_fame = value - Case BACKGROUND_GENERATION - ch.background_generation = value - Case BACKGROUND_HERD - ch.background_herd = value - Case BACKGROUND_INFLUENCE - ch.background_influence = value - Case BACKGROUND_MENTOR - ch.background_mentor = value - Case BACKGROUND_RESOURCES - ch.background_resources = value - Case BACKGROUND_RETAINERS - ch.background_retainers = value - Case BACKGROUND_STATUS - ch.background_status = value - End Select -End Sub - -Function GetBackground (ch As CharacterType, index As Integer) - Select Case index - Case BACKGROUND_ALLIES - GetBackground = ch.background_allies - Case BACKGROUND_CONTACTS - GetBackground = ch.background_contacts - Case BACKGROUND_FAME - GetBackground = ch.background_fame - Case BACKGROUND_GENERATION - GetBackground = ch.background_generation - Case BACKGROUND_HERD - GetBackground = ch.background_herd - Case BACKGROUND_INFLUENCE - GetBackground = ch.background_influence - Case BACKGROUND_MENTOR - GetBackground = ch.background_mentor - Case BACKGROUND_RESOURCES - GetBackground = ch.background_resources - Case BACKGROUND_RETAINERS - GetBackground = ch.background_retainers - Case BACKGROUND_STATUS - GetBackground = ch.background_status - End Select -End Function - -Sub FillBackgrounds (ch As CharacterType, backgrounds() As Integer) - For index = 1 To BACKGROUNDS_COUNT - backgrounds(index) = GetBackground(ch, index) - Next -End Sub - -Function GetBackgroundPoints () - GetBackgroundPoints = BACKGROUND_POINTS -End Function - -' Genders - -' Derangements - -Sub NewDerangement (derangement As DerangementType, id As Integer, label As String, textColor As Integer, description As -String) derangement.id = id derangement.label = label derangement.textColor = textColor derangement.description = -description End Sub - -Function GetAllDerangementsLine$ (ch As CharacterType) - Dim allDerangements(1) As DerangementType - Call FillDerangements(ch, allDerangements()) - allDerangementsString$ = "" - For i = 0 To UBound(allDerangements) - 1 - allDerangementsString$ = allDerangementsString$ + allDerangements(i).label + ", " - Next - GetAllDerangementsLine$ = allDerangementsString$ -End Function - -Sub FillDerangements (ch As CharacterType, myDerangements() As DerangementType) - count = 1 - If ch.derangementId < 0 Or ch.derangementId >= count Then - Exit Sub - End If - ReDim myDerangements(count) As DerangementType - myDerangements(0) = Derangements(ch.derangementId) -End Sub - -' Roads -function GetRoadName$(ch as charactertype) - getroadname = ch.roadName -end function - -sub SetRoadName(ch as charactertype, roadName as string) - ch.roadname = roadname -end sub - -function GetRoadValue(ch as charactertype) - getroadvalue = ch.roadValue -end function - -sub SetRoadValue(ch as charactertype, roadValue as integer) - ch.roadvalue = roadvalue -end sub - -' Freebies -sub NewFreebie (freebie As FreebieType, id As integer, cost As integer, freebieName As string, freebieLabel As string) - freebie.id = id - freebie.cost = cost - freebie.name = freebieName - freebie.label = freebieLabel -end sub - -' Scalars -function GetGeneration(ch as charactertype) - getgeneration = ch.generation -end function - -Sub Test - 'End -End Sub - - - */ } // End namespace SBF