|
发表于 2014-10-27 13:51:41
|
显示全部楼层
本帖最后由 卡特铁角 于 2014-10-27 14:00 编辑
Mr_I 发表于 2014-10-27 09:30 
“大概明白了”,你还是没明白。或者不想明白?
我说的做法就是包括组装的。
你所谓的读表工具里面大概是这个样子:
- local function ReadSkillConfigFile(file_path)
- local ret_table = {} -- return data table
- --从c++里读取数据表
- local config = mjlib.LuaXmlParseFile(file_path);
- if config == nil then
- print( "xml file table is nil")
- else
- --表的结构与xml的配置文件的结构相关,目前从xml读取到的结构如下
- --print_table("skill",config)
- for i, iv in pairs(config) do --{}
- if type(iv) == "table" then
-
- for k, kv in pairs(iv) do --skills
- if type(kv) == "table" then --skill
-
- --处理skill表
- local tmp_skill_table = {}
- if kv.id ~= nil then
- ret_table[kv.id] = tmp_skill_table;
- end
-
- for j, jv in pairs(kv) do --skill
-
- if type(jv) == "table" then --skill below table
-
- --处理表成员
- if jv.id ~= nil then
- --将名字相同的叶子节点合并为一个表,并建立索引
- if tmp_skill_table[jv.name] == nil then
- tmp_skill_table[jv.name] = {}
- end
- tmp_skill_table[jv.name][jv.id] = jv;
-
- else
- --只存在一个表的不需要合并
- if not tmp_skill_table[jv.name] then
- tmp_skill_table[jv.name] = jv
- end
- end
-
- else
- --非表内成员值直接赋值
- tmp_skill_table[j] = jv
- end
- end
-
- end
- end
-
- end
- end
- end
- return ret_table
- end
复制代码 对应的XML表大概这样:- <skill id="6" nameid="3" name="突击步枪点射(1级)" vocation="1" skilllevel="1" skilltype="1" casttype="5" bulletspeed="200" humanaccuracy="50" vehicleaccuracy="50" boataccuracy="50" submarineaccuracy="50" aircraftaccuracy="50" friendlyfire="1">
- <castcondition readytime="0" cooldowntime="0.5" friendly="2" rangemin="0" rangemax="100" enviroment="1" moveable="1" weapontype="6" weaponid="0" ammotype="6" ammosum="1" itemid="0" itemsum="0" machinetype="0" machineid="0" seatid="0" castinmachine="0" equipmentid1="0" equipmentid2="0" equipmentid3="0" hp="0" sp="0" food="0" money="0" fuel="0" endure="0" energy="0" horizonmin="-180" horizonmax="180" verticalmin="-180" verticalmax="180"/>
- <targeteffect id="1" effectid="6" shape="1" arearadius="0" probability="100"/>
- <targeteffect id="2" effectid="0" shape="0" arearadius="0" probability="0"/>
- <targeteffect id="3" effectid="0" shape="0" arearadius="0" probability="0"/>
- <castereffect id="1" effectid="0" shape="0" arearadius="0" probability="0"/>
- <castereffect/>
- </skill>
复制代码 这是那个伪FPS项目中一个技能的描述,还是挺早期的版本。后来这个<skill>下又加了两种包含若干参数的子节点。
上面的数据解析函数已经写的比较“通用”了,但为了方便后面的技能处理逻辑获取数据并减少冗余,还是做了一些针对性的处理。对于这个数据解析函数,修改节点的成员数量或在某个节点下增加同名叶子节点时,这个解析函数不用修改就可以用;但如果增加的新节点内部还有结构,或者在当前某个叶子节点里面又加了一层,那就需要修改解析函数。当然,这个解析函数还可以写得更“通用”一些,不过又有多大意义呢?当XML表的结构发生改变,技能处理逻辑中访问/使用/处理数据的方法流程必定要做相应的调整,这才是耗神又容易出错的工作。
通用技能处理逻辑部分代码(这里贴上来的就是按你说的表格描述通用技能,脚本描述特殊技能的方式做的):
- function OnLoad()
- local scriptType = luacom.SKILL_SCRIPT
- local event_tab = luacom.GetEventTable(scriptType)
- luacom.RegisterEvent(event_tab,scriptType,0,OnEvent)
-
- luacom.ImportSkillData() --将技能、效果数据从硬盘文件导入到内存
- end
- function OnEvent(event,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)
- --_G.print("debug:luascript-skill:OnEvent() called! event="..event.." arg1="..arg1.." arg2="..arg2.." arg3="..arg3.." arg4="..arg4.." arg5="..arg5.." arg6="..arg6.." arg7="..arg7.." arg8="..arg8)
-
- --若存在对应于当前事件中技能ID的特殊技能脚本,则调用此特殊技能脚本处理该事件,而不需要再通过技能脚本的总入口处理
- local subScriptType = luacom.SKILL_SCRIPT
- local subScriptID = arg1
- if(luacom.CallRegisteredScript(subScriptType,subScriptID,event,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)) then
- return
- end
-
- if(eventProcessor[event]) then
- eventProcessor[event](arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)
- end
- end
- ventProcessor[luacom.SKILL_BULLET_IMPACT_TARGET] = function(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)
- --_G.print("debug:luascript-skill:eventProcessor[luacom.SKILL_BULLET_IMPACT_TARGET]() called!")
- local skillID = arg1
- local casterID = arg2
- local targetID = arg3
- local impact_x = arg4
- local impact_y = arg5
- local impact_z = arg6
- local criticalBonus = arg7
- local weaponAndAmmo = arg8
-
- local skill = luacom.GetSkillData(skillID)
- if(skill.casttype ~= 3 and skill.cassttyp ~= 4) then --保险措施:正确的情况下,3、4类技能(按角色朝向施放的范围技能)不会触发该事件
- skillImpactAndExplode(skillID,casterID,targetID,impact_x,impact_y,impact_z,criticalBonus,weaponAndAmmo)
- end
- end
- eventProcessor[luacom.SKILL_EXPLODE_AFFECT_CHARACTER] = function(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)
- local skillID = arg1
- local casterID = arg2
- local targetID = arg3
- local explodeShape = arg4
- local distanceSquare = arg5
- local criticalBonus = arg6
- local weaponAndAmmo = arg7
-
- local skill = luacom.GetSkillData(skillID)
-
- if(skill == nil) then
- _G.print("luascript-skill:eventProcessor[luacom.SKILL_EXPLODE_AFFECT_CHARACTER]()error! skillID:"..arg1.." is not exist!")
- return
- end
-
- if(skill.targeteffect == nil) then
- _G.print("luascript-skill:eventProcessor[luacom.SKILL_EXPLODE_AFFECT_CHARACTER]() error! skill.targeteffect is nil! skillID:"..arg1)
- return
- end
-
- if(luacom.IsCharacterInMachine(targetID) == false) then
- --[[setTargetAttribute()将一并负责对目标及其乘员的属性进行计算和设置,若没有乘员则只对目标本身进行设置。机体内的乘员不会单独受到爆炸影响。
- 即,此处认为爆炸只对爆炸范围内处于机体外的单兵角色以及机体产生作用。否则机体内乘员在同一次爆炸中所受伤害会被重复计算。]]
- for i in _G.pairs(skill.targeteffect) do
- local radiusSquare = skill.targeteffect[i].arearadius^2
- local shape = skill.targeteffect[i].shape
-
- if(shape == explodeShape and radiusSquare >= distanceSquare) then --由于同一技能中形状不同的爆炸事件是分别设置的,故这里只对explodeShape指定形状的爆炸进行处理
- local effect = luacom.GetEffectData(skill.targeteffect[i].effectid)
- if(effect == nil) then
- _G.print("luascript-skill:eventProcessor[luacom.SKILL_EXPLODE_AFFECT_CHARACTER]() error! effectID:"..skill.targeteffect[i].effectid.." is not exist!")
- return
- end
-
- if(effect.friendly ~= 0) then --阵营属性对效果生效与否的判断
- if(effect.friendly == 1) then --援助技能
- if(luacom.TargetCanAssist(casterID,targetID) == false) then
- return
- end
- elseif(effect.friendly == 2) then --攻击技能
- if(luacom.TargetCanAttack(casterID,targetID) == false) then
- return
- end
- end
- end
-
- if(skill.targeteffect[i].probability >= 100 or skill.targeteffect[i].probability ~= nil
- and skill.targeteffect[i].probability > 0 and luacom.MathRandom(1,100) <= skill.targeteffect[i].probability) then
- if(canAffectTarget(skill.targeteffect[i].effectid,casterID,targetID)) then
- setTargetAttribute(skillID,skill.targeteffect[i].effectid,criticalBonus,weaponAndAmmo,casterID,targetID,true)
- end
- if(canAffectPassenger(skill.targeteffect[i].effectid,casterID,targetID)) then
- setPassengerAttribute(skillID,skill.targeteffect[i].effectid,criticalBonus,weaponAndAmmo,shape,casterID,targetID,true)
- end
- end
- end
- end
- end
- end
- eventProcessor[luacom.SKILL_BUFF_CHECK] = function(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)
- --arg1=skillID arg2=casterID arg3=targetID arg4=effectID arg5=buffslotID arg6=startTime arg7=preBeat arg8=weaponAndAmmo
- local skillID = arg1
- local casterID = arg2
- local targetID = arg3
- local effectID = arg4
- local buffslotID = arg5
- local startTime = arg6
- local preBeat = arg7
- local weaponAndAmmo = arg8
-
- local effect = luacom.GetEffectData(effectID)
- if(effect == nil) then
- _G.print("luascript-skill:eventProcessor[luacom.SKILL_BUFF_CHECK]() error! effectID:"..effectID.." is not exist!")
- return
- end
-
- local currentTime = luacom.GetSystemSec()
- local endTime = startTime + effect.lasttime
- if(currentTime > endTime) then
- currentTime = endTime
- end
-
- if(effect.intervaltime > 0 and currentTime - preBeat >= effect.intervaltime) then
- local times = luacom.MathFloor((currentTime - preBeat)/effect.intervaltime)
- for i = 1,times do
- setTargetAttribute(skillID,effectID,1,weaponAndAmmo,casterID,targetID,false)
- end
- luacom.SetBuffPreBeat(targetID,buffslotID,preBeat+times*effect.intervaltime,startTime)
- end
-
- if(currentTime >= endTime) then
- luacom.ClearBuff(targetID,effectID,buffslotID,startTime)
-
- --[[if(effect.endeffect == nil) then
- _G.print("luascript-skill:eventProcessor[luacom.SKILL_BUFF_CHECK]() error! effectID:"..effectID.." 's endeffect is nil!")
- return
- end
-
- for i in _G.pairs(effect.endeffect) do
- setTargetAttribute(skillID,effect.endeffect[i].effectid,weaponAndAmmo,casterID
- end]]
- end
- end
复制代码 再一段:- eventProcessor[luacom.SKILL_CHARACTER_CAST_BEGIN] = function(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8)
- --_G.print("debug:luascript-skill:eventProcessor[luacom.SKILL_CHARACTER_CAST_BEGIN]() called!")
- local skillID = arg1
- local casterID = arg2
- local targetID = arg3
- local impact_x = arg4
- local impact_y = arg5
- local impact_z = arg6
- local event = luacom.SKILL_CHARACTER_CAST_BEGIN
-
- local skill = luacom.GetSkillData(arg1)
- if(skill == nil) then
- _G.print("luascript-skill:skillID:"..arg1.." is not exist!")
- if(luacom.IsNpc(arg2)) then
- _G.print("luascript-skill:caster is NPC:"..luacom.GetNpcTypeID(arg2))
- end
- return
- end
-
- if(targetID ~= nil and targetID ~= INVALID_ID) then
- local machineInstanceID = luacom.GetMachineAndSeat(targetID)
- if(machineInstanceID ~= 0) then --目标在机体中
- targetID = machineInstanceID
- end
- end
-
- --[[if((skill.castcondition.weapontype == nil or skill.castcondition.weapontype == 0)
- and (skill.castcondition.weaponid == nil or skill.castcondition.weaponid == 0)) then
- local _,_,buffslotID,startTime,_,_ = luacom.GetBuffInfo(casterID,30)
- if(buffslotID) then
- local clearSucceed,sameNameBuffEffection = luacom.ClearBuff(casterID,buffslotID,startTime)
- if(clearSucceed) then
- local recoverValue
- if(effect.intervaltime == 0) then --BUFF结束时,对恒定状态BUFF(intervaltime为0)的属性加成/扣减进行恢复
- for _,attriChange in _G.pairs(effect.attrichange) do
- if(attriChange.percentage ~= 1) then
- recoverValue = luacom.GetCharacterAttribute(casterID,attriChange.attributeid) - attriChange.changevalue
- else
- recoverValue = luacom.GetCharacterAttribute(casterID,attriChange.attributeid)*100/(100 + attriChange.changevalue)
- end
- luacom.SetCharacterAttribute(casterID,attriChange.attributeid,recoverValue)
- end
- end
- end
- end
- end]]
-
- if(skill.casttype == 1) then --选中目标才能施放的技能
- if(targetID == nil or targetID == INVALID_ID) then
- canCast = false
- failReason = CAST_FAIL_TAR_NIL
- luacom.SkillCastFail(skillID,casterID,failReason)
- return
- end
-
- local t_x,t_y,t_z = luacom.GetCharacterPosition(targetID)
- local c_x,c_y,c_z = luacom.GetCharacterPosition(casterID)
- local distanceSquare = luacom.GetDistanceSquare(t_x,t_y,t_z,c_x,c_y,c_z)
- local distance = luacom.MathSqrt(distanceSquare)
-
- local canCast,failReason = skillCanCast(skillID,casterID,targetID,distanceSquare,impact_x,impact_y,impact_z,event)
- if(canCast) then
- if(skill.castcondition == nil) then
- _G.print("luascript-skill:error! skill.castcondition is nil! skillID:"..skillID)
- return
- end
- if(skill.castcondition.readytime == 0) then --瞬发技能
- skillExpend(skillID,casterID)
- local flyingTime = skillFlyingTime(skillID,distance)
- local canHit,bullet_angle = skillCanHit(skillID,casterID,targetID,distanceSquare)
- if(canHit) then --命中判断
- luacom.SkillWillHit(skillID,casterID,targetID,impact_x,impact_y,impact_z,flyingTime) --技能施放成功完成,且将在flyingTime后命中目标或弹着点(当第三个参数为0时表示该技能的命中点是三维坐标)
-
- local criticalBonus = getCriticalBonus(casterID)
- local weaponAndAmmo
- if(arg8 == nil or arg8 == 0) then --若arg8不为空或0,则说明改技能所使用的道具(手雷等)已通过arg8传入。目前,只有特殊技能脚本会通过arg8传入道具ID
- weaponAndAmmo = getWeaponAndAmmo(skillID,casterID)
- else
- weaponAndAmmo = arg8
- end
- if(flyingTime == 0) then
- skillImpactAndExplode(skillID,casterID,targetID,impact_x,impact_y,impact_z,criticalBonus,weaponAndAmmo)
- else
- luacom.SetDelayedEvent(flyingTime,1,luacom.SKILL_BULLET_IMPACT_TARGET,arg1,arg2,arg3,arg4,arg5,arg6,criticalBonus,weaponAndAmmo) --飞行延迟定时
- end
- else
- local errorDistance = bullet_angle*distance
- impact_x = t_x + luacom.MathRandom(-errorDistance,errorDistance)
- impact_y = t_y + luacom.MathRandom(-errorDistance,errorDistance)
- impact_z = t_z
- targetID = INVALID_ID
- luacom.SkillWillHit(skillID,casterID,targetID,impact_x,impact_y,impact_z,flyingTime)
-
- local criticalBonus = 1
- local weaponAndAmmo
- if(arg8 == nil or arg8 == 0) then
- weaponAndAmmo = getWeaponAndAmmo(skillID,casterID)
- else
- weaponAndAmmo = arg8
- end
- if(flyingTime == 0) then
- skillImpactAndExplode(skillID,casterID,targetID,impact_x,impact_y,impact_z,criticalBonus,weaponAndAmmo)
- else
- luacom.SetDelayedEvent(flyingTime,1,luacom.SKILL_BULLET_IMPACT_TARGET,skillID,casterID,targetID,impact_x,impact_y,impact_z,criticalBonus,weaponAndAmmo)
- end
- end
- else --需要吟唱(预备)的技能
- if(skill.castcondition == nil) then
- return
- end
- luacom.SkillCastBegin(skillID,casterID,skill.castcondition.readytime*1000,1,luacom.SKILL_CHARACTER_CAST_END,skillID,casterID,targetID,0,0,0,0,arg8) --通知服务器该次技能施放成功开始且会持续吟唱skill.castcondition.readytime(秒),之后触发SKILL_CHARACTER_CAST_END事件
- end
- elseif(failReason) then
- luacom.SkillCastFail(skillID,casterID,failReason) --通知服务器该次技能施放失败,及失败原因
- end
复制代码
|
|