/// <summary> /// Generate some general goods the NPC has with them /// </summary> /// <param name="npc"></param> /// <returns></returns> private static List<DmItemAbstract> GenerateInventory( DmNPC npc ) { List<DmItemAbstract> list = new List<DmItemAbstract>(); // Money : // Adventurers should have a money pouch. Maybe more. // Commoners may or may not have one on their person. // Packs : // Adventurers should be created with at least one, and it should have a fairly basic set // (bedrool, food, light source) as well as other goods.) // Additional packs may be generated, but increasingly less likely. // Commoners may or may not have a pack with them. If they do, it shall be created completely at random // (who knows when a farmer might wander into a bar with a single sheet of parchment, an empty scroll case, and a ladder? switch( npc.characterType ) { case NPCType.Adventurer: { // create the money pouch DmItemContainer beltpouch = new DmItemContainer( DmItemTypeContainer.BeltPouch ); // add some random type/amount of money beltpouch.Contents.Add( DmItemFactory.CreateItem( DmItemType.Money ) ); beltpouch.Contents.Add( DmItemFactory.CreateItem( DmItemType.Money ) ); beltpouch.Contents.Add( DmItemFactory.CreateItem( DmItemType.Money ) ); // add the filled pouch to the list list.Add( beltpouch ); // Good chance for 1 bag... if( rand.Next( 100 ) < 90 ) { list.Add( DmItemFactory.CreateItem( DmItemType.Container ) ); // if they have one, small chance for a 2nd... if( rand.Next( 100 ) < 30 ) { list.Add( DmItemFactory.CreateItem( DmItemType.Container ) ); // if they have 2, _really_ slim chance for a 3rd. if( rand.Next( 100 ) < 5 ) list.Add( DmItemFactory.CreateItem( DmItemType.Container ) ); } } } break; default: { if( npc.characterProfession == NPCTypeProfession.None ) { // beggar? slim chance for money, nothing else. if( rand.Next( 100 ) < 10 ) { // create the money pouch DmItemContainer beltpouch = new DmItemContainer( DmItemTypeContainer.BeltPouch ); // add some random type/amount of money // TODO : maybe (just maybe) limit this to make sure we didn;t just give some grubby beggar a fist-ful of platinum. // unless we meant to, so we could return it to it's rightful owner coughtcoughtstealitcoughcough. beltpouch.Contents.Add( DmItemFactory.CreateItem( DmItemType.Money ) ); // add the filled pouch to the list list.Add( beltpouch ); } } else { // not a beggar : good chance for money, slim chance for 1 bag of stuff. if( rand.Next( 100 ) < 80 ) { // create the money pouch DmItemContainer beltpouch = new DmItemContainer( DmItemTypeContainer.BeltPouch ); // add some random type/amount of money beltpouch.Contents.Add( DmItemFactory.CreateItem( DmItemType.Money ) ); // add the filled pouch to the list list.Add( beltpouch ); } // TODO : limit this some? Or should NPCs be allowed to drag around a bucket and a locked chest? if( rand.Next( 100 ) < 20 ) list.Add( DmItemFactory.CreateItem( DmItemType.Container ) ); } } break; } return list; }
/// <summary> /// PIcks a style of clothing for the NPC /// </summary> /// <param name="npc"></param> /// <returns></returns> private static DmItemClothing GenerateClothing( DmNPC npc ) { //DmItemClothing item; List<DmItemTypeClothing> choices = new List<DmItemTypeClothing>(); switch( npc.characterType ) { case NPCType.Adventurer: // for NPC base class types, the clothing is essentially what they've got under their armor. // This list is completely arbitary, and purely cosmetic // TODO : Except for Wizards and Sorcerers, which cannot wear armor, and Monks that probably don't want to wear armor. switch( npc.characterClass ) { case NPCTypeAdventurer.Bard: choices.Add( DmItemTypeClothing.ArtisanOutfit ); choices.Add( DmItemTypeClothing.CourtiersOutfit ); choices.Add( DmItemTypeClothing.EntertainersOutfit ); break; case NPCTypeAdventurer.Barbarian: case NPCTypeAdventurer.Fighter: choices.Add( DmItemTypeClothing.ColdWeatherOutfit ); choices.Add( DmItemTypeClothing.ExplorersOutfit ); choices.Add( DmItemTypeClothing.PeasantsOutfit ); choices.Add( DmItemTypeClothing.TravelersOutfit ); break; case NPCTypeAdventurer.Cleric: choices.Add( DmItemTypeClothing.NoblesOutfit ); choices.Add( DmItemTypeClothing.ClericVestments ); break; case NPCTypeAdventurer.Rogue: case NPCTypeAdventurer.Ranger: choices.Add( DmItemTypeClothing.ColdWeatherOutfit ); choices.Add( DmItemTypeClothing.ExplorersOutfit ); choices.Add( DmItemTypeClothing.TravelersOutfit ); break; case NPCTypeAdventurer.Druid: case NPCTypeAdventurer.Monk: choices.Add( DmItemTypeClothing.NoblesOutfit ); choices.Add( DmItemTypeClothing.MonksOutfit ); choices.Add( DmItemTypeClothing.TravelersOutfit ); break; case NPCTypeAdventurer.Paladin: choices.Add( DmItemTypeClothing.TravelersOutfit ); choices.Add( DmItemTypeClothing.NoblesOutfit ); choices.Add( DmItemTypeClothing.ArtisanOutfit ); break; case NPCTypeAdventurer.Sorcerer: case NPCTypeAdventurer.Wizard: choices.Add( DmItemTypeClothing.NoblesOutfit ); choices.Add( DmItemTypeClothing.ArtisanOutfit ); choices.Add( DmItemTypeClothing.ScholarsOutfit ); choices.Add( DmItemTypeClothing.CastersRobesElaborate ); choices.Add( DmItemTypeClothing.CastersRobesFine ); choices.Add( DmItemTypeClothing.CastersRobesSimple ); break; } break; case NPCType.NonAdventurer: // for non-class NPCs, the outfit is their current (and possibly only) garb. switch( npc.characterProfession ) { case NPCTypeProfession.Adept: case NPCTypeProfession.Apothecary: case NPCTypeProfession.Aritocrat: case NPCTypeProfession.Enchanter: case NPCTypeProfession.Herbalist: choices.Add( DmItemTypeClothing.ArtisanOutfit ); choices.Add( DmItemTypeClothing.ClericVestments ); choices.Add( DmItemTypeClothing.NoblesOutfit ); choices.Add( DmItemTypeClothing.RoyalOutfit ); choices.Add( DmItemTypeClothing.ScholarsOutfit ); choices.Add( DmItemTypeClothing.CastersRobesElaborate ); choices.Add( DmItemTypeClothing.CastersRobesFine ); choices.Add( DmItemTypeClothing.CastersRobesSimple ); break; case NPCTypeProfession.Baker: case NPCTypeProfession.Barkeep: case NPCTypeProfession.GeneralLabor: case NPCTypeProfession.GeneralShopkeep: case NPCTypeProfession.Farmer: case NPCTypeProfession.Waiter: case NPCTypeProfession.InnKepper: case NPCTypeProfession.Marchant: choices.Add( DmItemTypeClothing.ArtisanOutfit ); choices.Add( DmItemTypeClothing.EntertainersOutfit ); choices.Add( DmItemTypeClothing.ExplorersOutfit ); choices.Add( DmItemTypeClothing.PeasantsOutfit ); break; case NPCTypeProfession.Bowyer: case NPCTypeProfession.Fletcher: case NPCTypeProfession.Jeweler: case NPCTypeProfession.StableMaster: case NPCTypeProfession.ArmorSmith: case NPCTypeProfession.WeaponSmith: choices.Add( DmItemTypeClothing.PeasantsOutfit ); break; default: // if profession is 'None', they're unemployed... but they're still not naked. choices.Add(DmItemTypeClothing.PeasantsOutfit); break; } break; } // given the specified list of acceptable clothing for this NPC's class, pick one at random. return DmItemFactory.CreateClothing( choices[ rand.Next( choices.Count ) ] ); }
/// <summary> /// Randomly assigns weapons to the NPC /// </summary> /// <param name="npc"></param> /// <returns></returns> private static List<DmItemAbstract> GenerateArmor( DmNPC npc ) { List<DmItemAbstract> list = new List<DmItemAbstract>(); List<DmItemTypeArmorType> armors = new List<DmItemTypeArmorType>(); List<DmItemTypeArmorShield> shields = new List<DmItemTypeArmorShield>(); switch( npc.characterClass ) { case NPCTypeAdventurer.Barbarian: // armor : light, medium armors.Add( DmItemTypeArmorType.Light ); armors.Add( DmItemTypeArmorType.Medium ); // sheild : any shields.Add( DmItemTypeArmorShield.Buckler ); shields.Add( DmItemTypeArmorShield.HeavySteel ); shields.Add( DmItemTypeArmorShield.HeavyWooden ); shields.Add( DmItemTypeArmorShield.LightSteel ); shields.Add( DmItemTypeArmorShield.LightWooden ); shields.Add( DmItemTypeArmorShield.Tower ); break; case NPCTypeAdventurer.Bard: // aarmor : any (light = no casting penalties, though) armors.Add( DmItemTypeArmorType.Light ); // shield : any except Tower shields.Add( DmItemTypeArmorShield.Buckler ); shields.Add( DmItemTypeArmorShield.HeavySteel ); shields.Add( DmItemTypeArmorShield.HeavyWooden ); shields.Add( DmItemTypeArmorShield.LightSteel ); shields.Add( DmItemTypeArmorShield.LightWooden ); break; case NPCTypeAdventurer.Cleric: // armor : any armors.Add( DmItemTypeArmorType.Light ); armors.Add( DmItemTypeArmorType.Medium ); armors.Add( DmItemTypeArmorType.Heavy ); // shield : any shields.Add( DmItemTypeArmorShield.Buckler ); shields.Add( DmItemTypeArmorShield.HeavySteel ); shields.Add( DmItemTypeArmorShield.HeavyWooden ); shields.Add( DmItemTypeArmorShield.LightSteel ); shields.Add( DmItemTypeArmorShield.LightWooden ); shields.Add( DmItemTypeArmorShield.Tower ); break; case NPCTypeAdventurer.Druid: // armor : light and medium armors but are prohibited from wearing metal armor (thus, they may wear only padded, leather, or hide armor) armors.Add( DmItemTypeArmorType.Light ); armors.Add( DmItemTypeArmorType.Medium ); armors.Add( DmItemTypeArmorType.Heavy ); // sheild : wooden only shields.Add( DmItemTypeArmorShield.Buckler ); shields.Add( DmItemTypeArmorShield.HeavyWooden ); shields.Add( DmItemTypeArmorShield.LightWooden ); break; case NPCTypeAdventurer.Fighter: // armor : any armors.Add( DmItemTypeArmorType.Light ); armors.Add( DmItemTypeArmorType.Medium ); armors.Add( DmItemTypeArmorType.Heavy ); // shields : any shields.Add( DmItemTypeArmorShield.Buckler ); shields.Add( DmItemTypeArmorShield.HeavySteel ); shields.Add( DmItemTypeArmorShield.HeavyWooden ); shields.Add( DmItemTypeArmorShield.LightSteel ); shields.Add( DmItemTypeArmorShield.LightWooden ); shields.Add( DmItemTypeArmorShield.Tower ); break; case NPCTypeAdventurer.Monk: // armor : preferred none - penalties induced for wearing anything but simple clothing. // shield : none break; case NPCTypeAdventurer.Paladin: // armor : any armors.Add( DmItemTypeArmorType.Light ); armors.Add( DmItemTypeArmorType.Medium ); armors.Add( DmItemTypeArmorType.Heavy ); // shields : any shields.Add( DmItemTypeArmorShield.Buckler ); shields.Add( DmItemTypeArmorShield.HeavySteel ); shields.Add( DmItemTypeArmorShield.HeavyWooden ); shields.Add( DmItemTypeArmorShield.LightSteel ); shields.Add( DmItemTypeArmorShield.LightWooden ); shields.Add( DmItemTypeArmorShield.Tower ); break; case NPCTypeAdventurer.Ranger: // armor : light, medium armors.Add( DmItemTypeArmorType.Light ); armors.Add( DmItemTypeArmorType.Medium ); // shields : any shields.Add( DmItemTypeArmorShield.Buckler ); shields.Add( DmItemTypeArmorShield.HeavySteel ); shields.Add( DmItemTypeArmorShield.HeavyWooden ); shields.Add( DmItemTypeArmorShield.LightSteel ); shields.Add( DmItemTypeArmorShield.LightWooden ); shields.Add( DmItemTypeArmorShield.Tower ); break; case NPCTypeAdventurer.Rogue: // armor : light armors.Add( DmItemTypeArmorType.Light ); // shields : none break; case NPCTypeAdventurer.Sorcerer: // armor : none (robes only) // shields : none break; case NPCTypeAdventurer.Wizard: // armor : none (robes only) // shields : none break; default: // NPCTypeAdventurer.None : no armor for non-adventurer types break; } if( armors.Count() > 0 ) { list.Add( DmItemFactory.CreateItem( armors[rand.Next( armors.Count() )] ) ); // TODO : special case for Druids - no metal armor allowed. } if( shields.Count() > 0 ) { // arbitrary - if they /can/ have a shield, it doesn't mean they /do/... 40% chance they're packin' protection. if( rand.Next(100) < 40 ) list.Add( new DmItemArmorShield( shields[ rand.Next(shields.Count()) ] ) ); // TODO : special case for druids? } return list; }
/// <summary> /// Adjusts the base stats for this NOPC based on their race /// </summary> /// <param name="npc"></param> private static void AdjustStatsForRace( DmNPC npc ) { switch( npc.race ) { case NPCRace.Angelic: case NPCRace.Dragonborne: case NPCRace.Eldarin: case NPCRace.Orc: // no stat adjustment numbers for these yet... return; case NPCRace.Dwarf: npc.statCON += 2; npc.statCHR -= 2; break; case NPCRace.Elf: npc.statCON -= 2; npc.statDEX += 2; break; case NPCRace.Gnome: npc.statSTR -= 2; npc.statCON += 2; break; case NPCRace.HalfElf: // nothing special break; case NPCRace.HalfOrc: npc.statSTR += 2; npc.statINT -= 2; npc.statCHR -= 2; break; case NPCRace.Human: // nothing special break; } }
/// <summary> /// Generate a random NPC of the specified type (Profession or Adventurer) /// </summary> /// <param name="type"></param> /// <returns></returns> public static DmNPC GenerateNPC( NPCType type ) { DmNPC npc = new DmNPC(); npc.race = (NPCRace)rand.Next( Enum.GetValues( typeof(NPCRace) ).Length ); AdjustStatsForRace( npc ); npc.gender = (NPCGender)rand.Next( Enum.GetValues( typeof(NPCGender) ).Length ); npc.name = DmNameGenerator.GenerateName( npc.race, npc.gender ); npc.age = (NPCAge)rand.Next( Enum.GetValues( typeof(NPCAge) ).Length ); int numFeatures = rand.Next(11)-5; for( int i=0; i<numFeatures; i++ ) { NPCFeatures feature = (NPCFeatures)rand.Next( Enum.GetValues( typeof( NPCFeatures ) ).Length ); while( npc.features.Contains( feature ) ) feature = (NPCFeatures)rand.Next( Enum.GetValues( typeof( NPCFeatures ) ).Length ); npc.features.Add( feature ); } npc.eyeColor = (NPCEyeColor)rand.Next( Enum.GetValues( typeof( NPCEyeColor ) ).Length ); npc.hairColor = (NPCHairColor)rand.Next( Enum.GetValues( typeof( NPCHairColor ) ).Length ); npc.hairStyle = (NPCHairStyle)rand.Next( Enum.GetValues( typeof( NPCHairStyle ) ).Length ); npc.hairLength= (NPCHairLength)rand.Next( Enum.GetValues( typeof( NPCHairLength ) ).Length ); if( npc.gender == NPCGender.Male ) npc.facialHair = (NPCFacialHair)rand.Next( Enum.GetValues( typeof( NPCFacialHair ) ).Length ); npc.bodySize = (NPCBodySize)rand.Next( Enum.GetValues( typeof( NPCBodySize ) ).Length ); npc.bodyBuild = (NPCBodyBuild)rand.Next( Enum.GetValues( typeof( NPCBodyBuild ) ).Length ); npc.characterType = type; if( npc.characterType == NPCType.Adventurer ) { // make sure we choose something other than 'None' NPCTypeAdventurer iType = NPCTypeAdventurer.None; while( iType == NPCTypeAdventurer.None ) iType = (NPCTypeAdventurer)rand.Next( Enum.GetValues( typeof( NPCTypeAdventurer ) ).Length ); npc.characterClass = iType; } else { // unlike adventurer types, Profession can be 'None' - which indicates some sort of beggar or unemployed commoner npc.characterProfession= (NPCTypeProfession)rand.Next( Enum.GetValues( typeof( NPCTypeProfession ) ).Length ); } npc.clothing = GenerateClothing( npc ); npc.armor = GenerateArmor( npc ); npc.weapons = GenerateWeapons( npc ); npc.inventory = GenerateInventory( npc ); npc.mentalState = (NPCMentalState)rand.Next( Enum.GetValues( typeof( NPCMentalState ) ).Length ); npc.mood = (NPCMood)rand.Next( Enum.GetValues( typeof( NPCMood ) ).Length ); npc.personality = (NPCPersonaliy)rand.Next( Enum.GetValues( typeof( NPCPersonaliy ) ).Length ); return npc; }
/// <summary> /// Randomly assigns some armor to the NPC /// </summary> /// <param name="npc"></param> /// <returns></returns> private static List<DmItemAbstract> GenerateWeapons( DmNPC npc ) { List<DmItemAbstract> list = new List<DmItemAbstract>(); List<DmItemTypeWeaponClass> weaponsClasses = new List<DmItemTypeWeaponClass>(); List<DmItemTypeWeaponType> weaponsTypes = new List<DmItemTypeWeaponType>(); switch( npc.characterClass ) { case NPCTypeAdventurer.Barbarian: // weapons : simple weaponsClasses.Add( DmItemTypeWeaponClass.Simple ); weaponsTypes.Add( DmItemTypeWeaponType.Melee ); weaponsTypes.Add( DmItemTypeWeaponType.Ranged ); break; case NPCTypeAdventurer.Bard: // weapons : simple weapons + longsword, rapier, sap, short sword, shortbow, and whip weaponsClasses.Add( DmItemTypeWeaponClass.Simple ); weaponsTypes.Add( DmItemTypeWeaponType.Melee ); weaponsTypes.Add( DmItemTypeWeaponType.Ranged ); break; case NPCTypeAdventurer.Cleric: // weapons : blunt only, (unless exceptions allow) weaponsClasses.Add( DmItemTypeWeaponClass.Simple ); weaponsClasses.Add( DmItemTypeWeaponClass.Martial ); weaponsTypes.Add( DmItemTypeWeaponType.Melee ); break; case NPCTypeAdventurer.Druid: // weapons : club, dagger, dart, halfspear, longspear, quarterstaff, scimitar, sickle, shortspear, and sling weaponsClasses.Add( DmItemTypeWeaponClass.Simple ); weaponsTypes.Add( DmItemTypeWeaponType.Melee ); break; case NPCTypeAdventurer.Fighter: // weapons : simple + martial weaponsClasses.Add( DmItemTypeWeaponClass.Simple ); weaponsClasses.Add( DmItemTypeWeaponClass.Martial ); weaponsTypes.Add( DmItemTypeWeaponType.Melee ); weaponsTypes.Add( DmItemTypeWeaponType.Ranged ); break; case NPCTypeAdventurer.Monk: // weapons : Simple peasant weapons and club, crossbow (light or heavy), dagger, handaxe, javelin, kama, nunchaku, quarterstaff, shuriken, siangham, sling weaponsClasses.Add( DmItemTypeWeaponClass.Simple ); weaponsClasses.Add( DmItemTypeWeaponClass.Martial ); weaponsTypes.Add( DmItemTypeWeaponType.Melee ); weaponsTypes.Add( DmItemTypeWeaponType.Ranged ); break; case NPCTypeAdventurer.Paladin: // weapons : simple + martial weaponsClasses.Add( DmItemTypeWeaponClass.Simple ); weaponsClasses.Add( DmItemTypeWeaponClass.Martial ); weaponsTypes.Add( DmItemTypeWeaponType.Melee ); weaponsTypes.Add( DmItemTypeWeaponType.Ranged ); break; case NPCTypeAdventurer.Ranger: // weapons : simple + martial weaponsClasses.Add( DmItemTypeWeaponClass.Simple ); weaponsClasses.Add( DmItemTypeWeaponClass.Martial ); weaponsTypes.Add( DmItemTypeWeaponType.Melee ); weaponsTypes.Add( DmItemTypeWeaponType.Ranged ); break; case NPCTypeAdventurer.Rogue: // weapons : crossbow (hand or light), dagger (any type), dart, light mace, sap, shortbow (normal and composite), and short sword, // medium-sized races and up also get : club, heavy crossbow, heavy mace, morningstar, quarterstaff, and rapier weaponsClasses.Add( DmItemTypeWeaponClass.Simple ); weaponsClasses.Add( DmItemTypeWeaponClass.Martial ); weaponsClasses.Add( DmItemTypeWeaponClass.Exotic ); weaponsTypes.Add( DmItemTypeWeaponType.Melee ); weaponsTypes.Add( DmItemTypeWeaponType.Ranged ); break; case NPCTypeAdventurer.Sorcerer: // weapons : simple weaponsClasses.Add( DmItemTypeWeaponClass.Simple ); weaponsTypes.Add( DmItemTypeWeaponType.Melee ); weaponsTypes.Add( DmItemTypeWeaponType.Ranged ); break; case NPCTypeAdventurer.Wizard: // weapons : club, dagger, heavy crossbow, light crossbow, and quarterstaff weaponsClasses.Add( DmItemTypeWeaponClass.Simple ); weaponsTypes.Add( DmItemTypeWeaponType.Melee ); weaponsTypes.Add( DmItemTypeWeaponType.Ranged ); break; default: // NPCTypeAdventurer.None : no armor for non-adventurer types DmItemWeaponMeleeSimple item = new DmItemWeaponMeleeSimple(DmItemTypeWeaponMeleeSimple.Dirk); item.Quality = DmItemQuality.Poor; list.Add( item ); // default - beggars have a small, crappy knife. break; } if( weaponsClasses.Count() > 0 ) { int numWeapons = rand.Next( 3 )+1; for( int i=0; i<numWeapons; i++ ) { list.Add( DmItemFactory.CreateItem( weaponsClasses[rand.Next( weaponsClasses.Count() )], /* */ weaponsTypes [rand.Next( weaponsTypes .Count() )] /* */ ) /* */ ); // TODO : special conditions for classes with specific lists. // TODO : make sure the items in the lists are in the list of weapons enum... } } return list; }