/// <summary> /// Add interior people flats. /// </summary> private void AddPeople(PlayerGPS.DiscoveredBuilding buildingData) { GameObject node = new GameObject("People Flats"); node.transform.parent = this.transform; bool isMemberOfBuildingGuild = GameManager.Instance.GuildManager.GetGuild(buildingData.factionID).IsMember(); // Add block flats foreach (DFBlock.RmbBlockPeopleRecord obj in recordData.Interior.BlockPeopleRecords) { // Calculate position Vector3 billboardPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; // Import 3D character instead of billboard if (MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, node.transform) != null) { continue; } // Spawn billboard gameobject GameObject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, node.transform); // Set position DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>(); go.transform.position = billboardPosition; go.transform.position += new Vector3(0, dfBillboard.Summary.Size.y / 2, 0); // Add RMB data to billboard dfBillboard.SetRMBPeopleData(obj); // Add StaticNPC behaviour StaticNPC npc = go.AddComponent <StaticNPC>(); npc.SetLayoutData(obj, entryDoor.buildingKey); // Disable people if shop or building is closed DFLocation.BuildingTypes buildingType = buildingData.buildingType; if ((RMBLayout.IsShop(buildingType) && !GameManager.Instance.PlayerEnterExit.IsPlayerInsideOpenShop) || (buildingType <= DFLocation.BuildingTypes.Palace && !RMBLayout.IsShop(buildingType) && !PlayerActivate.IsBuildingOpen(buildingType))) { go.SetActive(false); } // Disable people if player owns this house else if (DaggerfallBankManager.IsHouseOwned(buildingData.buildingKey)) { go.SetActive(false); } // Disable people if this is TG/DB house and player is not a member else if (buildingData.buildingType == DFLocation.BuildingTypes.House2 && buildingData.factionID != 0 && !isMemberOfBuildingGuild) { go.SetActive(false); } // Disable people if they are TG spymaster, but not in a legit TG house (TODO: spot any other instances for TG/DB) else if (buildingData.buildingType == DFLocation.BuildingTypes.House2 && buildingData.factionID == 0 && npc.Data.factionID == (int)GuildNpcServices.TG_Spymaster) { go.SetActive(false); } } }
/// <summary> /// Add interior people flats. /// </summary> private void AddPeople(PlayerGPS.DiscoveredBuilding buildingData) { GameObject node = new GameObject(peopleFlats); node.transform.parent = this.transform; IGuild guild = GameManager.Instance.GuildManager.GetGuild(buildingData.factionID); bool isMemberOfBuildingGuild = guild.IsMember(); // Add block flats foreach (DFBlock.RmbBlockPeopleRecord obj in recordData.Interior.BlockPeopleRecords) { // Calculate position Vector3 billboardPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; // Make person gameobject GameObject go = MeshReplacement.ImportCustomFlatGameobject(obj.TextureArchive, obj.TextureRecord, billboardPosition, node.transform); if (!go) { // Spawn billboard gameobject go = GameObjectHelper.CreateDaggerfallBillboardGameObject(obj.TextureArchive, obj.TextureRecord, node.transform); // Set position DaggerfallBillboard dfBillboard = go.GetComponent <DaggerfallBillboard>(); go.transform.position = billboardPosition; go.transform.position += new Vector3(0, dfBillboard.Summary.Size.y / 2, 0); // Add RMB data to billboard dfBillboard.SetRMBPeopleData(obj); } // Add StaticNPC behaviour StaticNPC npc = go.AddComponent <StaticNPC>(); npc.SetLayoutData(obj, entryDoor.buildingKey); // Disable people if shop or building is closed DFLocation.BuildingTypes buildingType = buildingData.buildingType; if ((RMBLayout.IsShop(buildingType) && !GameManager.Instance.PlayerEnterExit.IsPlayerInsideOpenShop) || (buildingType <= DFLocation.BuildingTypes.Palace && !RMBLayout.IsShop(buildingType) && !(PlayerActivate.IsBuildingOpen(buildingType) || buildingType == DFLocation.BuildingTypes.GuildHall && guild.HallAccessAnytime()))) { go.SetActive(false); } // Disable people if player owns this house else if (DaggerfallBankManager.IsHouseOwned(buildingData.buildingKey)) { go.SetActive(false); } // Disable people if this is TG/DB house and player is not a member else if (buildingData.buildingType == DFLocation.BuildingTypes.House2 && buildingData.factionID != 0 && !isMemberOfBuildingGuild) { go.SetActive(false); } } }
private static void OnTransitionToInterior_VariantShopTavernNPCsprites(PlayerEnterExit.TransitionEventArgs args) { PlayerEnterExit playerEnterExit = GameManager.Instance.PlayerEnterExit; DFLocation.BuildingData buildingData = playerEnterExit.Interior.BuildingData; if (buildingData.BuildingType == DFLocation.BuildingTypes.Tavern || RMBLayout.IsShop(buildingData.BuildingType)) { Billboard[] dfBillboards = playerEnterExit.Interior.GetComponentsInChildren <Billboard>(); foreach (Billboard billboard in dfBillboards) { int record = -1; if (billboard.Summary.Archive == 182 && billboard.Summary.Record == 0) { record = GetRecord_182_0(buildingData.Quality); // (buildingData.Quality - 1) / 4; #if UNITY_EDITOR Debug.LogFormat("Shop quality {0} using record {1} to replace 182_0", buildingData.Quality, record); #endif } else if (billboard.Summary.Archive == 182 && billboard.Summary.Record == 1) { if (buildingData.Quality < 12) { // Using big test flats version record = 4; } else if (buildingData.Quality > 14) { record = 5; } #if UNITY_EDITOR Debug.LogFormat("Tavern quality {0} using record {1} to replace 182_1", buildingData.Quality, record); #endif } else if (billboard.Summary.Archive == 182 && billboard.Summary.Record == 2) { if (buildingData.Quality > 12) { record = 6; } #if UNITY_EDITOR Debug.LogFormat("Tavern quality {0} using record {1} to replace 182_2", buildingData.Quality, record); #endif } if (record > -1) { billboard.SetMaterial(197, record); GameObjectHelper.AlignBillboardToGround(billboard.gameObject, billboard.Summary.Size); } } } }
private static void ShopShelfBurglar(RaycastHit hit) { PlayerGPS.DiscoveredBuilding buildingData = GameManager.Instance.PlayerEnterExit.BuildingDiscoveryData; if (RMBLayout.IsShop(buildingData.buildingType) && !PlayerActivate.IsBuildingOpen(buildingData.buildingType)) { int stealthValue = playerEntity.Skills.GetLiveSkillValue(DFCareer.Skills.Stealth); stealthValue -= buildingData.quality * 2; if (Dice100.FailedRoll(StealthCalc(stealthValue, false))) { burglaryCounter += Mathf.Clamp(UnityEngine.Random.Range(100, 200) - playerEntity.Stats.LiveLuck, 10, 100); } } }
private void AddFurnitureAction(DFBlock.RmbBlock3dObjectRecord obj, GameObject go, PlayerGPS.DiscoveredBuilding buildingData) { // Create unique LoadID for save system, using 9 lsb and the sign bit from each coord pos int ulong loadID = ((ulong)buildingData.buildingKey) << 30 | (uint)(obj.XPos << 1 & posMask) << 20 | (uint)(obj.YPos << 1 & posMask) << 10 | (uint)(obj.ZPos << 1 & posMask); DFLocation.BuildingTypes buildingType = buildingData.buildingType; // Handle shelves: if (shopShelvesObjectGroupIndices.Contains(obj.ModelIdNum - containerObjectGroupOffset)) { if (RMBLayout.IsShop(buildingType)) { // Shop shelves, so add a DaggerfallLoot component DaggerfallLoot loot = go.AddComponent <DaggerfallLoot>(); if (loot) { // Set as shelves, assign load id and create serialization object loot.ContainerType = LootContainerTypes.ShopShelves; loot.ContainerImage = InventoryContainerImages.Shelves; loot.LoadID = loadID; if (SaveLoadManager.Instance != null) { go.AddComponent <SerializableLootContainer>(); } } } else if (buildingType == DFLocation.BuildingTypes.Library || buildingType == DFLocation.BuildingTypes.GuildHall || buildingType == DFLocation.BuildingTypes.Temple) { // Bookshelves, add DaggerfallBookshelf component go.AddComponent <DaggerfallBookshelf>(); } else if (DaggerfallBankManager.IsHouseOwned(buildingData.buildingKey)) { // Player owned house, everything is a house container MakeHouseContainer(obj, go, loadID); } } // Handle generic furniture as (private) house containers: // (e.g. shelves, boxes, wardrobes, drawers etc) else if (obj.ModelIdNum / 100 == houseContainerObjectGroup || houseContainerObjectGroupIndices.Contains(obj.ModelIdNum - containerObjectGroupOffset)) { MakeHouseContainer(obj, go, loadID); } }
/// <summary> /// Update NPC presence for shops and guilds after resting/idling. /// </summary> public void UpdateNpcPresence() { PlayerEnterExit playerEnterExit = GameManager.Instance.PlayerEnterExit; DFLocation.BuildingTypes buildingType = playerEnterExit.BuildingType; if ((RMBLayout.IsShop(buildingType) && !playerEnterExit.IsPlayerInsideOpenShop) || (!RMBLayout.IsShop(buildingType) && buildingType <= DFLocation.BuildingTypes.Palace && buildingType != DFLocation.BuildingTypes.HouseForSale)) { Transform npcTransforms = transform.Find(peopleFlats); if (PlayerActivate.IsBuildingOpen(buildingType)) { foreach (Transform npcTransform in npcTransforms) { npcTransform.gameObject.SetActive(true); } Debug.Log("Updated npcs to be present."); } } }
// Player has clicked on a static NPC void StaticNPCClick(StaticNPC npc) { // Do nothing if no NPC passed or fade in progress // Quest machine does not tick while fading (to prevent things happening while screen is black) // But this can result in player clicking a quest NPC before quest state ticks after load and breaking quest if (!npc || DaggerfallUI.Instance.FadeInProgress) { return; } // Store the NPC just clicked in quest engine QuestMachine.Instance.LastNPCClicked = npc; // Check if this NPC is a quest giver and show temp guild quest popup // This will be changed later when temp guild system replaced with real thing if (QuestorCheck(npc)) { return; } // Handle quest NPC click and exit if linked to a Person resource QuestResourceBehaviour questResourceBehaviour = npc.gameObject.GetComponent <QuestResourceBehaviour>(); if (questResourceBehaviour) { if (TriggerQuestResourceBehaviourClick(questResourceBehaviour)) { return; } } // Do nothing further if a quest is actively listening on this individual NPC // This NPC not reserved as a Person resource but has a WhenNpcIsAvailable action listening on it // This effectively shuts down several named NPCs during main quest, but not trivial to otherwise determine appropriate access // TODO: Try to find a good solution for releasing listeners when the owning action is disabled if (QuestMachine.Instance.HasFactionListener(npc.Data.factionID)) { return; } // Get faction data. FactionFile.FactionData factionData; if (playerEnterExit.IsPlayerInsideBuilding && GameManager.Instance.PlayerEntity.FactionData.GetFactionData(npc.Data.factionID, out factionData)) { UserInterfaceManager uiManager = DaggerfallUI.Instance.UserInterfaceManager; Debug.LogFormat("faction id: {0}, social group: {1}, guild: {2}", npc.Data.factionID, (FactionFile.SocialGroups)factionData.sgroup, (FactionFile.GuildGroups)factionData.ggroup); // Check if the NPC offers a guild service. if (Enum.IsDefined(typeof(GuildServices), npc.Data.factionID)) { FactionFile.GuildGroups guild = (FactionFile.GuildGroups)factionData.ggroup; GuildServices service = (GuildServices)npc.Data.factionID; Debug.Log("NPC offers guild service: " + service.ToString()); uiManager.PushWindow(new DaggerfallGuildServicePopupWindow(uiManager, npc, guild, service)); } // Check if this NPC is a merchant. else if ((FactionFile.SocialGroups)factionData.sgroup == FactionFile.SocialGroups.Merchants) { // Shop? if (RMBLayout.IsShop(playerEnterExit.BuildingDiscoveryData.buildingType)) { if (RMBLayout.IsRepairShop(playerEnterExit.BuildingDiscoveryData.buildingType)) { uiManager.PushWindow(new DaggerfallMerchantRepairPopupWindow(uiManager, npc)); } else { uiManager.PushWindow(new DaggerfallMerchantServicePopupWindow(uiManager, npc, DaggerfallMerchantServicePopupWindow.Services.Sell)); } } // Bank? else if (playerEnterExit.BuildingDiscoveryData.buildingType == DFLocation.BuildingTypes.Bank) { uiManager.PushWindow(new DaggerfallMerchantServicePopupWindow(uiManager, npc, DaggerfallMerchantServicePopupWindow.Services.Banking)); } // Tavern? else if (playerEnterExit.BuildingDiscoveryData.buildingType == DFLocation.BuildingTypes.Tavern) { // for now only talk to all npc in taverns - TODO: add tavern option in here GameManager.Instance.TalkManager.TalkToStaticNPC(npc); } } // TODO - more checks for npc social types? else // if no special handling had to be done for npc with social group of type merchant: talk to the static npc { GameManager.Instance.TalkManager.TalkToStaticNPC(npc); } } else // if no special handling had to be done (all remaining npcs of the remaining social groups not handled explicitely above): default is talk to the static npc { // with one exception: guards if (npc.Data.billboardArchiveIndex == 183 && npc.Data.billboardRecordIndex == 3) // detect if clicked guard (comment Nystul: didn't find a better mechanism than billboard texture check) { return; // if guard was clicked don't open talk window } // otherwise open talk window GameManager.Instance.TalkManager.TalkToStaticNPC(npc); } }
// Display a shop quality level private DaggerfallMessageBox PresentShopQuality(StaticBuilding building) { const int qualityLevel1TextId = 266; // "Incense and soft music soothe your nerves" const int qualityLevel2TextId = 267; // "The shop is better appointed than many" const int qualityLevel3TextId = 268; // "The shop is laid out in a practical" const int qualityLevel4TextId = 269; // "Sturdy shelves, cobbled together" const int qualityLevel5TextId = 270; // "Rusty relics lie wherever they were last tossed" // Get building directory for location BuildingDirectory buildingDirectory = GameManager.Instance.StreamingWorld.GetCurrentBuildingDirectory(); if (!buildingDirectory) { return(null); } // Get detailed building data from directory BuildingSummary buildingSummary; if (!buildingDirectory.GetBuildingSummary(building.buildingKey, out buildingSummary)) { return(null); } // Do nothing if not a shop if (!RMBLayout.IsShop(buildingSummary.BuildingType)) { return(null); } // Set quality level text ID from quality value 01-20 // UESP states this is building quality / 4 but Daggerfall uses manual thresholds int qualityTextId; if (buildingSummary.Quality <= 3) { qualityTextId = qualityLevel5TextId; // 01 - 03 } else if (buildingSummary.Quality <= 7) { qualityTextId = qualityLevel4TextId; // 04 - 07 } else if (buildingSummary.Quality <= 13) { qualityTextId = qualityLevel3TextId; // 08 - 13 } else if (buildingSummary.Quality <= 17) { qualityTextId = qualityLevel2TextId; // 14 - 17 } else { qualityTextId = qualityLevel1TextId; // 18 - 20 } // Log quality of building entered for debugging //Debug.Log("Entered store with quality of " + buildingData.Quality); // Output quality text based on settings switch (DaggerfallUnity.Settings.ShopQualityPresentation) { case 0: // Display popup as per classic return(DaggerfallUI.MessageBox(qualityTextId)); case 1: // Display HUD text only with variable delay TextFile.Token[] tokens = DaggerfallUnity.Instance.TextProvider.GetRSCTokens(qualityTextId); for (int i = 0; i < tokens.Length; i++) { if (tokens[i].formatting == TextFile.Formatting.Text) { DaggerfallUI.AddHUDText(tokens[i].text, DaggerfallUnity.Settings.ShopQualityHUDDelay); } } break; case 2: // Display nothing about shop quality default: return(null); } return(null); }
static void ThiefEffects_OnNewMagicRound() { //Debug.Log("[ThiefOverhaul] Magic Round"); if (playerEnterExit.IsPlayerInsideBuilding) { PlayerGPS.DiscoveredBuilding buildingData = GameManager.Instance.PlayerEnterExit.BuildingDiscoveryData; if (RMBLayout.IsShop(buildingData.buildingType) && !PlayerActivate.IsBuildingOpen(buildingData.buildingType)) { int stealthValue = playerEntity.Skills.GetLiveSkillValue(DFCareer.Skills.Stealth); stealthValue -= buildingData.quality * 2; if (Dice100.FailedRoll(StealthCalc(stealthValue, false))) { if (burglaryCounter >= 100) { DaggerfallUI.MessageBox("'Guards! Guards! We're being robbed!'"); if (Dice100.SuccessRoll(playerEntity.Stats.LiveLuck)) { playerEntity.MagicalConcealmentFlags = MagicalConcealmentFlags.None; DaggerfallUI.AddHUDText("Your magical concealment is broken"); } playerEntity.CrimeCommitted = PlayerEntity.Crimes.Breaking_And_Entering; playerEntity.SpawnCityGuards(true); } else if (burglaryCounter == 0) { DaggerfallUI.MessageBox(burglaryString1()); burglaryCounter += Mathf.Clamp(UnityEngine.Random.Range(100, 200) - playerEntity.Stats.LiveLuck, 10, 100); } else if (burglaryCounter < 50) { DaggerfallUI.MessageBox(burglaryString2()); burglaryCounter += Mathf.Clamp(UnityEngine.Random.Range(100, 200) - playerEntity.Stats.LiveLuck, 10, 100); } else { burglaryCounter += Mathf.Clamp(UnityEngine.Random.Range(100, 200) - playerEntity.Stats.LiveLuck, 10, 100); } } } } DaggerfallUnityItem ringSlot0 = playerEntity.ItemEquipTable.GetItem(EquipSlots.Ring0); DaggerfallUnityItem ringSlot1 = playerEntity.ItemEquipTable.GetItem(EquipSlots.Ring1); DaggerfallUnityItem markSlot0 = playerEntity.ItemEquipTable.GetItem(EquipSlots.Mark0); DaggerfallUnityItem markSlot1 = playerEntity.ItemEquipTable.GetItem(EquipSlots.Mark1); DaggerfallUnityItem braceletSlot0 = playerEntity.ItemEquipTable.GetItem(EquipSlots.Bracelet0); DaggerfallUnityItem braceletSlot1 = playerEntity.ItemEquipTable.GetItem(EquipSlots.Bracelet1); DaggerfallUnityItem bracerSlot0 = playerEntity.ItemEquipTable.GetItem(EquipSlots.Bracer0); DaggerfallUnityItem bracerSlot1 = playerEntity.ItemEquipTable.GetItem(EquipSlots.Bracer1); DaggerfallUnityItem crystalSlot0 = playerEntity.ItemEquipTable.GetItem(EquipSlots.Crystal0); DaggerfallUnityItem crystalSlot1 = playerEntity.ItemEquipTable.GetItem(EquipSlots.Crystal1); if (ringSlot0 != null && ringSlot0.TemplateIndex == templateIndex_Ring) { lockpickingBonus = 20; } else if (ringSlot1 != null && ringSlot1.TemplateIndex == templateIndex_Ring) { lockpickingBonus = 20; } else { lockpickingBonus = 0; } if (markSlot0 != null && markSlot0.TemplateIndex == templateIndex_Mark) { streetwiseBonus = 20; } else if (markSlot1 != null && markSlot1.TemplateIndex == templateIndex_Mark) { streetwiseBonus = 20; } else { streetwiseBonus = 0; } if (braceletSlot0 != null && braceletSlot0.TemplateIndex == templateIndex_Bracelet) { pickpocketBonus = 20; } else if (braceletSlot1 != null && braceletSlot1.TemplateIndex == templateIndex_Bracelet) { pickpocketBonus = 20; } else { pickpocketBonus = 0; } if (bracerSlot0 != null && bracerSlot0.TemplateIndex == templateIndex_Bracer) { climbingBonus = 20; } else if (bracerSlot1 != null && bracerSlot1.TemplateIndex == templateIndex_Bracer) { climbingBonus = 20; } else { climbingBonus = 0; } if (crystalSlot0 != null && crystalSlot0.TemplateIndex == templateIndex_Crystal) { stealthBonus = 20; } else if (crystalSlot1 != null && crystalSlot1.TemplateIndex == templateIndex_Crystal) { stealthBonus = 20; } else { stealthBonus = 0; } if (!GameManager.IsGamePaused && playerEntity.CurrentHealth > 0) { int[] skillMods = new int[DaggerfallSkills.Count]; skillMods[(int)DFCareer.Skills.Lockpicking] = +lockpickingBonus; skillMods[(int)DFCareer.Skills.Streetwise] = +streetwiseBonus; skillMods[(int)DFCareer.Skills.Pickpocket] = +pickpocketBonus; skillMods[(int)DFCareer.Skills.Climbing] = +climbingBonus; skillMods[(int)DFCareer.Skills.Stealth] = +stealthBonus; playerEffectManager.MergeDirectSkillMods(skillMods); } }