/// <summary> /// initializes the collider, id, amount and vp_Toss component of a pickup /// (vp_Toss is what moves the pickup in a nice bouncy arc when dropped). /// </summary> protected virtual vp_Toss InitPickup(GameObject pickup, int units, int id) { Collider[] cs = pickup.GetComponentsInChildren <Collider>(); foreach (Collider c in cs) { if (c.isTrigger) { Collider cc = c; vp_Timer.In(1, delegate() { if (cc != null) { cc.enabled = true; } }); } else { c.enabled = false; } } // NOTE: in the case of throwing weapons (e.g. grenades), 2 vp_ItemPickup // components may be present on the pickup gameobject. the first is for // the grenade unit (ammo) type and the second is for the 'grenade thrower' // weapon. to account for this case, there's some special logic to initing // the components of a pickup prefab: // fetch all pickup components on the prefab vp_ItemPickup[] ips = pickup.GetComponentsInChildren <vp_ItemPickup>(); if (ips.Length == 0) { return(null); // abort if no pickup components } // iterate through all pickup components on this prefab (usually only one) for (int v = 0; v < ips.Length; v++) { if (ips[v] == null) { if (v == 0) { return(null); // abort if first pickup component is null } continue; // skip if the second or later component is null } ips[v].ID = id + v; // id of first component will be 'id', the rest will be incremented from that if (v == 0) { ips[v].Amount = units; // only the first pickup component can have a count, the rest will be zero. } // IMPORTANT: for grenades, the first vp_ItemPickup component must be for the unit, and the second for the throwing weapon else { ips[v].Amount = 0; } // handle edge cases where ammo pickups end up empty - by canceling the item drop if (ips[v].ItemTypeObject is vp_UnitType && (units == 0)) { return(null); } vp_GlobalEvent <vp_ItemPickup> .Send("RegisterPickup", ips[v]); // this only has effect in multiplayer. NOTE: we must register all pickup // components on the transform (grenade throwers as well as grenade units) } // make sure the pickup has a toss component and return it vp_Toss toss = pickup.GetComponent <vp_Toss>(); if (toss == null) { toss = pickup.AddComponent <vp_Toss>(); } return(toss); }
/// <summary> /// internal method for handling all aspects of dropping any item type. /// NOTE: in multiplayer, this only gets run on the master, which in turn /// triggers 'MPClientDropItem' on clients /// </summary> protected virtual bool TryDropItemInternal(vp_ItemType itemType, Vector3 direction, int units = 0, int id = 0) { //Debug.Log("TryDropItemInternal: " + itemType + ", " + units); if (!vp_Gameplay.IsMaster) { return(false); } // fetch pickup prefab of the item type GameObject prefab = GetPickupPrefab(itemType, units); if (prefab == null) { return(false); } // try to remove item records or units from the inventory if (!TryRemoveItem(itemType, units, id)) { return(false); } // keep track of the number of item drop attempts for circular distribution and max cap UpdateDropCount(); // abort if we can't drop any more items at once if (m_ItemDropsThisFrame >= MaxDrops) { return(false); } // spawn a pickup GameObject pickup = SpawnPickup( prefab, transform.position // position of inventory owner + (Vector3.up * SpawnHeight) // plus a height offset + (direction * SpawnDistance) // plus a little bit away from body of inventory holder ); if (pickup == null) { return(false); } // in the UFPS multiplayer add-on, every pickup must be assigned a unique id on // spawn / startup (+ the id feature is reserved for the vp_MPPickupManager system) if (vp_Gameplay.IsMultiplayer) { id = vp_Utility.UniqueID; } // initialize the pickup with a collision timer, units, id and a toss component vp_Toss toss = InitPickup(pickup, units, id); if (toss == null) { Object.Destroy(pickup); return(false); } // item drop success! play drop sound TryPlayDropSound(); // offset direction based on how many items we have thrown this frame, so as // to not throw items inside each other direction = GetCircleDirection(direction); // toss the pickup away from the owner // the first 8 items will be tossed to 'm_DestDistance'. after that, // 75% of the initial distance will be added every 8 items, causing // large amounts of items to be arranged in concentric rings float additionalDistance = (((int)((m_ItemDropsThisFrame - 1) / 8)) * (TossDistance * 0.75f)); float targetYaw = Random.Range(-180, 180); Vector3 finalPosition = toss.Toss(pickup.transform.position, targetYaw, direction, (TossDistance + additionalDistance), !DisableBob, !DisableSpin); //Debug.Log("item drops: " + m_ItemDropsThisFrame + ", additional: " + additionalDistance); // notify master object vp_ItemPickup itemPickup = pickup.GetComponentInChildren <vp_ItemPickup>(); if (itemPickup != null) { vp_GlobalEvent <object[]> .Send("TransmitDropItem", new object[] { itemType.name, finalPosition, targetYaw, transform.root, itemPickup.ID, itemPickup.Amount }); } return(true); }
/// <summary> /// forces a multiplayer client to drop an item (remotely triggered by /// the master in multiplayer) /// </summary> public virtual void MPClientDropItem(string itemTypeName, Vector3 targetPosition, float targetYaw, int id, int units) { vp_ItemType itemType; if (!m_SceneItemTypesByName.TryGetValue(itemTypeName, out itemType)) { return; } if (itemType == null) { return; } if (itemType is vp_UnitType) { TryRemoveItem(itemType, units); } else { TryRemoveItem(itemType); } // fetch pickup prefab of the item type GameObject prefab = GetPickupPrefab(itemType, units); if (prefab == null) { return; } // spawn a pickup GameObject pickup = SpawnPickup( prefab, transform.position // position of inventory owner + (Vector3.up * SpawnHeight) // plus a height offset // plus offset in the direction of the target position (but at the original height) + vp_3DUtility.HorizontalVector((targetPosition - transform.position).normalized * SpawnDistance) ); if (pickup == null) { return; } // initialize the pickup with a collision timer, a toss component, // and the units and id as specified by master vp_Toss toss = InitPickup(pickup, units, id); if (toss == null) { Object.Destroy(pickup); return; } // toss the pickup to the specified position - without local collision // detection - which is assumed to have been already taken care of on // the master toss.Toss(pickup.transform.position, targetPosition, targetYaw, !DisableBob, !DisableSpin); // play sound TryPlayDropSound(); }