Added VisibleKey, allowing objects to be locked so they are not visible by normal look command.

Fixed bug in create_object that sometimes caused rooms to be created with a location !=None
Expanded @destroy to better handle names and not just dbrefs.
/Griatch
This commit is contained in:
Griatch 2009-10-22 19:44:16 +00:00
parent 557c4eb07b
commit 656ecd9f97
6 changed files with 163 additions and 42 deletions

View file

@ -1022,6 +1022,7 @@ def cmd_dig(command):
None, None,
source_object, source_object,
script_parent=room_parent) script_parent=room_parent)
ptext = "" ptext = ""
if room_parent: if room_parent:
if new_room.get_script_parent() == room_parent: if new_room.get_script_parent() == room_parent:
@ -1277,26 +1278,26 @@ def cmd_destroy(command):
switch_override = True switch_override = True
for targetname in targetlist: for targetname in targetlist:
target_obj = source_object.search_for_object(targetname) target_obj = source_object.search_for_object_global(targetname)
# Use search_for_object to handle duplicate/nonexistant results. # Use search_for_object to handle duplicate/nonexistant results.
if not target_obj: if not target_obj:
return return
if target_obj.is_player() or target_obj.has_flag('SAFE'): if target_obj.is_player() or target_obj.has_flag('SAFE'):
if source_object.id == target_obj.id: if source_object.id == target_obj.id:
source_object.emit_to("You can't destroy yourself.") source_object.emit_to("%s: You can't destroy yourself." % targetname)
return continue
if not switch_override: if not switch_override:
source_object.emit_to("You must use @destroy/override on Players and objects with the SAFE flag set.") source_object.emit_to("%s: You must use @destroy/override on Players and objects with the SAFE flag set." % targetname)
return continue
if target_obj.is_superuser(): if target_obj.is_superuser():
source_object.emit_to("You can't destroy a superuser.") source_object.emit_to("%s: You can't destroy a superuser." % targetname)
return continue
elif target_obj.is_garbage(): elif target_obj.is_garbage():
source_object.emit_to("That object is already destroyed.") source_object.emit_to("%s: That object is already destroyed." % targetname)
return continue
elif target_obj.is_going() and 'instant' not in switches: elif target_obj.is_going() and 'instant' not in switches:
source_object.emit_to("That object is already scheduled for destruction.") source_object.emit_to("%s: That object is already scheduled for destruction." % targetname)
return continue
# Run any scripted things that happen before destruction. # Run any scripted things that happen before destruction.
target_obj.scriptlink.at_object_destruction(pobject=source_object) target_obj.scriptlink.at_object_destruction(pobject=source_object)
@ -1370,10 +1371,13 @@ def cmd_lock(command):
EnterLock: Players/Things: controls who may enter/teleport into EnterLock: Players/Things: controls who may enter/teleport into
the object. the object.
VisibleLock: Players/Things: controls if the object is visible to
someone using the look command.
Fail messages echoed to the player are stored in the attributes 'lock_msg', Fail messages echoed to the player are stored in the attributes 'lock_msg',
'use_lock_msg' and 'enter_lock_msg' on the locked object in question. If no 'use_lock_msg', 'enter_lock_msg' and 'visible_lock_msg' on the locked object
such message is stored, a default will be used (or none at all in some cases). in question. If no such message is stored, a default will be used (or none at
all in some cases).
""" """
source_object = command.source_object source_object = command.source_object
@ -1397,7 +1401,7 @@ def cmd_lock(command):
ltype = "DefaultLock" ltype = "DefaultLock"
obj_name, ltype = obj_name.strip(), ltype.strip() obj_name, ltype = obj_name.strip(), ltype.strip()
if ltype not in ["DefaultLock","UseLock","EnterLock"]: if ltype not in ["DefaultLock","UseLock","EnterLock","VisibleLock"]:
source_object.emit_to("Lock type '%s' not recognized." % ltype) source_object.emit_to("Lock type '%s' not recognized." % ltype)
return return
@ -1407,7 +1411,7 @@ def cmd_lock(command):
obj_locks = obj.get_attribute_value("LOCKS") obj_locks = obj.get_attribute_value("LOCKS")
if "list" in switches or not switches: if "list" in switches:
if not obj_locks: if not obj_locks:
s = "There are no locks on %s." % obj.get_name() s = "There are no locks on %s." % obj.get_name()
else: else:

View file

@ -44,10 +44,9 @@ class Key(object):
def __str__(self): def __str__(self):
string = " " string = " "
if not self.criteria: if not self.criteria:
string += " <Impassable>" string += " (Impassable)"
for crit in self.criteria: string += ", ".join(self.criteria)
string += " %s," % crit return string
return string[:-1].strip()
def _result(self, result): def _result(self, result):
"Return result depending on exact criterion." "Return result depending on exact criterion."

View file

@ -133,21 +133,35 @@ class ObjectManager(models.Manager):
except IndexError: except IndexError:
return None return None
def global_object_name_search(self, ostring, exact_match=False, limit_types=[]): def global_object_name_search(self, ostring, exact_match=True, limit_types=[]):
""" """
Searches through all objects for a name match. Searches through all objects for a name match.
limit_types is a list of types as defined in defines_global. limit_types is a list of types as defined in defines_global.
""" """
if self.is_dbref(ostring): if self.is_dbref(ostring):
return [self.dbref_search(ostring, limit_types=limit_types)] o_query = self.dbref_search(ostring, limit_types=limit_types)
if o_query:
return [o_query]
return None
# get rough match
o_query = self.filter(name__icontains=ostring)
o_query = o_query.exclude(type__in=[defines_global.OTYPE_GARBAGE,
defines_global.OTYPE_GOING])
if not o_query:
# use list-search to catch N-style queries. Note
# that we want to keep the original ostring since
# search_object_namestr does its own N-string treatment
# on this.
dum, test_ostring = self._parse_match_number(ostring)
o_query = self.filter(name__icontains=test_ostring)
o_query = o_query.exclude(type__in=[defines_global.OTYPE_GARBAGE,
defines_global.OTYPE_GOING])
match_type = "fuzzy"
if exact_match: if exact_match:
o_query = self.filter(name__iexact=ostring) match_type = "exact"
else: return self.list_search_object_namestr(o_query, ostring,
o_query = self.filter(name__icontains=ostring) limit_types=limit_types,
if limit_types is not False: match_type=match_type)
for limiter in limit_types:
o_query.filter(type=limiter)
return o_query.exclude(type__in=[defines_global.OTYPE_GARBAGE, return o_query.exclude(type__in=[defines_global.OTYPE_GARBAGE,
defines_global.OTYPE_GOING]) defines_global.OTYPE_GOING])
@ -196,16 +210,16 @@ class ObjectManager(models.Manager):
if prospect.dbref_match(ostring)] if prospect.dbref_match(ostring)]
#search by name - this may return multiple matches. #search by name - this may return multiple matches.
results = self._list_search_helper1(searchlist,ostring,dbref_only, results = self._match_name_attribute(searchlist,ostring,dbref_only,
limit_types, match_type, limit_types, match_type,
attribute_name=attribute_name) attribute_name=attribute_name)
match_number = None match_number = None
if not results: if not results:
#if we have no match, check if we are dealing #if we have no match, check if we are dealing
#with a "N-keyword" query - if so, strip it and run again. #with a "N-keyword" query - if so, strip it and run again.
match_number, ostring = self._list_search_helper2(ostring) match_number, ostring = self._parse_match_number(ostring)
if match_number != None and ostring: if match_number != None and ostring:
results = self._list_search_helper1(searchlist,ostring,dbref_only, results = self._match_name_attribute(searchlist,ostring,dbref_only,
limit_types, match_type, limit_types, match_type,
attribute_name=attribute_name) attribute_name=attribute_name)
if match_type == "fuzzy": if match_type == "fuzzy":
@ -226,7 +240,7 @@ class ObjectManager(models.Manager):
pass pass
return results return results
def _list_search_helper1(self, searchlist, ostring, dbref_only, def _match_name_attribute(self, searchlist, ostring, dbref_only,
limit_types, match_type, limit_types, match_type,
attribute_name=None): attribute_name=None):
""" """
@ -261,10 +275,10 @@ class ObjectManager(models.Manager):
return [prospect for prospect in searchlist return [prospect for prospect in searchlist
if prospect.name_match(ostring, match_type=match_type)] if prospect.name_match(ostring, match_type=match_type)]
def _list_search_helper2(self, ostring): def _parse_match_number(self, ostring):
""" """
Hhelper function for list_search_object_namestr - Helper function for list_search_object_namestr -
strips eventual keyword-N endings from a search criterion strips eventual N-keyword endings from a search criterion
""" """
if not '-' in ostring: if not '-' in ostring:
return False, ostring return False, ostring
@ -426,6 +440,7 @@ class ObjectManager(models.Manager):
default_desc = defines_global.DESC_PLAYER default_desc = defines_global.DESC_PLAYER
elif otype == defines_global.OTYPE_ROOM: elif otype == defines_global.OTYPE_ROOM:
default_desc = defines_global.DESC_ROOM default_desc = defines_global.DESC_ROOM
location = None
elif otype == defines_global.OTYPE_EXIT: elif otype == defines_global.OTYPE_EXIT:
default_desc = defines_global.DESC_EXIT default_desc = defines_global.DESC_EXIT
else: else:

View file

@ -221,23 +221,27 @@ class Object(models.Model):
else: else:
return results[0] return results[0]
def search_for_object_global(self, ostring, exact_match=True, limit_types=[]): def search_for_object_global(self, ostring, exact_match=True, limit_types=[],
emit_to_obj=None):
""" """
Search for ostring in all objects, globally. Handle multiple-matches Search for ostring in all objects, globally. Handle multiple-matches
and no matches gracefully. This is mainly intended to be used by and no matches gracefully. This is mainly intended to be used by
admin and build-type commands. It also accepts #dbref admin and build-type commands. It also accepts #dbref
search queries. search queries.
""" """
if not emit_to_obj:
emit_to_obj = self
results = Object.objects.global_object_name_search(ostring, exact_match=exact_match, results = Object.objects.global_object_name_search(ostring, exact_match=exact_match,
limit_types=limit_types) limit_types=limit_types)
if not results: if not results:
self.emit_to("No matches found for '%s'." % ostring) emit_to_obj.emit_to("No matches found for '%s'." % ostring)
return return
if len(results) > 1: if len(results) > 1:
string = "More than one match for '%s' (please narrow target):" % ostring string = "More than one match for '%s' (please narrow target):" % ostring
for res in results: for res in results:
string += "\n %s" % res.get_name() string += "\n %s" % res.get_name()
self.emit_to(string) emit_to_obj.emit_to(string)
return return
return results[0] return results[0]
@ -1157,7 +1161,10 @@ class Object(models.Model):
self.clear_all_attributes() self.clear_all_attributes()
self.clear_all_flags() self.clear_all_flags()
self.clear_state() self.clear_state()
self.home = None
self.owner = None
self.location = None
self.save()
# Deferred imports are poopy. This will require some thought to fix. # Deferred imports are poopy. This will require some thought to fix.
from src import cmdhandler from src import cmdhandler

View file

@ -137,6 +137,13 @@ class EvenniaBasicObject(object):
# See if the envoker sees dbref numbers. # See if the envoker sees dbref numbers.
lock_msg = "" lock_msg = ""
if pobject: if pobject:
#check visibility lock
if not target_obj.scriptlink.visible_lock(pobject):
temp = target_obj.get_attribute_value("visible_lock_msg")
if temp:
return temp
return "I don't see that here."
show_dbrefs = pobject.sees_dbrefs() show_dbrefs = pobject.sees_dbrefs()
#check for the defaultlock, this shows a lock message after the normal desc, if one is defined. #check for the defaultlock, this shows a lock message after the normal desc, if one is defined.
@ -165,6 +172,9 @@ class EvenniaBasicObject(object):
con_exits = [] con_exits = []
for obj in target_obj.get_contents(): for obj in target_obj.get_contents():
# check visible lock.
if pobject and not obj.scriptlink.visible_lock(pobject):
continue
if obj.is_player(): if obj.is_player():
if (obj != pobject and obj.is_connected_plr()) or pobject == None: if (obj != pobject and obj.is_connected_plr()) or pobject == None:
con_players.append(obj) con_players.append(obj)
@ -236,6 +246,21 @@ class EvenniaBasicObject(object):
else: else:
return True return True
def visible_lock(self, pobject):
"""
This method returns a True or False boolean value to determine whether
the actor passes the lock. This is generally used for picking up
objects or traversing exits.
values:
* pobject: (Object) The object requesting the action.
"""
locks = self.scripted_obj.get_attribute_value("LOCKS")
if locks:
return locks.check("VisibleLock", pobject)
else:
return True
def lock_func(self, obj): def lock_func(self, obj):
""" """
This is a custom function called by locks with the FuncKey key. Its This is a custom function called by locks with the FuncKey key. Its

View file

@ -109,3 +109,74 @@ class EvenniaBasicPlayer(object):
location = pobject.get_location() location = pobject.get_location()
if location != None: if location != None:
location.emit_to_contents("%s has disconnected." % (pobject.get_name(show_dbref=False),), exclude=pobject) location.emit_to_contents("%s has disconnected." % (pobject.get_name(show_dbref=False),), exclude=pobject)
def default_lock(self, pobject):
"""
This method returns a True or False boolean value to determine whether
the actor passes the lock. This is generally used for picking up
objects or traversing exits.
values:
* pobject: (Object) The object requesting the action.
"""
locks = self.scripted_obj.get_attribute_value("LOCKS")
if locks:
return locks.check("DefaultLock", pobject)
else:
return True
def use_lock(self, pobject):
"""
This method returns a True or False boolean value to determine whether
the actor passes the lock. This is generally used for seeing whether
a player can use an object or any of its commands.
values:
* pobject: (Object) The object requesting the action.
"""
locks = self.scripted_obj.get_attribute_value("LOCKS")
if locks:
return locks.check("UseLock", pobject)
else:
return True
def enter_lock(self, pobject):
"""
This method returns a True or False boolean value to determine whether
the actor passes the lock. This is generally used for seeing whether
a player can enter another object.
values:
* pobject: (Object) The object requesting the action.
"""
locks = self.scripted_obj.get_attribute_value("LOCKS")
if locks:
return locks.check("EnterLock", pobject)
else:
return True
def visible_lock(self, pobject):
"""
This method returns a True or False boolean value to determine whether
the actor passes the lock. This is generally used for picking up
objects or traversing exits.
values:
* pobject: (Object) The object requesting the action.
"""
locks = self.scripted_obj.get_attribute_value("LOCKS")
if locks:
return locks.check("VisibleLock", pobject)
else:
return True
def lock_func(self, obj):
"""
This is a custom function called by locks with the FuncKey key. Its
return value should match that specified in the lock (so no true/false
lock result is actually determined in here). Default desired return
value is True. Also remember that the comparison in FuncKey is made
using the string representation of the return value, since @lock can
only define string lock criteria.
"""
return False