protected override void OnTick() { if (m_Cycle != 5) { //Display warning message if (KinCityManager.OnLBChangeWarning != null) { KinCityManager.OnLBChangeWarning(m_City); ++m_Cycle; Start(); } } else { //Switch on LB guards KinCityData cityData = KinCityManager.GetCityData(m_City); if (cityData != null) { //Don't change the guards if it's somehow now owned by the GCs if (cityData.ControlingKin == IOBAlignment.None) { return; } cityData.GuardOption = KinCityData.GuardOptions.LordBritish; cityData.ClearAllGuardPosts(); //Switch on patrol npc guard type cityData.SetNPCFlag(KinCityData.NPCFlags.Patrol, true); //Raise event for the regions to sort themselves out with the new changes if (KinCityManager.OnChangeGuards != null) { KinCityManager.OnChangeGuards(m_City, KinCityData.GuardOptions.LordBritish); } } } }
/// <summary> /// Called when [death]. /// </summary> /// <param name="m">The m.</param> /// <returns></returns> public void OnDeath(Mobile m) { if (m is GolemController) { ProcessActivity(KinFactionActivityTypes.GCDeath); } else if (m is PlayerMobile) { PlayerMobile pm = ((PlayerMobile)m); if (pm.IOBRealAlignment == IOBAlignment.None) { return; } KinCityData data = KinCityManager.GetCityData(City); if (data == null) { return; } if (data.ControlingKin == pm.IOBRealAlignment) { ProcessActivity(KinFactionActivityTypes.FriendlyDeath); } else { ProcessActivity(KinFactionActivityTypes.Death); } } else if (m is BaseCreature) { if (((BaseCreature)m).Spawner is KinGuardPost) { ProcessActivity(KinFactionActivityTypes.GuardDeath); } } }
/// <summary> /// Changes the guards. /// </summary> /// <param name="city">The city.</param> /// <param name="guardOption">The guard option.</param> public static void ChangeGuards(KinFactionCities city, KinCityData.GuardOptions guardOption, bool overrideTimeout) { KinCityData cityData = GetCityData(city); if (cityData == null) { return; } if (cityData.GuardOption == guardOption) { return; } if (!overrideTimeout) { if (DateTime.Now <= cityData.LastGuardChangeTime + TimeSpan.FromHours(KinSystemSettings.GuardChangeTimeHours)) { return; } } cityData.LastGuardChangeTime = DateTime.Now; if (guardOption == KinCityData.GuardOptions.LordBritish) { LBGuardTimer timer = new LBGuardTimer(city); timer.Start(); } else { cityData.GuardOption = guardOption; //Switch off patrol npc guard type cityData.SetNPCFlag(KinCityData.NPCFlags.Patrol, false); if (guardOption == KinCityData.GuardOptions.None) { cityData.ClearAllGuardPosts(); } //Update existing guards with the new rules foreach (KinCityData.BeneficiaryData bd in cityData.BeneficiaryDataList) { foreach (KinGuardPost kgp in bd.GuardPosts) { if (kgp != null && !kgp.Deleted) { kgp.UpdateExisitngGuards(); } } } //Raise event for the regions to sort themselves out with the new changes if (KinCityManager.OnChangeGuards != null) { KinCityManager.OnChangeGuards(city, guardOption); } } }
/// <summary> /// Processes the sale, adding the tax to the treasury. /// </summary> /// <param name="city">The city.</param> /// <param name="vendor">The vendor.</param> /// <param name="totalCost">The tax to add</param> public static void ProcessSale(KinFactionCities city, Mobile vendor, int totalTax) { KinCityData data = GetCityData(city); if (data == null) { return; } if (data.ControlingKin != IOBAlignment.None) { data.AddToTreasury(totalTax); } }
/// <summary> /// Processes the activity delta. (Forwards the data on to the relevant city) /// </summary> /// <param name="city">The city.</param> /// <param name="delta">The delta.</param> public static void ProcessActivityDelta(KinFactionCities city, KinFactionActivityTypes type) { KinCityData data = GetCityData(city); if (data == null) { return; } //log that shit Logging.ActivityGranular act = new Server.Engines.IOBSystem.Logging.ActivityGranular(); act.ActivityType = type.ToString(); act.City = city.ToString(); act.Kin = data.ControlingKin.ToString(); act.LogTime = DateTime.Now; Logging.KinFactionLogs.Instance.AddEntityToSerialize(act); data.ProcessActivityDelta(GetActivityDeltaAmount(type)); }
private static void EventSink_Speech(SpeechEventArgs e) { Mobile from = e.Mobile; int[] keywords = e.Keywords; for (int i = 0; i < keywords.Length; ++i) { switch (keywords[i]) { case 0x00EC: // *showscore* { if (KinSystemSettings.PointsEnabled && from is PlayerMobile && from.Alive) { PlayerMobile pm = from as PlayerMobile; from.PublicOverheadMessage(Server.Network.MessageType.Regular, 0x3B2, true, string.Format("Unassisted: {0:0.00}", pm.KinSoloPoints)); from.PublicOverheadMessage(Server.Network.MessageType.Regular, 0x3B2, true, string.Format("Assisted: {0:0.00}", pm.KinTeamPoints)); from.SendMessage("Unassisted: {0:0.00}", pm.KinSoloPoints); from.SendMessage("Assisted: {0:0.00}", pm.KinTeamPoints); from.SendMessage("Power: {0:0.00}", pm.KinPowerPoints); } break; } } } if (e.Mobile != null && e.Mobile is PlayerMobile && e.Mobile.Alive) { if (e.Speech.ToLower().IndexOf("i wish to place a guard post") > -1) { //wooo sanity! PlayerMobile pm = e.Mobile as PlayerMobile; if (pm == null || pm.IOBRealAlignment == IOBAlignment.None) { return; } //Check player is in a faction region if (!(pm.Region is KinCityRegion)) { pm.SendMessage("You are not within a faction city where you are a beneficiary."); return; } //Check they are a beneficiary KinCityData cityData = KinCityManager.GetCityData(((KinCityRegion)pm.Region).KinFactionCity); if (cityData == null) { return; } KinCityData.BeneficiaryData bd = cityData.GetBeneficiary(pm); if (bd == null) { pm.SendMessage("You are not within a faction city where you are a beneficiary."); return; } if (cityData.GuardOption == KinCityData.GuardOptions.LordBritish || cityData.GuardOption == KinCityData.GuardOptions.None) { pm.SendMessage("You may not place a guard post with your city's current guard policy"); return; } IPooledEnumerable eable = pm.GetItemsInRange(5); if (eable != null) { try { foreach (Item i in eable) { if (i != null && i is KinGuardPost && !i.Deleted) { pm.SendMessage("You may not place a guard post this close to another guard post"); return; } } } finally { eable.Free(); eable = null; } } eable = pm.GetItemsInRange(3); if (eable != null) { try { foreach (Item i in eable) { if (i != null && i is BaseDoor && !i.Deleted) { pm.SendMessage("You may not place a guard post this close to a door"); return; } } } finally { eable.Free(); eable = null; } } //Check they have enough spare guard slots if (bd.UnassignedGuardSlots < 1) { pm.SendMessage("You do not have enough free guard slots to create a guard post"); return; } //Test the 8 squares around the target tile to make sure there is nothing blocking there. for (int x = -1; x < 2; x++) { for (int y = -1; y < 2; y++) { if (x == 0 && y == 0) { continue; //ignore the tile where they are standing } Point3D location = pm.Location; location.X += x; location.Y += y; if (!pm.Map.CanSpawnMobile(location)) { pm.SendMessage("You must have at least one free space in every direction around you."); return; } } } //Place & register guard post KinGuardPost kgp = new KinGuardPost(0x429, pm, KinFactionGuardTypes.FactionHenchman, ((KinCityRegion)pm.Region).KinFactionCity); if (bd.RegisterGuardPost(kgp)) { pm.SendMessage("Successfully created guard post."); kgp.MoveToWorld(pm.Location, pm.Map); kgp.Visible = true; } else { kgp.Delete(); } } else if (e.Speech.ToLower().IndexOf("i wish to fund my guard post") > -1) { //wooo sanity! PlayerMobile pm = e.Mobile as PlayerMobile; if (pm == null || pm.IOBRealAlignment == IOBAlignment.None) { return; } pm.SendMessage("Select the guard post you would like to fund"); pm.Target = new KinGuardPostFundTarget(); } else if (e.Speech.ToLower().IndexOf("i renounce my kin status") > -1) { ((PlayerMobile)e.Mobile).ResetIOBRankTime(); e.Mobile.SendMessage("You have reduced your rank."); } } }
/// <summary> /// Function called from heartbeat job /// </summary> public static void ProcessSigils() { //This job is called every two hours, and is responsible for updating the cities' next capture times based on their //capture points. If a city will fall in less than four hours, its precise vortex spawn timer is started. //run if factions is on if (KinSystemSettings.CityCaptureEnabled) { //iterate through all the cities and update their capture time as neccesary foreach (KinFactionCities e in Enum.GetValues(typeof(KinFactionCities))) { KinCityData data = GetCityData(e); if (data == null) { continue; //should be impossible except "Other" } Logging.ActivityProcessing act = new ActivityProcessing(); act.City = data.City.ToString(); act.Kin = data.ControlingKin.ToString(); act.LogTime = DateTime.Now; //sanity if (data.Sigil == null || data.Sigil.Deleted) { Console.WriteLine("Warning: The faction city of " + e.ToString() + "'s sigil appears to have been deleted or not yet assigned."); continue; } if (!data.Sigil.Active) { continue; } //see if this city is in a voting stage which has now expired if (data.HasVotingStageExpired) { //process vote results and move on data.ProcessVotes(); } /* * //if not, but city is still within voting stage then ignore * else if (data.IsVotingStage) * { * continue; * } */ //Ignore if a vortex is already spawned, or in the process of spawning if (data.Sigil.InCapturePhase() || data.Sigil.IsVortexSpawning()) { continue; } //Update the control points / times ////////////////////////////////////////////////////////////////////////////// //Plasma: Explanation on how this works! ////////////////////////////////////////////////////////////////////////////// //A city starts off with 7 days on the clock. Each day passed will always reduce this by one day. //Each two hours, the actvity delta is taken which will be sitting at a max of +/- 100 //This is used to work out a percentage of pro or negative activity. //Note that pro activity counts for only a third that of negativity. This levels the algorithm //as it is constantly declining anyway and thus is balanced. ////////////////////////////////////////////////////////////////////////////// if (data.Sigil.NextEventTime == DateTime.MinValue) { return; } act.PointsProcessed = data.ActivityDelta; act.PreviousDecayTime = data.Sigil.NextEventTime; //plasma: skip all activity stuff if the sigil is in scheduled mode if (!data.Sigil.ScheduledMode) { //data.Sigil.NextEventTime = data.Sigil.NextEventTime.AddHours(-2.0); int activityDelta = data.ActivityDelta; int delayMinutes = 0; if (activityDelta > 0) { //Work out the slight additional increase that at max each beat will allow four extra days in delay delayMinutes = Convert.ToInt32(Math.Floor((double)(activityDelta / 100.0) * 36)); } else { //Work out the possibly massive additional decrease (up to 2.6 hours EXTRA so thats 3.6 hours) delayMinutes = -Convert.ToInt32(Math.Floor((double)(activityDelta / 100.0) * 160)); } //Reduce/increase minutes based on activity data.Sigil.NextEventTime = data.Sigil.NextEventTime.AddMinutes(delayMinutes); } act.NewDecayTime = data.Sigil.NextEventTime; act.TimeDeltaMinutes = (act.PreviousDecayTime - act.NewDecayTime).Minutes; KinFactionLogs.Instance.AddEntityToSerialize(act); //Wipe activity data.ClearActivityDelta(); //If the city's new capture time is in under 4 hours, start vortex spawn timer TimeSpan t = data.Sigil.NextEventTime - DateTime.Now; if (t <= TimeSpan.FromHours(4)) { data.Sigil.StartVortexSpawnTimer(); } } } else { Console.WriteLine("Nothing to do.. Faction town capture not switched on in KinSettings"); } }
/// <summary> /// Transfers owership of a city to a kin or golem controller king /// </summary> /// <param name="city"></param> /// <param name="winners"></param> public static void TransferOwnership(KinFactionCities city, IOBAlignment kin, List <PlayerMobile> winners) { KinCityData cd = GetCityData(city); if (cd == null) { Console.WriteLine("Error in KinCityManager.TransferOwnership() - City Data not found"); return; } //Set props that apply to both GC and Kin cd.CityLeader = null; cd.CaptureTime = DateTime.Now; cd.ClearAllGuardPosts(); cd.ClearActivityDelta(); if (kin == IOBAlignment.None) //GCs! { cd.ControlingKin = kin; //setup defaults for a controller city cd.IsVotingStage = false; cd.TaxRate = 0.0; cd.BeneficiaryDataList.Clear(); cd.UnassignedGuardPostSlots = 0; //Absorb treasury cd.EmptyTreasury(); ChangeGuards(city, KinCityData.GuardOptions.None, true); cd.ClearNPCFLags(); //Update townspeople spawners and switch on GCs UpdateCityNPCSpawners(cd.City); if (OnGolemController != null) { OnGolemController(cd.City, true); } } else { //check to see if the city was previously owned by the controllers if (cd.ControlingKin == IOBAlignment.None) { //if so then apply default settings for a town cd.SetAllNPCFlags(); ChangeGuards(city, KinCityData.GuardOptions.None, true); //Set last change time so they can change the guards immediately cd.LastGuardChangeTime = DateTime.Now.AddHours(-KinSystemSettings.GuardChangeTimeHours); //Update townspeople spawners and switch off GCs UpdateCityNPCSpawners(cd.City); SetGolemControllers(cd.City, false); if (OnGolemController != null) { OnGolemController(cd.City, false); } } else { cd.LastGuardChangeTime = DateTime.Now.AddHours(-KinSystemSettings.GuardChangeTimeHours); } cd.ControlingKin = kin; //Assign voting info cd.BeneficiaryDataList.Clear(); foreach (PlayerMobile pm in winners) { cd.BeneficiaryDataList.Add(new KinCityData.BeneficiaryData(pm, 0)); } //Change the guards to none if it is LB incase the new owners are all red if (cd.GuardOption == KinCityData.GuardOptions.LordBritish) { ChangeGuards(cd.City, KinCityData.GuardOptions.None, true); } //Skip voting if only one beneficiary if (cd.BeneficiaryDataList.Count == 1) { cd.CityLeader = cd.BeneficiaryDataList[0].Pm; } else { cd.IsVotingStage = true; } cd.UnassignedGuardPostSlots = KinSystem.GetCityGuardPostSlots(city); //Voting is controlled by heartbeat } }
/// <summary> /// Updates the city NPC spawners. /// </summary> /// <param name="city">The city.</param> public static void UpdateCityNPCSpawners(KinFactionCities city) { KinCityData data = GetCityData(city); if (data == null) //woo sanity { return; } List <Type> switchOn = new List <Type>(); List <Type> switchOff = new List <Type>(); List <Type> addTo = null; //Populate the spawners to always switch off (kin stuff, fighters, rangers, etc) switchOff.Add(typeof(Fighter)); switchOff.Add(typeof(Ranger)); switchOff.Add(typeof(Paladin)); foreach (KinCityData.NPCFlags npcFlag in Enum.GetValues(typeof(KinCityData.NPCFlags))) { if (npcFlag == KinCityData.NPCFlags.None) { continue; } if (data.GetNPCFlag(npcFlag)) //set reference to relevant collection { addTo = switchOn; } else { addTo = switchOff; } switch (npcFlag) //add NPC types { case KinCityData.NPCFlags.Animal: { addTo.Add(typeof(AnimalTrainer)); addTo.Add(typeof(Veterinarian)); break; } case KinCityData.NPCFlags.Bank: { addTo.Add(typeof(Banker)); addTo.Add(typeof(Minter)); break; } case KinCityData.NPCFlags.Carpenter: { addTo.Add(typeof(GeneralContractor)); addTo.Add(typeof(Carpenter)); addTo.Add(typeof(RealEstateBroker)); addTo.Add(typeof(Architect)); addTo.Add(typeof(StoneCrafter)); break; } case KinCityData.NPCFlags.EatDrink: { addTo.Add(typeof(Barkeeper)); addTo.Add(typeof(Waiter)); addTo.Add(typeof(Cook)); addTo.Add(typeof(TavernKeeper)); addTo.Add(typeof(Farmer)); addTo.Add(typeof(Butcher)); addTo.Add(typeof(Fisherman)); break; } case KinCityData.NPCFlags.FightBroker: { addTo.Add(typeof(FightBroker)); break; } case KinCityData.NPCFlags.Gypsy: { addTo.Add(typeof(GypsyTrader)); break; } case KinCityData.NPCFlags.Healer: { addTo.Add(typeof(Healer)); addTo.Add(typeof(EvilHealer)); addTo.Add(typeof(HealerGuildmaster)); break; } case KinCityData.NPCFlags.Inn: { addTo.Add(typeof(InnKeeper)); break; } case KinCityData.NPCFlags.Mages: { addTo.Add(typeof(Mage)); addTo.Add(typeof(MageGuildmaster)); addTo.Add(typeof(Alchemist)); addTo.Add(typeof(Herbalist)); addTo.Add(typeof(HairStylist)); break; } case KinCityData.NPCFlags.Misc: { addTo.Add(typeof(Tinker)); addTo.Add(typeof(TinkerGuildmaster)); addTo.Add(typeof(Furtrader)); addTo.Add(typeof(Tanner)); addTo.Add(typeof(BardGuildmaster)); addTo.Add(typeof(Bard)); addTo.Add(typeof(Bowyer)); addTo.Add(typeof(MerchantGuildmaster)); addTo.Add(typeof(Shipwright)); addTo.Add(typeof(Mapmaker)); addTo.Add(typeof(Scribe)); addTo.Add(typeof(Jeweler)); addTo.Add(typeof(Baker)); addTo.Add(typeof(MinerGuildmaster)); addTo.Add(typeof(WarriorGuildmaster)); break; } case KinCityData.NPCFlags.Patrol: { addTo.Add(typeof(PatrolGuard)); break; } case KinCityData.NPCFlags.Provisioner: { addTo.Add(typeof(Provisioner)); addTo.Add(typeof(Cobbler)); break; } case KinCityData.NPCFlags.Quest: { addTo.Add(typeof(BaseEscortable)); addTo.Add(typeof(Noble)); addTo.Add(typeof(SeekerOfAdventure)); break; } case KinCityData.NPCFlags.Smith: { addTo.Add(typeof(Blacksmith)); addTo.Add(typeof(BlacksmithGuildmaster)); break; } case KinCityData.NPCFlags.Tailor: { addTo.Add(typeof(Tailor)); addTo.Add(typeof(Weaver)); addTo.Add(typeof(TailorGuildmaster)); break; } case KinCityData.NPCFlags.TownCrier: { addTo.Add(typeof(TownCrier)); break; } case KinCityData.NPCFlags.WeaponArmour: { addTo.Add(typeof(Armorer)); addTo.Add(typeof(Weaponsmith)); break; } } } SetNPCSpawners(city, switchOn, switchOff); }
public static void OnLoad() { try { Console.WriteLine("KinCityManager Loading..."); string filePath = Path.Combine("Saves/AngelIsland", "KinCityManager.bin"); if (!File.Exists(filePath)) { Console.Write("Kin faction city data file not found. Generating default city data..."); foreach (int city in Enum.GetValues(typeof(KinFactionCities))) { _cityData.Add((KinFactionCities)city, new KinCityData((KinFactionCities)city)); } Console.WriteLine("done."); return; } BinaryFileReader datreader = new BinaryFileReader(new BinaryReader(new FileStream(filePath, FileMode.Open, FileAccess.Read))); int version = datreader.ReadInt(); switch (version) { case 1: { int cityCount = datreader.ReadInt(); if (cityCount > 0) { for (int i = 0; i < cityCount; ++i) { try { KinCityData data = new KinCityData(datreader); _cityData.Add(data.City, data); } catch { } } } break; } } //if any were corrupted and failed to load, create a new set of data. foreach (int city in Enum.GetValues(typeof(KinFactionCities))) { if (!_cityData.ContainsKey((KinFactionCities)city)) { Console.WriteLine("Warning: KinCityData for {0} did not load successfully, and a new blank set of data has been created.", ((KinFactionCities)city).ToString()); _cityData.Add((KinFactionCities)city, new KinCityData((KinFactionCities)city)); } } datreader.Close(); } catch (Exception ex) { System.Console.WriteLine("Error loading KinCityManager!"); Scripts.Commands.LogHelper.LogException(ex); } }