Index: cpp/frams/vm/classes/collectionobj.cpp
===================================================================
--- cpp/frams/vm/classes/collectionobj.cpp	(revision 848)
+++ cpp/frams/vm/classes/collectionobj.cpp	(revision 849)
@@ -1,4 +1,4 @@
 // This file is a part of Framsticks SDK.  http://www.framsticks.com/
-// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
+// Copyright (C) 1999-2019  Maciej Komosinski and Szymon Ulatowski.
 // See LICENSE.txt for details.
 
@@ -50,5 +50,5 @@
 ParamEntry dictionary_paramtab[] =
 {
-	{ "Dictionary", 1, 11, "Dictionary", "Dictionary associates stored values with string keys "
+	{ "Dictionary", 1, 12, "Dictionary", "Dictionary associates stored values with string keys "
 	"(\"key\" is the first argument in get/set/remove functions). Integer key can be "
 	"used to enumerate all elements (note that while iterating, the elements are returned in no particular order).\n"
@@ -70,6 +70,7 @@
 	{ "size", 0, PARAM_NOSTATIC | PARAM_READONLY, "Element count", "d", GETONLY(size), },
 	{ "remove", 0, PARAM_NOSTATIC, "Remove", "p(x key)", PROCEDURE(p_remove), "Removes the named or indexed element (depending on the argument type: string or int)." },
-	{ "get", 0, PARAM_NOSTATIC, "Get element", "p x(x key)", PROCEDURE(p_get), "Retrieves the named or indexed element (depending on the argument type: string or int). null is returned for nonexistent keys.\nobject.get(key) can be shortened to 'object[key]'" },
+	{ "get", 0, PARAM_NOSTATIC, "Get element", "p x(x key)", PROCEDURE(p_get), "Retrieves the named or indexed element (depending on the argument type: string or int). Accessing nonexistent keys is an error (use hasKey() if necessary).\nobject.get(key) can be shortened to 'object[key]'" },
 	{ "getKey", 0, PARAM_NOSTATIC, "Get a key", "p s(d index)", PROCEDURE(p_getKey), "Returns the key of the indexed element (0 <= index < size)" },
+	{ "hasKey", 0, PARAM_NOSTATIC, "Check if key exists", "p d(s key)", PROCEDURE(p_hasKey), "Returns 1 (interpreted as true) if dictionary contains the supplied key, or 0 (false) otherwise.\nExample:\n   if (obj.hasKey(\"a\"))\n      x = obj->a;" },
 	{ "set", 0, PARAM_NOSTATIC, "Set element", "p x(x key,x value)", PROCEDURE(p_set), "Set element value for the specified key or index (depending on the argument type: string or int).\n"
 	"Returns the value previously associated with the given key (or index).\n"
@@ -106,6 +107,6 @@
 		for (int i = data.size() - 1; i >= 0; i--)
 		{
-		ExtValue *v = (ExtValue*)data.get(i);
-		if (v) delete v;
+			ExtValue *v = (ExtValue*)data.get(i);
+			if (v) delete v;
 		}
 	data.clear();
@@ -221,5 +222,5 @@
 	{
 		double d = a - ((ExtValue*)data.get(i))->getDouble();
-		s += d*d;
+		s += d * d;
 	}
 	ret->setDouble(sqrt(s / max(1, data.size() - 1)));
@@ -391,8 +392,17 @@
 ExtValue DictionaryObject::get(SString key)
 {
-	ExtValue *val = (ExtValue*)hash.get(key);
-	if (val)
-		return *val;
-	return ExtValue::empty();
+	int found = 0;
+	ExtValue *val = (ExtValue*)hash.get(key, &found);
+	if (found == 0)
+	{
+		logPrintf("Dictionary", "get", LOG_ERROR, "Key '%s' not found", key.c_str());
+		return ExtValue::invalid();
+	}
+	else
+	{
+		if (val)
+			return *val;
+		return ExtValue::empty();
+	}
 }
 
@@ -422,4 +432,11 @@
 	}
 	*ret = ExtValue();
+}
+
+void DictionaryObject::p_hasKey(PARAMPROCARGS)
+{
+	int found = 0;
+	hash.get(args->getString(), &found);
+	ret->setInt(found);
 }
 
Index: cpp/frams/vm/classes/collectionobj.h
===================================================================
--- cpp/frams/vm/classes/collectionobj.h	(revision 848)
+++ cpp/frams/vm/classes/collectionobj.h	(revision 849)
@@ -1,4 +1,4 @@
 // This file is a part of Framsticks SDK.  http://www.framsticks.com/
-// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
+// Copyright (C) 1999-2019  Maciej Komosinski and Szymon Ulatowski.
 // See LICENSE.txt for details.
 
@@ -73,4 +73,5 @@
 	PARAMPROCDEF(p_get);
 	PARAMPROCDEF(p_getKey);
+	PARAMPROCDEF(p_hasKey);
 	PARAMPROCDEF(p_set);
 	PARAMPROCDEF(p_find);
