Пример #1
0
 /// <summary>
 /// Creates a building of given entry at given tile with given owner
 /// </summary>
 /// <param id="entry">Db entry of the building</param>
 /// <param id="tile">Tile if the building</param>
 /// <param id="owner">Owner of the building</param>
 /// <returns>The created building</returns>
 public IScriptBuilding CreateBuilding(IScriptDbEntry entry, IScriptTile tile, IScriptPlayer owner)
 {
   Building bldg = new Building();
   bldg.Initialize((EntryDb)entry, this, (Player)owner, (Tile)tile);
   bldg.InitializeGraphics();
   SendData(Network.MakeServerMessage(MessageType.GameObjCreate, bldg));
   return bldg;
 }
Пример #2
0
    public void PlacePlayer(int n, Player player)
    {
      foreach (var res in Db.Instance.Resources)
      {
        player.ResourceStockpiles[res.Value] += res.Value.StartWith;
      }

      Players.Add(player);
      Tile loc = Map.StartLocations[n];
      int x = loc.X;
      int y = loc.Y;

      // Place buildings
      foreach (var bldgEntry in Db.Instance.Buildings.Where(p => p.Value.BuiltOnStart))
      {
        bool tileOk = false;
        int c = 0;
        Tile t = null;

        // Get random location around center
        while (!tileOk)
        {
          int rx = x + (int)(random.NextDouble() * 8) - 4;
          int ry = y + (int)(random.NextDouble() * 8) - 4;
          t = Map.Tiles[rx, ry];
          if (!Building.CanPlace(Map, t))
          {
            c++;
            if (c > 100)
            {
              Logger.Log("Unable to place building " + bldgEntry.Key + " - no free space", "MapGen");
              break;
            }
          }
          else
          {
            tileOk = true;
          }
        }

        if (tileOk)
        {
          Building bldg = new Building();
          bldg.Initialize(bldgEntry.Value, this, player, t);
          bldg.InitializeGraphics();
          bldg.Completed(false);
        }
      }

      // Place units
      foreach (var unitEntry in Db.Instance.Units.Where(p => p.Value.GivenOnStart > 0))
      {
        for (int i = 0; i < unitEntry.Value.GivenOnStart; i++)
        {
          int rx = x + (int)(random.NextDouble() * 8) - 4;
          int ry = y + (int)(random.NextDouble() * 8) - 4;
          Tile t = Map.Tiles[rx, ry];

          Unit u = new Unit();
          u.Initialize(unitEntry.Value, this, player, t.MapPosition);
          u.InitializeGraphics();
        }
      }
    }
Пример #3
0
 /// <summary>
 /// Method that deserializes the data from the line starting at given position in given context depending on the MessageType
 /// </summary>
 /// <param id="mt">MessageType defining the extend of deserialization which is to be performed</param>
 /// <param id="line">String array containing the serialized data</param>
 /// <param id="position">Current position in the array</param>
 /// <param id="context">Context of the serialized data, game where this INetworkSerializable object is in</param>
 public override void Deserialize(MessageType mt, string[] line, ref int position, WildmenGame context)
 {
   base.Deserialize(mt, line, ref position, context);
   switch (mt)
   {
     case MessageType.GameTransfer:
     case MessageType.GameEffectCreate:
       spawner = (Building)context.GetGameObjectById(int.Parse(line[position++]));
       ((Building)spawner).ResetSpawner(this);
       Spawnee = Db.Instance.Units[line[position++]];
       int playerId = int.Parse(line[position++]);
       owner = context.Players.First(u => u.Id == playerId);
       spawnPoint = new Vector2(float.Parse(line[position++], CultureInfo.InvariantCulture), float.Parse(line[position++], CultureInfo.InvariantCulture));
       break;
     default:
       throw new Exception();
   }
 }
Пример #4
0
    /// <summary>
    /// Carries out the order
    /// </summary>
    private void UpdateDoOrder()
    {
      GameEffect gEff = null;
      Building bldg = null;
      Tile tile = null;
      BuildingDb bldgEntry = null;
      switch (Order)
      {
        case GameObjectOrder.Idle:
          #region
          Logger.Log(string.Format("Unit #{0}:{1} finished move order", this.ObjectUID, this.Entry.Id), "Server update");

          if (!game.IsServer)
          {
            State = GameObjectState.Idle;
          }
          else
          {
            // Find position along traveling vector available for movement
            bool closeFound = false;
            if (NearestTile == null)
            {
              // Nearest Tile not yet updated
              return;
            }

            // If standing too close to other unit, move aside (if possible)
            foreach (var closeUnit in NearestTile.Units)
            {
              // Ignore self
              if (closeUnit == this) continue;
              // Ignore moving units
              if (closeUnit.State == GameObjectState.MovingToOrder) continue;
              // Check minimal distance
              if ((closeUnit.MapPosition - this.MapPosition).Length() < MIN_IDLE_DISTANCE)
              {
                Vector2 vector;
                // If the map positions aren't same, move in the same amount you are standing towards the other unit
                if (this.MapPosition != closeUnit.MapPosition)
                {
                  vector = this.MapPosition - closeUnit.MapPosition;
                  vector.Normalize();
                  OrderPosition = this.MapPosition + vector * DODGE_DISTANCE;
                }
                // If the position is same, come up with some vector
                else
                {
                  // Try to move in same amount you are standing from the origin position of the map
                  vector = this.MapPosition;
                  vector.Normalize();
                  if (NearestTile.Units.Any(q => (q.MapPosition - OrderPosition).Length() >= MOVEMENT_RANGE))
                  {
                    OrderPosition = this.MapPosition + vector * DODGE_DISTANCE;
                  }
                  // If the place is already occupied, try inverted vector and orthogonal vectors
                  else
                  {
                    Vector2 ort = new Vector2(-vector.Y, vector.X);
                    Queue<Vector2> attemptVector = new Queue<Vector2>();
                    attemptVector.Enqueue(ort); attemptVector.Enqueue(-vector);
                    attemptVector.Enqueue(-ort); attemptVector.Enqueue(vector);
                    Vector2 projectedPosition = default(Vector2);
                    while (attemptVector.Count > 0)
                    {
                      projectedPosition = this.MapPosition + attemptVector.Dequeue() * DODGE_DISTANCE;
                      if (NearestTile.Units.Any(q => (q.MapPosition - projectedPosition).Length() >= MOVEMENT_RANGE))
                        break;
                    }
                    // If everything else fails, use last failed
                    OrderPosition = projectedPosition;
                  }
                }

                State = GameObjectState.MovingToOrder;
                closeFound = true;
                game.SendData(Network.MakeServerMessage(MessageType.GameObjUpdate, this));
                break;
              }
            }
            // If there is no other unit, become idle
            if (!closeFound)
            {
              State = GameObjectState.Idle;
            }
            else
            {
              OrderTarget = null;
              OrderRange = MOVEMENT_RANGE;
            }
          }
          #endregion
          break;
        case GameObjectOrder.Attack:
          #region
          if (OrderTarget == null) return;

          if (OrderTarget == this)
          {
            CancelOrders(true);
            return;
          }

          // Animation effect
          TextureTileSet2D tex = new TextureTileSet2D(UI.Instance.GetTexture("combat"), 24, 1);
          Vector2 p = (Position + OrderTarget.Position) / 2;
          gEff = new AnimationEffect(tex, p + AlignmentOffset + Size / 2 - tex.FrameSize / 2, 24, 10, true);
          gEff.Initialize(game, NearestTile);
          this.game.Effects.Add(gEff);

          if (game.IsServer)
          {
            // Apply modifiers
            float amount = entry.AttackAmount;
            if (entry.Modifiers != null)
              for (int i = 0; i < entry.Modifiers.Length; i++)
                if (entry.Modifiers[i].Entry == OrderTarget.Entry)
                  amount *= entry.Modifiers[i].Mod;

            Logger.Log(string.Format("Unit #{0}:{1} attacking (-{2}) #{3}:{4} (before {5}/?)",
              this.ObjectUID, entry.Id, (int)amount, OrderTarget.ObjectUID, OrderTarget.Entry.Id,
              OrderTarget.Health), "Server update");

            // Apply damage
            OrderTarget.ReceiveDamage((int)amount);

            // Check whether target is alive
            if (OrderTarget.Health == 0)
            {
              CancelOrders(true);
              return;
            }
          }
          #endregion
          break;
        case GameObjectOrder.Construct:
          #region
          if (game.IsServer)
          {
            if (OrderTarget != null)
            {
              Debug.Assert(OrderTarget.GetEntityType == GameEntityType.Building);
              Logger.Log(string.Format("Unit #{0}:{1} constructing (+{2}) effect #{3}:{4} (before {5}/100)",
                this.ObjectUID, entry.Id, entry.ConstructAmount, OrderTarget.ObjectUID, OrderTarget.Entry.Id,
                ((Building)OrderTarget).Construction), "Server update");

              // Construct part of the building
              ((Building)OrderTarget).ConstructionProgress(entry.ConstructAmount);

            }
            else
            {
              Logger.Log(string.Format("Unit #{0}:{1} starting construction of {2}",
                this.ObjectUID, entry.Id, OrderEntry.Id), "Server update");
              tile = game.Map.GetTileFlat(OrderPosition);

              // Check whether building can be constructed at given position
              if (!Building.CanPlace(game.Map, tile) || Owner.Fow[tile.X, tile.Y] == 0)
              {
                Logger.Log(string.Format("Unit #{0}:{1} construction of {2} aborted - unable to place",
                  this.ObjectUID, entry.Id, OrderEntry.Id), "Server update");
                CancelOrders(true);
                return;
              }

              bldgEntry = (BuildingDb)OrderEntry;

              // Check whether building can be built more than once
              if (bldgEntry.OnlyOneAllowed && Owner.Buildings.Any(q => q.Entry == bldgEntry))
              {
                ScrollUpMessage("Only one such building allowed at a time", 100, true);
                CancelOrders(true);
                return;
              }

              if (bldgEntry.UnlockedBy != null)
              {
                bldg = Owner.Buildings.FirstOrDefault(q => q.Entry == bldgEntry.UnlockedBy);
                if (bldg == null || !bldg.Constructed)
                {
                  ScrollUpMessage("Building unavailable", 100, true);
                  CancelOrders(true);
                  return;
                }
              }

              // Check whether player canCast enough resources
              if (bldgEntry.Cost != null)
              {
                foreach (var costEntry in bldgEntry.Cost)
                {
                  if (Owner.ResourceStockpiles[costEntry.Entry] < costEntry.Amount)
                  {
                    ScrollUpMessage("Not enough resources", 100, true);
                    CancelOrders(true);
                    return;
                  }
                }
              }

              // Place new building
              bldg = new Building();
              bldg.Initialize(bldgEntry, game, Owner, tile);
              bldg.InitializeGraphics();
              game.SendData(Network.MakeServerMessage(MessageType.GameObjCreate, bldg));

              // Deduct resources from the player
              if (bldgEntry.Cost != null)
                foreach (var costEntry in bldgEntry.Cost)
                  Owner.ResourceStockpiles[costEntry.Entry] -= costEntry.Amount;

              // Set target for this unit (so it will automatically construct the building)
              OrderTarget = bldg;
              OrderEntry = null;

              game.SendData(Network.MakeServerMessage(MessageType.PlayerUpdate, Owner));
              game.SendData(Network.MakeServerMessage(MessageType.GameObjUpdate, this));
            }
          }
          #endregion
          break;
        case GameObjectOrder.Spell:
          #region
          EffectDb effect = (EffectDb)OrderEntry;
          if (game.IsServer)
          {
            // Check whether spell can be cast
            if (effect.UnlockedBy != null)
            {
              bldg = Owner.Buildings.FirstOrDefault(q => q.Entry == effect.UnlockedBy);
              if (bldg == null || !bldg.Constructed)
              {
                CancelOrders(true);
                return;
              }
            }

            Logger.Log(string.Format("Unit #{0}:{1} casting {2}", this.ObjectUID, entry.Id, OrderEntry.Id), "Server update");
            switch (effect.Spell.Target)
            {
              case SpellEntry.TargetType.Tile:
                tile = game.Map.GetTileFlat(OrderPosition);
                gEff = new GameEffect(effect, this, tile);
                gEff.Initialize(game, tile);
                this.game.Effects.Add(gEff);
                break;
              case SpellEntry.TargetType.GameEntity:
                Debug.Assert(OrderTarget != null);
                gEff = new GameEffect(effect, this, OrderTarget);
                gEff.Initialize(game, OrderTarget.NearestTile);
                this.game.Effects.Add(gEff);
                break;
              default:
                throw new Exception("Undefined spell type");
            }
            game.SendData(Network.MakeServerMessage(MessageType.GameEffectCreate, gEff));
          }
          if (!effect.AutoRepeat)
          {
            State = GameObjectState.Idle;
          }
          #endregion
          break;
        case GameObjectOrder.Gather:
          #region
          if (OrderTarget.GetEntityType == GameEntityType.Building)
          {
            Debug.Assert(carryType != null);

            if (carryAmount > 0)
            {
              ScrollUpMessage(string.Format("Returned {0} of {1}", carryAmount, carryType.Name), 50);
            }

            if (game.IsServer)
            {
              // First zoneFound only transfers carried resources and sets order delay, second time around unit moves back to resource
              if (carryAmount > 0)
              {
                Debug.Assert(((BuildingDb)OrderTarget.Entry).ResourceCenter);

                Logger.Log(string.Format("Unit #{0}:{1} returned +{2} of {3} (before {4}) to #{5}:{6}",
                  this.ObjectUID, this.Entry.Id, carryAmount, carryType.Id, Owner.ResourceStockpiles[carryType],
                  OrderTarget.ObjectUID, OrderTarget.Entry.Id), "Server update");

                // Give resources to player
                Owner.ResourceStockpiles[carryType] += carryAmount;
                carryAmount = 0;
                OrderTimeout = GATHER_RETURN_DELAY;

                game.SendData(Network.MakeServerMessage(MessageType.GameObjUpdate, this));
                game.SendData(Network.MakeServerMessage(MessageType.PlayerUpdate, Owner));
              }
              else
              {
                if (lastGatheredResource.Amount == 0)
                {
                  CancelOrders(true);
                  return;
                }
                // Head towards resource
                Debug.Assert(lastGatheredResource != null);
                OrderTarget = lastGatheredResource;
                OrderRange = entry.GatherRange;
                OrderTimeout = entry.GatherSpeed;

                game.SendData(Network.MakeServerMessage(MessageType.GameObjUpdate, this));
              }
            }
          }
          else if (OrderTarget.GetEntityType == GameEntityType.Resource)
          {
            Debug.Assert(carryAmount == 0 || carryType == (ResourceDb)OrderTarget.Entry);
            Resource res = (Resource)OrderTarget;

            if (res.Cooldown > 0) break;

            if (game.IsServer)
            {

              if (carryAmount == 0)
              {
                carryType = (ResourceDb)res.Entry;
              }

              if (res.Amount == 0)
              {
                CancelOrders(true);
                return;
              }

              int take = res.Take(entry.GatherAmount);

              Logger.Log(string.Format("Unit #{0}:{1} gathered +{2} of {3} (before {4}) from #{5}:{6}",
                this.ObjectUID, this.Entry.Id, take, carryType.Id, carryAmount,
                OrderTarget.ObjectUID, OrderTarget.Entry.Id), "Server update");

              carryAmount += take;

              game.SendData(Network.MakeServerMessage(MessageType.GameObjUpdate, res));
              ScrollUpMessage(string.Format("Gathered {0} of {1}", take, OrderTarget.Entry.Name), 30, true);
            }
          }
          else
          {
            CancelOrders(true);
          }

          #endregion
          break;
        case GameObjectOrder.Train:
          #region
          if (game.IsServer)
          {
            bldg = (Building)OrderTarget;
            // If the building is already training, wait
            if (bldg.Spawner != null && bldg.Spawner.Active) break;
            bldgEntry = (BuildingDb)bldg.Entry;

            bool noEntry = true;
            BuildingDb.TrainEntry trainEntry = default(BuildingDb.TrainEntry);
            if (bldgEntry.Trains != null)
            {
              foreach (var iterTrainEntry in bldgEntry.Trains)
              {
                if (iterTrainEntry.TrainFrom == this.entry)
                {
                  noEntry = false;
                  trainEntry = iterTrainEntry;
                  break;
                }
              }
            }

            if (noEntry)
            {
              ScrollUpMessage("Unable to train this unit in this building", 100, true);
              CancelOrders(true);
              return;
            }

            // Check whether player canCast enough resources
            if (trainEntry.Cost != null)
            {
              foreach (var costEntry in trainEntry.Cost)
              {
                if (Owner.ResourceStockpiles[costEntry.Entry] < costEntry.Amount)
                {
                  ScrollUpMessage("Not enough resources", 100, true);
                  CancelOrders(true);
                  return;
                }
              }
            }

            Logger.Log(string.Format("Unit #{0}:{1} start training in #{2}:{3} towards {4}",
              this.ObjectUID, this.Entry.Id, OrderTarget.ObjectUID, OrderTarget.Entry.Id, bldgEntry.Id), "Server update");

            // Initialize spawning of the new unit
            bldg.StartUnitSpawner(trainEntry.TrainTo, trainEntry.Speed);

            // Deduct resources from the player
            if (trainEntry.Cost != null)
              foreach (var costEntry in trainEntry.Cost)
                Owner.ResourceStockpiles[costEntry.Entry] -= costEntry.Amount;
            game.SendData(Network.MakeServerMessage(MessageType.PlayerUpdate, Owner));

            // Info newText
            gEff = new ScrollTextEffect("Training", Position, 50, new Vector2(0, -1));
            gEff.Initialize(game, bldg.NearestTile);
            this.game.Effects.Add(gEff);
            game.SendData(Network.MakeServerMessage(MessageType.GameEffectCreate, gEff));

            // Kill the unit
            Kill(true);
            return;
          }
          #endregion
          break;
      }
    }
Пример #5
0
    /// <summary>
    /// Constructor of this class
    /// </summary>
    /// <param name="spawner">Building doing the spawning</param>
    /// <param name="spawnee">Unit type to spawn</param>
    /// <param name="owner">Owner of the new unit</param>
    /// <param name="spawnPoint">Position of the new unit</param>
    /// <param name="speed">Spawning speed</param>
    public SpawnerEffect(Building spawner, UnitDb spawnee, Player owner, Vector2 spawnPoint, int speed)
    {
      this.spawner = spawner;
      this.Spawnee = spawnee;
      this.owner = owner;
      this.spawnPoint = spawnPoint;

      this.Speed = speed;
      this.Duration = 0;
    }
Пример #6
0
 /// <summary>
 /// Disposes resources used by this instance
 /// </summary>
 public override void Dispose()
 {
   Building bldg;
   if ((bldg = spawner as Building) != null)
     if (bldg.Spawner == this)
       bldg.ResetSpawner(null);
   spawner = null;
   Spawnee = null;
   owner = null;
   base.Dispose();
 }
Пример #7
0
    public bool ShamanAvailable()
    {
      // If shaman is dead or not existing, look for new shaman
      if (shaman == null || shaman.Removed || shaman.Health == 0)
      {
        shaman = null;
        shaman = Units.FirstOrDefault(
          p => ((UnitDb)p.Entry).Shaman && !p.Removed && p.Health != 0);
      }
      // If there is a shaman, player isn't defeated
      if (shaman != null) return true;

      // If there's no shaman spawn place, look for new one
      if (shamanSpawn == null || shamanSpawn.Removed || shamanSpawn.Health == 0 || !shamanSpawn.Constructed)
      {
        var shamanSpawnCandidates = Buildings.Where(
          p => !p.Removed && p.Health != 0 && ((BuildingDb)p.Entry).Spawns != null &&
            ((BuildingDb)p.Entry).Spawns.Any(
              q => q.Entry.Shaman));

        // Try spawn sites that are already constructed
        shamanSpawn = shamanSpawnCandidates.FirstOrDefault(p => p.Constructed);
        // If we found one, player isn't defeated
        if (shamanSpawn != null) return true;

        // Player has no spawn site
        return false;
      }

      // Player has a working spawn place and isn't defeated
      return true;
    }
Пример #8
0
 /// <summary>
 /// Creates a new instance of the Building class using the serialized data
 /// </summary>
 /// <param id="mt">MessageType defining the extend of deserialization which is to be performed</param>
 /// <param id="line">String array containing the serialized data</param>
 /// <param id="position">Current position in the array</param>
 /// <param id="context">Context of the serialized data, game where this INetworkSerializable object is in</param>
 /// <returns>Building created using the provided serialized data</returns>
 public static Building Create(MessageType mt, string[] line, ref int position, WildmenGame context)
 {
   Building b = new Building();
   b.Deserialize(mt, line, ref position, context);
   b.game = context;
   b.ClaimTiles(b.NearestTile);
   b.InitializeGraphics();
   return b;
 }
Пример #9
0
    //

    public void BuildingFinished(Building building)
    {
      GameObjectListModified = true;
    }
Пример #10
0
 public void Unassign(Building building)
 {
   Buildings.Remove(building);
   game.GameObjectListChanged = true;
 }
Пример #11
0
 public void Assign(Building building)
 {
   Buildings.Add(building);
   building.Owner = this;
   game.GameObjectListChanged = true;
 }
Пример #12
0
 /// <summary>
 /// Unassigns building from this Tile
 /// </summary>
 public void Unassign(Building building)
 {
   Debug.Assert(this.Building == building);
   this.Building = null;
 }
Пример #13
0
    // ASSIGNMENT

    /// <summary>
    /// Assigns building to this Tile
    /// </summary>
    public void Assign(Building building)
    {
      if (this.Building == building) return;
      Debug.Assert(this.Building == null);
      this.Building = building;
    }