A
A
Alexander2014-09-05 15:25:24
Programming
Alexander, 2014-09-05 15:25:24

How to implement a system of effects (modifiers) imposed on the player?

This system is found in games quite often. Its essence is that various items that the player can use (put on, drink, etc.) give effects to the player's characteristics (increase strength by 10%, increase health by 5 points, etc.).
Please tell me how to implement this, perhaps there are articles on this topic or code examples. In general, any information on the topic is welcome.

Answer the question

In order to leave comments, you need to log in

6 answer(s)
B
bromzh, 2014-09-05
@fuliozor

Since you did not say what language you write in, I will throw off the code in python:

class Effect:

    def __init__(self, name, mods):
        self.name = name
        self.mods = mods
        # mods - это словарь с модификаторами
        # ключ - имя поля в классе User
        # значение - функция, которая принимает экземпляр класса User и промежуточное значение поля
        # а возвращает изменённое значение поля


class User:

    def __init__(self, name, strength, agility):
        # Инициируем начальные значения
        self.name = name
        self.strength = strength
        self.health = strength * 100
        self.agility = agility
        self.effects = list()

    # в самом классе храним только независимые значения
    # но любой доступ к параметрам должен идти через геттер
    # для каждого необходимого параметра создаём функцию-геттер
    # которая будет учитывать применение эффектов
    # можно вместо этого использовать @property
    def get_strength(self):
        strength = self.strength
        for effect in self.effects:
            if effect.mods.get('strength'):
                strength = effect.mods['strength'](strength, self)  # вызываем функцию - модификатор
        return strength

    def get_agility(self):
        agility = self.agility
        for effect in self.effects:
            if effect.mods.get('agility'):
                agility = effect.mods['agility'](agility, self)  # вызываем функцию - модификатор
        return agility

    def get_health(self):
        health = self.health
        for effect in self.effects:
            if effect.mods.get('health'):
                health = effect.mods['health'](health, self)  # вызываем функцию - модификатор
        return health

    # Это зависимый параметр
    def get_max_health(self):
        max_health = self.get_strength() * 100  # первоначальное значение вычисляется на основе силы
        for effect in self.effects:
            if effect.mods.get('max_health'):
                max_health = effect.mods['max_health'](max_health, self)  # вызываем функцию - модификатор
        return max_health


if __name__ == '__main__':
    foo = User('Foo', 10, 10)
    god_strength = Effect('God strength', {
        'strength': lambda s, u: s + 10
    })

    def _life_power_func(value, user):
        return value + 100

    life_power = Effect('Life Power', {
        'max_health': _life_power_func
    })

    def _extra_agility_func(value, user):
        return value + 10

    # этот эффект влияет сразу на 2 параметра
    extra_agility = Effect('Extra agility', {
        'agility': _extra_agility_func,
        'max_health': lambda h, u: h - 400
    })
    print(foo.get_strength(), foo.get_max_health(), foo.get_health(), foo.get_agility(), [e.name for e in foo.effects])
    foo.effects.append(god_strength)
    print(foo.get_strength(), foo.get_max_health(), foo.get_health(), foo.get_agility(), [e.name for e in foo.effects])
    foo.effects.append(life_power)
    print(foo.get_strength(), foo.get_max_health(), foo.get_health(), foo.get_agility(), [e.name for e in foo.effects])
    foo.effects.append(extra_agility)
    print(foo.get_strength(), foo.get_max_health(), foo.get_health(), foo.get_agility(), [e.name for e in foo.effects])

Result:
10 1000 1000 10 []
20 2000 1000 10 ['God strength']
20 2100 1000 10 ['God strength', 'Life Power']
20 1700 1000 20 ['God strength', 'Life Power', 'Extra agility']

X
xmoonlight, 2014-09-05
@xmoonlight

Do it ONLY as a transaction (as in banks) to exclude cheats!
1. check whether the intermediate buffer is empty (whether the transaction is active)
2. save the indicator by putting it in the buffer
3. reduce the number of the object (property) - empty the bottle
4. increase the hero's indicator by the amount from the buffer.
5. clear the buffer
This is a separate class-manipulator for moving energies in the game world.

S
Sali_cat, 2014-09-09
@Sali_cat

Well, print all the values ​​into variables, and then just process and add them.

K
KorsaR-ZN, 2014-09-05
@KorsaR-ZN

Try to implement it based on the "command" pattern, i.e. each feature is a separate "command" class with one public execute() method, and you attach an array of these commands to the user class and apply one after another in the loop.

D
Deerenaros, 2014-09-05
@Deerenaros

In general, the subsequent implementation is highly dependent on the current architecture. Personally, I would do something like this (python rules):

class Modifiable:
  base = {"strength": 10}
  mod = {"strength*": 2, "strength+", -3}

  def __init__(self, **kwargs):
    pass


class Hero(Modifiable):
  def __init__(self, **kwargs):
    pass
    
  @property
  def strength(self):
    return self.base["strength"] * self.mod["strength*"] + self.mod["strength+"]

The essence is approximately clear, besides, you can go further and file a class - ObjectProperty and ObjectModificator with all the necessary methods, and then exactly multiply by calling the overloaded __mul__.

M
Maxim Grechushnikov, 2014-09-05
@maxyc_webber

here in this matter the principle of increasing the cost of buildings / improvements is still interesting.
but on the theme of the question, I think everyone does it himself. If anyone has done this, please share your experience.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question