Example #1
0
def query_object_properties(typeclass_key, object_key):
    """
    Query all properties of the given object.

    Args:
        typeclass_key: (string) typeclass' key.
        object_key: (string) object' key.
    """
    # Get fields.
    fields = []
    fields.append({
        "name": "level",
        "label": _("Level"),
        "help_text": _("Properties's level.")
    })

    properties_info = TYPECLASS(typeclass_key).get_properties_info()
    for key, info in properties_info.items():
        if info["mutable"]:
            continue

        fields.append({
            "name": key,
            "label": info["name"],
            "help_text": info["desc"]
        })

    if len(fields) == 1:
        # No custom properties.
        table = {
            "fields": [],
            "records": [],
        }
        return table

    # Get rows.
    levels = []
    data = {}
    records = OBJECT_PROPERTIES.get_properties_all_levels(object_key)
    for record in records:
        if record.level not in levels:
            levels.append(record.level)
            data[record.level] = {"level": record.level}
        data[record.level][record.property] = record.value

    rows = []
    for level in levels:
        line = [data[level].get(field["name"], "") for field in fields]
        rows.append(line)

    table = {
        "fields": fields,
        "records": rows,
    }

    return table
Example #2
0
    def set_typeclass(self, typeclass_key):
        """
        Set object's typeclass.
        
        Args:
            typeclass_key: (string) Typeclass's key.
        """
        typeclass_cls = TYPECLASS(typeclass_key)
        if not typeclass_cls:
            logger.log_errmsg("Can not get %s's typeclass: %s." %
                              (self.get_data_key(), typeclass_key))
            return

        if type(self) == typeclass_cls:
            # No change.
            return

        if not hasattr(self, 'swap_typeclass'):
            logger.log_errmsg("%s cannot have a type at all!" %
                              self.get_data_key())
            return

        # Set new typeclass.
        # It will call target typeclass's at_object_creation hook.
        # You should prevent at_object_creation rewrite current attributes.
        self.swap_typeclass(typeclass_cls, clean_attributes=False)
        if typeclass_cls.path != self.typeclass_path:
            logger.log_errmsg("%s's typeclass %s is wrong!" %
                              (self.get_data_key(), typeclass_cls.path))
            return
Example #3
0
class MudderyWorldNPC(TYPECLASS("NPC")):
    """
    The character not controlled by players.
    """
    typeclass_key = "WORLD_NPC"
    typeclass_name = _("World NPC", "typeclasses")
    model_name = "world_npcs"
Example #4
0
def get_object_record(obj_key):
    """
    Query the object's record.

    Args:
        obj_key: (string) The key of the object.

    Returns:
        The object's data record.
    """
    record = None
    model_name = TYPECLASS("OBJECT").model_name
    try:
        # Get record.
        model_obj = apps.get_model(settings.WORLD_DATA_APP, model_name)
        record = model_obj.objects.get(key=obj_key)
    except Exception as e:
        ostring = "Can not get record %s: %s." % (obj_key, e)
        print(ostring)
        print(traceback.print_exc())

    if not record:
        ostring = "Can not get record %s." % obj_key
        print(ostring)
        print(traceback.print_exc())

    return record
Example #5
0
class MudderyReverseExit(TYPECLASS("EXIT")):
    """
    This is the reverse side of the two way exit.
    """
    typeclass_key = "REVERSE_EXIT"
    typeclass_name = _("Reverse Exit", "typeclasses")

    def after_data_loaded(self):
        """
        Called after self.data_loaded().
        """
        self.set_name(getattr(self.dfield, "reverse_name", ""))

        # reverse location and destination
        if not self.location:
            self.set_location(getattr(self.dfield, "destination", ""))

        # set exit's destination
        self.set_obj_destination(getattr(self.dfield, "location", ""))

        self.condition = getattr(self.dfield, "condition", "")

        # set icon
        self.set_icon(getattr(self.dfield, "icon", ""))

    def reset_location(self):
        """
        Set object's location to its default location.

        Returns:
            None
        """
        if hasattr(self.dfield, "destination"):
            self.set_location(self.dfield.destination)
Example #6
0
class MudderyCommonNPC(TYPECLASS("BASE_NPC")):
    """
    The character not controlled by players.
    """
    typeclass_key = "COMMON_NPC"
    typeclass_name = _("Common NPC", "typeclasses")
    model_name = "common_npcs"
Example #7
0
def update_object_key(typeclass_key, old_key, new_key):
    """
    Update an object's key in other tables.

    Args:
        typeclass: (string) object's typeclass.
        old_key: (string) object's old key.
        new_key: (string) object's new key
    """
    # The object's key has changed.
    typeclass = TYPECLASS(typeclass_key)
    if issubclass(typeclass, TYPECLASS("AREA")):
        # Update relative room's location.
        model_name = TYPECLASS("ROOM").model_name
        if model_name:
            general_query_mapper.filter_records(model_name, location=old_key).update(location=new_key)
    elif issubclass(typeclass, TYPECLASS("ROOM")):
        # Update relative exit's location.
        model_name = TYPECLASS("EXIT").model_name
        if model_name:
            general_query_mapper.filter_records(model_name, location=old_key).update(location=new_key)
            general_query_mapper.filter_records(model_name, destination=old_key).update(destination=new_key)

        # Update relative world object's location.
        model_name = TYPECLASS("WORLD_OBJECT").model_name
        if model_name:
            general_query_mapper.filter_records(model_name, location=old_key).update(location=new_key)

        # Update relative world NPC's location.
        model_name = TYPECLASS("WORLD_NPC").model_name
        if model_name:
            general_query_mapper.filter_records(model_name, location=old_key).update(location=new_key)
Example #8
0
class MudderyMonster(TYPECLASS("NON_PLAYER")):
    """
    Default mob. Monsters are hostile to players, they can be attacked.
    """
    typeclass_key = "MONSTER"

    def after_data_loaded(self):
        """
        Init the character.
        """
        super(MudderyMonster, self).after_data_loaded()

        # set level
        self.db.level = getattr(self.dfield, "level", 1)

        # Character can auto fight.
        self.auto_fight = True

        # set home
        self.home = self.location

        # load dialogues.
        self.load_dialogues()

    def load_dialogues(self):
        """
        Load dialogues.
        """
        dialogues = NPC_DIALOGUES.filter(self.get_data_key())

        self.default_dialogues = [
            dialogue.dialogue for dialogue in dialogues if dialogue.default
        ]
        self.dialogues = [
            dialogue.dialogue for dialogue in dialogues if not dialogue.default
        ]

    def get_available_commands(self, caller):
        """
        This returns a list of available commands.
        """
        commands = []
        if self.is_alive():
            if self.dialogues or self.default_dialogues:
                # If the character have something to talk, add talk command.
                commands.append({
                    "name": _("Talk"),
                    "cmd": "talk",
                    "args": self.dbref
                })

            commands.append({
                "name": _("Attack"),
                "cmd": "attack",
                "args": self.dbref
            })
        return commands
Example #9
0
def query_typeclass_table(typeclass_key):
    """
    Query a table of objects of the same typeclass.

    Args:
        typeclass_key: (string) typeclass's key.
    """
    typeclass_cls = TYPECLASS(typeclass_key)
    if not typeclass_cls:
        raise MudderyError(ERR.no_table,
                           "Can not find typeclass %s" % typeclass_key)

    # get all tables' name
    tables = typeclass_cls.get_models()
    if not tables:
        raise MudderyError(ERR.no_table,
                           "Can not get tables of %s" % typeclass_key)

    # get all tables' fields
    # add the first table
    table_fields = query_fields(tables[0])
    fields = [field for field in table_fields if field["name"] != "id"]

    # add other tables
    for table in tables[1:]:
        table_fields = query_fields(table)
        fields.extend([
            field for field in table_fields
            if field["name"] != "id" and field["name"] != "key"
        ])

    # get all tables' data
    records = general_query_mapper.get_all_from_tables(tables)

    rows = []
    for record in records:
        line = [str(record[field["name"]]) for field in fields]
        rows.append(line)

    table = {
        "fields": fields,
        "records": rows,
    }
    return table
Example #10
0
class MudderyRoom(TYPECLASS("OBJECT"), DefaultRoom):
    """
    Rooms are like any Object, except their location is None
    (which is default). They also use basetype_setup() to
    add locks so they cannot be puppeted or picked up.
    (to change that, use at_object_creation instead)

    See examples/object.py for a list of
    properties and methods available on all Objects.
    """
    typeclass_key = "ROOM"
    typeclass_name = _("Room", "typeclasses")
    model_name = "world_rooms"

    def at_object_creation(self):
        """
        Called once, when this object is first created. This is the
        normal hook to overload for most object types.
        """
        super(MudderyRoom, self).at_object_creation()

        self.peaceful = False
        self.position = None
        self.background = None

    def after_data_loaded(self):
        """
        Set data_info to the object.
        """
        super(MudderyRoom, self).after_data_loaded()

        self.peaceful = getattr(self.dfield, "peaceful", False)

        self.position = None
        try:
            # set position
            position = getattr(self.dfield, "position", None)
            if position:
                self.position = ast.literal_eval(position)
        except Exception, e:
            logger.log_tracemsg("load position error: %s" % e)

        # get background
        self.background = None
        resource = getattr(self.dfield, "background", None)
        if resource:
            try:
                resource_info = IMAGE_RESOURCES.get(resource)
                self.background = {
                    "resource": resource_info.resource,
                    "width": resource_info.image_width,
                    "height": resource_info.image_height
                }
            except Exception, e:
                logger.log_tracemsg("Load background %s error: %s" %
                                    (resource, e))
Example #11
0
def query_object_form(base_typeclass, obj_typeclass, obj_key):
    """
    Query all data of an object.

    Args:
        base_typeclass: (string) candidate typeclass group.
        obj_typeclass: (string, optional) object's typeclass. If it is empty, use the typeclass of the object
                        or use base typeclass as object's typeclass.
        obj_key: (string) object's key. If it is empty, query an empty form.
    """
    candidate_typeclasses = TYPECLASS_SET.get_group(base_typeclass)
    if not candidate_typeclasses:
        raise MudderyError(ERR.no_table,
                           "Can not find typeclass: %s" % base_typeclass)

    if not obj_typeclass:
        if obj_key:
            # Get typeclass from the object's record
            table_name = TYPECLASS("OBJECT").model_name
            record = general_query_mapper.get_record_by_key(
                table_name, obj_key)
            obj_typeclass = record.typeclass
        else:
            # Or use the base typeclass
            obj_typeclass = base_typeclass

    typeclass = TYPECLASS_SET.get(obj_typeclass)
    if not typeclass:
        raise MudderyError(ERR.no_table,
                           "Can not find typeclass: %s" % obj_typeclass)
    table_names = typeclass.get_models()

    forms = []
    for table_name in table_names:
        if obj_key:
            object_form = query_form(table_name, key=obj_key)
        else:
            object_form = query_form(table_name)

        forms.append({"table": table_name, "fields": object_form})

    # add typeclasses
    if len(forms) > 0:
        for field in forms[0]["fields"]:
            if field["name"] == "typeclass":
                # set typeclass to the new value
                field["value"] = obj_typeclass
                field["type"] = "Select"
                field["choices"] = [
                    (key, cls.typeclass_name + " (" + key + ")")
                    for key, cls in candidate_typeclasses.items()
                ]
                break

    return forms
Example #12
0
def save_object_form(tables, obj_typeclass, obj_key):
    """
    Save all data of an object.

    Args:
        tables: (list) a list of table data.
               [{
                 "table": (string) table's name.
                 "record": (string, optional) record's id. If it is empty, add a new record.
                }]
        obj_typeclass: (string) object's typeclass.
        obj_key: (string) current object's key. If it is empty or changed, query an empty form.
    """
    if not tables:
        raise MudderyError(ERR.invalid_form,
                           "Invalid form.",
                           data="Empty form.")

    try:
        typeclass = TYPECLASS(obj_typeclass)
    except:
        raise MudderyError(ERR.invalid_form,
                           "Invalid form.",
                           data="No typeclass: %s" % obj_typeclass)

    # Get object's new key from the first form.
    new_obj = not (obj_key and obj_key == tables[0]["values"]["key"])
    if new_obj:
        try:
            obj_key = tables[0]["values"]["key"]
        except KeyError:
            pass

        if not obj_key:
            # Generate a new key.
            try:
                # Get object table's last id.
                query = general_query_mapper.get_the_last_record(
                    typeclass.model_name)
                if query:
                    index = int(query.id) + 1
                else:
                    index = 1
            except Exception, e:
                raise MudderyError(ERR.invalid_form,
                                   "Invalid form.",
                                   data="No typeclass model: %s" %
                                   obj_typeclass)

            obj_key = obj_typeclass + "_" + str(index)

            for table in tables:
                table["values"]["key"] = obj_key
Example #13
0
class MudderySkillBook(TYPECLASS("COMMON_OBJECT")):
    """
    This is a skill book. Players can use it to learn a new skill.
    """
    typeclass_key = "SKILL_BOOK"
    typeclass_name = _("Skill Book", "typeclasses")
    model_name = "skill_books"

    def get_available_commands(self, caller):
        """
        This returns a list of available commands.
        "args" must be a string without ' and ", usually it is self.dbref.
        """
        commands = []
        if self.db.number > 0:
            commands.append({
                "name": _("Use"),
                "cmd": "use",
                "args": self.dbref
            })
            if self.location and self.can_discard:
                commands.append({
                    "name": _("Discard"),
                    "cmd": "discard",
                    "args": self.dbref
                })
        return commands

    def take_effect(self, user, number):
        """
        Use this object.

        Args:
            user: (object) the object who uses this
            number: (int) the number of the object to use

        Returns:
            (result, number):
                result: (string) a description of the result
                number: (int) actually used number
        """
        if not user:
            raise ValueError("User should not be None.")

        skill_key = getattr(self.dfield, "skill", None)
        if not skill_key:
            return _("No effect."), 0

        if user.learn_skill(skill_key, False, False):
            return _("You learned skill."), 1
        else:
            return _("No effect."), 0
Example #14
0
def query_typeclass_table(typeclass_key):
    """
    Query a table of objects of the same typeclass.

    Args:
        typeclass_key: (string) typeclass's key.
    """
    typeclass_cls = TYPECLASS(typeclass_key)
    if not typeclass_cls:
        raise MudderyError(ERR.no_table, "Can not find typeclass %s" % typeclass_key)

    # get all tables' name
    tables = typeclass_cls.get_models()
    if not tables:
        raise MudderyError(ERR.no_table, "Can not get tables of %s" % typeclass_key)

    # get all tables' fields
    # add the first table
    table_fields = query_fields(tables[0])
    fields = [field for field in table_fields if field["name"] != "id"]

    # add other tables
    for table in tables[1:]:
        table_fields = query_fields(table)
        fields.extend([field for field in table_fields if field["name"] != "id" and field["name"] != "key"])

    # get all tables' data
    records = general_query_mapper.get_all_from_tables(tables)

    rows = []
    for record in records:
        line = [str(record[field["name"]]) for field in fields]
        rows.append(line)

    table = {
        "fields": fields,
        "records": rows,
    }
    return table
Example #15
0
class MudderyArea(TYPECLASS("OBJECT")):
    """
    Areas are compose the whole map. Rooms are belongs to areas.
    """
    typeclass_key = "AREA"
    typeclass_name = _("Area", "typeclasses")

    def at_object_creation(self):
        """
        Called once, when this object is first created. This is the
        normal hook to overload for most object types.
        """
        super(MudderyArea, self).at_object_creation()

        self.background = None
        self.background_point = None
        self.corresp_map_pos = None

    def after_data_loaded(self):
        """
        Set data_info to the object.
        """
        super(MudderyArea, self).after_data_loaded()

        # get background
        self.background = None
        resource = getattr(self.dfield, "background", None)
        if resource:
            try:
                resource_info = IMAGE_RESOURCES.get(resource)
                self.background = {
                    "resource": resource_info.resource,
                    "width": resource_info.image_width,
                    "height": resource_info.image_height
                }
            except Exception, e:
                logger.log_tracemsg("Load background %s error: %s" %
                                    (resource, e))

        self.background_point = None
        background_point = getattr(self.dfield, "background_point", None)
        try:
            # set background point
            if background_point:
                self.background_point = ast.literal_eval(background_point)
        except Exception, e:
            logger.log_tracemsg("load background point '%s' error: %s" %
                                (background_point, e))
Example #16
0
class MudderyArea(TYPECLASS("OBJECT")):
    """
    Areas are compose the whole map. Rooms are belongs to areas.
    """
    typeclass_key = "AREA"
    typeclass_name = _("Area", "typeclasses")
    model_name = "world_areas"

    def at_object_creation(self):
        """
        Called once, when this object is first created. This is the
        normal hook to overload for most object types.
        """
        super(MudderyArea, self).at_object_creation()
        self.background = None

    def after_data_loaded(self):
        """
        Set data_info to the object.
        """
        super(MudderyArea, self).after_data_loaded()

        # get background
        self.background = None
        resource = getattr(self.system, "background", None)
        if resource:
            try:
                resource_info = IMAGE_RESOURCES.get(resource)
                self.background = {
                    "resource": resource_info.resource,
                    "width": resource_info.image_width,
                    "height": resource_info.image_height
                }
            except Exception as e:
                logger.log_tracemsg("Load background %s error: %s" %
                                    (resource, e))

    def get_appearance(self, caller):
        """
        This is a convenient hook for a 'look'
        command to call.
        """
        info = super(MudderyArea, self).get_appearance(caller)

        # add background
        info["background"] = getattr(self, "background", None)

        return info
Example #17
0
class MudderyObjectCreator(TYPECLASS("WORLD_OBJECT")):
    """
    This object loads attributes from world data on init automatically.
    """
    typeclass_key = "WORLD_OBJECT_CREATOR"
    typeclass_name = _("Object Creator", "typeclasses")
    model_name = "object_creators"

    # initialize loot handler in a lazy fashion
    @lazy_property
    def loot_handler(self):
        return LootHandler(self, CREATOR_LOOT_LIST.filter(self.get_data_key()))

    def after_data_loaded(self):
        """
        Set data_info to the object."
        """
        super(MudderyObjectCreator, self).after_data_loaded()

        # Load creator info.
        self.loot_verb = getattr(self.dfield, "loot_verb", None)
        if not self.loot_verb:
            self.loot_verb = _("Loot")
        self.loot_condition = getattr(self.dfield, "loot_condition", None)

    def get_available_commands(self, caller):
        """
        This returns a list of available commands.
        "args" must be a string without ' and ", usually it is self.dbref.
        """
        if not STATEMENT_HANDLER.match_condition(self.loot_condition, caller,
                                                 self):
            return []

        commands = [{
            "name": self.loot_verb,
            "cmd": "loot",
            "args": self.dbref
        }]
        return commands

    def loot(self, caller):
        """
        Loot objects.
        """
        self.loot_handler.loot(caller)
Example #18
0
class MudderyWorldNPC(TYPECLASS("BASE_NPC")):
    """
    The character not controlled by players.
    """
    typeclass_key = "WORLD_NPC"
    typeclass_name = _("World NPC", "typeclasses")
    model_name = "world_npcs"

    def after_data_loaded(self):
        """
        Init the character.
        """
        super(MudderyWorldNPC, self).after_data_loaded()

        # if it is dead, reborn at init.
        if not self.is_alive():
            if not self.is_temp and self.reborn_time > 0:
                self.reborn()
Example #19
0
def delete_object(obj_key, base_typeclass=None):
    """
    Delete an object from all tables under the base typeclass.
    """
    if not base_typeclass:
        table_name = TYPECLASS("OBJECT").model_name
        record = general_query_mapper.get_record_by_key(table_name, obj_key)
        base_typeclass = record.typeclass

    typeclasses = TYPECLASS_SET.get_group(base_typeclass)
    tables = set()
    for key, value in typeclasses.items():
        tables.update(value.get_models())

    with transaction.atomic():
        for table in tables:
            try:
                general_query_mapper.delete_record_by_key(table, obj_key)
            except ObjectDoesNotExist:
                pass
Example #20
0
    def attack_target(self, target, desc=""):
        """
        Attack a target.

        Args:
            target: (object) the target object.
            desc: (string) string to describe this attack

        Returns:
            (boolean) attack begins
        """
        if self.is_in_combat():
            # already in battle
            logger.log_errmsg("%s is already in battle." % self.dbref)
            return False

        # search target
        if not target:
            logger.log_errmsg("Can not find the target.")
            return False

        if not target.is_typeclass(TYPECLASS(
                settings.GENERAL_CHARACTER_TYPECLASS_KEY),
                                   exact=False):
            # Target is not a character.
            logger.log_errmsg("Can not attack the target %s." % target.dbref)
            return False

        if target.is_in_combat():
            # obj is already in battle
            logger.log_errmsg("%s is already in battle." % target.dbref)
            return False

        # create a new combat handler
        chandler = create_script(settings.NORMAL_COMBAT_HANDLER)

        # set combat team and desc
        chandler.set_combat({1: [target], 2: [self]}, desc, 0)

        return True
Example #21
0
    def match_condition(self, quest_key):
        """
        Check if the quest matches its condition.
        Args:
            quest_key: (string) quest's key

        Returns:
            (boolean) result
        """
        # Get quest's record.
        model_name = TYPECLASS("QUEST").model_name
        if not model_name:
            return False

        model_quest = apps.get_model(settings.WORLD_DATA_APP, model_name)

        try:
            record = model_quest.objects.get(key=quest_key)
            return STATEMENT_HANDLER.match_condition(record.condition,
                                                     self.owner, None)
        except Exception, e:
            logger.log_errmsg("Can't get quest %s's condition: %s" %
                              (quest_key, e))
Example #22
0
class MudderyExit(TYPECLASS("OBJECT"), DefaultExit):
    """
    Exits are connectors between rooms. Exits are normal Objects except
    they defines the `destination` property. It also does work in the
    following methods:

     basetype_setup() - sets default exit locks (to change, use `at_object_creation` instead).
     at_cmdset_get(**kwargs) - this is called when the cmdset is accessed and should
                              rebuild the Exit cmdset along with a command matching the name
                              of the Exit object. Conventionally, a kwarg `force_init`
                              should force a rebuild of the cmdset, this is triggered
                              by the `@alias` command when aliases are changed.
     at_failed_traverse() - gives a default error message ("You cannot
                            go there") if exit traversal fails and an
                            attribute `err_traverse` is not defined.

    Relevant hooks to overload (compared to other types of Objects):
        at_before_traverse(traveller) - called just before traversing.
        at_after_traverse(traveller, source_loc) - called just after traversing.
        at_failed_traverse(traveller) - called if traversal failed for some reason. Will
                                        not be called if the attribute `err_traverse` is
                                        defined, in which case that will simply be echoed.
    """
    typeclass_key = "EXIT"
    typeclass_name = _("Exit", "typeclasses")
    model_name = "world_exits"

    def after_data_loaded(self):
        """
        Load exit data.

        Returns:
            None
        """
        super(MudderyExit, self).after_data_loaded()

        # set exit's destination
        self.set_obj_destination(getattr(self.system, "destination", None))

        # set action verb
        self.verb = getattr(self.system, "verb", _("GOTO"))

    def at_before_traverse(self, traversing_object):
        """
        Called just before an object uses this object to traverse to
        another object (i.e. this object is a type of Exit)

        Args:
            traversing_object (Object): The object traversing us.

        Notes:
            The target destination should normally be available as
            `self.destination`.
            
            If this method returns False/None, the traverse is cancelled
            before it is even started.

        """
        # trigger event
        if traversing_object.has_account:
            return self.event.at_character_traverse(traversing_object)

        return True

    def at_failed_traverse(self, traversing_object, **kwargs):
        """
        Overloads the default hook to implement a simple default error message.

        Args:
            traversing_object (Object): The object that failed traversing us.

        Notes:
            Using the default exits, this hook will not be called if an
            Attribute `err_traverse` is defined - this will in that case be
            read for an error string instead.

        """
        traversing_object.msg({"alert": "You cannot go there."})

    @classmethod
    def get_event_trigger_types(cls):
        """
        Get an object's available event triggers.
        """
        return [defines.EVENT_TRIGGER_TRAVERSE]

    def get_name(self):
        """
        Get exit's name.
        """
        if self.name:
            return self.name
        elif self.destination:
            return self.destination.get_name()
        else:
            return ""

    def get_available_commands(self, caller):
        """
        This returns a list of available commands.
        "args" must be a string without ' and ", usually it is self.dbref.
        """
        commands = [{"name": self.verb, "cmd": "goto", "args": self.dbref}]
        return commands
Example #23
0
class MudderySkill(TYPECLASS("OBJECT")):
    """
    A skill of the character.
    """
    typeclass_key = "SKILL"

    msg_escape = re.compile(r'%[%|n|c|t]')

    @staticmethod
    def escape_fun(word):
        """
        Change escapes to target words.
        """
        escape_word = word.group()
        char = escape_word[1]
        if char == "%":
            return char
        else:
            return "%(" + char + ")s"

    def at_object_creation(self):
        """
        Set default values.

        Returns:
            None
        """
        super(MudderySkill, self).at_object_creation()

        # set status
        if not self.attributes.has("owner"):
            self.db.owner = None
        if not self.attributes.has("cd_finish_time"):
            self.db.cd_finish_time = 0
        if not self.attributes.has("is_default"):
            self.db.is_default = False

    def set_default(self, is_default):
        """
        Set this skill as the character's default skill.
        When skills in table default_skills changes, character's relative skills
        will change too.

        Args:
            is_default: (boolean) if the is default or not.
        """
        self.db.is_default = is_default

    def is_default(self):
        """
        Check if this skill is the character's default skill.

        Returns:
            (boolean) is default or not
        """
        return self.db.is_default

    def after_data_loaded(self):
        """
        Set data_info to the object.

        Returns:
            None
        """
        super(MudderySkill, self).after_data_loaded()

        # set data
        self.function = getattr(self.dfield, "function", "")
        self.cd = getattr(self.dfield, "cd", 0)
        self.passive = getattr(self.dfield, "passive", False)
        self.main_type = getattr(self.dfield, "main_type", "")
        self.sub_type = getattr(self.dfield, "sub_type", "")

        message_model = getattr(self.dfield, "message", "")
        self.message_model = self.msg_escape.sub(self.escape_fun,
                                                 message_model)

    def get_available_commands(self, caller):
        """
        This returns a list of available commands.

        Args:
            caller: (object) command's caller

        Returns:
            commands: (list) a list of available commands
        """
        if self.passive:
            return

        commands = [{
            "name": _("Cast"),
            "cmd": "castskill",
            "args": self.get_data_key()
        }]
        return commands

    def set_owner(self, owner):
        """
        Set the owner of the skill.

        Args:
            owner: (object) skill's owner

        Returns:
            None
        """
        self.db.owner = owner

        if not self.passive:
            # Set skill cd. Add gcd to new the skill.
            gcd = GAME_SETTINGS.get("global_cd")
            if gcd > 0:
                self.db.cd_finish_time = time.time() + gcd

    def cast_skill(self, target, passive):
        """
        Cast this skill.

        Args:
            target: (object) skill's target.
            passive: (boolean) cast a passive skill.

        Returns:
            (result, cd):
                result: (dict) skill's result
                cd: (dict) skill's cd
        """
        owner = self.db.owner

        message = {}
        not_available = self.check_available(passive)
        if not_available:
            message = {"cast": not_available}
        else:
            results = self.do_skill(target)

            if not passive:
                # set message
                message = {
                    "caller": owner.dbref,
                    "skill": self.get_data_key(),
                    "cast": self.cast_message(target)
                }

                if target:
                    message["target"] = target.dbref

                if results:
                    message["result"] = " ".join(results)

                # set status
                status = {}
                if owner.is_in_combat():
                    for char in owner.ndb.combat_handler.get_all_characters():
                        status[char.dbref] = char.get_combat_status()
                elif owner.location:
                    status[owner.dbref] = owner.get_combat_status()
                message["status"] = status

        if not passive and message:
            # send message
            if owner.is_in_combat():
                owner.ndb.combat_handler.msg_all({"skill_cast": message})
            elif owner.location:
                owner.location.msg_contents({"skill_cast": message})

        return True

    def do_skill(self, target):
        """
        Do this skill.
        """
        # set cd
        if not self.passive:
            # set cd
            time_now = time.time()
            if self.cd > 0:
                self.db.cd_finish_time = time_now + self.cd

        # call skill function
        return STATEMENT_HANDLER.do_skill(self.function, self.db.owner, target)

    def check_available(self, passive):
        """
        Check this skill.
        
        Args:
            passive: (boolean) cast a passive skill.

        Returns:
            message: (string) If the skill is not available, returns a string of reason.
                     If the skill is available, return "".
        """
        if not passive and self.passive:
            return _("{c%s{n is a passive skill!") % self.get_name()

        if self.is_cooling_down():
            return _("{c%s{n is not ready yet!") % self.get_name()

        return ""

    def is_available(self, passive):
        """
        If this skill is available.
        
        Args:
            passive: (boolean) cast a passive skill.

        Returns:
            (boolean) available or not.
        """
        if not passive and self.passive:
            return False

        if self.is_cooling_down():
            return False

        return True

    def is_cooling_down(self):
        """
        If this skill is cooling down.
        """
        if self.cd > 0:
            if self.db.cd_finish_time:
                if time.time() < self.db.cd_finish_time:
                    return True
        return False

    def get_remain_cd(self):
        """
        Get skill's CD.

        Returns:
            (float) Remain CD in seconds.
        """
        remain_cd = self.db.cd_finish_time - time.time()
        if remain_cd < 0:
            remain_cd = 0
        return remain_cd

    def cast_message(self, target):
        """
        Create skill's result message.
        """
        caller_name = ""
        target_name = ""
        message = ""

        if self.db.owner:
            caller_name = self.db.owner.get_name()

        if target:
            target_name = target.get_name()

        if self.message_model:
            values = {"n": self.name, "c": caller_name, "t": target_name}
            message = self.message_model % values

        return message

    def get_appearance(self, caller):
        """
        This is a convenient hook for a 'look'
        command to call.
        """
        info = super(MudderySkill, self).get_appearance(caller)

        info["passive"] = self.passive
        info["cd_remain"] = self.get_remain_cd()

        return info
Example #24
0
class MudderyBaseNPC(TYPECLASS("CHARACTER")):
    """
    The character not controlled by players.
    """
    typeclass_key = "BASE_NPC"
    typeclass_name = _("Base None Player Character", "typeclasses")
    model_name = "base_npcs"

    def at_object_creation(self):
        """
        Called once, when this object is first created. This is the
        normal hook to overload for most object types.

        """
        super(MudderyBaseNPC, self).at_object_creation()

        # NPC's shop
        if not self.attributes.has("shops"):
            self.db.shops = {}

    def after_data_loaded(self):
        """
        Init the character.
        """
        super(MudderyBaseNPC, self).after_data_loaded()

        # Character can auto fight.
        self.auto_fight = True

        # set home
        self.home = self.location

        # load dialogues.
        self.load_dialogues()

        # load shops
        self.load_shops()

    def load_dialogues(self):
        """
        Load dialogues.
        """
        dialogues = NPC_DIALOGUES.filter(self.get_data_key())

        self.default_dialogues = [
            dialogue.dialogue for dialogue in dialogues if dialogue.default
        ]
        self.dialogues = [
            dialogue.dialogue for dialogue in dialogues if not dialogue.default
        ]

    def load_shops(self):
        """
        Load character's shop.
        """
        # shops records
        shop_records = NPC_SHOPS.filter(self.get_data_key())

        shop_keys = set([record.shop for record in shop_records])

        # remove old shops
        for shop_key in self.db.shops:
            if shop_key not in shop_keys:
                # remove this shop
                self.db.shops[shop_key].delete()
                del self.db.shops[shop_key]

        # add new shop
        for shop_record in shop_records:
            shop_key = shop_record.shop
            if shop_key not in self.db.shops:
                # Create shop object.
                shop_obj = build_object(shop_key)
                if not shop_obj:
                    logger.log_errmsg("Can't create shop: %s" % shop_key)
                    continue

                self.db.shops[shop_key] = shop_obj
                shop_obj.set_owner(self)

    def get_available_commands(self, caller):
        """
        This returns a list of available commands.
        """
        commands = []
        if self.is_alive():
            if self.dialogues or self.default_dialogues:
                # If the character have something to talk, add talk command.
                commands.append({
                    "name": _("Talk"),
                    "cmd": "talk",
                    "args": self.dbref
                })

            # Add shops.
            for shop_obj in self.db.shops.values():
                if not shop_obj.is_visible(caller):
                    continue

                verb = shop_obj.verb
                if not verb:
                    verb = shop_obj.get_name()
                commands.append({
                    "name": verb,
                    "cmd": "shopping",
                    "args": shop_obj.dbref
                })

            if self.friendly <= 0:
                commands.append({
                    "name": _("Attack"),
                    "cmd": "attack",
                    "args": self.dbref
                })

        return commands

    def have_quest(self, caller):
        """
        If the npc can complete or provide quests.
        Returns (can_provide_quest, can_complete_quest).
        """
        return DIALOGUE_HANDLER.have_quest(caller, self)

    def leave_combat(self):
        """
        Leave the current combat.
        """
        status = None
        opponents = None
        if self.ndb.combat_handler:
            result = self.ndb.combat_handler.get_combat_result(self)
            if result:
                status, opponents = result

        if not self.is_temp:
            if status == defines.COMBAT_LOSE:
                self.die(opponents)

        super(MudderyBaseNPC, self).leave_combat()

        if not self.is_temp:
            if status != defines.COMBAT_LOSE:
                self.recover()
Example #25
0
class MudderyCharacter(TYPECLASS("OBJECT"), DefaultCharacter):
    """
    The Character defaults to implementing some of its hook methods with the
    following standard functionality:

    at_basetype_setup - always assigns the DefaultCmdSet to this object type
                    (important!)sets locks so character cannot be picked up
                    and its commands only be called by itself, not anyone else.
                    (to change things, use at_object_creation() instead)
    at_after_move - launches the "look" command
    at_post_puppet(player) -  when Player disconnects from the Character, we
                    store the current location, so the "unconnected" character
                    object does not need to stay on grid but can be given a
                    None-location while offline.
    at_pre_puppet - just before Player re-connects, retrieves the character's
                    old location and puts it back on the grid with a "charname
                    has connected" message echoed to the room

    """
    typeclass_key = "CHARACTER"
    typeclass_name = _("Character", "typeclasses")
    model_name = "characters"

    # initialize loot handler in a lazy fashion
    @lazy_property
    def loot_handler(self):
        return LootHandler(self,
                           CHARACTER_LOOT_LIST.filter(self.get_data_key()))

    @lazy_property
    def body_properties_handler(self):
        return DataFieldHandler(self)

    # @property body stores character's body properties before using equipments and skills.
    def __body_get(self):
        """
        A non-attr_obj store (ndb: NonDataBase). Everything stored
        to this is guaranteed to be cleared when a server is shutdown.
        Syntax is same as for the _get_db_holder() method and
        property, e.g. obj.ndb.attr = value etc.
        """
        try:
            return self._body_holder
        except AttributeError:
            self._body_holder = DbHolder(
                self,
                "body_properties",
                manager_name='body_properties_handler')
            return self._body_holder

    # @body.setter
    def __body_set(self, value):
        "Stop accidentally replacing the ndb object"
        string = "Cannot assign directly to ndb object! "
        string += "Use self.body.name=value instead."
        raise Exception(string)

    # @body.deleter
    def __body_del(self):
        "Stop accidental deletion."
        raise Exception("Cannot delete the body object!")

    body = property(__body_get, __body_set, __body_del)

    def at_object_creation(self):
        """
        Called once, when this object is first created. This is the
        normal hook to overload for most object types.
            
        """
        super(MudderyCharacter, self).at_object_creation()

        # set default values
        if not self.attributes.has("team"):
            self.db.team = 0

        # init equipments
        if not self.attributes.has("equipments"):
            self.db.equipments = {}
        if not self.attributes.has("position_names"):
            self.db.position_names = {}
        self.reset_equip_positions()

        if not self.attributes.has("skills"):
            self.db.skills = {}

        # set quests
        if not self.attributes.has("finished_quests"):
            self.db.finished_quests = set()
        if not self.attributes.has("current_quests"):
            self.db.current_quests = {}

        # set closed events
        if not self.attributes.has("closed_events"):
            self.db.closed_events = set()

        # skill's gcd
        self.skill_gcd = GAME_SETTINGS.get("global_cd")
        self.auto_cast_skill_cd = GAME_SETTINGS.get("auto_cast_skill_cd")
        self.gcd_finish_time = 0

        # loop for auto cast skills
        self.auto_cast_loop = None

        self.target = None
        self.reborn_time = 0

        # A temporary character will be deleted after the combat finished.
        self.is_temp = False

    def at_object_delete(self):
        """
        Called just before the database object is permanently
        delete()d from the database. If this method returns False,
        deletion is aborted.

        All skills, contents will be removed too.
        """
        result = super(MudderyCharacter, self).at_object_delete()
        if not result:
            return result

        # leave combat
        if self.ndb.combat_handler:
            self.ndb.combat_handler.remove_character(self)

        # stop auto casting
        self.stop_auto_combat_skill()

        # delete all skills
        for skill in self.db.skills.values():
            skill.delete()

        # delete all contents
        for content in self.contents:
            content.delete()

        return True

    def load_custom_properties(self, level):
        """
        Load body properties from db. Body properties do no include mutable properties.
        """
        # Get object level.
        if level is None:
            level = self.db.level

        # Load values from db.
        values = {}
        for record in OBJECT_PROPERTIES.get_properties(self.get_data_key(),
                                                       level):
            key = record.property
            serializable_value = record.value
            if serializable_value == "":
                value = None
            else:
                try:
                    value = ast.literal_eval(serializable_value)
                except (SyntaxError, ValueError) as e:
                    # treat as a raw string
                    value = serializable_value
            values[key] = value

        # Set body values.
        for key, info in self.get_properties_info().items():
            if not info["mutable"]:
                self.custom_properties_handler.add(key, values.get(key, None))
                self.body_properties_handler.add(key, values.get(key, None))

        # Set default mutable custom properties.
        self.set_default_custom_properties()

    def set_default_custom_properties(self):
        """
        Set default mutable custom properties.
        """
        for key, info in self.get_properties_info().items():
            if info["mutable"]:
                # Set default mutable properties to prop.
                if not self.custom_properties_handler.has(key):
                    self.custom_properties_handler.add(key, "")

    def after_data_loaded(self):
        """
        Init the character.
        """
        super(MudderyCharacter, self).after_data_loaded()

        # get level
        if not self.db.level:
            self.db.level = getattr(self.system, "level", 1)

        # friendly
        self.friendly = getattr(self.system, "friendly", 0)

        # skill's ai
        ai_choose_skill_class = class_from_module(settings.AI_CHOOSE_SKILL)
        self.ai_choose_skill = ai_choose_skill_class()

        # skill's gcd
        self.skill_gcd = GAME_SETTINGS.get("global_cd")
        self.auto_cast_skill_cd = GAME_SETTINGS.get("auto_cast_skill_cd")
        self.gcd_finish_time = 0

        # loop for auto cast skills
        self.auto_cast_loop = None

        # clear target
        self.target = None

        # set reborn time
        self.reborn_time = getattr(self.system, "reborn_time", 0)

        # A temporary character will be deleted after the combat finished.
        self.is_temp = False

        # update equipment positions
        self.reset_equip_positions()

        # load default skills
        self.load_default_skills()

        # load default objects
        self.load_default_objects()

        # refresh the character's properties.
        self.refresh_properties()

    def set_level(self, level):
        """
        Set object's level.
        Args:
            level: object's new level

        Returns:
            None
        """
        super(MudderyCharacter, self).set_level(level)
        self.refresh_properties()

    def reset_equip_positions(self):
        """
        Reset equipment's position data.
        Returns:
            None
        """
        positions = []
        self.db.position_names = {}

        # reset equipment's position
        for record in CM.EQUIPMENT_POSITIONS.all():
            positions.append(record.key)
            self.db.position_names[record.key] = record.name

        for position in self.db.equipments:
            if position not in positions:
                del self.db.equipments[position]

        for position in positions:
            if position not in self.db.equipments:
                self.db.equipments[position] = None

        # reset equipments status
        equipped = set()
        equipments = self.db.equipments
        for position in equipments:
            if equipments[position]:
                equipped.add(equipments[position])

        for content in self.contents:
            if content.dbref in equipped:
                content.equipped = True

    def refresh_properties(self):
        """
        Refresh character's final properties.
        """
        # Load body properties.
        for key, value in self.body_properties_handler.all(True):
            self.custom_properties_handler.add(key, value)

        # load equips
        self.wear_equipments()

        # load passive skills
        self.cast_passive_skills()

    @classmethod
    def get_event_trigger_types(cls):
        """
        Get an object's available event triggers.
        """
        return [defines.EVENT_TRIGGER_KILL, defines.EVENT_TRIGGER_DIE]

    def close_event(self, event_key):
        """
        If an event is closed, it will never be triggered.

        Args:
            event_key: (string) event's key
        """
        self.db.closed_events.add(event_key)

    def is_event_closed(self, event_key):
        """
        Return True If this event is closed.

        Args:
            event_key: (string) event's key
        """
        return event_key in self.db.closed_events

    def change_properties(self, increments):
        """
        Change values of specified properties.
        
        Args:
            increments: (dict) values to change.
            
        Return:
            (dict) values that actually changed.
        """
        changes = {}
        properties_info = self.get_properties_info()

        for key, increment in increments.items():
            changes[key] = 0

            if not self.custom_properties_handler.has(key):
                continue

            origin_value = getattr(self.prop, key)

            # check limits
            max_key = "max_" + key
            if self.custom_properties_handler.has(max_key):
                max_value = getattr(self.prop, max_key)
                if origin_value + increment > max_value:
                    increment = max_value - origin_value

            # Default minimum value is 0.
            min_value = 0
            min_key = "min_" + key
            if self.custom_properties_handler.has(min_key):
                min_value = getattr(self.prop, min_key)

            if origin_value + increment < min_value:
                increment = min_value - origin_value

            # Set the value.
            if increment != 0:
                value = origin_value + increment
                self.custom_properties_handler.add(key, value)
                changes[key] = increment

        return changes

    def set_properties(self, values):
        """
        Set values of specified properties.

        Args:
            values: (dict) values to set.

        Return:
            (dict) values that actually set.
        """
        actual = {}
        properties_info = self.get_properties_info()

        for key, value in values.items():
            actual[key] = 0

            if not self.custom_properties_handler.has(key):
                continue

            # check limits
            max_key = "max_" + key
            if self.custom_properties_handler.has(max_key):
                max_value = getattr(self.prop, max_key)
                if value > max_value:
                    value = max_value

            # Default minimum value is 0.
            min_key = "min_" + key
            if self.custom_properties_handler.has(min_key):
                min_value = getattr(self.prop, min_key)
                if value < min_value:
                    value = min_value

            # Set the value.
            setattr(self.prop, key, value)
            actual[key] = value

        return actual

    def get_combat_status(self):
        """
        Get character status used in combats.
        """
        return {}

    def search_inventory(self, obj_key):
        """
        Search specified object in the inventory.
        """
        result = [
            item for item in self.contents if item.get_data_key() == obj_key
        ]
        return result

    def set_equips(self):
        """
        Load equipments data.
        """
        # set equipments status
        equipped = set()
        equipments = self.db.equipments
        for position in equipments:
            if equipments[position]:
                equipped.add(equipments[position])

        for content in self.contents:
            if content.dbref in equipped:
                content.equipped = True

        # set character's attributes
        self.refresh_properties()

    def wear_equipments(self):
        """
        Add equipment's attributes to the character
        """
        # find equipments
        equipped = set(
            [equip_id for equip_id in self.db.equipments.values() if equip_id])

        # add equipment's attributes
        for content in self.contents:
            if content.dbref in equipped:
                content.equip_to(self)

    def load_default_skills(self):
        """
        Load character's default skills.
        """
        # default skills
        skill_records = DEFAULT_SKILLS.filter(self.get_data_key())
        default_skill_ids = set([record.skill for record in skill_records])

        # remove old default skills
        for key, skill in self.db.skills.items():
            if not skill:
                del self.db.skills[key]
            elif skill.is_default() and key not in default_skill_ids:
                # remove this skill
                skill.delete()
                del self.db.skills[key]

        # add new default skills
        for skill_record in skill_records:
            if skill_record.skill not in self.db.skills:
                self.learn_skill(skill_record.skill, True, True)

    def load_default_objects(self):
        """
        Load character's default objects.
        """
        pass

    def at_after_move(self, source_location, **kwargs):
        """
        Called after move has completed, regardless of quiet mode or
        not.  Allows changes to the object due to the location it is
        now in.

        Args:
            source_location : (Object) Where we came from. This may be `None`.

        """
        pass

    ########################################
    #
    # Skill methods.
    #
    ########################################

    def learn_skill(self, skill_key, is_default, silent):
        """
        Learn a new skill.

        Args:
            skill_key: (string) skill's key
            is_default: (boolean) if it is a default skill
            silent: (boolean) do not show messages to the player

        Returns:
            (boolean) learned skill
        """
        if skill_key in self.db.skills:
            self.msg({"msg": _("You have already learned this skill.")})
            return False

        # Create skill object.
        skill_obj = build_object(skill_key)
        if not skill_obj:
            self.msg({"msg": _("Can not learn this skill.")})
            return False

        # set default
        if is_default:
            skill_obj.set_default(is_default)

        # Store new skill.
        skill_obj.set_owner(self)
        self.db.skills[skill_key] = skill_obj

        # If it is a passive skill, player's status may change.
        if skill_obj.passive:
            self.refresh_properties()

        # Notify the player
        if not silent and self.has_account:
            self.show_status()
            self.show_skills()
            self.msg(
                {"msg": _("You learned skill {c%s{n.") % skill_obj.get_name()})

        return True

    def cast_skill(self, skill_key, target):
        """
        Cast a skill.

        Args:
            skill_key: (string) skill's key.
            target: (object) skill's target.
        """
        time_now = time.time()
        if time_now < self.gcd_finish_time:
            # In GCD.
            self.msg({"skill_cast": {"cast": _("Global cooling down!")}})
            return

        if skill_key not in self.db.skills:
            self.msg(
                {"skill_cast": {
                    "cast": _("You do not have this skill.")
                }})
            return

        skill = self.db.skills[skill_key]
        if not skill.cast_skill(target, passive=False):
            return

        if self.skill_gcd > 0:
            # set GCD
            self.gcd_finish_time = time_now + self.skill_gcd

        # send CD to the player
        cd = {
            "skill": skill_key,  # skill's key
            "cd": skill.cd,  # skill's cd
            "gcd": self.skill_gcd
        }

        self.msg({"skill_cd": cd})
        return

    def auto_cast_skill(self):
        """
        Cast a new skill automatically.
        """
        if not self.is_alive():
            return

        if not self.is_in_combat():
            # combat is finished, stop ticker
            self.stop_auto_combat_skill()
            return

        # Choose a skill and the skill's target.
        result = self.ai_choose_skill.choose(self)
        if result:
            skill, target = result
            self.ndb.combat_handler.prepare_skill(skill, self, target)

    def cast_passive_skills(self):
        """
        Cast all passive skills.
        """
        for skill in self.db.skills.values():
            if skill.passive:
                skill.cast_skill(self, passive=True)

    def start_auto_combat_skill(self):
        """
        Start auto cast skill.
        """
        if self.auto_cast_loop and self.auto_cast_loop.running:
            return

        # Cast a skill immediately
        # self.auto_cast_skill()

        # Set timer of auto cast.
        self.auto_cast_loop = task.LoopingCall(self.auto_cast_skill)
        self.auto_cast_loop.start(self.auto_cast_skill_cd)

    def stop_auto_combat_skill(self):
        """
        Stop auto cast skill.
        """
        if hasattr(self, "auto_cast_loop"
                   ) and self.auto_cast_loop and self.auto_cast_loop.running:
            self.auto_cast_loop.stop()

    ########################################
    #
    # Attack a target.
    #
    ########################################
    def set_target(self, target):
        """
        Set character's target.

        Args:
            target: (object) character's target

        Returns:
            None
        """
        self.target = target

    def clear_target(self):
        """
        Clear character's target.
        """
        self.target = None

    def attack_target(self, target, desc=""):
        """
        Attack a target.

        Args:
            target: (object) the target object.
            desc: (string) string to describe this attack

        Returns:
            (boolean) attack begins
        """
        if self.is_in_combat():
            # already in battle
            logger.log_errmsg("%s is already in battle." % self.dbref)
            return False

        # search target
        if not target:
            logger.log_errmsg("Can not find the target.")
            return False

        if not target.is_typeclass(TYPECLASS(
                settings.GENERAL_CHARACTER_TYPECLASS_KEY),
                                   exact=False):
            # Target is not a character.
            logger.log_errmsg("Can not attack the target %s." % target.dbref)
            return False

        if target.is_in_combat():
            # obj is already in battle
            logger.log_errmsg("%s is already in battle." % target.dbref)
            return False

        # create a new combat handler
        chandler = create_script(settings.NORMAL_COMBAT_HANDLER)

        # set combat team and desc
        chandler.set_combat({1: [target], 2: [self]}, desc, 0)

        return True

    def attack_current_target(self, desc=""):
        """
        Attack current target.

        Args:
            desc: (string) string to describe this attack

        Returns:
            None
        """
        self.attack_target(self.target, desc)

    def attack_target_dbref(self, target_dbref, desc=""):
        """
        Attack a target by dbref.

        Args:
            target_dbref: (string) the dbref of the target.
            desc: (string) string to describe this attack

        Returns:
            None
        """
        target = self.search_dbref(target_dbref)
        self.attack_target(target, desc)

    def attack_temp_current_target(self, desc=""):
        """
        Attack current target's temporary clone object.

        Args:
            desc: (string) string to describe this attack

        Returns:
            None
        """
        self.attack_temp_target(self.target.get_data_key(),
                                self.target.db.level, desc)

    def attack_temp_target(self, target_key, target_level=0, desc=""):
        """
        Attack a temporary clone of a target. This creates a new character object for attack.
        The origin target will not be affected.

        Args:
            target_key: (string) the info key of the target object.
            target_level: (int) target object's level
            desc: (string) string to describe this attack

        Returns:
            (boolean) fight begins
        """
        if target_level == 0:
            # Find the target and get its level.
            obj = search_obj_data_key(target_key)
            if obj:
                obj = obj[0]
                target_level = obj.db.level

        # Create a target.
        target = build_object(target_key, target_level, reset_location=False)
        if not target:
            logger.log_errmsg("Can not create the target %s." % target_key)
            return False

        target.is_temp = True
        return self.attack_target(target, desc)

    def is_in_combat(self):
        """
        Check if the character is in combat.

        Returns:
            (boolean) is in combat or not
        """
        return bool(self.ndb.combat_handler)

    def set_team(self, team_id):
        """
        Set character's team id in combat.

        Args:
            team_id: team's id

        Returns:
            None
        """
        self.db.team = team_id

    def get_team(self):
        """
        Get character's team id in combat.

        Returns:
            team id
        """
        return self.db.team

    def is_alive(self):
        """
        Check if the character is alive.

        Returns:
            (boolean) the character is alive or not
        """
        return True

    def die(self, killers):
        """
        This character die.

        Args:
            killers: (list of objects) characters who kill this

        Returns:
            None
        """
        # trigger event
        self.event.at_character_die()
        self.event.at_character_kill(killers)

        if not self.is_temp and self.reborn_time > 0:
            # Set reborn timer.
            self.defer = deferLater(reactor, self.reborn_time, self.reborn)

    def reborn(self):
        """
        Reborn after being killed.
        """
        # Reborn at its home.
        if self.home:
            self.move_to(self.home, quiet=True)

    def get_combat_commands(self):
        """
        This returns a list of combat commands.

        Returns:
            (list) available commands for combat
        """
        commands = []
        for key, skill in self.db.skills.items():
            if skill.passive:
                # exclude passive skills
                continue

            command = {
                "name": skill.get_name(),
                "key": key,
                "icon": getattr(skill, "icon", None)
            }

            commands.append(command)

        return commands

    def provide_exp(self, killer):
        """
        Calculate the exp provide to the killer.
        Args:
            killer: (object) the character who kills it.

        Returns:
            (int) experience give to the killer
        """
        return 0

    def add_exp(self, exp):
        """
        Add character's exp.
        Args:
            exp: the exp value to add.

        Returns:
            None
        """
        pass

    def level_up(self):
        """
        Upgrade level.

        Returns:
            None
        """
        self.set_level(self.db.level + 1)

    def show_status(self):
        """
        Show character's status.
        """
        pass
Example #26
0
class MudderyShopGoods(TYPECLASS("OBJECT")):
    """
    This is a shop goods. Shops show these objects to players. It contains a common object
    to sell and additional shop information.
    """
    typeclass_key = "SHOP_GOODS"
    typeclass_name = _("Goods", "typeclasses")

    def at_object_creation(self):
        """
        Called once, when this object is first created. This is the
        normal hook to overload for most object types.

        """
        super(MudderyShopGoods, self).at_object_creation()

        # Set default values.
        if not self.attributes.has("goods"):
            self.db.goods = None

        self.available = False

    def after_data_loaded(self):
        """
        Load goods data.

        Returns:
            None
        """
        self.available = False

        self.shop_key = getattr(self.dfield, "shop", "")
        self.goods_key = getattr(self.dfield, "goods", "")

        if not self.shop_key or not self.goods_key:
            if self.db.goods:
                self.db.goods.delete()
                self.db.goods = None
            return

        # set goods information
        self.price = getattr(self.dfield, "price", 0)
        self.unit_key = getattr(self.dfield, "unit", "")
        self.number = getattr(self.dfield, "number", 0)
        self.condition = getattr(self.dfield, "condition", "")

        # get price unit information
        unit_record = get_object_record(self.unit_key)
        if not unit_record:
            logger.log_errmsg("Can not find %s price unit %s." %
                              (self.goods_key, self.unit_key))
            return
        self.unit_name = unit_record.name

        # load goods object
        goods = self.db.goods
        if goods:
            if goods.get_data_key() == self.goods_key:
                goods.load_data()
            else:
                goods.set_data_key(self.goods_key)
        else:
            goods = build_object(self.goods_key)
            if goods:
                self.db.goods = goods
            else:
                logger.log_err("Can not create goods %s." % self.goods_key)
                return

        self.name = goods.get_name()
        self.desc = goods.db.desc
        self.icon = getattr(goods, "icon", None)

        self.available = True

    def sell_to(self, caller):
        """
        Buy this goods.

        Args:
            caller: the buyer

        Returns:

        """
        # check price
        unit_number = caller.get_object_number(self.unit_key)
        if unit_number < self.price:
            caller.msg(
                {"alert": _("Sorry, %s is not enough.") % self.unit_name})
            return

        # check if can get these objects
        if not caller.can_get_object(self.db.goods.get_data_key(),
                                     self.number):
            caller.msg({
                "alert":
                _("Sorry, you can not take more %s.") %
                self.db.goods.get_name()
            })
            return

        # Reduce price units.
        if not caller.remove_object(self.unit_key, self.price):
            caller.msg(
                {"alert": _("Sorry, %s is not enough.") % self.unit_name})
            return

        # Give goods.
        obj_list = [{
            "object": self.db.goods.get_data_key(),
            "number": self.number
        }]
        caller.receive_objects(obj_list)
Example #27
0
class MudderyNPC(TYPECLASS("NON_PLAYER")):
    """
    Neutral or friendly NPC. They can not be attacked.
    """
    typeclass_key = "NPC"

    def at_object_creation(self):
        """
        Called once, when this object is first created. This is the
        normal hook to overload for most object types.
            
        """
        super(MudderyNPC, self).at_object_creation()

        # NPC's shop
        if not self.attributes.has("shops"):
            self.db.shops = {}

    def after_data_loaded(self):
        """
        Init the character.
        """
        super(MudderyNPC, self).after_data_loaded()

        # set level
        self.db.level = getattr(self.dfield, "level", 1)

        # Character can auto fight.
        self.auto_fight = True

        # set home
        self.home = self.location

        # load dialogues.
        self.load_dialogues()

        # load shops
        self.load_shops()

    def load_dialogues(self):
        """
        Load dialogues.
        """
        dialogues = NPC_DIALOGUES.filter(self.get_data_key())

        self.default_dialogues = [
            dialogue.dialogue for dialogue in dialogues if dialogue.default
        ]
        self.dialogues = [
            dialogue.dialogue for dialogue in dialogues if not dialogue.default
        ]

    def load_shops(self):
        """
        Load character's shop.
        """
        # shops records
        shop_records = NPC_SHOPS.filter(self.get_data_key())

        shop_keys = set([record.shop for record in shop_records])

        # remove old shops
        for shop_key in self.db.shops:
            if shop_key not in shop_keys:
                # remove this shop
                self.db.shops[shop_key].delete()
                del self.db.shops[shop_key]

        # add new shop
        for shop_record in shop_records:
            shop_key = shop_record.shop
            if shop_key not in self.db.shops:
                # Create shop object.
                shop_obj = build_object(shop_key)
                if not shop_obj:
                    logger.log_errmsg("Can't create shop: %s" % shop_key)
                    continue

                self.db.shops[shop_key] = shop_obj

    def get_available_commands(self, caller):
        """
        This returns a list of available commands.
        """
        commands = []
        if self.dialogues or self.default_dialogues:
            # If the character have something to talk, add talk command.
            commands.append({
                "name": _("Talk"),
                "cmd": "talk",
                "args": self.dbref
            })

        # Add shops.
        for shop_obj in self.db.shops.values():
            if not shop_obj.is_visible(caller):
                continue

            verb = shop_obj.verb
            if not verb:
                verb = shop_obj.get_name()
            commands.append({
                "name": verb,
                "cmd": "shopping",
                "args": shop_obj.dbref
            })

        return commands

    def have_quest(self, caller):
        """
        If the npc can complete or provide quests.
        Returns (can_provide_quest, can_complete_quest).
        """
        return DIALOGUE_HANDLER.have_quest(caller, self)
Example #28
0
class MudderyWorldObject(TYPECLASS("OBJECT")):
    typeclass_key = "WORLD_OBJECT"
    typeclass_name = _("World Object", "typeclasses")
    model_name = "world_objects"
Example #29
0
class MudderyPlayerCharacter(TYPECLASS("CHARACTER")):
    """
    The Character defaults to implementing some of its hook methods with the
    following standard functionality:

    at_basetype_setup - always assigns the DefaultCmdSet to this object type
                    (important!)sets locks so character cannot be picked up
                    and its commands only be called by itself, not anyone else.
                    (to change things, use at_object_creation() instead)
    at_after_move - launches the "look" command
    at_post_puppet(player) -  when Player disconnects from the Character, we
                    store the current location, so the "unconnected" character
                    object does not need to stay on grid but can be given a
                    None-location while offline.
    at_pre_puppet - just before Player re-connects, retrieves the character's
                    old location and puts it back on the grid with a "charname
                    has connected" message echoed to the room

    """
    typeclass_key = "PLAYER_CHARACTER"

    # initialize all handlers in a lazy fashion
    @lazy_property
    def quest_handler(self):
        return QuestHandler(self)

    # attributes used in statements
    @lazy_property
    def statement_attr(self):
        return StatementAttributeHandler(self)

    def at_object_creation(self):
        """
        Called once, when this object is first created. This is the
        normal hook to overload for most object types.
            
        """
        super(MudderyPlayerCharacter, self).at_object_creation()
        
        # honour
        if not HONOURS_MAPPER.has_info(self):
            if self.db.level >= settings.MIN_HONOUR_LEVEL:
                HONOURS_MAPPER.set_honour(self, 0)
            else:
                HONOURS_MAPPER.set_honour(self, -1)

        # Set default data.
        if not self.attributes.has("nickname"):
            self.db.nickname = ""
        if not self.attributes.has("unlocked_exits"):
            self.db.unlocked_exits = set()
        if not self.attributes.has("revealed_map"):
            self.db.revealed_map = set()

        # set custom attributes
        if not self.attributes.has("attributes"):
            self.db.attributes = {}

        """
        # Choose a random career.
        if not self.attributes.has("career"):
            self.db.career = ""
            try:
                careers = DATA_SETS.character_careers.objects.all()
                if careers:
                    career = random.choice(careers)
                    self.db.career = career.key
            except Exception, e:
                pass
        """
        
    def after_data_loaded(self):
        """
        """
        super(MudderyPlayerCharacter, self).after_data_loaded()

        self.solo_mode = GAME_SETTINGS.get("solo_mode")
        self.available_channels = {}

        # refresh data
        self.refresh_data()

    def move_to(self, destination, quiet=False,
                emit_to_obj=None, use_destination=True, to_none=False, move_hooks=True, **kwargs):
        """
        Moves this object to a new location.
        """
        if not quiet and self.solo_mode:
            # If in solo mode, move quietly.
            quiet = True

        return super(MudderyPlayerCharacter, self).move_to(destination,
                                                           quiet,
                                                           emit_to_obj,
                                                           use_destination,
                                                           to_none,
                                                           move_hooks)

    def at_object_receive(self, moved_obj, source_location, **kwargs):
        """
        Called after an object has been moved into this object.
        
        Args:
        moved_obj (Object): The object moved into this one
        source_location (Object): Where `moved_object` came from.
        
        """
        super(MudderyPlayerCharacter, self).at_object_receive(moved_obj, source_location)

        # send latest inventory data to player
        self.msg({"inventory": self.return_inventory()})
    
    def at_object_left(self, moved_obj, target_location):
        """
        Called after an object has been removed from this object.
        
        Args:
        moved_obj (Object): The object leaving
        target_location (Object): Where `moved_obj` is going.
        
        """
        super(MudderyPlayerCharacter, self).at_object_left(moved_obj, target_location)
        
        # send latest inventory data to player
        self.msg({"inventory": self.return_inventory()})

    def at_after_move(self, source_location):
        """
        We make sure to look around after a move.

        """
        self.msg({"msg": _("Moving to %s ...") % self.location.name})
        self.show_location()

    def at_post_puppet(self):
        """
        Called just after puppeting has been completed and all
        Player<->Object links have been established.

        """
        self.available_channels = self.get_available_channels()
        
        # Send puppet info to the client first.
        self.msg({"puppet": {"dbref": self.dbref,
                             "name": self.get_name(),
                             "icon": getattr(self, "icon", None)}})

        # send character's data to player
        message = {"status": self.return_status(),
                   "equipments": self.return_equipments(),
                   "inventory": self.return_inventory(),
                   "skills": self.return_skills(),
                   "quests": self.quest_handler.return_quests(),
                   "revealed_map": self.get_revealed_map(),
                   "channels": self.available_channels}
        self.msg(message)

        self.show_location()

        # notify its location
        if not self.solo_mode:
            if self.location:
                change = {"dbref": self.dbref,
                          "name": self.get_name()}
                self.location.msg_contents({"player_online": change}, exclude=[self])

        self.resume_last_dialogue()

        self.resume_combat()

    def at_pre_unpuppet(self):
        """
        Called just before beginning to un-connect a puppeting from
        this Player.
        
        """
        if not self.solo_mode:
            # notify its location
            if self.location:
                change = {"dbref": self.dbref,
                          "name": self.get_name()}
                self.location.msg_contents({"player_offline":change}, exclude=self)

        MATCH_QUEUE_HANDLER.remove(self)

    def set_nickname(self, nickname):
        """
        Set player character's nickname.
        """
        self.db.nickname = nickname

    def get_name(self):
        """
        Get player character's name.
        """
        # Use nick name instead of normal name.
        return self.db.nickname

    def get_available_commands(self, caller):
        """
        This returns a list of available commands.
        """
        commands = []
        if self.is_alive():
            commands.append({"name": _("Attack"), "cmd": "attack", "args": self.dbref})
        return commands

    def get_available_channels(self):
        """
        Get available channel's info.

        Returns:
            (dict) channels
        """
        channels = {"": _("Say", category="channels"),
                    "Public": _("Public", category="channels")}

        commands = False
        if self.account:
            if self.is_superuser:
                commands = True
            else:
                for perm in self.account.permissions.all():
                    if perm in settings.PERMISSION_COMMANDS:
                        commands = True
                        break
        if commands:
            channels["cmd"] = _("Cmd")

        return channels

    def get_revealed_map(self):
        """
        Get the map that the character has revealed.
        Return value:
            {
                "rooms": {room1's key: {"name": name,
                                        "icon": icon,
                                        "area": area,
                                        "pos": position},
                          room2's key: {"name": name,
                                        "icon": icon,
                                        "area": area,
                                        "pos": position},
                          ...},
                "exits": {exit1's key: {"from": room1's key,
                                        "to": room2's key},
                          exit2's key: {"from": room3's key,
                                        "to": room4's key},
                          ...}
            }
        """
        rooms = {}
        exits = {}

        for room_key in self.db.revealed_map:
            # get room's information
            room = utils.search_obj_data_key(room_key)
            if room:
                room = room[0]
                rooms[room_key] = {"name": room.get_name(),
                                   "icon": room.icon,
                                   "area": room.location and room.location.get_data_key(),
                                   "pos": room.position}

                new_exits = room.get_exits()
                if new_exits:
                    exits.update(new_exits)

        for path in exits.values():
            # add room's neighbours
            if not path["to"] in rooms:
                neighbour = utils.search_obj_data_key(path["to"])
                if neighbour:
                    neighbour = neighbour[0]                    
                    rooms[neighbour.get_data_key()] = {"name": neighbour.get_name(),
                                                       "icon": neighbour.icon,
                                                       "area": neighbour.location and neighbour.location.get_data_key(),
                                                       "pos": neighbour.position}
                    
        return {"rooms": rooms, "exits": exits}

    def show_location(self):
        """
        show character's location
        """
        if self.location:
            location_key = self.location.get_data_key()
            area = self.location.location and self.location.location.get_appearance(self)

            msg = {"current_location": {"key": location_key,
                                        "area": area}}

            """
            reveal_map:
            {
                "rooms": {room1's key: {"name": name,
                                        "icon": icon,
                                        "area": area,
                                        "pos": position},
                          room2's key: {"name": name,
                                        "icon": icon,
                                        "area": area,
                                        "pos": position},
                          ...},
                "exits": {exit1's key: {"from": room1's key,
                                        "to": room2's key},
                          exit2's key: {"from": room3's key,
                                        "to": room4's key},
                          ...}
            }
            """
            reveal_map = None
            if not location_key in self.db.revealed_map:
                # reveal map
                self.db.revealed_map.add(self.location.get_data_key())

                rooms = {location_key: {"name": self.location.get_name(),
                                        "icon": self.location.icon,
                                        "area": self.location.location and self.location.location.get_data_key(),
                                        "pos": self.location.position}}

                exits = self.location.get_exits()

                for path in exits.values():
                    # add room's neighbours
                    if not path["to"] in rooms:
                        neighbour = utils.search_obj_data_key(path["to"])
                        if neighbour:
                            neighbour = neighbour[0]

                            rooms[neighbour.get_data_key()] = {"name": neighbour.get_name(),
                                                               "icon": neighbour.icon,
                                                               "area": neighbour.location and neighbour.location.get_data_key(),
                                                               "pos": neighbour.position}
                    
                msg["reveal_map"] = {"rooms": rooms, "exits": exits}

            # get appearance
            appearance = self.location.get_appearance(self)
            appearance.update(self.location.get_surroundings(self))
            msg["look_around"] = appearance

            self.msg(msg)

    def load_default_objects(self):
        """
        Load character's default objects.
        """
        # get character's model name
        model_name = getattr(self.dfield, "model", None)
        if not model_name:
            model_name = self.get_data_key()
        
        # default objects
        object_records = DEFAULT_OBJECTS.filter(model_name)

        default_object_ids = set([record.object for record in object_records])

        # add new default objects
        for object_record in object_records:
            if not self.search_inventory(object_record.object):
                obj_list = [{"object": object_record.object, "number": object_record.number}]
                self.receive_objects(obj_list, mute=True)

    def receive_objects(self, obj_list, mute=False, combat=False):
        """
        Add objects to the inventory.

        Args:
            obj_list: (list) a list of object keys and there numbers.
                             list item: {"object": object's key
                                         "number": object's number}
            mute: (boolean) do not send messages to the owner
            combat: (boolean) get objects in combat.

        Returns:
            (dict) a list of objects that not have been received and their reasons.
        """
        accepted_keys = {}      # the keys of objects that have been accepted
        accepted_names = {}     # the names of objects that have been accepted
        rejected_keys = {}      # the keys of objects that have been rejected
        reject_reason = {}      # the reasons of why objects have been rejected

        # check what the character has now
        inventory = {}
        for item in self.contents:
            key = item.get_data_key()
            if key in inventory:
                # if the character has more than one item of the same kind,
                # get the smallest stack.
                if inventory[key].db.number > item.db.number:
                    inventory[key] = item
            else:
                inventory[key] = item

        for obj in obj_list:
            key = obj["object"]
            available = obj["number"]
            number = available
            accepted = 0
            name = ""
            unique = False

            if number == 0:
                # it is an empty object
                if key in inventory:
                    # already has this object
                    accepted_keys[key] = 0
                    accepted_names[name] = 0
                    continue

                object_record = get_object_record(key)
                if not object_record:
                    # can not find object's data record
                    reason = _("Can not get %s.") % name
                    rejected_keys[key] = 0
                    reject_reason[name] = reason
                    continue

                if object_record.can_remove:
                    # remove this empty object
                    accepted_keys[key] = 0
                    accepted_names[name] = 0
                    continue

                # create a new content
                new_obj = build_object(key)
                if not new_obj:
                    reason = _("Can not get %s.") % name
                    rejected_keys[key] = 0
                    reject_reason[name] = reason
                    continue

                name = new_obj.get_name()

                # move the new object to the character
                if not new_obj.move_to(self, quiet=True, emit_to_obj=self):
                    new_obj.delete()
                    reason = _("Can not get %s.") % name
                    rejected_keys[key] = 0
                    reject_reason[name] = reason
                    break

                # accept this object
                accepted_keys[key] = 0
                accepted_names[name] = 0

            else:
                # common number
                # if already has this kind of object
                if key in inventory:
                    # add to current object
                    name = inventory[key].name
                    unique = inventory[key].unique

                    add = number
                    if add > inventory[key].max_stack - inventory[key].db.number:
                        add = inventory[key].max_stack - inventory[key].db.number

                    if add > 0:
                        # increase stack number
                        inventory[key].increase_num(add)
                        number -= add
                        accepted += add

                # if does not have this kind of object, or stack is full
                reason = ""
                while number > 0:
                    if unique:
                        # can not have more than one unique objects
                        reason = _("Can not get more %s.") % name
                        break

                    # create a new content
                    new_obj = build_object(key)
                    if not new_obj:
                        reason = _("Can not get %s.") % name
                        break

                    name = new_obj.get_name()
                    unique = new_obj.unique

                    # move the new object to the character
                    if not new_obj.move_to(self, quiet=True, emit_to_obj=self):
                        new_obj.delete()
                        reason = _("Can not get %s.") % name
                        break

                    # Get the number that actually added.
                    add = number
                    if add > new_obj.max_stack:
                        add = new_obj.max_stack

                    if add <= 0:
                        break

                    new_obj.increase_num(add)
                    number -= add
                    accepted += add

                if accepted > 0:
                    accepted_keys[key] = accepted
                    accepted_names[name] = accepted

                if accepted < available:
                    rejected_keys[key] = available - accepted
                    reject_reason[name] = reason

        if not mute:
            # Send results to the player.
            message = {"get_objects":
                            {"accepted": accepted_names,
                             "rejected": reject_reason,
                             "combat": combat}}
            self.msg(message)
            self.show_inventory()

            # call quest handler
            for key in accepted_keys:
                self.quest_handler.at_objective(defines.OBJECTIVE_OBJECT, key, accepted_keys[key])

        return rejected_keys

    def get_object_number(self, obj_key):
        """
        Get the number of this object.
        Args:
            obj_key: (String) object's key

        Returns:
            int: object number
        """
        objects = self.search_inventory(obj_key)

        # get total number
        sum = 0
        for obj in objects:
            obj_num = obj.get_number()
            sum += obj_num

        return sum

    def can_get_object(self, obj_key, number):
        """
        Check if the character can get these objects.

        Args:
            obj_key: (String) object's key
            number: (int) object's number

        Returns:
            boolean: can get

        Notice:
            If the character does not have this object, the return will be always true,
            despite of the number!
        """
        objects = self.search_inventory(obj_key)

        if not objects:
            return True

        obj = objects[0]
        if not obj.unique:
            return True

        if obj.get_number() + number <= obj.max_stack:
            return True

        return False

    def use_object(self, obj, number=1):
        """
        Use an object.

        Args:
            obj: (object) object to use
            number: (int) number to use

        Returns:
            result: (string) the description of the result
        """
        if not obj:
            return _("Can not find this object.")

        if obj.db.number < number:
            return _("Not enough number.")

        # take effect
        try:
            result, used = obj.take_effect(self, number)
            if used > 0:
                # remove used object
                self.remove_object(obj.get_data_key(), used)
            return result
        except Exception, e:
            ostring = "Can not use %s: %s" % (obj.get_data_key(), e)
            logger.log_tracemsg(ostring)

        return _("No effect.")
Example #30
0
class MudderyShopGoods(TYPECLASS("OBJECT")):
    """
    This is a shop goods. Shops show these objects to players. It contains a common object
    to sell and additional shop information.
    """
    typeclass_key = "SHOP_GOODS"
    typeclass_name = _("Goods", "typeclasses")
    model_name = "shop_goods"

    def at_object_creation(self):
        """
        Called once, when this object is first created. This is the
        normal hook to overload for most object types.

        """
        super(MudderyShopGoods, self).at_object_creation()

        # Set default values.
        if not self.attributes.has("goods"):
            self.db.goods = None

        self.available = False

    def after_data_loaded(self):
        """
        Load goods data.

        Returns:
            None
        """
        self.available = False

        self.shop_key = getattr(self.system, "shop", "")
        self.goods_key = getattr(self.system, "goods", "")
        self.goods_level = getattr(self.system, "level", 0)

        if not self.shop_key or not self.goods_key:
            if self.db.goods:
                self.db.goods.delete()
                self.db.goods = None
            return

        # set goods information
        self.price = getattr(self.system, "price", 0)
        self.unit_key = getattr(self.system, "unit", "")
        self.number = getattr(self.system, "number", 0)
        self.condition = getattr(self.system, "condition", "")

        # get price unit information
        unit_record = get_object_record(self.unit_key)
        if not unit_record:
            logger.log_errmsg("Can not find %s price unit %s." %
                              (self.goods_key, self.unit_key))
            return
        self.unit_name = unit_record.name

        # load goods object
        goods = self.db.goods
        if goods:
            if goods.get_data_key() == self.goods_key:
                # Load data.
                try:
                    # Load db data.
                    goods.load_data()
                except Exception, e:
                    logger.log_errmsg("%s(%s) can not load data:%s" %
                                      (self.goods_key, self.dbref, e))
            else:
                goods.set_data_key(self.goods_key, self.goods_level)
        else:
Example #31
0
        try:
            # set data
            obj.load_data()
            # put obj to its default location
            obj.reset_location()
        except Exception, e:
            ostring = "%s can not load data:%s" % (obj.dbref, e)
            print(ostring)
            print(traceback.print_exc())
            if caller:
                caller.msg(ostring)

        current_obj_keys.add(obj_key)

    # Create new objects.
    object_model_name = TYPECLASS("OBJECT").model_name
    object_model = apps.get_model(settings.WORLD_DATA_APP, object_model_name)
    for record in objects_data:
        if not record.key in current_obj_keys:
            # Create new objects.
            ostring = "Creating %s." % record.key
            print(ostring)
            if caller:
                caller.msg(ostring)

            try:
                object_record = object_model.objects.get(key=record.key)
                typeclass_path = TYPECLASS_SET.get_module(
                    object_record.typeclass)
                obj = create.create_object(typeclass_path, object_record.name)
                count_create += 1