/// <summary> /// Called if the vortex was not killed quick enough /// </summary> public void VortexTimeOut() { if (m_Vortex != null && !m_Vortex.Deleted) //sanity { m_Vortex.TimedOut = true; m_Vortex.Kill(); //Hand town over to golem controllers and set next spawn time KinCityManager.TransferOwnership(m_City, IOBAlignment.None, null); SetNewSpawnTime(); } }
/// <summary> /// Called when the vortex is sucessfully killed /// All the points calculation and processing happens here /// </summary> public void VortexDeath() { CaptureData logData = new CaptureData(); logData.City = m_City.ToString(); logData.CaptureTime = DateTime.Now; logData.LogTime = DateTime.Now; //turn off expire timer if (m_Timer != null && m_Timer.Running) { m_Timer.Stop(); } if (KinSystemSettings.OutputCaptureData) { SendMessageToLocalGM(string.Format("Vortex for the city of {0} has been destroyed", m_City.ToString())); } Dictionary <PlayerMobile, double> individualCapturePoints //dual purpose damage dictionary and capture points = new Dictionary <PlayerMobile, double>(); Dictionary <IOBAlignment, int> kinDamageSpread //kin damage spread dictionary = new Dictionary <IOBAlignment, int>(); KinCapturePointList kinCapturePoints = new KinCapturePointList(); //final kin capture point list KinCapturePointList finalCapturePoints = new KinCapturePointList(); //final individual capture point list IOBAlignment winningKin = IOBAlignment.None; //Winning kin double capturePointsPerVortexDamage = 0.0; //Standardised capture points per vortex damage point double capturePointsPerDefensePoint = 0.0; //Standardised capture points per defense point double totalCapturePoints = 0.0; //total capture points int totalVortexDamage = 0; //total vortex damage //First, cycle thru the vortex's damage list and populate individual and kin damage dictionaries foreach (DamageEntry de in m_Vortex.DamageEntries) { PlayerMobile pm = null; //Check this is a real factioner or a factioner's pet if (de.Damager is PlayerMobile && ((PlayerMobile)de.Damager).IsRealFactioner) { pm = ((PlayerMobile)de.Damager); } else if (de.Damager is BaseCreature) { BaseCreature bc = ((BaseCreature)de.Damager); if (bc.ControlMaster != null && bc.ControlMaster is PlayerMobile && ((PlayerMobile)bc.ControlMaster).IsRealFactioner) { pm = ((PlayerMobile)bc.ControlMaster); } else if (bc.Summoned && bc.SummonMaster != null && bc.SummonMaster is PlayerMobile && ((PlayerMobile)bc.SummonMaster).IsRealFactioner) { pm = ((PlayerMobile)bc.SummonMaster); } } if (pm == null) { continue; } //add this player and the damage to the dictionary, to be converted into capture points in the next stage if (individualCapturePoints.ContainsKey(pm)) { individualCapturePoints[pm] += de.DamageGiven; } else { individualCapturePoints.Add(pm, de.DamageGiven); } //keep running total of all damage totalVortexDamage += de.DamageGiven; //also add this damage to the kin dictionary for later if (!kinDamageSpread.ContainsKey(pm.IOBRealAlignment)) { kinDamageSpread.Add(pm.IOBRealAlignment, de.DamageGiven); } else { kinDamageSpread[pm.IOBRealAlignment] += de.DamageGiven; } } //add anyone else from the defense points into the damage list, with 0 damage foreach (PlayerMobile pm in m_DefensePoints.Keys) { if (!individualCapturePoints.ContainsKey(pm)) { individualCapturePoints.Add(pm, 0.0); } } //add up defense points, this will act as the total amount of capture points avaliable foreach (KeyValuePair <PlayerMobile, double> pair in m_DefensePoints) { totalCapturePoints += pair.Value; } //Make sure we have at least 1 capture point to work with if (totalCapturePoints == 0) { totalCapturePoints = 1; } //standardise each damage point of the vortex damage so the vortex is worth KinSystemSettings % of the points capturePointsPerVortexDamage = ((totalCapturePoints * KinSystemSettings.VortexCaptureProportion) / totalVortexDamage); //the remainder contributes to defenders capturePointsPerDefensePoint = ((totalCapturePoints * (1.0 - KinSystemSettings.VortexCaptureProportion) / totalCapturePoints)); //output data thus far to local GM's journal if (KinSystemSettings.OutputCaptureData) { //Individual damage SendMessageToLocalGM("Individual damage to vortex:"); foreach (KeyValuePair <PlayerMobile, double> kvp in individualCapturePoints) { Player p = new Player(kvp.Key); p.Value = kvp.Value; logData.IndividualVortexDamage.Add(p); SendMessageToLocalGM(string.Format("Player {0} inflicted {1} points of damage", kvp.Key.Name, kvp.Value)); } //Total damage SendMessageToLocalGM(string.Format("Total damage inflicted on vortex: {0}", totalVortexDamage)); logData.TotalVortexDamage = totalVortexDamage; //Damage split by Kin SendMessageToLocalGM("Kin damage to vortex:"); foreach (KeyValuePair <IOBAlignment, int> kvp in kinDamageSpread) { StringDoublePair k = new StringDoublePair(); k.Name = kvp.Key.ToString(); k.Value = kvp.Value; logData.KinDamageSpread.Add(k); SendMessageToLocalGM(string.Format("Kin {0} inflicted {1} points of damage", kvp.Key.ToString(), kvp.Value)); } //Individual defense points SendMessageToLocalGM("Individual defense points earnt:"); foreach (KeyValuePair <PlayerMobile, double> kvp in m_DefensePoints) { Player p = new Player(kvp.Key); p.Value = kvp.Value; logData.IndividualDefensePoints.Add(p); SendMessageToLocalGM(string.Format("Player {0} earnt {1} defense points", kvp.Key.Name, kvp.Value)); } //Total defense points SendMessageToLocalGM(string.Format("Total defense (capture) points earnt: {0}", totalCapturePoints)); logData.TotalCapturePoints = totalCapturePoints; //Calculated points SendMessageToLocalGM(string.Format("Capture points per vortex damage : {0}", capturePointsPerVortexDamage)); SendMessageToLocalGM(string.Format("Capture points per defense point : {0}", capturePointsPerDefensePoint)); } //Reformat the individual list into capture points. List <PlayerMobile> pms = new List <PlayerMobile>(); //Temp list foreach (PlayerMobile pm in individualCapturePoints.Keys) { pms.Add(pm); } foreach (PlayerMobile pm in pms) { //reformat damage points individualCapturePoints[pm] *= capturePointsPerVortexDamage; if (m_DefensePoints.ContainsKey(pm)) { //Add any more capture points from defense individualCapturePoints[pm] += (m_DefensePoints[pm] * capturePointsPerDefensePoint); } //add this player's total capture points towards kin total kinCapturePoints.AddPoints(pm.IOBRealAlignment, individualCapturePoints[pm]); } //Free up temp list! pms.Clear(); pms = null; //Sort kin capture points (desc) kinCapturePoints.Sort(); //More output data if (KinSystemSettings.OutputCaptureData) { SendMessageToLocalGM("Total individual capture points:"); foreach (KeyValuePair <PlayerMobile, double> kvp in individualCapturePoints) { Player p = new Player(kvp.Key); p.Value = kvp.Value; logData.IndividualCapturePoints.Add(p); SendMessageToLocalGM(string.Format("Player {0} earnt {1} total capture points", kvp.Key.Name, kvp.Value)); } SendMessageToLocalGM("Total kin capture points:"); foreach (KinCapturePoints points in kinCapturePoints) { StringDoublePair k = new StringDoublePair(); k.Name = points.Obj.ToString(); k.Value = points.Points; logData.KinCapturePoints.Add(k); SendMessageToLocalGM(string.Format("Kin {0} earnt {1} total capture points", points.Obj.ToString(), points.Points)); } } //Now find a winner - but the winning kin must also have done at least x% of the vortex damage for (int i = 0; i < kinCapturePoints.Count; ++i) { IOBAlignment kin = IOBAlignment.None; if (kinCapturePoints[i].Obj is IOBAlignment) { kin = (IOBAlignment)kinCapturePoints[i].Obj; } int damage = 0; if (kinDamageSpread.ContainsKey(kin)) { damage = kinDamageSpread[kin]; } else { damage = 0; } if (damage >= (totalVortexDamage * KinSystemSettings.VortexMinDamagePercentage)) { //found our winner winningKin = kin; break; } else { if (KinSystemSettings.OutputCaptureData) { SendMessageToLocalGM(string.Format("Kin {0} would have won, but didn't do enough damage to the vortex", kin.ToString())); } } } logData.WinningKin = winningKin.ToString(); if (winningKin == IOBAlignment.None || winningKin == IOBAlignment.Healer || winningKin == IOBAlignment.OutCast) { //this shouldn't really happen. //Hand city over to golem controllers KinCityManager.TransferOwnership(m_City, IOBAlignment.None, null); } //Find and move all of this kin into the final capture point list foreach (KeyValuePair <PlayerMobile, double> pair in individualCapturePoints) { if (pair.Key.IOBRealAlignment == winningKin) { finalCapturePoints.AddPoints(pair.Key, pair.Value); } } //woo sanity if (finalCapturePoints.Count == 0) { //this should never happen. //Hand city over to golem controllers KinCityManager.TransferOwnership(m_City, IOBAlignment.None, null); } //Sort capture points list desc finalCapturePoints.Sort(); int totalBenes = 0; //now we want the top x% of this list to act as beneficiaries for the town, with a cap if (finalCapturePoints.Count < KinSystemSettings.BeneficiaryCap) { totalBenes = finalCapturePoints.Count; } else { //plasma: removing the qualification % for now, it's too inhibitive with a little amount of players. totalBenes = KinSystemSettings.BeneficiaryCap; //totalBenes = (int)Math.Round((double)finalCapturePoints.Count * KinSystemSettings.BeneficiaryQualifyPercentage, 0); //Should never happen, but possible depending on the KinSystemSettings variables if (totalBenes < 1) { totalBenes = 1; } } //Send message to winners List <PlayerMobile> winners = new List <PlayerMobile>(); for (int i = 0; i < totalBenes; ++i) { winners.Add(finalCapturePoints[i].Obj as PlayerMobile); } //Send message to all KinSystem.SendKinMessage(string.Format("The City of {0} has fallen to the {1}! ", m_City.ToString(), winningKin == IOBAlignment.None ? "Golem Controller Lord" : IOBSystem.GetIOBName(winningKin))); winners.ForEach(delegate(PlayerMobile pm) { pm.SendMessage("You have qualified as a beneficiary of {0}. Head to the city's control board to vote for a City leader.", m_City.ToString()); }); if (KinSystemSettings.OutputCaptureData) { SendMessageToLocalGM("Final beneficiaries of town:"); foreach (PlayerMobile pm in winners) { Player p = new Player(pm); logData.BeneficiariesCpaturePoints.Add(p); SendMessageToLocalGM(pm.Name); } } //Hand city over to the kin and its beneficiaries KinCityManager.TransferOwnership(m_City, winningKin, winners); m_DefensePoints.Clear(); if (KinSystemSettings.OutputCaptureData) { KinFactionLogs.Instance.AddEntityToSerialize(logData); } //Fianlly set the base next vortex spawn time for this city/sigil SetNewSpawnTime(); }