Ejemplo n.º 1
0
        private Dictionary <int, List <PlanetFaction> > GetPlanetFactions(IDbConnection connection,
                                                                          IReadOnlyDictionary <int, Faction> factionMap)
        {
            Dictionary <int, List <PlanetFaction> > planetPlanetFactionMap = new Dictionary <int, List <PlanetFaction> >();
            IDbCommand command = connection.CreateCommand();

            command.CommandText = "SELECT * FROM PlanetFaction";
            var reader = command.ExecuteReader();

            while (reader.Read())
            {
                int   planetId         = reader.GetInt32(0);
                int   factionId        = reader.GetInt32(1);
                bool  isPublic         = reader.GetBoolean(2);
                int   population       = reader.GetInt32(3);
                int   pdfMembers       = reader.GetInt32(4);
                float playerReputation = (float)reader[5];

                PlanetFaction planetFaction =
                    new PlanetFaction(factionMap[factionId])
                {
                    IsPublic         = isPublic,
                    Population       = population,
                    PDFMembers       = pdfMembers,
                    PlayerReputation = playerReputation
                };

                if (!planetPlanetFactionMap.ContainsKey(planetId))
                {
                    planetPlanetFactionMap[planetId] = new List <PlanetFaction>();
                }
                planetPlanetFactionMap[planetId].Add(planetFaction);
            }
            return(planetPlanetFactionMap);
        }
Ejemplo n.º 2
0
        private void HandlePlanetaryAssaults()
        {
            foreach (Planet planet in GameSettings.Galaxy.Planets)
            {
                if (planet.IsUnderAssault)
                {
                    PlanetFaction controllingForce = planet.PlanetFactionMap[planet.ControllingFaction.Id];
                    foreach (PlanetFaction planetFaction in planet.PlanetFactionMap.Values)
                    {
                        if (planetFaction != controllingForce && planetFaction.IsPublic)
                        {
                            // this is a revolting force
                            long attackPower  = planetFaction.Population * 3 / 4;
                            long defensePower = controllingForce.PDFMembers;
                            // revolting PDF members count triple for their ability to wreck defensive forces
                            attackPower += planetFaction.PDFMembers * 2;
                            double attackMultiplier  = (RNG.GetLinearDouble() / 25.0) + 0.01;
                            double defenseMultiplier = (RNG.GetLinearDouble() / 25.0) + 0.01;

                            if (planetFaction.PDFMembers > 0)
                            {
                                // having PDF members means it's the first round of revolt, triple defensive casualties
                                attackMultiplier        *= 3;
                                planetFaction.PDFMembers = 0;
                            }
                            int defendCasualties = defensePower == 0 ?
                                                   (int)(attackPower * attackMultiplier * 1000) :
                                                   (int)(attackPower * attackMultiplier / defensePower);
                            int attackCasualties = (int)(defensePower * defenseMultiplier / attackPower);
                            planetFaction.Population -= attackCasualties;
                            if (planetFaction.Population <= 100)
                            {
                                planet.IsUnderAssault  = false;
                                planetFaction.IsPublic = false;
                            }
                            controllingForce.PDFMembers -= defendCasualties;
                            controllingForce.Population -= defendCasualties;
                            if (controllingForce.PDFMembers <= 0)
                            {
                                controllingForce.Population += controllingForce.PDFMembers;
                                controllingForce.PDFMembers  = 0;
                                planet.ControllingFaction    = planetFaction.Faction;
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 3
0
        public Planet GenerateNewPlanet(IReadOnlyDictionary <int, PlanetTemplate> planetTemplateMap,
                                        Vector2 position, Faction controllingFaction, Faction infiltratingFaction)
        {
            PlanetTemplate template  = DeterminePlanetTemplate(planetTemplateMap);
            int            nameIndex = RNG.GetIntBelowMax(0, TempPlanetList.PlanetNames.Length);

            while (_usedPlanetNameIndexes.Contains(nameIndex))
            {
                nameIndex = RNG.GetIntBelowMax(0, TempPlanetList.PlanetNames.Length);
            }
            _usedPlanetNameIndexes.Add(nameIndex);
            int importance = (int)(template.ImportanceRange.BaseValue)
                             + (int)(RNG.NextGaussianDouble() * template.ImportanceRange.StandardDeviation);
            int taxLevel =
                RNG.GetIntBelowMax(template.TaxRange.MinValue, template.TaxRange.MaxValue + 1);
            Planet planet = new Planet(_nextId, TempPlanetList.PlanetNames[nameIndex],
                                       position, template, importance, taxLevel);

            _nextId++;

            int popToDistribute = (int)(template.PopulationRange.BaseValue)
                                  + (int)(Mathf.Pow(10, (float)RNG.NextGaussianDouble()) * template.PopulationRange.StandardDeviation);

            // determine if this planet starts with a genestealer cult in place
            // TODO: make this configurable
            if (infiltratingFaction != null)
            {
                double        infiltrationRate = RNG.GetLinearDouble() / 2.0;
                PlanetFaction infiltration     = new PlanetFaction(infiltratingFaction);
                infiltration.PlayerReputation = 0;
                infiltration.IsPublic         = false;
                infiltration.Population       = (int)(popToDistribute * infiltrationRate);
                infiltration.PDFMembers       = (int)(infiltration.Population / 33);
                planet.PlanetFactionMap[infiltratingFaction.Id] = infiltration;
            }

            PlanetFaction planetFaction = new PlanetFaction(controllingFaction);

            planetFaction.PlayerReputation = 0;
            planetFaction.IsPublic         = true;
            planetFaction.Population       = popToDistribute;
            planetFaction.PDFMembers       = popToDistribute / 33;
            planet.PlanetFactionMap[controllingFaction.Id] = planetFaction;
            planet.ControllingFaction = controllingFaction;
            return(planet);
        }
Ejemplo n.º 4
0
        private static Unit GenerateNewArmy(PlanetFaction planetFaction, Planet planet)
        {
            int factionId = planetFaction.Faction.Id;
            // if we got here, the assaulting force doesn't have an army generated
            // generate an army (and decrement it from the population
            Unit newArmy = TempArmyBuilder.GenerateArmyFromPlanetFaction(planetFaction);

            if (!planet.FactionSquadListMap.ContainsKey(factionId))
            {
                planet.FactionSquadListMap[factionId] = new List <Squad>();
            }

            // add unit to faction
            planetFaction.Faction.Units.Add(newArmy);

            // add unit to planet
            foreach (Squad squad in newArmy.GetAllSquads())
            {
                squad.IsInReserve = false;
                squad.Location    = planet;
                planet.FactionSquadListMap[factionId].Add(squad);
            }

            // modify planetFaction based on new unit
            int   headcount = newArmy.GetAllMembers().Count();
            float ratio     = ((float)planetFaction.PDFMembers) /
                              (planetFaction.Population + planetFaction.PDFMembers);
            int pdfHeadcount = (int)(headcount * ratio);

            headcount -= pdfHeadcount;
            planetFaction.PDFMembers -= pdfHeadcount;
            if (planetFaction.PDFMembers < 0)
            {
                headcount -= planetFaction.PDFMembers;
                planetFaction.PDFMembers = 0;
            }
            planetFaction.Population -= headcount;
            if (planetFaction.Population < 0)
            {
                planetFaction.Population = 0;
                // TODO: remove this planetFaction from the planet?
            }
            return(newArmy);
        }
    public static List <Faction> GetContestingFactions(Planet p1)
    {
        List <Faction> l = new List <Faction>();

        foreach (Link link in p1.LinksByPlanetID1.Union(p1.LinksByPlanetID2).ToList())
        {
            Planet otherPlanet = link.PlanetID1 == p1.PlanetID ? link.PlanetByPlanetID2 : link.PlanetByPlanetID1;
            if (otherPlanet.PlanetFactions.FirstOrDefault().Influence == GlobalConst.PlanetWarsMaximumIP && !l.Contains(otherPlanet.PlanetFactions.FirstOrDefault().Faction))
            {
                l.Add(otherPlanet.PlanetFactions.FirstOrDefault().Faction);
            }
        }
        PlanetFaction currentDominant = p1.PlanetFactions.FirstOrDefault();

        if (!l.Contains(currentDominant.Faction) && currentDominant.Influence > 0)
        {
            l.Add(currentDominant.Faction);
        }
        return(l);
    }
    /// <summary>
    /// Updates shadow influence and new owners
    /// </summary>
    /// <param name="db"></param>
    /// <param name="sb">optional spring batle that caused this change (for event logging)</param>
    public static void SetPlanetOwners(IPlanetwarsEventCreator eventCreator, ZkDataContext db = null, SpringBattle sb = null)
    {
        if (db == null)
        {
            db = new ZkDataContext();
        }

        Galaxy gal = db.Galaxies.Single(x => x.IsDefault);

        foreach (Planet planet in gal.Planets)
        {
            if (planet.OwnerAccountID != null)
            {
                foreach (var ps in planet.PlanetStructures.Where(x => x.OwnerAccountID == null))
                {
                    ps.OwnerAccountID = planet.OwnerAccountID;
                    ps.ReactivateAfterBuild();
                }
            }


            PlanetFaction best       = planet.PlanetFactions.OrderByDescending(x => x.Influence).FirstOrDefault();
            Faction       newFaction = planet.Faction;
            Account       newAccount = planet.Account;

            if (best == null || best.Influence < GlobalConst.InfluenceToCapturePlanet)
            {
                // planet not capture

                if (planet.Faction != null)
                {
                    var curFacInfluence =
                        planet.PlanetFactions.Where(x => x.FactionID == planet.OwnerFactionID).Select(x => x.Influence).FirstOrDefault();

                    if (curFacInfluence <= GlobalConst.InfluenceToLosePlanet)
                    {
                        // owners have too small influence, planet belong to nobody
                        newFaction = null;
                        newAccount = null;
                    }
                }
            }
            else
            {
                if (best.Faction != planet.Faction)
                {
                    newFaction = best.Faction;

                    // best attacker without planets
                    Account candidate =
                        planet.AccountPlanets.Where(
                            x => x.Account.FactionID == newFaction.FactionID && x.AttackPoints > 0 && !x.Account.Planets.Any()).OrderByDescending(
                            x => x.AttackPoints).Select(x => x.Account).FirstOrDefault();

                    if (candidate == null)
                    {
                        // best attacker
                        candidate =
                            planet.AccountPlanets.Where(x => x.Account.FactionID == newFaction.FactionID && x.AttackPoints > 0).OrderByDescending(
                                x => x.AttackPoints).ThenBy(x => x.Account.Planets.Count()).Select(x => x.Account).FirstOrDefault();
                    }

                    // best player without planets
                    if (candidate == null)
                    {
                        candidate =
                            newFaction.Accounts.Where(x => !x.Planets.Any()).OrderByDescending(x => x.AccountPlanets.Sum(y => y.AttackPoints)).
                            FirstOrDefault();
                    }

                    // best with planets
                    if (candidate == null)
                    {
                        candidate =
                            newFaction.Accounts.OrderByDescending(x => x.AccountPlanets.Sum(y => y.AttackPoints)).
                            FirstOrDefault();
                    }

                    newAccount = candidate;
                }
            }

            // change has occured
            if (newFaction != planet.Faction)
            {
                // disable structures
                foreach (PlanetStructure structure in planet.PlanetStructures.Where(x => x.StructureType.OwnerChangeDisablesThis))
                {
                    structure.ReactivateAfterBuild();
                    structure.Account = newAccount;
                }

                // delete structures being lost on planet change
                foreach (PlanetStructure structure in
                         planet.PlanetStructures.Where(structure => structure.StructureType.OwnerChangeDeletesThis).ToList())
                {
                    db.PlanetStructures.DeleteOnSubmit(structure);
                }

                // reset attack points memory
                foreach (AccountPlanet acp in planet.AccountPlanets)
                {
                    acp.AttackPoints = 0;
                }

                if (newFaction == null)
                {
                    Account account = planet.Account;
                    Clan    clan    = null;
                    if (account != null)
                    {
                        clan = planet.Account != null ? planet.Account.Clan : null;
                    }

                    db.Events.InsertOnSubmit(eventCreator.CreateEvent("{0} planet {1} owned by {2} {3} was abandoned. {4}",
                                                                      planet.Faction,
                                                                      planet,
                                                                      account,
                                                                      clan,
                                                                      sb));
                    if (account != null)
                    {
                        eventCreator.GhostPm(planet.Account.Name, string.Format(
                                                 "Warning, you just lost planet {0}!! {2}/PlanetWars/Planet/{1}",
                                                 planet.Name,
                                                 planet.PlanetID,
                                                 GlobalConst.BaseSiteUrl));
                    }
                }
                else
                {
                    // new real owner

                    // log messages
                    if (planet.OwnerAccountID == null) // no previous owner
                    {
                        db.Events.InsertOnSubmit(eventCreator.CreateEvent("{0} has claimed planet {1} for {2} {3}. {4}",
                                                                          newAccount,
                                                                          planet,
                                                                          newFaction,
                                                                          newAccount.Clan,
                                                                          sb));
                        eventCreator.GhostPm(newAccount.Name, string.Format(
                                                 "Congratulations, you now own planet {0}!! {2}/PlanetWars/Planet/{1}",
                                                 planet.Name,
                                                 planet.PlanetID,
                                                 GlobalConst.BaseSiteUrl));
                    }
                    else
                    {
                        db.Events.InsertOnSubmit(eventCreator.CreateEvent("{0} of {1} {2} has captured planet {3} from {4} of {5} {6}. {7}",
                                                                          newAccount,
                                                                          newFaction,
                                                                          newAccount.Clan,
                                                                          planet,
                                                                          planet.Account,
                                                                          planet.Faction,
                                                                          planet.Account.Clan,
                                                                          sb));

                        eventCreator.GhostPm(newAccount.Name, string.Format(
                                                 "Congratulations, you now own planet {0}!! {2}/PlanetWars/Planet/{1}",
                                                 planet.Name,
                                                 planet.PlanetID,
                                                 GlobalConst.BaseSiteUrl));

                        eventCreator.GhostPm(planet.Account.Name, string.Format(
                                                 "Warning, you just lost planet {0}!! {2}/PlanetWars/Planet/{1}",
                                                 planet.Name,
                                                 planet.PlanetID,
                                                 GlobalConst.BaseSiteUrl));
                    }


                    if (planet.PlanetStructures.Any(x => x.StructureType.OwnerChangeWinsGame))
                    {
                        WinGame(db, gal, newFaction, eventCreator.CreateEvent("CONGRATULATIONS!! {0} has won the PlanetWars by capturing {1} planet {2}!", newFaction, planet.Faction, planet));
                    }
                }

                planet.Faction = newFaction;
                planet.Account = newAccount;
            }
            ReturnPeacefulDropshipsHome(db, planet);
        }
        db.SaveChanges();
    }
    /// <summary>
    /// Process planet wars turn
    /// </summary>
    /// <param name="mapName"></param>
    /// <param name="extraData"></param>
    /// <param name="db"></param>
    /// <param name="winnerSide">0 = first team wins, 1 = second team wins</param>
    /// <param name="players"></param>
    /// <param name="text"></param>
    /// <param name="sb"></param>
    ///
    public static void ResolveBattleOutcome(string mapName, List <string> extraData, ZkDataContext db, int?winnerSide, List <Account> players, List <Account> firstSidePlayers, StringBuilder text, SpringBattle sb, IPlanetwarsEventCreator eventCreator, ZkLobbyServer.ZkLobbyServer server)
    {
        if (extraData == null)
        {
            extraData = new List <string>();
        }
        Galaxy gal         = db.Galaxies.Single(x => x.IsDefault);
        Planet planet      = gal.Planets.Single(x => x.Resource.InternalName == mapName);
        var    hqStructure = db.StructureTypes.FirstOrDefault(x => x.EffectDisconnectedMetalMalus != null || x.EffectDistanceMetalBonusMax != null);

        text.AppendFormat("Battle on {1}/PlanetWars/Planet/{0} has ended\n", planet.PlanetID, GlobalConst.BaseSiteUrl);

        bool firstFactionWon;
        bool wasFirstCcDestroyed  = false;
        bool wasSecondCcDestroyed = false;

        if (winnerSide != null)
        {
            if (winnerSide == 0)
            {
                firstFactionWon = true;
            }
            else
            {
                firstFactionWon = false;
            }

            wasFirstCcDestroyed  = extraData.Any(x => x.StartsWith("hqkilled,0"));
            wasSecondCcDestroyed = extraData.Any(x => x.StartsWith("hqkilled,1"));
        }
        else
        {
            text.AppendFormat("No winner on this battle!");
            Trace.TraceError("PW battle without a winner {0}", sb != null ? sb.SpringBattleID : (int?)null);
            return;
        }

        Faction firstFaction      = firstSidePlayers.Where(x => x.Faction != null).Select(x => x.Faction).First();
        var     secondSidePlayers = players.Where(x => x.FactionID != firstFaction.FactionID && x.FactionID != null).ToList();
        Faction secondFaction     = null;

        if (secondSidePlayers.Any())
        {
            secondFaction = secondSidePlayers.Where(x => x.Faction != null).Select(x => x.Faction).First();
        }

        Faction winningFaction;
        Faction losingFaction;
        bool    ccDestroyed = false;

        if (firstFactionWon)
        {
            winningFaction = firstFaction;
            losingFaction  = secondFaction;
            ccDestroyed    = wasFirstCcDestroyed;
        }
        else
        {
            winningFaction = secondFaction;
            losingFaction  = firstFaction;
            ccDestroyed    = wasSecondCcDestroyed;
        }

        if (winningFaction == null)
        {
            text.AppendFormat("Winning team had no players!");
            Trace.TraceError("PW battle where the winner had no players!", sb != null ? sb.SpringBattleID : (int?)null);
            return;
        }

        double baseInfluence   = GlobalConst.BaseInfluencePerBattle;
        double influenceChange = baseInfluence;
        double loserInfluence  = 0;
        double ipMultiplier    = 1;

        string influenceReport = "";
        string ipReason;

        bool reducedEnemyInfluence = false;
        bool flippedDominance      = false;
        bool planetConquered       = false;

        if (ccDestroyed)
        {
            ipMultiplier = GlobalConst.PlanetWarsLostCcMultiplier;
            ipReason     = "due to winning but losing Command Centre";
        }
        else
        {
            ipReason = "due to winning flawlessly";
        }


        influenceChange = (influenceChange) * ipMultiplier;
        if (influenceChange < 0)
        {
            influenceChange = 0;
        }
        influenceChange = Math.Floor(influenceChange * 100) / 100;

        PlanetFaction entry = planet.PlanetFactions.FirstOrDefault();

        if (entry == null)
        {
            entry = new PlanetFaction {
                Faction = winningFaction, Planet = planet,
            };
            planet.PlanetFactions.Add(entry);
        }
        // if non-winner currently dominates planet
        if (entry.Faction != winningFaction)
        {
            loserInfluence = entry.Influence;

            // if win is insufficient to change this
            if (loserInfluence >= influenceChange)
            {
                reducedEnemyInfluence = true;
                entry.Influence      -= influenceChange;
            }
            else // flip dominance
            {
                flippedDominance = true;
                planet.PlanetFactions.Remove(entry);
                entry = new PlanetFaction {
                    Faction = winningFaction, Planet = planet,
                };
                planet.PlanetFactions.Add(entry);
                entry.Influence += (influenceChange - loserInfluence);

                if (entry.Influence >= GlobalConst.PlanetWarsMaximumIP)
                {
                    entry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    planetConquered = true;
                }
            }
        }
        else // increase winner's existing dominance
        {
            if (entry.Influence < GlobalConst.PlanetWarsMaximumIP)
            {
                entry.Influence += influenceChange;
                if (entry.Influence >= GlobalConst.PlanetWarsMaximumIP)
                {
                    entry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    planetConquered = true;
                }
            }
        }

        string contestReport = "";
        int    newContested  = 0;

        if (planetConquered)
        {
            foreach (Link link in planet.LinksByPlanetID1.Union(planet.LinksByPlanetID2).ToList())
            {
                Planet        otherPlanet        = link.PlanetID1 == planet.PlanetID ? link.PlanetByPlanetID2 : link.PlanetByPlanetID1;
                PlanetFaction otherPlanetFaction = otherPlanet.PlanetFactions.FirstOrDefault();

                if (otherPlanetFaction.Faction != winningFaction && otherPlanetFaction.Influence > GlobalConst.BreakthroughInfluence)
                {
                    otherPlanetFaction.Influence = GlobalConst.BreakthroughInfluence;
                    if (newContested > 0)
                    {
                        contestReport += ", ";
                    }
                    contestReport += otherPlanet.Name;
                    newContested++;
                }
            }
        }
        if (newContested > 0)
        {
            contestReport = "Adjacent planets now contested: " + contestReport + ".";
        }

        // Check all planets to see if they are contested by a single faction
        string controlReport = "";
        int    newControlled = 0;

        foreach (Planet p1 in gal.Planets)
        {
            List <Faction> l = GetContestingFactions(p1);

            if (l.Count() == 1)
            {
                Faction       f      = l.FirstOrDefault(); // this faction should be made dominant if it is not already
                PlanetFaction cEntry = p1.PlanetFactions.FirstOrDefault();
                if (cEntry.Faction != f)
                {
                    p1.PlanetFactions.Remove(cEntry);
                    cEntry = new PlanetFaction {
                        Faction = f, Planet = p1, Influence = 0
                    };
                    p1.PlanetFactions.Add(cEntry);
                }
                if (cEntry.Influence != GlobalConst.PlanetWarsMaximumIP)
                {
                    cEntry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    if (newControlled > 0)
                    {
                        controlReport += ", ";
                    }
                    controlReport += p1.Name;
                    newControlled++;
                }
            }
        }
        if (newControlled > 0)
        {
            controlReport = "Planets automatically controlled: " + controlReport + ".";
        }

        // Update actual *control* of all planets
        PlanetWarsTurnHandler.SetPlanetOwners(eventCreator, db, sb);

        try
        {
            if (planetConquered)
            {
                influenceReport = String.Format("{0} conquered the planet, gained {1} influence ({2}% {3} of {4})",
                                                winningFaction.Shortcut,
                                                influenceChange,
                                                (int)(ipMultiplier * 100.0),
                                                ipReason,
                                                baseInfluence + " base");
            }
            else
            {
                if (reducedEnemyInfluence)
                {
                    influenceReport = String.Format("{0} reduced influence of {1} by {2} ({3}% {4} of {5}); {6} has {7} influence remaining on {8}",
                                                    winningFaction.Shortcut,
                                                    (losingFaction == null) ? "opposing faction" : losingFaction.Shortcut,
                                                    influenceChange,
                                                    (int)(ipMultiplier * 100.0),
                                                    ipReason,
                                                    baseInfluence + " base",
                                                    entry.Faction,
                                                    entry.Influence,
                                                    entry.Planet);
                }
                else
                {
                    if (flippedDominance)
                    {
                        influenceReport = String.Format("{0} took dominance from {1} and gained {2} influence ({3}% {4} of {5}); {6} now has {7} influence on {8}",
                                                        winningFaction.Shortcut,
                                                        (losingFaction == null) ? "opposing faction" : losingFaction.Shortcut,
                                                        influenceChange,
                                                        (int)(ipMultiplier * 100.0),
                                                        ipReason,
                                                        baseInfluence + " base",
                                                        entry.Faction,
                                                        entry.Influence,
                                                        entry.Planet);
                    }
                    else
                    {
                        influenceReport = String.Format("{0} gained {1} influence ({2}% {3} of {4}); {5} now has {6} influence on {7} ",
                                                        winningFaction.Shortcut,
                                                        influenceChange,
                                                        (int)(ipMultiplier * 100.0),
                                                        ipReason,
                                                        baseInfluence + " base",
                                                        entry.Faction,
                                                        entry.Influence,
                                                        entry.Planet);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        // paranoia!
        try
        {
            var mainEvent = eventCreator.CreateEvent("{0} defeated {1} on {2} in {3}. {4}. {5} {6}",
                                                     winningFaction,
                                                     (losingFaction == null) ? "opposing faction" : losingFaction.Shortcut,
                                                     planet,
                                                     (sb == null) ? "no battle" : string.Format("B{0}", sb.SpringBattleID),
                                                     influenceReport,
                                                     contestReport,
                                                     controlReport
                                                     );
            db.Events.InsertOnSubmit(mainEvent);
            text.AppendLine(mainEvent.PlainText);
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        db.SaveChanges();

        /*gal.Turn++;
         * db.SaveChanges();
         *
         * db = new ZkDataContext(); // is this needed - attempt to fix setplanetownersbeing buggy
         * SetPlanetOwners(eventCreator, db, sb != null ? db.SpringBattles.Find(sb.SpringBattleID) : null);
         * gal = db.Galaxies.Single(x => x.IsDefault);*/
    }
    public static void EndTurn(string mapName, List <string> extraData, ZkDataContext db, int?winNum, List <Account> players, StringBuilder text, SpringBattle sb, List <Account> attackers, IPlanetwarsEventCreator eventCreator, ZkLobbyServer.ZkLobbyServer server)
    {
        if (extraData == null)
        {
            extraData = new List <string>();
        }
        Galaxy gal         = db.Galaxies.Single(x => x.IsDefault);
        Planet planet      = gal.Planets.Single(x => x.Resource.InternalName == mapName);
        var    hqStructure = db.StructureTypes.FirstOrDefault(x => x.EffectDisconnectedMetalMalus != null || x.EffectDistanceMetalBonusMax != null);

        text.AppendFormat("Battle on {1}/PlanetWars/Planet/{0} has ended\n", planet.PlanetID, GlobalConst.BaseSiteUrl);


        Faction attacker  = attackers.Where(x => x.Faction != null).Select(x => x.Faction).First();
        var     defenders = players.Where(x => x.FactionID != attacker.FactionID && x.FactionID != null).ToList();
        bool    isAttackerWinner;
        bool    wasAttackerCcDestroyed = false;
        bool    wasDefenderCcDestroyed = false;

        if (winNum != null)
        {
            if (winNum == 0)
            {
                isAttackerWinner = true;
            }
            else
            {
                isAttackerWinner = false;
            }

            wasAttackerCcDestroyed = extraData.Any(x => x.StartsWith("hqkilled,0"));
            wasDefenderCcDestroyed = extraData.Any(x => x.StartsWith("hqkilled,1"));
        }
        else
        {
            text.AppendFormat("No winner on this battle!");
            Trace.TraceError("PW battle without a winner {0}", sb != null ? sb.SpringBattleID : (int?)null);
            return;
        }

        var evacuatedStructureTypeIDs = GetEvacuatedStructureTypes(extraData, db);

        string influenceReport = "";

        // distribute influence
        // save influence gains
        // give influence to main attackers
        double planetIpDefs = planet.GetEffectiveIpDefense();

        double  baseInfluence         = GlobalConst.BaseInfluencePerBattle;
        double  influenceChange       = baseInfluence;
        double  loserInfluence        = 0;
        Faction loserFaction          = attacker; // TODO make this less awful
        bool    reducedEnemyInfluence = false;
        bool    flippedDominance      = false;
        bool    planetConquered       = false;

        double shipBonus = planet.GetEffectiveShipIpBonus(attacker);

        double defenseBonus = -planetIpDefs;
        double techBonus    = attacker.GetFactionUnlocks().Count() * GlobalConst.InfluencePerTech;
        double ipMultiplier = 1;
        string ipReason;

        if (!isAttackerWinner)
        {
            if (wasDefenderCcDestroyed)
            {
                ipMultiplier = GlobalConst.PlanetWarsDefenderWinKillCcMultiplier;
                ipReason     = "from losing but killing defender's CC";
            }
            else
            {
                ipMultiplier = 0;
                ipReason     = "from losing horribly";
            }
        }
        else
        {
            if (wasAttackerCcDestroyed)
            {
                ipReason     = "from losing own CC";
                ipMultiplier = GlobalConst.PlanetWarsAttackerWinLoseCcMultiplier;
            }
            else
            {
                ipReason = "from winning flawlessly";
            }
        }

        influenceChange = (influenceChange + shipBonus + techBonus + defenseBonus) * ipMultiplier;
        if (influenceChange < 0)
        {
            influenceChange = 0;
        }
        influenceChange = Math.Floor(influenceChange * 100) / 100;

        // main winner influence
        // PlanetFaction entry = planet.PlanetFactions.FirstOrDefault(x => x.Faction == attacker);
        PlanetFaction entry = planet.PlanetFactions.FirstOrDefault();

        if (entry == null)
        {
            entry = new PlanetFaction {
                Faction = attacker, Planet = planet,
            };
            planet.PlanetFactions.Add(entry);
        }
        // if non-winner currently dominates planet
        if (entry.Faction != attacker)
        {
            loserFaction   = entry.Faction;
            loserInfluence = entry.Influence;

            // if win is insufficient to change this
            if (loserInfluence >= influenceChange)
            {
                reducedEnemyInfluence = true;
                entry.Influence      -= influenceChange;
            }
            else // flip dominance
            {
                flippedDominance = true;
                planet.PlanetFactions.Remove(entry);
                entry = new PlanetFaction {
                    Faction = attacker, Planet = planet,
                };
                planet.PlanetFactions.Add(entry);
                entry.Influence += (influenceChange - loserInfluence);

                if (entry.Influence >= GlobalConst.PlanetWarsMaximumIP)
                {
                    entry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    planetConquered = true;
                }
            }
        }
        else // increase winner's existing dominance
        {
            if (entry.Influence < GlobalConst.PlanetWarsMaximumIP)
            {
                entry.Influence += influenceChange;
                if (entry.Influence >= GlobalConst.PlanetWarsMaximumIP)
                {
                    entry.Influence = GlobalConst.PlanetWarsMaximumIP;
                    planetConquered = true;
                }
            }
        }

        // TODO remove dependence on attacker

        if (planetConquered)
        {
            // Contest Adjacent Planets
            // GlobalConst.PlanetWarsBreakthroughIP
        }

        // Check all planets to see if they are contested by a single faction

        try
        {
            if (reducedEnemyInfluence)
            {
                influenceReport = String.Format("{0} reduced influence of {1} by {2} ({3}% {4} of {5}{6}{7}{8})",
                                                attacker.Shortcut,
                                                loserFaction.Shortcut,
                                                influenceChange,
                                                (int)(ipMultiplier * 100.0),
                                                ipReason,
                                                baseInfluence + " base",
                                                techBonus > 0 ? " +" + techBonus + " from techs" : "",
                                                shipBonus > 0 ? " +" + shipBonus + " from dropships" : "",
                                                defenseBonus != 0 ? " -" + -defenseBonus + " from defenses" : "");
            }
            else
            {
                if (flippedDominance)
                {
                    influenceReport = String.Format("{0} took dominance from {1} and gained {2} influence ({3}% {4} of {5}{6}{7}{8})",
                                                    attacker.Shortcut,
                                                    loserFaction.Shortcut,
                                                    influenceChange - loserInfluence,
                                                    (int)(ipMultiplier * 100.0),
                                                    ipReason,
                                                    baseInfluence + " base",
                                                    techBonus > 0 ? " +" + techBonus + " from techs" : "",
                                                    shipBonus > 0 ? " +" + shipBonus + " from dropships" : "",
                                                    defenseBonus != 0 ? " -" + -defenseBonus + " from defenses" : "");
                }
                else
                {
                    influenceReport = String.Format("{0} gained {1} influence ({2}% {3} of {4}{5}{6}{7})",
                                                    attacker.Shortcut,
                                                    influenceChange,
                                                    (int)(ipMultiplier * 100.0),
                                                    ipReason,
                                                    baseInfluence + " base",
                                                    techBonus > 0 ? " +" + techBonus + " from techs" : "",
                                                    shipBonus > 0 ? " +" + shipBonus + " from dropships" : "",
                                                    defenseBonus != 0 ? " -" + -defenseBonus + " from defenses" : "");
                }
            }
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        // distribute metal
        var attackersTotalMetal = CalculateFactionMetalGain(planet, hqStructure, attacker, GlobalConst.PlanetWarsAttackerMetal, eventCreator, db, text, sb);
        var attackerMetal       = Math.Floor(attackersTotalMetal / attackers.Count);

        foreach (Account w in attackers)
        {
            w.ProduceMetal(attackerMetal);
            var ev = eventCreator.CreateEvent("{0} gained {1} metal from battle {2}",
                                              w,
                                              attackerMetal,
                                              sb);
            db.Events.InsertOnSubmit(ev);
            text.AppendLine(ev.PlainText);
        }


        var defendersTotalMetal = planet.OwnerFactionID == null?Math.Floor(GlobalConst.PlanetWarsDefenderMetal) : CalculateFactionMetalGain(planet, hqStructure, planet.Faction, GlobalConst.PlanetWarsDefenderMetal, eventCreator, db, text, sb);

        if (defenders.Count > 0)
        {
            var defenderMetal = Math.Floor(defendersTotalMetal / defenders.Count);
            foreach (Account w in defenders)
            {
                w.ProduceMetal(defenderMetal);
                var ev = eventCreator.CreateEvent("{0} gained {1} metal from battle {2}", w, defenderMetal, sb);
                db.Events.InsertOnSubmit(ev);
                text.AppendLine(ev.PlainText);
            }
        }
        else
        {
            // planet had no defenders, give metal to owner's faction
            if (planet.OwnerFactionID != null)
            {
                planet.Faction.ProduceMetal(defendersTotalMetal);
                var ev = eventCreator.CreateEvent("{0} gained {1} metal from battle {2}", planet.Faction, defendersTotalMetal, sb);
                db.Events.InsertOnSubmit(ev);
            }
        }


        // remove attacker's dropships
        foreach (var pf in planet.PlanetFactions.Where(x => x.Faction == attacker))
        {
            pf.Dropships = 0;
        }


        // remove dropships staying for too long (return to faction pool)
        foreach (var pf in planet.PlanetFactions.Where(x => x.Faction != attacker && x.Dropships > 0 && x.DropshipsLastAdded != null))
        {
            if (DateTime.UtcNow.Subtract(pf.DropshipsLastAdded.Value).TotalMinutes > GlobalConst.PlanetWarsDropshipsStayForMinutes)
            {
                pf.Faction.ProduceDropships(pf.Dropships);
                pf.Dropships = 0;
            }
        }


        // add attack points
        foreach (Account acc in players)
        {
            int ap = acc.Faction == attacker ? GlobalConst.AttackPointsForVictory : GlobalConst.AttackPointsForDefeat;
            if (acc.Faction != null)
            {
                AccountPlanet apentry = planet.AccountPlanets.SingleOrDefault(x => x.AccountID == acc.AccountID);
                if (apentry == null)
                {
                    apentry = new AccountPlanet {
                        AccountID = acc.AccountID, PlanetID = planet.PlanetID
                    };
                    db.AccountPlanets.InsertOnSubmit(apentry);
                }

                apentry.AttackPoints += ap;
            }
            acc.PwAttackPoints += ap;
        }

        // paranoia!
        try
        {
            var mainEvent = eventCreator.CreateEvent("{0} attacked {1} {2} in {3} and {4}. {5}",
                                                     attacker,
                                                     planet.Faction,
                                                     planet,
                                                     sb,
                                                     isAttackerWinner ? "won" : "lost",
                                                     influenceReport
                                                     );
            db.Events.InsertOnSubmit(mainEvent);
            text.AppendLine(mainEvent.PlainText);
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        // destroy pw structures killed ingame
        if (!isAttackerWinner)
        {
            var handled = new List <string>();
            foreach (string line in extraData.Where(x => x.StartsWith("structurekilled", StringComparison.InvariantCulture)))
            {
                string[] data     = line.Substring(16).Split(',');
                string   unitName = data[0];
                if (handled.Contains(unitName))
                {
                    continue;
                }
                handled.Add(unitName);
                foreach (PlanetStructure s in planet.PlanetStructures.Where(x => x.StructureType.IngameUnitName == unitName))
                {
                    if (s.StructureType.IsIngameDestructible)
                    {
                        s.ReactivateAfterDestruction();

                        var ev = eventCreator.CreateEvent("{0} has been disabled on {1} planet {2}. {3}", s.StructureType.Name, planet.Faction, planet, sb);
                        db.Events.InsertOnSubmit(ev);
                        text.AppendLine(ev.PlainText);
                    }
                }
            }
        }
        else
        {
            // attacker won disable all but evacuated
            foreach (var s in planet.PlanetStructures.Where(x => x.StructureType.IsIngameDestructible))
            {
                if (evacuatedStructureTypeIDs.Contains(s.StructureTypeID))
                {
                    var evSaved = eventCreator.CreateEvent("{0} structure {1} on planet {2} has been saved by evacuation. {3}",
                                                           planet.Faction,
                                                           s.StructureType,
                                                           planet,
                                                           sb);
                    db.Events.InsertOnSubmit(evSaved);
                    text.AppendLine(evSaved.PlainText);
                }
                else
                {
                    s.ReactivateAfterDestruction();
                }
            }
            // destroy structures by battle (usually defenses)
            foreach (PlanetStructure s in planet.PlanetStructures.Where(x => x.StructureType.BattleDeletesThis).ToList())
            {
                if (evacuatedStructureTypeIDs.Contains(s.StructureTypeID))
                {
                    var evSaved = eventCreator.CreateEvent("{0} structure {1} on planet {2} has been saved by evacuation. {3}",
                                                           planet.Faction,
                                                           s.StructureType,
                                                           planet,
                                                           sb);
                    db.Events.InsertOnSubmit(evSaved);
                    text.AppendLine(evSaved.PlainText);
                }
                else
                {
                    planet.PlanetStructures.Remove(s);
                }
            }

            var ev = eventCreator.CreateEvent("All non-evacuated structures have been disabled on {0} planet {1}. {2}", planet.Faction, planet, sb);
            db.Events.InsertOnSubmit(ev);
            text.AppendLine(ev.PlainText);
        }

        db.SaveChanges();

        // no longer used?
        //gal.DecayInfluence();
        //gal.SpreadInfluence();

        // process faction energies
        foreach (var fac in db.Factions.Where(x => !x.IsDeleted))
        {
            fac.ProcessEnergy(gal.Turn);
        }

        // process production (incl. victory points)
        gal.ProcessProduction();
        db.SaveChanges();

        var vpFacs = db.Factions.Where(x => x.VictoryPoints > 0);

        if (vpFacs.Count() > 1)
        {
            foreach (var fac in vpFacs)
            {
                fac.VictoryPoints -= Math.Min(fac.VictoryPoints, GlobalConst.VictoryPointDecay);
            }
        }

        // delete one time activated structures
        gal.DeleteOneTimeActivated(eventCreator, db);
        db.SaveChanges();

        // process treaties
        foreach (var tr in db.FactionTreaties.Where(x => x.TreatyState == TreatyState.Accepted || x.TreatyState == TreatyState.Suspended))
        {
            var failedTradeFaction = tr.ProcessTrade(false);
            if (failedTradeFaction == null)
            {
                tr.TreatyState = TreatyState.Accepted;
                if (tr.TurnsTotal != null)
                {
                    tr.TurnsRemaining--;

                    if (tr.TurnsRemaining <= 0) // treaty expired
                    {
                        tr.TreatyState = TreatyState.Ended;
                        tr.FactionByAcceptingFactionID.ProduceMetal(tr.AcceptingFactionGuarantee ?? 0);
                        tr.FactionByProposingFactionID.ProduceMetal(tr.ProposingFactionGuarantee ?? 0);
                    }
                }
            }
            else
            {
                // failed to perform trade
                if (tr.TreatyUnableToTradeMode == TreatyUnableToTradeMode.Suspend)
                {
                    tr.TreatyState = TreatyState.Suspended;
                }
                else
                { // forced cancel
                    tr.CancelTreaty(failedTradeFaction);
                    db.Events.InsertOnSubmit(server.PlanetWarsEventCreator.CreateEvent("Treaty {0} between {1} and {2} cancelled by {3} because it failed to trade", tr, tr.FactionByProposingFactionID, tr.FactionByAcceptingFactionID, failedTradeFaction));
                }
            }
        }

        // burn extra energy
        foreach (var fac in db.Factions.Where(x => !x.IsDeleted))
        {
            fac.ConvertExcessEnergyToMetal();
        }


        int?oldOwner = planet.OwnerAccountID;

        gal.Turn++;
        db.SaveChanges();

        db = new ZkDataContext(); // is this needed - attempt to fix setplanetownersbeing buggy
        SetPlanetOwners(eventCreator, db, sb != null ? db.SpringBattles.Find(sb.SpringBattleID) : null);
        gal = db.Galaxies.Single(x => x.IsDefault);

        var winByVictoryPoints = db.Factions.FirstOrDefault(x => !x.IsDeleted && x.VictoryPoints >= GlobalConst.PlanetWarsVictoryPointsToWin);

        if (winByVictoryPoints != null)
        {
            WinGame(db,
                    gal,
                    winByVictoryPoints,
                    eventCreator.CreateEvent("CONGRATULATIONS!! {0} has won the PlanetWars by getting enough victory points!", winByVictoryPoints));
            db.SaveChanges();
        }


        planet = gal.Planets.Single(x => x.Resource.InternalName == mapName);
        if (planet.OwnerAccountID != oldOwner && planet.OwnerAccountID != null)
        {
            text.AppendFormat("Congratulations!! Planet {0} was conquered by {1} !!  {3}/PlanetWars/Planet/{2}\n",
                              planet.Name,
                              planet.Account.Name,
                              planet.PlanetID,
                              GlobalConst.BaseSiteUrl);
        }

        server.PublishUserProfilePlanetwarsPlayers();

        try
        {
            // store history
            foreach (Planet p in gal.Planets)
            {
                var hist = db.PlanetOwnerHistories.FirstOrDefault(x => x.PlanetID == p.PlanetID && x.Turn == gal.Turn);
                if (hist == null)
                {
                    hist = new PlanetOwnerHistory()
                    {
                        PlanetID = p.PlanetID, Turn = gal.Turn
                    };
                    db.PlanetOwnerHistories.Add(hist);
                }
                hist.OwnerAccountID = p.OwnerAccountID;
                hist.OwnerClanID    = p.OwnerAccountID != null ? p.Account.ClanID : null;
                hist.OwnerFactionID = p.OwnerFactionID;
            }

            db.SaveChanges();
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
            text.AppendLine("error saving history: " + ex);
        }

        //rotate map
        if (GlobalConst.RotatePWMaps)
        {
            db     = new ZkDataContext();
            gal    = db.Galaxies.Single(x => x.IsDefault);
            planet = gal.Planets.Single(x => x.Resource.InternalName == mapName);
            var mapList = db.Resources.Where(x => x.MapPlanetWarsIcon != null && x.Planets.Where(p => p.GalaxyID == gal.GalaxyID).Count() == 0 && x.MapSupportLevel >= MapSupportLevel.Featured &&
                                             x.ResourceID != planet.MapResourceID && x.MapWaterLevel == planet.Resource.MapWaterLevel).ToList();
            if (mapList.Count > 0)
            {
                int      r          = new Random().Next(mapList.Count);
                int      resourceID = mapList[r].ResourceID;
                Resource newMap     = db.Resources.Single(x => x.ResourceID == resourceID);
                text.AppendLine(String.Format("Map cycler - {0} maps found, selected map {1} to replace map {2}", mapList.Count, newMap.InternalName, planet.Resource.InternalName));
                planet.Resource = newMap;
                gal.IsDirty     = true;
            }
            else
            {
                text.AppendLine("Map cycler - no maps found");
            }
            db.SaveChanges();
        }
    }
Ejemplo n.º 9
0
 public static MvcHtmlString PrintInfluence(this HtmlHelper helper, PlanetFaction planetFaction)
 {
     return(PrintInfluence(helper, planetFaction.Faction, planetFaction.Influence));
 }
    /// <summary>
    /// Process planet wars turn
    /// </summary>
    /// <param name="mapName"></param>
    /// <param name="extraData"></param>
    /// <param name="db"></param>
    /// <param name="winNum">0 = attacker wins, 1 = defender wins</param>
    /// <param name="players"></param>
    /// <param name="text"></param>
    /// <param name="sb"></param>
    public static void EndTurn(string mapName, List <string> extraData, ZkDataContext db, int?winNum, List <Account> players, StringBuilder text, SpringBattle sb, List <Account> attackers)
    {
        if (extraData == null)
        {
            extraData = new List <string>();
        }
        Galaxy gal    = db.Galaxies.Single(x => x.IsDefault);
        Planet planet = gal.Planets.Single(x => x.Resource.InternalName == mapName);

        text.AppendFormat("Battle on http://zero-k.info/PlanetWars/Planet/{0} has ended\n", planet.PlanetID);


        Faction attacker  = attackers.Where(x => x.Faction != null).Select(x => x.Faction).First();
        var     defenders = players.Where(x => x.FactionID != attacker.FactionID && x.FactionID != null).ToList();
        bool    isAttackerWinner;
        bool    wasAttackerCcDestroyed = false;
        bool    wasDefenderCcDestroyed = false;

        if (winNum != null)
        {
            if (winNum == 0)
            {
                isAttackerWinner = true;
            }
            else
            {
                isAttackerWinner = false;
            }

            wasAttackerCcDestroyed = extraData.Any(x => x.StartsWith("hqkilled,0"));
            wasDefenderCcDestroyed = extraData.Any(x => x.StartsWith("hqkilled,1"));
        }
        else
        {
            text.AppendFormat("No winner on this battle!");
            Trace.TraceError("PW battle without a winner {0}", sb != null ? sb.SpringBattleID : (int?)null);
            return;
        }

        int    dropshipsSent   = (planet.PlanetFactions.Where(x => x.Faction == attacker).Sum(x => (int?)x.Dropships) ?? 0);
        bool   isLinked        = planet.CanDropshipsAttack(attacker);
        string influenceReport = "";

        // distribute influence
        // save influence gains
        // give influence to main attackers
        double planetDropshipDefs = (planet.PlanetStructures.Where(x => x.IsActive).Sum(x => x.StructureType.EffectDropshipDefense) ?? 0);
        double planetIpDefs       = (planet.PlanetStructures.Where(x => x.IsActive).Sum(x => x.StructureType.EffectReduceBattleInfluenceGain) ?? 0);

        double baseInfluence = GlobalConst.BaseInfluencePerBattle;
        double influence     = baseInfluence;


        double effectiveShips = Math.Max(0, (dropshipsSent - planetDropshipDefs));
        double shipBonus      = effectiveShips * GlobalConst.InfluencePerShip;

        double defenseBonus = -planetIpDefs;
        double techBonus    = attacker.GetFactionUnlocks().Count() * GlobalConst.InfluencePerTech;
        double ipMultiplier = 1;
        string ipReason;

        if (!isAttackerWinner)
        {
            if (wasDefenderCcDestroyed)
            {
                ipMultiplier = 0.2;
                ipReason     = "from losing but killing defender's CC";
            }
            else
            {
                ipMultiplier = 0;
                ipReason     = "from losing horribly";
            }
        }
        else
        {
            if (wasAttackerCcDestroyed)
            {
                ipReason     = "from losing own CC";
                ipMultiplier = 0.5;
            }
            else
            {
                ipReason = "from winning flawlessly";
            }
        }
        if (!isLinked && effectiveShips < GlobalConst.DropshipsForFullWarpIPGain)
        {
            var newMult = effectiveShips / GlobalConst.DropshipsForFullWarpIPGain;
            ipMultiplier *= newMult;
            ipReason      = ipReason + string.Format(" and reduced to {0}% because only {1} of {2} ships needed for warp attack got past defenses", (int)(newMult * 100.0), (int)effectiveShips, GlobalConst.DropshipsForFullWarpIPGain);
        }


        influence = (influence + shipBonus + techBonus) * ipMultiplier + defenseBonus;
        if (influence < 0)
        {
            influence = 0;
        }
        influence = Math.Floor(influence * 100) / 100;

        // main winner influence
        PlanetFaction entry = planet.PlanetFactions.FirstOrDefault(x => x.Faction == attacker);

        if (entry == null)
        {
            entry = new PlanetFaction {
                Faction = attacker, Planet = planet,
            };
            planet.PlanetFactions.Add(entry);
        }

        entry.Influence += influence;


        // clamping of influence
        // gained over 100, sole owner
        if (entry.Influence >= 100)
        {
            entry.Influence = 100;
            foreach (var pf in planet.PlanetFactions.Where(x => x.Faction != attacker))
            {
                pf.Influence = 0;
            }
        }
        else
        {
            var sumOthers = planet.PlanetFactions.Where(x => x.Faction != attacker).Sum(x => (double?)x.Influence) ?? 0;
            if (sumOthers + entry.Influence > 100)
            {
                var excess = sumOthers + entry.Influence - 100;
                foreach (var pf in planet.PlanetFactions.Where(x => x.Faction != attacker))
                {
                    pf.Influence -= pf.Influence / sumOthers * excess;
                }
            }
        }
        try
        {
            influenceReport = String.Format("{0} gained {1} influence ({2}% {3} of {4}{5}{6}{7})",
                                            attacker.Shortcut,
                                            influence,
                                            (int)(ipMultiplier * 100.0),
                                            ipReason,
                                            baseInfluence + " base",
                                            techBonus > 0 ? " +" + techBonus + " from techs" : "",
                                            shipBonus > 0 ? " +" + shipBonus + " from dropships" : "",
                                            defenseBonus != 0 ? " -" + -defenseBonus + " from defenses" : "");
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }


        // distribute metal
        var attackersTotalMetal = Math.Floor(GlobalConst.PlanetWarsAttackerMetal);
        var defendersTotalMetal = Math.Floor(GlobalConst.PlanetWarsDefenderMetal);
        var attackerMetal       = Math.Floor(attackersTotalMetal / attackers.Count);
        var defenderMetal       = Math.Floor(defendersTotalMetal / defenders.Count);

        foreach (Account w in attackers)
        {
            w.ProduceMetal(attackerMetal);
            var ev = Global.CreateEvent("{0} gained {1} metal from battle {2}",
                                        w,
                                        attackerMetal,
                                        sb);
            db.Events.InsertOnSubmit(ev);
            text.AppendLine(ev.PlainText);
        }

        foreach (Account w in defenders)
        {
            w.ProduceMetal(defenderMetal);
            var ev = Global.CreateEvent("{0} gained {1} metal from battle {2}",
                                        w,
                                        defenderMetal,
                                        sb);

            db.Events.InsertOnSubmit(ev);
            text.AppendLine(ev.PlainText);
        }


        // remove dropships
        foreach (var pf in planet.PlanetFactions.Where(x => x.Faction == attacker))
        {
            pf.Dropships = 0;
        }


        // add attack points
        foreach (Account acc in players)
        {
            int ap = acc.Faction == attacker ? GlobalConst.AttackPointsForVictory : GlobalConst.AttackPointsForDefeat;
            if (acc.Faction != null)
            {
                AccountPlanet apentry = planet.AccountPlanets.SingleOrDefault(x => x.AccountID == acc.AccountID);
                if (apentry == null)
                {
                    apentry = new AccountPlanet {
                        AccountID = acc.AccountID, PlanetID = planet.PlanetID
                    };
                    db.AccountPlanets.InsertOnSubmit(apentry);
                }

                apentry.AttackPoints += ap;
            }
            acc.PwAttackPoints += ap;
        }

        // paranoia!
        try
        {
            var mainEvent = Global.CreateEvent("{0} attacked {1} {2} in {3} and {4}. {5}",
                                               attacker,
                                               planet.Faction,
                                               planet,
                                               sb,
                                               isAttackerWinner ? "won. " : "lost. ",
                                               influenceReport
                                               );
            db.Events.InsertOnSubmit(mainEvent);
            text.AppendLine(mainEvent.PlainText);
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
        }

        // destroy pw structures killed ingame
        if (!isAttackerWinner)
        {
            var handled = new List <string>();
            foreach (string line in extraData.Where(x => x.StartsWith("structurekilled")))
            {
                string[] data     = line.Substring(16).Split(',');
                string   unitName = data[0];
                if (handled.Contains(unitName))
                {
                    continue;
                }
                handled.Add(unitName);
                foreach (PlanetStructure s in planet.PlanetStructures.Where(x => x.StructureType.IngameUnitName == unitName))
                {
                    if (s.StructureType.IsIngameDestructible)
                    {
                        s.IsActive        = false;
                        s.ActivatedOnTurn = gal.Turn + (int)(s.StructureType.TurnsToActivate * (GlobalConst.StructureIngameDisableTimeMult - 1));

                        var ev = Global.CreateEvent("{0} has been disabled on {1} planet {2}. {3}", s.StructureType.Name, planet.Faction, planet, sb);
                        db.Events.InsertOnSubmit(ev);
                        text.AppendLine(ev.PlainText);
                    }
                }
            }
        }
        else
        {
            // attacker won disable all
            foreach (var s in planet.PlanetStructures.Where(x => x.StructureType.IsIngameDestructible))
            {
                s.IsActive        = false;
                s.ActivatedOnTurn = gal.Turn + (int)(s.StructureType.TurnsToActivate * (GlobalConst.StructureIngameDisableTimeMult - 1));
            }
            // destroy structures by battle (usually defenses)
            foreach (PlanetStructure s in planet.PlanetStructures.Where(x => x.StructureType.BattleDeletesThis).ToList())
            {
                planet.PlanetStructures.Remove(s);
            }

            var ev = Global.CreateEvent("All structures have been disabled on {0} planet {1}. {2}", planet.Faction, planet, sb);
            db.Events.InsertOnSubmit(ev);
            text.AppendLine(ev.PlainText);
        }

        db.SubmitAndMergeChanges();

        gal.DecayInfluence();
        gal.SpreadInfluence();

        // process faction energies
        foreach (var fac in db.Factions.Where(x => !x.IsDeleted))
        {
            fac.ProcessEnergy(gal.Turn);
        }

        // process production
        gal.ProcessProduction();


        // process treaties
        foreach (var tr in db.FactionTreaties.Where(x => x.TreatyState == TreatyState.Accepted || x.TreatyState == TreatyState.Suspended))
        {
            if (tr.ProcessTrade(false))
            {
                tr.TreatyState = TreatyState.Accepted;
                if (tr.TurnsTotal != null)
                {
                    tr.TurnsRemaining--;
                    if (tr.TurnsRemaining <= 0)
                    {
                        tr.TreatyState = TreatyState.Invalid;
                        db.FactionTreaties.DeleteOnSubmit(tr);
                    }
                }
            }
            else
            {
                tr.TreatyState = TreatyState.Suspended;
            }
        }

        // burn extra energy
        foreach (var fac in db.Factions.Where(x => !x.IsDeleted))
        {
            fac.ConvertExcessEnergyToMetal();
        }


        int?oldOwner = planet.OwnerAccountID;

        gal.Turn++;
        db.SubmitAndMergeChanges();

        db = new ZkDataContext(); // is this needed - attempt to fix setplanetownersbeing buggy
        PlanetwarsController.SetPlanetOwners(db, sb);
        gal = db.Galaxies.Single(x => x.IsDefault);

        planet = gal.Planets.Single(x => x.Resource.InternalName == mapName);
        if (planet.OwnerAccountID != oldOwner && planet.OwnerAccountID != null)
        {
            text.AppendFormat("Congratulations!! Planet {0} was conquered by {1} !!  http://zero-k.info/PlanetWars/Planet/{2}\n",
                              planet.Name,
                              planet.Account.Name,
                              planet.PlanetID);
        }

        try
        {
            // store history
            foreach (Planet p in gal.Planets)
            {
                db.PlanetOwnerHistories.InsertOnSubmit(new PlanetOwnerHistory
                {
                    PlanetID       = p.PlanetID,
                    OwnerAccountID = p.OwnerAccountID,
                    OwnerClanID    = p.OwnerAccountID != null ? p.Account.ClanID : null,
                    OwnerFactionID = p.OwnerFactionID,
                    Turn           = gal.Turn
                });
            }

            db.SubmitChanges();
        }
        catch (Exception ex)
        {
            Trace.TraceError(ex.ToString());
            text.AppendLine("error saving history: " + ex);
        }

        //rotate map
        if (GlobalConst.RotatePWMaps)
        {
            db     = new ZkDataContext();
            gal    = db.Galaxies.Single(x => x.IsDefault);
            planet = gal.Planets.Single(x => x.Resource.InternalName == mapName);
            var mapList = db.Resources.Where(x => x.MapPlanetWarsIcon != null && x.Planets.Where(p => p.GalaxyID == gal.GalaxyID).Count() == 0 && x.FeaturedOrder != null &&
                                             x.ResourceID != planet.MapResourceID && x.MapWaterLevel == planet.Resource.MapWaterLevel).ToList();
            if (mapList.Count > 0)
            {
                int      r          = new Random().Next(mapList.Count);
                int      resourceID = mapList[r].ResourceID;
                Resource newMap     = db.Resources.Single(x => x.ResourceID == resourceID);
                text.AppendLine(String.Format("Map cycler - {0} maps found, selected map {1} to replace map {2}", mapList.Count, newMap.InternalName, planet.Resource.InternalName));
                planet.Resource = newMap;
                gal.IsDirty     = true;
            }
            else
            {
                text.AppendLine("Map cycler - no maps found");
            }
            db.SubmitAndMergeChanges();
        }
    }
Ejemplo n.º 11
0
        public ActionResult SendDropships(int planetID, int count, bool?useWarp)
        {
            var     db  = new ZkDataContext();
            Account acc = db.Accounts.Single(x => x.AccountID == Global.AccountID);

            if (acc.Faction == null)
            {
                return(Content("Join a faction first"));
            }
            Planet planet     = db.Planets.SingleOrDefault(x => x.PlanetID == planetID);
            int    there      = planet.PlanetFactions.Where(x => x.FactionID == acc.FactionID).Sum(x => (int?)x.Dropships) ?? 0;
            bool   accessible = useWarp == true?planet.CanDropshipsWarp(acc.Faction) : planet.CanDropshipsAttack(acc.Faction);

            if (!accessible)
            {
                return(Content(string.Format("That planet cannot be attacked")));
            }
            if (Global.Server.GetPlanetBattles(planet).Any(x => x.IsInGame))
            {
                return(Content("Battle in progress on the planet, cannot send ships"));
            }

            int cnt = Math.Max(count, 0);

            int capa = acc.GetDropshipCapacity();

            if (cnt + there > capa)
            {
                return(Content("Too many dropships on planet - the fleet limit is " + capa));
            }
            cnt = Math.Min(cnt, (int)acc.GetDropshipsAvailable());
            if (useWarp == true)
            {
                cnt = Math.Min(cnt, (int)acc.GetWarpAvailable());
            }
            if (cnt > 0)
            {
                acc.SpendDropships(cnt);
                if (useWarp == true)
                {
                    acc.SpendWarps(cnt);
                    if (cnt < GlobalConst.DropshipsForFullWarpIPGain)
                    {
                        return(Content($"You must send at least {GlobalConst.DropshipsForFullWarpIPGain} dropships when warping"));
                    }
                }

                if (planet.Account != null)
                {
                    Global.Server.GhostPm(planet.Account.Name, string.Format(
                                              "Warning: long range scanners detected fleet of {0} ships inbound to your planet {1} {3}/Planetwars/Planet/{2}",
                                              cnt,
                                              planet.Name,
                                              planet.PlanetID,
                                              GlobalConst.BaseSiteUrl));
                }
                PlanetFaction pac = planet.PlanetFactions.SingleOrDefault(x => x.FactionID == acc.FactionID);
                if (pac == null)
                {
                    pac = new PlanetFaction {
                        FactionID = Global.FactionID, PlanetID = planetID
                    };
                    db.PlanetFactions.InsertOnSubmit(pac);
                }
                pac.Dropships         += cnt;
                pac.DropshipsLastAdded = DateTime.UtcNow;

                if (cnt > 0)
                {
                    db.Events.InsertOnSubmit(PlanetwarsEventCreator.CreateEvent("{0} sends {1} {2} dropships to {3} {4} {5}",
                                                                                acc,
                                                                                cnt,
                                                                                acc.Faction,
                                                                                planet.Faction,
                                                                                planet,
                                                                                useWarp == true ? "using warp drives" : ""));
                }
                db.SaveChanges();
            }
            return(RedirectToAction("Planet", new { id = planetID }));
        }
Ejemplo n.º 12
0
 public static Unit GenerateArmyFromPlanetFaction(PlanetFaction planetFaction)
 {
     return(GenerateArmy(0, planetFaction.Faction));
 }
Ejemplo n.º 13
0
        private void EndOfTurnPlanetUpdate(Planet planet)
        {
            // increase the population of the planet
            float pdfRatio = ((float)planet.PlanetaryDefenseForces) / planet.Population;

            foreach (PlanetFaction planetFaction in planet.PlanetFactionMap.Values)
            {
                float newPop = 0;
                switch (planetFaction.Faction.GrowthType)
                {
                case GrowthType.Logistic:
                    newPop = planetFaction.Population * 1.00015f;
                    break;

                case GrowthType.Conversion:

                    PlanetFaction defaultFaction = planet.PlanetFactionMap
                                                   .Values
                                                   .First(pf => pf.Faction.IsDefaultFaction);
                    // converting factions always convert one new member per week
                    if (defaultFaction?.Population > 0)
                    {
                        defaultFaction.Population--;
                        planetFaction.Population++;
                        float pdfChance = (float)(defaultFaction.PDFMembers) / defaultFaction.Population;
                        if (RNG.GetLinearDouble() < pdfChance)
                        {
                            defaultFaction.PDFMembers--;
                            planetFaction.PDFMembers++;
                        }
                        if (planetFaction.Population > 100)
                        {
                            // at larger sizes, converting factions
                            // also grow organically
                            // at a much faster rate than a normal population
                            newPop = planetFaction.Population * 1.002f;
                        }
                        // if the converting population is larger than
                        // the non-converted PDF force, they start their revolt
                        if (newPop > (planet.PlanetaryDefenseForces - planetFaction.PDFMembers) &&
                            !planet.IsUnderAssault)
                        {
                            planetFaction.IsPublic = true;
                            planet.IsUnderAssault  = true;
                        }
                    }
                    break;

                default:
                    newPop = planetFaction.Population;
                    break;
                }

                planetFaction.Population = (int)newPop;
                if (RNG.GetLinearDouble() < newPop % 1)
                {
                    planetFaction.Population++;
                }

                // if the pdf is less than three percent of the population, more people are drafted
                // additionally, secret factions love to infiltrate the PDF
                if (pdfRatio < 0.03f || !planetFaction.IsPublic)
                {
                    planetFaction.PDFMembers += (int)(newPop * 0.05f);
                }
                else if (planetFaction.Faction == planet.ControllingFaction || !planetFaction.IsPublic)
                {
                    planetFaction.PDFMembers += (int)(newPop * 0.03f);
                }
            }

            // see if the planet is called to tithe a regiment
            //tax level / 50
            if (RNG.GetLinearDouble() < planet.TaxLevel / 50f)
            {
                GenerateNewRegiment(planet);
            }
        }