RPG多人回合制战斗框架设计《四:技能设计》

齐高阳
2023-12-01

RPG战斗框架包含以下四部分的内容:


一、基本战斗流程

二、战斗角色设计

三、战斗伤害计算

四、技能设计

五、BUFF设计

六、战斗AI

四:技能设计

被动技能的功能:

1、有这个技能,会有某种功能,例如:加属性

2、有这个被动技能,在某些时机会产生某种效果,例如:有被动技能A时候,再收到伤害时候会回血。

技能定义:

skill_def .py

PERFORM_TIMEPOINT_NORMAL = 0x1
PERFORM_TIMEPOINT_READY = 0x2
PERFORM_TIMEPOINT_HIT = 0x4
PERFORM_TIMEPOINT_DAMAGE = 0x9

PERFORM_TYPE_CAST = 0x0
PERFORM_TYPE_PHYSICS = 0x1
PERFORM_TYPE_MAGIC = 0x2
PERFORM_TYPE_SEAL = 0x3
PERFORM_TYPE_HEAL = 0x4

PASSIVE_TIMEPOINT_WARSTART = 0x1
PASSIVE_TIMEPOINT_RECVDAMAGE = 0X02


ATTACKTYPE_MAGIC

技能基类:

class CSkill(object):
    m_name = "未知技能"
    m_id = 0

    def __init__(self):
        pass

    def apply(self, who, lv):
        pass

    def register(self, who, lv):
        pass

    def release(self, who):
        pass

    def valid_cast(self, warobj, caster, target, lv):  # 战斗状态
        return False

    def do_cast(self, warobj, caster, target, lv):
        return 0

被动技能:


class CPassive(CSkill):
    m_fight_data = []
    m_timePoint2FuncStr = {
        PASSIVE_TIMEPOINT_WARSTART: "on_war_start",  # 进入战斗
        PASSIVE_TIMEPOINT_RECVDAMAGE: "on_recv_damage",  # 受伤
    }

    def get_fight_data(self, lv):
        lv = min(len(self.m_fight_data), lv)
        return self.m_fight_data[lv - 1]

    def calculate_values(self, who, lv):
        fd = self.get_fight_data(lv)
        values = {}
        for k, v in fd["applys"].iteritems():
            values[k] = values.get(k, 0) + v
        return values

    def apply(self, warrior, lv):
        values = self.calculate_values(who, lv)
        warrior.add_apply(values, comment="skill_%d" % self.m_ID)
        warrior.skill_prop[self.m_ID] = values
        self.register(warrior, lv)

    def release(self, who):
        values = who.skill_prop.get(self.m_ID)
        if values:
            who.remove_apply(values, comment="skill_%d" % self.m_ID)
            del who.skill_prop[self.m_ID]
        self.unregister(who)

    def register(self, who, lv):
        fd = self.get_fight_data(lv)
        for k, v in fd["effect"].iteritems():
            func = getattr(self, self.m_timePoint2FuncStr[k])
            who.m_war_hook[k][self.m_ID] = func

    def unregister(self, who):
        for timepoint, timepointdict in who.m_war_hook.iteritems():
            timepointdict.pop(self.m_ID, None)

    def apply_effect(self, caster, targets, damage, lv, itype):
        fd = self.get_fight_data(lv)
        eff = fd["effect"][itype]
        for eid, arg in eff:
        # 执行效果
        # eobj = effect.LoadEffect(eid)
        # eobj.apply(caster, caster, arg, self, lv, damage)
        return damage

    def on_war_start(self, lv, who):
        self.apply_effect(who, None, 0, lv, PERFORM_TIMEPOINT_WARSTART)

    def on_recv_damage(self, lv, who, att, damage, skob, sklv):
        self.apply_effect(who, [att], damage, lv, PERFORM_TIMEPOINT_RECVDAMAGE)

被动技能例子:

九阴真经加最大血量48,受到伤害时候会触发某效果,进入战斗时候也会触发效果

class CSkill(CPassive):
	m_id = 1001
	m_name = "九阴真经"
	m_fight_data = [
		{
			"applys": {
				"m_hp_max": 48,
			},
			"effect": {
				PASSIVE_TIMEPOINT_WARSTART: [],
				PASSIVE_TIMEPOINT_RECVDAMAGE: [],
			},
	]

主动技能的功能:

被动技能的功能:

1、消耗

2、目标选择

3、造成伤害

4、触发效果

skill_def.py

目标选择的目标类型

PERFORM_TARGET_PLAYER = 0x1
PERFORM_TARGET_SUMMON = 0x2
PERFORM_TARGET_DIED = 0x4

主动技能基类:

class CPerform(CSkill):
    m_Type = PERFORM_TYPE_CAST
    m_fight_data = []
    m_Weight = None

    def get_fight_data(self, warobj, lv):
        fd = self.m_fight_data
        return fd[lv - 1]

    def get_mp_cost(self, caster, lv):
        mpc = int(eval(fd["mp_cost"]))
        return mpc

    def valid_cast(self, warobj, caster, target, lv):  # 战斗状态
        if caster.m_MP < self.get_mp_cost(caster, lv):
            return "真气不足"

    def do_cost(self, caster, lv):
        mp = self.get_mp_cost(caster, lv)
        caster.add_mp(-mp)

    def get_targets(self, warobj, caster, target, lv):
        return [ob for ob in warobj.m_teams[target.m_lineup]]

    def apply_effect(self, caster, targets, damage, lv, itype):  # 技能等级lv
        fd = self.get_fight_data(caster.m_War, lv)
        eff = fd["effect"][itype]

        for eid, arg, isself in eff:
            # 效果
            pass
        # arg = efv.get(eid, arg)
        # eobj = effect.LoadEffect(eid)
        # value = eobj.apply(caster, caster, arg, self, lv, damage, self.GetDamageType())
        return damage

    def on_fight_ready(self, caster, tid, lv):
        vic = caster.m_War.get_warrior(tid)
        self.apply_effect(caster, [vic], 0, lv, PERFORM_TIMEPOINT_READY)

    def on_damage(self, caster, target, damage, lv):
        self.apply_effect(caster, [target], damage, lv, PERFORM_TIMEPOINT_DAMAGE)

    def get_physics_damage(self, warobj, lv, caster, vic):
        damage = warobj.physics_damage(caster, vic, self.get_skill_attack(lv, caster)
        return damage

    def get_magic_damage(self, warobj, lv, caster, vic):
        damage = warobj.magic_damageamage(caster, vic, self.get_skill_attack(lv, caster)
        return damage

    def get_skill_attack(self, slv, caster):
        fd = self.get_fight_data(caster.m_War, slv)
        return int(eval(fd["attack"]))

    def do_cast(self, warobj, caster, targets, lv, back=0):
        fd = self.get_fight_data(warobj, lv)

        delay = 0  # 150 喊招时间已在技能里

        if self.m_Type == PERFORM_TYPE_PHYSICS:
            # print "物理招式"
            dmg_func = self.get_physics_damage
            func = self.perform_physics
        elif self.m_Type == PERFORMTYPE_MAGIC:
            # print "法术招式"
            dmg_func = self.get_magic_damage
            func = self.perform_magic

        dmg = dmg_func(warobj, lv, caster, vic)
        d, b = func(warobj, caster, vic, lv, fd, dmg)
        delay += d  # 额外的技能消耗

        return delay

    def perform_physics(self, warobj, caster, vic, lv, fd, damage, hitobj, back):
        delay = 0
        damage = self.on_hit(caster, vic, damage, lv)
        damage, real_damage = vic.receive_damage(damage, caster, ATTACKTYPE_PERFORM)

        vic.OnHurtEx(caster, damage, dt, attack_status)

        return (delay, caster.IsDied())

    def perform_magic(self, warobj, caster, vic, lv, fd, damage, hitobj, back):
        delay = 0
        damage = self.on_hit(caster, vic, damage, lv)
        vic.receive_damage(damage, caster)

        return delay, False

    def on_hit(self, caster, target, damage, lv):
        caster.on_hit(target, damage, self, lv)

主动技能例子:

class CSkill(CPerform):
	m_id = 1002
	m_name = "化骨绵掌"
	m_yype = PERFORM_TYPE_CAST
	m_level_max = 1
	m_fight_data = 	[
		{	#level = 1
			"mp_cost"	: "",
			"target"	: PERFORM_TARGET_PLAYER|PERFORM_TARGET_SUMMON
			"attack"	: "0",
			"hit"		: 100,
			"delay"		: 78,
			"effect"	: {
				PERFORM_TIMEPOINT_CASTHIT	: ([],[]),
				PERFORM_TIMEPOINT_READY		: ([],[]),
			},
		},
	]

技能触发效果实现:

设计:

有三部分组成,判断+目标+执行,希望灵活填表去实现策划的效果需求

提高代码复用

# coding: utf-8

import limit
import target
import apply

class CEffectBase(object):
	m_id = 0
	m_name = "基础效果"
	m_limit = []
	m_target = 0
	m_apply = []

	def __str__(self):
		return self.m_name

	def __init__(self):
		self.m_limit_objects = []
		self.m_target_objects = []
		self.m_apply_objects = []
		for lid in self.m_limit:
			self.m_limit_objects.append(limit.LoadLimit(lid).IsLimited)
		self.m_target_objects = target.LoadTarget(self.m_target).GetTarget
		for aid in self.m_apply:
			self.m_apply_objects.append(apply.LoadApply(aid).OnApply)

	def __call__(self, caster, target, arg, skob, lv, *args, **kwargs):
		for limit_fun in self.m_limit_objects:
			if not limit_fun(caster, target, arg, skob, lv, *args, **kwargs):
				return

		target = self.m_target_objects(caster, target, arg, skob, lv, *args, **kwargs)
		for apply_fun in self.m_apply_objects:
			apply_fun(caster, target, arg, skob, lv, *args, **kwargs)



target1001.py   
def GetTarget(caster, target, arg, skob, lv, *args, **kwargs):
    return target

 
 limit1001.py
 def IsLimited(caster, target, arg, skob, lv, *args, **kwargs):
	if caster.get_grade() > 10:
		return True
	return False


apply1001.py
def OnApply(caster, target, arg, skob, lv, *args, **kwargs):
	target.add_hp(arg[0])

 

填表例子:

effect1001.py

class CEffect(effect.CEffectBases):
	m_id = 0
	m_name = "等级大于10时候给自己加血"
	m_limit = [1001]
	m_target = 1001
	m_apply = [1001]

 类似资料: