public void OnAfterDeserialize() { // Clear our runtime lists _weapons.Clear(); _ammo.Clear(); _foods.Clear(); // Clone inspector lists into runtime lists foreach (InventoryWeaponMountInfo info in _weaponMounts) { InventoryWeaponMountInfo clone = new InventoryWeaponMountInfo { Weapon = info.Weapon }; _weapons.Add(clone); } foreach (InventoryAmmoMountInfo info in _ammoMounts) { InventoryAmmoMountInfo clone = new InventoryAmmoMountInfo { Ammo = info.Ammo }; _ammo.Add(clone); } foreach (InventoryFoodMountInfo info in _foodMounts) { InventoryFoodMountInfo clone = new InventoryFoodMountInfo { Item = info.Item }; _foods.Add(clone); } }
// -------------------------------------------------------------------------------------------- // Name : GetAvailableAmmo // Desc : Returns the number of bullets in the inventory for the passed ammo type. If true // is passed for the second parameter this will include bullet at the weapon mount // as well. // -------------------------------------------------------------------------------------------- public override int GetAvailableAmmo(InventoryItemAmmo ammo, bool includeWeapon) { if (!ammo) { return(0); } // Sum all ammo of the correct type on the ammo belt int roundCount = 0; for (int i = 0; i < _ammo.Count; i++) { InventoryAmmoMountInfo ammoMountInfo = _ammo[i]; if (ammoMountInfo.Ammo != ammo) { continue; } roundCount += ammoMountInfo.Rounds; } // Also include ammo at the weapon mount if requested and applicable if (includeWeapon) { for (int i = 0; i < 2; i++) { InventoryWeaponMountInfo weaponMountInfo = _weapons[i]; if (weaponMountInfo.Weapon == null || weaponMountInfo.Weapon.ammo != ammo) { continue; } roundCount += weaponMountInfo.InGunRounds; } } return(roundCount); }
public override CollectableItem DropWeaponItem(int mountIndex) { if (mountIndex < 0 || mountIndex >= _weapons.Count) { return(null); } InventoryWeaponMountInfo itemMount = _weapons[mountIndex]; if (itemMount == null || itemMount.Weapon == null) { return(null); } InventoryItemWeapon weapon = itemMount.Weapon; Vector3 position = _playerPosition != null ? _playerPosition.value : Vector3.zero; position += _playerDirection != null ? _playerDirection.value : Vector3.zero; var droppedItem = weapon.Drop(position); OnItemDropped.Invoke(itemMount.Weapon); _weapons[mountIndex].Weapon = null; return(droppedItem); }
private void OnSwitchWeapon(InventoryWeaponMountInfo wmi) { if (_inventory) { _inventory.DropWeaponItem(wmi.Weapon.weaponType == InventoryWeaponType.SingleHanded ? 0 : 1); int mountIndex = wmi.Weapon.weaponType == InventoryWeaponType.SingleHanded ? 0 : 1; _inventory.AssignWeapon(mountIndex, wmi); } }
// -------------------------------------------------------------------------------------------- // Name : OnAfterDeserialize() // Desc : We use this function so at runtime we clone the Mounts into copies that we can // mutate without any affecting our original lists as defined in the inpsector. // Note : This has to be a deep copy as having two seperate lists referencing the same // Mount objects will still mutate the original data. // -------------------------------------------------------------------------------------------- public void OnAfterDeserialize() { // Clear our runtime lists _weapons.Clear(); _ammo.Clear(); _backpack.Clear(); _recordings.Clear(); // Clone inspector lists into runtime lists foreach (InventoryWeaponMountInfo info in _weaponMounts) { InventoryWeaponMountInfo clone = new InventoryWeaponMountInfo(); clone.Condition = info.Condition; clone.InGunRounds = info.InGunRounds; clone.Weapon = info.Weapon; _weapons.Add(clone); // This implementation supports only two weapons so ignore any others specified if (_weapons.Count == 2) { break; } } foreach (InventoryAmmoMountInfo info in _ammoMounts) { InventoryAmmoMountInfo clone = new InventoryAmmoMountInfo(); clone.Ammo = info.Ammo; clone.Rounds = info.Rounds; _ammo.Add(clone); } foreach (InventoryBackpackMountInfo info in _backpackMounts) { InventoryBackpackMountInfo clone = new InventoryBackpackMountInfo(); clone.Item = info.Item; _backpack.Add(clone); } foreach (InventoryItemAudio recording in _audioRecordings) { _recordings.Add(recording); } // Reset the audio recording selection _activeAudioRecordingIndex = -1; }
// -------------------------------------------------------------------------------------------- // Name : AddWeaponItem // Desc : Adding weapons is actually handled very differently from other // objects. All this function does is record the object we wish // to change to and send out a message to invoke the correct dismount/mount // animations. The ACTUAL pickup is deferred until AssignWeapon function // is called by the Listener. // Note : In DeadEarth the listener is the CharacterManager's which handles syncing // weapon animation. // -------------------------------------------------------------------------------------------- protected bool AddWeaponItem(InventoryItemWeapon inventoryItemWeapon, CollectableWeapon collectableWeapon, bool playAudio) { // Is the weapon we are about to pick up single handled or two handed weapon int mountIndex = (inventoryItemWeapon.weaponType == InventoryWeaponType.SingleHanded) ? 0 : 1; // Create a mount info object to describe the weapon and instance data we wish // to change to. InventoryWeaponMountInfo wmi = new InventoryWeaponMountInfo(); wmi.Weapon = inventoryItemWeapon; wmi.Condition = collectableWeapon.condition; wmi.InGunRounds = collectableWeapon.rounds; // Invoke event so the object in charge of weapon switching and animation (our CharacterManager for example) // can set the process of switching in motion. OnWeaponChange.Invoke(wmi); return(true); }
// ---------------------------------------------------------------------------- // Name : OnClickWeaponMount // Desc : Called when mouse clicks on a Weapon Mount's frame // ---------------------------------------------------------------------------- public void OnClickWeaponMount(Image image) { int mount; if (image == null || !int.TryParse(image.name, out mount)) { Debug.Log("OnEnterWeaponMount Error! Could not parse image name as int"); return; } // Is this a valid mount that's been clicked if (mount >= 0 && mount < _ammoMounts.Count) { // Get Inventory Item InventoryWeaponMountInfo itemMount = _inventory.GetWeapon(mount); // No highlight if nothing at this slot if (itemMount == null || itemMount.Weapon == null) { return; } // We are clicking on the selected item so unselect if (mount == _selectedMount && _selectedPanelType == InventoryPanelType.Weapons) { Invalidate(); image.color = _weaponMountHover; image.fillCenter = false; DisplayWeaponDescription(itemMount.Weapon); } else { Invalidate(); _selectedPanelType = InventoryPanelType.Weapons; _selectedMount = mount; image.color = _weaponMountColor; image.fillCenter = true; DisplayWeaponDescription(itemMount.Weapon); } } }
// ------------------------------------------------------------------------------------------- // Name : OnEnterWeaponMount // Desc : Called when mouse enters a Weapon Mount's frame // ------------------------------------------------------------------------------------------- public void OnEnterWeaponMount(Image image) { int mount; if (image == null || !int.TryParse(image.name, out mount)) { Debug.Log("OnEnterWeaponMount Error! Could not parse image name as int"); return; } // Valid mount index? if (mount >= 0 && mount < _weaponMounts.Count) { // Get Inventory Item InventoryWeaponMountInfo itemMount = _inventory.GetWeapon(mount); // No highlight if nothing at this slot if (itemMount == null || itemMount.Weapon == null) { return; } // Set the hover color of the frame if (_selectedPanelType != InventoryPanelType.Weapons || _selectedMount != mount) { image.color = _weaponMountHover; } // If something is selected then return without updating the Info pane if (_selectedPanelType != InventoryPanelType.None) { return; } // Display Description Window DisplayWeaponDescription(itemMount.Weapon); } }
// ---------------------------------------------------------------------------------- // Name : AssignWeaponToMount // Desc : This function assigns the passed weaponMountInfo DIRECTLY to the specified // mount. // NOTE : This function does no house keeping...it does NOT remove/drop/enable/disable // any weapons and will overwrite anything stored there. You should use // AddItem to add a weapon to the inventory in a usual case. // This function will be used by the FPS Arms Animation System. // ----------------------------------------------------------------------------------- public override void AssignWeapon(int mountIndex, InventoryWeaponMountInfo mountInfo) { if (mountInfo == null || mountInfo.Weapon == null) { return; } if (mountIndex < 0 || mountIndex >= _weapons.Count) { return; } // Assign the new mount info _weapons[mountIndex] = mountInfo; // Play the pickup sound _weapons[mountIndex].Weapon.Pickup(_playerPosition != null ? _playerPosition.value : Vector3.zero); // And then notify them the new weapon has been added if (_notificationQueue) { _notificationQueue.Enqueue("Weapon Mounted : " + mountInfo.Weapon.inventoryName); } }
// -------------------------------------------------------------------------------------------- // Name : DropWeaponItem // Desc : Drop the weapon at the specified mount into the scene // -------------------------------------------------------------------------------------------- public override void DropWeaponItem(int mountIndex, bool playAudio = true) { if (mountIndex < 0 || mountIndex >= _weapons.Count) { return; } // Chck we have a valid BackPack mount in the inventory InventoryWeaponMountInfo itemMount = _weapons[mountIndex]; if (itemMount == null || itemMount.Weapon == null) { return; } // This is the weapon we want to drop InventoryItemWeapon weapon = itemMount.Weapon; // Drop it into the scene Vector3 position = _playerPosition != null ? _playerPosition.value : Vector3.zero; position += _playerDirection != null ? _playerDirection.value : Vector3.zero; CollectableWeapon sceneWeapon = weapon.Drop(position, playAudio) as CollectableWeapon; if (sceneWeapon) { // Copy over instance data from mount into proxy sceneWeapon.condition = itemMount.Condition; sceneWeapon.rounds = itemMount.InGunRounds; } // Nullify the slot so it is empty _weapons[mountIndex].Weapon = null; // Broadcast event that this weapon has been dropped OnWeaponDropped.Invoke(weapon); }
public abstract void AssignWeapon(int mountIndex, InventoryWeaponMountInfo mountInfo);
// -------------------------------------------------------------------------------------------- // Name : Invalidate // Desc : This function updates the UI so all elements reflect the current state of the // user's inventory. This function also resets the Inventory to an unselected // state. // -------------------------------------------------------------------------------------------- protected virtual void Invalidate() { // Make sure its initialized before its is rendered for the first time if (!_isInitialized) { Initialize(); } // Reset Selections _selectedPanelType = InventoryPanelType.None; _selectedMount = -1; // Deactivate Description Panels if (_generalDescriptionLayout.LayoutContainer != null) { _generalDescriptionLayout.LayoutContainer.SetActive(false); } if (_weaponDescriptionLayout.LayoutContainer != null) { _weaponDescriptionLayout.LayoutContainer.SetActive(false); } // Deactivate the action buttons if (_actionButton1.GameObject != null) { _actionButton1.GameObject.SetActive(false); } if (_actionButton2.GameObject != null) { _actionButton2.GameObject.SetActive(false); } // Clear the Weapon Mounts for (int i = 0; i < _weaponMounts.Count; i++) { if (_weaponMounts[i] != null) { if (_weaponMountImages[i] != null) { _weaponMountImages[i].sprite = null; } if (_weaponMountNames[i] != null) { _weaponMountNames[i].text = ""; } if (_weaponMountSliders[i] != null) { _weaponMountSliders[i].enabled = false; } _weaponMounts[i].SetActive(false); _weaponMounts[i].transform.GetComponent <Image>().fillCenter = false; } } // Iterate over the UI Backpack mounts and set all to empty and unselected for (int i = 0; i < _backpackMounts.Count; i++) { // Clear sprite and deactivate mount if (_backpackMountImages[i] != null) { _backpackMountImages[i].gameObject.SetActive(false); _backpackMountImages[i].sprite = null; } // Enable the text for this slot that says "EMPTY" if (_backpackMountText[i] != null) { _backpackMountText[i].gameObject.SetActive(true); } // Make all mounts look unselected if (_backpackMounts[i] != null) { // Get the image of the mount itself (the frame) Image img = _backpackMounts[i].GetComponent <Image>(); if (img) { img.fillCenter = false; img.color = _backpackMountColor; } } } // Configure the ammo slots for (int i = 0; i < _ammoMounts.Count; i++) { // Clear Sprite and deactivate mount if (_ammoMounts[i] != null) { if (_ammoMountImages[i]) { _ammoMountImages[i].gameObject.SetActive(false); _ammoMountImages[i].sprite = null; } } // Enable the text for this slot that says "EMPTY" if (_ammoMountEmptyText[i] != null) { _ammoMountEmptyText[i].gameObject.SetActive(true); } if (_ammoMountRoundsText[i] != null) { _ammoMountRoundsText[i].gameObject.SetActive(false); } // Give Mount Frame unselected look if (_ammoMounts[i] != null) { Image img = _ammoMounts[i].GetComponent <Image>(); if (img) { img.fillCenter = false; img.color = _ammoMountColor; } } } // Other PDA things if (_pDAReferences._autoplayOnPickup) { if (_audioPlayOnPickup) { _pDAReferences._autoplayOnPickup.isOn = true; } else { _pDAReferences._autoplayOnPickup.isOn = false; } } // Finally update the status panel if (_statusPanelUI.HealthSlider) { _statusPanelUI.HealthSlider.value = _health.value; } if (_statusPanelUI.InfectionSlider) { _statusPanelUI.InfectionSlider.value = _infection.value; } if (_statusPanelUI.StaminaSlider) { _statusPanelUI.StaminaSlider.value = _stamina.value; } if (_statusPanelUI.FlashlightSlider) { _statusPanelUI.FlashlightSlider.value = _flashlight.value; } if (_statusPanelUI.NightVisionSlider) { _statusPanelUI.NightVisionSlider.value = _nightvision.value; } // DO we have a valid Inventory Referenc. If so...let's paint it if (_inventory != null) { // Configure Weapons Panel by iterating through each mount for (int i = 0; i < _weaponMounts.Count; i++) { // Do we have a weapon mount here if (_weaponMounts[i] != null) { // Get the matching mount and weapon data from the inventory InventoryWeaponMountInfo weaponMountInfo = _inventory.GetWeapon(i); InventoryItemWeapon weapon = null; if (weaponMountInfo != null) { weapon = weaponMountInfo.Weapon; } // No weapon info here to skip this mount if (weapon == null) { continue; } // Set sprite and name of weapon if (_weaponMountImages[i] != null) { _weaponMountImages[i].sprite = weapon.inventoryImage; } if (_weaponMountNames[i] != null) { _weaponMountNames[i].text = weapon.inventoryName; } // If its a melee weapon then deactivate the entire AmmoInfo section of the UI // otherwise Enabled it and show the Reload Type and Rounds in Gun if (_weaponMountAmmoInfo[i] != null) { if (weapon.weaponFeedType == InventoryWeaponFeedType.Melee) { _weaponMountAmmoInfo[i].SetActive(false); } else { // Activate Mount _weaponMountAmmoInfo[i].SetActive(true); // Display Reload Type if (_weaponMountReloadType[i] != null) { _weaponMountReloadType[i].text = weapon.reloadType.ToString(); } if (_weaponMountRounds[i] != null) { _weaponMountRounds[i].text = weaponMountInfo.InGunRounds + " / " + weapon.ammoCapacity; } } } // Update the condition slider if (_weaponMountSliders[i] != null) { _weaponMountSliders[i].enabled = true; _weaponMountSliders[i].value = weaponMountInfo.Condition; } _weaponMounts[i].SetActive(true); } } // Configure Ammo Mounts for (int i = 0; i < _ammoMounts.Count; i++) { // Clear Sprite and deactivate mount if (_ammoMounts[i] != null) { // Get the ammo and it's mount info for this mount InventoryAmmoMountInfo ammoMountInfo = _inventory.GetAmmo(i); InventoryItemAmmo ammo = null; if (ammoMountInfo != null) { ammo = ammoMountInfo.Ammo; } // No weapon at this mount so skip if (ammo == null) { continue; } // Set image if (_ammoMountImages[i]) { _ammoMountImages[i].gameObject.SetActive(true); _ammoMountImages[i].sprite = ammoMountInfo.Ammo.inventoryImage; } // Set and Enable Rounds Text if (_ammoMountRoundsText[i] != null) { _ammoMountRoundsText[i].gameObject.SetActive(true); _ammoMountRoundsText[i].text = ammoMountInfo.Rounds.ToString(); } // Disable Empty text if (_ammoMountEmptyText[i] != null) { _ammoMountEmptyText[i].gameObject.SetActive(false); } } } // Iterate over the UI Backpack mounts and set all to empty and unselected for (int i = 0; i < _backpackMounts.Count; i++) { if (_backpackMounts[i] != null) { InventoryBackpackMountInfo backpackMountInfo = _inventory.GetBackpack(i); InventoryItem item = null; if (backpackMountInfo != null) { item = backpackMountInfo.Item; } if (item != null) { // Set sprite and activate mount if (_backpackMountImages[i] != null) { _backpackMountImages[i].gameObject.SetActive(true); _backpackMountImages[i].sprite = item.inventoryImage; } // Disable the text for this slot that says "EMPTY" if (_backpackMountText[i] != null) { _backpackMountText[i].gameObject.SetActive(false); } } } } } }
// -------------------------------------------------------------------------------------------- // Name : IsReloadAvailable // Desc : Returns true if ammo exists in the users inventory that has a greater // number of rounds than the number passed. For Partial reload weapons // such as Shotgun, the passed amount will always be 1 as rounds can // be loaded one at a time. For NonPartial (magazine based) it will // only return true if a clip is found that contains MORE rounds // than those currently in the Weapon Mount // -------------------------------------------------------------------------------------------- public override bool IsReloadAvailable(int weaponMountIndex) { if (weaponMountIndex < 0 || weaponMountIndex >= _weapons.Count) { return(false); } // Get the weapon mount and the weapon from that mount InventoryWeaponMountInfo weaponMountInfo = _weapons[weaponMountIndex]; InventoryItemWeapon weapon = weaponMountInfo.Weapon; // If no weapon, no ammo or no ammo needed return false if (!weapon || weapon.reloadType == InventoryWeaponReloadType.None || weapon.weaponType == InventoryWeaponType.None || weaponMountInfo.InGunRounds >= weapon.ammoCapacity || weapon.ammo == null) { return(false); } // If its a Non-Partial Reload type then simply search the belt for a clip // with the most bullets if (weapon.reloadType == InventoryWeaponReloadType.NonPartial) { // Search for a clip in our belt that has the highest round count // that matches the ammo of the gun int roundCount = -1; for (int i = 0; i < _ammo.Count; i++) { InventoryAmmoMountInfo ammoMountInfo = _ammo[i]; if (ammoMountInfo.Ammo != weapon.ammo) { continue; } if (ammoMountInfo.Rounds > roundCount) { roundCount = ammoMountInfo.Rounds; } } // If the highest available rounds found is less than or equal to the // amount we are looking for as a minimum to make a reload worth while return false if (roundCount <= weaponMountInfo.InGunRounds) { return(false); } // A clip has been found so return true to allow a reload to proceed return(true); } else if (weapon.reloadType == InventoryWeaponReloadType.Partial) { // Loop through items on ammo belt searching for the correct ammo type for (int i = 0; i < _ammo.Count; i++) { // If not the right type of ammo then continue InventoryAmmoMountInfo ammoMountInfo = _ammo[i]; if (ammoMountInfo.Ammo != weapon.ammo) { continue; } // Partial reload so only looks for at last 1 if (ammoMountInfo.Rounds > 0) { return(true); } } return(false); } // Fall through case in case we add more reload types return(false); }
// -------------------------------------------------------------------------------------------- // Name : ReloadWeapon // Desc : This function can be called from the InventoryUI and the main game code. Usually, // We will want to play the audio when at the inventory screen but pass false to this // function when calling from real time. // -------------------------------------------------------------------------------------------- public override bool ReloadWeapon(int mountIndex, bool playAudio = true) { // Invalid mount index (This invetory supports only 2 weapon mounts if (mountIndex < 0 || mountIndex > 1) { return(false); } // Get weapon mount and return if no weapon assigned InventoryWeaponMountInfo weaponMountInfo = _weapons[mountIndex]; if (weaponMountInfo.Weapon == null) { return(false); } // To reduce typing :) InventoryItemWeapon weapon = weaponMountInfo.Weapon; InventoryItemAmmo ammo = weapon.ammo; // If no ammo assigned or this mount is already at the gun's capacity...just bail if (ammo == null || weaponMountInfo.InGunRounds >= weapon.ammoCapacity) { return(false); } // If its a Non-Partial Reload type then simply search the belt for a clip // with the most bullets if (weapon.reloadType == InventoryWeaponReloadType.NonPartial) { // Search for a clip in our belt that has the highest round count // that matches the ammoID of the gun int ammoMountCandidate = -1; int roundCount = -1; for (int i = 0; i < _ammo.Count; i++) { InventoryAmmoMountInfo ammoMountInfo = _ammo[i]; // If ammo at this mount is not the correct type of ammo skip it if (ammoMountInfo.Ammo != ammo) { continue; } // If the ammo we have found has more rounds than currently stored // at then record this as the best candidate for a swap if (ammoMountInfo.Rounds > roundCount) { roundCount = ammoMountInfo.Rounds; ammoMountCandidate = i; } } // If we didn't find any matching ammo or if we found no ammo // with more rounds in then is currently in the gun ... bail if (ammoMountCandidate == -1 || roundCount <= weaponMountInfo.InGunRounds) { return(false); } // We have found some ammo we can use so consume it. First // remember how many rounds were in the clip that is in the gun currently int oldInGunRounds = weaponMountInfo.InGunRounds; // Set the round count to that of the new clip weaponMountInfo.InGunRounds = _ammo[ammoMountCandidate].Rounds; // In terms of the inventory...using a weapon is reloading it. Firing the weapon // is handled somewhere else entirely weapon.Use(Vector3.zero, playAudio); // If no rounds where in the gun before the reload, we have nothing to // swap with the mount so remove the item from the mount if (oldInGunRounds == 0) { // Clear the mount _ammo[ammoMountCandidate].Ammo = null; // Lets now create an instance of the ammo type in the scene // to simulate the clip we have ejected from the gun Vector3 position = _playerPosition != null ? _playerPosition.value : Vector3.zero; position += _playerDirection != null ? _playerDirection.value : Vector3.zero; CollectableAmmo sceneAmmo = ammo.Drop(position, playAudio) as CollectableAmmo; // Now we must configure the scene ammo we just instantiated to reflect the number // of rounds that was in the gun if (sceneAmmo) { sceneAmmo.rounds = 0; } } // Otherwise simply swap the the clip else { _ammo[ammoMountCandidate].Rounds = oldInGunRounds; } } else if (weapon.reloadType == InventoryWeaponReloadType.Partial) { // If the gun is full, abort reload int roundsWanted = weapon.ammoCapacity - weaponMountInfo.InGunRounds; if (roundsWanted < 1) { return(false); } // Loop through items on ammo belt searching for the correct ammo type for (int i = 0; i < _ammo.Count; i++) { // If not the right type of ammo then continue InventoryAmmoMountInfo ammoMountInfo = _ammo[i]; if (ammoMountInfo.Ammo != weapon.ammo) { continue; } // Otherwise we have found some ammo so lets remove // some items from it int ammoTaken = Mathf.Min(roundsWanted, ammoMountInfo.Rounds); weaponMountInfo.InGunRounds += ammoTaken; ammoMountInfo.Rounds -= ammoTaken; roundsWanted -= ammoTaken; // Use the weapon to reload it weapon.Use(Vector3.zero, playAudio); // If we have emptied this ammo item then remove from belt if (ammoMountInfo.Rounds == 0) { ammoMountInfo.Ammo = null; } // If the gun is full then return and don't continue to seek if (roundsWanted <= 0) { break; } } } // Weapon Successfully Reload return(true); }