Created
June 23, 2013 16:23
-
-
Save KapLex/5845573 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
---------------------------------------------------------- | |
-----------金庸群侠传复刻之Lua版---------------------------- | |
--版权所无,敬请复制 | |
--您可以随意使用代码 | |
---本代码由游泳的鱼编写 | |
--本模块是lua主模块,由C主程序JYLua.exe调用。C程序主要提供游戏需要的视频、音乐、键盘等API函数,供lua调用。 | |
--游戏的所有逻辑都在lua代码中,以方便大家对代码的修改。 | |
--为加快速度,显示主地图/场景地图/战斗地图部分用C API实现。 | |
--导入其他模块。之所以做成函数是为了避免编译查错时编译器会寻找这些模块。 | |
function IncludeFile() --导入其他模块 | |
--dofile("config.lua"); --此文件在C函数中预先加载。这里就不加载了 | |
dofile(CONFIG.ScriptPath .. "jyconst.lua"); | |
dofile(CONFIG.ScriptPath .. "jymodify.lua"); | |
end | |
function SetGlobal() --设置游戏内部使用的全程变量 | |
JY={}; | |
JY.Status=GAME_INIT; --游戏当前状态 | |
--保存R×数据 | |
JY.Base={}; --基本数据 | |
JY.PersonNum=0; --人物个数 | |
JY.Person={}; --人物数据 | |
JY.ThingNum=0 --物品数量 | |
JY.Thing={}; --物品数据 | |
JY.SceneNum=0 --物品数量 | |
JY.Scene={}; --物品数据 | |
JY.WugongNum=0 --物品数量 | |
JY.Wugong={}; --物品数据 | |
JY.ShopNum=0 --商店数量 | |
JY.Shop={}; --商店数据 | |
JY.Data_Base=nil; --实际保存R*数据 | |
JY.Data_Person=nil; | |
JY.Data_Thing=nil; | |
JY.Data_Scene=nil; | |
JY.Data_Wugong=nil; | |
JY.Data_Shop=nil; | |
JY.MyCurrentPic=0; --主角当前走路贴图在贴图文件中偏移 | |
JY.MyPic=0; --主角当前贴图 | |
JY.MyTick=0; --主角没有走路的持续帧数 | |
JY.MyTick2=0; --显示事件动画的节拍 | |
JY.EnterSceneXY=nil; --保存进入场景的坐标,有值可以进入,为nil则重新计算。 | |
JY.oldMMapX=-1; --上次显示主地图的坐标。用来判断是否需要全部重绘屏幕 | |
JY.oldMMapY=-1; | |
JY.oldMMapPic=-1; --上次显示主地图主角贴图 | |
JY.SubScene=-1; --当前子场景编号 | |
JY.SubSceneX=0; --子场景显示位置偏移,场景移动指令使用 | |
JY.SubSceneY=0; | |
JY.Darkness=0; --=0 屏幕正常显示,=1 不显示,屏幕全黑 | |
JY.CurrentD=-1; --当前调用D*的编号 | |
JY.OldDPass=-1; --上次触发路过事件的D*编号, 避免多次触发 | |
JY.CurrentEventType=-1 --当前触发事件的方式 1 空格 2 物品 3 路过 | |
JY.oldSMapX=-1; --上次显示场景地图的坐标。用来判断是否需要全部重绘屏幕 | |
JY.oldSMapY=-1; | |
JY.oldSMapXoff=-1; --上次场景偏移 | |
JY.oldSMapYoff=-1; | |
JY.oldSMapPic=-1; --上次显示场景地图主角贴图 | |
JY.D_Valid=nil --记录当前场景有效的D的编号,提高速度,不用每次显示都计算了。若为nil则重新计算 | |
JY_D_Valld_Num=0; --当前场景有效的D个数 | |
JY.D_PicChange={} --记录事件动画改变,以计算Clip | |
JY.NumD_PicChange=0; --事件动画改变的个数 | |
JY.CurrentThing=-1; --当前选择物品,触发事件使用 | |
JY.MmapMusic=-1; --切换大地图音乐,返回主地图时,如果设置,则播放此音乐 | |
JY.CurrentMIDI=-1; --当前播放的音乐id,用来在关闭音乐时保存音乐id。 | |
JY.EnableMusic=1; --是否播放音乐 1 播放,0 不播放 | |
JY.EnableSound=1; --是否播放音效 1 播放,0 不播放 | |
JY.ThingUseFunction={}; --物品使用时调用函数,SetModify函数使用,增加新类型的物品 | |
JY.SceneNewEventFunction={}; --调用场景事件函数,SetModify函数使用,定义使用新场景事件触发的函数 | |
WAR={}; --战斗使用的全程变量。。这里占个位置,因为程序后面不允许定义全局变量了。具体内容在WarSetGlobal函数中 | |
end | |
function JY_Main() --主程序入口 | |
os.remove("debug.txt"); --清除以前的debug输出 | |
xpcall(JY_Main_sub,myErrFun); --捕获调用错误 | |
end | |
function myErrFun(err) --错误处理,打印错误信息 | |
lib.Debug(err); --输出错误信息 | |
lib.Debug(debug.traceback()); --输出调用堆栈信息 | |
end | |
function JY_Main_sub() --真正的游戏主程序入口 | |
IncludeFile(); --导入其他模块 | |
SetGlobalConst(); --设置全程变量CC, 程序使用的常量 | |
SetGlobal(); --设置全程变量JY | |
GenTalkIdx(); --生成对话idx | |
SetModify(); --设置对函数的修改,定义新的物品,事件等等 | |
--禁止访问全程变量 | |
setmetatable(_G,{ __newindex =function (_,n) | |
error("attempt read write to undeclared variable " .. n,2); | |
end, | |
__index =function (_,n) | |
error("attempt read read to undeclared variable " .. n,2); | |
end, | |
} ); | |
lib.Debug("JY_Main start."); | |
math.randomseed(os.time()); --初始化随机数发生器 | |
lib.EnableKeyRepeat(CONFIG.KeyRepeatDelay,CONFIG.KeyRePeatInterval); --设置键盘重复率 | |
JY.Status=GAME_START; | |
lib.PicInit(CC.PaletteFile); --加载原来的256色调色板 | |
lib.PlayMPEG(CONFIG.DataPath .. "start.mpg",VK_ESCAPE); | |
Cls(); | |
PlayMIDI(16); | |
lib.ShowSlow(50,0); | |
local menu={ {"重新开始",nil,1}, | |
{"载入进度",nil,1}, | |
{"离开游戏",nil,1} }; | |
local menux=(CC.ScreenW-4*CC.StartMenuFontSize-2*CC.MenuBorderPixel)/2 | |
local menuReturn=ShowMenu(menu,3,0,menux,CC.StartMenuY,0,0,0,0,CC.StartMenuFontSize,C_STARTMENU, C_RED) | |
if menuReturn == 1 then --重新开始游戏 | |
Cls(); | |
DrawString(menux,CC.StartMenuY,"请稍候...",C_RED,CC.StartMenuFontSize); | |
ShowScreen(); | |
NewGame(); --设置新游戏数据 | |
JY.SubScene=CC.NewGameSceneID; --新游戏直接进入场景 | |
JY.Scene[JY.SubScene]["名称"]=JY.Person[0]["姓名"] .. "居"; | |
JY.Base["人X1"]=CC.NewGameSceneX; | |
JY.Base["人Y1"]=CC.NewGameSceneY; | |
JY.MyPic=CC.NewPersonPic; | |
lib.ShowSlow(50,1) | |
JY.Status=GAME_SMAP; | |
JY.MMAPMusic=-1; | |
CleanMemory(); | |
Init_SMap(0); | |
if CC.NewGameEvent>0 then | |
oldCallEvent(CC.NewGameEvent); | |
end | |
elseif menuReturn == 2 then --载入旧的进度 | |
Cls(); | |
local loadMenu={ {"进度一",nil,1}, | |
{"进度二",nil,1}, | |
{"进度三",nil,1} }; | |
local menux=(CC.ScreenW-3*CC.StartMenuFontSize-2*CC.MenuBorderPixel)/2 | |
local r=ShowMenu(loadMenu,3,0,menux,CC.StartMenuY,0,0,0,0,CC.StartMenuFontSize,C_STARTMENU, C_RED) | |
Cls(); | |
DrawString(menux,CC.StartMenuY,"请稍候...",C_RED,CC.StartMenuFontSize); | |
ShowScreen(); | |
LoadRecord(r); | |
Cls(); | |
ShowScreen(); | |
JY.Status=GAME_FIRSTMMAP; | |
elseif menuReturn == 3 then | |
return ; | |
end | |
lib.LoadPicture("",0,0); | |
lib.GetKey(); | |
Game_Cycle(); | |
end | |
function CleanMemory() --清理lua内存 | |
if CONFIG.CleanMemory==1 then | |
collectgarbage("collect"); | |
--lib.Debug(string.format("Lua memory=%d",collectgarbage("count"))); | |
end | |
end | |
function NewGame() --选择新游戏,设置主角初始属性 | |
LoadRecord(0); -- 载入新游戏数据 | |
JY.Person[0]["姓名"]=CC.NewPersonName; | |
while true do | |
JY.Person[0]["内力性质"]=Rnd(2); | |
JY.Person[0]["内力最大值"]=Rnd(20)+21; | |
JY.Person[0]["攻击力"]=Rnd(10)+21; | |
JY.Person[0]["防御力"]=Rnd(10)+21; | |
JY.Person[0]["轻功"]=Rnd(10)+21; | |
JY.Person[0]["医疗能力"]=Rnd(10)+21; | |
JY.Person[0]["用毒能力"]=Rnd(10)+21; | |
JY.Person[0]["解毒能力"]=Rnd(10)+21; | |
JY.Person[0]["抗毒能力"]=Rnd(10)+21; | |
JY.Person[0]["拳掌功夫"]=Rnd(10)+21; | |
JY.Person[0]["御剑能力"]=Rnd(10)+21; | |
JY.Person[0]["耍刀技巧"]=Rnd(10)+21; | |
JY.Person[0]["特殊兵器"]=Rnd(10)+21; | |
JY.Person[0]["暗器技巧"]=Rnd(10)+21; | |
JY.Person[0]["生命增长"]=Rnd(5)+3; | |
JY.Person[0]["生命最大值"]= JY.Person[0]["生命增长"]*3+29; | |
local rate=Rnd(10); | |
if rate<2 then | |
JY.Person[0]["资质"]=Rnd(35)+30; | |
elseif rate<=7 then | |
JY.Person[0]["资质"]=Rnd(20)+60; | |
else | |
JY.Person[0]["资质"]=Rnd(20)+75; | |
end | |
JY.Person[0]["生命"]=JY.Person[0]["生命最大值"]; | |
JY.Person[0]["内力"]=JY.Person[0]["内力最大值"]; | |
Cls(); | |
local fontsize=CC.NewGameFontSize; | |
local h=fontsize+CC.RowPixel; | |
local w=fontsize*4; | |
local x1=(CC.ScreenW-w*4)/2; | |
local y1=CC.NewGameY; | |
local i=0; | |
local function DrawAttrib(str1,str2) --定义内部函数 | |
DrawString(x1+i*w,y1,str1,C_RED,fontsize); | |
DrawString(x1+i*w+fontsize*2,y1,string.format("%3d ",JY.Person[0][str2]),C_WHITE,fontsize); | |
i=i+1; | |
end | |
DrawString(x1,y1,"这样的属性满意吗(Y/N)?",C_GOLD,fontsize); | |
i=0; y1=y1+h; | |
DrawAttrib("内力","内力"); DrawAttrib("攻击","攻击力"); DrawAttrib("轻功","轻功"); DrawAttrib("防御","防御力"); | |
i=0; y1=y1+h; | |
DrawAttrib("生命","生命"); DrawAttrib("医疗","医疗能力");DrawAttrib("用毒","用毒能力"); DrawAttrib("解毒","解毒能力"); | |
i=0; y1=y1+h; | |
DrawAttrib("拳掌","拳掌功夫"); DrawAttrib("御剑","御剑能力"); DrawAttrib("耍刀","耍刀技巧"); DrawAttrib("暗器","暗器技巧"); | |
ShowScreen(); | |
local menu={{"是 ",nil,1}, | |
{"否 ",nil,2}, | |
}; | |
local ok=ShowMenu2(menu,2,0,x1+11*fontsize,CC.NewGameY-CC.MenuBorderPixel,0,0,0,0,fontsize,C_RED, C_WHITE) | |
if ok==1 then | |
break; | |
end | |
end | |
end | |
function Game_Cycle() --游戏主循环 | |
lib.Debug("Start game cycle"); | |
while JY.Status ~=GAME_END do | |
local tstart=lib.GetTime(); | |
JY.MyTick=JY.MyTick+1; --20个节拍无击键,则主角变为站立状态 | |
JY.MyTick2=JY.MyTick2+1; --20个节拍无击键,则主角变为站立状态 | |
if JY.MyTick==20 then | |
JY.MyCurrentPic=0; | |
JY.MyTick=0; | |
end | |
if JY.MyTick2==1000 then | |
JY.MYtick2=0; | |
end | |
if JY.Status==GAME_FIRSTMMAP then --首次显示主场景,重新调用主场景贴图,渐变显示。然后转到正常显示 | |
CleanMemory(); | |
lib.ShowSlow(50,1) | |
JY.MmapMusic=16; | |
JY.Status=GAME_MMAP; | |
Init_MMap(); | |
lib.DrawMMap(JY.Base["人X"],JY.Base["人Y"],GetMyPic()); | |
lib.ShowSlow(50,0); | |
elseif JY.Status==GAME_MMAP then | |
Game_MMap(); | |
elseif JY.Status==GAME_SMAP then | |
Game_SMap() | |
end | |
collectgarbage("step",0); | |
local tend=lib.GetTime(); | |
if tend-tstart<CC.Frame then | |
lib.Delay(CC.Frame-(tend-tstart)); | |
end | |
end | |
end | |
function Init_MMap() --初始化主地图数据 | |
lib.PicInit(); | |
lib.LoadMMap(CC.MMapFile[1],CC.MMapFile[2],CC.MMapFile[3], | |
CC.MMapFile[4],CC.MMapFile[5],CC.MWidth,CC.MHeight,JY.Base["人X"],JY.Base["人Y"]); | |
lib.PicLoadFile(CC.MMAPPicFile[1],CC.MMAPPicFile[2],0); | |
lib.PicLoadFile(CC.HeadPicFile[1],CC.HeadPicFile[2],1); | |
if CC.LoadThingPic==1 then | |
lib.PicLoadFile(CC.ThingPicFile[1],CC.ThingPicFile[2],2); | |
end | |
JY.EnterSceneXY=nil; --设为空,强制重新生成场景入口数据。防止有事件更改了场景入口。 | |
JY.oldMMapX=-1; | |
JY.oldMMapY=-1; | |
PlayMIDI(JY.MmapMusic); | |
end | |
function Game_MMap() --主地图 | |
local direct = -1; | |
local keypress = lib.GetKey(); | |
if keypress ~= -1 then | |
JY.MyTick=0; | |
if keypress==VK_ESCAPE then | |
MMenu(); | |
if JY.Status==GAME_FIRSTMMAP then | |
return ; | |
end | |
JY.oldMMapX=-1; --强制重绘 | |
JY.oldMMapY=-1; | |
elseif keypress==VK_UP then | |
direct=0; | |
elseif keypress==VK_DOWN then | |
direct=3; | |
elseif keypress==VK_LEFT then | |
direct=2; | |
elseif keypress==VK_RIGHT then | |
direct=1; | |
end | |
end | |
local x,y; --按照方向键要到达的坐标 | |
if direct ~= -1 then --按下了光标键 | |
AddMyCurrentPic(); --增加主角贴图编号,产生走路效果 | |
x=JY.Base["人X"]+CC.DirectX[direct+1]; | |
y=JY.Base["人Y"]+CC.DirectY[direct+1]; | |
JY.Base["人方向"]=direct; | |
else | |
x=JY.Base["人X"]; | |
y=JY.Base["人Y"]; | |
end | |
JY.SubScene=CanEnterScene(x,y); --判断是否进入子场景 | |
if lib.GetMMap(x,y,3)==0 and lib.GetMMap(x,y,4)==0 then --没有建筑,可以到达 | |
JY.Base["人X"]=x; | |
JY.Base["人Y"]=y; | |
end | |
JY.Base["人X"]=limitX(JY.Base["人X"],10,CC.MWidth-10); --限制坐标不能超出范围 | |
JY.Base["人Y"]=limitX(JY.Base["人Y"],10,CC.MHeight-10); | |
if CC.MMapBoat[lib.GetMMap(JY.Base["人X"],JY.Base["人Y"],0)]==1 then | |
JY.Base["乘船"]=1; | |
else | |
JY.Base["乘船"]=0; | |
end | |
local pic=GetMyPic(); | |
if CONFIG.FastShowScreen==1 then --设置快速显示,并且主角位置不变,则显示裁剪窗口 | |
if JY.oldMMapX==JY.Base["人X"] and JY.oldMMapY==JY.Base["人Y"] then | |
if JY.oldMMapPic>=0 and JY.oldMMapPic ~= pic then --主角贴图有变化,则刷新显示。 | |
local rr=ClipRect(Cal_PicClip(0,0,JY.oldMMapPic,0,0,0,pic,0)); | |
if rr~=nil then | |
lib.SetClip(rr.x1,rr.y1,rr.x2,rr.y2); | |
lib.DrawMMap(JY.Base["人X"],JY.Base["人Y"],pic); --显示主地图 | |
end | |
end | |
else | |
lib.SetClip(0,0,CC.ScreenW,CC.ScreenH); | |
lib.DrawMMap(JY.Base["人X"],JY.Base["人Y"],pic); --显示主地图 | |
end | |
else --全部显示 | |
lib.DrawMMap(JY.Base["人X"],JY.Base["人Y"],pic); --显示主地图 | |
end | |
if CC.ShowXY==1 then | |
DrawString(10,CC.ScreenH-20,string.format("%d %d",JY.Base["人X"],JY.Base["人Y"]) ,C_GOLD,16); | |
end | |
ShowScreen(CONFIG.FastShowScreen); | |
lib.SetClip(0,0,0,0); | |
JY.oldMMapX=JY.Base["人X"]; | |
JY.oldMMapY=JY.Base["人Y"]; | |
JY.oldMMapPic=pic; | |
if JY.SubScene >= 0 then --进入子场景 | |
CleanMemory(); | |
lib.UnloadMMap(); | |
lib.PicInit(); | |
lib.ShowSlow(50,1) | |
JY.Status=GAME_SMAP; | |
JY.MMAPMusic=-1; | |
JY.MyPic=GetMyPic(); | |
JY.Base["人X1"]=JY.Scene[JY.SubScene]["入口X"] | |
JY.Base["人Y1"]=JY.Scene[JY.SubScene]["入口Y"] | |
Init_SMap(1); | |
end | |
end | |
--showname =1 显示场景名 0 不显示 | |
function Init_SMap(showname) --初始化场景数据 | |
lib.PicInit(); | |
lib.PicLoadFile(CC.SMAPPicFile[1],CC.SMAPPicFile[2],0); | |
lib.PicLoadFile(CC.HeadPicFile[1],CC.HeadPicFile[2],1); | |
if CC.LoadThingPic==1 then | |
lib.PicLoadFile(CC.ThingPicFile[1],CC.ThingPicFile[2],2); | |
end | |
PlayMIDI(JY.Scene[JY.SubScene]["进门音乐"]); | |
JY.oldSMapX=-1; | |
JY.oldSMapY=-1; | |
JY.SubSceneX=0; | |
JY.SubSceneY=0; | |
JY.OldDPass=-1; | |
JY.D_Valid=nil; | |
DrawSMap(); | |
lib.ShowSlow(50,0) | |
lib.GetKey(); | |
if showname==1 then | |
DrawStrBox(-1,10,JY.Scene[JY.SubScene]["名称"],C_WHITE,CC.DefaultFont); | |
ShowScreen(); | |
WaitKey(); | |
Cls(); | |
ShowScreen(); | |
end | |
end | |
--计算贴图改变形成的Clip裁剪 | |
--(dx1,dy1) 新贴图和绘图中心点的坐标偏移。在场景中,视角不同而主角动时用到 | |
--pic1 旧的贴图编号 | |
--id1 贴图文件加载编号 | |
--(dx2,dy2) 新贴图和绘图中心点的偏移 | |
--pic2 旧的贴图编号 | |
--id2 贴图文件加载编号 | |
--返回,裁剪矩形 {x1,y1,x2,y2} | |
function Cal_PicClip(dx1,dy1,pic1,id1,dx2,dy2,pic2,id2) --计算贴图改变形成的Clip裁剪 | |
local w1,h1,x1_off,y1_off=lib.PicGetXY(id1,pic1*2); | |
local old_r={}; | |
old_r.x1=CC.XScale*(dx1-dy1)+CC.ScreenW/2-x1_off; | |
old_r.y1=CC.YScale*(dx1+dy1)+CC.ScreenH/2-y1_off; | |
old_r.x2=old_r.x1+w1; | |
old_r.y2=old_r.y1+h1; | |
local w2,h2,x2_off,y2_off=lib.PicGetXY(id2,pic2*2); | |
local new_r={}; | |
new_r.x1=CC.XScale*(dx2-dy2)+CC.ScreenW/2-x2_off; | |
new_r.y1=CC.YScale*(dx2+dy2)+CC.ScreenH/2-y2_off; | |
new_r.x2=new_r.x1+w2; | |
new_r.y2=new_r.y1+h2; | |
return MergeRect(old_r,new_r); | |
end | |
function MergeRect(r1,r2) --合并矩形 | |
local res={}; | |
res.x1=math.min(r1.x1, r2.x1); | |
res.y1=math.min(r1.y1, r2.y1); | |
res.x2=math.max(r1.x2, r2.x2); | |
res.y2=math.max(r1.y2, r2.y2); | |
return res; | |
end | |
----对矩形进行屏幕剪裁 | |
--返回剪裁后的矩形,如果超出屏幕,返回空 | |
function ClipRect(r) --对矩形进行屏幕剪裁 | |
if r.x1>=CC.ScreenW or r.x2<= 0 or r.y1>=CC.ScreenH or r.y2 <=0 then | |
return nil | |
else | |
local res={}; | |
res.x1=limitX(r.x1,0,CC.ScreenW); | |
res.x2=limitX(r.x2,0,CC.ScreenW); | |
res.y1=limitX(r.y1,0,CC.ScreenH); | |
res.y2=limitX(r.y2,0,CC.ScreenH); | |
return res; | |
end | |
end | |
function GetMyPic() --计算主角当前贴图 | |
local n; | |
if JY.Status==GAME_MMAP and JY.Base["乘船"]==1 then | |
if JY.MyCurrentPic >=4 then | |
JY.MyCurrentPic=0 | |
end | |
else | |
if JY.MyCurrentPic >6 then | |
JY.MyCurrentPic=1 | |
end | |
end | |
if JY.Base["乘船"]==0 then | |
n=CC.MyStartPic+JY.Base["人方向"]*7+JY.MyCurrentPic; | |
else | |
n=CC.BoatStartPic+JY.Base["人方向"]*4+JY.MyCurrentPic; | |
end | |
return n; | |
end | |
--增加当前主角走路动画帧, 主地图和场景地图都使用 | |
function AddMyCurrentPic() ---增加当前主角走路动画帧, | |
JY.MyCurrentPic=JY.MyCurrentPic+1; | |
end | |
--场景是否可进 | |
--id 场景代号 | |
--x,y 当前主地图坐标 | |
--返回:场景id,-1表示没有场景可进 | |
function CanEnterScene(x,y) --场景是否可进 | |
if JY.EnterSceneXY==nil then --如果为空,则重新产生数据。 | |
Cal_EnterSceneXY(); | |
end | |
local id=JY.EnterSceneXY[y*CC.MWidth+x]; | |
if id~=nil then | |
local e=JY.Scene[id]["进入条件"]; | |
if e==0 then --可进 | |
return id; | |
elseif e==1 then --不可进 | |
return -1 | |
elseif e==2 then --有轻功高者进 | |
for i=1,CC.TeamNum do | |
local pid=JY.Base["队伍" .. i]; | |
if pid>=0 then | |
if JY.Person[pid]["轻功"]>=70 then | |
return id; | |
end | |
end | |
end | |
end | |
end | |
return -1; | |
end | |
function Cal_EnterSceneXY() --计算哪些坐标可以进入场景 | |
JY.EnterSceneXY={}; | |
for id = 0,JY.SceneNum-1 do | |
local scene=JY.Scene[id]; | |
if scene["外景入口X1"]>0 and scene["外景入口Y1"] then | |
JY.EnterSceneXY[scene["外景入口Y1"]*CC.MWidth+scene["外景入口X1"]]=id; | |
end | |
if scene["外景入口X2"]>0 and scene["外景入口Y2"] then | |
JY.EnterSceneXY[scene["外景入口Y2"]*CC.MWidth+scene["外景入口X2"]]=id; | |
end | |
end | |
end | |
--主菜单 | |
function MMenu() --主菜单 | |
local menu={ {"医疗",Menu_Doctor,1}, | |
{"解毒",Menu_DecPoison,1}, | |
{"物品",Menu_Thing,1}, | |
{"状态",Menu_Status,1}, | |
{"离队",Menu_PersonExit,1}, | |
{"系统",Menu_System,1}, }; | |
if JY.Status==GAME_SMAP then --子场景,后两个菜单不可见 | |
menu[5][3]=0; | |
menu[6][3]=0; | |
end | |
ShowMenu(menu,6,0,CC.MainMenuX,CC.MainMenuY,0,0,1,1,CC.DefaultFont,C_ORANGE, C_WHITE) | |
end | |
--系统子菜单 | |
function Menu_System() --系统子菜单 | |
local menu={ {"读取进度",Menu_ReadRecord,1}, | |
{"保存进度",Menu_SaveRecord,1}, | |
{"离开游戏",Menu_Exit,1}, }; | |
local r=ShowMenu(menu,3,0,CC.MainSubMenuX,CC.MainSubMenuY,0,0,1,1,CC.DefaultFont,C_ORANGE, C_WHITE); | |
if r == 0 then | |
return 0; | |
elseif r<0 then --要退出全部菜单, | |
return 1; | |
end | |
end | |
--离开菜单 | |
function Menu_Exit() --离开菜单 | |
Cls(); | |
if DrawStrBoxYesNo(-1,-1,"是否真的要离开游戏?",C_WHITE,CC.DefaultFont) == true then | |
JY.Status =GAME_END; | |
end | |
return 1; | |
end | |
--保存进度 | |
function Menu_SaveRecord() --保存进度菜单 | |
local menu={ {"进度一",nil,1}, | |
{"进度二",nil,1}, | |
{"进度三",nil,1}, }; | |
local r=ShowMenu(menu,3,0,CC.MainSubMenuX2,CC.MainSubMenuY,0,0,1,1,CC.DefaultFont,C_ORANGE, C_WHITE); | |
if r>0 then | |
DrawStrBox(CC.MainSubMenuX2,CC.MainSubMenuY,"请稍候......",C_WHITE,CC.DefaultFont); | |
ShowScreen(); | |
SaveRecord(r); | |
Cls(CC.MainSubMenuX2,CC.MainSubMenuY,CC.ScreenW,CC.ScreenH); | |
end | |
return 0; | |
end | |
--读取进度 | |
function Menu_ReadRecord() --读取进度菜单 | |
local menu={ {"进度一",nil,1}, | |
{"进度二",nil,1}, | |
{"进度三",nil,1}, }; | |
local r=ShowMenu(menu,3,0,CC.MainSubMenuX2,CC.MainSubMenuY,0,0,1,1,CC.DefaultFont,C_ORANGE, C_WHITE); | |
if r == 0 then | |
return 0; | |
elseif r>0 then | |
DrawStrBox(CC.MainSubMenuX2,CC.MainSubMenuY,"请稍候......",C_WHITE,CC.DefaultFont); | |
ShowScreen(); | |
LoadRecord(r); | |
JY.Status=GAME_FIRSTMMAP; | |
return 1; | |
end | |
end | |
--状态子菜单 | |
function Menu_Status() --状态子菜单 | |
DrawStrBox(CC.MainSubMenuX,CC.MainSubMenuY,"要查阅谁的状态",C_WHITE,CC.DefaultFont); | |
local nexty=CC.MainSubMenuY+CC.SingleLineHeight; | |
local r=SelectTeamMenu(CC.MainSubMenuX,nexty); | |
if r >0 then | |
ShowPersonStatus(r) | |
return 1; | |
else | |
Cls(); | |
return 0; | |
end | |
end | |
--离队Exit | |
function Menu_PersonExit() --离队Exit | |
DrawStrBox(CC.MainSubMenuX,CC.MainSubMenuY,"要求谁离队",C_WHITE,CC.DefaultFont); | |
local nexty=CC.MainSubMenuY+CC.SingleLineHeight; | |
local r=SelectTeamMenu(CC.MainSubMenuX,nexty); | |
if r==1 then | |
DrawStrBoxWaitKey("抱歉!没有你游戏进行不下去",C_WHITE,CC.DefaultFont,1); | |
elseif r>1 then | |
local personid=JY.Base["队伍" .. r]; | |
for i,v in ipairs(CC.PersonExit) do --在离队列表中调用离队函数 | |
if personid==v[1] then | |
oldCallEvent(v[2]); | |
end | |
end | |
end | |
Cls(); | |
return 0; | |
end | |
--队伍选择人物菜单 | |
function SelectTeamMenu(x,y) --队伍选择人物菜单 | |
local menu={}; | |
for i=1,CC.TeamNum do | |
menu[i]={"",nil,0}; | |
local id=JY.Base["队伍" .. i] | |
if id>=0 then | |
if JY.Person[id]["生命"]>0 then | |
menu[i][1]=JY.Person[id]["姓名"]; | |
menu[i][3]=1; | |
end | |
end | |
end | |
return ShowMenu(menu,CC.TeamNum,0,x,y,0,0,1,1,CC.DefaultFont,C_ORANGE, C_WHITE); | |
end | |
function GetTeamNum() --得到队友个数 | |
local r=CC.TeamNum; | |
for i=1,CC.TeamNum do | |
if JY.Base["队伍" .. i]<0 then | |
r=i-1; | |
break; | |
end | |
end | |
return r; | |
end | |
---显示队友状态 | |
-- 左右键翻页,上下键换队友 | |
function ShowPersonStatus(teamid)---显示队友状态 | |
local page=1; | |
local pagenum=2; | |
local teamnum=GetTeamNum(); | |
while true do | |
Cls(); | |
local id=JY.Base["队伍" .. teamid]; | |
ShowPersonStatus_sub(id,page); | |
ShowScreen(); | |
local keypress=WaitKey(); | |
lib.Delay(100); | |
if keypress==VK_ESCAPE then | |
break; | |
elseif keypress==VK_UP then | |
teamid=teamid-1; | |
elseif keypress==VK_DOWN then | |
teamid=teamid+1; | |
elseif keypress==VK_LEFT then | |
page=page-1; | |
elseif keypress==VK_RIGHT then | |
page=page+1; | |
end | |
teamid=limitX(teamid,1,teamnum); | |
page=limitX(page,1,pagenum); | |
end | |
end | |
--id 人物编号 | |
--page 显示页数,目前共两页 | |
function ShowPersonStatus_sub(id,page) --显示人物状态页面 | |
local size=CC.DefaultFont; --字体大小 | |
local p=JY.Person[id]; | |
local width=18*size+15; --18个汉字字符宽 | |
local h=size+CC.PersonStateRowPixel; | |
local height=13*h+10; --12个汉字字符高 | |
local dx=(CC.ScreenW-width)/2; | |
local dy=(CC.ScreenH-height)/2; | |
local i=1; | |
local x1,y1,x2; | |
DrawBox(dx,dy,dx+width,dy+height,C_WHITE); | |
x1=dx+5; | |
y1=dy+5; | |
x2=4*size; | |
local headw,headh=lib.PicGetXY(1,p["头像代号"]*2); | |
local headx=(width/2-headw)/2; | |
local heady=(h*6-headh)/2; | |
lib.PicLoadCache(1,p["头像代号"]*2,x1+headx,y1+heady,1); | |
i=6; | |
DrawString(x1,y1+h*i,p["姓名"],C_WHITE,size); | |
DrawString(x1+10*size/2,y1+h*i,string.format("%3d",p["等级"]),C_GOLD,size); | |
DrawString(x1+13*size/2,y1+h*i,"级",C_ORANGE,size); | |
local function DrawAttrib(str,color1,color2,v) --定义内部函数 | |
v=v or 0; | |
DrawString(x1,y1+h*i,str,color1,size); | |
DrawString(x1+x2,y1+h*i,string.format("%5d",p[str]+v),color2,size); | |
i=i+1; | |
end | |
if page==1 then | |
local color; --显示生命和最大值,根据受伤和中毒显示不同颜色 | |
if p["受伤程度"]<33 then | |
color =RGB(236,200,40); | |
elseif p["受伤程度"]<66 then | |
color=RGB(244,128,32); | |
else | |
color=RGB(232,32,44); | |
end | |
i=i+1; | |
DrawString(x1,y1+h*i,"生命",C_ORANGE,size); | |
DrawString(x1+2*size,y1+h*i,string.format("%5d",p["生命"]),color,size); | |
DrawString(x1+9*size/2,y1+h*i,"/",C_GOLD,size); | |
if p["中毒程度"]==0 then | |
color =RGB(252,148,16); | |
elseif p["中毒程度"]<50 then | |
color=RGB(120,208,88); | |
else | |
color=RGB(56,136,36); | |
end | |
DrawString(x1+5*size,y1+h*i,string.format("%5s",p["生命最大值"]),color,size); | |
i=i+1; --显示内力和最大值,根据内力性质显示不同颜色 | |
if p["内力性质"]==0 then | |
color=RGB(208,152,208); | |
elseif p["内力性质"]==1 then | |
color=RGB(236,200,40); | |
else | |
color=RGB(236,236,236); | |
end | |
DrawString(x1,y1+h*i,"内力",C_ORANGE,size); | |
DrawString(x1+2*size,y1+h*i,string.format("%5d/%5d",p["内力"],p["内力最大值"]),color,size); | |
i=i+1; | |
DrawAttrib("体力",C_ORANGE,C_GOLD) | |
DrawAttrib("经验",C_ORANGE,C_GOLD) | |
local tmp; | |
if p["等级"] >=CC.Level then | |
tmp="="; | |
else | |
tmp=string.format("%5d",CC.Exp[p["等级"]]); | |
end | |
DrawString(x1,y1+h*i,"升级",C_ORANGE,size); | |
DrawString(x1+x2,y1+h*i,tmp,C_GOLD,size); | |
local tmp1,tmp2,tmp3=0,0,0; | |
if p["武器"]>-1 then | |
tmp1=tmp1+JY.Thing[p["武器"]]["加攻击力"]; | |
tmp2=tmp2+JY.Thing[p["武器"]]["加防御力"]; | |
tmp3=tmp3+JY.Thing[p["武器"]]["加轻功"]; | |
end | |
if p["防具"]>-1 then | |
tmp1=tmp1+JY.Thing[p["防具"]]["加攻击力"]; | |
tmp2=tmp2+JY.Thing[p["防具"]]["加防御力"]; | |
tmp3=tmp3+JY.Thing[p["防具"]]["加轻功"]; | |
end | |
i=i+1; | |
DrawString(x1,y1+h*i,"左右键翻页,上下键查看其它队友",C_RED,size); | |
i=0; | |
x1=dx+width/2; | |
DrawAttrib("攻击力",C_WHITE,C_GOLD,tmp1); | |
DrawAttrib("防御力",C_WHITE,C_GOLD,tmp2); | |
DrawAttrib("轻功",C_WHITE,C_GOLD,tmp3); | |
DrawAttrib("医疗能力",C_WHITE,C_GOLD); | |
DrawAttrib("用毒能力",C_WHITE,C_GOLD); | |
DrawAttrib("解毒能力",C_WHITE,C_GOLD); | |
DrawAttrib("拳掌功夫",C_WHITE,C_GOLD); | |
DrawAttrib("御剑能力",C_WHITE,C_GOLD); | |
DrawAttrib("耍刀技巧",C_WHITE,C_GOLD); | |
DrawAttrib("特殊兵器",C_WHITE,C_GOLD); | |
DrawAttrib("暗器技巧",C_WHITE,C_GOLD); | |
DrawAttrib("资质",C_WHITE,C_GOLD); | |
elseif page==2 then | |
i=i+1; | |
DrawString(x1,y1+h*i,"武器:",C_ORANGE,size); | |
if p["武器"]>-1 then | |
DrawString(x1+size*3,y1+h*i,JY.Thing[p["武器"]]["名称"],C_GOLD,size); | |
end | |
i=i+1; | |
DrawString(x1,y1+h*i,"防具:",C_ORANGE,size); | |
if p["防具"]>-1 then | |
DrawString(x1+size*3,y1+h*i,JY.Thing[p["防具"]]["名称"],C_GOLD,size); | |
end | |
i=i+1; | |
DrawString(x1,y1+h*i,"修炼物品",C_ORANGE,size); | |
local thingid=p["修炼物品"]; | |
if thingid>0 then | |
i=i+1; | |
DrawString(x1+size,y1+h*i,JY.Thing[thingid]["名称"],C_GOLD,size); | |
i=i+1; | |
local n=TrainNeedExp(id); | |
if n <math.huge then | |
DrawString(x1+size,y1+h*i,string.format("%5d/%5d",p["修炼点数"],n),C_GOLD,size); | |
else | |
DrawString(x1+size,y1+h*i,string.format("%5d/===",p["修炼点数"]),C_GOLD,size); | |
end | |
else | |
i=i+2; | |
end | |
i=i+1; | |
DrawString(x1,y1+h*i,"左右键翻页,上下键查看其它队友",C_RED,size); | |
i=0; | |
x1=dx+width/2; | |
DrawString(x1,y1+h*i,"所会功夫",C_ORANGE,size); | |
for j=1,10 do | |
i=i+1 | |
local wugong=p["武功" .. j]; | |
if wugong > 0 then | |
local level=math.modf(p["武功等级" .. j] / 100)+1; | |
DrawString(x1+size,y1+h*i,string.format("%s",JY.Wugong[wugong]["名称"]),C_GOLD,size); | |
DrawString(x1+size*7,y1+h*i,string.format("%2d",level),C_WHITE,size); | |
end | |
end | |
end | |
end | |
--计算人物修炼成功需要的点数 | |
--id 人物id | |
function TrainNeedExp(id) --计算人物修炼物品成功需要的点数 | |
local thingid=JY.Person[id]["修炼物品"]; | |
local r =0; | |
if thingid >= 0 then | |
if JY.Thing[thingid]["练出武功"] >=0 then | |
local level=0; --此处的level是实际level-1。这样没有武功時和炼成一级是一样的。 | |
for i =1,10 do -- 查找当前已经炼成武功等级 | |
if JY.Person[id]["武功" .. i]==JY.Thing[thingid]["练出武功"] then | |
level=math.modf(JY.Person[id]["武功等级" .. i] /100); | |
break; | |
end | |
end | |
if level <9 then | |
r=(7-math.modf(JY.Person[id]["资质"]/15))*JY.Thing[thingid]["需经验"]*(level+1); | |
else | |
r=math.huge; | |
end | |
else | |
r=(7-math.modf(JY.Person[id]["资质"]/15))*JY.Thing[thingid]["需经验"]*2; | |
end | |
end | |
return r; | |
end | |
--医疗菜单 | |
function Menu_Doctor() --医疗菜单 | |
DrawStrBox(CC.MainSubMenuX,CC.MainSubMenuY,"谁要使用医术",C_WHITE,CC.DefaultFont); | |
local nexty=CC.MainSubMenuY+CC.SingleLineHeight; | |
DrawStrBox(CC.MainSubMenuX,nexty,"医疗能力",C_ORANGE,CC.DefaultFont); | |
local menu1={}; | |
for i=1,CC.TeamNum do | |
menu1[i]={"",nil,0}; | |
local id=JY.Base["队伍" .. i] | |
if id >=0 then | |
if JY.Person[id]["医疗能力"]>=20 then | |
menu1[i][1]=string.format("%-10s%4d",JY.Person[id]["姓名"],JY.Person[id]["医疗能力"]); | |
menu1[i][3]=1; | |
end | |
end | |
end | |
local id1,id2; | |
nexty=nexty+CC.SingleLineHeight; | |
local r=ShowMenu(menu1,CC.TeamNum,0,CC.MainSubMenuX,nexty,0,0,1,1,CC.DefaultFont,C_ORANGE, C_WHITE); | |
if r >0 then | |
id1=JY.Base["队伍" .. r]; | |
Cls(CC.MainSubMenuX,CC.MainSubMenuY,CC.ScreenW,CC.ScreenH); | |
DrawStrBox(CC.MainSubMenuX,CC.MainSubMenuY,"要医治谁",C_WHITE,CC.DefaultFont); | |
nexty=CC.MainSubMenuY+CC.SingleLineHeight; | |
local menu2={}; | |
for i=1,CC.TeamNum do | |
menu2[i]={"",nil,0}; | |
local id=JY.Base["队伍" .. i] | |
if id>=0 then | |
menu2[i][1]=string.format("%-10s%4d/%4d",JY.Person[id]["姓名"],JY.Person[id]["生命"],JY.Person[id]["生命最大值"]); | |
menu2[i][3]=1; | |
end | |
end | |
local r2=ShowMenu(menu2,CC.TeamNum,0,CC.MainSubMenuX,nexty,0,0,1,1,CC.DefaultFont,C_ORANGE,C_WHITE); | |
if r2 >0 then | |
id2=JY.Base["队伍" .. r2]; | |
local num=ExecDoctor(id1,id2); | |
if num>0 then | |
AddPersonAttrib(id1,"体力",-2); | |
end | |
DrawStrBoxWaitKey(string.format("%s 生命增加 %d",JY.Person[id2]["姓名"],num),C_ORANGE,CC.DefaultFont); | |
end | |
end | |
Cls(); | |
return 0; | |
end | |
--执行医疗 | |
--id1 医疗id2, 返回id2生命增加点数 | |
function ExecDoctor(id1,id2) --执行医疗 | |
if JY.Person[id1]["体力"]<50 then | |
return 0; | |
end | |
local add=JY.Person[id1]["医疗能力"]; | |
local value=JY.Person[id2]["受伤程度"]; | |
if value > add+20 then | |
return 0; | |
end | |
if value <25 then --根据受伤程度计算实际医疗能力 | |
add=add*4/5; | |
elseif value <50 then | |
add=add*3/4; | |
elseif value <75 then | |
add=add*2/3; | |
else | |
add=add/2; | |
end | |
add=math.modf(add)+Rnd(5); | |
AddPersonAttrib(id2,"受伤程度",-add); | |
return AddPersonAttrib(id2,"生命",add) | |
end | |
--解毒 | |
function Menu_DecPoison() --解毒 | |
DrawStrBox(CC.MainSubMenuX,CC.MainSubMenuY,"谁要帮人解毒",C_WHITE,CC.DefaultFont); | |
local nexty=CC.MainSubMenuY+CC.SingleLineHeight; | |
DrawStrBox(CC.MainSubMenuX,nexty,"解毒能力",C_ORANGE,CC.DefaultFont); | |
local menu1={}; | |
for i=1,CC.TeamNum do | |
menu1[i]={"",nil,0}; | |
local id=JY.Base["队伍" .. i] | |
if id>=0 then | |
if JY.Person[id]["解毒能力"]>=20 then | |
menu1[i][1]=string.format("%-10s%4d",JY.Person[id]["姓名"],JY.Person[id]["解毒能力"]); | |
menu1[i][3]=1; | |
end | |
end | |
end | |
local id1,id2; | |
nexty=nexty+CC.SingleLineHeight; | |
local r=ShowMenu(menu1,CC.TeamNum,0,CC.MainSubMenuX,nexty,0,0,1,1,CC.DefaultFont,C_ORANGE, C_WHITE); | |
if r >0 then | |
id1=JY.Base["队伍" .. r]; | |
Cls(CC.MainSubMenuX,CC.MainSubMenuY,CC.ScreenW,CC.ScreenH); | |
DrawStrBox(CC.MainSubMenuX,CC.MainSubMenuY,"替谁解毒",C_WHITE,CC.DefaultFont); | |
nexty=CC.MainSubMenuY+CC.SingleLineHeight; | |
DrawStrBox(CC.MainSubMenuX,nexty,"中毒程度",C_WHITE,CC.DefaultFont); | |
nexty=nexty+CC.SingleLineHeight; | |
local menu2={}; | |
for i=1,CC.TeamNum do | |
menu2[i]={"",nil,0}; | |
local id=JY.Base["队伍" .. i] | |
if id>=0 then | |
menu2[i][1]=string.format("%-10s%5d",JY.Person[id]["姓名"],JY.Person[id]["中毒程度"]); | |
menu2[i][3]=1; | |
end | |
end | |
local r2=ShowMenu(menu2,CC.TeamNum,0,CC.MainSubMenuX,nexty,0,0,1,1,CC.DefaultFont,C_ORANGE, C_WHITE); | |
if r2 >0 then | |
id2=JY.Base["队伍" .. r2]; | |
local num=ExecDecPoison(id1,id2); | |
DrawStrBoxWaitKey(string.format("%s 中毒程度减少 %d",JY.Person[id2]["姓名"],num),C_ORANGE,CC.DefaultFont); | |
end | |
end | |
Cls(); | |
return 0; | |
end | |
--解毒 | |
--id1 解毒id2, 返回id2中毒减少点数 | |
function ExecDecPoison(id1,id2) --执行解毒 | |
local add=JY.Person[id1]["解毒能力"]; | |
local value=JY.Person[id2]["中毒程度"]; | |
if value > add+20 then | |
return 0; | |
end | |
add=limitX(math.modf(add/3)+Rnd(10)-Rnd(10),0,value); | |
return -AddPersonAttrib(id2,"中毒程度",-add); | |
end | |
--物品菜单 | |
function Menu_Thing() --物品菜单 | |
local menu={ {"全部物品",nil,1}, | |
{"剧情物品",nil,1}, | |
{"神兵宝甲",nil,1}, | |
{"武功秘笈",nil,1}, | |
{"灵丹妙药",nil,1}, | |
{"伤人暗器",nil,1}, }; | |
local r=ShowMenu(menu,CC.TeamNum,0,CC.MainSubMenuX,CC.MainSubMenuY,0,0,1,1,CC.DefaultFont,C_ORANGE, C_WHITE); | |
if r>0 then | |
local thing={}; | |
local thingnum={}; | |
for i = 0,CC.MyThingNum-1 do | |
thing[i]=-1; | |
thingnum[i]=0; | |
end | |
local num=0 | |
for i = 0,CC.MyThingNum-1 do | |
local id=JY.Base["物品" .. i+1]; | |
if id>=0 then | |
if r==1 then | |
thing[i]=id | |
thingnum[i]=JY.Base["物品数量" ..i+1]; | |
else | |
if JY.Thing[id]["类型"]==r-2 then --对应于类型0-4 | |
thing[num]=id; | |
thingnum[num]=JY.Base["物品数量" ..i+1]; | |
num=num+1; | |
end | |
end | |
end | |
end | |
local r=SelectThing(thing,thingnum); | |
if r>=0 then | |
UseThing(r); --使用物品 | |
return 1; --退出主菜单 | |
end | |
end | |
return 0; | |
end | |
--新的显示物品菜单,模仿原游戏 | |
--显示物品菜单 | |
--返回选择的物品编号, -1表示没有选择 | |
function SelectThing(thing,thingnum) --显示物品菜单 | |
local xnum=CC.MenuThingXnum; | |
local ynum=CC.MenuThingYnum; | |
local w=CC.ThingPicWidth*xnum+(xnum-1)*CC.ThingGapIn+2*CC.ThingGapOut; --总体宽度 | |
local h=CC.ThingPicHeight*ynum+(ynum-1)*CC.ThingGapIn+2*CC.ThingGapOut; --物品栏高度 | |
local dx=(CC.ScreenW-w)/2; | |
local dy=(CC.ScreenH-h-2*(CC.ThingFontSize+2*CC.MenuBorderPixel+5))/2; | |
local y1_1,y1_2,y2_1,y2_2,y3_1,y3_2; --名称,说明和图片的Y坐标 | |
local cur_line=0; | |
local cur_x=0; | |
local cur_y=0; | |
local cur_thing=-1; | |
while true do | |
Cls(); | |
y1_1=dy; | |
y1_2=y1_1+CC.ThingFontSize+2*CC.MenuBorderPixel; | |
DrawBox(dx,y1_1,dx+w,y1_2,C_WHITE); | |
y2_1=y1_2+5 | |
y2_2=y2_1+CC.ThingFontSize+2*CC.MenuBorderPixel | |
DrawBox(dx,y2_1,dx+w,y2_2,C_WHITE); | |
y3_1=y2_2+5; | |
y3_2=y3_1+h; | |
DrawBox(dx,y3_1,dx+w,y3_2,C_WHITE); | |
for y=0,ynum-1 do | |
for x=0,xnum-1 do | |
local id=y*xnum+x+xnum*cur_line --当前待选择物品 | |
local boxcolor; | |
if x==cur_x and y==cur_y then | |
boxcolor=C_WHITE; | |
if thing[id]>=0 then | |
cur_thing=thing[id]; | |
local str=JY.Thing[thing[id]]["名称"]; | |
if JY.Thing[thing[id]]["类型"]==1 or JY.Thing[thing[id]]["类型"]==2 then | |
if JY.Thing[thing[id]]["使用人"] >=0 then | |
str=str .. "(" .. JY.Person[JY.Thing[thing[id]]["使用人"]]["姓名"] .. ")"; | |
end | |
end | |
str=string.format("%s X %d",str,thingnum[id]); | |
local str2=JY.Thing[thing[id]]["物品说明"]; | |
DrawString(dx+CC.ThingGapOut,y1_1+CC.MenuBorderPixel,str,C_GOLD,CC.ThingFontSize); | |
DrawString(dx+CC.ThingGapOut,y2_1+CC.MenuBorderPixel,str2,C_ORANGE,CC.ThingFontSize); | |
else | |
cur_thing=-1; | |
end | |
else | |
boxcolor=C_BLACK; | |
end | |
local boxx=dx+CC.ThingGapOut+x*(CC.ThingPicWidth+CC.ThingGapIn); | |
local boxy=y3_1+CC.ThingGapOut+y*(CC.ThingPicHeight+CC.ThingGapIn); | |
lib.DrawRect(boxx,boxy,boxx+CC.ThingPicWidth+1,boxy+CC.ThingPicHeight+1,boxcolor); | |
if thing[id]>=0 then | |
if CC.LoadThingPic==1 then | |
lib.PicLoadCache(2,thing[id]*2,boxx+1,boxy+1,1); | |
else | |
lib.PicLoadCache(0,(thing[id]+CC.StartThingPic)*2,boxx+1,boxy+1,1); | |
end | |
end | |
end | |
end | |
ShowScreen(); | |
local keypress=WaitKey(); | |
lib.Delay(100); | |
if keypress==VK_ESCAPE then | |
cur_thing=-1; | |
break; | |
elseif keypress==VK_RETURN or keypress==VK_SPACE then | |
break; | |
elseif keypress==VK_UP then | |
if cur_y == 0 then | |
if cur_line > 0 then | |
cur_line = cur_line - 1; | |
end | |
else | |
cur_y = cur_y - 1; | |
end | |
elseif keypress==VK_DOWN then | |
if cur_y ==ynum-1 then | |
if cur_line < (math.modf(200/xnum)-ynum) then | |
cur_line = cur_line + 1; | |
end | |
else | |
cur_y = cur_y + 1; | |
end | |
elseif keypress==VK_LEFT then | |
if cur_x > 0 then | |
cur_x=cur_x-1; | |
else | |
cur_x=xnum-1; | |
end | |
elseif keypress==VK_RIGHT then | |
if cur_x ==xnum-1 then | |
cur_x=0; | |
else | |
cur_x=cur_x+1; | |
end | |
end | |
end | |
Cls(); | |
return cur_thing; | |
end | |
--场景处理主函数 | |
function Game_SMap() --场景处理主函数 | |
DrawSMap(CONFIG.FastShowScreen); | |
if CC.ShowXY==1 then | |
DrawString(10,CC.ScreenH-20,string.format("%s %d %d",JY.Scene[JY.SubScene]["名称"],JY.Base["人X1"],JY.Base["人Y1"]) ,C_GOLD,16); | |
end | |
ShowScreen(CONFIG.FastShowScreen); | |
lib.SetClip(0,0,0,0); | |
local d_pass=GetS(JY.SubScene,JY.Base["人X1"],JY.Base["人Y1"],3); --当前路过事件 | |
if d_pass>=0 then | |
if d_pass ~=JY.OldDPass then --避免重复触发 | |
EventExecute(d_pass,3); --路过触发事件 | |
JY.OldDPass=d_pass; | |
JY.oldSMapX=-1; | |
JY.oldSMapY=-1; | |
JY.D_Valid=nil; | |
end | |
else | |
JY.OldDPass=-1; | |
end | |
local isout=0; --是否碰到出口 | |
if (JY.Scene[JY.SubScene]["出口X1"] ==JY.Base["人X1"] and JY.Scene[JY.SubScene]["出口Y1"] ==JY.Base["人Y1"]) or | |
(JY.Scene[JY.SubScene]["出口X2"] ==JY.Base["人X1"] and JY.Scene[JY.SubScene]["出口Y2"] ==JY.Base["人Y1"]) or | |
(JY.Scene[JY.SubScene]["出口X3"] ==JY.Base["人X1"] and JY.Scene[JY.SubScene]["出口Y3"] ==JY.Base["人Y1"]) then | |
isout=1; | |
end | |
if isout==1 then --出去,返回主地图 | |
JY.Status=GAME_MMAP; | |
lib.PicInit(); | |
CleanMemory(); | |
lib.ShowSlow(50,1) | |
if JY.MMAPMusic<0 then | |
JY.MMAPMusic=JY.Scene[JY.SubScene]["出门音乐"]; | |
end | |
Init_MMap(); | |
JY.SubScene=-1; | |
JY.oldSMapX=-1; | |
JY.oldSMapY=-1; | |
lib.DrawMMap(JY.Base["人X"],JY.Base["人Y"],GetMyPic()); | |
lib.ShowSlow(50,0) | |
lib.GetKey(); | |
return; | |
end | |
--是否跳转到其他场景 | |
if JY.Scene[JY.SubScene]["跳转场景"] >=0 then | |
if JY.Base["人X1"]==JY.Scene[JY.SubScene]["跳转口X1"] and JY.Base["人Y1"]==JY.Scene[JY.SubScene]["跳转口Y1"] then | |
JY.SubScene=JY.Scene[JY.SubScene]["跳转场景"]; | |
lib.ShowSlow(50,1); | |
if JY.Scene[JY.SubScene]["外景入口X1"]==0 and JY.Scene[JY.SubScene]["外景入口Y1"]==0 then | |
JY.Base["人X1"]=JY.Scene[JY.SubScene]["入口X"]; --新场景的外景入口为0,表示这是一个内部场景 | |
JY.Base["人Y1"]=JY.Scene[JY.SubScene]["入口Y"]; | |
else | |
JY.Base["人X1"]=JY.Scene[JY.SubScene]["跳转口X2"]; --外部场景,即从其他内部场景跳回。 | |
JY.Base["人Y1"]=JY.Scene[JY.SubScene]["跳转口Y2"]; | |
end | |
Init_SMap(1); | |
return; | |
end | |
end | |
local x,y; | |
local keypress = lib.GetKey(); | |
local direct=-1; | |
if keypress ~= -1 then | |
JY.MyTick=0; | |
if keypress==VK_ESCAPE then | |
MMenu(); | |
JY.oldSMapX=-1; | |
JY.oldSMapY=-1; | |
elseif keypress==VK_UP then | |
direct=0; | |
elseif keypress==VK_DOWN then | |
direct=3; | |
elseif keypress==VK_LEFT then | |
direct=2; | |
elseif keypress==VK_RIGHT then | |
direct=1; | |
elseif keypress==VK_SPACE or keypress==VK_RETURN then | |
if JY.Base["人方向"]>=0 then --当前方向下一个位置 | |
local d_num=GetS(JY.SubScene,JY.Base["人X1"]+CC.DirectX[JY.Base["人方向"]+1],JY.Base["人Y1"]+CC.DirectY[JY.Base["人方向"]+1],3); | |
if d_num>=0 then | |
EventExecute(d_num,1); --空格触发事件 | |
JY.oldSMapX=-1; | |
JY.oldSMapY=-1; | |
JY.D_Valid=nil; | |
end | |
end | |
end | |
end | |
if JY.Status~=GAME_SMAP then | |
return ; | |
end | |
if direct ~= -1 then | |
AddMyCurrentPic(); | |
x=JY.Base["人X1"]+CC.DirectX[direct+1]; | |
y=JY.Base["人Y1"]+CC.DirectY[direct+1]; | |
JY.Base["人方向"]=direct; | |
else | |
x=JY.Base["人X1"]; | |
y=JY.Base["人Y1"]; | |
end | |
JY.MyPic=GetMyPic(); | |
DtoSMap(); | |
if SceneCanPass(x,y)==true then --新的坐标可以走过去 | |
JY.Base["人X1"]=x; | |
JY.Base["人Y1"]=y; | |
end | |
JY.Base["人X1"]=limitX(JY.Base["人X1"],1,CC.SWidth-2); | |
JY.Base["人Y1"]=limitX(JY.Base["人Y1"],1,CC.SHeight-2); | |
end | |
--场景坐标(x,y)是否可以通过 | |
--返回true,可以,false不能 | |
function SceneCanPass(x,y) --场景坐标(x,y)是否可以通过 | |
local ispass=true; --是否可以通过 | |
if GetS(JY.SubScene,x,y,1)>0 then --场景层1有物品,不可通过 | |
ispass=false; | |
end | |
local d_data=GetS(JY.SubScene,x,y,3); --事件层4 | |
if d_data>=0 then | |
if GetD(JY.SubScene,d_data,0)~=0 then --d*数据为不能通过 | |
ispass=false; | |
end | |
end | |
if CC.SceneWater[GetS(JY.SubScene,x,y,0)] ~= nil then --水面,不可进入 | |
ispass=false; | |
end | |
return ispass; | |
end | |
function Cal_D_Valid() --计算200个D中有效的D | |
if JY.D_Valid~=nil then | |
return ; | |
end | |
local sceneid=JY.SubScene; | |
JY.D_Valid={}; | |
JY.D_Valid_Num=0; | |
for i=0,CC.DNum-1 do | |
local x=GetD(sceneid,i,9); | |
local y=GetD(sceneid,i,10); | |
local v=GetS(sceneid,x,y,3); | |
if v>=0 then | |
JY.D_Valid[JY.D_Valid_Num]=i; | |
JY.D_Valid_Num=JY.D_Valid_Num+1; | |
end | |
end | |
end | |
function DtoSMap() ---D*中的事件处理动画效果。 | |
local sceneid=JY.SubScene; | |
JY.NumD_PicChange=0; | |
JY.D_PicChange={}; | |
if JY.D_Valid==nil then | |
Cal_D_Valid(); | |
end | |
for k=0,JY.D_Valid_Num-1 do | |
local i=JY.D_Valid[k]; | |
local p1=GetD(sceneid,i,5); | |
if p1>0 then | |
local p2=GetD(sceneid,i,6); | |
local p3=GetD(sceneid,i,7); | |
if p1 ~= p2 then | |
local old_p3=p3; | |
local delay=GetD(sceneid,i,8); | |
if not (p3>=CC.SceneFlagPic[1]*2 and p3<=CC.SceneFlagPic[2]*2 and CC.ShowFlag==0) then --是否显示旗帜 | |
if p3<=p1 then --动画已停止 | |
if JY.MyTick2 %100 > delay then | |
p3=p3+2; | |
end | |
else | |
if JY.MyTick2 % 4 ==0 then --4个节拍动画增加一次 | |
p3=p3+2; | |
end | |
end | |
if p3>p2 then | |
p3=p1; | |
end | |
end | |
if old_p3 ~=p3 then --动画改变了,增加一个 | |
local x=GetD(sceneid,i,9); | |
local y=GetD(sceneid,i,10); | |
local dy=GetS(sceneid,x,y,4); --海拔 | |
JY.D_PicChange[JY.NumD_PicChange]={x=x, y=y, dy=dy, p1=old_p3/2, p2=p3/2} | |
JY.NumD_PicChange=JY.NumD_PicChange+1; | |
SetD(sceneid,i,7,p3); | |
end | |
end | |
end | |
end | |
end | |
--fastdraw = 0 or nil 全部重绘。用于事件中 | |
-- 1 考虑脏矩形 用于显示场景循环 | |
function DrawSMap(fastdraw) --绘场景地图 | |
if fastdraw==nil then | |
fastdraw=0; | |
end | |
local x0=JY.SubSceneX+JY.Base["人X1"]-1; --绘图中心点 | |
local y0=JY.SubSceneY+JY.Base["人Y1"]-1; | |
local x=limitX(x0,CC.SceneXMin,CC.SceneXMax)-JY.Base["人X1"]; | |
local y=limitX(y0,CC.SceneYMin,CC.SceneYMax)-JY.Base["人Y1"]; | |
if fastdraw==0 then | |
lib.DrawSMap(JY.SubScene,JY.Base["人X1"],JY.Base["人Y1"],x,y,JY.MyPic); | |
else | |
if JY.oldSMapX>=0 and JY.oldSMapY>=0 and | |
JY.oldSMapX+JY.oldSMapXoff==JY.Base["人X1"]+x and --绘图中心点不变,人走路也可以用裁剪方式绘图 | |
JY.oldSMapY+JY.oldSMapYoff==JY.Base["人Y1"]+y then | |
local num_clip=0; | |
local clip={}; | |
for i=0,JY.NumD_PicChange-1 do --计算D*中贴图改变的矩形 | |
local dx=JY.D_PicChange[i].x-JY.Base["人X1"]-x; | |
local dy=JY.D_PicChange[i].y-JY.Base["人Y1"]-y; | |
clip[num_clip]=Cal_PicClip(dx,dy,JY.D_PicChange[i].p1,0, | |
dx,dy,JY.D_PicChange[i].p2,0 ); | |
clip[num_clip].y1=clip[num_clip].y1-JY.D_PicChange[i].dy | |
clip[num_clip].y2=clip[num_clip].y2-JY.D_PicChange[i].dy | |
num_clip=num_clip+1; | |
end | |
if JY.oldSMapPic>=0 then --计算主角矩形 | |
if not ( JY.oldSMapX==JY.Base["人X1"] and --主角有变化 | |
JY.oldSMapY==JY.Base["人Y1"] and | |
JY.oldSMapPic==JY.MyPic ) then | |
local dy1=GetS(JY.SubScene,JY.Base["人X1"],JY.Base["人Y1"],4); --海拔 | |
local dy2=GetS(JY.SubScene,JY.oldSMapX,JY.oldSMapY,4); | |
local dy=math.max(dy1,dy2); | |
clip[num_clip]=Cal_PicClip(-JY.oldSMapXoff,-JY.oldSMapYoff,JY.oldSMapPic,0, | |
-x,-y,JY.MyPic,0) | |
clip[num_clip].y1=clip[num_clip].y1- dy; | |
clip[num_clip].y2=clip[num_clip].y2- dy; | |
num_clip=num_clip+1; | |
end | |
end | |
local area=0; --计算所有脏矩形面积 | |
for i=0,num_clip-1 do | |
clip[i]=ClipRect(clip[i]); --矩形屏幕剪裁 | |
if clip[i]~=nil then | |
area=area+(clip[i].x2-clip[i].x1)*(clip[i].y2-clip[i].y1) | |
end | |
end | |
if area <CC.ScreenW*CC.ScreenH/2 and num_clip<15 then --面积足够小,矩形数目少,则更新脏矩形。 | |
for i=0,num_clip-1 do | |
if clip[i]~=nil then | |
lib.SetClip(clip[i].x1,clip[i].y1,clip[i].x2,clip[i].y2); | |
lib.DrawSMap(JY.SubScene,JY.Base["人X1"],JY.Base["人Y1"],x,y,JY.MyPic); | |
end | |
end | |
else --面积太大,直接重绘 | |
lib.SetClip(0,0,CC.ScreenW,CC.ScreenH); --由于redraw=0,必须给出裁剪矩形以后才能ShowSurface | |
lib.DrawSMap(JY.SubScene,JY.Base["人X1"],JY.Base["人Y1"],x,y,JY.MyPic); | |
end | |
else | |
lib.SetClip(0,0,CC.ScreenW,CC.ScreenH); | |
lib.DrawSMap(JY.SubScene,JY.Base["人X1"],JY.Base["人Y1"],x,y,JY.MyPic); | |
end | |
end | |
JY.oldSMapX=JY.Base["人X1"]; | |
JY.oldSMapY=JY.Base["人Y1"]; | |
JY.oldSMapPic=JY.MyPic; | |
JY.oldSMapXoff=x; | |
JY.oldSMapYoff=y; | |
end | |
-- 读取游戏进度 | |
-- id=0 新进度,=1/2/3 进度 | |
-- | |
--这里是先把数据读入Byte数组中。然后定义访问相应表的方法,在访问表时直接从数组访问。 | |
--与以前的实现相比,从文件中读取和保存到文件的时间显著加快。而且内存占用少了 | |
function LoadRecord(id) -- 读取游戏进度 | |
local t1=lib.GetTime(); | |
--读取R*.idx文件 | |
local data=Byte.create(6*4); | |
Byte.loadfile(data,CC.R_IDXFilename[id],0,6*4); | |
local idx={}; | |
idx[0]=0; | |
for i =1,6 do | |
idx[i]=Byte.get32(data,4*(i-1)); | |
end | |
--读取R*.grp文件 | |
JY.Data_Base=Byte.create(idx[1]-idx[0]); --基本数据 | |
Byte.loadfile(JY.Data_Base,CC.R_GRPFilename[id],idx[0],idx[1]-idx[0]); | |
--设置访问基本数据的方法,这样就可以用访问表的方式访问了。而不用把二进制数据转化为表。节约加载时间和空间 | |
local meta_t={ | |
__index=function(t,k) | |
return GetDataFromStruct(JY.Data_Base,0,CC.Base_S,k); | |
end, | |
__newindex=function(t,k,v) | |
SetDataFromStruct(JY.Data_Base,0,CC.Base_S,k,v); | |
end | |
} | |
setmetatable(JY.Base,meta_t); | |
JY.PersonNum=math.floor((idx[2]-idx[1])/CC.PersonSize); --人物 | |
JY.Data_Person=Byte.create(CC.PersonSize*JY.PersonNum); | |
Byte.loadfile(JY.Data_Person,CC.R_GRPFilename[id],idx[1],CC.PersonSize*JY.PersonNum); | |
for i=0,JY.PersonNum-1 do | |
JY.Person[i]={}; | |
local meta_t={ | |
__index=function(t,k) | |
return GetDataFromStruct(JY.Data_Person,i*CC.PersonSize,CC.Person_S,k); | |
end, | |
__newindex=function(t,k,v) | |
SetDataFromStruct(JY.Data_Person,i*CC.PersonSize,CC.Person_S,k,v); | |
end | |
} | |
setmetatable(JY.Person[i],meta_t); | |
end | |
JY.ThingNum=math.floor((idx[3]-idx[2])/CC.ThingSize); --物品 | |
JY.Data_Thing=Byte.create(CC.ThingSize*JY.ThingNum); | |
Byte.loadfile(JY.Data_Thing,CC.R_GRPFilename[id],idx[2],CC.ThingSize*JY.ThingNum); | |
for i=0,JY.ThingNum-1 do | |
JY.Thing[i]={}; | |
local meta_t={ | |
__index=function(t,k) | |
return GetDataFromStruct(JY.Data_Thing,i*CC.ThingSize,CC.Thing_S,k); | |
end, | |
__newindex=function(t,k,v) | |
SetDataFromStruct(JY.Data_Thing,i*CC.ThingSize,CC.Thing_S,k,v); | |
end | |
} | |
setmetatable(JY.Thing[i],meta_t); | |
end | |
JY.SceneNum=math.floor((idx[4]-idx[3])/CC.SceneSize); --场景 | |
JY.Data_Scene=Byte.create(CC.SceneSize*JY.SceneNum); | |
Byte.loadfile(JY.Data_Scene,CC.R_GRPFilename[id],idx[3],CC.SceneSize*JY.SceneNum); | |
for i=0,JY.SceneNum-1 do | |
JY.Scene[i]={}; | |
local meta_t={ | |
__index=function(t,k) | |
return GetDataFromStruct(JY.Data_Scene,i*CC.SceneSize,CC.Scene_S,k); | |
end, | |
__newindex=function(t,k,v) | |
SetDataFromStruct(JY.Data_Scene,i*CC.SceneSize,CC.Scene_S,k,v); | |
end | |
} | |
setmetatable(JY.Scene[i],meta_t); | |
end | |
JY.WugongNum=math.floor((idx[5]-idx[4])/CC.WugongSize); --武功 | |
JY.Data_Wugong=Byte.create(CC.WugongSize*JY.WugongNum); | |
Byte.loadfile(JY.Data_Wugong,CC.R_GRPFilename[id],idx[4],CC.WugongSize*JY.WugongNum); | |
for i=0,JY.WugongNum-1 do | |
JY.Wugong[i]={}; | |
local meta_t={ | |
__index=function(t,k) | |
return GetDataFromStruct(JY.Data_Wugong,i*CC.WugongSize,CC.Wugong_S,k); | |
end, | |
__newindex=function(t,k,v) | |
SetDataFromStruct(JY.Data_Wugong,i*CC.WugongSize,CC.Wugong_S,k,v); | |
end | |
} | |
setmetatable(JY.Wugong[i],meta_t); | |
end | |
JY.ShopNum=math.floor((idx[6]-idx[5])/CC.ShopSize); --小宝商店 | |
JY.Data_Shop=Byte.create(CC.ShopSize*JY.ShopNum); | |
Byte.loadfile(JY.Data_Shop,CC.R_GRPFilename[id],idx[5],CC.ShopSize*JY.ShopNum); | |
for i=0,JY.ShopNum-1 do | |
JY.Shop[i]={}; | |
local meta_t={ | |
__index=function(t,k) | |
return GetDataFromStruct(JY.Data_Shop,i*CC.ShopSize,CC.Shop_S,k); | |
end, | |
__newindex=function(t,k,v) | |
SetDataFromStruct(JY.Data_Shop,i*CC.ShopSize,CC.Shop_S,k,v); | |
end | |
} | |
setmetatable(JY.Shop[i],meta_t); | |
end | |
lib.LoadSMap(CC.S_Filename[id],CC.TempS_Filename,JY.SceneNum,CC.SWidth,CC.SHeight,CC.D_Filename[id],CC.DNum,11); | |
collectgarbage(); | |
lib.Debug(string.format("Loadrecord time=%d",lib.GetTime()-t1)); | |
end | |
-- 写游戏进度 | |
-- id=0 新进度,=1/2/3 进度 | |
function SaveRecord(id) -- 写游戏进度 | |
--读取R*.idx文件 | |
local t1=lib.GetTime(); | |
local data=Byte.create(6*4); | |
Byte.loadfile(data,CC.R_IDXFilename[id],0,6*4); | |
local idx={}; | |
idx[0]=0; | |
for i =1,6 do | |
idx[i]=Byte.get32(data,4*(i-1)); | |
end | |
--写R*.grp文件 | |
Byte.savefile(JY.Data_Base,CC.R_GRPFilename[id],idx[0],idx[1]-idx[0]); | |
Byte.savefile(JY.Data_Person,CC.R_GRPFilename[id],idx[1],CC.PersonSize*JY.PersonNum); | |
Byte.savefile(JY.Data_Thing,CC.R_GRPFilename[id],idx[2],CC.ThingSize*JY.ThingNum); | |
Byte.savefile(JY.Data_Scene,CC.R_GRPFilename[id],idx[3],CC.SceneSize*JY.SceneNum); | |
Byte.savefile(JY.Data_Wugong,CC.R_GRPFilename[id],idx[4],CC.WugongSize*JY.WugongNum); | |
Byte.savefile(JY.Data_Shop,CC.R_GRPFilename[id],idx[5],CC.ShopSize*JY.ShopNum); | |
lib.SaveSMap(CC.S_Filename[id],CC.D_Filename[id]); | |
lib.Debug(string.format("SaveRecord time=%d",lib.GetTime()-t1)); | |
end | |
------------------------------------------------------------------------------------- | |
-----------------------------------通用函数------------------------------------------- | |
function filelength(filename) --得到文件长度 | |
local inp=io.open(filename,"rb"); | |
local l= inp:seek("end"); | |
inp:close(); | |
return l; | |
end | |
--读S×数据, (x,y) 坐标,level 层 0-5 | |
function GetS(id,x,y,level) --读S×数据 | |
return lib.GetS(id,x,y,level); | |
end | |
--写S× | |
function SetS(id,x,y,level,v) --写S× | |
lib.SetS(id,x,y,level,v); | |
end | |
--读D* | |
--sceneid 场景编号, | |
--id D*编号 | |
--要读第几个数据, 0-10 | |
function GetD(Sceneid,id,i) --读D* | |
return lib.GetD(Sceneid,id,i); | |
end | |
--写D× | |
function SetD(Sceneid,id,i,v) --写D× | |
lib.SetD(Sceneid,id,i,v); | |
end | |
--从数据的结构中翻译数据 | |
--data 二进制数组 | |
--offset data中的偏移 | |
--t_struct 数据的结构,在jyconst中有很多定义 | |
--key 访问的key | |
function GetDataFromStruct(data,offset,t_struct,key) --从数据的结构中翻译数据,用来取数据 | |
local t=t_struct[key]; | |
local r; | |
if t[2]==0 then | |
r=Byte.get16(data,t[1]+offset); | |
elseif t[2]==1 then | |
r=Byte.getu16(data,t[1]+offset); | |
elseif t[2]==2 then | |
if CC.SrcCharSet==0 then | |
r=lib.CharSet(Byte.getstr(data,t[1]+offset,t[3]),0); | |
else | |
r=Byte.getstr(data,t[1]+offset,t[3]); | |
end | |
end | |
return r; | |
end | |
function SetDataFromStruct(data,offset,t_struct,key,v) --从数据的结构中翻译数据,保存数据 | |
local t=t_struct[key]; | |
if t[2]==0 then | |
Byte.set16(data,t[1]+offset,v); | |
elseif t[2]==1 then | |
Byte.setu16(data,t[1]+offset,v); | |
elseif t[2]==2 then | |
local s; | |
if CC.SrcCharSet==0 then | |
s=lib.CharSet(v,1); | |
else | |
s=v; | |
end | |
Byte.setstr(data,t[1]+offset,t[3],s); | |
end | |
end | |
--按照t_struct 定义的结构把数据从data二进制串中读到表t中 | |
function LoadData(t,t_struct,data) --data二进制串中读到表t中 | |
for k,v in pairs(t_struct) do | |
if v[2]==0 then | |
t[k]=Byte.get16(data,v[1]); | |
elseif v[2]==1 then | |
t[k]=Byte.getu16(data,v[1]); | |
elseif v[2]==2 then | |
if CC.SrcCharSet==0 then | |
t[k]=lib.CharSet(Byte.getstr(data,v[1],v[3]),0); | |
else | |
t[k]=Byte.getstr(data,v[1],v[3]); | |
end | |
end | |
end | |
end | |
--按照t_struct 定义的结构把数据写入data Byte数组中。 | |
function SaveData(t,t_struct,data) --数据写入data Byte数组中。 | |
for k,v in pairs(t_struct) do | |
if v[2]==0 then | |
Byte.set16(data,v[1],t[k]); | |
elseif v[2]==1 then | |
Byte.setu16(data,v[1],t[k]); | |
elseif v[2]==2 then | |
local s; | |
if CC.SrcCharSet==0 then | |
s=lib.CharSet(t[k],1); | |
else | |
s=t[k]; | |
end | |
Byte.setstr(data,v[1],v[3],s); | |
end | |
end | |
end | |
function limitX(x,minv,maxv) --限制x的范围 | |
if x<minv then | |
x=minv; | |
elseif x>maxv then | |
x=maxv; | |
end | |
return x | |
end | |
function RGB(r,g,b) --设置颜色RGB | |
return r*65536+g*256+b; | |
end | |
function GetRGB(color) --分离颜色的RGB分量 | |
color=color%(65536*256); | |
local r=math.floor(color/65536); | |
color=color%65536; | |
local g=math.floor(color/256); | |
local b=color%256; | |
return r,g,b | |
end | |
--等待键盘输入 | |
function WaitKey() --等待键盘输入 | |
local keyPress=-1; | |
while true do | |
keyPress=lib.GetKey(); | |
if keyPress ~=-1 then | |
break; | |
end | |
lib.Delay(20); | |
end | |
return keyPress; | |
end | |
--绘制一个带背景的白色方框,四角凹进 | |
function DrawBox(x1,y1,x2,y2,color) --绘制一个带背景的白色方框 | |
local s=4; | |
lib.Background(x1,y1+s,x1+s,y2-s,128); --阴影,四角空出 | |
lib.Background(x1+s,y1,x2-s,y2,128); | |
lib.Background(x2-s,y1+s,x2,y2-s,128); | |
local r,g,b=GetRGB(color); | |
DrawBox_1(x1+1,y1+1,x2,y2,RGB(math.modf(r/2),math.modf(g/2),math.modf(b/2))); | |
DrawBox_1(x1,y1,x2-1,y2-1,color); | |
end | |
--绘制四角凹进的方框 | |
function DrawBox_1(x1,y1,x2,y2,color) --绘制四角凹进的方框 | |
local s=4; | |
lib.DrawRect(x1+s,y1,x2-s,y1,color); | |
lib.DrawRect(x2-s,y1,x2-s,y1+s,color); | |
lib.DrawRect(x2-s,y1+s,x2,y1+s,color); | |
lib.DrawRect(x2,y1+s,x2,y2-s,color); | |
lib.DrawRect(x2,y2-s,x2-s,y2-s,color); | |
lib.DrawRect(x2-s,y2-s,x2-s,y2,color); | |
lib.DrawRect(x2-s,y2,x1+s,y2,color); | |
lib.DrawRect(x1+s,y2,x1+s,y2-s,color); | |
lib.DrawRect(x1+s,y2-s,x1,y2-s,color); | |
lib.DrawRect(x1,y2-s,x1,y1+s,color); | |
lib.DrawRect(x1,y1+s,x1+s,y1+s,color); | |
lib.DrawRect(x1+s,y1+s,x1+s,y1,color); | |
end | |
--显示阴影字符串 | |
function DrawString(x,y,str,color,size) --显示阴影字符串 | |
-- local r,g,b=GetRGB(color); | |
-- lib.DrawStr(x+1,y+1,str,RGB(math.modf(r/2),math.modf(g/2),math.modf(b/2)),size,CC.FontName,CC.SrcCharSet,CC.OSCharSet); | |
lib.DrawStr(x,y,str,color,size,CC.FontName,CC.SrcCharSet,CC.OSCharSet); | |
end | |
--显示带框的字符串 | |
--(x,y) 坐标,如果都为-1,则在屏幕中间显示 | |
function DrawStrBox(x,y,str,color,size) --显示带框的字符串 | |
local ll=#str; | |
local w=size*ll/2+2*CC.MenuBorderPixel; | |
local h=size+2*CC.MenuBorderPixel; | |
if x==-1 then | |
x=(CC.ScreenW-size/2*ll-2*CC.MenuBorderPixel)/2; | |
end | |
if y==-1 then | |
y=(CC.ScreenH-size-2*CC.MenuBorderPixel)/2; | |
end | |
DrawBox(x,y,x+w-1,y+h-1,C_WHITE); | |
DrawString(x+CC.MenuBorderPixel,y+CC.MenuBorderPixel,str,color,size); | |
end | |
--显示并询问Y/N,如果点击Y,则返回true, N则返回false | |
--(x,y) 坐标,如果都为-1,则在屏幕中间显示 | |
--改为用菜单询问是否 | |
function DrawStrBoxYesNo(x,y,str,color,size) --显示字符串并询问Y/N | |
lib.GetKey(); | |
local ll=#str; | |
local w=size*ll/2+2*CC.MenuBorderPixel; | |
local h=size+2*CC.MenuBorderPixel; | |
if x==-1 then | |
x=(CC.ScreenW-size/2*ll-2*CC.MenuBorderPixel)/2; | |
end | |
if y==-1 then | |
y=(CC.ScreenH-size-2*CC.MenuBorderPixel)/2; | |
end | |
DrawStrBox(x,y,str,color,size); | |
local menu={{"确定/是",nil,1}, | |
{"取消/否",nil,2}}; | |
local r=ShowMenu(menu,2,0,x+w-4*size-2*CC.MenuBorderPixel,y+h+CC.MenuBorderPixel,0,0,1,0,CC.DefaultFont,C_ORANGE, C_WHITE) | |
if r==1 then | |
return true; | |
else | |
return false; | |
end | |
end | |
--显示字符串并等待击键,字符串带框,显示在屏幕中间 | |
function DrawStrBoxWaitKey(s,color,size) --显示字符串并等待击键 | |
lib.GetKey(); | |
Cls(); | |
DrawStrBox(-1,-1,s,color,size); | |
ShowScreen(); | |
WaitKey(); | |
end | |
--返回 [0 , i-1] 的整形随机数 | |
function Rnd(i) --随机数 | |
local r=math.random(i); | |
return r-1; | |
end | |
--增加人物属性,如果有最大值限制,则应用最大值限制。最小值则限制为0 | |
--id 人物id | |
--str属性字符串 | |
--value 要增加的值,负数表示减少 | |
--返回1,实际增加的值 | |
--返回2,字符串:xxx 增加/减少 xxxx,用于显示药品效果 | |
function AddPersonAttrib(id,str,value) --增加人物属性 | |
local oldvalue=JY.Person[id][str]; | |
local attribmax=math.huge; | |
if str=="生命" then | |
attribmax=JY.Person[id]["生命最大值"] ; | |
elseif str=="内力" then | |
attribmax=JY.Person[id]["内力最大值"] ; | |
else | |
if CC.PersonAttribMax[str] ~= nil then | |
attribmax=CC.PersonAttribMax[str]; | |
end | |
end | |
local newvalue=limitX(oldvalue+value,0,attribmax); | |
JY.Person[id][str]=newvalue; | |
local add=newvalue-oldvalue; | |
local showstr=""; | |
if add>0 then | |
showstr=string.format("%s 增加 %d",str,add); | |
elseif add<0 then | |
showstr=string.format("%s 减少 %d",str,-add); | |
end | |
return add,showstr; | |
end | |
--播放midi | |
function PlayMIDI(id) --播放midi | |
JY.CurrentMIDI=id; | |
if JY.EnableMusic==0 then | |
return ; | |
end | |
if id>=0 then | |
lib.PlayMIDI(string.format(CC.MIDIFile,id+1)); | |
end | |
end | |
--播放音效atk*** | |
function PlayWavAtk(id) --播放音效atk*** | |
if JY.EnableSound==0 then | |
return ; | |
end | |
if id>=0 then | |
lib.PlayWAV(string.format(CC.ATKFile,id)); | |
end | |
end | |
--播放音效e** | |
function PlayWavE(id) --播放音效e** | |
if JY.EnableSound==0 then | |
return ; | |
end | |
if id>=0 then | |
lib.PlayWAV(string.format(CC.EFile,id)); | |
end | |
end | |
--flag =0 or nil 全部刷新屏幕 | |
-- 1 考虑脏矩形的快速刷新 | |
function ShowScreen(flag) --刷新屏幕显示 | |
if JY.Darkness==0 then | |
if flag==nil then | |
flag=0; | |
end | |
lib.ShowSurface(flag); | |
end | |
end | |
--通用菜单函数 | |
-- menuItem 表,每项保存一个子表,内容为一个菜单项的定义 | |
-- 菜单项定义为 { ItemName, 菜单项名称字符串 | |
-- ItemFunction, 菜单调用函数,如果没有则为nil | |
-- Visible 是否可见 0 不可见 1 可见, 2 可见,作为当前选择项。只能有一个为2, | |
-- 多了则只取第一个为2的,没有则第一个菜单项为当前选择项。 | |
-- 在只显示部分菜单的情况下此值无效。 | |
-- 此值目前只用于是否菜单缺省显示否的情况 | |
-- } | |
-- 菜单调用函数说明: itemfunction(newmenu,id) | |
-- | |
-- 返回值 | |
-- 0 正常返回,继续菜单循环 1 调用函数要求退出菜单,不进行菜单循环 | |
-- | |
-- numItem 总菜单项个数 | |
-- numShow 显示菜单项目,如果总菜单项很多,一屏显示不下,则可以定义此值 | |
-- =0表示显示全部菜单项 | |
-- (x1,y1),(x2,y2) 菜单区域的左上角和右下角坐标,如果x2,y2=0,则根据字符串长度和显示菜单项自动计算x2,y2 | |
-- isBox 是否绘制边框,0 不绘制,1 绘制。若绘制,则按照(x1,y1,x2,y2)的矩形绘制白色方框,并使方框内背景变暗 | |
-- isEsc Esc键是否起作用 0 不起作用,1起作用 | |
-- Size 菜单项字体大小 | |
-- color 正常菜单项颜色,均为RGB | |
-- selectColor 选中菜单项颜色, | |
--; | |
-- 返回值 0 Esc返回 | |
-- >0 选中的菜单项(1表示第一项) | |
-- <0 选中的菜单项,调用函数要求退出父菜单,这个用于退出多层菜单 | |
function ShowMenu(menuItem,numItem,numShow,x1,y1,x2,y2,isBox,isEsc,size,color,selectColor) --通用菜单函数 | |
local w=0; | |
local h=0; --边框的宽高 | |
local i=0; | |
local num=0; --实际的显示菜单项 | |
local newNumItem=0; --能够显示的总菜单项数 | |
lib.GetKey(); | |
local newMenu={}; -- 定义新的数组,以保存所有能显示的菜单项 | |
--计算能够显示的总菜单项数 | |
for i=1,numItem do | |
if menuItem[i][3]>0 then | |
newNumItem=newNumItem+1; | |
newMenu[newNumItem]={menuItem[i][1],menuItem[i][2],menuItem[i][3],i}; --新数组多了[4],保存和原数组的对应 | |
end | |
end | |
--计算实际显示的菜单项数 | |
if numShow==0 or numShow > newNumItem then | |
num=newNumItem; | |
else | |
num=numShow; | |
end | |
--计算边框实际宽高 | |
local maxlength=0; | |
if x2==0 and y2==0 then | |
for i=1,newNumItem do | |
if string.len(newMenu[i][1])>maxlength then | |
maxlength=string.len(newMenu[i][1]); | |
end | |
end | |
w=size*maxlength/2+2*CC.MenuBorderPixel; --按照半个汉字计算宽度,一边留4个象素 | |
h=(size+CC.RowPixel)*num+CC.MenuBorderPixel; --字之间留4个象素,上面再留4个象素 | |
else | |
w=x2-x1; | |
h=y2-y1; | |
end | |
local start=1; --显示的第一项 | |
local current =1; --当前选择项 | |
for i=1,newNumItem do | |
if newMenu[i][3]==2 then | |
current=i; | |
break; | |
end | |
end | |
if numShow~=0 then | |
current=1; | |
end | |
local keyPress =-1; | |
local returnValue =0; | |
if isBox==1 then | |
DrawBox(x1,y1,x1+w,y1+h,C_WHITE); | |
end | |
while true do | |
if numShow ~=0 then | |
Cls(x1,y1,x1+w,y1+h); | |
if isBox==1 then | |
DrawBox(x1,y1,x1+w,y1+h,C_WHITE); | |
end | |
end | |
for i=start,start+num-1 do | |
local drawColor=color; --设置不同的绘制颜色 | |
if i==current then | |
drawColor=selectColor; | |
end | |
DrawString(x1+CC.MenuBorderPixel,y1+CC.MenuBorderPixel+(i-start)*(size+CC.RowPixel), | |
newMenu[i][1],drawColor,size); | |
end | |
ShowScreen(); | |
keyPress=WaitKey(); | |
lib.Delay(100); | |
if keyPress==VK_ESCAPE then --Esc 退出 | |
if isEsc==1 then | |
break; | |
end | |
elseif keyPress==VK_DOWN then --Down | |
current = current +1; | |
if current > (start + num-1) then | |
start=start+1; | |
end | |
if current > newNumItem then | |
start=1; | |
current =1; | |
end | |
elseif keyPress==VK_UP then --Up | |
current = current -1; | |
if current < start then | |
start=start-1; | |
end | |
if current < 1 then | |
current = newNumItem; | |
start =current-num+1; | |
end | |
elseif (keyPress==VK_SPACE) or (keyPress==VK_RETURN) then | |
if newMenu[current][2]==nil then | |
returnValue=newMenu[current][4]; | |
break; | |
else | |
local r=newMenu[current][2](newMenu,current); --调用菜单函数 | |
if r==1 then | |
returnValue= -newMenu[current][4]; | |
break; | |
else | |
Cls(x1,y1,x1+w,y1+h); | |
if isBox==1 then | |
DrawBox(x1,y1,x1+w,y1+h,C_WHITE); | |
end | |
end | |
end | |
end | |
end | |
Cls(x1,y1,x1+w+1,y1+h+1,0,1); | |
return returnValue; | |
end | |
--横向显示菜单,参数和ShowMenu一样 | |
function ShowMenu2(menuItem,numItem,numShow,x1,y1,x2,y2,isBox,isEsc,size,color,selectColor) --通用菜单函数 | |
local w=0; | |
local h=0; --边框的宽高 | |
local i=0; | |
local num=0; --实际的显示菜单项 | |
local newNumItem=0; --能够显示的总菜单项数 | |
lib.GetKey(); | |
local newMenu={}; -- 定义新的数组,以保存所有能显示的菜单项 | |
--计算能够显示的总菜单项数 | |
for i=1,numItem do | |
if menuItem[i][3]>0 then | |
newNumItem=newNumItem+1; | |
newMenu[newNumItem]={menuItem[i][1],menuItem[i][2],menuItem[i][3],i}; --新数组多了[4],保存和原数组的对应 | |
end | |
end | |
--计算实际显示的菜单项数 | |
if numShow==0 or numShow > newNumItem then | |
num=newNumItem; | |
else | |
num=numShow; | |
end | |
--计算边框实际宽高 | |
local maxlength=0; | |
if x2==0 and y2==0 then | |
for i=1,newNumItem do | |
if string.len(newMenu[i][1])>maxlength then | |
maxlength=string.len(newMenu[i][1]); | |
end | |
end | |
w=(size*maxlength/2+CC.RowPixel)*num+CC.MenuBorderPixel; | |
h=size+2*CC.MenuBorderPixel; | |
else | |
w=x2-x1; | |
h=y2-y1; | |
end | |
local start=1; --显示的第一项 | |
local current =1; --当前选择项 | |
for i=1,newNumItem do | |
if newMenu[i][3]==2 then | |
current=i; | |
break; | |
end | |
end | |
if numShow~=0 then | |
current=1; | |
end | |
local keyPress =-1; | |
local returnValue =0; | |
if isBox==1 then | |
DrawBox(x1,y1,x1+w,y1+h,C_WHITE); | |
end | |
while true do | |
if numShow ~=0 then | |
Cls(x1,y1,x1+w,y1+h); | |
if isBox==1 then | |
DrawBox(x1,y1,x1+w,y1+h,C_WHITE); | |
end | |
end | |
for i=start,start+num-1 do | |
local drawColor=color; --设置不同的绘制颜色 | |
if i==current then | |
drawColor=selectColor; | |
end | |
DrawString(x1+CC.MenuBorderPixel+(i-start)*(size*maxlength/2+CC.RowPixel), | |
y1+CC.MenuBorderPixel,newMenu[i][1],drawColor,size); | |
end | |
ShowScreen(); | |
keyPress=WaitKey(); | |
lib.Delay(100); | |
if keyPress==VK_ESCAPE then --Esc 退出 | |
if isEsc==1 then | |
break; | |
end | |
elseif keyPress==VK_RIGHT then --Down | |
current = current +1; | |
if current > (start + num-1) then | |
start=start+1; | |
end | |
if current > newNumItem then | |
start=1; | |
current =1; | |
end | |
elseif keyPress==VK_LEFT then --Up | |
current = current -1; | |
if current < start then | |
start=start-1; | |
end | |
if current < 1 then | |
current = newNumItem; | |
start =current-num+1; | |
end | |
elseif (keyPress==VK_SPACE) or (keyPress==VK_RETURN) then | |
if newMenu[current][2]==nil then | |
returnValue=newMenu[current][4]; | |
break; | |
else | |
local r=newMenu[current][2](newMenu,current); --调用菜单函数 | |
if r==1 then | |
returnValue= -newMenu[current][4]; | |
break; | |
else | |
Cls(x1,y1,x1+w,y1+h); | |
if isBox==1 then | |
DrawBox(x1,y1,x1+w,y1+h,C_WHITE); | |
end | |
end | |
end | |
end | |
end | |
Cls(x1,y1,x1+w+1,y1+h+1,0,1); | |
return returnValue; | |
end | |
------------------------------------------------------------------------------------ | |
--------------------------------------物品使用--------------------------------------- | |
--物品使用模块 | |
--当前物品id | |
--返回1 使用了物品, 0 没有使用物品。可能是某些原因不能使用 | |
function UseThing(id) --物品使用 | |
--调用函数 | |
if JY.ThingUseFunction[id]==nil then | |
return DefaultUseThing(id); | |
else | |
return JY.ThingUseFunction[id](id); | |
end | |
end | |
--缺省物品使用函数,实现原始游戏效果 | |
--id 物品id | |
function DefaultUseThing(id) --缺省物品使用函数 | |
if JY.Thing[id]["类型"]==0 then | |
return UseThing_Type0(id); | |
elseif JY.Thing[id]["类型"]==1 then | |
return UseThing_Type1(id); | |
elseif JY.Thing[id]["类型"]==2 then | |
return UseThing_Type2(id); | |
elseif JY.Thing[id]["类型"]==3 then | |
return UseThing_Type3(id); | |
elseif JY.Thing[id]["类型"]==4 then | |
return UseThing_Type4(id); | |
end | |
end | |
--剧情物品,触发事件 | |
function UseThing_Type0(id) --剧情物品使用 | |
if JY.SubScene>=0 then | |
local x=JY.Base["人X1"]+CC.DirectX[JY.Base["人方向"]+1]; | |
local y=JY.Base["人Y1"]+CC.DirectY[JY.Base["人方向"]+1]; | |
local d_num=GetS(JY.SubScene,x,y,3) | |
if d_num>=0 then | |
JY.CurrentThing=id; | |
EventExecute(d_num,2); --物品触发事件 | |
JY.CurrentThing=-1; | |
return 1; | |
else | |
return 0; | |
end | |
end | |
end | |
--装备物品 | |
function UseThing_Type1(id) --装备物品使用 | |
DrawStrBox(CC.MainSubMenuX,CC.MainSubMenuY,string.format("谁要配备%s?",JY.Thing[id]["名称"]),C_WHITE,CC.DefaultFont); | |
local nexty=CC.MainSubMenuY+CC.SingleLineHeight; | |
local r=SelectTeamMenu(CC.MainSubMenuX,nexty); | |
if r>0 then | |
local personid=JY.Base["队伍" ..r] | |
if CanUseThing(id,personid) then | |
if JY.Thing[id]["装备类型"]==0 then | |
if JY.Thing[id]["使用人"]>=0 then | |
JY.Person[JY.Thing[id]["使用人"]]["武器"]=-1; | |
end | |
if JY.Person[personid]["武器"]>=0 then | |
JY.Thing[JY.Person[personid]["武器"]]["使用人"]=-1 | |
end | |
JY.Person[personid]["武器"]=id; | |
elseif JY.Thing[id]["装备类型"]==1 then | |
if JY.Thing[id]["使用人"]>=0 then | |
JY.Person[JY.Thing[id]["使用人"]]["防具"]=-1; | |
end | |
if JY.Person[personid]["防具"]>=0 then | |
JY.Thing[JY.Person[personid]["防具"]]["使用人"]=-1 | |
end | |
JY.Person[personid]["防具"]=id; | |
end | |
JY.Thing[id]["使用人"]=personid | |
else | |
DrawStrBoxWaitKey("此人不适合配备此物品",C_WHITE,CC.DefaultFont); | |
return 0; | |
end | |
end | |
-- Cls(); | |
-- ShowScreen(); | |
return 1; | |
end | |
--判断一个人是否可以装备或修炼一个物品 | |
--返回 true可以修炼,false不可 | |
function CanUseThing(id,personid) --判断一个人是否可以装备或修炼一个物品 | |
local str=""; | |
if JY.Thing[id]["仅修炼人物"] >=0 then | |
if JY.Thing[id]["仅修炼人物"] ~= personid then | |
return false; | |
end | |
end | |
if JY.Thing[id]["需内力性质"] ~=2 and JY.Person[personid]["内力性质"] ~=2 then | |
if JY.Thing[id]["需内力性质"] ~= JY.Person[personid]["内力性质"] then | |
return false; | |
end | |
end | |
if JY.Thing[id]["需内力"] > JY.Person[personid]["内力最大值"] then | |
return false; | |
end | |
if JY.Thing[id]["需攻击力"] > JY.Person[personid]["攻击力"] then | |
return false; | |
end | |
if JY.Thing[id]["需轻功"] > JY.Person[personid]["轻功"] then | |
return false; | |
end | |
if JY.Thing[id]["需用毒能力"] > JY.Person[personid]["用毒能力"] then | |
return false; | |
end | |
if JY.Thing[id]["需医疗能力"] > JY.Person[personid]["医疗能力"] then | |
return false; | |
end | |
if JY.Thing[id]["需解毒能力"] > JY.Person[personid]["解毒能力"] then | |
return false; | |
end | |
if JY.Thing[id]["需拳掌功夫"] > JY.Person[personid]["拳掌功夫"] then | |
return false; | |
end | |
if JY.Thing[id]["需御剑能力"] > JY.Person[personid]["御剑能力"] then | |
return false; | |
end | |
if JY.Thing[id]["需耍刀技巧"] > JY.Person[personid]["耍刀技巧"] then | |
return false; | |
end | |
if JY.Thing[id]["需特殊兵器"] > JY.Person[personid]["特殊兵器"] then | |
return false; | |
end | |
if JY.Thing[id]["需暗器技巧"] > JY.Person[personid]["暗器技巧"] then | |
return false; | |
end | |
if JY.Thing[id]["需资质"] >= 0 then | |
if JY.Thing[id]["需资质"] > JY.Person[personid]["资质"] then | |
return false; | |
end | |
else | |
if -JY.Thing[id]["需资质"] < JY.Person[personid]["资质"] then | |
return false; | |
end | |
end | |
return true | |
end | |
--秘籍物品 | |
function UseThing_Type2(id) --秘籍物品使用 | |
if JY.Thing[id]["使用人"]>=0 then | |
if DrawStrBoxYesNo(-1,-1,"此物品已经有人修炼,是否换人修炼?",C_WHITE,CC.DefaultFont)==false then | |
Cls(CC.MainSubMenuX,CC.MainSubMenuY,CC.ScreenW,CC.ScreenH); | |
ShowScreen(); | |
return 0; | |
end | |
end | |
Cls(); | |
DrawStrBox(CC.MainSubMenuX,CC.MainSubMenuY,string.format("谁要修炼%s?",JY.Thing[id]["名称"]),C_WHITE,CC.DefaultFont); | |
local nexty=CC.MainSubMenuY+CC.SingleLineHeight; | |
local r=SelectTeamMenu(CC.MainSubMenuX,nexty); | |
if r>0 then | |
local personid=JY.Base["队伍" ..r] | |
if JY.Thing[id]["练出武功"]>=0 then | |
local yes=0; | |
for i = 1,10 do | |
if JY.Person[personid]["武功"..i]==JY.Thing[id]["练出武功"] then | |
yes=1; --武功已经有了 | |
break; | |
end | |
end | |
if yes==0 and JY.Person[personid]["武功10"]>0 then | |
DrawStrBoxWaitKey("一个人只能修炼10种武功",C_WHITE,CC.DefaultFont); | |
return 0; | |
end | |
end | |
if CC.Shemale[id]==1 then --辟邪和葵花 | |
if JY.Person[personid]["性别"]==0 then | |
Cls(CC.MainSubMenuX,CC.MainSubMenuY,CC.ScreenW,CC.ScreenH); | |
if DrawStrBoxYesNo(-1,-1,"修炼此书必须先挥刀自宫,是否仍要修炼?",C_WHITE,CC.DefaultFont)==false then | |
return 0; | |
else | |
JY.Person[personid]["性别"]=2; | |
end | |
elseif JY.Person[personid]["性别"]==1 then | |
DrawStrBoxWaitKey("此人不适合修炼此物品",C_WHITE,CC.DefaultFont); | |
return 0; | |
end | |
end | |
if CanUseThing(id,personid) then | |
if JY.Thing[id]["使用人"]==personid then | |
return 0; | |
end | |
if JY.Person[personid]["修炼物品"]>=0 then | |
JY.Thing[JY.Person[personid]["修炼物品"]]["使用人"]=-1; | |
end | |
if JY.Thing[id]["使用人"]>=0 then | |
JY.Person[JY.Thing[id]["使用人"]]["修炼物品"]=-1; | |
JY.Person[JY.Thing[id]["使用人"]]["修炼点数"]=0; | |
JY.Person[JY.Thing[id]["使用人"]]["物品修炼点数"]=0; | |
end | |
JY.Thing[id]["使用人"]=personid | |
JY.Person[personid]["修炼物品"]=id; | |
JY.Person[personid]["修炼点数"]=0; | |
JY.Person[personid]["物品修炼点数"]=0; | |
else | |
DrawStrBoxWaitKey("此人不适合修炼此物品",C_WHITE,CC.DefaultFont); | |
return 0; | |
end | |
end | |
return 1; | |
end | |
--药品物品 | |
function UseThing_Type3(id) --药品物品使用 | |
local usepersonid=-1; | |
if JY.Status==GAME_MMAP or JY.Status==GAME_SMAP then | |
Cls(CC.MainSubMenuX,CC.MainSubMenuY,CC.ScreenW,CC.ScreenH); | |
DrawStrBox(CC.MainSubMenuX,CC.MainSubMenuY,string.format("谁要使用%s?",JY.Thing[id]["名称"]),C_WHITE,CC.DefaultFont); | |
local nexty=CC.MainSubMenuY+CC.SingleLineHeight; | |
local r=SelectTeamMenu(CC.MainSubMenuX,nexty); | |
if r>0 then | |
usepersonid=JY.Base["队伍" ..r] | |
end | |
elseif JY.Status==GAME_WMAP then ---战斗场景使用药品 | |
usepersonid=WAR.Person[WAR.CurID]["人物编号"]; | |
end | |
if usepersonid>=0 then | |
if UseThingEffect(id,usepersonid)==1 then --使用有效果 | |
instruct_32(id,-1); --物品数量减少 | |
WaitKey(); | |
else | |
return 0; | |
end | |
end | |
-- Cls(); | |
-- ShowScreen(); | |
return 1; | |
end | |
--药品使用实际效果 | |
--id 物品id, | |
--personid 使用人id | |
--返回值:0 使用没有效果,物品数量应该不变。1 使用有效果,则使用后物品数量应该-1 | |
function UseThingEffect(id,personid) --药品使用实际效果 | |
local str={}; | |
str[0]=string.format("使用 %s",JY.Thing[id]["名称"]); | |
local strnum=1; | |
local addvalue; | |
if JY.Thing[id]["加生命"] >0 then | |
local add=JY.Thing[id]["加生命"]-math.modf(JY.Person[personid]["受伤程度"]/2)+Rnd(10); | |
if add <=0 then | |
add=5+Rnd(5); | |
end | |
AddPersonAttrib(personid,"受伤程度",-JY.Thing[id]["加生命"]/4); | |
addvalue,str[strnum]=AddPersonAttrib(personid,"生命",add); | |
if addvalue ~=0 then | |
strnum=strnum+1 | |
end | |
end | |
local function ThingAddAttrib(s) ---定义局部函数,处理吃药后增加属性 | |
if JY.Thing[id]["加" .. s] ~=0 then | |
addvalue,str[strnum]=AddPersonAttrib(personid,s,JY.Thing[id]["加" .. s]); | |
if addvalue ~=0 then | |
strnum=strnum+1 | |
end | |
end | |
end | |
ThingAddAttrib("生命最大值"); | |
if JY.Thing[id]["加中毒解毒"] <0 then | |
addvalue,str[strnum]=AddPersonAttrib(personid,"中毒程度",math.modf(JY.Thing[id]["加中毒解毒"]/2)); | |
if addvalue ~=0 then | |
strnum=strnum+1 | |
end | |
end | |
ThingAddAttrib("体力"); | |
if JY.Thing[id]["改变内力性质"] ==2 then | |
str[strnum]="内力门路改为阴阳合一" | |
strnum=strnum+1 | |
end | |
ThingAddAttrib("内力"); | |
ThingAddAttrib("内力最大值"); | |
ThingAddAttrib("攻击力"); | |
ThingAddAttrib("防御力"); | |
ThingAddAttrib("轻功"); | |
ThingAddAttrib("医疗能力"); | |
ThingAddAttrib("用毒能力"); | |
ThingAddAttrib("解毒能力"); | |
ThingAddAttrib("抗毒能力"); | |
ThingAddAttrib("拳掌功夫"); | |
ThingAddAttrib("御剑能力"); | |
ThingAddAttrib("耍刀技巧"); | |
ThingAddAttrib("特殊兵器"); | |
ThingAddAttrib("暗器技巧"); | |
ThingAddAttrib("武学常识"); | |
ThingAddAttrib("攻击带毒"); | |
if strnum>1 then | |
local maxlength=0 --计算字符串最大长度 | |
for i = 0,strnum-1 do | |
if #str[i] > maxlength then | |
maxlength=#str[i]; | |
end | |
end | |
Cls(); | |
local ww=maxlength*CC.DefaultFont/2+CC.MenuBorderPixel*2; | |
local hh=strnum*CC.DefaultFont+(strnum-1)*CC.RowPixel+2*CC.MenuBorderPixel; | |
local x=(CC.ScreenW-ww)/2; | |
local y=(CC.ScreenH-hh)/2; | |
DrawBox(x,y,x+ww,y+hh,C_WHITE); | |
DrawString(x+CC.MenuBorderPixel,y+CC.MenuBorderPixel,str[0],C_WHITE,CC.DefaultFont); | |
for i =1,strnum-1 do | |
DrawString(x+CC.MenuBorderPixel,y+CC.MenuBorderPixel+(CC.DefaultFont+CC.RowPixel)*i,str[i],C_ORANGE,CC.DefaultFont); | |
end | |
ShowScreen(); | |
return 1; | |
else | |
return 0; | |
end | |
end | |
--暗器物品 | |
function UseThing_Type4(id) --暗器物品使用 | |
if JY.Status==GAME_WMAP then | |
return War_UseAnqi(id); | |
end | |
return 0; | |
end | |
-------------------------------------------------------------------------------- | |
--------------------------------------事件调用----------------------------------- | |
--事件调用主入口 | |
--id,d*中的编号 | |
--flag 1 空格触发,2,物品触发,3,路过触发 | |
function EventExecute(id,flag) --事件调用主入口 | |
JY.CurrentD=id; | |
if JY.SceneNewEventFunction[JY.SubScene]==nil then --没有定义新的事件处理函数,调用旧的 | |
oldEventExecute(flag) | |
else | |
JY.SceneNewEventFunction[JY.SubScene](flag) --调用新的事件处理函数 | |
end | |
JY.CurrentD=-1; | |
JY.Darkness=0; | |
end | |
--调用原有的指定位置的函数 | |
--旧的函数名字格式为 oldevent_xxx(); xxx为事件编号 | |
function oldEventExecute(flag) --调用原有的指定位置的函数 | |
local eventnum; | |
if flag==1 then | |
eventnum=GetD(JY.SubScene,JY.CurrentD,2); | |
elseif flag==2 then | |
eventnum=GetD(JY.SubScene,JY.CurrentD,3); | |
elseif flag==3 then | |
eventnum=GetD(JY.SubScene,JY.CurrentD,4); | |
end | |
if eventnum>0 then | |
oldCallEvent(eventnum); | |
end | |
end | |
function oldCallEvent(eventnum) --执行旧的事件函数 | |
local eventfilename=string.format("oldevent_%d.lua",eventnum); | |
lib.Debug(eventfilename); | |
dofile(CONFIG.OldEventPath .. eventfilename); | |
end | |
--改变大地图坐标,从场景出去后移动到相应坐标 | |
function ChangeMMap(x,y,direct) --改变大地图坐标 | |
JY.Base["人X"]=x; | |
JY.Base["人Y"]=y; | |
JY.Base["人方向"]=direct; | |
end | |
--改变当前场景 | |
function ChangeSMap(sceneid,x,y,direct) --改变当前场景 | |
JY.SubScene=sceneid; | |
JY.Base["人X1"]=x; | |
JY.Base["人Y1"]=y; | |
JY.Base["人方向"]=direct; | |
end | |
--清除(x1,y1)-(x2,y2)矩形内的文字等。 | |
--如果没有参数,则清除整个屏幕表面 | |
--注意该函数并不直接刷新显示屏幕 | |
function Cls(x1,y1,x2,y2) --清除屏幕 | |
if x1==nil then --第一个参数为nil,表示没有参数,用缺省 | |
x1=0; | |
y1=0; | |
x2=0; | |
y2=0; | |
end | |
lib.SetClip(x1,y1,x2,y2); | |
if JY.Status==GAME_START then | |
lib.FillColor(0,0,0,0,0); | |
lib.LoadPicture(CC.FirstFile,-1,-1); | |
elseif JY.Status==GAME_MMAP then | |
lib.DrawMMap(JY.Base["人X"],JY.Base["人Y"],GetMyPic()); --显示主地图 | |
elseif JY.Status==GAME_SMAP then | |
DrawSMap(); | |
elseif JY.Status==GAME_WMAP then | |
WarDrawMap(0); | |
elseif JY.Status==GAME_DEAD then | |
lib.FillColor(0,0,0,0,0); | |
lib.LoadPicture(CC.DeadFile,-1,-1); | |
end | |
lib.SetClip(0,0,0,0); | |
end | |
--产生对话显示需要的字符串,即每隔n个中文字符加一个星号 | |
function GenTalkString(str,n) --产生对话显示需要的字符串 | |
local tmpstr=""; | |
for s in string.gmatch(str .. "*","(.-)%*") do --去掉对话中的所有*. 字符串尾部加一个星号,避免无法匹配 | |
tmpstr=tmpstr .. s; | |
end | |
local newstr=""; | |
while #tmpstr>0 do | |
local w=0; | |
while w<#tmpstr do | |
local v=string.byte(tmpstr,w+1); --当前字符的值 | |
if v>=128 then | |
w=w+2; | |
else | |
w=w+1; | |
end | |
if w >= 2*n-1 then --为了避免跨段中文字符 | |
break; | |
end | |
end | |
if w<#tmpstr then | |
if w==2*n-1 and string.byte(tmpstr,w+1)<128 then | |
newstr=newstr .. string.sub(tmpstr,1,w+1) .. "*"; | |
tmpstr=string.sub(tmpstr,w+2,-1); | |
else | |
newstr=newstr .. string.sub(tmpstr,1,w) .. "*"; | |
tmpstr=string.sub(tmpstr,w+1,-1); | |
end | |
else | |
newstr=newstr .. tmpstr; | |
break; | |
end | |
end | |
return newstr; | |
end | |
--最简单版本对话 | |
function Talk(s,personid) --最简单版本对话 | |
local flag; | |
if personid==0 then | |
flag=1; | |
else | |
flag=0; | |
end | |
TalkEx(s,JY.Person[personid]["头像代号"],flag); | |
end | |
--复杂版本对话 | |
--s 字符串,必须加上*作为分行,如果里面没有*,则会自动加上 | |
function TalkEx(s,headid,flag) --复杂版本对话 | |
local picw=100; --最大头像图片宽高 | |
local pich=100; | |
local talkxnum=12; --对话一行字数 | |
local talkynum=3; --对话行数 | |
local dx=2; | |
local dy=2; | |
local boxpicw=picw+10; | |
local boxpich=pich+10; | |
local boxtalkw=12*CC.DefaultFont+10; | |
local boxtalkh=boxpich; | |
local talkBorder=(pich-talkynum*CC.DefaultFont)/(talkynum+1); | |
--显示头像和对话的坐标 | |
local xy={ [0]={headx=dx,heady=dy, | |
talkx=dx+boxpicw+2,talky=dy, | |
showhead=1}, | |
{headx=CC.ScreenW-1-dx-boxpicw,heady=CC.ScreenH-dy-boxpich, | |
talkx=CC.ScreenW-1-dx-boxpicw-boxtalkw-2,talky= CC.ScreenH-dy-boxpich, | |
showhead=1}, | |
{headx=dx,heady=dy, | |
talkx=dx+boxpicw+2,talky=dy, | |
showhead=0}, | |
{headx=CC.ScreenW-1-dx-boxpicw,heady=CC.ScreenH-dy-boxpich, | |
talkx=CC.ScreenW-1-dx-boxpicw-boxtalkw-2,talky= CC.ScreenH-dy-boxpich, | |
showhead=1}, | |
{headx=CC.ScreenW-1-dx-boxpicw,heady=dy, | |
talkx=CC.ScreenW-1-dx-boxpicw-boxtalkw-2,talky=dy,showhead=1}, | |
{headx=dx,heady=CC.ScreenH-dy-boxpich,talkx=dx+boxpicw+2,talky=CC.ScreenH-dy-boxpich,showhead=1}, } | |
if flag<0 or flag>5 then | |
flag=0; | |
end | |
if xy[flag].showhead==0 then | |
headid=-1; | |
end | |
if string.find(s,"*") ==nil then | |
s=GenTalkString(s,12); | |
end | |
if CONFIG.KeyRepeat==0 then | |
lib.EnableKeyRepeat(0,CONFIG.KeyRepeatInterval); | |
end | |
lib.GetKey(); | |
local startp=1 | |
local endp; | |
local dy=0; | |
while true do | |
if dy==0 then | |
Cls(); | |
if headid>=0 then | |
DrawBox(xy[flag].headx, xy[flag].heady, xy[flag].headx + boxpicw, xy[flag].heady + boxpich,C_WHITE); | |
local w,h=lib.PicGetXY(1,headid*2); | |
local x=(picw-w)/2; | |
local y=(pich-h)/2; | |
lib.PicLoadCache(1,headid*2,xy[flag].headx+5+x,xy[flag].heady+5+y,1); | |
end | |
DrawBox(xy[flag].talkx, xy[flag].talky, xy[flag].talkx +boxtalkw, xy[flag].talky + boxtalkh,C_WHITE); | |
end | |
endp=string.find(s,"*",startp); | |
if endp==nil then | |
DrawString(xy[flag].talkx + 5, xy[flag].talky + 5+talkBorder + dy * (CC.DefaultFont+talkBorder),string.sub(s,startp),C_WHITE,CC.DefaultFont); | |
ShowScreen(); | |
WaitKey(); | |
break; | |
else | |
DrawString(xy[flag].talkx + 5, xy[flag].talky + 5+talkBorder + dy * (CC.DefaultFont+talkBorder),string.sub(s,startp,endp-1),C_WHITE,CC.DefaultFont); | |
end | |
dy=dy+1; | |
startp=endp+1; | |
if dy>=talkynum then | |
ShowScreen(); | |
WaitKey(); | |
dy=0; | |
end | |
end | |
if CONFIG.KeyRepeat==0 then | |
lib.EnableKeyRepeat(CONFIG.KeyRepeatDelay,CONFIG.KeyRepeatInterval); | |
end | |
Cls(); | |
end | |
--测试指令,占位置用 | |
function instruct_test(s) | |
DrawStrBoxWaitKey(s,C_ORANGE,24); | |
end | |
--清屏 | |
function instruct_0() --清屏 | |
Cls(); | |
end | |
--对话 | |
--talkid: 为数字,则为对话编号;为字符串,则为对话本身。 | |
--headid: 头像id | |
--flag :对话框位置:0 屏幕上方显示, 左边头像,右边对话 | |
-- 1 屏幕下方显示, 左边对话,右边头像 | |
-- 2 屏幕上方显示, 左边空,右边对话 | |
-- 3 屏幕下方显示, 左边对话,右边空 | |
-- 4 屏幕上方显示, 左边对话,右边头像 | |
-- 5 屏幕下方显示, 左边头像,右边对话 | |
function instruct_1(talkid,headid,flag) --对话 | |
local s=ReadTalk(talkid); | |
if s==nil then --对话id不存在 | |
return ; | |
end | |
TalkEx(s,headid,flag); | |
end | |
--根据oldtalk.grp文件来idx索引文件。供后面读对话使用 | |
function GenTalkIdx() --生成对话索引文件 | |
os.remove(CC.TalkIdxFile); | |
local p=io.open(CC.TalkIdxFile,"w"); | |
p:close(); | |
p=io.open(CC.TalkGrpFile,"r"); | |
local num=0 | |
for line in p:lines() do | |
num=num+1; | |
end | |
p:seek("set",0); | |
local data=Byte.create(num*4); | |
for i=0,num-1 do | |
local talk=p:read("*line"); | |
local offset=p:seek(); | |
Byte.set32(data,i*4,offset); | |
end | |
p:close(); | |
Byte.savefile(data,CC.TalkIdxFile,0,num*4); | |
end | |
--从old_talk.lua中读取编号为talkid的字符串。 | |
--需要的时候读取,可以节约内存占用,不用再把整个文件读入内存数据了。 | |
function ReadTalk(talkid) --从文件读取一条对话 | |
local idxfile=CC.TalkIdxFile | |
local grpfile=CC.TalkGrpFile | |
local length=filelength(idxfile); | |
if talkid<0 and talkid>=length/4 then | |
return | |
end | |
local data=Byte.create(2*4); | |
local id1,id2; | |
if talkid==0 then | |
Byte.loadfile(data,idxfile,0,4); | |
id1=0; | |
id2=Byte.get32(data,0); | |
else | |
Byte.loadfile(data,idxfile,(talkid-1)*4,4*2); | |
id1=Byte.get32(data,0); | |
id2=Byte.get32(data,4); | |
end | |
local p=io.open(grpfile,"r"); | |
p:seek("set",id1); | |
local talk=p:read("*line"); | |
p:close(); | |
return talk; | |
end | |
--得到物品 | |
function instruct_2(thingid,num) --得到物品 | |
if JY.Thing[thingid]==nil then --无此物品id | |
return ; | |
end | |
instruct_32(thingid,num); --增加物品 | |
DrawStrBoxWaitKey(string.format("得到物品:%s %d",JY.Thing[thingid]["名称"],num),C_ORANGE,CC.DefaultFont); | |
instruct_2_sub(); --是否可得武林帖 | |
end | |
--声望>200以及14天书后得到武林帖 | |
function instruct_2_sub() --声望>200以及14天书后得到武林帖 | |
if JY.Person[0]["声望"] < 200 then | |
return ; | |
end | |
if instruct_18(189) ==true then --有武林帖, 189 武林帖id | |
return; | |
end | |
local booknum=0; | |
for i=1,CC.BookNum do | |
if instruct_18(CC.BookStart+i-1)==true then | |
booknum=booknum+1; | |
end | |
end | |
if booknum==CC.BookNum then --设置主角居桌子上的武林帖事件 | |
instruct_3(70,11,-1,1,932,-1,-1,7968,7968,7968,-2,-2,-2); | |
end | |
end | |
--修改D* | |
-- sceneid 场景id, -2表示当前场景 | |
-- id D*的id, -2表示当前id | |
-- v0 - v10 D*参数, -2表示此参数不变 | |
function instruct_3(sceneid,id,v0,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10) --修改D* | |
if sceneid==-2 then | |
sceneid=JY.SubScene; | |
end | |
if id==-2 then | |
id=JY.CurrentD; | |
end | |
if v0~=-2 then | |
SetD(sceneid,id,0,v0) | |
end | |
if v1~=-2 then | |
SetD(sceneid,id,1,v1) | |
end | |
if v2~=-2 then | |
SetD(sceneid,id,2,v2) | |
end | |
if v3~=-2 then | |
SetD(sceneid,id,3,v3) | |
end | |
if v4~=-2 then | |
SetD(sceneid,id,4,v4) | |
end | |
if v5~=-2 then | |
SetD(sceneid,id,5,v5) | |
end | |
if v6~=-2 then | |
SetD(sceneid,id,6,v6) | |
end | |
if v7~=-2 then | |
SetD(sceneid,id,7,v7) | |
end | |
if v8~=-2 then | |
SetD(sceneid,id,8,v8) | |
end | |
if v9~=-2 and v10 ~=-2 then | |
if v9>0 and v10 >0 then --为了和苍龙兼容,修改的坐标不能为0 | |
SetS(sceneid,GetD(sceneid,id,9),GetD(sceneid,id,10),3,-1); --如果xy坐标移动了,那么S中相应数据要修改。 | |
SetD(sceneid,id,9,v9) | |
SetD(sceneid,id,10,v10) | |
SetS(sceneid,GetD(sceneid,id,9),GetD(sceneid,id,10),3,id); | |
end | |
end | |
end | |
--是否使用物品触发 | |
function instruct_4(thingid) --是否使用物品触发 | |
if JY.CurrentThing==thingid then | |
return true; | |
else | |
return false; | |
end | |
end | |
function instruct_5() --选择战斗 | |
return DrawStrBoxYesNo(-1,-1,"是否与之过招(Y/N)?",C_ORANGE,CC.DefaultFont); | |
end | |
function instruct_6(warid,tmp,tmp,flag) --战斗 | |
return WarMain(warid,flag); | |
end | |
function instruct_7() --已经翻译为return了 | |
instruct_test("指令7测试") | |
end | |
function instruct_8(musicid) --改变主地图音乐 | |
JY.MmapMusic=musicid; | |
end | |
function instruct_9() --是否要求加入队伍 | |
Cls(); | |
return DrawStrBoxYesNo(-1,-1,"是否要求加入(Y/N)?",C_ORANGE,CC.DefaultFont); | |
end | |
function instruct_10(personid) --加入队员 | |
if JY.Person[personid]==nil then | |
lib.Debug("instruct_10 error: person id not exist"); | |
return ; | |
end | |
local add=0; | |
for i =2, CC.TeamNum do --第一个位置是主角,从第二个开始 | |
if JY.Base["队伍"..i]<0 then | |
JY.Base["队伍"..i]=personid; | |
add=1; | |
break; | |
end | |
end | |
if add==0 then | |
lib.Debug("instruct_10 error: 加入队伍已满"); | |
return ; | |
end | |
for i =1,4 do --个人物品归公 | |
local id =JY.Person[personid]["携带物品" .. i]; | |
local n=JY.Person[personid]["携带物品数量" .. i]; | |
if id>=0 and n>0 then | |
instruct_2(id,n); | |
JY.Person[personid]["携带物品" .. i]=-1; | |
JY.Person[personid]["携带物品数量" .. i]=0; | |
end | |
end | |
end | |
function instruct_11() --是否住宿 | |
Cls(); | |
return DrawStrBoxYesNo(-1,-1,"是否住宿(Y/N)?",C_ORANGE,CC.DefaultFont); | |
end | |
function instruct_12() --住宿,回复体力 | |
for i=1,CC.TeamNum do | |
local id=JY.Base["队伍" .. i]; | |
if id>=0 then | |
if JY.Person[id]["受伤程度"]<33 and JY.Person[id]["中毒程度"]<=0 then | |
JY.Person[id]["受伤程度"]=0; | |
AddPersonAttrib(id,"体力",math.huge); --给一个很大的值,自动限制为最大值 | |
AddPersonAttrib(id,"生命",math.huge); | |
AddPersonAttrib(id,"内力",math.huge); | |
end | |
end | |
end | |
end | |
function instruct_13() --场景变亮 | |
Cls(); | |
JY.Darkness=0; | |
lib.ShowSlow(50,0) | |
lib.GetKey(); | |
end | |
function instruct_14() --场景变黑 | |
lib.ShowSlow(50,1); | |
JY.Darkness=1; | |
end | |
function instruct_15() --game over | |
JY.Status=GAME_DEAD; | |
Cls(); | |
DrawString(CC.GameOverX,CC.GameOverY,JY.Person[0]["姓名"],RGB(0,0,0),CC.DefaultFont); | |
local x=CC.ScreenW-9*CC.DefaultFont; | |
DrawString(x,10,os.date("%Y-%m-%d %H:%M"),RGB(216, 20, 24) ,CC.DefaultFont); | |
DrawString(x,10+CC.DefaultFont+CC.RowPixel,"在地球的某处",RGB(216, 20, 24) ,CC.DefaultFont); | |
DrawString(x,10+(CC.DefaultFont+CC.RowPixel)*2,"当地人口的失踪数",RGB(216, 20, 24) ,CC.DefaultFont); | |
DrawString(x,10+(CC.DefaultFont+CC.RowPixel)*3,"又多了一笔。。。",RGB(216, 20, 24) ,CC.DefaultFont); | |
local loadMenu={ {"载入进度一",nil,1}, | |
{"载入进度二",nil,1}, | |
{"载入进度三",nil,1}, | |
{"回家睡觉去",nil,1} }; | |
local y=CC.ScreenH-4*(CC.DefaultFont+CC.RowPixel)-10; | |
local r=ShowMenu(loadMenu,4,0,x,y,0,0,0,0,CC.DefaultFont,C_ORANGE, C_WHITE) | |
if r<4 then | |
LoadRecord(r); | |
JY.Status=GAME_FIRSTMMAP; | |
else | |
JY.Status=GAME_END; | |
end | |
end | |
function instruct_16(personid) --队伍中是否有某人 | |
local r=false; | |
for i = 1, CC.TeamNum do | |
if personid==JY.Base["队伍" .. i] then | |
r=true; | |
break; | |
end | |
end; | |
return r; | |
end | |
function instruct_17(sceneid,level,x,y,v) --修改场景图形 | |
if sceneid==-2 then | |
sceneid=JY.SubScene; | |
end | |
SetS(sceneid,x,y,level,v); | |
end | |
function instruct_18(thingid) --是否有某种物品 | |
for i = 1,CC.MyThingNum do | |
if JY.Base["物品" .. i]==thingid then | |
return true; | |
end | |
end | |
return false; | |
end | |
function instruct_19(x,y) --改变主角位置 | |
JY.Base["人X1"]=x; | |
JY.Base["人Y1"]=y; | |
JY.SubSceneX=0; | |
JY.SubSceneY=0; | |
end | |
function instruct_20() --判断队伍是否满 | |
if JY.Base["队伍" .. CC.TeamNum ] >=0 then | |
return true; | |
end | |
return false; | |
end | |
function instruct_21(personid) --离队 | |
if JY.Person[personid]==nil then | |
lib.Debug("instruct_21 error: personid not exist"); | |
return ; | |
end | |
local j=0; | |
for i = 1, CC.TeamNum do | |
if personid==JY.Base["队伍" .. i] then | |
j=i; | |
break; | |
end | |
end; | |
if j==0 then | |
return; | |
end | |
for i=j+1,CC.TeamNum do | |
JY.Base["队伍" .. i-1]=JY.Base["队伍" .. i]; | |
end | |
JY.Base["队伍" .. CC.TeamNum]=-1; | |
if JY.Person[personid]["武器"]>=0 then | |
JY.Thing[JY.Person[personid]["武器"]]["使用人"]=-1; | |
JY.Person[personid]["武器"]=-1 | |
end | |
if JY.Person[personid]["防具"]>=0 then | |
JY.Thing[JY.Person[personid]["防具"]]["使用人"]=-1; | |
JY.Person[personid]["防具"]=-1; | |
end | |
if JY.Person[personid]["修炼物品"]>=0 then | |
JY.Thing[JY.Person[personid]["修炼物品"]]["使用人"]=-1; | |
JY.Person[personid]["修炼物品"]=-1; | |
end | |
JY.Person[personid]["修炼点数"]=0; | |
JY.Person[personid]["物品修炼点数"]=0; | |
end | |
function instruct_22() --内力降为0 | |
for i = 1, CC.TeamNum do | |
if JY.Base["队伍" .. i] >=0 then | |
JY.Person[JY.Base["队伍" .. i]]["内力"]=0; | |
end | |
end | |
end | |
function instruct_23(personid,value) --设置用毒 | |
JY.Person[personid]["用毒能力"]=value; | |
AddPersonAttrib(personid,"用毒能力",0) | |
end | |
--空指令 | |
function instruct_24() | |
instruct_test("指令24测试") | |
end | |
--场景移动 | |
--为简化,实际上是场景移动(x2-x1),(y2-y1)。先y后x。因此,x1,y1可设为0 | |
function instruct_25(x1,y1,x2,y2) --场景移动 | |
local sign; | |
if y1 ~= y2 then | |
if y2<y1 then | |
sign=-1; | |
else | |
sign=1; | |
end | |
for i=y1+sign,y2,sign do | |
local t1=lib.GetTime(); | |
JY.SubSceneY=JY.SubSceneY+sign; | |
--JY.oldSMapX=-1; | |
--JY.oldSMapY=-1; | |
DrawSMap(); | |
ShowScreen(); | |
local t2=lib.GetTime(); | |
if (t2-t1)<CC.SceneMoveFrame then | |
lib.Delay(CC.SceneMoveFrame-(t2-t1)); | |
end | |
end | |
end | |
if x1 ~= x2 then | |
if x2<x1 then | |
sign=-1; | |
else | |
sign=1; | |
end | |
for i=x1+sign,x2,sign do | |
local t1=lib.GetTime(); | |
JY.SubSceneX=JY.SubSceneX+sign; | |
--JY.oldSMapX=-1; | |
--JY.oldSMapY=-1; | |
DrawSMap(); | |
ShowScreen(); | |
local t2=lib.GetTime(); | |
if (t2-t1)<CC.SceneMoveFrame then | |
lib.Delay(CC.SceneMoveFrame-(t2-t1)); | |
end | |
end | |
end | |
end | |
function instruct_26(sceneid,id,v1,v2,v3) --增加D*编号 | |
if sceneid==-2 then | |
sceneid=JY.SubScene; | |
end | |
local v=GetD(sceneid,id,2); | |
SetD(sceneid,id,2,v+v1); | |
v=GetD(sceneid,id,3); | |
SetD(sceneid,id,3,v+v2); | |
v=GetD(sceneid,id,4); | |
SetD(sceneid,id,4,v+v3); | |
end | |
--显示动画 id=-1 主角位置动画 | |
function instruct_27(id,startpic,endpic) --显示动画 | |
local old1,old2,old3; | |
if id ~=-1 then | |
old1=GetD(JY.SubScene,id,5); | |
old2=GetD(JY.SubScene,id,6); | |
old3=GetD(JY.SubScene,id,7); | |
end | |
--Cls(); | |
--ShowScreen(); | |
for i =startpic,endpic,2 do | |
local t1=lib.GetTime(); | |
if id==-1 then | |
JY.MyPic=i/2; | |
else | |
SetD(JY.SubScene,id,5,i); | |
SetD(JY.SubScene,id,6,i); | |
SetD(JY.SubScene,id,7,i); | |
end | |
DtoSMap(); | |
DrawSMap(); | |
ShowScreen(); | |
local t2=lib.GetTime(); | |
if t2-t1<CC.AnimationFrame then | |
lib.Delay(CC.AnimationFrame-(t2-t1)); | |
end | |
end | |
if id ~=-1 then | |
SetD(JY.SubScene,id,5,old1); | |
SetD(JY.SubScene,id,6,old2); | |
SetD(JY.SubScene,id,7,old3); | |
end | |
end | |
--判断品德 | |
function instruct_28(personid,vmin,vmax) --判断品德 | |
local v=JY.Person[personid]["品德"]; | |
if v >=vmin and v<=vmax then | |
return true; | |
else | |
return false; | |
end | |
end | |
--判断攻击力 | |
function instruct_29(personid,vmin,vmax) --判断攻击力 | |
local v=JY.Person[personid]["攻击力"]; | |
if v >=vmin and v<=vmax then | |
return true; | |
else | |
return false | |
end | |
end | |
--主角走动 | |
--为简化,走动使用相对值(x2-x1)(y2-y1),因此x1,y1可以为0,不必一定要为当前坐标。 | |
function instruct_30(x1,y1,x2,y2) --主角走动 | |
--Cls(); | |
--ShowScreen(); | |
if x1<x2 then | |
for i=x1+1,x2 do | |
local t1=lib.GetTime(); | |
instruct_30_sub(1); | |
local t2=lib.GetTime(); | |
if (t2-t1)<CC.PersonMoveFrame then | |
lib.Delay(CC.PersonMoveFrame-(t2-t1)); | |
end | |
end | |
elseif x1>x2 then | |
for i=x2+1,x1 do | |
local t1=lib.GetTime(); | |
instruct_30_sub(2); | |
local t2=lib.GetTime(); | |
if (t2-t1)<CC.PersonMoveFrame then | |
lib.Delay(CC.PersonMoveFrame-(t2-t1)); | |
end | |
end | |
end | |
if y1<y2 then | |
for i=y1+1,y2 do | |
local t1=lib.GetTime(); | |
instruct_30_sub(3); | |
local t2=lib.GetTime(); | |
if (t2-t1)<CC.PersonMoveFrame then | |
lib.Delay(CC.PersonMoveFrame-(t2-t1)); | |
end | |
end | |
elseif y1>y2 then | |
for i=y2+1,y1 do | |
local t1=lib.GetTime(); | |
instruct_30_sub(0); | |
local t2=lib.GetTime(); | |
if (t2-t1)<CC.PersonMoveFrame then | |
lib.Delay(CC.PersonMoveFrame-(t2-t1)); | |
end | |
end | |
end | |
end | |
--主角走动sub | |
function instruct_30_sub(direct) --主角走动sub | |
local x,y; | |
AddMyCurrentPic(); | |
x=JY.Base["人X1"]+CC.DirectX[direct+1]; | |
y=JY.Base["人Y1"]+CC.DirectY[direct+1]; | |
JY.Base["人方向"]=direct; | |
JY.MyPic=GetMyPic(); | |
DtoSMap(); | |
if SceneCanPass(x,y)==true then | |
JY.Base["人X1"]=x; | |
JY.Base["人Y1"]=y; | |
end | |
JY.Base["人X1"]=limitX(JY.Base["人X1"],1,CC.SWidth-2); | |
JY.Base["人Y1"]=limitX(JY.Base["人Y1"],1,CC.SHeight-2); | |
DrawSMap(); | |
-- Cls(); | |
ShowScreen(); | |
end | |
--判断是否够钱 | |
function instruct_31(num) --判断是否够钱 | |
local r=false; | |
for i =1,CC.MyThingNum do | |
if JY.Base["物品" .. i]==CC.MoneyID then | |
if JY.Base["物品数量" .. i]>=num then | |
r=true; | |
end | |
break; | |
end | |
end | |
return r; | |
end | |
--增加物品 | |
--num 物品数量,负数则为减少物品 | |
function instruct_32(thingid,num) --增加物品 | |
local p=1; | |
for i=1,CC.MyThingNum do | |
if JY.Base["物品" .. i]==thingid then | |
JY.Base["物品数量" .. i]=JY.Base["物品数量" .. i]+num | |
p=i; | |
break; | |
elseif JY.Base["物品" .. i]==-1 then | |
JY.Base["物品" .. i]=thingid; | |
JY.Base["物品数量" .. i]=num; | |
p=1; | |
break; | |
end | |
end | |
if JY.Base["物品数量" .. p] <=0 then | |
for i=p+1,CC.MyThingNum do | |
JY.Base["物品" .. i-1]=JY.Base["物品" .. i]; | |
JY.Base["物品数量" .. i-1]=JY.Base["物品数量" .. i]; | |
end | |
JY.Base["物品" .. CC.MyThingNum]=-1; | |
JY.Base["物品数量" .. CC.MyThingNum]=0; | |
end | |
end | |
--学会武功 | |
function instruct_33(personid,wugongid,flag) --学会武功 | |
local add=0; | |
for i=1,10 do | |
if JY.Person[personid]["武功" .. i]==0 then | |
JY.Person[personid]["武功" .. i]=wugongid; | |
JY.Person[personid]["武功等级" .. i]=0; | |
add=1 | |
break; | |
end | |
end | |
if add==0 then --,武功已满,覆盖最后一个武功 | |
JY.Person[personid]["武功10" ]=wugongid; | |
JY.Person[personid]["武功等级10"]=0; | |
end | |
if flag==0 then | |
DrawStrBoxWaitKey(string.format("%s 学会武功 %s",JY.Person[personid]["姓名"],JY.Wugong[wugongid]["名称"]),C_ORANGE,CC.DefaultFont); | |
end | |
end | |
--资质增加 | |
function instruct_34(id,value) --资质增加 | |
local add,str=AddPersonAttrib(id,"资质",value); | |
DrawStrBoxWaitKey(JY.Person[id]["姓名"] .. str,C_ORANGE,CC.DefaultFont); | |
end | |
--设置武功 | |
function instruct_35(personid,id,wugongid,wugonglevel) --设置武功 | |
if id>=0 then | |
JY.Person[personid]["武功" .. id+1]=wugongid; | |
JY.Person[personid]["武功等级" .. id+1]=wugonglevel; | |
else | |
local flag=0; | |
for i =1,10 do | |
if JY.Person[personid]["武功" .. i]==0 then | |
flag=1; | |
JY.Person[personid]["武功" .. i]=wugongid; | |
JY.Person[personid]["武功等级" .. i]=wugonglevel; | |
return; | |
end | |
end | |
if flag==0 then | |
JY.Person[personid]["武功" .. 1]=wugongid; | |
JY.Person[personid]["武功等级" .. 1]=wugonglevel; | |
end | |
end | |
end | |
--判断主角性别 | |
function instruct_36(sex) --判断主角性别 | |
if JY.Person[0]["性别"]==sex then | |
return true; | |
else | |
return false; | |
end | |
end | |
function instruct_37(v) --增加品德 | |
AddPersonAttrib(0,"品德",v); | |
end | |
--修改场景某层贴图 | |
function instruct_38(sceneid,level,oldpic,newpic) --修改场景某层贴图 | |
if sceneid==-2 then | |
sceneid=JY.SubScene; | |
end | |
for i=0,CC.SWidth-1 do | |
for j=1, CC.SHeight-1 do | |
if GetS(sceneid,i,j,level)==oldpic then | |
SetS(sceneid,i,j,level,newpic) | |
end | |
end | |
end | |
end | |
function instruct_39(sceneid) --打开场景 | |
JY.Scene[sceneid]["进入条件"]=0; | |
end | |
function instruct_40(v) --改变主角方向 | |
JY.Base["人方向"]=v; | |
JY.MyPic=GetMyPic(); | |
end | |
function instruct_41(personid,thingid,num) --其他人员增加物品 | |
local k=0; | |
for i =1, 4 do --已有物品 | |
if JY.Person[personid]["携带物品" .. i]==thingid then | |
JY.Person[personid]["携带物品数量" .. i]=JY.Person[personid]["携带物品数量" .. i]+num; | |
k=i; | |
break | |
end | |
end | |
--物品减少到0,则后面物品往前移动 | |
if k>0 and JY.Person[personid]["携带物品数量" .. k] <=0 then | |
for i=k+1,4 do | |
JY.Person[personid]["携带物品" .. i-1]=JY.Person[personid]["携带物品" .. i]; | |
JY.Person[personid]["携带物品数量" .. i-1]=JY.Person[personid]["携带物品数量" .. i]; | |
end | |
JY.Person[personid]["携带物品" .. 4]=-1; | |
JY.Person[personid]["携带物品数量" .. 4]=0; | |
end | |
if k==0 then --没有物品,注意此处不考虑超过4个物品的情况,如果超过,则无法加入。 | |
for i =1, 4 do --已有物品 | |
if JY.Person[personid]["携带物品" .. i]==-1 then | |
JY.Person[personid]["携带物品" .. i]=thingid; | |
JY.Person[personid]["携带物品数量" .. i]=num; | |
break | |
end | |
end | |
end | |
end | |
function instruct_42() --队伍中是否有女性 | |
local r=false; | |
for i =1,CC.TeamNum do | |
if JY.Base["队伍" .. i] >=0 then | |
if JY.Person[JY.Base["队伍" .. i]]["性别"]==1 then | |
r=true; | |
end | |
end | |
end | |
return r; | |
end | |
function instruct_43(thingid) --是否有某种物品 | |
return instruct_18(thingid); | |
end | |
function instruct_44(id1,startpic1,endpic1,id2,startpic2,endpic2) --同时显示两个动画 | |
local old1=GetD(JY.SubScene,id1,5); | |
local old2=GetD(JY.SubScene,id1,6); | |
local old3=GetD(JY.SubScene,id1,7); | |
local old4=GetD(JY.SubScene,id2,5); | |
local old5=GetD(JY.SubScene,id2,6); | |
local old6=GetD(JY.SubScene,id2,7); | |
--Cls(); | |
--ShowScreen(); | |
for i =startpic1,endpic1,2 do | |
local t1=lib.GetTime(); | |
if id1==-1 then | |
JY.MyPic=i/2; | |
else | |
SetD(JY.SubScene,id1,5,i); | |
SetD(JY.SubScene,id1,6,i); | |
SetD(JY.SubScene,id1,7,i); | |
end | |
if id2==-1 then | |
JY.MyPic=i/2; | |
else | |
SetD(JY.SubScene,id2,5,i-startpic1+startpic2); | |
SetD(JY.SubScene,id2,6,i-startpic1+startpic2); | |
SetD(JY.SubScene,id2,7,i-startpic1+startpic2); | |
end | |
DtoSMap(); | |
DrawSMap(); | |
ShowScreen(); | |
local t2=lib.GetTime(); | |
if t2-t1<CC.AnimationFrame then | |
lib.Delay(CC.AnimationFrame-(t2-t1)); | |
end | |
end | |
SetD(JY.SubScene,id1,5,old1); | |
SetD(JY.SubScene,id1,6,old2); | |
SetD(JY.SubScene,id1,7,old3); | |
SetD(JY.SubScene,id2,5,old4); | |
SetD(JY.SubScene,id2,6,old5); | |
SetD(JY.SubScene,id2,7,old6); | |
end | |
function instruct_45(id,value) --增加轻功 | |
local add,str=AddPersonAttrib(id,"轻功",value); | |
DrawStrBoxWaitKey(JY.Person[id]["姓名"] .. str,C_ORANGE,CC.DefaultFont); | |
end | |
function instruct_46(id,value) --增加内力 | |
local add,str=AddPersonAttrib(id,"内力最大值",value); | |
AddPersonAttrib(id,"内力",0); | |
DrawStrBoxWaitKey(JY.Person[id]["姓名"] .. str,C_ORANGE,CC.DefaultFont); | |
end | |
function instruct_47(id,value) | |
local add,str=AddPersonAttrib(id,"攻击力",value); --增加攻击力 | |
DrawStrBoxWaitKey(JY.Person[id]["姓名"] .. str,C_ORANGE,CC.DefaultFont); | |
end | |
function instruct_48(id,value) --增加生命 | |
local add,str=AddPersonAttrib(id,"生命最大值",value); | |
AddPersonAttrib(id,"生命",0); | |
if instruct_16(id)==true then --我方队员,显示增加 | |
DrawStrBoxWaitKey(JY.Person[id]["姓名"] .. str,C_ORANGE,CC.DefaultFont); | |
end | |
end | |
function instruct_49(personid,value) --设置内力属性 | |
JY.Person[personid]["内力性质"]=value; | |
end | |
--判断是否有5种物品 | |
function instruct_50(id1,id2,id3,id4,id5) --判断是否有5种物品 | |
local num=0; | |
if instruct_18(id1)==true then | |
num=num+1; | |
end | |
if instruct_18(id2)==true then | |
num=num+1; | |
end | |
if instruct_18(id3)==true then | |
num=num+1; | |
end | |
if instruct_18(id4)==true then | |
num=num+1; | |
end | |
if instruct_18(id5)==true then | |
num=num+1; | |
end | |
if num==5 then | |
return true; | |
else | |
return false; | |
end | |
end | |
function instruct_51() --问软体娃娃 | |
instruct_1(2547+Rnd(18),114,0); | |
end | |
function instruct_52() --看品德 | |
DrawStrBoxWaitKey(string.format("你现在的品德指数为: %d",JY.Person[0]["品德"]),C_ORANGE,CC.DefaultFont); | |
end | |
function instruct_53() --看声望 | |
DrawStrBoxWaitKey(string.format("你现在的声望指数为: %d",JY.Person[0]["声望"]),C_ORANGE,CC.DefaultFont); | |
end | |
function instruct_54() --开放其他场景 | |
for i = 0, JY.SceneNum-1 do | |
JY.Scene[i]["进入条件"]=0; | |
end | |
JY.Scene[2]["进入条件"]=2; --云鹤崖 | |
JY.Scene[38]["进入条件"]=2; --摩天崖 | |
JY.Scene[75]["进入条件"]=1; --桃花岛 | |
JY.Scene[80]["进入条件"]=1; --绝情谷底 | |
end | |
function instruct_55(id,num) --判断D*编号的触发事件 | |
if GetD(JY.SubScene,id,2)==num then | |
return true; | |
else | |
return false; | |
end | |
end | |
function instruct_56(v) --增加声望 | |
JY.Person[0]["声望"]=JY.Person[0]["声望"]+v; | |
instruct_2_sub(); --是否可以增加武林帖 | |
end | |
--高昌迷宫劈门 | |
function instruct_57() --高昌迷宫劈门 | |
instruct_27(-1,7664,7674); | |
--Cls(); | |
--ShowScreen(); | |
for i=0,56,2 do | |
local t1=lib.GetTime(); | |
if JY.MyPic< 7688/2 then | |
JY.MyPic=(7676+i)/2; | |
end | |
SetD(JY.SubScene,2,5,i+7690); | |
SetD(JY.SubScene,2,6,i+7690); | |
SetD(JY.SubScene,2,7,i+7690); | |
SetD(JY.SubScene,3,5,i+7748); | |
SetD(JY.SubScene,3,6,i+7748); | |
SetD(JY.SubScene,3,7,i+7748); | |
SetD(JY.SubScene,4,5,i+7806); | |
SetD(JY.SubScene,4,6,i+7806); | |
SetD(JY.SubScene,4,7,i+7806); | |
DtoSMap(); | |
DrawSMap(); | |
ShowScreen(); | |
local t2=lib.GetTime(); | |
if t2-t1<CC.AnimationFrame then | |
lib.Delay(CC.AnimationFrame-(t2-t1)); | |
end | |
end | |
end | |
--武道大会比武 | |
function instruct_58() --武道大会比武 | |
local group=5 --比武的组数 | |
local num1 = 6 --每组有几个战斗 | |
local num2 = 3 --选择的战斗数 | |
local startwar=102 --起始战斗编号 | |
local flag={}; | |
for i = 0,group-1 do | |
for j=0,num1-1 do | |
flag[j]=0; | |
end | |
for j = 1,num2 do | |
local r; | |
while true do --选择一场战斗 | |
r=Rnd(num1); | |
if flag[r]==0 then | |
flag[r]=1; | |
break; | |
end | |
end | |
local warnum =r+i*num1; --武道大会战斗编号 | |
WarLoad(warnum + startwar); | |
instruct_1(2854+warnum, JY.Person[WAR.Data["敌人1"]]["头像代号"], 0); | |
instruct_0(); | |
if WarMain(warnum + startwar, 0) ==true then --赢 | |
instruct_0(); | |
instruct_13(); | |
TalkEx("还有那位前辈肯赐教?", 0, 1) | |
instruct_0(); | |
else | |
instruct_15(); | |
return; | |
end | |
end | |
if i < group - 1 then | |
TalkEx("少侠已连战三场,*可先休息再战.", 70, 0); | |
instruct_0(); | |
instruct_14(); | |
lib.Delay(300); | |
if JY.Person[0]["受伤程度"] < 50 and JY.Person[0]["中毒程度"] <= 0 then | |
JY.Person[0]["受伤程度"] = 0 | |
AddPersonAttrib(0,"体力",math.huge); | |
AddPersonAttrib(0,"内力",math.huge); | |
AddPersonAttrib(0,"生命",math.huge); | |
end | |
instruct_13(); | |
TalkEx("我已经休息够了,*有谁要再上?",0,1); | |
instruct_0(); | |
end | |
end | |
TalkEx("接下来换谁?**....*....***没有人了吗?",0,1); | |
instruct_0(); | |
TalkEx("如果还没有人要出来向这位*少侠挑战,那麽这武功天下*第一之名,武林盟主之位,*就由这位少侠夺得.***......*......*......*好,恭喜少侠,这武林盟主*之位就由少侠获得,而这把*”武林神杖”也由你保管.",70,0); | |
instruct_0(); | |
TalkEx("恭喜少侠!",12,0); | |
instruct_0(); | |
TalkEx("小兄弟,恭喜你!",64,4); | |
instruct_0(); | |
TalkEx("好,今年的武林大会到此已*圆满结束,希望明年各位武*林同道能再到我华山一游.",19,0); | |
instruct_0(); | |
instruct_14(); | |
for i = 24,72 do | |
instruct_3(-2, i, 0, 0, -1, -1, -1, -1, -1, -1, -2, -2, -2) | |
end | |
instruct_0(); | |
instruct_13(); | |
TalkEx("历经千辛万苦,我终於打败*群雄,得到这武林盟主之位*及神杖.*但是”圣堂”在那呢?*为什麽没人告诉我,难道大*家都不知道.*这会儿又有的找了.", 0, 1) | |
instruct_0(); | |
instruct_2(143, 1) --得到神杖 | |
end | |
--全体队员离队 | |
function instruct_59() --全体队员离队 | |
for i=CC.TeamNum,2,-1 do | |
if JY.Base["队伍" .. i]>=0 then | |
instruct_21(JY.Base["队伍" .. i]); | |
end | |
end | |
for i,v in ipairs(CC.AllPersonExit) do | |
instruct_3(v[1],v[2],0,0,-1,-1,-1,-1,-1,-1,0,-2,-2); | |
end | |
end | |
--判断D*图片 | |
function instruct_60(sceneid,id,num) --判断D*图片 | |
if sceneid==-2 then | |
sceneid=JY.SubScene; | |
end | |
if id==-2 then | |
id=JY.CurrentD; | |
end | |
if GetD(sceneid,id,5)==num then | |
return true; | |
else | |
return false; | |
end | |
end | |
--判断是否放完14天书 | |
function instruct_61() --判断是否放完14天书 | |
for i=11,24 do | |
if GetD(JY.SubScene,i,5) ~= 4664 then | |
return false; | |
end | |
end | |
return true; | |
end | |
--播放时空机动画,结束 | |
function instruct_62(id1,startnum1,endnum1,id2,startnum2,endnum2) --播放时空机动画,结束 | |
JY.MyPic=-1; | |
instruct_44(id1,startnum1,endnum1,id2,startnum2,endnum2); | |
--此处应该插入正规的片尾动画。这里暂时用图片代替 | |
lib.LoadPicture(CONFIG.PicturePath .."end.png",-1,-1); | |
ShowScreen(); | |
PlayMIDI(24); | |
lib.Delay(5000); | |
lib.GetKey(); | |
WaitKey(); | |
JY.Status=GAME_END; | |
end | |
--设置性别 | |
function instruct_63(personid,sex) --设置性别 | |
JY.Person[personid]["性别"]=sex | |
end | |
--小宝卖东西 | |
function instruct_64() --小宝卖东西 | |
local headid=111; --小宝头像 | |
local id=-1; | |
for i=0,JY.ShopNum-1 do --找到当前商店id | |
if CC.ShopScene[i].sceneid==JY.SubScene then | |
id=i; | |
break; | |
end | |
end | |
if id<0 then | |
return ; | |
end | |
TalkEx("这位小哥,看看有什麽需要*的,小宝我卖的东西价钱绝*对公道.",headid,0); | |
local menu={}; | |
for i=1,5 do | |
menu[i]={}; | |
local thingid=JY.Shop[id]["物品" ..i]; | |
menu[i][1]=string.format("%-12s %5d",JY.Thing[thingid]["名称"],JY.Shop[id]["物品价格" ..i]); | |
menu[i][2]=nil; | |
if JY.Shop[id]["物品数量" ..i] >0 then | |
menu[i][3]=1; | |
else | |
menu[i][3]=0; | |
end | |
end | |
local x1=(CC.ScreenW-9*CC.DefaultFont-2*CC.MenuBorderPixel)/2; | |
local y1=(CC.ScreenH-5*CC.DefaultFont-4*CC.RowPixel-2*CC.MenuBorderPixel)/2; | |
local r=ShowMenu(menu,5,0,x1,y1,0,0,1,1,CC.DefaultFont,C_ORANGE, C_WHITE); | |
if r>0 then | |
if instruct_31(JY.Shop[id]["物品价格" ..r])==false then | |
TalkEx("非常抱歉,*你身上的钱似乎不够.",headid,0); | |
else | |
JY.Shop[id]["物品数量" ..r]=JY.Shop[id]["物品数量" ..r]-1; | |
instruct_32(CC.MoneyID,-JY.Shop[id]["物品价格" ..r]); | |
instruct_32(JY.Shop[id]["物品" ..r],1); | |
TalkEx("大爷买了我小宝的东西,*保证绝不後悔.",headid,0); | |
end | |
end | |
for i,v in ipairs(CC.ShopScene[id].d_leave) do | |
instruct_3(-2,v,0,-2,-1,-1,939,-1,-1,-1,-2,-2,-2); --设置离开场景时触发小宝离开事件, | |
end | |
end | |
--小宝去其他客栈 | |
function instruct_65() --小宝去其他客栈 | |
local id=-1; | |
for i=0,JY.ShopNum-1 do --找到当前商店id | |
if CC.ShopScene[i].sceneid==JY.SubScene then | |
id=i; | |
break; | |
end | |
end | |
if id<0 then | |
return ; | |
end | |
---清除当前商店所有小宝D× | |
instruct_3(-2,CC.ShopScene[id].d_shop,0,-2,-1,-1,-1,-1,-1,-1,-2,-2,-2); | |
for i,v in ipairs(CC.ShopScene[id].d_leave) do | |
instruct_3(-2,v,0,-2,-1,-1,-1,-1,-1,-1,-2,-2,-2); | |
end | |
local newid=id+1; --暂时用顺序取代随机, | |
if newid>=5 then | |
newid=0; | |
end | |
--设置新的小宝商店位置 | |
instruct_3(CC.ShopScene[newid].sceneid,CC.ShopScene[newid].d_shop,1,-2,938,-1,-1,8256,8256,8256,-2,-2,-2); | |
end | |
--播放音乐 | |
function instruct_66(id) --播放音乐 | |
PlayMIDI(id); | |
end | |
--播放音效 | |
function instruct_67(id) --播放音效 | |
PlayWavAtk(id); | |
end | |
--------------------------------------------------------------------------- | |
---------------------------------战斗----------------------------------- | |
--入口函数为WarMain,由战斗指令调用 | |
--设置战斗全程变量 | |
function WarSetGlobal() --设置战斗全程变量 | |
WAR={}; | |
WAR.Data={}; --战斗信息,war.sta文件 | |
WAR.SelectPerson={} --设置选择参战人 0 未选,1 选,不可取消,2 选,可取消。选择参展人菜单调用使用 | |
WAR.Person={}; --战斗人物信息 | |
for i=0,26-1 do | |
WAR.Person[i]={}; | |
WAR.Person[i]["人物编号"]=-1; | |
WAR.Person[i]["我方"]=true; --true 我方,false敌人 | |
WAR.Person[i]["坐标X"]=-1; | |
WAR.Person[i]["坐标Y"]=-1; | |
WAR.Person[i]["死亡"]=true; | |
WAR.Person[i]["人方向"]=-1; | |
WAR.Person[i]["贴图"]=-1; | |
WAR.Person[i]["贴图类型"]=0; --0 wmap中贴图,1 fight***中贴图 | |
WAR.Person[i]["轻功"]=0; | |
WAR.Person[i]["移动步数"]=0; | |
WAR.Person[i]["点数"]=0; | |
WAR.Person[i]["经验"]=0; | |
WAR.Person[i]["自动选择对手"]=-1; --自动战斗中每个人选择的战斗对手 | |
end | |
WAR.PersonNum=0; --战斗人物个数 | |
WAR.AutoFight=0; --我方自动战斗参数 0 手动,1 自动。 | |
WAR.CurID=-1; --当前操作战斗人id | |
WAR.ShowHead=0; --是否显示头像 | |
WAR.Effect=0; --效果,用来确认人物头上数字的颜色 | |
--2 杀生命 , 3 杀内力, 4 医疗 , 5 用毒 , 6 解毒 | |
WAR.EffectColor={}; ---定义人物头上数字的颜色 | |
WAR.EffectColor[2]=RGB(236, 200, 40); | |
WAR.EffectColor[3]=RGB(112, 12, 112); | |
WAR.EffectColor[4]=RGB(236, 200, 40); | |
WAR.EffectColor[5]=RGB(96, 176, 64) | |
WAR.EffectColor[6]=RGB(104, 192, 232); | |
WAR.EffectXY=nil --保存武功效果产生的坐标 | |
WAR.EffectXYNum=0; --坐标个数 | |
end | |
--加载战斗数据 | |
function WarLoad(warid) --加载战斗数据 | |
WarSetGlobal(); --初始化战斗变量 | |
local data=Byte.create(CC.WarDataSize); --读取战斗数据 | |
Byte.loadfile(data,CC.WarFile,warid*CC.WarDataSize,CC.WarDataSize); | |
LoadData(WAR.Data,CC.WarData_S,data); | |
end | |
--战斗主函数 | |
--warid 战斗编号 | |
--isexp 输后是否有经验 0 没经验,1 有经验 | |
--返回 true 战斗胜利,false 失败 | |
function WarMain(warid,isexp) --战斗主函数 | |
lib.Debug(string.format("war start. warid=%d",warid)); | |
WarLoad(warid); | |
WarSelectTeam(); --选择我方 | |
WarSelectEnemy(); --选择敌人 | |
CleanMemory() | |
lib.PicInit(); | |
lib.ShowSlow(50,1) ; --场景变暗 | |
WarLoadMap(WAR.Data["地图"]); --加载战斗地图 | |
JY.Status=GAME_WMAP; | |
--加载贴图文件 | |
lib.PicLoadFile(CC.WMAPPicFile[1],CC.WMAPPicFile[2],0); | |
lib.PicLoadFile(CC.HeadPicFile[1],CC.HeadPicFile[2],1); | |
if CC.LoadThingPic==1 then | |
lib.PicLoadFile(CC.ThingPicFile[1],CC.ThingPicFile[2],2); | |
end | |
lib.PicLoadFile(CC.EffectFile[1],CC.EffectFile[2],3); | |
PlayMIDI(WAR.Data["音乐"]); | |
local first=0; --第一次显示战斗标记 | |
local warStatus; --战斗状态 | |
WarPersonSort(); --战斗人按轻功排序 | |
for i=0,WAR.PersonNum-1 do | |
local pid=WAR.Person[i]["人物编号"]; | |
lib.PicLoadFile(string.format(CC.FightPicFile[1],JY.Person[pid]["头像代号"]), | |
string.format(CC.FightPicFile[2],JY.Person[pid]["头像代号"]), | |
4+i); | |
end | |
while true do --战斗主循环 | |
for i=0,WAR.PersonNum-1 do | |
WAR.Person[i]["贴图"]=WarCalPersonPic(i); | |
end | |
for i=0,WAR.PersonNum-1 do ---计算各人的轻功,包括装备加成 | |
local id=WAR.Person[i]["人物编号"]; | |
local move=math.modf(WAR.Person[i]["轻功"]/15)-math.modf(JY.Person[id]["受伤程度"]/40); | |
if move<0 then | |
move=0; | |
end | |
WAR.Person[i]["移动步数"]=move; | |
end | |
WarSetPerson(); --设置战斗人物位置 | |
local p=0; | |
while p<WAR.PersonNum do --每回合战斗循环,每个人轮流战斗 | |
collectgarbage("step",0); | |
WAR.Effect=0; | |
if WAR.AutoFight==1 then --我方自动战斗时读取键盘,看是否取消 | |
local keypress=lib.GetKey(); | |
if keypress==VK_SPACE or keypress==VK_RETURN then | |
WAR.AutoFight=0; | |
end | |
end | |
if WAR.Person[p]["死亡"]==false then | |
WAR.CurID=p; | |
if first==0 then --第一次渐亮显示 | |
WarDrawMap(0); | |
lib.ShowSlow(50,0) | |
first=1; | |
else | |
-- WarDrawMap(0); | |
--WarShowHead(); | |
-- ShowScreen(); | |
end | |
local r; | |
if WAR.Person[p]["我方"]==true then | |
if WAR.AutoFight==0 then | |
r=War_Manual(); --手动战斗 | |
else | |
r=War_Auto(); --自动战斗 | |
end | |
else | |
r=War_Auto(); --自动战斗 | |
end | |
warStatus=War_isEnd(); --战斗是否结束? 0继续,1赢,2输 | |
if math.abs(r)==7 then --等待 | |
p=p-1; | |
end | |
if warStatus>0 then | |
break; | |
end | |
end | |
p=p+1; | |
end | |
if warStatus>0 then | |
break; | |
end | |
War_PersonLostLife(); | |
end | |
local r; | |
WAR.ShowHead=0; | |
if warStatus==1 then | |
DrawStrBoxWaitKey("战斗胜利",C_WHITE,CC.DefaultFont); | |
r=true; | |
elseif warStatus==2 then | |
DrawStrBoxWaitKey("战斗失败",C_WHITE,CC.DefaultFont); | |
r=false; | |
end | |
War_EndPersonData(isexp,warStatus); --战斗后设置人物参数 | |
lib.ShowSlow(50,1); | |
if JY.Scene[JY.SubScene]["进门音乐"]>=0 then | |
PlayMIDI(JY.Scene[JY.SubScene]["进门音乐"]); | |
else | |
PlayMIDI(0); | |
end | |
CleanMemory(); | |
lib.PicInit(); | |
lib.PicLoadFile(CC.SMAPPicFile[1],CC.SMAPPicFile[2],0); | |
lib.PicLoadFile(CC.HeadPicFile[1],CC.HeadPicFile[2],1); | |
if CC.LoadThingPic==1 then | |
lib.PicLoadFile(CC.ThingPicFile[1],CC.ThingPicFile[2],2); | |
end | |
JY.Status=GAME_SMAP; | |
return r; | |
end | |
function War_PersonLostLife() --计算战斗后每回合由于中毒或受伤而掉血 | |
for i=0,WAR.PersonNum-1 do | |
local pid=WAR.Person[i]["人物编号"] | |
if WAR.Person[i]["死亡"]==false then | |
if JY.Person[pid]["受伤程度"]>0 then | |
local dec=math.modf(JY.Person[pid]["受伤程度"]/20); | |
AddPersonAttrib(pid,"生命",-dec); | |
end | |
if JY.Person[pid]["中毒程度"]>0 then | |
local dec=math.modf(JY.Person[pid]["中毒程度"]/10); | |
AddPersonAttrib(pid,"生命",-dec); | |
end | |
if JY.Person[pid]["生命"]<=0 then | |
JY.Person[pid]["生命"]=1; | |
end | |
end | |
end | |
end | |
function War_EndPersonData(isexp,warStatus) --战斗以后设置人物参数 | |
--敌方人员参数恢复 | |
for i=0,WAR.PersonNum-1 do | |
local pid=WAR.Person[i]["人物编号"] | |
if WAR.Person[i]["我方"]==false then | |
JY.Person[pid]["生命"]=JY.Person[pid]["生命最大值"]; | |
JY.Person[pid]["内力"]=JY.Person[pid]["内力最大值"]; | |
JY.Person[pid]["体力"]=CC.PersonAttribMax["体力"]; | |
JY.Person[pid]["受伤程度"]=0; | |
JY.Person[pid]["中毒程度"]=0; | |
end | |
end | |
--我方人员参数恢复,输赢都有 | |
for i=0,WAR.PersonNum-1 do | |
local pid=WAR.Person[i]["人物编号"] | |
if WAR.Person[i]["我方"]==true then | |
if JY.Person[pid]["生命"]<JY.Person[pid]["生命最大值"]/5 then | |
JY.Person[pid]["生命"]=math.modf(JY.Person[pid]["生命最大值"]/5); | |
end | |
if JY.Person[pid]["体力"]<10 then | |
JY.Person[pid]["体力"]=10 ; | |
end | |
end | |
end | |
if warStatus==2 and isexp==0 then --输,没有经验,退出 | |
return ; | |
end | |
local liveNum=0; --计算我方活着的人数 | |
for i=0,WAR.PersonNum-1 do | |
if WAR.Person[i]["我方"]==true and JY.Person[WAR.Person[i]["人物编号"]]["生命"]>0 then | |
liveNum=liveNum+1; | |
end | |
end | |
--分配战斗经验---基本经验,战斗数据中的 | |
if warStatus==1 then --赢了才有 | |
for i=0,WAR.PersonNum-1 do | |
local pid=WAR.Person[i]["人物编号"] | |
if WAR.Person[i]["我方"]==true then | |
if JY.Person[pid]["生命"]>0 then | |
WAR.Person[i]["经验"]=WAR.Person[i]["经验"] + math.modf(WAR.Data["经验"]/liveNum); | |
end | |
end | |
end | |
end | |
--每个人经验增加,以及升级 | |
for i=0,WAR.PersonNum-1 do | |
local pid=WAR.Person[i]["人物编号"]; | |
AddPersonAttrib(pid,"物品修炼点数",math.modf(WAR.Person[i]["经验"]*8/10)); | |
AddPersonAttrib(pid,"修炼点数",math.modf(WAR.Person[i]["经验"]*8/10)); | |
AddPersonAttrib(pid,"经验",WAR.Person[i]["经验"]); | |
if WAR.Person[i]["我方"]==true then | |
DrawStrBoxWaitKey( string.format("%s 获得经验点数 %d",JY.Person[pid]["姓名"],WAR.Person[i]["经验"]),C_WHITE,CC.DefaultFont); | |
local r=War_AddPersonLevel(pid); --人物升级 | |
if r==true then | |
DrawStrBoxWaitKey( string.format("%s 升级了",JY.Person[pid]["姓名"]),C_WHITE,CC.DefaultFont); | |
end | |
end | |
War_PersonTrainBook(pid); --修炼秘籍 | |
War_PersonTrainDrug(pid); --修炼药品 | |
end | |
end | |
--人物是否升级 | |
--pid 人id | |
--返回 true 升级,false不升级 | |
function War_AddPersonLevel(pid) --人物是否升级 | |
local tmplevel=JY.Person[pid]["等级"]; | |
if tmplevel>=CC.Level then --级别到顶 | |
return false; | |
end | |
if JY.Person[pid]["经验"]<CC.Exp[tmplevel] then --经验不够升级 | |
return false | |
end | |
while true do --判断可以升几级 | |
if tmplevel >= CC.Level then | |
break; | |
end | |
if JY.Person[pid]["经验"]>=CC.Exp[tmplevel] then | |
tmplevel=tmplevel+1; | |
else | |
break; | |
end | |
end | |
local leveladd=tmplevel-JY.Person[pid]["等级"]; --升级次数 | |
JY.Person[pid]["等级"]=JY.Person[pid]["等级"]+leveladd; | |
AddPersonAttrib(pid,"生命最大值", (JY.Person[pid]["生命增长"]+Rnd(3))*leveladd*3); | |
JY.Person[pid]["生命"]=JY.Person[pid]["生命最大值"]; | |
JY.Person[pid]["体力"]=CC.PersonAttribMax["体力"]; | |
JY.Person[pid]["受伤程度"]=0; | |
JY.Person[pid]["中毒程度"]=0; | |
local cleveradd; | |
if JY.Person[pid]["资质"]<30 then | |
cleveradd=2; | |
elseif JY.Person[pid]["资质"]<50 then | |
cleveradd=3; | |
elseif JY.Person[pid]["资质"]<70 then | |
cleveradd=4; | |
elseif JY.Person[pid]["资质"]<90 then | |
cleveradd=5; | |
else | |
cleveradd=6; | |
end | |
cleveradd=Rnd(cleveradd)+1; --按照资质计算的增长点,越高则技能增加越多,而内力增加越少。 | |
AddPersonAttrib(pid,"内力最大值", (9-cleveradd)*leveladd*4); --聪明人不练内力 | |
JY.Person[pid]["内力"]=JY.Person[pid]["内力最大值"]; | |
AddPersonAttrib(pid,"攻击力", cleveradd*leveladd); | |
AddPersonAttrib(pid,"防御力", cleveradd*leveladd); | |
AddPersonAttrib(pid,"轻功", cleveradd*leveladd); | |
if JY.Person[pid]["医疗能力"]>=20 then | |
AddPersonAttrib(pid,"医疗能力", Rnd(3)); | |
end | |
if JY.Person[pid]["用毒能力"]>=20 then | |
AddPersonAttrib(pid,"用毒能力", Rnd(3)); | |
end | |
if JY.Person[pid]["解毒能力"]>=20 then | |
AddPersonAttrib(pid,"解毒能力", Rnd(3)); | |
end | |
if JY.Person[pid]["拳掌功夫"]>=20 then | |
AddPersonAttrib(pid,"拳掌功夫", Rnd(3)); | |
end | |
if JY.Person[pid]["御剑能力"]>=20 then | |
AddPersonAttrib(pid,"御剑能力", Rnd(3)); | |
end | |
if JY.Person[pid]["耍刀技巧"]>=20 then | |
AddPersonAttrib(pid,"耍刀技巧", Rnd(3)); | |
end | |
if JY.Person[pid]["暗器技巧"]>=20 then | |
AddPersonAttrib(pid,"暗器技巧", Rnd(3)); | |
end | |
return true; | |
end | |
--修炼秘籍 | |
function War_PersonTrainBook(pid) --战斗后修炼秘籍是否成功 | |
local p=JY.Person[pid]; | |
local thingid=p["修炼物品"]; | |
if thingid<0 then | |
return ; | |
end | |
local wugongid=JY.Thing[thingid]["练出武功"]; | |
local needpoint=TrainNeedExp(pid); --计算修炼成功需要点数 | |
if p["修炼点数"]>=needpoint then --修炼成功 | |
DrawStrBoxWaitKey( string.format("%s 修炼 %s 成功",p["姓名"],JY.Thing[thingid]["名称"]),C_WHITE,CC.DefaultFont); | |
AddPersonAttrib(pid,"生命最大值",JY.Thing[thingid]["加生命最大值"]); | |
if JY.Thing[thingid]["改变内力性质"]==2 then | |
p["内力性质"]=2; | |
end | |
AddPersonAttrib(pid,"内力最大值",JY.Thing[thingid]["加内力最大值"]); | |
AddPersonAttrib(pid,"攻击力",JY.Thing[thingid]["加攻击力"]); | |
AddPersonAttrib(pid,"轻功",JY.Thing[thingid]["加轻功"]); | |
AddPersonAttrib(pid,"防御力",JY.Thing[thingid]["加防御力"]); | |
AddPersonAttrib(pid,"医疗能力",JY.Thing[thingid]["加医疗能力"]); | |
AddPersonAttrib(pid,"用毒能力",JY.Thing[thingid]["加用毒能力"]); | |
AddPersonAttrib(pid,"解毒能力",JY.Thing[thingid]["加解毒能力"]); | |
AddPersonAttrib(pid,"抗毒能力",JY.Thing[thingid]["加抗毒能力"]); | |
AddPersonAttrib(pid,"拳掌功夫",JY.Thing[thingid]["加拳掌功夫"]); | |
AddPersonAttrib(pid,"御剑能力",JY.Thing[thingid]["加御剑能力"]); | |
AddPersonAttrib(pid,"耍刀技巧",JY.Thing[thingid]["加耍刀技巧"]); | |
AddPersonAttrib(pid,"特殊兵器",JY.Thing[thingid]["加特殊兵器"]); | |
AddPersonAttrib(pid,"暗器技巧",JY.Thing[thingid]["加暗器技巧"]); | |
AddPersonAttrib(pid,"武学常识",JY.Thing[thingid]["加武学常识"]); | |
AddPersonAttrib(pid,"品德",JY.Thing[thingid]["加品德"]); | |
AddPersonAttrib(pid,"攻击带毒",JY.Thing[thingid]["加攻击带毒"]); | |
if JY.Thing[thingid]["加攻击次数"]==1 then | |
p["左右互搏"]=1; | |
end | |
p["修炼点数"]=0; | |
if wugongid>=0 then | |
local oldwugong=0; | |
for i =1,10 do | |
if p["武功" .. i]==wugongid then | |
oldwugong=1; | |
p["武功等级" .. i]=p["武功等级" .. i]+100; | |
DrawStrBoxWaitKey(string.format("%s 升为第%s级",JY.Wugong[wugongid]["名称"],math.modf(p["武功等级" ..i]/100)+1),C_WHITE,CC.DefaultFont); | |
break; | |
end | |
end | |
if oldwugong==0 then --新的武功 | |
for i=1,10 do | |
if p["武功" .. i]==0 then | |
p["武功" .. i]=wugongid; | |
break; | |
end | |
end | |
---这里不考虑10个武功已满的时候如何增加新的武功 | |
end | |
end | |
end | |
end | |
--练出药品 | |
function War_PersonTrainDrug(pid) --战斗后是否修炼出物品 | |
local p=JY.Person[pid]; | |
local thingid=p["修炼物品"]; | |
if thingid<0 then | |
return ; | |
end | |
if JY.Thing[thingid]["练出物品需经验"] <=0 then --不可以修炼出物品 | |
return ; | |
end | |
local needpoint=(7-math.modf(p["资质"]/15))*JY.Thing[thingid]["练出物品需经验"]; | |
if p["物品修炼点数"]< needpoint then | |
return ; | |
end | |
local haveMaterial=0; --是否有需要的材料 | |
local MaterialNum=-1; | |
for i=1,CC.MyThingNum do | |
if JY.Base["物品" .. i]==JY.Thing[thingid]["需材料"] then | |
haveMaterial=1; | |
MaterialNum=JY.Base["物品数量" .. i] | |
break; | |
end | |
end | |
if haveMaterial==1 then --有材料 | |
local enough={}; | |
local canMake=0; | |
for i=1,5 do --根据需要材料的数量,标记可以练出哪些物品 | |
if JY.Thing[thingid]["练出物品" .. i] >=0 and MaterialNum >= JY.Thing[thingid]["需要物品数量" .. i] then | |
canMake=1; | |
enough[i]=1; | |
else | |
enough[i]=0; | |
end | |
end | |
if canMake ==1 then --可练出物品 | |
local makeID; | |
while true do --随机选择练出的物品,必须是前面enough数组中标记可以练出的 | |
makeID=Rnd(5)+1; | |
if enough[makeID]==1 then | |
break; | |
end | |
end | |
local newThingID=JY.Thing[thingid]["练出物品" .. makeID]; | |
DrawStrBoxWaitKey(string.format("%s 制造出 %s",p["姓名"],JY.Thing[newThingID]["名称"]),C_WHITE,CC.DefaultFont); | |
if instruct_18(newThingID)==true then --已经有物品 | |
instruct_32(newThingID,1); | |
else | |
instruct_32(newThingID,1+Rnd(3)); | |
end | |
instruct_32(JY.Thing[thingid]["需材料"],-JY.Thing[thingid]["需要物品数量" .. makeID]); | |
p["物品修炼点数"]=0; | |
end | |
end | |
end | |
--战斗是否结束 | |
--返回:0 继续 1 赢 2 输 | |
function War_isEnd() --战斗是否结束 | |
for i=0,WAR.PersonNum-1 do | |
if JY.Person[WAR.Person[i]["人物编号"]]["生命"]<=0 then | |
WAR.Person[i]["死亡"]=true; | |
end | |
end | |
WarSetPerson(); --设置战斗人物位置 | |
Cls(); | |
ShowScreen(); | |
local myNum=0; | |
local EmenyNum=0; | |
for i=0,WAR.PersonNum-1 do | |
if WAR.Person[i]["死亡"]==false then | |
if WAR.Person[i]["我方"]==true then | |
myNum=1; | |
else | |
EmenyNum=1; | |
end | |
end | |
end | |
if EmenyNum==0 then | |
return 1; | |
end | |
if myNum==0 then | |
return 2; | |
end | |
return 0; | |
end | |
--选择我方参战人 | |
function WarSelectTeam() --选择我方参战人 | |
WAR.PersonNum=0; | |
for i=1,6 do | |
local id=WAR.Data["自动选择参战人" .. i]; | |
if id>=0 then | |
WAR.Person[WAR.PersonNum]["人物编号"]=id; | |
WAR.Person[WAR.PersonNum]["我方"]=true; | |
WAR.Person[WAR.PersonNum]["坐标X"]=WAR.Data["我方X" .. i]; | |
WAR.Person[WAR.PersonNum]["坐标Y"]=WAR.Data["我方Y" .. i]; | |
WAR.Person[WAR.PersonNum]["死亡"]=false; | |
WAR.Person[WAR.PersonNum]["人方向"]=2; | |
WAR.PersonNum=WAR.PersonNum+1; | |
end | |
end | |
if WAR.PersonNum>0 then | |
return ; | |
end | |
for i=1,CC.TeamNum do --设置事先确定的参战人 | |
WAR.SelectPerson[i]=0; | |
local id=JY.Base["队伍" .. i]; | |
if id>=0 then | |
for j=1,6 do | |
if WAR.Data["手动选择参战人" .. j]==id then | |
WAR.SelectPerson[i]=1; | |
end | |
end | |
end | |
end | |
local menu={}; | |
for i=1, CC.TeamNum do | |
menu[i]={"",WarSelectMenu,0}; | |
local id=JY.Base["队伍" .. i]; | |
if id>=0 then | |
menu[i][3]=1; | |
local s=JY.Person[id]["姓名"]; | |
if WAR.SelectPerson[i]==1 then | |
menu[i][1]="*" .. s; | |
else | |
menu[i][1]=" " .. s; | |
end | |
end | |
end | |
menu[CC.TeamNum+1]={" 结束",nil,1} | |
while true do | |
Cls(); | |
local x=(CC.ScreenW-7*CC.DefaultFont-2*CC.MenuBorderPixel)/2; | |
DrawStrBox(x,10,"请选择参战人物",C_WHITE,CC.DefaultFont); | |
local r=ShowMenu(menu,CC.TeamNum+1,0,x,10+CC.SingleLineHeight,0,0,1,0,CC.DefaultFont,C_ORANGE,C_WHITE); | |
Cls(); | |
for i=1,6 do | |
if WAR.SelectPerson[i]>0 then | |
WAR.Person[WAR.PersonNum]["人物编号"]=JY.Base["队伍" ..i]; | |
WAR.Person[WAR.PersonNum]["我方"]=true; | |
WAR.Person[WAR.PersonNum]["坐标X"]=WAR.Data["我方X" .. i]; | |
WAR.Person[WAR.PersonNum]["坐标Y"]=WAR.Data["我方Y" .. i]; | |
WAR.Person[WAR.PersonNum]["死亡"]=false; | |
WAR.Person[WAR.PersonNum]["人方向"]=2; | |
WAR.PersonNum=WAR.PersonNum+1; | |
end | |
end | |
if WAR.PersonNum>0 then --选择了我方参战人 | |
break; | |
end | |
end | |
end | |
--选中战斗人菜单调用函数 | |
function WarSelectMenu(newmenu,newid) --选择战斗人菜单调用函数 | |
local id=newmenu[newid][4]; | |
if WAR.SelectPerson[id]==0 then | |
WAR.SelectPerson[id]=2; | |
elseif WAR.SelectPerson[id]==2 then | |
WAR.SelectPerson[id]=0; | |
end | |
if WAR.SelectPerson[id]>0 then | |
newmenu[newid][1]="*" .. string.sub(newmenu[newid][1],2); | |
else | |
newmenu[newid][1]=" " .. string.sub(newmenu[newid][1],2); | |
end | |
return 0; | |
end | |
--选择敌方参战人 | |
function WarSelectEnemy() --选择敌方参战人 | |
for i=1,20 do | |
if WAR.Data["敌人" .. i]>0 then | |
WAR.Person[WAR.PersonNum]["人物编号"]=WAR.Data["敌人" .. i]; | |
WAR.Person[WAR.PersonNum]["我方"]=false; | |
WAR.Person[WAR.PersonNum]["坐标X"]=WAR.Data["敌方X" .. i]; | |
WAR.Person[WAR.PersonNum]["坐标Y"]=WAR.Data["敌方Y" .. i]; | |
WAR.Person[WAR.PersonNum]["死亡"]=false; | |
WAR.Person[WAR.PersonNum]["人方向"]=1; | |
WAR.PersonNum=WAR.PersonNum+1; | |
end | |
end | |
end | |
--加载战斗地图 | |
--共6层,包括了工作用地图 | |
-- 0层 地面数据 | |
-- 1层 建筑 | |
--以上为战斗地图数据,从战斗文件中载入。下面为工作用的地图结构 | |
-- 2层 战斗人战斗编号,即WAR.Person的编号 | |
-- 3层 移动时显示可移动的位置 | |
-- 4层 命中效果 | |
-- 5层 战斗人对应的贴图 | |
function WarLoadMap(mapid) --加载战斗地图 | |
lib.Debug(string.format("load war map %d",mapid)); | |
lib.LoadWarMap(CC.WarMapFile[1],CC.WarMapFile[2],mapid,6,CC.WarWidth,CC.WarHeight); | |
end | |
function GetWarMap(x,y,level) --取战斗地图数据 | |
return lib.GetWarMap(x,y,level); | |
end | |
function SetWarMap(x,y,level,v) --存战斗地图数据 | |
lib.SetWarMap(x,y,level,v); | |
end | |
--设置某层为给定值 | |
function CleanWarMap(level,v) | |
lib.CleanWarMap(level,v); | |
end | |
--绘战斗地图 | |
--flag==0 基本 | |
-- 1 显示移动路径 (v1,v2) 当前移动位置 | |
-- 2 命中人物(武功,医疗等)另一个颜色显示 | |
-- 4 战斗动画, v1 战斗人物pic, v2战斗人物贴图类型(0 使用战斗场景贴图,4,fight***贴图编号 v3 武功效果贴图 -1没有效果 | |
function WarDrawMap(flag,v1,v2,v3) | |
local x=WAR.Person[WAR.CurID]["坐标X"]; | |
local y=WAR.Person[WAR.CurID]["坐标Y"]; | |
if flag==0 then | |
lib.DrawWarMap(0,x,y,0,0,-1); | |
elseif flag==1 then | |
if WAR.Data["地图"]==0 then --雪地地图用黑色菱形 | |
lib.DrawWarMap(1,x,y,v1,v2,-1); | |
else | |
lib.DrawWarMap(2,x,y,v1,v2,-1); | |
end | |
elseif flag==2 then | |
lib.DrawWarMap(3,x,y,0,0,-1); | |
elseif flag==4 then | |
lib.DrawWarMap(4,x,y,v1,v2,v3); | |
end | |
if WAR.ShowHead==1 then | |
WarShowHead(); | |
end | |
end | |
function WarPersonSort() --战斗人物按轻功排序 | |
for i=0,WAR.PersonNum-1 do ---计算各人的轻功,包括装备加成 | |
local id=WAR.Person[i]["人物编号"]; | |
local add=0; | |
if JY.Person[id]["武器"]>-1 then | |
add=add+JY.Thing[JY.Person[id]["武器"]]["加轻功"]; | |
end | |
if JY.Person[id]["防具"]>-1 then | |
add=add+JY.Thing[JY.Person[id]["防具"]]["加轻功"]; | |
end | |
WAR.Person[i]["轻功"]=JY.Person[id]["轻功"]+add; | |
local move=math.modf(WAR.Person[i]["轻功"]/15)-math.modf(JY.Person[id]["受伤程度"]/40); | |
if move<0 then | |
move=0; | |
end | |
WAR.Person[i]["移动步数"]=move; | |
end | |
--按轻功排序,用比较笨的方法 | |
for i=0,WAR.PersonNum-2 do | |
local maxid=i; | |
for j=i,WAR.PersonNum-1 do | |
if WAR.Person[j]["轻功"]>WAR.Person[maxid]["轻功"] then | |
maxid=j; | |
end | |
end | |
WAR.Person[maxid],WAR.Person[i]=WAR.Person[i],WAR.Person[maxid]; | |
end | |
end | |
--设置战斗人物位置和贴图 | |
function WarSetPerson() --设置战斗人物位置 | |
CleanWarMap(2,-1); | |
CleanWarMap(5,-1); | |
for i=0,WAR.PersonNum-1 do | |
if WAR.Person[i]["死亡"]==false then | |
SetWarMap(WAR.Person[i]["坐标X"],WAR.Person[i]["坐标Y"],2,i); | |
SetWarMap(WAR.Person[i]["坐标X"],WAR.Person[i]["坐标Y"],5,WAR.Person[i]["贴图"]); | |
end | |
end | |
end | |
function WarCalPersonPic(id) --计算战斗人物贴图 | |
local n=5106; --战斗人物贴图起始位置 | |
n=n+JY.Person[WAR.Person[id]["人物编号"]]["头像代号"]*8+WAR.Person[id]["人方向"]*2; | |
return n; | |
end | |
------------------------------------------------------------------------------------------- | |
---------------------------------以下为手动战斗函数------------------------------------------- | |
------------------------------------------------------------------------------------------- | |
--手动战斗 | |
--id 战斗人物编号 | |
--返回,选中菜单编号,选中"等待"时有效, | |
function War_Manual() --手动战斗 | |
local r; | |
while true do | |
WAR.ShowHead=1; --显示头像 | |
r=War_Manual_Sub(); --手动战斗菜单 | |
if math.abs(r)~=1 then --移动完毕后,重新生成菜单 | |
break; | |
end | |
end | |
WAR.ShowHead=0; | |
return r; | |
end | |
function War_Manual_Sub() --手动战斗菜单 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local menu={ {"移动",War_MoveMenu,1}, | |
{"攻击",War_FightMenu,1}, | |
{"用毒",War_PoisonMenu,1}, | |
{"解毒",War_DecPoisonMenu,1}, | |
{"医疗",War_DoctorMenu,1}, | |
{"物品",War_ThingMenu,1}, | |
{"等待",War_WaitMenu,1}, | |
{"状态",War_StatusMenu,1}, | |
{"休息",War_RestMenu,1}, | |
{"自动",War_AutoMenu,1}, }; | |
if JY.Person[pid]["体力"]<=5 or WAR.Person[WAR.CurID]["移动步数"]<=0 then --不能移动 | |
menu[1][3]=0; | |
end | |
local minv=War_GetMinNeiLi(pid); | |
if JY.Person[pid]["内力"] < minv or JY.Person[pid]["体力"] <10 then --不能战斗 | |
menu[2][3]=0; | |
end | |
if JY.Person[pid]["体力"]<10 or JY.Person[pid]["用毒能力"]<20 then --不能用毒 | |
menu[3][3]=0; | |
end | |
if JY.Person[pid]["体力"]<10 or JY.Person[pid]["解毒能力"]<20 then --不能解毒 | |
menu[4][3]=0; | |
end | |
if JY.Person[pid]["体力"]<50 or JY.Person[pid]["医疗能力"]<20 then --不能医疗 | |
menu[5][3]=0; | |
end | |
lib.GetKey(); | |
Cls(); | |
return ShowMenu(menu,10,0,CC.MainMenuX,CC.MainMenuY,0,0,1,0,CC.DefaultFont,C_ORANGE,C_WHITE); | |
end | |
function War_GetMinNeiLi(pid) --计算所有武功中需要内力最少的 | |
local minv=math.huge; | |
for i=1,10 do | |
local tmpid=JY.Person[pid]["武功" .. i]; | |
if tmpid >0 then | |
if JY.Wugong[tmpid]["消耗内力点数"]< minv then | |
minv=JY.Wugong[tmpid]["消耗内力点数"]; | |
end | |
end | |
end | |
return minv; | |
end | |
function WarShowHead() --显示战斗人头像 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local p=JY.Person[pid]; | |
local h=16+2; | |
local width=112+2*CC.MenuBorderPixel; | |
local height=100+2*CC.MenuBorderPixel+4*h; | |
local x1,y1; | |
local i=1; | |
if WAR.Person[WAR.CurID]["我方"]==true then | |
x1=CC.ScreenW-width-10; | |
y1=CC.ScreenH-height-10; | |
else | |
x1=10; | |
y1=10; | |
end | |
DrawBox(x1,y1,x1+width,y1+height,C_WHITE); | |
local headw,headh=lib.PicGetXY(1,p["头像代号"]*2); | |
local headx=(100-headw)/2; | |
local heady=(100-headh)/2; | |
lib.PicLoadCache(1,p["头像代号"]*2,x1+5+headx,y1+5+heady,1); | |
x1=x1+5 | |
y1=y1+5+100; | |
DrawString(x1,y1,p["姓名"],C_WHITE,16); | |
local color; --显示生命和最大值,根据受伤和中毒显示不同颜色 | |
if p["受伤程度"]<33 then | |
color =RGB(236,200,40); | |
elseif p["受伤程度"]<66 then | |
color=RGB(244,128,32); | |
else | |
color=RGB(232,32,44); | |
end | |
DrawString(x1,y1+h,"生命",C_ORANGE,16); | |
DrawString(x1+40,y1+h,string.format("%4d",p["生命"]),color,16); | |
DrawString(x1+40+32,y1+h,"/",C_GOLD,16); | |
if p["中毒程度"]==0 then | |
color =RGB(252,148,16); | |
elseif p["中毒程度"]<50 then | |
color=RGB(120,208,88); | |
else | |
color=RGB(56,136,36); | |
end | |
DrawString(x1+40+40,y1+h,string.format("%4d",p["生命最大值"]),color,16); | |
--显示内力和最大值,根据内力性质显示不同颜色 | |
if p["内力性质"]==0 then | |
color=RGB(208,152,208); | |
elseif p["内力性质"]==1 then | |
color=RGB(236,200,40); | |
else | |
color=RGB(236,236,236); | |
end | |
DrawString(x1,y1+h*2,"内力",C_ORANGE,16); | |
DrawString(x1+40,y1+h*2,string.format("%4d/%4d",p["内力"],p["内力最大值"]),color,16); | |
DrawString(x1,y1+h*3,"体力",C_ORANGE,16); | |
DrawString(x1+40,y1+h*3,string.format("%4d",p["体力"]),C_GOLD,16); | |
end | |
--返回1:已经移动 0 没有移动 | |
function War_MoveMenu() --执行移动菜单 | |
WAR.ShowHead=0; --不显示头像 | |
if WAR.Person[WAR.CurID]["移动步数"]<=0 then | |
return 0; | |
end | |
War_CalMoveStep(WAR.CurID,WAR.Person[WAR.CurID]["移动步数"],0); --计算移动步数 | |
local r; | |
local x,y=War_SelectMove() --选择移动位置 | |
if x ~=nil then --空值表示没有选择,esc返回了,非空则表示选择了位置 | |
War_MovePerson(x,y); --移动到相应的位置 | |
r=1; | |
else | |
r=0 | |
WAR.ShowHead=1; | |
Cls(); | |
end | |
lib.GetKey(); | |
return r; | |
end | |
--计算可移动步数 | |
--id 战斗人id, | |
--stepmax 最大步数, | |
--flag=0 移动,物品不能绕过,1 武功,用毒医疗等,不考虑挡路。 | |
function War_CalMoveStep(id,stepmax,flag) --计算可移动步数 | |
CleanWarMap(3,255); --第三层坐标用来设置移动,先都设为255, | |
local x=WAR.Person[id]["坐标X"]; | |
local y=WAR.Person[id]["坐标Y"]; | |
local steparray={}; --用数组保存第n步的坐标。 | |
for i=0,stepmax do | |
steparray[i]={}; | |
steparray[i].x={}; | |
steparray[i].y={}; | |
end | |
SetWarMap(x,y,3,0); | |
steparray[0].num=1; | |
steparray[0].x[1]=x; | |
steparray[0].y[1]=y; | |
for i=0,stepmax-1 do --根据第0步的坐标找出第1步,然后继续找 | |
War_FindNextStep(steparray,i,flag); | |
if steparray[i+1].num==0 then | |
break; | |
end | |
end | |
return steparray; | |
end | |
function War_FindNextStep(steparray,step,flag) --设置下一步可移动的坐标 | |
local num=0; | |
local step1=step+1; | |
for i=1,steparray[step].num do | |
local x=steparray[step].x[i]; | |
local y=steparray[step].y[i]; | |
if x+1<CC.WarWidth-1 then --当前步数的相邻格 | |
local v=GetWarMap(x+1,y,3); | |
if v ==255 and War_CanMoveXY(x+1,y,flag)==true then | |
num= num+1; | |
steparray[step1].x[num]=x+1; | |
steparray[step1].y[num]=y; | |
SetWarMap(x+1,y,3,step1); | |
end | |
end | |
if x-1>0 then --当前步数的相邻格 | |
local v=GetWarMap(x-1,y,3); | |
if v ==255 and War_CanMoveXY(x-1,y,flag)==true then | |
num=num+1; | |
steparray[step1].x[num]=x-1; | |
steparray[step1].y[num]=y; | |
SetWarMap(x-1,y,3,step1); | |
end | |
end | |
if y+1<CC.WarHeight-1 then --当前步数的相邻格 | |
local v=GetWarMap(x,y+1,3); | |
if v ==255 and War_CanMoveXY(x,y+1,flag)==true then | |
num= num+1; | |
steparray[step1].x[num]=x; | |
steparray[step1].y[num]=y+1; | |
SetWarMap(x,y+1,3,step1); | |
end | |
end | |
if y-1>0 then --当前步数的相邻格 | |
local v=GetWarMap(x ,y-1,3); | |
if v ==255 and War_CanMoveXY(x,y-1,flag)==true then | |
num= num+1; | |
steparray[step1].x[num]=x ; | |
steparray[step1].y[num]=y-1; | |
SetWarMap(x ,y-1,3,step1); | |
end | |
end | |
end | |
steparray[step1].num=num; | |
end | |
function War_CanMoveXY(x,y,flag) --坐标是否可以通过,判断移动时使用 | |
if GetWarMap(x,y,1)>0 then --第1层有物体 | |
return false | |
end | |
if flag==0 then | |
if CC.WarWater[GetWarMap(x,y,0)]~=nil then --水面,不可走 | |
return false | |
end | |
if GetWarMap(x,y,2)>=0 then --有人 | |
return false | |
end | |
end | |
return true; | |
end | |
function War_SelectMove() ---选择移动位置 | |
local x0=WAR.Person[WAR.CurID]["坐标X"]; | |
local y0=WAR.Person[WAR.CurID]["坐标Y"]; | |
local x=x0; | |
local y=y0; | |
while true do | |
local x2=x; | |
local y2=y; | |
WarDrawMap(1,x,y); | |
ShowScreen(); | |
local key=WaitKey(); | |
if key==VK_UP then | |
y2=y-1; | |
elseif key==VK_DOWN then | |
y2=y+1; | |
elseif key==VK_LEFT then | |
x2=x-1; | |
elseif key==VK_RIGHT then | |
x2=x+1; | |
elseif key==VK_SPACE or key==VK_RETURN then | |
return x,y; | |
elseif key==VK_ESCAPE then | |
return nil; | |
end | |
if GetWarMap(x2,y2,3)<128 then | |
x=x2; | |
y=y2; | |
end | |
end | |
end | |
function War_MovePerson(x,y) --移动人物到位置x,y | |
local movenum=GetWarMap(x,y,3); | |
WAR.Person[WAR.CurID]["移动步数"]=WAR.Person[WAR.CurID]["移动步数"]-movenum; --可移动步数减小 | |
local movetable={}; -- 记录每步移动 | |
for i=movenum,1,-1 do --从目的位置反着找到初始位置,作为移动的次序 | |
movetable[i]={}; | |
movetable[i].x=x; | |
movetable[i].y=y; | |
if GetWarMap(x-1,y,3)==i-1 then | |
x=x-1; | |
movetable[i].direct=1; | |
elseif GetWarMap(x+1,y,3)==i-1 then | |
x=x+1; | |
movetable[i].direct=2; | |
elseif GetWarMap(x,y-1,3)==i-1 then | |
y=y-1; | |
movetable[i].direct=3; | |
elseif GetWarMap(x,y+1,3)==i-1 then | |
y=y+1; | |
movetable[i].direct=0; | |
end | |
end | |
for i=1,movenum do | |
local t1=lib.GetTime(); | |
SetWarMap(WAR.Person[WAR.CurID]["坐标X"],WAR.Person[WAR.CurID]["坐标Y"],2,-1); | |
SetWarMap(WAR.Person[WAR.CurID]["坐标X"],WAR.Person[WAR.CurID]["坐标Y"],5,-1); | |
WAR.Person[WAR.CurID]["坐标X"]=movetable[i].x; | |
WAR.Person[WAR.CurID]["坐标Y"]=movetable[i].y; | |
WAR.Person[WAR.CurID]["人方向"]=movetable[i].direct; | |
WAR.Person[WAR.CurID]["贴图"]=WarCalPersonPic(WAR.CurID); | |
SetWarMap(WAR.Person[WAR.CurID]["坐标X"],WAR.Person[WAR.CurID]["坐标Y"],2,WAR.CurID); | |
SetWarMap(WAR.Person[WAR.CurID]["坐标X"],WAR.Person[WAR.CurID]["坐标Y"],5,WAR.Person[WAR.CurID]["贴图"]); | |
WarDrawMap(0); | |
ShowScreen(); | |
local t2=lib.GetTime(); | |
if i<movenum then | |
if (t2-t1)< 2*CC.Frame then | |
lib.Delay(2*CC.Frame-(t2-t1)); | |
end | |
end | |
end | |
end | |
function War_FightMenu() --执行攻击菜单 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local numwugong=0; | |
local menu={}; | |
for i=1,10 do | |
local tmp=JY.Person[pid]["武功" .. i]; | |
if tmp>0 then | |
menu[i]={JY.Wugong[tmp]["名称"],nil,1}; | |
if JY.Wugong[tmp]["消耗内力点数"] > JY.Person[pid]["内力"] then | |
menu[i][3]=0; | |
end | |
numwugong=numwugong+1; | |
end | |
end | |
if numwugong==0 then | |
return 0; | |
end | |
local r; | |
if numwugong==1 then | |
r=1; | |
else | |
r=ShowMenu(menu,numwugong,0,CC.MainSubMenuX,CC.MainSubMenuY,0,0,1,1,CC.DefaultFont,C_ORANGE,C_WHITE); | |
end | |
if r==0 then | |
return 0; | |
end | |
WAR.ShowHead=0; | |
local r2=War_Fight_Sub(WAR.CurID,r); | |
WAR.ShowHead=1; | |
Cls(); | |
return r2; | |
end | |
--执行战斗,自动和手动战斗都调用 | |
function War_Fight_Sub(id,wugongnum,x,y) --执行战斗 | |
local pid=WAR.Person[id]["人物编号"]; | |
local wugong=JY.Person[pid]["武功" .. wugongnum]; | |
local level=math.modf(JY.Person[pid]["武功等级" .. wugongnum]/100)+1; | |
CleanWarMap(4,0); | |
local fightscope=JY.Wugong[wugong]["攻击范围"]; | |
--在map4标注武功攻击效果 | |
if fightscope==0 then | |
if War_FightSelectType0(wugong,level,x,y)==false then | |
return 0; | |
end | |
elseif fightscope==1 then | |
War_FightSelectType1(wugong,level,x,y) | |
elseif fightscope==2 then | |
War_FightSelectType2(wugong,level,x,y) | |
elseif fightscope==3 then | |
if War_FightSelectType3(wugong,level,x,y)==false then | |
return 0; | |
end | |
end | |
local fightnum=1; | |
if JY.Person[pid]["左右互搏"]==1 then | |
fightnum=2; | |
end | |
for k=1,fightnum do --如果左右互搏,则攻击两次 | |
for i=0,CC.WarWidth-1 do | |
for j=0,CC.WarHeight-1 do | |
local effect=GetWarMap(i,j,4); | |
if effect>0 then --攻击效果地方 | |
local emeny=GetWarMap(i,j,2); | |
if emeny>=0 then --有人 | |
if WAR.Person[WAR.CurID]["我方"] ~= WAR.Person[emeny]["我方"] then --是敌人 | |
--只有点和面攻击可以杀内力。此时伤害类型有效 | |
if JY.Wugong[wugong]["伤害类型"]==1 and (fightscope==0 or fightscope==3) then | |
WAR.Person[emeny]["点数"]=-War_WugongHurtNeili(emeny,wugong,level) | |
SetWarMap(i,j,4,3); | |
WAR.Effect=3; | |
else | |
WAR.Person[emeny]["点数"]=-War_WugongHurtLife(emeny,wugong,level) | |
WAR.Effect=2; | |
SetWarMap(i,j,4,2); | |
end | |
end | |
end | |
end | |
end | |
end | |
War_ShowFight(pid,wugong,JY.Wugong[wugong]["武功类型"],level,x,y,JY.Wugong[wugong]["武功动画&音效"]); | |
for i=0,WAR.PersonNum-1 do | |
WAR.Person[i]["点数"]=0; | |
end | |
WAR.Person[WAR.CurID]["经验"]=WAR.Person[WAR.CurID]["经验"]+2; | |
if JY.Person[pid]["武功等级" .. wugongnum]<900 then | |
JY.Person[pid]["武功等级" .. wugongnum]=JY.Person[pid]["武功等级" .. wugongnum]+Rnd(2)+1; | |
end | |
if math.modf(JY.Person[pid]["武功等级" .. wugongnum]/100)+1 ~= level then --武功升级了 | |
level=math.modf(JY.Person[pid]["武功等级" .. wugongnum]/100)+1; | |
DrawStrBox(-1,-1,string.format("%s 升为 %d 级",JY.Wugong[wugong]["名称"],level),C_ORANGE,CC.DefaultFont) | |
ShowScreen(); | |
lib.Delay(500); | |
Cls(); | |
ShowScreen(); | |
end | |
AddPersonAttrib(pid,"内力",-math.modf((level+1)/2)*JY.Wugong[wugong]["消耗内力点数"]) | |
end | |
AddPersonAttrib(pid,"体力",-3); | |
return 1; | |
end | |
--选择点攻击 | |
--x1,y1 攻击点,如果为空则手工选择 | |
function War_FightSelectType0(wugong,level,x1,y1) --选择点攻击 | |
local x0=WAR.Person[WAR.CurID]["坐标X"]; | |
local y0=WAR.Person[WAR.CurID]["坐标Y"]; | |
War_CalMoveStep(WAR.CurID,JY.Wugong[wugong]["移动范围" .. level],1); | |
if x1==nil and y1==nil then | |
x1,y1=War_SelectMove(); --选择攻击对象 | |
end | |
if x1 ==nil then | |
lib.GetKey(); | |
Cls(); | |
return false; | |
end | |
WAR.Person[WAR.CurID]["人方向"]=War_Direct(x0,y0,x1,y1); | |
SetWarMap(x1,y1,4,1); | |
WAR.EffectXY={}; | |
WAR.EffectXY[1]={x1,y1}; | |
WAR.EffectXY[2]={x1,y1}; | |
end | |
--选择线攻击 | |
--direct 攻击方向,为空则手工设置 | |
function War_FightSelectType1(wugong,level,x,y) --选择线攻击 | |
local x0=WAR.Person[WAR.CurID]["坐标X"]; | |
local y0=WAR.Person[WAR.CurID]["坐标Y"]; | |
local direct; | |
if x==nil and y==nil then | |
direct =-1; | |
DrawStrBox(CC.MainSubMenuX,CC.MainSubMenuY,"请选择攻击方向",C_ORANGE,CC.DefaultFont) | |
ShowScreen(); | |
while true do --选择方向 | |
local key=WaitKey(); | |
if key==VK_UP then | |
direct=0; | |
elseif key==VK_DOWN then | |
direct=3; | |
elseif key==VK_LEFT then | |
direct=2; | |
elseif key==VK_RIGHT then | |
direct=1; | |
end | |
if direct>=0 then | |
break; | |
end | |
end | |
Cls(CC.MainSubMenuX,CC.MainSubMenuY,CC.ScreenW,CC.ScreenH); | |
ShowScreen(); | |
else | |
direct=War_Direct(x0,y0,x,y); | |
end | |
WAR.Person[WAR.CurID]["人方向"]=direct; | |
local move=JY.Wugong[wugong]["移动范围" .. level] | |
WAR.EffectXY={}; | |
for i=1,move do | |
if direct==0 then | |
SetWarMap(x0,y0-i,4,1); | |
elseif direct==3 then | |
SetWarMap(x0,y0+i,4,1); | |
elseif direct==2 then | |
SetWarMap(x0-i,y0,4,1); | |
elseif direct==1 then | |
SetWarMap(x0+i,y0,4,1); | |
end | |
end | |
if direct==0 then | |
WAR.EffectXY[1]={x0,y0-1}; | |
WAR.EffectXY[2]={x0,y0-move}; | |
elseif direct==3 then | |
WAR.EffectXY[1]={x0,y0+1}; | |
WAR.EffectXY[2]={x0,y0+move}; | |
elseif direct==2 then | |
WAR.EffectXY[1]={x0-1,y0}; | |
WAR.EffectXY[2]={x0-move,y0}; | |
elseif direct==1 then | |
WAR.EffectXY[1]={x0+1,y0}; | |
WAR.EffectXY[2]={x0+move,y0}; | |
end | |
end | |
--选择十字攻击 | |
function War_FightSelectType2(wugong,level) --选择十字攻击 | |
local x0=WAR.Person[WAR.CurID]["坐标X"]; | |
local y0=WAR.Person[WAR.CurID]["坐标Y"]; | |
local move=JY.Wugong[wugong]["移动范围" .. level] | |
WAR.EffectXY={}; | |
for i=1,move do | |
SetWarMap(x0,y0-i,4,1); | |
SetWarMap(x0,y0+i,4,1); | |
SetWarMap(x0-i,y0,4,1); | |
SetWarMap(x0+i,y0,4,1); | |
end | |
WAR.EffectXY[1]={x0-move,y0}; | |
WAR.EffectXY[2]={x0+move,y0}; | |
end | |
--选择面攻击 | |
--x1,y1 攻击点,如果为空则手工选择 | |
function War_FightSelectType3(wugong,level,x1,y1) --选择面攻击 | |
local x0=WAR.Person[WAR.CurID]["坐标X"]; | |
local y0=WAR.Person[WAR.CurID]["坐标Y"]; | |
War_CalMoveStep(WAR.CurID,JY.Wugong[wugong]["移动范围" .. level],1); | |
if x1==nil and y1==nil then | |
x1,y1=War_SelectMove(); --选择攻击对象 | |
end | |
if x1 ==nil then | |
lib.GetKey(); | |
Cls(); | |
return false; | |
end | |
WAR.Person[WAR.CurID]["人方向"]=War_Direct(x0,y0,x1,y1); | |
local move=JY.Wugong[wugong]["杀伤范围" .. level] | |
WAR.EffectXY={}; | |
for i=-move,move do | |
for j=-move,move do | |
SetWarMap(x1+i,y1+j,4,1); | |
end | |
end | |
WAR.EffectXY[1]={x1-2*move,y1}; | |
WAR.EffectXY[2]={x1+2*move,y1}; | |
end | |
--计算人方向 | |
--(x1,y1) 人位置 -(x2,y2) 目标位置 | |
--返回: 方向 | |
function War_Direct(x1,y1,x2,y2) --计算人方向 | |
local x=x2-x1; | |
local y=y2-y1; | |
if math.abs(y)>math.abs(x) then | |
if y>0 then | |
return 3; | |
else | |
return 0 | |
end | |
else | |
if x>0 then | |
return 1; | |
else | |
return 2; | |
end | |
end | |
end | |
--显示战斗动画 | |
--pid 人id | |
--wugong 武功编号, 0 表示用毒解毒等,使用普通攻击效果 | |
--wogongtype =0 医疗用毒解毒,1,2,3,4 武功类型 -1 暗器 | |
--level 武功等级 | |
--x,y 攻击坐标 | |
--eft 武功动画效果id eft.idx/grp中的效果 | |
function War_ShowFight(pid,wugong,wugongtype,level,x,y,eft) --显示战斗动画 | |
local x0=WAR.Person[WAR.CurID]["坐标X"]; | |
local y0=WAR.Person[WAR.CurID]["坐标Y"]; | |
local fightdelay,fightframe,sounddelay; | |
if wugongtype>=0 then | |
fightdelay=JY.Person[pid]["出招动画延迟" .. wugongtype+1]; | |
fightframe=JY.Person[pid]["出招动画帧数" .. wugongtype+1]; | |
sounddelay=JY.Person[pid]["武功音效延迟" .. wugongtype+1]; | |
else ---暗器,这些数据什么意思?? | |
fightdelay=0; | |
fightframe=-1; | |
sounddelay=-1; | |
end | |
local framenum=fightdelay+CC.Effect[eft]; --总帧数 | |
local startframe=0; --计算fignt***中当前出招起始帧 | |
if wugongtype>=0 then | |
for i=0,wugongtype-1 do | |
startframe=startframe+4*JY.Person[pid]["出招动画帧数" .. i+1]; | |
end | |
end | |
local starteft=0; --计算起始武功效果帧 | |
for i=0,eft-1 do | |
starteft=starteft+CC.Effect[i]; | |
end | |
WAR.Person[WAR.CurID]["贴图类型"]=0; | |
WAR.Person[WAR.CurID]["贴图"]=WarCalPersonPic(WAR.CurID); | |
WarSetPerson(); | |
WarDrawMap(0); | |
ShowScreen(); | |
local fastdraw; | |
if CONFIG.FastShowScreen==0 or CC.AutoWarShowHead==1 then --显示头像则全部重绘 | |
fastdraw=0; | |
else | |
fastdraw=1; | |
end | |
--在显示动画前先加载贴图 | |
local oldpic=WAR.Person[WAR.CurID]["贴图"]/2; | |
local oldpic_type=0; | |
local oldeft=-1; | |
for i=0,framenum-1 do | |
local tstart=lib.GetTime(); | |
local mytype; | |
if fightframe>0 then | |
WAR.Person[WAR.CurID]["贴图类型"]=1; | |
mytype=4+WAR.CurID; | |
if i<fightframe then | |
WAR.Person[WAR.CurID]["贴图"]=(startframe+WAR.Person[WAR.CurID]["人方向"]*fightframe+i)*2; | |
end | |
else --暗器,不使用fight中图像 | |
WAR.Person[WAR.CurID]["贴图类型"]=0; | |
WAR.Person[WAR.CurID]["贴图"]=WarCalPersonPic(WAR.CurID); | |
mytype=0; | |
end | |
if i==sounddelay then | |
PlayWavAtk(JY.Wugong[wugong]["出招音效"]); | |
end | |
if i==fightdelay then | |
PlayWavE(eft); | |
end | |
local pic=WAR.Person[WAR.CurID]["贴图"]/2; | |
if fastdraw==1 then | |
local rr=ClipRect(Cal_PicClip(0,0,oldpic,oldpic_type,0,0,pic,mytype)); | |
if rr ~=nil then | |
lib.SetClip(rr.x1,rr.y1,rr.x2,rr.y2); | |
end | |
else | |
lib.SetClip(0,0,0,0); | |
end | |
oldpic=pic; | |
oldpic_type=mytype; | |
if i<fightdelay then --只显示出招 | |
WarDrawMap(4,pic*2,mytype,-1); | |
else --同时显示武功效果 | |
starteft=starteft+1; --此处似乎是eft第一个数据有问题,应该是10,现为9,因此加1 | |
if fastdraw==1 then | |
local clip1={}; | |
clip1=Cal_PicClip(WAR.EffectXY[1][1]-x0,WAR.EffectXY[1][2]-y0,oldeft,3, | |
WAR.EffectXY[1][1]-x0,WAR.EffectXY[1][2]-y0,starteft,3); | |
local clip2={}; | |
clip2=Cal_PicClip(WAR.EffectXY[2][1]-x0,WAR.EffectXY[2][2]-y0,oldeft,3, | |
WAR.EffectXY[2][1]-x0,WAR.EffectXY[2][2]-y0,starteft,3); | |
local clip=ClipRect(MergeRect(clip1,clip2)); | |
if clip ~=nil then | |
local area=(clip.x2-clip.x1)*(clip.y2-clip.y1); --计算脏矩形面积 | |
if area <CC.ScreenW*CC.ScreenH/2 then --面积足够小,则更新脏矩形。 | |
WarDrawMap(4,pic*2,mytype,starteft*2); | |
lib.SetClip(clip.x1,clip.y1,clip.x2,clip.y2); | |
WarDrawMap(4,pic*2,mytype,starteft*2); | |
else --面积太大,直接重绘 | |
lib.SetClip(0,0,CC.ScreenW,CC.ScreenH); | |
WarDrawMap(4,pic*2,mytype,starteft*2); | |
end | |
else | |
WarDrawMap(4,pic*2,mytype,starteft*2); | |
end | |
else | |
lib.SetClip(0,0,0,0); | |
WarDrawMap(4,pic*2,mytype,starteft*2); | |
end | |
oldeft=starteft; | |
end | |
ShowScreen(fastdraw); | |
lib.SetClip(0,0,0,0); | |
local tend=lib.GetTime(); | |
if tend-tstart<1*CC.Frame then | |
lib.Delay(1*CC.Frame-(tend-tstart)); | |
end | |
end | |
lib.SetClip(0,0,0,0); | |
WAR.Person[WAR.CurID]["贴图类型"]=0; | |
WAR.Person[WAR.CurID]["贴图"]=WarCalPersonPic(WAR.CurID); | |
WarSetPerson(); | |
WarDrawMap(0); | |
ShowScreen(); | |
lib.Delay(200); | |
WarDrawMap(2); --全黑显示命中人物 | |
ShowScreen(); | |
lib.Delay(200); | |
WarDrawMap(0); | |
ShowScreen(); | |
local HitXY={}; --记录命中点数的坐标 | |
local HitXYNum=0; | |
for i = 0, WAR.PersonNum-1 do | |
local x1=WAR.Person[i]["坐标X"]; | |
local y1=WAR.Person[i]["坐标Y"]; | |
if WAR.Person[i]["死亡"]==false then | |
if GetWarMap(x1,y1,4)>1 then | |
local n=WAR.Person[i]["点数"] | |
HitXY[HitXYNum]={x1,y1,string.format("%+d",n)}; | |
HitXYNum=HitXYNum+1; | |
end | |
end | |
end | |
if HitXYNum>0 then | |
local clips={}; --计算命中点数clip | |
for i=0,HitXYNum-1 do | |
local dx=HitXY[i][1]-x0; | |
local dy=HitXY[i][2]-y0; | |
local ll=string.len(HitXY[i][3]); | |
local w=ll*CC.DefaultFont/2+1; | |
clips[i]={x1=CC.XScale*(dx-dy)+CC.ScreenW/2, | |
y1=CC.YScale*(dx+dy)+CC.ScreenH/2, | |
x2=CC.XScale*(dx-dy)+CC.ScreenW/2+w, | |
y2=CC.YScale*(dx+dy)+CC.ScreenH/2+CC.DefaultFont+1 }; | |
end | |
local clip=clips[0]; | |
for i=1,HitXYNum-1 do | |
clip=MergeRect(clip,clips[i]); | |
end | |
local area=(clip.x2-clip.x1)*(clip.y2-clip.y1) | |
for i=1,15 do --显示命中的点数 | |
local tstart=lib.GetTime(); | |
local y_off=i*2+65; | |
if fastdraw==1 and area <CC.ScreenW*CC.ScreenH/2 then | |
local tmpclip={x1=clip.x1, y1=clip.y1-y_off, x2=clip.x2, y2=clip.y2-y_off}; | |
tmpclip=ClipRect(tmpclip); | |
if tmpclip~=nil then | |
lib.SetClip(tmpclip.x1,tmpclip.y1,tmpclip.x2,tmpclip.y2); | |
WarDrawMap(0) | |
for j=0,HitXYNum-1 do | |
DrawString(clips[j].x1, clips[j].y1-y_off, HitXY[j][3], | |
WAR.EffectColor[WAR.Effect],CC.DefaultFont) | |
end | |
end | |
else --面积太大,直接重绘 | |
lib.SetClip(0,0,CC.ScreenW,CC.ScreenH); | |
WarDrawMap(0) | |
for j=0,HitXYNum-1 do | |
DrawString(clips[j].x1, clips[j].y1-y_off, HitXY[j][3], | |
WAR.EffectColor[WAR.Effect],CC.DefaultFont) | |
end | |
end | |
ShowScreen(1); | |
lib.SetClip(0,0,0,0); | |
local tend=lib.GetTime(); | |
if (tend-tstart)<CC.Frame then | |
lib.Delay(CC.Frame-(tend-tstart)); | |
end | |
end | |
end | |
lib.SetClip(0,0,0,0); | |
WarDrawMap(0); | |
ShowScreen(); | |
end | |
--武功伤害生命 | |
--enemyid 敌人战斗id, | |
--wugong 我方使用武功 | |
--返回:伤害点数 | |
function War_WugongHurtLife(emenyid,wugong,level) --计算武功伤害生命 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local eid=WAR.Person[emenyid]["人物编号"]; | |
--计算武学常识 | |
local mywuxue=0; | |
local emenywuxue=0; | |
for i=0,WAR.PersonNum-1 do | |
local id =WAR.Person[i]["人物编号"] | |
if WAR.Person[i]["死亡"]==false and JY.Person[id]["武学常识"]>80 then | |
if WAR.Person[WAR.CurID]["我方"]==WAR.Person[i]["我方"] then | |
mywuxue=mywuxue+JY.Person[id]["武学常识"]; | |
else | |
emenywuxue=emenywuxue+JY.Person[id]["武学常识"]; | |
end | |
end | |
end | |
--计算实际使用武功等级 | |
while true do | |
if math.modf((level+1)/2)*JY.Wugong[wugong]["消耗内力点数"] > JY.Person[pid]["内力"] then | |
level=level-1; | |
else | |
break; | |
end | |
end | |
if level<=0 then --防止出现左右互博时第一次攻击完毕,第二次攻击没有内力的情况。 | |
level=1; | |
end | |
--武功武器配合增加攻击力 | |
local fightnum=0; | |
for i,v in ipairs(CC.ExtraOffense) do | |
if v[1]==JY.Person[pid]["武器"] and v[2]==wugong then | |
fightnum=v[3]; | |
break; | |
end | |
end | |
--计算攻击力 | |
fightnum=fightnum+(JY.Person[pid]["攻击力"]*3+JY.Wugong[wugong]["攻击力" .. level ])/2; | |
if JY.Person[pid]["武器"]>=0 then | |
fightnum=fightnum+JY.Thing[JY.Person[pid]["武器"]]["加攻击力"]; | |
end | |
if JY.Person[pid]["防具"]>=0 then | |
fightnum=fightnum+JY.Thing[JY.Person[pid]["防具"]]["加攻击力"]; | |
end | |
fightnum=fightnum+mywuxue; | |
--计算防御力 | |
local defencenum=JY.Person[eid]["防御力"]; | |
if JY.Person[eid]["武器"]>=0 then | |
defencenum=defencenum+JY.Thing[JY.Person[eid]["武器"]]["加防御力"]; | |
end | |
if JY.Person[eid]["防具"]>=0 then | |
defencenum=defencenum+JY.Thing[JY.Person[eid]["防具"]]["加防御力"]; | |
end | |
defencenum= defencenum+ emenywuxue; | |
--计算实际伤害 | |
local hurt=(fightnum-3*defencenum)*2/3+Rnd(20)-Rnd(20); | |
if hurt <0 then | |
hurt=Rnd(10)+1; | |
end | |
hurt=hurt+JY.Person[pid]["体力"]/15+JY.Person[eid]["受伤程度"]/20; | |
--考虑距离因素 | |
local offset=math.abs(WAR.Person[WAR.CurID]["坐标X"]-WAR.Person[emenyid]["坐标X"])+ | |
math.abs(WAR.Person[WAR.CurID]["坐标Y"]-WAR.Person[emenyid]["坐标Y"]); | |
if offset <10 then | |
hurt=hurt*(100-(offset-1)*3)/100; | |
else | |
hurt=hurt*2/3; | |
end | |
hurt=math.modf(hurt); | |
if hurt<=0 then | |
hurt=Rnd(8)+1; | |
end | |
JY.Person[eid]["生命"]=JY.Person[eid]["生命"]-hurt; | |
WAR.Person[WAR.CurID]["经验"]=WAR.Person[WAR.CurID]["经验"]+math.modf(hurt/5); | |
if JY.Person[eid]["生命"]<0 then --打死敌人获得额外经验 | |
JY.Person[eid]["生命"]=0; | |
WAR.Person[WAR.CurID]["经验"]=WAR.Person[WAR.CurID]["经验"]+JY.Person[eid]["等级"]*10; | |
end | |
AddPersonAttrib(eid,"受伤程度",math.modf(hurt/10)); | |
--敌人中毒点数 | |
local poisonnum=level*JY.Wugong[wugong]["敌人中毒点数"]+JY.Person[pid]["攻击带毒"]; | |
if JY.Person[eid]["抗毒能力"]< poisonnum and JY.Person[eid]["抗毒能力"]<90 then | |
AddPersonAttrib(eid,"中毒程度",math.modf(poisonnum/15)); | |
end | |
return hurt; | |
end | |
--武功伤害内力 | |
--enemyid 敌人战斗id, | |
--wugong 我方使用武功 | |
--返回:伤害点数 | |
function War_WugongHurtNeili(enemyid,wugong,level) --计算武功伤害内力 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local eid=WAR.Person[enemyid]["人物编号"]; | |
local addvalue=JY.Wugong[wugong]["加内力" .. level]; | |
local decvalue=JY.Wugong[wugong]["杀内力" .. level]; | |
if addvalue>0 then | |
if math.modf(addvalue/2)>0 then | |
AddPersonAttrib(pid,"内力最大值",Rnd(math.modf(addvalue/2))); | |
end | |
AddPersonAttrib(pid,"内力",math.abs(addvalue+Rnd(3)-Rnd(3))); | |
end | |
return -AddPersonAttrib(eid,"内力",-math.abs(decvalue+Rnd(3)-Rnd(3))); | |
end | |
---用毒菜单 | |
function War_PoisonMenu() ---用毒菜单 | |
WAR.ShowHead=0; | |
local r=War_ExecuteMenu(1); | |
WAR.ShowHead=1; | |
Cls(); | |
return r; | |
end | |
--计算敌人中毒点数 | |
--pid 使毒人, | |
--emenyid 中毒人 | |
function War_PoisonHurt(pid,emenyid) --计算敌人中毒点数 | |
local v=math.modf((JY.Person[pid]["用毒能力"]-JY.Person[emenyid]["抗毒能力"])/4); | |
if v<0 then | |
v=0; | |
end | |
return AddPersonAttrib(emenyid,"中毒程度",v); | |
end | |
---解毒菜单 | |
function War_DecPoisonMenu() ---解毒菜单 | |
WAR.ShowHead=0; | |
local r=War_ExecuteMenu(2); | |
WAR.ShowHead=1; | |
Cls(); | |
return r; | |
end | |
---医疗菜单 | |
function War_DoctorMenu() ---医疗菜单 | |
WAR.ShowHead=0; | |
local r=War_ExecuteMenu(3); | |
WAR.ShowHead=1; | |
Cls(); | |
return r; | |
end | |
---执行医疗,解毒用毒 | |
---flag=1 用毒, 2 解毒,3 医疗 4 暗器 | |
---thingid 暗器物品id | |
function War_ExecuteMenu(flag,thingid) ---执行医疗,解毒用毒暗器 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local step; | |
if flag==1 then | |
step=math.modf(JY.Person[pid]["用毒能力"]/15)+1; --用毒步数 | |
elseif flag==2 then | |
step=math.modf(JY.Person[pid]["解毒能力"]/15)+1; --解毒步数 | |
elseif flag==3 then | |
step=math.modf(JY.Person[pid]["医疗能力"]/15)+1; --医疗步数 | |
elseif flag==4 then | |
step=math.modf(JY.Person[pid]["暗器技巧"]/15)+1; --暗器步数 | |
end | |
War_CalMoveStep(WAR.CurID,step,1); | |
local x1,y1=War_SelectMove(); --选择攻击对象 | |
if x1 ==nil then | |
lib.GetKey(); | |
Cls(); | |
return 0; | |
else | |
return War_ExecuteMenu_Sub(x1,y1,flag,thingid); | |
end | |
end | |
function War_ExecuteMenu_Sub(x1,y1,flag,thingid) ---执行医疗,解毒用毒暗器的子函数,自动医疗也可调用 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local x0=WAR.Person[WAR.CurID]["坐标X"]; | |
local y0=WAR.Person[WAR.CurID]["坐标Y"]; | |
CleanWarMap(4,0); | |
WAR.Person[WAR.CurID]["人方向"]=War_Direct(x0,y0,x1,y1); | |
SetWarMap(x1,y1,4,1); | |
local emeny=GetWarMap(x1,y1,2); | |
if emeny>=0 then --有人 | |
if flag==1 then | |
if WAR.Person[WAR.CurID]["我方"] ~= WAR.Person[emeny]["我方"] then --是敌人 | |
WAR.Person[emeny]["点数"]=War_PoisonHurt(pid,WAR.Person[emeny]["人物编号"]) | |
SetWarMap(x1,y1,4,5); | |
WAR.Effect=5; | |
end | |
elseif flag==2 then | |
if WAR.Person[WAR.CurID]["我方"] == WAR.Person[emeny]["我方"] then --不是敌人 | |
WAR.Person[emeny]["点数"]=ExecDecPoison(pid,WAR.Person[emeny]["人物编号"]) | |
SetWarMap(x1,y1,4,6); | |
WAR.Effect=6; | |
end | |
elseif flag==3 then | |
if WAR.Person[WAR.CurID]["我方"] == WAR.Person[emeny]["我方"] then --不是敌人 | |
WAR.Person[emeny]["点数"]=ExecDoctor(pid,WAR.Person[emeny]["人物编号"]) | |
SetWarMap(x1,y1,4,4); | |
WAR.Effect=4; | |
end | |
elseif flag==4 then | |
if WAR.Person[WAR.CurID]["我方"] ~= WAR.Person[emeny]["我方"] then --是敌人 | |
WAR.Person[emeny]["点数"]=War_AnqiHurt(pid,WAR.Person[emeny]["人物编号"],thingid) | |
SetWarMap(x1,y1,4,2); | |
WAR.Effect=2; | |
end | |
end | |
end | |
WAR.EffectXY={}; | |
WAR.EffectXY[1]={x1,y1}; | |
WAR.EffectXY[2]={x1,y1}; | |
if flag==1 then | |
War_ShowFight(pid,0,0,0,x1,y1,30); | |
elseif flag==2 then | |
War_ShowFight(pid,0,0,0,x1,y1,36); | |
elseif flag==3 then | |
War_ShowFight(pid,0,0,0,x1,y1,0); | |
elseif flag==4 then | |
if emeny>=0 then | |
War_ShowFight(pid,0,-1,0,x1,y1,JY.Thing[thingid]["暗器动画编号"]); | |
end | |
end | |
for i=0,WAR.PersonNum-1 do | |
WAR.Person[i]["点数"]=0; | |
end | |
if flag==4 then | |
if emeny>=0 then | |
instruct_32(thingid,-1); --物品数量减少 | |
return 1; | |
else | |
return 0; --暗器打空,则等于没有打 | |
end | |
else | |
WAR.Person[WAR.CurID]["经验"]=WAR.Person[WAR.CurID]["经验"]+1; | |
AddPersonAttrib(pid,"体力",-2); | |
end | |
return 1; | |
end | |
--物品菜单 | |
function War_ThingMenu() --战斗物品菜单 | |
WAR.ShowHead=0; | |
local thing={}; | |
local thingnum={}; | |
for i = 0,CC.MyThingNum-1 do | |
thing[i]=-1; | |
thingnum[i]=0; | |
end | |
local num=0; | |
for i = 0,CC.MyThingNum-1 do | |
local id = JY.Base["物品" .. i+1]; | |
if id>=0 then | |
if JY.Thing[id]["类型"]==3 or JY.Thing[id]["类型"]==4 then | |
thing[num]=id; | |
thingnum[num]=JY.Base["物品数量" ..i+1]; | |
num=num+1; | |
end | |
end | |
end | |
local r=SelectThing(thing,thingnum); | |
Cls(); | |
local rr=0; | |
if r>=0 then | |
if UseThing(r)==1 then | |
rr=1; | |
end | |
end | |
WAR.ShowHead=1; | |
Cls(); | |
return rr; | |
end | |
---使用暗器 | |
function War_UseAnqi(id) ---战斗使用暗器 | |
return War_ExecuteMenu(4,id); | |
end | |
function War_AnqiHurt(pid,emenyid,thingid) --计算暗器伤害 | |
local num; | |
if JY.Person[emenyid]["受伤程度"]==0 then | |
num=JY.Thing[thingid]["加生命"]/4-Rnd(5); | |
elseif JY.Person[emenyid]["受伤程度"]<=33 then | |
num=JY.Thing[thingid]["加生命"]/3-Rnd(5); | |
elseif JY.Person[emenyid]["受伤程度"]<=66 then | |
num=JY.Thing[thingid]["加生命"]/2-Rnd(5); | |
else | |
num=JY.Thing[thingid]["加生命"]/2-Rnd(5); | |
end | |
num=math.modf((num-JY.Person[pid]["暗器技巧"]*2)/3); | |
AddPersonAttrib(emenyid,"受伤程度",math.modf(-num/4)); --此处的num为负值 | |
local r=AddPersonAttrib(emenyid,"生命",math.modf(num)); | |
if JY.Thing[thingid]["加中毒解毒"]>0 then | |
num=math.modf((JY.Thing[thingid]["加中毒解毒"]+JY.Person[pid]["暗器技巧"])/2); | |
num=num-JY.Person[emenyid]["抗毒能力"]; | |
num=limitX(num,0,CC.PersonAttribMax["用毒能力"]); | |
AddPersonAttrib(emenyid,"中毒程度",num); | |
end | |
return r; | |
end | |
--休息 | |
function War_RestMenu() --休息 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local v=3+Rnd(3); | |
AddPersonAttrib(pid,"体力",v); | |
if JY.Person[pid]["体力"]>30 then | |
v=3+Rnd(math.modf(JY.Person[pid]["体力"]/10)-2); | |
AddPersonAttrib(pid,"生命",v); | |
v=3+Rnd(math.modf(JY.Person[pid]["体力"]/10)-2); | |
AddPersonAttrib(pid,"内力",v); | |
end | |
return 1; | |
end | |
--等待,把当前战斗人调到队尾 | |
function War_WaitMenu() --等待,把当前战斗人调到队尾 | |
for i =WAR.CurID, WAR.PersonNum-2 do | |
local tmp=WAR.Person[i+1]; | |
WAR.Person[i+1]=WAR.Person[i]; | |
WAR.Person[i]=tmp; | |
--调换人物 | |
end | |
WarSetPerson(); --设置战斗人物位置 | |
for i=0,WAR.PersonNum-1 do | |
WAR.Person[i]["贴图"]=WarCalPersonPic(i); | |
end | |
return 1; | |
end | |
function War_StatusMenu() --战斗中显示状态 | |
WAR.ShowHead=0; | |
Menu_Status(); | |
WAR.ShowHead=1; | |
Cls(); | |
end | |
function War_AutoMenu() --设置自动战斗 | |
WAR.AutoFight=1; | |
WAR.ShowHead=0; | |
Cls(); | |
War_Auto(); | |
return 1; | |
end | |
------------------------------------------------------------------------------------ | |
-----------------------------------自动战斗------------------------------------------ | |
function War_Auto() --自动战斗主函数 | |
WAR.ShowHead=1; | |
WarDrawMap(0); | |
ShowScreen(); | |
lib.Delay(CC.WarAutoDelay); | |
WAR.ShowHead=0; | |
if CC.AutoWarShowHead==1 then | |
WAR.ShowHead=1; | |
end | |
local autotype=War_Think(); --思考如何战斗 | |
if autotype==0 then --休息 | |
War_AutoEscape(); --先跑开 | |
War_RestMenu(); | |
elseif autotype==1 then | |
War_AutoFight(); --自动战斗 | |
elseif autotype==2 then --吃药加生命 | |
War_AutoEscape(); | |
War_AutoEatDrug(2); | |
elseif autotype==3 then --吃药加内力 | |
War_AutoEscape(); | |
War_AutoEatDrug(3); | |
elseif autotype==4 then --吃药加体力 | |
War_AutoEscape(); | |
War_AutoEatDrug(4); | |
elseif autotype==5 then --自己医疗 | |
War_AutoEscape(); | |
War_AutoDoctor(); | |
elseif autotype==6 then --吃药解毒 | |
War_AutoEscape(); | |
War_AutoEatDrug(6); | |
end | |
return 0; | |
end | |
--思考如何战斗 | |
--返回:0 休息, 1 战斗,2 使用物品增加生命, 3 使用物品增加内力 4 吃药加体力, 5 医疗 | |
-- 6 使用物品解毒 | |
function War_Think() --思考如何战斗 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local r=-1; --考虑的结果 | |
if JY.Person[pid]["体力"] <10 then --休息 | |
r=War_ThinkDrug(4); | |
if r>=0 then | |
return r; | |
end | |
return 0; | |
end | |
if JY.Person[pid]["生命"]<20 or JY.Person[pid]["受伤程度"]>50 then | |
r=War_ThinkDrug(2); --考虑增加生命 | |
if r>=0 then | |
return r; | |
end | |
end | |
local rate=-1; --增加生命的百分比 | |
if JY.Person[pid]["生命"] <JY.Person[pid]["生命最大值"] /5 then | |
rate=90; | |
elseif JY.Person[pid]["生命"] <JY.Person[pid]["生命最大值"] /4 then | |
rate=70; | |
elseif JY.Person[pid]["生命"] <JY.Person[pid]["生命最大值"] /3 then | |
rate=50; | |
elseif JY.Person[pid]["生命"] <JY.Person[pid]["生命最大值"] /2 then | |
rate=25; | |
end | |
if Rnd(100)<rate then | |
r=War_ThinkDrug(2); --考虑增加生命 | |
if r>=0 then | |
return r; | |
else --没有增加生命的药,考虑是否自己医疗 | |
r=War_ThinkDoctor(); | |
if r>=0 then | |
return r; | |
end | |
end | |
end | |
rate=-1; --增加内力的百分比 | |
if JY.Person[pid]["内力"] <JY.Person[pid]["内力最大值"] /5 then | |
rate=75; | |
elseif JY.Person[pid]["内力"] <JY.Person[pid]["内力最大值"] /4 then | |
rate=50; | |
end | |
if Rnd(100)<rate then | |
r=War_ThinkDrug(3); --考虑增加内力 | |
if r>=0 then | |
return r; | |
end | |
end | |
rate=-1; --解毒的百分比 | |
if JY.Person[pid]["中毒程度"] > CC.PersonAttribMax["中毒程度"] *3/4 then | |
rate=60; | |
elseif JY.Person[pid]["中毒程度"] >CC.PersonAttribMax["中毒程度"] /2 then | |
rate=30; | |
end | |
if Rnd(100)<rate then | |
r=War_ThinkDrug(6); --考虑解毒 | |
if r>=0 then | |
return r; | |
end | |
end | |
local minNeili=War_GetMinNeiLi(pid); --所有武功的最小内力 | |
if JY.Person[pid]["内力"]>=minNeili then | |
r=1; | |
else | |
r=0; | |
end | |
return r; | |
end | |
--能否吃药增加参数 | |
--flag=2 生命,3内力;4体力 6 解毒 | |
function War_ThinkDrug(flag) --能否吃药增加参数 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local str; | |
local r=-1; | |
if flag==2 then | |
str="加生命"; | |
elseif flag==3 then | |
str="加内力"; | |
elseif flag==4 then | |
str="加体力"; | |
elseif flag==6 then | |
str="加中毒解毒"; | |
else | |
return r; | |
end | |
local function Get_Add(thingid) --定义局部函数。取得物品thingid增加的值 | |
if flag==6 then | |
return -JY.Thing[thingid][str]; --解毒为负值 | |
else | |
return JY.Thing[thingid][str]; | |
end | |
end | |
if WAR.Person[WAR.CurID]["我方"]==true then | |
for i =1, CC.MyThingNum do | |
local thingid=JY.Base["物品" ..i]; | |
if thingid>=0 then | |
if JY.Thing[thingid]["类型"]==3 and Get_Add(thingid)>0 then | |
r=flag; ---有增加生命的药,则动作:使用物品加生命 | |
break; | |
end | |
end | |
end | |
else | |
for i =1, 4 do | |
local thingid=JY.Person[pid]["携带物品" ..i]; | |
if thingid>=0 then | |
if JY.Thing[thingid]["类型"]==3 and Get_Add(thingid)>0 then | |
r=flag; ---有增加生命的药,则动作:使用物品加生命 | |
break; | |
end | |
end | |
end | |
end | |
return r; | |
end | |
--考虑是否自己医疗 | |
function War_ThinkDoctor() --考虑是否给自己医疗 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
if JY.Person[pid]["体力"]<50 or JY.Person[pid]["医疗能力"]<20 then | |
return -1; | |
end | |
if JY.Person[pid]["受伤程度"]>JY.Person[pid]["医疗能力"]+20 then | |
return -1; | |
end | |
local rate = -1; | |
local v=JY.Person[pid]["生命最大值"]-JY.Person[pid]["生命"]; | |
if JY.Person[pid]["医疗能力"] < v/4 then | |
rate=30; | |
elseif JY.Person[pid]["医疗能力"] < v/3 then | |
rate=50; | |
elseif JY.Person[pid]["医疗能力"] < v/2 then | |
rate=70; | |
else | |
rate=90; | |
end | |
if Rnd(100) <rate then | |
return 5; | |
end | |
return -1; | |
end | |
---自动战斗 | |
function War_AutoFight() ---执行自动战斗 | |
local wugongnum=War_AutoSelectWugong(); --选择武功 | |
if wugongnum <=0 then --没有选择到武功,休息 | |
War_AutoEscape(); | |
War_RestMenu(); | |
return | |
end | |
local r=War_AutoMove(wugongnum); -- 往敌人方向移动 | |
if r==1 then --如果在攻击范围 | |
War_AutoExecuteFight(wugongnum); --攻击 | |
else | |
War_RestMenu(); --休息 | |
end | |
end | |
function War_AutoSelectWugong() --自动选择合适的武功 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local probability={}; --每种武功选择的概率 | |
local wugongnum=10; --缺省10种武功 | |
for i =1, 10 do --计算每种可选择武功的总攻击力 | |
local wugongid=JY.Person[pid]["武功" .. i]; | |
if wugongid>0 then | |
--选择杀生命的武功,必须消耗内力比现有内力小,起码可以发出一级的武功。 | |
if JY.Wugong[wugongid]["伤害类型"]==0 then | |
if JY.Wugong[wugongid]["消耗内力点数"]<=JY.Person[pid]["内力"] then | |
local level=math.modf(JY.Person[pid]["武功等级" .. i]/100)+1; | |
--总攻击力即为概率 | |
probability[i]=(JY.Person[pid]["攻击力"]*3+JY.Wugong[wugongid]["攻击力" .. level ])/2; | |
else | |
probability[i]=0; | |
end | |
else --杀内力的武功 | |
probability[i]=10; --很小的概率选择杀内力 | |
end | |
else | |
wugongnum=i-1; | |
break; | |
end | |
end | |
local maxoffense=0; --计算最大攻击力 | |
for i =1, wugongnum do | |
if probability[i]>maxoffense then | |
maxoffense=probability[i]; | |
end | |
end | |
local mynum=0; --计算我方和敌人个数 | |
local enemynum=0; | |
for i=0, WAR.PersonNum-1 do | |
if WAR.Person[i]["死亡"]==false then | |
if WAR.Person[i]["我方"]==WAR.Person[WAR.CurID]["我方"] then | |
mynum=mynum+1; | |
else | |
enemynum=enemynum+1; | |
end | |
end | |
end | |
local factor=0; --敌人人数影响因子,敌人多则对线面等攻击多人武功的选择概率增加 | |
if enemynum>mynum then | |
factor=2; | |
else | |
factor=1; | |
end | |
for i =1, wugongnum do --考虑其他概率效果 | |
local wugongid=JY.Person[pid]["武功" .. i]; | |
if probability[i]>0 then | |
if probability[i]<maxoffense/2 then --去掉攻击力小的武功 | |
probability[i]=0 | |
end | |
local extranum=0; --武功武器配合的攻击力 | |
for j,v in ipairs(CC.ExtraOffense) do | |
if v[1]==JY.Person[pid]["武器"] and v[2]==wugongid then | |
extranum=v[3]; | |
break; | |
end | |
end | |
local level=math.modf(JY.Person[pid]["武功等级" .. i]/100)+1; | |
probability[i]=probability[i]+JY.Wugong[wugongid]["攻击范围"]*factor*JY.Wugong[wugongid]["杀伤范围" ..level]*20; | |
end | |
end | |
local s={}; --按照概率依次累加 | |
local maxnum=0; | |
for i=1,wugongnum do | |
s[i]=maxnum; | |
maxnum=maxnum+probability[i]; | |
end | |
s[wugongnum+1]=maxnum; | |
if maxnum==0 then --没有可以选择的武功 | |
return -1; | |
end | |
local v=Rnd(maxnum); --产生随机数 | |
local selectid=0; | |
for i=1,wugongnum do --根据产生的随机数,寻找落在哪个武功区间 | |
if v>=s[i] and v< s[i+1] then | |
selectid=i; | |
break; | |
end | |
end | |
return selectid; | |
end | |
function War_AutoSelectEnemy() --选择战斗对手 | |
local enemyid=War_AutoSelectEnemy_near() | |
WAR.Person[WAR.CurID]["自动选择对手"]=enemyid; | |
return enemyid; | |
end | |
function War_AutoSelectEnemy_near() --选择最近对手 | |
War_CalMoveStep(WAR.CurID,100,1); --标记每个位置的步数 | |
local maxDest=math.huge; | |
local nearid=-1; | |
for i=0,WAR.PersonNum-1 do --查找最近步数的敌人 | |
if WAR.Person[WAR.CurID]["我方"] ~=WAR.Person[i]["我方"] then | |
if WAR.Person[i]["死亡"]==false then | |
local step=GetWarMap(WAR.Person[i]["坐标X"],WAR.Person[i]["坐标Y"],3); | |
if step<maxDest then | |
nearid=i; | |
maxDest=step; | |
end | |
end | |
end | |
end | |
return nearid; | |
end | |
--自动往敌人方向移动 | |
--人物武功编号,不是武功id | |
--返回 1=可以攻击敌人, 0 不能攻击 | |
function War_AutoMove(wugongnum) --自动往敌人方向移动 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local wugongid=JY.Person[pid]["武功" ..wugongnum]; | |
local level=math.modf(JY.Person[pid]["武功等级".. wugongnum]/100)+1; | |
local wugongtype=JY.Wugong[wugongid]["攻击范围"]; | |
local movescope=JY.Wugong[wugongid]["移动范围" ..level]; | |
local fightscope=JY.Wugong[wugongid]["杀伤范围" ..level]; | |
local scope=movescope+fightscope; | |
local x,y; | |
local move=128; | |
local maxenemy=0; | |
local movestep=War_CalMoveStep(WAR.CurID,WAR.Person[WAR.CurID]["移动步数"],0); --计算移动步数 | |
War_AutoCalMaxEnemyMap(wugongid,level); --计算该武功各个坐标可以攻击到敌人的个数 | |
for i=0,WAR.Person[WAR.CurID]["移动步数"] do | |
local step_num=movestep[i].num ; | |
if step_num==0 then | |
break; | |
end | |
for j=1,step_num do | |
local xx=movestep[i].x[j]; | |
local yy=movestep[i].y[j] | |
local num=0; | |
if wugongtype==0 or wugongtype==2 or wugongtype==3 then | |
num=GetWarMap(xx,yy,4) --计算这个位置可以攻击到的最多敌人个数 | |
elseif wugongtype==1 then | |
local v=GetWarMap(xx,yy,4) --计算这个位置可以攻击到的最多敌人个数 | |
if v>0 then | |
num=War_AutoCalMaxEnemy(xx,yy,wugongid,level); | |
end | |
end | |
if num>maxenemy then | |
maxenemy=num | |
x=xx; | |
y=yy; | |
move=i; | |
elseif num==maxenemy and num>0 then | |
if Rnd(3)==0 then | |
maxenemy=num | |
x=xx; | |
y=yy; | |
move=i; | |
end | |
end | |
end | |
end | |
if maxenemy>0 then | |
War_CalMoveStep(WAR.CurID,WAR.Person[WAR.CurID]["移动步数"],0); --重新计算移动步数 | |
War_MovePerson(x,y); --移动到相应的位置 | |
return 1; | |
else --任何移动都直接攻击不到敌人,寻找一条可以移动到攻击到敌人位置的路线 | |
x,y=War_GetCanFightEnemyXY(scope); --计算可以攻击到敌人的最近位置 | |
local minDest=math.huge; | |
if x==nil then --无法走到可以攻击敌人的地方,可能敌人被围住,或者被敌人围住。 | |
local enemyid=War_AutoSelectEnemy() --选择最近敌人 | |
War_CalMoveStep(WAR.CurID,100,0); --计算移动步数 假设最大100步 | |
for i=0,CC.WarWidth-1 do | |
for j=0,CC.WarHeight-1 do | |
local dest=GetWarMap(i,j,3); | |
if dest <128 then | |
local dx=math.abs(i-WAR.Person[enemyid]["坐标X"]) | |
local dy=math.abs(j-WAR.Person[enemyid]["坐标Y"]) | |
if minDest>(dx+dy) then --此时x,y是距离敌人的最短路径,虽然可能被围住 | |
minDest=dx+dy; | |
x=i; | |
y=j; | |
elseif minDest==(dx+dy) then | |
if Rnd(2)==0 then | |
x=i; | |
y=j; | |
end | |
end | |
end | |
end | |
end | |
else | |
minDest=0; --可以走到 | |
end | |
if minDest<math.huge then --有路可走 | |
while true do --从目的位置反着找到可以移动的位置,作为移动的次序 | |
local i=GetWarMap(x,y,3); | |
if i<=WAR.Person[WAR.CurID]["移动步数"] then | |
break; | |
end | |
if GetWarMap(x-1,y,3)==i-1 then | |
x=x-1; | |
elseif GetWarMap(x+1,y,3)==i-1 then | |
x=x+1; | |
elseif GetWarMap(x,y-1,3)==i-1 then | |
y=y-1; | |
elseif GetWarMap(x,y+1,3)==i-1 then | |
y=y+1; | |
end | |
end | |
War_MovePerson(x,y); --移动到相应的位置 | |
end | |
end | |
return 0; | |
end | |
--得到可以走到攻击到敌人的最近位置。 | |
--scope可以攻击的范围 | |
--返回 x,y。如果无法走到攻击位置,返回空 | |
function War_GetCanFightEnemyXY(scope) --得到可以走到攻击到敌人的最近位置 | |
local minStep=math.huge; | |
local newx,newy; | |
War_CalMoveStep(WAR.CurID,100,0); --计算移动步数 假设最大100步 | |
for x=0,CC.WarWidth-1 do | |
for y=0,CC.WarHeight-1 do | |
if GetWarMap(x,y,4)>0 then --这个位置可以攻击到敌人 | |
local step=GetWarMap(x,y,3); | |
if step<128 then | |
if minStep>step then | |
minStep=step; | |
newx=x; | |
newy=y; | |
elseif minStep==step then | |
if Rnd(2)==0 then | |
newx=x; | |
newy=y; | |
end | |
end | |
end | |
end | |
end | |
end | |
if minStep<math.huge then | |
return newx,newy; | |
end | |
end | |
function War_AutoCalMaxEnemyMap(wugongid,level) --计算地图上每个位置可以攻击的敌人数目 | |
local wugongtype=JY.Wugong[wugongid]["攻击范围"]; | |
local movescope=JY.Wugong[wugongid]["移动范围" ..level]; | |
local fightscope=JY.Wugong[wugongid]["杀伤范围" ..level]; | |
local x0=WAR.Person[WAR.CurID]["坐标X"]; | |
local y0=WAR.Person[WAR.CurID]["坐标Y"]; | |
CleanWarMap(4,0); --用level 4地图表示哪些位置可以攻击到敌人 | |
----点攻击和面攻击, 每个坐标可以攻击的敌人个数(显然只能为0和1) | |
---这里面攻击和点攻击一样处理,会导致面攻击可能不能攻击到最多的敌人,但是这样速度快 | |
if wugongtype==0 or wugongtype==3 then | |
for n=0,WAR.PersonNum-1 do | |
if n~=WAR.CurID and WAR.Person[n]["死亡"]==false and | |
WAR.Person[n]["我方"] ~=WAR.Person[WAR.CurID]["我方"] then --敌人 | |
local xx=WAR.Person[n]["坐标X"]; | |
local yy=WAR.Person[n]["坐标Y"]; | |
local movestep=War_CalMoveStep(n,movescope,1); --计算武功移动步数 | |
for i=1,movescope do | |
local step_num=movestep[i].num ; | |
if step_num==0 then | |
break; | |
end | |
for j=1,step_num do | |
SetWarMap(movestep[i].x[j],movestep[i].y[j],4,1); --标记武功移动的地方,即为可攻击到敌人之处 | |
end | |
end | |
end | |
end | |
--线攻击和十字 记录每个的点可以攻击到敌人的个数。对线攻击,数组并不准确,需要进一步核实。 | |
elseif wugongtype==1 or wugongtype==2 then | |
for n=0,WAR.PersonNum-1 do | |
if n~=WAR.CurID and WAR.Person[n]["死亡"]==false and | |
WAR.Person[n]["我方"] ~=WAR.Person[WAR.CurID]["我方"] then --敌人 | |
local xx=WAR.Person[n]["坐标X"]; | |
local yy=WAR.Person[n]["坐标Y"]; | |
for direct=0,3 do | |
for i=1,movescope do | |
local xnew=xx+CC.DirectX[direct+1]*i; | |
local ynew=yy+CC.DirectY[direct+1]*i; | |
if xnew>=0 and xnew<CC.WarWidth and ynew>=0 and ynew<CC.WarHeight then | |
local v=GetWarMap(xnew,ynew,4); | |
SetWarMap(xnew,ynew,4,v+1); | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
function War_AutoCalMaxEnemy(x,y,wugongid,level) --计算从(x,y)开始攻击最多能够击中几个敌人 | |
local wugongtype=JY.Wugong[wugongid]["攻击范围"]; | |
local movescope=JY.Wugong[wugongid]["移动范围" ..level]; | |
local fightscope=JY.Wugong[wugongid]["杀伤范围" ..level]; | |
local maxnum=0; | |
local xmax,ymax; | |
if wugongtype==0 or wugongtype==3 then | |
local movestep=War_CalMoveStep(WAR.CurID,movescope,1); --计算武功移动步数 | |
for i=1,movescope do | |
local step_num=movestep[i].num ; | |
if step_num==0 then | |
break; | |
end | |
for j=1,step_num do | |
local xx=movestep[i].x[j]; | |
local yy=movestep[i].y[j]; | |
local enemynum=0; | |
for n=0,WAR.PersonNum-1 do --计算武功攻击范围内的敌人个数 | |
if n~=WAR.CurID and WAR.Person[n]["死亡"]==false and | |
WAR.Person[n]["我方"] ~=WAR.Person[WAR.CurID]["我方"] then | |
local x=math.abs(WAR.Person[n]["坐标X"]-xx); | |
local y=math.abs(WAR.Person[n]["坐标Y"]-yy); | |
if x<=fightscope and y <=fightscope then | |
enemynum=enemynum+1; | |
end | |
end | |
end | |
if enemynum>maxnum then --记录最多敌人和位置 | |
maxnum=enemynum; | |
xmax=xx; | |
ymax=yy; | |
end | |
end | |
end | |
elseif wugongtype==1 then --线攻击 | |
for direct=0,3 do -- 对每个方向循环,找出敌人最多的 | |
local enemynum=0; | |
for i=1,movescope do | |
local xnew=x+CC.DirectX[direct+1]*i; | |
local ynew=y+CC.DirectY[direct+1]*i; | |
if xnew>=0 and xnew<CC.WarWidth and ynew>=0 and ynew<CC.WarHeight then | |
local id=GetWarMap(xnew,ynew,2); | |
if id>=0 then | |
if WAR.Person[WAR.CurID]["我方"] ~= WAR.Person[id]["我方"] then | |
enemynum=enemynum+1; --武功攻击范围内的敌人个数 | |
end | |
end | |
end | |
end | |
if enemynum>maxnum then --记录最多敌人和位置 | |
maxnum=enemynum; | |
xmax=x+CC.DirectX[direct+1]; --线攻击记录一个代表方向的坐标 | |
ymax=y+CC.DirectY[direct+1]; | |
end | |
end | |
elseif wugongtype==2 then --十字攻击 | |
local enemynum=0; | |
for direct=0,3 do -- 对每个方向循环 | |
for i=1,movescope do | |
local xnew=x+CC.DirectX[direct+1]*i; | |
local ynew=y+CC.DirectY[direct+1]*i; | |
if xnew>=0 and xnew<CC.WarWidth and ynew>=0 and ynew<CC.WarHeight then | |
local id=GetWarMap(xnew,ynew,2); | |
if id>=0 then | |
if WAR.Person[WAR.CurID]["我方"] ~= WAR.Person[id]["我方"] then | |
enemynum=enemynum+1; --武功攻击范围内的敌人个数 | |
end | |
end | |
end | |
end | |
end | |
if enemynum>0 then | |
maxnum=enemynum; | |
xmax=x; | |
ymax=y; | |
end | |
end | |
return maxnum,xmax,ymax; | |
end | |
--自动执行战斗,此时的位置一定可以打到敌人 | |
function War_AutoExecuteFight(wugongnum) --自动执行战斗,显示攻击动画 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local x0=WAR.Person[WAR.CurID]["坐标X"]; | |
local y0=WAR.Person[WAR.CurID]["坐标Y"]; | |
local wugongid=JY.Person[pid]["武功" ..wugongnum]; | |
local level=math.modf(JY.Person[pid]["武功等级".. wugongnum]/100)+1; | |
local maxnum,x,y=War_AutoCalMaxEnemy(x0,y0,wugongid,level); | |
if x ~= nil then | |
War_Fight_Sub(WAR.CurID,wugongnum,x,y); | |
end | |
end | |
--逃跑 | |
function War_AutoEscape() --逃跑 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
if JY.Person[pid]["体力"]<=5 then | |
return | |
end | |
local maxDest=0; | |
local x,y; | |
War_CalMoveStep(WAR.CurID,WAR.Person[WAR.CurID]["移动步数"],0); --计算移动步数 | |
for i=0,CC.WarWidth-1 do | |
for j=0,CC.WarHeight-1 do | |
if GetWarMap(i,j,3)<128 then | |
local minDest=math.huge; | |
for k=0,WAR.PersonNum-1 do | |
if WAR.Person[WAR.CurID]["我方"]~=WAR.Person[k]["我方"] and WAR.Person[k]["死亡"]==false then | |
local dx=math.abs(i-WAR.Person[k]["坐标X"]) | |
local dy=math.abs(j-WAR.Person[k]["坐标Y"]) | |
if minDest>(dx+dy) then --计算当前距离敌人最近的位置 | |
minDest=dx+dy; | |
end | |
end | |
end | |
if minDest>maxDest then --找一个最远的位置 | |
maxDest=minDest; | |
x=i; | |
y=j; | |
end | |
end | |
end | |
end | |
if maxDest>0 then | |
War_MovePerson(x,y); --移动到相应的位置 | |
end | |
end | |
---吃药 | |
----flag=2 生命,3内力;4体力 6 解毒 | |
function War_AutoEatDrug(flag) ---吃药加参数 | |
local pid=WAR.Person[WAR.CurID]["人物编号"]; | |
local life=JY.Person[pid]["生命"]; | |
local maxlife=JY.Person[pid]["生命最大值"]; | |
local selectid; | |
local minvalue=math.huge; | |
local shouldadd; | |
local maxattrib; | |
local str; | |
if flag==2 then | |
maxattrib=JY.Person[pid]["生命最大值"]; | |
shouldadd=maxattrib-JY.Person[pid]["生命"]; | |
str="加生命"; | |
elseif flag==3 then | |
maxattrib=JY.Person[pid]["内力最大值"]; | |
shouldadd=maxattrib-JY.Person[pid]["内力"]; | |
str="加内力"; | |
elseif flag==4 then | |
maxattrib=CC.PersonAttribMax["体力"]; | |
shouldadd=maxattrib-JY.Person[pid]["体力"]; | |
str="加体力"; | |
elseif flag==6 then | |
maxattrib=CC.PersonAttribMax["中毒程度"]; | |
shouldadd=JY.Person[pid]["中毒程度"]; | |
str="加中毒解毒"; | |
else | |
return ; | |
end | |
local function Get_Add(thingid) --定义物品增加的值 | |
if flag==6 then | |
return -JY.Thing[thingid][str]/2; --解毒为负值 | |
else | |
return JY.Thing[thingid][str]; | |
end | |
end | |
if WAR.Person[WAR.CurID]["我方"]==true then | |
local extra=0; | |
for i =1, CC.MyThingNum do | |
local thingid=JY.Base["物品" ..i]; | |
if thingid>=0 then | |
local add=Get_Add(thingid); | |
if JY.Thing[thingid]["类型"]==3 and add>0 then | |
local v=shouldadd-add; | |
if v<0 then --可以加满, 用其他方法找合适药品 | |
extra=1; | |
break; | |
else | |
if v<minvalue then --寻找加生命后生命最大的 | |
minvalue=v; | |
selectid=thingid; | |
end | |
end | |
end | |
end | |
end | |
if extra==1 then | |
minvalue=math.huge; | |
for i =1, CC.MyThingNum do | |
local thingid=JY.Base["物品" ..i]; | |
if thingid>=0 then | |
local add=Get_Add(thingid); | |
if JY.Thing[thingid]["类型"]==3 and add>0 then | |
local v=add-shouldadd; | |
if v>=0 then --可以加满生命 | |
if v<minvalue then | |
minvalue=v; | |
selectid=thingid; | |
end | |
end | |
end | |
end | |
end | |
end | |
if UseThingEffect(selectid,pid)==1 then --使用有效果 | |
instruct_32(selectid,-1); --物品数量减少 | |
end | |
else | |
local extra=0; | |
for i =1, 4 do | |
local thingid=JY.Person[pid]["携带物品" ..i]; | |
if thingid>=0 then | |
local add=Get_Add(thingid); | |
if JY.Thing[thingid]["类型"]==3 and add>0 then | |
local v=shouldadd-add; | |
if v<0 then --可以加满生命, 用其他方法找合适药品 | |
extra=1; | |
break; | |
else | |
if v<minvalue then --寻找加生命后生命最大的 | |
minvalue=v; | |
selectid=thingid; | |
end | |
end | |
end | |
end | |
end | |
if extra==1 then | |
minvalue=math.huge; | |
for i =1, 4 do | |
local thingid=JY.Person[pid]["携带物品" ..i]; | |
if thingid>=0 then | |
local add=Get_Add(thingid); | |
if JY.Thing[thingid]["类型"]==3 and add>0 then | |
local v=add-shouldadd; | |
if v>=0 then --可以加满生命 | |
if v<minvalue then | |
minvalue=v; | |
selectid=thingid; | |
end | |
end | |
end | |
end | |
end | |
end | |
if UseThingEffect(selectid,pid)==1 then --使用有效果 | |
instruct_41(pid,selectid,-1); --物品数量减少 | |
end | |
end | |
lib.Delay(500); | |
end | |
--自动医疗 | |
function War_AutoDoctor() --自动医疗 | |
local x1=WAR.Person[WAR.CurID]["坐标X"]; | |
local y1=WAR.Person[WAR.CurID]["坐标Y"]; | |
War_ExecuteMenu_Sub(x1,y1,3,-1); | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment