예제 #1
0
        public PyDataType CharAddImplant(PyInteger itemID, CallInformation call)
        {
            if (this.Character.SkillQueue.Count > 0)
            {
                throw new FailedPlugInImplant();
            }

            // get the item and plug it into our brain now!
            ItemEntity item = this.ItemFactory.LoadItem(itemID);

            // ensure the item is somewhere we can interact with it
            if (item.LocationID != call.Client.ShipID && item.LocationID != call.Client.StationID)
            {
                throw new CustomError("You do not have direct access to this implant");
            }

            // check if the slot is free or not
            this.Character.EnsureFreeImplantSlot(item);

            // check ownership and skills required to plug in the implant
            item.EnsureOwnership(this.Character);
            item.CheckPrerequisites(this.Character);

            // separate the item if there's more than one
            if (item.Quantity > 1)
            {
                item.Quantity--;

                // notify the client of the stack change
                call.Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(item, item.Quantity + 1));

                // save the item to the database
                item.Persist();

                // create the new item with a default location and flag
                // this way the item location change notification is only needed once
                item = this.ItemFactory.CreateSimpleItem(item.Type, item.OwnerID, 0,
                                                         Flags.None, 1, item.Contraband, item.Singleton);
            }

            int   oldLocationID = item.LocationID;
            Flags oldFlag       = item.Flag;

            item.LocationID = this.Character.ID;
            item.Flag       = Flags.Implant;

            call.Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(item, oldFlag, oldLocationID));

            // add the item to the inventory it belongs
            this.Character.AddItem(item);

            // persist item changes to database
            item.Persist();

            return(null);
        }
예제 #2
0
        public PyDataType MultiMerge(PyList merges, CallInformation call)
        {
            foreach (PyTuple merge in merges.GetEnumerable <PyTuple>())
            {
                if (merge[0] is PyInteger == false || merge[1] is PyInteger == false || merge[2] is PyInteger == false)
                {
                    continue;
                }

                PyInteger fromItemID = merge[0] as PyInteger;
                PyInteger toItemID   = merge[1] as PyInteger;
                PyInteger quantity   = merge[2] as PyInteger;

                if (this.mInventory.Items.TryGetValue(toItemID, out ItemEntity toItem) == false)
                {
                    continue;
                }

                ItemEntity fromItem = this.ItemFactory.GetItem(fromItemID);

                // ignore singleton items
                if (fromItem.Singleton == true || toItem.Singleton == true)
                {
                    continue;
                }
                // ignore items that are not the same type
                if (fromItem.Type.ID != toItem.Type.ID)
                {
                    continue;
                }
                // if we're fully merging two stacks, just remove one item
                if (quantity == fromItem.Quantity)
                {
                    int oldLocationID = fromItem.LocationID;
                    // remove the item
                    this.ItemFactory.DestroyItem(fromItem);
                    // notify the client about the item too
                    call.Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(fromItem, oldLocationID));
                }
                else
                {
                    // change the item's quantity
                    fromItem.Quantity -= quantity;
                    // notify the client about the change
                    call.Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(fromItem, fromItem.Quantity + quantity));
                    fromItem.Persist();
                }

                toItem.Quantity += quantity;
                call.Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(toItem, toItem.Quantity - quantity));
                toItem.Persist();
            }

            return(null);
        }
예제 #3
0
파일: ship.cs 프로젝트: lanicon/EVESharp
        public PyDataType AssembleShip(PyInteger itemID, CallInformation call)
        {
            int callerCharacterID = call.Client.EnsureCharacterIsSelected();
            int stationID         = call.Client.EnsureCharacterIsInStation();

            // ensure the item is loaded somewhere in this node
            // this will usually be taken care by the EVE Client
            if (this.ItemFactory.TryGetItem(itemID, out Ship ship) == false)
            {
                throw new CustomError("Ships not loaded for player and hangar!");
            }

            Character character = this.ItemFactory.GetItem <Character>(callerCharacterID);

            if (ship.OwnerID != callerCharacterID)
            {
                throw new AssembleOwnShipsOnly(ship.OwnerID);
            }

            // do not do anything if item is already assembled
            if (ship.Singleton == true)
            {
                return(new ShipAlreadyAssembled(ship.Type));
            }

            // first split the stack
            if (ship.Quantity > 1)
            {
                // subtract one off the stack
                ship.Quantity -= 1;
                ship.Persist();
                // notify the quantity change
                call.Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(ship, ship.Quantity + 1));

                // create the new item in the database
                Station station = this.ItemFactory.GetStaticStation(stationID);
                ship = this.ItemFactory.CreateShip(ship.Type, station, character);
                // notify the new item
                call.Client.NotifyMultiEvent(OnItemChange.BuildNewItemChange(ship));
            }
            else
            {
                // stack of one, simple as changing the singleton flag
                ship.Singleton = true;
                call.Client.NotifyMultiEvent(OnItemChange.BuildSingletonChange(ship, false));
            }

            // save the ship
            ship.Persist();

            return(null);
        }
예제 #4
0
        private void StackAll(Flags locationFlag, CallInformation call)
        {
            // TODO: ADD CONSTRAINTS CHECKS FOR THE LOCATIONFLAG
            foreach ((int firstItemID, ItemEntity firstItem) in this.mInventory.Items)
            {
                // singleton items are not even checked
                if (firstItem.Singleton == true || firstItem.Flag != locationFlag)
                {
                    continue;
                }

                foreach ((int secondItemID, ItemEntity secondItem) in this.mInventory.Items)
                {
                    // ignore the same itemID as they cannot really be merged
                    if (firstItemID == secondItemID)
                    {
                        continue;
                    }
                    // ignore the item if it's singleton
                    if (secondItem.Singleton == true || secondItem.Flag != locationFlag)
                    {
                        continue;
                    }
                    // ignore the item check if they're not the same type ID
                    if (firstItem.Type.ID != secondItem.Type.ID)
                    {
                        continue;
                    }
                    int oldQuantity = secondItem.Quantity;
                    // add the quantity of the first item to the second
                    secondItem.Quantity += firstItem.Quantity;
                    // also create the notification for the user
                    call.Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(secondItem, oldQuantity));
                    this.ItemFactory.DestroyItem(firstItem);
                    // notify the client about the item too
                    call.Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(firstItem, firstItem.Flag, secondItem.LocationID));
                    // ensure the second item is saved to database too
                    secondItem.Persist();
                    // finally break this loop as the merge was already done
                    break;
                }
            }
        }
예제 #5
0
        private void MoveItemHere(ItemEntity item, Flags newFlag)
        {
            // get the old location stored as it'll be used in the notifications
            int   oldLocation = item.LocationID;
            Flags oldFlag     = item.Flag;

            // rig slots cannot be moved
            if (item.IsInRigSlot() == true)
            {
                throw new CannotRemoveUpgradeManually();
            }

            // special situation, if the old location is a module slot ensure the item is first offlined
            if (item.IsInModuleSlot() == true)
            {
                if (item is ShipModule module)
                {
                    if (module.Attributes[Attributes.isOnline] == 1)
                    {
                        module.StopApplyingEffect("online", Client);
                    }

                    // disable passive effects too
                    module.StopApplyingPassiveEffects(Client);
                }
            }

            // extra special situation, is the new flag an autofit one?
            if (newFlag == Flags.AutoFit)
            {
                // capsules cannot fit anything
                if (this.mInventory.Type.ID == (int)Types.Capsule)
                {
                    throw new CantFitToCapsule();
                }

                if (this.mInventory is Ship ship)
                {
                    // determine where to put the item
                    if (item is ShipModule module)
                    {
                        if (module.IsHighSlot() == true)
                        {
                            newFlag = this.GetFreeHighSlot(ship);
                        }
                        else if (module.IsMediumSlot() == true)
                        {
                            newFlag = this.GetFreeMediumSlot(ship);
                        }
                        else if (module.IsLowSlot() == true)
                        {
                            newFlag = this.GetFreeLowSlot(ship);
                        }
                        else if (module.IsRigSlot() == true)
                        {
                            newFlag = this.GetFreeRigSlot(ship);
                        }
                        else
                        {
                            // this item cannot be fitted, move it to cargo, maybe throw a exception about not being able to fit it?
                            newFlag = Flags.Cargo;
                        }
                    }
                    // TODO: HANDLE CHARGES!
                    else
                    {
                        newFlag = Flags.Cargo;
                    }
                }
                else
                {
                    newFlag = Flags.Hangar;
                }
            }

            // special situation, if the new location is a module slot ensure the item is a singleton (TODO: HANDLE CHARGES TOO)
            if (newFlag.IsModule() == true)
            {
                ShipModule module = null;

                if (item is ShipModule shipModule)
                {
                    module = shipModule;
                }

                if (item.Quantity == 1)
                {
                    // remove item off the old inventory if required
                    if (this.ItemFactory.TryGetItem(item.LocationID, out ItemInventory inventory) == true)
                    {
                        inventory.RemoveItem(item);
                    }

                    OnItemChange changes = new OnItemChange(item);

                    if (item.Singleton == false)
                    {
                        changes.AddChange(ItemChange.Singleton, item.Singleton);
                    }

                    item.LocationID = this.mInventory.ID;
                    item.Flag       = newFlag;
                    item.Singleton  = true;

                    changes
                    .AddChange(ItemChange.LocationID, oldLocation)
                    .AddChange(ItemChange.Flag, (int)oldFlag);

                    // notify the character about the change
                    Client.NotifyMultiEvent(changes);
                    // update meta inventories too
                    this.ItemFactory.MetaInventoryManager.OnItemMoved(item, oldLocation, this.mInventory.ID);

                    // finally persist the item changes
                    item.Persist();
                }
                else
                {
                    // item is not a singleton, create a new item, decrease quantity and send notifications
                    ItemEntity newItem = this.ItemFactory.CreateSimpleItem(item.Type, item.OwnerID, this.mInventory.ID, newFlag, 1, false,
                                                                           true);

                    item.Quantity -= 1;

                    // notify the quantity change and the new item
                    Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(item, item.Quantity + 1));
                    Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(newItem, Flags.None, 0));

                    item.Persist();

                    // replace reference so the following code handle things properly
                    item = newItem;

                    if (item is ShipModule shipModule2)
                    {
                        module = shipModule2;
                    }
                }

                try
                {
                    // apply all the passive effects (this also blocks the item fitting if the initialization fails)
                    module?.ApplyPassiveEffects(Client);
                    // extra check, ensure that the character has the required skills
                }
                catch (UserError)
                {
                    // ensure that the passive effects that got applied already are removed from the item
                    module?.StopApplyingPassiveEffects(Client);

                    int   newOldLocation = item.LocationID;
                    Flags newOldFlag     = item.Flag;

                    // now undo the whole thing
                    item.LocationID = oldLocation;
                    item.Flag       = oldFlag;

                    Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(item, newOldFlag, newOldLocation));
                    throw;
                }

                // ensure the new inventory knows
                this.mInventory.AddItem(item);

                module?.Persist();

                // put the module online after fitting it as long as it's a normal module
                if (module?.IsRigSlot() == false)
                {
                    module?.ApplyEffect("online", Client);
                }
            }
            else
            {
                // remove item off the old inventory if required
                if (this.ItemFactory.TryGetItem(item.LocationID, out ItemInventory inventory) == true)
                {
                    inventory.RemoveItem(item);
                }

                // set the new location for the item
                item.LocationID = this.mInventory.ID;
                item.Flag       = newFlag;

                // notify the character about the change
                Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(item, oldFlag, oldLocation));
                // update meta inventories too
                this.ItemFactory.MetaInventoryManager.OnItemMoved(item, oldLocation, this.mInventory.ID);

                // ensure the new inventory knows
                this.mInventory.AddItem(item);

                // finally persist the item changes
                item.Persist();
            }
        }
예제 #6
0
        public PyDataType InjectSkillIntoBrain(PyList itemIDs, CallInformation call)
        {
            foreach (PyInteger item in itemIDs.GetEnumerable <PyInteger>())
            {
                try
                {
                    // get the item by it's ID and change the location of it
                    Skill skill = this.ItemFactory.GetItem <Skill>(item);

                    // check if the character already has this skill injected
                    if (this.Character.InjectedSkillsByTypeID.ContainsKey(skill.Type.ID) == true)
                    {
                        throw new CharacterAlreadyKnowsSkill(skill.Type);
                    }

                    // is this a stack of skills?
                    if (skill.Quantity > 1)
                    {
                        // add one of the skill into the character's brain
                        Skill newStack = this.ItemFactory.CreateSkill(skill.Type, this.Character, 0, SkillHistoryReason.None);

                        // subtract one from the quantity
                        skill.Quantity -= 1;

                        // save to database
                        skill.Persist();

                        // finally notify the client
                        call.Client.NotifyMultiEvent(OnItemChange.BuildQuantityChange(skill, skill.Quantity + 1));
                        call.Client.NotifyMultiEvent(OnItemChange.BuildNewItemChange(newStack));
                    }
                    else
                    {
                        // store old values for the notification
                        int   oldLocationID = skill.LocationID;
                        Flags oldFlag       = skill.Flag;

                        // now set the new values
                        skill.LocationID = this.Character.ID;
                        skill.Flag       = Flags.Skill;
                        skill.Level      = 0;
                        skill.Singleton  = true;

                        // ensure the character has the skill in his/her brain
                        this.Character.AddItem(skill);

                        // ensure the changes are saved
                        skill.Persist();

                        // notify the character of the change in the item
                        call.Client.NotifyMultiEvent(OnItemChange.BuildLocationChange(skill, oldFlag, oldLocationID));
                        call.Client.NotifyMultiEvent(OnItemChange.BuildSingletonChange(skill, false));
                    }
                }
                catch (CharacterAlreadyKnowsSkill)
                {
                    throw;
                }
                catch (Exception)
                {
                    Log.Error($"Cannot inject itemID {item} into {this.Character.ID}'s brain...");
                    throw;
                }
            }

            // send the skill injected notification to refresh windows if needed
            call.Client.NotifyMultiEvent(new OnSkillInjected());

            return(null);
        }