Update:

- fixed an issue where characters repeatedly moved items to the exact same position when their own position didn't change (FindValidPosition always gives the same output if nothing changed)
- improved decisionmaking in finding items to move (the closest item will be chosen with a 40% chance, since it's often the best solution)
- removed IsObjectOnObject check

Script:

Code
INIT

CHARACTER:__Me

EXTERN FLOAT3:%TargetPos = null
FLOAT3:%TempTarget
INT:%ItemMoveSuccess = 0

BEHAVIOUR

REACTION GetClose, 0
USAGE PEACE	
USAGE COMBAT
VARS
	FLOAT:_distance
	FLOAT:_MyX
	FLOAT:_MyZ
	FLOAT:_TargetX
	FLOAT:_TargetZ
	FLOAT:_AttemptCounter = 0
	FLOAT:_AddX
	FLOAT:_AddZ
	FLOAT:_Divisor
	FLOAT3:_Target
	FLOAT3:_MyPos
	FLOAT3:_TargetPosition
ACTIONS
	IF "c1&c2"
		GetPosition(__Me,_MyPos)
		GetVar(_TargetPosition,__Me,"TargetPos")
	THEN
		Set(%TempTarget,_TargetPosition)
	ENDIF
	IF "c1&c2&c3&c4&c5"
		GetX(_MyPos,_MyX)
		GetZ(_MyPos,_MyZ)
		GetX(_TargetPosition,_TargetX)
		GetZ(_TargetPosition,_TargetZ)
		GetDistance(_distance,__Me,_TargetPosition)
	THEN
		Subtract(_TargetX,_MyX)
		Subtract(_TargetZ,_MyZ)
		GetRandom(_Divisor,1.8,1.9,2,2.1,2.2)
		Divide(_TargetX,_Divisor)
		Divide(_TargetZ,_Divisor)
		Add(_MyX,_TargetX)
		Add(_MyZ,_TargetZ)
		SetX(%TempTarget,_MyX)
		SetZ(%TempTarget,_MyZ)
		CharacterLookAt(%TempTarget)
		IF "c1"
			IsGreaterThen(_AttemptCounter,4)
		THEN
			Set(_AttemptCounter,0)
			SetPriority("MoveItems",0)
			IF "c1"
				IsInCombat(__Me)
			THEN
				CharacterEndTurn()
			ELSE
				DelayReaction("GetClose",5)
			ENDIF			
			SetPriority("GetClose",0)
		ELIF "c1"
			IsLessThen(_distance,4)
		THEN	
			CharacterLookAt(_TargetPosition)
			IF "c1"
				IsInCombat(__Me)
			THEN
				CharacterMoveTo(_TargetPosition,1,0,0,0.2,1)
			ELSE
				CharacterMoveTo(_TargetPosition,0,0,0,0.2,1)
			ENDIF
			SetPriority("GetClose",0)
		ELIF "!c1"
			IsLessThen(_distance,4)
		THEN			
			IF "!c1"
				FindValidPosition(%TempTarget,4,__Me) 
			THEN										
				Interrupt("GetClose")
			ENDIF
			IF "c1"
				IsInCombat(__Me)
			THEN
				CharacterMoveTo(%TempTarget,1,0,0,0.2,1.4)
			ELSE 
				CharacterMoveTo(%TempTarget,0,0,0,0.2,1.4) 
			ENDIF
			SetPriority("MoveItems",0)
		ELSE
			Set(_AttemptCounter,0)
			SetPriority("MoveItems",0)
			SetPriority("GetClose",0)
		ENDIF
	ENDIF
INTERRUPT
	Reset()
	ON
		OnMovementFailed(_)
		OnManualInterrupt("GetClose")
	ACTIONS
		Add(_AttemptCounter,1)
		SetPriority("MoveItems",3000)
		SetPriority("GetClose",0) 
		
REACTION MoveItems, 0
USAGE PEACE
USAGE COMBAT
VARS
	ITEM:_Item
	ITEM:_Item2
	ITEM:_IgnoreItem1
	ITEM:_IgnoreItem2
	ITEM:_IgnoreItem3
	FLOAT:_Weight
	FLOAT:_X
	FLOAT:_Z
	FLOAT:_MyPosX
	FLOAT:_MyPosZ
	FLOAT3:_MyPos
	CHARACTER:_Enemy
CHECK "(((((c1&c2)|(c3&c4))&c5&c6&((!c7&c8)|c9))|(c10&c11&c12&((!c13&c14)|c15)))&!c16)|(c17&c18)"
	IsRandom(0.4)
	ItemGet(_Item,__Me,6,Lowest,Distance,"")
	ItemGet(_Item,__Me,6,Random,Distance,"")
	CanSee(__Me,_Item)
	IsFacing(__Me,_Item)
	ItemGetStat(_Weight,_Item,Weight)
	IsLessThen(_Weight,1000)
	IsLessThen(_Weight,40001)
	IsEqual(_Weight,200000) //Ice_Crystal
	ItemGet(_Item,%TempTarget,6,Random,Distance,"")
	IsFacing(__Me,_Item)
	ItemGetStat(_Weight,_Item,Weight)
	IsLessThen(_Weight,1000)
	IsLessThen(_Weight,40001)
	IsEqual(_Weight,200000) //Ice_Crystal
	ItemIsDestroyed(_Item)
	IsInCombat(__Me)
	CharacterGet(_Enemy,__Me,5,Lowest,Distance,Enemy)
ACTIONS
	IF "!c1"
		IsEqual(_Enemy,null)
	THEN
		CharacterMoveTo(_Enemy,1)
		CharacterAttack(_Enemy)
		Goto("End")
	ENDIF
	IF "c1"
		IsInCombat(__Me)
	THEN
		CharacterMoveTo(_Item,1)
	ELSE
		CharacterMoveTo(_Item)
	ENDIF
	IF "c1"
		IsEqual(_Weight,200000) //Ice_Crystal
	THEN
		WHILE "!c1"
			ItemIsDestroyed(_Item)
		DO
			CharacterAttack(_Item)
		ENDWHILE
	ELSE
		GetPosition(__Me,_MyPos)
		GetRandom(_X,-3,-2,2,3)
		GetRandom(_Z,-3,-2,2,3)
		IF "!c1&c2&c3"
			ItemIsDestroyed(_Item)
			GetX(_MyPos,_MyPosX)
			GetZ(_MyPos,_MyPosZ)
		THEN
			Subtract(_MyPosX,_X)
			Subtract(_MyPosZ,_Z)
			SetX(_MyPos,_MyPosX)
			SetZ(_MyPos,_MyPosZ)
			IF "c1"
				FindValidPosition(_MyPos,4,_Item)
			THEN
				StartTimer("CheckMoveItemSuccess",3,0)
				CharacterMoveItem(_Item,_MyPos)
				Set(%ItemMoveSuccess,1)	
			ENDIF
		ENDIF
	ENDIF
	Label("End")
	Set(_Enemy,null)
	SetPriority("MoveItems",0)
INTERRUPT
	Reset()
	Set(_Enemy,null)
	SetPriority("MoveItems",0)
	
EVENTS

EVENT CheckItemMoveSuccess
ON
	OnTimer("CheckMoveItemSuccess")
ACTIONS
	IF "c1"
		IsEqual(%ItemMoveSuccess,1)
	THEN
		Set(%ItemMoveSuccess,0)
	ELSE		
		Interrupt("MoveItems")
	ENDIF
	
EVENT GetCloseActivation
ON
	OnCharacterEvent(__Me,"ActivateGetClose")
ACTIONS
	SetPriority("GetClose",2000)

INTERRUPT code:

Code
 //to be added to every reaction with movement

VARS
	FLOAT3:_Pos

INTERRUPT
//Reset() //not necessary for functionality, but for most reactions recommended
ON
	OnMovementFailed(_Pos)
ACTIONS
	SetVar(__Me,"TargetPos",_Pos)
	CharacterEvent(__Me,"ActivateGetClose")


Last edited by Abraxas*; 22/02/17 10:39 AM. Reason: Little correction in FindValidPosition; removed Sleep(1)

My mods for DOS 1 EE: FasterAnimations - QuietDay - Samaritan