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]