diff --git a/rules_shipping_base.php b/rules_shipping_base.php
index 4ffcc520ae7e2dd8ee8b80eadfa7217a4282b04a..ab8a9a7700e1a16ac1561aeb12a19b70a40bb9e0 100644
--- a/rules_shipping_base.php
+++ b/rules_shipping_base.php
@@ -232,15 +232,42 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
 
 
 
-	protected function findMatchingRule (&$cartvals, $method) {
-		$result = array("rule"=>Null, "rule_name"=>"", "modifiers"=>array());
-		// TODO: Handle modifiers
-		foreach ($method->rules as $r) {
-			// If the rule is a variable definition, it will NOT match, but modify the $cartvals array for the next rules
-			if ($r->matches($cartvals)) {
-				$result["rule"] = $r;
-				$result["rule_name"] = $r->getRuleName($cartvals);
-				return $result;
+	protected function evaluateMethodRules ($cart, $method, $cart_prices) {
+		// $method->match will cache the matched rule and the modifiers
+		if ($method->evaluated) {
+			return $method->match;
+		} else {
+			$method->evaluated = True;
+			$method->match = Null;
+			// Evaluate all rules and find the matching ones (including modifiers and definitions!)
+			$result = array("rule"=>Null, "rule_name"=>"", "modifiers_add"=>array(), "modifiers_multiply"=>array());
+			$cartvals = $this->getCartValues ($cart, $cart->products, $method, $cart_prices);
+			foreach ($method->rules as $r) {
+				if ($r->matches($cartvals)) {
+					switch ($r->getType() {
+						case 'shipping': 
+						case 'shippingwithtax':
+						case 'noshipping': 
+								$result["rule"] = $r;
+								$result["rule_name"] = $r->getRuleName($cartvals);
+								break;
+						case 'extrashippingcharge':
+								$result["modifiers_add"][] = $r;
+								break;
+						case 'extrashippingmultiplier':
+								$result["modifiers_multiply"][] = $r;
+								break;
+						case 'definition': // A definition has modified the $cartvals, but has no other effects
+								break;
+						default:
+								$this->printWarning(JText::sprintf('VMSHIPMENT_RULES_UNKNOWN_TYPE', $r->rulestring));
+								break;
+					}
+				}
+				if (!is_null($result["rule"])) {
+					$method->match = $result;
+					return $result; // <- This also breaks out of the foreach loop!
+				}
 			}
 		}
 		// None of the rules matched, so return NULL;
@@ -254,25 +281,23 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
 	 * @return bool
 	 */
 	protected function checkConditions ($cart, $method, $cart_prices) {
-		if (!isset($method->rules)) $this->parseMethodRules($method);
-
-		$cartvals = $this->getCartValues ($cart, $method, $cart_prices);
-		$match = $this->findMatchingRule ($cartvals, $method);
+		if (!isset($method->rules)) 
+			$this->parseMethodRules($method);
+		$match = $this->evaluateMethodRules ($cart, $method, $cart_prices);
 		if ($match) {
-			$method->matched_rule = $match["rule"];
 			$method->rule_name = $match["rule_name"];
 			// If NoShipping is set, this method should NOT offer any shipping at all, so return FALSE, otherwise TRUE
 			// If the rule has a name, print it as warning (otherwise don't print anything)
-			if ($method->matched_rule->isNoShipping()) {
+			if ($match['rule']->isNoShipping()) {
 				if (!empty($method->rule_name))
 					$this->printWarning(JText::sprintf('VMSHIPMENT_RULES_NOSHIPPING_MESSAGE', $method->rule_name));
-				vmdebug('checkConditions '.$method->shipment_name.' indicates NoShipping for rule "'.$method->rule_name.'" ('.$method->matched_rule->rulestring.').');
+				vmdebug('checkConditions '.$method->shipment_name.' indicates NoShipping for this method, specified by rule "'.$method->rule_name.'" ('.$match['rule']->rulestring.').');
 				return FALSE;
 			} else {
 				return TRUE;
 			}
 		}
-		vmdebug('checkConditions '.$method->shipment_name.' does not fit');
+		vmdebug('checkConditions '.$method->shipment_name.' does not fulfill all conditions, no rule matches');
 		return FALSE;
 	}
 
@@ -284,16 +309,22 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
 	 */
 	function getCosts (VirtueMartCart $cart, $method, $cart_prices) {
 		if (!isset($method->rules)) $this->parseMethodRules($method);
-		$cartvals = $this->getCartValues ($cart, $method, $cart_prices);
-		$match = $this->findMatchingRule ($cartvals, $method);
+		$match = $this->evaluateMethodRules ($cart, $method, $cart_prices);
 		if ($match) {
 			$r = $match["rule"];
-			$rulename = $match["rule_name"];
-			vmdebug('Rule '.$rulename.' ('.$r->rulestring.') matched.');
+			vmdebug('Rule ' . $match["rule_name"] . ' ('.$r->rulestring.') matched.');
 			$method->tax_id = $r->tax_id;
-			$method->matched_rule = $r;
-			$method->rule_name = $rulename;
+			$method->rule_name = $match["rule_name"];
+			// Final shipping costs are calculated as:
+			//   Shipping*ExtraShippingMultiplier + ExtraShippingCharge
+			// with possibly multiple modifiers
 			$method->cost = $r->getShippingCosts($cartvals);
+			foreach ($match['modifiers_multiply'] as $modifier) {
+				$method->cost *= $modifier->getShippingCosts($cartvals);
+			}
+			foreach ($match['modifiers_add'] as $modifier) {
+				$method->cost += $modifier->getShippingCosts($cartvals);
+			}
 			$method->includes_tax = $r->includes_tax;
 			return $method->cost;
 		}
@@ -423,7 +454,7 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
 	}
 
 	protected function createMethodRule ($r, $countries, $tax) {
-		return new ShippingRule($r, $countries, $tax);
+		return new ShippingRule(this, $r, $countries, $tax);
 	}
 
 	private function parseMethodRule ($rulestring, $countries, $tax, &$method) {
@@ -447,30 +478,22 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
 		$this->parseMethodRule ($method->rules8, $method->countries8, $method->tax_id8, $method);
 	}
 
-	protected function getOrderArticles (VirtueMartCart $cart) {
-		/* Cache the value in a static variable and calculate it only once! */
-		static $articles = 0;
-		if(empty($articles) and count($cart->products)>0){
-			foreach ($cart->products as $product) {
-				$articles += $product->quantity;
-			}
+	/** Functions to calculate all the different variables for the given cart and given (sub)set of products in the cart */
+	protected function getOrderArticles (VirtueMartCart $cart, $products) {
+		$articles = 0;
+		foreach ($products as $product) {
+			$articles += $product->quantity;
 		}
 		return $articles;
 	}
 
-	protected function getOrderProducts (VirtueMartCart $cart) {
-		/* Cache the value in a static variable and calculate it only once! */
-		static $products = 0;
-		if(empty($products) and count($cart->products)>0){
-			$products = count($cart->products);
-		}
-		return $products;
+	protected function getOrderProducts (VirtueMartCart $cart, $products) {
+		return count($products);
 	}
 
-	protected function getOrderDimensions (VirtueMartCart $cart, $length_dimension) {
+	protected function getOrderDimensions (VirtueMartCart $cart, $products, $length_dimension) {
 		/* Cache the value in a static variable and calculate it only once! */
-		static $calculated = 0;
-		static $dimensions=array(
+		$dimensions=array(
 			'volume' => 0,
 			'maxvolume' => 0, 'minvolume' => 9999999999,
 			'maxlength' => 0, 'minlength' => 9999999999, 'totallength' => 0,
@@ -478,61 +501,54 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
 			'maxheight' => 0, 'minheight' => 9999999999, 'totalheight' => 0,
 			'maxpackaging' => 0, 'minpackaging' => 9999999999, 'totalpackaging' => 0,
 		);
-		if ($calculated==0) {
-			$calculated=1;
-			foreach ($cart->products as $product) {
+		foreach ($products as $product) {
 	
-				$l = ShopFunctions::convertDimensionUnit ($product->product_length, $product->product_lwh_uom, $length_dimension);
-				$w = ShopFunctions::convertDimensionUnit ($product->product_width, $product->product_lwh_uom, $length_dimension);
-				$h = ShopFunctions::convertDimensionUnit ($product->product_height, $product->product_lwh_uom, $length_dimension);
-
-				$volume = $l * $w * $h;
-				$dimensions['volume'] += $volume * $product->quantity;
-				$dimensions['maxvolume'] = max ($dimensions['maxvolume'], $volume);
-				$dimensions['minvolume'] = min ($dimensions['minvolume'], $volume);
+			$l = ShopFunctions::convertDimensionUnit ($product->product_length, $product->product_lwh_uom, $length_dimension);
+			$w = ShopFunctions::convertDimensionUnit ($product->product_width, $product->product_lwh_uom, $length_dimension);
+			$h = ShopFunctions::convertDimensionUnit ($product->product_height, $product->product_lwh_uom, $length_dimension);
+
+			$volume = $l * $w * $h;
+			$dimensions['volume'] += $volume * $product->quantity;
+			$dimensions['maxvolume'] = max ($dimensions['maxvolume'], $volume);
+			$dimensions['minvolume'] = min ($dimensions['minvolume'], $volume);
 				
-				$dimensions['totallength'] += $l * $product->quantity;
-				$dimensions['maxlength'] = max ($dimensions['maxlength'], $l);
-				$dimensions['minlength'] = min ($dimensions['minlength'], $l);
-				$dimensions['totalwidth'] += $w * $product->quantity;
-				$dimensions['maxwidth'] = max ($dimensions['maxwidth'], $w);
-				$dimensions['minwidth'] = min ($dimensions['minwidth'], $w);
-				$dimensions['totalheight'] += $h * $product->quantity;
-				$dimensions['maxheight'] = max ($dimensions['maxheight'], $h);
-				$dimensions['minheight'] = min ($dimensions['minheight'], $h);
-				$dimensions['totalpackaging'] += $product->product_packaging * $product->quantity;
-				$dimensions['maxpackaging'] = max ($dimensions['maxpackaging'], $product->product_packaging);
-				$dimensions['minpackaging'] = min ($dimensions['minpackaging'], $product->product_packaging);
-			}
+			$dimensions['totallength'] += $l * $product->quantity;
+			$dimensions['maxlength'] = max ($dimensions['maxlength'], $l);
+			$dimensions['minlength'] = min ($dimensions['minlength'], $l);
+			$dimensions['totalwidth'] += $w * $product->quantity;
+			$dimensions['maxwidth'] = max ($dimensions['maxwidth'], $w);
+			$dimensions['minwidth'] = min ($dimensions['minwidth'], $w);
+			$dimensions['totalheight'] += $h * $product->quantity;
+			$dimensions['maxheight'] = max ($dimensions['maxheight'], $h);
+			$dimensions['minheight'] = min ($dimensions['minheight'], $h);
+			$dimensions['totalpackaging'] += $product->product_packaging * $product->quantity;
+			$dimensions['maxpackaging'] = max ($dimensions['maxpackaging'], $product->product_packaging);
+			$dimensions['minpackaging'] = min ($dimensions['minpackaging'], $product->product_packaging);
 		}
 
 		return $dimensions;
 	}
 	
-	function getOrderWeights (VirtueMartCart $cart, $weight_unit) {
-		static $calculated = 0;
-		static $dimensions=array(
+	protected function getOrderWeights (VirtueMartCart $cart, $products, $weight_unit) {
+		$dimensions=array(
 			'weight' => 0,
 			'maxweight' => 0, 'minweight' => 9999999999,
 		);
-		if ($calculated==0 && count($cart->products)>0) {
-			$calculated = 1;
-			foreach ($cart->products as $product) {
-				$w = ShopFunctions::convertWeigthUnit ($product->product_weight, $product->product_weight_uom, $weight_unit);
-				$dimensions['maxweight'] = max ($dimensions['maxweight'], $w);
-				$dimensions['minweight'] = min ($dimensions['minweight'], $w);
-				$dimensions['weight'] += $w * $product->quantity;
-			}
+		foreach ($products as $product) {
+			$w = ShopFunctions::convertWeigthUnit ($product->product_weight, $product->product_weight_uom, $weight_unit);
+			$dimensions['maxweight'] = max ($dimensions['maxweight'], $w);
+			$dimensions['minweight'] = min ($dimensions['minweight'], $w);
+			$dimensions['weight'] += $w * $product->quantity;
 		}
 		return $dimensions;
 	}
 	
-	function getOrderListProperties (VirtueMartCart $cart) {
+	protected function getOrderListProperties (VirtueMartCart $cart, $products) {
 		$categories = array();
 		$vendors = array();
 		$skus = array();
 		$manufacturers = array();
-		foreach ($cart->products as $product) {
+		foreach ($products as $product) {
 			$skus[] = $product->product_sku;
 			$categories = array_merge ($categories, $product->categories);
 			$vendors[] = $product->virtuemart_vendor_id;
@@ -540,8 +556,10 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
 				$manufacturers[] = $product->virtuemart_manufacturer_id;
 			}
 		}
-		$categories = array_unique($categories);
+		$skus = array_unique($skus);
 		$vendors = array_unique($vendors);
+		$categories = array_unique($categories);
+		$manufacturers = array_unique($manufacturers);
 		return array ('skus'=>$skus, 
 			      'categories'=>$categories,
 			      'vendors'=>$vendors,
@@ -549,7 +567,7 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
 		);
 	}
 	
-	function getOrderCountryState (VirtueMartCart $cart, $address) {
+	protected function getOrderCountryState (VirtueMartCart $cart, $address) {
 		$data = array (
 			'countryid' => 0, 'country' => '', 'country2' => '', 'country3' => '',
 			'stateid'   => 0, 'state'   => '', 'state2'   => '', 'state3'   => '',
@@ -593,52 +611,114 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
 
 	}
 	
-	/** Allow child classes to add additional variables for the rules
+	protected function getOrderAddress (VirtueMartCart $cart, $address) {
+		$zip = isset($address['zip'])?trim($address['zip']):'';
+		$data = array('zip'=>$zip,
+			'zip1'=>substr($zip,0,1),
+			'zip2'=>substr($zip,0,2),
+			'zip3'=>substr($zip,0,3),
+			'zip4'=>substr($zip,0,4),
+			'zip5'=>substr($zip,0,5),
+			'zip6'=>substr($zip,0,6),
+			'city'=>isset($address['city'])?trim($address['city']):'',
+		);
+		return $data;
+	}
+	
+	protected function getOrderPrices (VirtueMartCart $cart, $products, $cart_prices) {
+		$data = array(
+			'amount' => 0, 
+			'amountwithtax' => 0, 
+			'amountwithouttax' => 0, 
+			'baseprice' => 0, 
+			'basepricewithtax' => 0, 
+			'discountedpricewithouttax' => 0, 
+			'salesprice' => 0, 
+			'taxamount' => 0, 
+			'salespricewithdiscount' => 0, 
+			'discountamount' => 0, 
+			'pricewithouttax' => 0,
+		);
+// JFactory::getApplication()->enqueueMessage("<pre>Product: ".print_r($products, 1)."</pre>", 'error');
+		if (!empty($cart_prices)) {
+			// get prices for the whole cart -> simply user the cart_prices
+			$data['amount']                 = $cart_prices['salesPrice'];
+			$data['amountwithtax']          = $cart_prices['salesPrice'];
+			$data['amountwithouttax']       = $cart_prices['priceWithoutTax'];
+			$data['baseprice']              = $cart_prices['basePrice'];
+			$data['basepricewithtax']       = $cart_prices['basePriceWithTax'];
+			$data['discountedpricewithouttax'] = $cart_prices['discountedPriceWithoutTax'];
+			$data['salesprice']             = $cart_prices['salesPrice'];
+			$data['taxamount']              = $cart_prices['taxAmount'];
+			$data['salespricewithdiscount'] = $cart_prices['salesPriceWithDiscount'];
+			$data['discountamount']         = $cart_prices['discountAmount'];
+			$data['pricewithouttax']        = $cart_prices['priceWithoutTax'];
+		} else {
+			// TODO: Calculate the prices from the individual products!
+			// Possible problems are discounts on the order total
+			foreach ($products as $product) {
+				$data['amount']                 = $product->allPrices[$product->selectedPrice]['salesPrice'];
+				$data['amountwithtax']          = $product->allPrices[$product->selectedPrice]['salesPrice'];
+				$data['amountwithouttax']       = $product->allPrices[$product->selectedPrice]['priceWithoutTax'];
+				$data['baseprice']              = $product->allPrices[$product->selectedPrice]['basePrice'];
+				$data['basepricewithtax']       = $product->allPrices[$product->selectedPrice]['basePriceWithTax'];
+				$data['discountedpricewithouttax'] = $product->allPrices[$product->selectedPrice]['discountedPriceWithoutTax'];
+				$data['salesprice']             = $product->allPrices[$product->selectedPrice]['salesPrice'];
+				$data['taxamount']              = $product->allPrices[$product->selectedPrice]['taxAmount'];
+				$data['salespricewithdiscount'] = $product->allPrices[$product->selectedPrice]['salesPriceWithDiscount'];
+				$data['discountamount']         = $product->allPrices[$product->selectedPrice]['discountAmount'];
+				$data['pricewithouttax']        = $product->allPrices[$product->selectedPrice]['priceWithoutTax'];
+			}
+		}
+		return $data;
+	}
+
+	/** Allow child classes to add additional variables for the rules or modify existing one
 	 */
-	protected function addCustomCartValues (VirtueMartCart $cart, $cart_prices, &$values) {
+	protected function addCustomCartValues (VirtueMartCart $cart, $products, $cart_prices, &$values) {
 	}
-	protected function getCartValues (VirtueMartCart $cart, $method, $cart_prices) {
+
+	protected function getCartValues (VirtueMartCart $cart, $products, $method, $cart_prices) {
+// JFactory::getApplication()->enqueueMessage("<pre>getCartValues, cart=".print_r($cart, 1)."</pre>", 'error');
 		$address = (($cart->ST == 0 || $cart->STSameAsBT == 1) ? $cart->BT : $cart->ST);
-		$zip = isset($address['zip'])?trim($address['zip']):'';
-		$cartvals = array('zip'=>$zip,
-				  'zip1'=>substr($zip,0,1),
-				  'zip2'=>substr($zip,0,2),
-				  'zip3'=>substr($zip,0,3),
-				  'zip4'=>substr($zip,0,4),
-				  'zip5'=>substr($zip,0,5),
-				  'zip6'=>substr($zip,0,6),
-				  'city'=>isset($address['city'])?trim($address['city']):'',
-				  'articles'=>$this->getOrderArticles($cart),
-				  'products'=>$this->getOrderProducts($cart),
-				  'amount'=>$cart_prices['salesPrice'],
-				  'amountwithtax'=>$cart_prices['salesPrice'],
-				  'amountwithouttax'=>$cart_prices['priceWithoutTax'],
-
-				  'baseprice'=>$cart_prices['basePrice'],
-				  'basepricewithtax'=>$cart_prices['basePriceWithTax'],
-				  'discountedpricewithouttax'=>$cart_prices['discountedPriceWithoutTax'],
-				  'salesprice'=>$cart_prices['salesPrice'],
-				  'taxamount'=>$cart_prices['taxAmount'],
-				  'salespricewithdiscount'=>$cart_prices['salesPriceWithDiscount'],
-				  'discountamount'=>$cart_prices['discountAmount'],
-				  'pricewithouttax'=>$cart_prices['priceWithoutTax'],
-			);
-		
-		// Add 'skus', 'categories', 'vendors' variables:
-		$cartvals = array_merge ($cartvals, $this->getOrderListProperties ($cart));
-		// Add country / state variables:
-		$cartvals = array_merge ($cartvals, $this->getOrderCountryState ($cart, $address));
-		// Add Total/Min/Max weight and dimension variables:
-		$cartvals = array_merge ($cartvals, $this->getOrderWeights ($cart, $method->weight_unit));
-		$cartvals = array_merge ($cartvals, $this->getOrderDimensions ($cart, $method->length_unit));
+		$cartvals = array_merge (
+			array(
+				'articles'=>$this->getOrderArticles($cart, $products),
+				'products'=>$this->getOrderProducts($cart, $products),
+			),
+			// Add the prices, optionally calculated from the products subset of the cart
+			$this->getOrderPrices ($cart, $products, $cart_prices),
+			// Add 'skus', 'categories', 'vendors' variables:
+			$this->getOrderListProperties ($cart, $products),
+			// Add country / state variables:
+			$this->getOrderCountryState ($cart, $address),
+			// Add Total/Min/Max weight and dimension variables:
+			$this->getOrderWeights ($cart, $products, $method->weight_unit),
+			$this->getOrderDimensions ($cart, $products, $method->length_unit)
+		);
 		// Let child classes update the $cartvals array, or add new variables
-		$this->addCustomCartValues($cart, $cart_prices, $cartvals);
+		$this->addCustomCartValues($cart, $products, $cart_prices, $cartvals);
+		// Finally, call the triger of vmshipmentrules plugins to let them add/modify variables
+		JPluginHelper::importPlugin('vmshipmentrules');
+		$dispatcher = JDispatcher::getInstance();
+		$dispatcher->trigger('onVmShippingRulesGetCartValues',array(&$cartvals, $cart, $products, $method, $cart_prices));
+		
 		// Add the whole list of cart value to the values, so we can print them out as a debug statement!
 		$cartvals['values_debug'] = print_r($cartvals,1);
 		$cartvals['values'] = $cartvals;
 		return $cartvals;
 	}
 
+	/** Filter the given array of products and return only those that belong to the categories, manufacturers, 
+	 *  vendors or products given in the $filter_conditions. The $filter_conditions is an array of the form:
+	 *     array( 'skus'=>array(....), 'categories'=>array(1,2,3,42), 'manufacturers'=>array(77,78,83), 'vendors'=>array(1,2))
+	 *  Notice that giving an empty array for any of the keys means "no restriction" and is exactly the same 
+	 *  as leaving out the enty altogether
+	 */
+	function filterProducts($products, $filter_conditions) {
+		
+		
+	}
 	/**
 	 * Create the table for this plugin if it does not yet exist.
 	 * This functions checks if the called plugin is active one.
@@ -738,7 +818,8 @@ class plgVmShipmentRules_Shipping_Base extends vmPSPlugin {
 			return FALSE;
 		}
 		if (isset($data['rules1'])) {
-			// Try to parse all rules (and spit out error) to inform the user:
+			// Try to parse all rules (and spit out error) to inform the user. There is no other 
+			// reason to parse the rules here, it's really only to trigger warnings/errors in case of a syntax error.
 			$method = new StdClass ();
 			$this->parseMethodRule ($data['rules1'], isset($data['countries1'])?$data['countries1']:array(), $data['tax_id1'], $method);
 			$this->parseMethodRule ($data['rules2'], isset($data['countries2'])?$data['countries2']:array(), $data['tax_id2'], $method);
@@ -760,16 +841,21 @@ if (class_exists ('ShippingRule')) {
 }
 
 class ShippingRule {
+	var $method = Null;
 	var $rulestring = '';
+	var $name = '';
+	var $ruletype = '';
+	var $evaluated = False;
+	var $match = False;
+	var $value = Null;
+	
+	var $shipping = 0;
+	var $conditions = array();
 	var $countries = array();
 	var $tax_id = 0;
-	var $conditions = array();
-	var $shipping = 0;
 	var $includes_tax = 0;
-	var $name = '';
-	var $is_definition = 0;
 	
-	function __construct ($rule, $countries, $tax_id) {
+	function __construct ($method, $rule, $countries, $tax_id) {
 		if (is_array($countries)) {
 			$this->countries = $countries;
 		} elseif (!empty($countries)) {
@@ -778,6 +864,7 @@ class ShippingRule {
 		$this->tax_id = $tax_id;
 		$this->rulestring = $rule;
 		$this->parseRule($rule);
+		$this->method=$method;
 	}
 	
 	function parseRule($rule) {
@@ -789,15 +876,17 @@ class ShippingRule {
 	
 	function handleAssignment ($var, $value, $rulepart) {
 		switch (strtolower($var)) {
-			case 'name': $this->name = $value; break;
-			case 'shipping': $this->shipping = $value; $this->includes_tax = False; break;
-			case 'shippingwithtax': $this->shipping = $value; $this->includes_tax = True; break;
-			case 'variable':   // Variable=... is the same as Definition=...
-			case 'definition': $this->name = strtolower($value); $this->is_definition = True; break;
-			case 'value': $this->shipping = $value; break; // definition values are also stored in the shipping member!
-			case 'comment': break; // Completely ignore all comments!
-			case 'condition': $this->conditions[] = $value; break;
-			default: JFactory::getApplication()->enqueueMessage(JText::sprintf('VMSHIPMENT_RULES_UNKNOWN_VARIABLE', $var, $rulepart), 'error');
+			case 'name':            $this->name = $value; break;
+			case 'shipping':        $this->shipping = $value; $this->includes_tax = False; $this->ruletype='shipping'; break;
+			case 'shippingwithtax': $this->shipping = $value; $this->includes_tax = True; $this->ruletype='shipping'; break;
+			case 'variable':        // Variable=... is the same as Definition=...
+			case 'definition':      $this->name = strtolower($value); $this->ruletype = 'definition'; break;
+			case 'value':           $this->shipping = $value; $this->ruletype = 'definition'; break; // definition values are also stored in the shipping member!
+			case 'extrashippingcharge': $this->shipping = $value; $this->ruletype = 'modifiers_add'; break; // modifiers are also stored in the shipping member!
+			case 'extrashippingmultiplier': $this->shipping = $value; $this->ruletype = 'modifiers_multiply'; break; // modifiers are also stored in the shipping member!
+			case 'comment':         break; // Completely ignore all comments!
+			case 'condition':       $this->conditions[] = $value; break;
+			default:                JFactory::getApplication()->enqueueMessage(JText::sprintf('VMSHIPMENT_RULES_UNKNOWN_VARIABLE', $var, $rulepart), 'error');
 		}
 	}
 	
@@ -1126,11 +1215,16 @@ class ShippingRule {
 		return $this->evaluateTerm($this->shipping, $vals);
 	}
 
-	function matches(&$vals) {
+	function evaluateRule (&$vals) {
+		if ($this->evaluated) 
+			return; // Already evaluated
+
+		$this->evaluated = True;
+		$this->match = False; // Default, set it to True below if all conditions match...
 		// First, check the country, if any conditions are given:
 		if (count ($this->countries) > 0 && !in_array ($vals['countryid'], $this->countries)) {
 // 			vmdebug('Rule::matches: Country check failed: countryid='.print_r($vals['countryid'],1).', countries are: '.print_r($this->countries,1).'...');
-			return False;
+			return;
 		}
 
 		foreach ($this->conditions as $c) {
@@ -1138,18 +1232,21 @@ class ShippingRule {
 			$ret = $this->evaluateTerm($c, $vals);
 
 			if (is_null($ret) || (!$ret)) {
-				return false;
+				return;
 			}
 		}
-		// All conditions match, so return true for rules; For definitions add the variable to the vals 
-		if ($this->is_definition) {
-			$vals[$this->name] = $this->evaluateTerm($this->shipping, $vals);
-			// This rule does not specify shipping costs (just modify the cart values!), so return false
-			return false;
-		} else {
-			return true;
+		// All conditions match
+		$this->match = True;
+		$this->value = $this->calculateShipping($vals);
+		// For definitions add the variable to the vals 
+		if ($this->ruletype=='definition') {
+			$vals[$this->name] = $this->value;
 		}
 	}
+	function matches(&$vals) {
+		$this->evaluateRule($vals);
+		return $this->match;
+	}
 
 	function getRuleName($vals) {
 		// Replace all {variable} tags in the name by the variables from $vals
@@ -1167,16 +1264,14 @@ class ShippingRule {
 	}
 	
 	function getShippingCosts($vals) {
-		return $this->calculateShipping($vals);
+		$this->evaluateRule($vals);
+		return $this->value;
 	}
 	
 	function isNoShipping() {
 		// NoShipping is set, so if the rule matches, this method should not offer any shipping at all
 		return (is_string($this->shipping) && (strtolower($this->shipping)=="noshipping"));
 	}
-	function isDefinition() {
-		return $this->is_definition;
-	}
 
 }