- Joined
- Mar 19, 2008
- Messages
- 3,141
Small snippet for cheating item pickup despite unit inventory being full.
This is done by periodic timer with distance checking that accounts for unit's collision size.
Generates custom event for triggering item pickup.
Allows for specifying arbitrary conditions via SmoothPickupPredicate interface for deciding whether to account for given unit in smooth item pickup process.
Example of usage: ItemRecipe, StackNSplit.
This is done by periodic timer with distance checking that accounts for unit's collision size.
Generates custom event for triggering item pickup.
Allows for specifying arbitrary conditions via SmoothPickupPredicate interface for deciding whether to account for given unit in smooth item pickup process.
Example of usage: ItemRecipe, StackNSplit.
Wurst:
/*
* SmoothItemPickup v1.0.1.3
* by Bannar
*
* Allows for item pickup despite unit inventory being full.
*/
package SmoothItemPickup
import LinkedList
import LinkedListModule
import HashMap
import RegisterEvents
import ClosureTimers
import Orders
tuple eventInfo(unit u, item itm)
var eventState = eventInfo(null, null)
constant eventTrigger = CreateTrigger()
constant conditions = new LinkedList<SmoothPickupPredicate>()
constant looper = CreateTimer()
/** Default pickup range degined in gameplay constants. */
@configurable constant real PICK_UP_RANGE = 150.0
public interface SmoothPickupPredicate
/** Determinates whether unit can pickup specified item. */
function canPickup(unit whichUnit, item whichItem) returns boolean
/** Returns unit attempting to pickup event item. */
public function getSmoothItemPickupUnit() returns unit
return eventState.u
/** Returns item that is being picked up. */
public function getSmoothItemPickupItem() returns item
return eventState.itm
/** Adds new condition for item to be picked up smoothly. Conditions are aggregated in 'OR' fashion. */
public function addSmoothItemPickupCondition(SmoothPickupPredicate predicate)
if predicate != null
conditions.add(predicate)
/** Removes specified condition from predicate list. */
public function removeSmoothItemPickupCondition(SmoothPickupPredicate predicate)
if predicate != null
conditions.remove(predicate)
public function registerSmoothItemPickupEvent(code func)
eventTrigger.addCondition(Condition(func))
class PeriodicData
use LinkedListModule
unit picker
item itm
real range
static constant instances = new HashMap<int, PeriodicData>()
construct(unit u, real range)
this.picker = u
this.range = range
instances.put(u.getHandleId(), this)
ondestroy
instances.remove(picker.getHandleId())
if size == 1
looper.pause()
static function get(int index) returns thistype
thistype result = null
if instances.has(index)
result = instances.get(index)
return result
function fireEvent(eventInfo currState)
var prevState = eventState
eventState = currState
eventTrigger.evaluate()
eventState = prevState
function test(unit u, item itm, real range) returns boolean
if u.hasItem(itm)
return true
var pos = itm.getPos() - u.getPos()
// Assumes range is multipled to avoid invoking SquareRoot
return pos.dot(pos) <= range
function onCallback()
var iter = PeriodicData.iterator()
while iter.hasNext()
var data = iter.next()
if not data.picker.isAlive() or data.picker.getCurrentOrder() != Orders.move or not data.itm.isPickupable()
destroy data
else
if test(data.picker, data.itm, data.range)
fireEvent(eventInfo(data.picker, data.itm))
destroy data
iter.close()
function onTargetOrder()
var u = GetTriggerUnit()
if not u.isInventoryFull() or GetIssuedOrderId() != SpecialOrders.smart
return
var itm = GetOrderTargetItem()
if itm == null or itm.isPowerup()
return
var proceed = false
for condition in conditions
if condition.canPickup(u, itm)
proceed = true
break
if not proceed
return
var collision = u.getCollisionSize()
var range = (PICK_UP_RANGE + collision) * (PICK_UP_RANGE + collision)
if test(u, itm, range)
// Ensures order is finished before item is picked up.
// Fixes the issue with unit moving towards the item location, rather than stopping
nullTimer() ->
if u.isAlive() and itm.isPickupable()
fireEvent(eventInfo(u, itm))
// If unit is not nearby target item, issue artificial move order
else
var data = PeriodicData.get(u.getHandleId())
if data == null
if PeriodicData.size == 0
looper.startPeriodic(0.031250000, () -> onCallback())
data = new PeriodicData(u, range)
data.itm = itm
var ipos = itm.getPos()
var angle = ipos.angleTo(u.getPos())
var resultPos = ipos + angle.toVec(PICK_UP_RANGE)
var t = getPlayerUnitEventTrigger(EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
t.disable()
u.issuePointOrderById(Orders.move, resultPos)
t.enable()
init
registerPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, () -> onTargetOrder())
Last edited: