diff --git a/TrekSharp.AdventureTools/Pages/CreateMini.razor b/TrekSharp.AdventureTools/Pages/CreateMini.razor index 1fa7209..5502902 100644 --- a/TrekSharp.AdventureTools/Pages/CreateMini.razor +++ b/TrekSharp.AdventureTools/Pages/CreateMini.razor @@ -9,6 +9,11 @@
+
+ +
diff --git a/TrekSharp.AdventureTools/Pages/ViewCharacterSheet.razor b/TrekSharp.AdventureTools/Pages/ViewCharacterSheet.razor index 56fb656..20eafd9 100644 --- a/TrekSharp.AdventureTools/Pages/ViewCharacterSheet.razor +++ b/TrekSharp.AdventureTools/Pages/ViewCharacterSheet.razor @@ -30,7 +30,7 @@
SPECIES:
-
@Player.Species
+
@Player.Species.ToFullString()
ASSIGNMENT:
diff --git a/TrekSharp.AdventureTools/Pages/ViewCharacterSupportSheet.razor b/TrekSharp.AdventureTools/Pages/ViewCharacterSupportSheet.razor index 172b259..c6b0fac 100644 --- a/TrekSharp.AdventureTools/Pages/ViewCharacterSupportSheet.razor +++ b/TrekSharp.AdventureTools/Pages/ViewCharacterSupportSheet.razor @@ -31,7 +31,7 @@
SPECIES:
-
@Player.Species
+
@Player.Species.ToFullString()
diff --git a/TrekSharp.AdventureTools/Shared/LifepathWizard.razor b/TrekSharp.AdventureTools/Shared/LifepathWizard.razor index 22e390c..1032c0f 100644 --- a/TrekSharp.AdventureTools/Shared/LifepathWizard.razor +++ b/TrekSharp.AdventureTools/Shared/LifepathWizard.razor @@ -70,6 +70,19 @@ + + +

+ Many characters have parents from different species. Mixed-heritage species are treated as a member of the primary species taking more features from one parent than from the other, but inherits the traits of and can choose the talents avaliable for the other species. This step is optional as you may choose to not have a character be of mixed-heritage. +

+
+ +
+ @if (useMixed) { + + } +
+
@@ -79,7 +92,7 @@
- @if (characterSpecies.AttributeModifiers == null) { + @if (characterPrimarySpecies.AttributeModifiers == null) {

This species has no default attributes, choose 3 attributes to increase.

@@ -93,7 +106,7 @@

This species has the following default attributes

- foreach (var attr in characterSpecies.AttributeModifiers.Enumerate()) { + foreach (var attr in characterPrimarySpecies.AttributeModifiers.Enumerate()) {
@@ -148,7 +161,7 @@
@context.Description
- @if ((context.AttributeSelectionMask ?? characterSpecies.AttributeModifiers ?? characterCustomSpeciesAttributes) != null) { + @if ((context.AttributeSelectionMask ?? characterPrimarySpecies.AttributeModifiers ?? characterCustomSpeciesAttributes) != null) {
@@ -157,7 +170,7 @@
- @foreach (var item in (context.AttributeSelectionMask ?? characterSpecies.AttributeModifiers ?? characterCustomSpeciesAttributes).Enumerate()){ + @foreach (var item in (context.AttributeSelectionMask ?? characterPrimarySpecies.AttributeModifiers ?? characterCustomSpeciesAttributes).Enumerate()){ if (item.Value > 0) {
@item.Name
} @@ -207,7 +220,7 @@
@@ -877,7 +890,7 @@ private Attributes characterBaseAttributes = new Attributes (7); private Disciplines characterBaseDisciplines = new Disciplines (1); private Attributes characterCustomSpeciesAttributes = new Attributes(0); - private Attributes speciesAttributes => characterSpecies?.AttributeModifiers ?? characterCustomSpeciesAttributes; + private Attributes speciesAttributes => characterPrimarySpecies?.AttributeModifiers ?? characterCustomSpeciesAttributes; private Attributes characterCareerPathAttributes = new Attributes(); private Disciplines characterCareerPathMajorDisciplines = new Disciplines(); @@ -925,7 +938,8 @@ Name = characterName, Rank = characterRank, Assignment = characterAssignment, - Species = characterSpecies, + // Produces a "pure" species if characterSubspecies is null or empty + Species = characterPrimarySpecies.DeriveMixedSpecies(characterSubspecies), Attributes = characterAttributesAfterRebalance, Disciplines = characterDisciplinesAfterRebalance, Equipment = characterEquipment, @@ -942,8 +956,18 @@ #region Species private ListSelect speciesSelector; - private Species characterSpecies => speciesSelector?.Selected; + private Species characterPrimarySpecies => speciesSelector?.Selected; private bool requireSpecies() => speciesSelector?.Selected != null; + + private bool useMixed; + private ListSelect speciesSecondarySelector; + private List characterSubspecies => speciesSecondarySelector.AllSelected; + private void toggleMixedHeritage() { + useMixed = !useMixed; + if (!useMixed) { + speciesSecondarySelector?.DeselectAll(); + } + } #endregion #region First Talent diff --git a/TrekSharp.AdventureTools/Shared/ListSelect.razor b/TrekSharp.AdventureTools/Shared/ListSelect.razor index 5832eea..1a5fa9a 100644 --- a/TrekSharp.AdventureTools/Shared/ListSelect.razor +++ b/TrekSharp.AdventureTools/Shared/ListSelect.razor @@ -86,4 +86,10 @@ } OnSelectionChanged?.Invoke(); } + + public void DeselectAll() { + this.AllSelected.Clear(); + OnSelectionChanged?.Invoke(); + StateHasChanged(); + } } \ No newline at end of file diff --git a/TrekSharp/src/Rulebooks/Core.cs b/TrekSharp/src/Rulebooks/Core.cs index d1b3ecf..e634958 100644 --- a/TrekSharp/src/Rulebooks/Core.cs +++ b/TrekSharp/src/Rulebooks/Core.cs @@ -97,7 +97,7 @@ List items new SpeciesRestrictedTalent("Andorian", "Proud and Honorable", "Your personal integrity is unimpeachable, and you will not willingly break a promise made. Whenever you attempt a Task to resist being coerced into breaking a promise, betraying your allies, or otherwise acting dishonorably, you redice the Difficulty by 1."), new SpeciesRestrictedTalent("Andorian", "The Ushaan", "You are experienced in the tradition of honor-dueling known as the Ushaan, having spilt much blood upon the ice. When you make a melee Attack, or are targeted by a melee Attack, and buy one or more d20s by adding to the Threat, you may re-roll the dice pool for the Task. Further, you own an Ushaan-tor mining tool traditionally used on these duels."), new SpeciesRestrictedTalent("Bajoran", "Orb Experience", "You have received a vision from the Bajoran Prophets, through one of the Orbs. This rare experience, though confusing at first, has shaped your life and outlook. YOu have one additional Value, reflecting the insights you received. The first time this Value is challenged, roll 1 challenge die; if an effect is rolled, then some foretold element of the Orb Experience has come to pass, and the Value is not crossed out."), - new SpeciesRestrictedTalent("Bajoran", "String Pagh", "You believe profoundly in the Prophets, and rely heavily upon that faith to see you through hardship. Whenever you attempt a Task to resist being coerced or threatened, you reduce the Difficulty of that Task by 1."), + new SpeciesRestrictedTalent("Bajoran", "Strong Pagh", "You believe profoundly in the Prophets, and rely heavily upon that faith to see you through hardship. Whenever you attempt a Task to resist being coerced or threatened, you reduce the Difficulty of that Task by 1."), new SpeciesRestrictedTalent("Betazoid", "Empath", "You can sense the emotions of most living beings nearby, and can communicate telepathically with other empaths and telepaths, as well as with whom you are extremely familiar. YOu cannot choose not to sense the emotions of those nearby except for those who are resistant to telepathy. It may require effort and a Task to pick out the emotions of a specific individual in a crowd, or to block out the emotions of those nearby. Increase the difficulty of the Task if the situation is stressful, there are lats of people present, if the target has resistance to telepathy, or other relevant factors."), new SpeciesRestrictedTalent("Betazoid", "Telepath", "You can sense the surface thoughts and emotions of most living beings nearby, and can communicate telepathically with other empaths and telepaths, as well as those with whom you are extremely familiar. Surface thoughts are whatever a creature is thinking about at that precise moment. The character cannot choose not to sense the emotions or read the surface thoughts of those nearby, except for those that are resistant to telepathy. If will require effort and a Task to pick out the emotions or thoughts od a specific individual in a crowd, to search a creature;s mind for specific thoughts or memories, or to block out the minds of those nearby."), new SpeciesRestrictedTalent("Denobulan", "Cultural Flexibility", "Your people are friendly, patient, and inquisitive, and you exemplify those traits. You are at ease when meeting new cultures, and adapt to unfamiliar social structures easily. When you attempt a Task to learn about an unfamiliar culture, or to act in the appropriate manner when interating with members of such a culture, you reduce the Difficulty by 1."), diff --git a/TrekSharp/src/Species.cs b/TrekSharp/src/Species.cs index 57f9273..4799fb7 100644 --- a/TrekSharp/src/Species.cs +++ b/TrekSharp/src/Species.cs @@ -1,3 +1,6 @@ +using System.Collections.Generic; +using System.Linq; + namespace TrekSharp { public class CustomSpecies : Species { @@ -12,6 +15,8 @@ public class Species : IResearchableEntity { public string Name {get; set;} public Attributes AttributeModifiers {get; set;} + public List OtherHeritage {get; set;} + public Species () {} public Species (string name, Attributes modifiers) { this.Name = name; @@ -33,6 +38,23 @@ public override int GetHashCode() { public override string ToString(){ return this.Name; } + + public string ToFullString() { + return this.Name + (OtherHeritage == null || OtherHeritage.Count < 1 ? string.Empty : ("/" + string.Join('/',this.OtherHeritage))); + } + + /// + /// Create a mixed species whose primary appearance and atttributes are derived from this species, but can have talents from other other constituent species. + /// + /// other species to mix with + /// new mixed species + public Species DeriveMixedSpecies(IEnumerable others) { + return new Species { + Name = new string(this.Name), + AttributeModifiers = this.AttributeModifiers == null ? null : new Attributes(this.AttributeModifiers), + OtherHeritage = others?.ToList() + }; + } } } \ No newline at end of file diff --git a/TrekSharp/src/Talents.cs b/TrekSharp/src/Talents.cs index 54d1031..c97d022 100644 --- a/TrekSharp/src/Talents.cs +++ b/TrekSharp/src/Talents.cs @@ -38,7 +38,7 @@ public SpeciesRestrictedTalent (string species, string name, string description) this.species = species; } public override bool CanBeUsedBy(Character character) { - return character.Species.Name == this.species; + return character.Species.Name == this.species || (character.Species.OtherHeritage != null && character.Species.OtherHeritage.Select(s => s.Name).Contains(this.species)); } }