From f4f2393f72b370040cce6b10d037698bc10fdab5 Mon Sep 17 00:00:00 2001 From: templarz Date: Tue, 26 May 2026 16:41:20 +0800 Subject: [PATCH] init: add workspace files --- .env | 13 + api/base.js | 145 + api/game.js | 47 + api/user.js | 206 ++ config.js | 29 + data/db.js | 200 ++ data/def/data.js | 1 + data/sql.js | 132 + main.js | 58 + os/base.js | 179 ++ os/char/chara_comm.js | 234 ++ os/char/chara_equip.js | 175 ++ os/char/chara_move.js | 169 ++ os/char/chara_prop.js | 137 + os/char/chara_skill.js | 566 ++++ os/char/character.js | 351 +++ os/char/combat.js | 250 ++ os/char/follower.js | 485 ++++ os/char/monster.js | 114 + os/char/npc.js | 227 ++ os/char/user.js | 845 ++++++ os/command.js | 47 + os/const.js | 116 + os/data.js | 123 + os/item.js | 250 ++ os/item/container.js | 69 + os/item/corpse.js | 71 + os/item/equipment.js | 450 +++ os/item/money.js | 25 + os/item/obj.js | 228 ++ os/login.js | 38 + os/net-ws.js | 340 +++ os/room/area.js | 135 + os/room/fam_area.js | 5 + os/room/room.js | 692 +++++ os/skill/family.js | 94 + os/skill/skill.js | 648 +++++ os/task/events.js | 49 + os/task/playertask.js | 48 + os/task/task.js | 36 + os/util/data.js | 154 + os/util/util.js | 406 +++ os/world.js | 341 +++ os/ws.js | 49 + package.json | 38 + readme.md | 1 + src/api.js | 64 + src/base/page.js | 139 + src/client.js | 192 ++ src/combat.js | 400 +++ src/confirm.js | 315 ++ src/dialog/base.js | 137 + src/dialog/channel.js | 118 + src/dialog/events.js | 136 + src/dialog/extend.js | 629 ++++ src/dialog/jh.js | 530 ++++ src/dialog/keys.js | 194 ++ src/dialog/list.js | 274 ++ src/dialog/map.js | 35 + src/dialog/master.js | 156 + src/dialog/message.js | 456 +++ src/dialog/packet.js | 701 +++++ src/dialog/packet2.js | 111 + src/dialog/paimai.js | 156 + src/dialog/party.js | 268 ++ src/dialog/relation.js | 94 + src/dialog/score.js | 333 +++ src/dialog/setting.js | 1087 +++++++ src/dialog/shop.js | 274 ++ src/dialog/skills.js | 534 ++++ src/dialog/stats.js | 354 +++ src/dialog/tasks.js | 169 ++ src/dialog/team.js | 75 + src/dialog/trade.js | 148 + src/fonts/fa-solid-900.woff2 | Bin 0 -> 158220 bytes src/fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes src/fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes src/fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes src/fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes src/game/main.js | 275 ++ src/game/tool.js | 89 + src/img/loader.gif | Bin 0 -> 1024 bytes src/img/thk.png | Bin 0 -> 66145 bytes src/img/timg.gif | Bin 0 -> 46803 bytes src/index.html | 15 + src/login/bind-phone.js | 84 + src/login/change-pwd.js | 82 + src/login/create-role.js | 89 + src/login/index.js | 139 + src/login/login-in.js | 70 + src/login/news.js | 20 + src/login/regist.js | 86 + src/login/reset-pwd.js | 67 + src/login/roles.js | 157 + src/login/server.js | 111 + src/main.js | 21 + src/map.js | 356 +++ src/message.js | 87 + src/process.js | 542 ++++ src/script.js | 246 ++ src/setting.js | 183 ++ src/startup.js | 30 + src/styles/dialog.css | 254 ++ src/styles/global.css | 840 ++++++ src/styles/main.css | 687 +++++ src/utils/util.js | 449 +++ vite.config.js | 19 + web.js | 144 + world/area/fb1/fb1.js | 33 + world/area/fb1/fb2.js | 45 + world/area/fb1/fb3.js | 53 + world/area/fb1/fb4.js | 51 + world/area/fb1/fb5.js | 50 + world/area/fb1/fb5_5.js | 54 + world/area/fb1/fb6.js | 30 + world/area/fb1/fb8.js | 31 + world/area/map/emei.js | 29 + world/area/map/gaibang.js | 23 + world/area/map/heiying.js | 50 + world/area/map/home.js | 21 + world/area/map/huashan.js | 34 + world/area/map/kezhan.js | 11 + world/area/map/leitai.js | 15 + world/area/map/new.js | 13 + world/area/map/party.js | 21 + world/area/map/shaolin.js | 33 + world/area/map/shashou.js | 27 + world/area/map/ta.js | 53 + world/area/map/wudang.js | 31 + world/area/map/xiangyang.js | 166 ++ world/area/map/xiaoyao.js | 29 + world/area/map/yz.js | 56 + world/cmd/action/actions.js | 44 + world/cmd/action/answer.js | 24 + world/cmd/action/ask.js | 70 + world/cmd/action/bai.js | 55 + world/cmd/action/caiyao.js | 56 + world/cmd/action/challenge.js | 7 + world/cmd/action/cr.js | 489 ++++ world/cmd/action/cr2.js | 74 + world/cmd/action/dazuo.js | 93 + world/cmd/action/diaoyu.js | 75 + world/cmd/action/dismiss.js | 28 + world/cmd/action/follow.js | 19 + world/cmd/action/go.js | 135 + world/cmd/action/goto.js | 158 + world/cmd/action/liaoshang.js | 56 + world/cmd/action/look.js | 98 + world/cmd/action/look1.js | 32 + world/cmd/action/look3.js | 64 + world/cmd/action/makelove.js | 120 + world/cmd/action/select.js | 81 + world/cmd/action/state.js | 20 + world/cmd/action/status.js | 44 + world/cmd/action/wakuang.js | 29 + world/cmd/action/wk.js | 63 + world/cmd/admin/call.js | 24 + world/cmd/admin/notice.js | 32 + world/cmd/admin/recover.js | 20 + world/cmd/admin/send.js | 71 + world/cmd/admin/shutdown.js | 27 + world/cmd/admin/update.js | 120 + world/cmd/admin/user.js | 11 + world/cmd/battle/combat.js | 53 + world/cmd/battle/escape.js | 9 + world/cmd/battle/fight.js | 75 + world/cmd/battle/kill.js | 88 + world/cmd/battle/pfm.js | 169 ++ world/cmd/battle/pk.js | 11 + world/cmd/battle/relive.js | 109 + world/cmd/battle/spfm.js | 24 + world/cmd/channel/chat.js | 52 + world/cmd/channel/emote.js | 220 ++ world/cmd/channel/es.js | 39 + world/cmd/channel/fam.js | 35 + world/cmd/channel/filter.js | 421 +++ world/cmd/channel/pty.js | 39 + world/cmd/channel/rumor.js | 14 + world/cmd/channel/say.js | 19 + world/cmd/channel/sys.js | 16 + world/cmd/channel/tell.js | 9 + world/cmd/channel/tm.js | 22 + world/cmd/comm/clearwait.js | 6 + world/cmd/comm/createrole.js | 98 + world/cmd/comm/dc.js | 50 + world/cmd/comm/deleterole.js | 24 + world/cmd/comm/greet.js | 68 + world/cmd/comm/info.js | 69 + world/cmd/comm/login.js | 102 + world/cmd/comm/rel.js | 81 + world/cmd/comm/setting.js | 315 ++ world/cmd/comm/shortcut.js | 30 + world/cmd/comm/sx.js | 221 ++ world/cmd/comm/systask.js | 22 + world/cmd/comm/team.js | 234 ++ world/cmd/comm/title.js | 35 + world/cmd/comm/zigong.js | 50 + world/cmd/dialog/cha.js | 76 + world/cmd/dialog/events.js | 64 + world/cmd/dialog/i.js | 103 + world/cmd/dialog/jh.js | 385 +++ world/cmd/dialog/list.js | 53 + world/cmd/dialog/map.js | 71 + world/cmd/dialog/message.js | 74 + world/cmd/dialog/qu.js | 24 + world/cmd/dialog/relation.js | 94 + world/cmd/dialog/reward.js | 65 + world/cmd/dialog/score.js | 145 + world/cmd/dialog/score2.js | 77 + world/cmd/dialog/shop.js | 281 ++ world/cmd/dialog/stats.js | 418 +++ world/cmd/dialog/store.js | 122 + world/cmd/dialog/task.js | 64 + world/cmd/dialog/tasks.js | 25 + world/cmd/dialog/trade.js | 13 + world/cmd/extend/auto.js | 70 + world/cmd/extend/biwu.js | 446 +++ world/cmd/extend/ex.js | 18 + world/cmd/extend/paimai.js | 11 + world/cmd/extend/party.js | 10 + world/cmd/obj/buy.js | 80 + world/cmd/obj/checkobj.js | 65 + world/cmd/obj/combine.js | 40 + world/cmd/obj/dice.js | 71 + world/cmd/obj/drop.js | 40 + world/cmd/obj/eq_group.js | 42 + world/cmd/obj/equip.js | 29 + world/cmd/obj/fenjie.js | 109 + world/cmd/obj/get.js | 132 + world/cmd/obj/give.js | 63 + world/cmd/obj/jinglian.js | 106 + world/cmd/obj/lianyao.js | 7 + world/cmd/obj/lockobj.js | 21 + world/cmd/obj/open.js | 26 + world/cmd/obj/packitem.js | 13 + world/cmd/obj/receive.js | 82 + world/cmd/obj/recobj.js | 8 + world/cmd/obj/sell.js | 104 + world/cmd/obj/unequip.js | 21 + world/cmd/obj/unjinglian.js | 52 + world/cmd/obj/unxiangqian.js | 101 + world/cmd/obj/use.js | 68 + world/cmd/obj/xiangqian.js | 51 + world/cmd/skill/checkskill.js | 43 + world/cmd/skill/enable.js | 73 + world/cmd/skill/fangqi.js | 115 + world/cmd/skill/fenpei.js | 51 + world/cmd/skill/lianxi.js | 188 ++ world/cmd/skill/sbook.js | 101 + world/cmd/skill/sk_group.js | 59 + world/cmd/skill/stopstate.js | 10 + world/cmd/skill/study.js | 141 + world/cmd/skill/xiulian.js | 6 + world/cmd/skill/xue.js | 279 ++ world/extends/char/auto_combat.js | 195 ++ world/extends/char/combat.js | 382 +++ world/extends/char/user.js | 197 ++ world/extends/data.js | 115 + world/extends/item/eq.js | 15 + world/extends/item/obj.js | 10 + world/extends/login.js | 101 + world/extends/map/area.js | 22 + world/extends/map/fam_area.js | 37 + world/extends/message.js | 169 ++ world/extends/skill/family.js | 415 +++ world/extends/skill/skill.js | 51 + world/extends/stats.js | 232 ++ world/extends/update.js | 0 world/extends/world.js | 63 + world/family/emei.js | 89 + world/family/gaibang.js | 87 + world/family/huashan.js | 90 + world/family/liushan.js | 28 + world/family/monster.js | 11 + world/family/none.js | 42 + world/family/shaolin.js | 98 + world/family/shashou.js | 107 + world/family/wudang.js | 82 + world/family/wulang.js | 28 + world/family/xiaoyao.js | 90 + world/map/banghui/cangku.js | 28 + world/map/banghui/damen.js | 5 + world/map/banghui/juyitang.js | 4 + world/map/banghui/liangong.js | 30 + world/map/banghui/lianyao.js | 29 + world/map/banghui/yuanzi.js | 13 + world/map/bj/ao/andao.js | 29 + world/map/bj/ao/anshi.js | 9 + world/map/bj/ao/chufang.js | 6 + world/map/bj/ao/damen.js | 10 + world/map/bj/ao/dayuan.js | 6 + world/map/bj/ao/houyuan.js | 20 + world/map/bj/ao/laofang.js | 5 + world/map/bj/ao/shufang.js | 38 + world/map/bj/ao/woshi.js | 18 + world/map/bj/shenlong/dadao.js | 8 + world/map/bj/shenlong/dadao2.js | 8 + world/map/bj/shenlong/damen.js | 17 + world/map/bj/shenlong/dating.js | 8 + world/map/bj/shenlong/haitan.js | 50 + world/map/bj/shenlong/kongdi.js | 8 + world/map/bj/shenlong/lin1.js | 20 + world/map/bj/shenlong/lin2.js | 8 + world/map/bj/shenlong/wuchang.js | 8 + world/map/bj/shenlong/xiaowu.js | 8 + world/map/bj/tdh/andao.js | 22 + world/map/bj/tdh/andao1.js | 6 + world/map/bj/tdh/andao2.js | 6 + world/map/bj/tdh/ceting.js | 16 + world/map/bj/tdh/dating.js | 7 + world/map/bj/tdh/hct.js | 5 + world/map/bj/tdh/hutong.js | 3 + world/map/bj/tdh/kedian.js | 39 + world/map/bj/tdh/kedian3.js | 8 + world/map/bj/tdh/neishi.js | 31 + world/map/bj/zhuang/changlang.js | 6 + world/map/bj/zhuang/dalu.js | 3 + world/map/bj/zhuang/damen.js | 27 + world/map/bj/zhuang/dating.js | 7 + world/map/bj/zhuang/dating1.js | 6 + world/map/bj/zhuang/dating2.js | 5 + world/map/bj/zhuang/dayuan.js | 5 + world/map/bj/zhuang/xiaolu.js | 31 + world/map/bj/zhuang/xiaolu2.js | 5 + world/map/bj/zhuang/xiaowu.js | 5 + world/map/emei/chufang.js | 4 + world/map/emei/dadian.js | 5 + world/map/emei/duguangtai.js | 4 + world/map/emei/guangchang.js | 7 + world/map/emei/huacang.js | 4 + world/map/emei/jinding.js | 4 + world/map/emei/liangong.js | 6 + world/map/emei/miaomen.js | 5 + world/map/emei/qingxiu.js | 6 + world/map/emei/xiaowu.js | 5 + world/map/emei/xiuxishi.js | 4 + world/map/emei/zoulang1.js | 4 + world/map/emei/zoulang2.js | 5 + world/map/emei/zoulang3.js | 4 + world/map/emei/zoulang4.js | 4 + world/map/gaibang/andao1.js | 4 + world/map/gaibang/andao2.js | 5 + world/map/gaibang/andao3.js | 4 + world/map/gaibang/andao4.js | 6 + world/map/gaibang/mishi.js | 6 + world/map/gaibang/pomiao.js | 6 + world/map/gaibang/shudong.js | 4 + world/map/gaibang/shudongxia.js | 6 + world/map/gaibang/xiaowu.js | 5 + world/map/home/danjian.js | 54 + world/map/home/huayuan.js | 36 + world/map/home/liangong.js | 35 + world/map/home/lianyao.js | 33 + world/map/home/store.js | 4 + world/map/home/woshi.js | 31 + world/map/home/yuanzi.js | 32 + world/map/huashan/canglong.js | 4 + world/map/huashan/hole.js | 4 + world/map/huashan/jueding.js | 8 + world/map/huashan/keting.js | 6 + world/map/huashan/liangong.js | 5 + world/map/huashan/lianwu.js | 7 + world/map/huashan/luoyan.js | 79 + world/map/huashan/pianting.js | 4 + world/map/huashan/pingdi.js | 4 + world/map/huashan/qiaobi.js | 4 + world/map/huashan/shangu.js | 4 + world/map/huashan/shanlu.js | 4 + world/map/huashan/sheshen.js | 25 + world/map/huashan/siguoya.js | 25 + world/map/huashan/woshi.js | 4 + world/map/huashan/xiaojing.js | 4 + world/map/huashan/xiaowu.js | 5 + world/map/huashan/yunv.js | 7 + world/map/huashan/yunvci.js | 4 + world/map/huashan/zhandao.js | 4 + world/map/huashan/zhenyue.js | 8 + world/map/kezhan/fang1.js | 39 + world/map/kezhan/fang2.js | 40 + world/map/kezhan/fang3.js | 39 + world/map/new/new1.js | 129 + world/map/new/new2.js | 122 + world/map/new/new3.js | 13 + world/map/shaolin/banruo.js | 6 + world/map/shaolin/cangjing.js | 4 + world/map/shaolin/damo.js | 4 + world/map/shaolin/damodong.js | 4 + world/map/shaolin/daxiong.js | 4 + world/map/shaolin/fangzhang.js | 6 + world/map/shaolin/guangchang.js | 5 + world/map/shaolin/gulou.js | 4 + world/map/shaolin/houdian.js | 4 + world/map/shaolin/jielv.js | 4 + world/map/shaolin/liangong1.js | 5 + world/map/shaolin/liangong2.js | 5 + world/map/shaolin/lianwu.js | 7 + world/map/shaolin/luohan.js | 5 + world/map/shaolin/shanmen.js | 5 + world/map/shaolin/twdian.js | 5 + world/map/shaolin/zhonglou.js | 4 + world/map/shaolin/zhulin1.js | 4 + world/map/shaolin/zhulin2.js | 4 + world/map/shashou/ange1.js | 17 + world/map/shashou/ange2.js | 7 + world/map/shashou/ange3.js | 7 + world/map/shashou/damen.js | 9 + world/map/shashou/datang.js | 8 + world/map/shashou/jinlou.js | 7 + world/map/shashou/liangong.js | 6 + world/map/shashou/pingtai.js | 7 + world/map/shashou/shufang.js | 8 + world/map/shashou/tonglou.js | 7 + world/map/shashou/xiuxi.js | 6 + world/map/shashou/yinlou.js | 8 + world/map/wd/chaotian.js | 4 + world/map/wd/guangchang.js | 5 + world/map/wd/hutou.js | 4 + world/map/wd/liangong.js | 6 + world/map/wd/nanyan.js | 4 + world/map/wd/sanqing.js | 5 + world/map/wd/santian.js | 4 + world/map/wd/sheshen.js | 4 + world/map/wd/shijie1.js | 5 + world/map/wd/taiziyan.js | 6 + world/map/wd/tylu.js | 4 + world/map/wd/wulao.js | 4 + world/map/wd/wuya.js | 4 + world/map/wd/xiaolu.js | 4 + world/map/wd/xiaolu2.js | 4 + world/map/wd/xiaoyuan.js | 5 + world/map/wd/zijin.js | 4 + world/map/wudao/ding.js | 9 + world/map/wudao/east.js | 23 + world/map/wudao/men.js | 26 + world/map/wudao/north.js | 22 + world/map/wudao/south.js | 23 + world/map/wudao/ta.js | 204 ++ world/map/wudao/ta2.js | 94 + world/map/wudao/up.js | 6 + world/map/wudao/west.js | 22 + world/map/xiangyang/bingying2.js | 13 + world/map/xiangyang/eastgate1.js | 9 + world/map/xiangyang/eastgate2.js | 8 + world/map/xiangyang/eastjie1.js | 10 + world/map/xiangyang/eastjie2.js | 16 + world/map/xiangyang/eastjie3.js | 9 + world/map/xiangyang/guangchang.js | 10 + world/map/xiangyang/northgate1.js | 9 + world/map/xiangyang/northgate2.js | 7 + world/map/xiangyang/northjie1.js | 7 + world/map/xiangyang/northjie2.js | 7 + world/map/xiangyang/northjie3.js | 7 + world/map/xiangyang/southgate1.js | 9 + world/map/xiangyang/southgate2.js | 6 + world/map/xiangyang/southjie1.js | 9 + world/map/xiangyang/southjie2.js | 9 + world/map/xiangyang/southjie3.js | 9 + world/map/xiangyang/walle1.js | 7 + world/map/xiangyang/walle10.js | 7 + world/map/xiangyang/walle11.js | 7 + world/map/xiangyang/walle12.js | 7 + world/map/xiangyang/walle13.js | 7 + world/map/xiangyang/walle14.js | 7 + world/map/xiangyang/walle15.js | 7 + world/map/xiangyang/walle16.js | 7 + world/map/xiangyang/walle17.js | 7 + world/map/xiangyang/walle18.js | 7 + world/map/xiangyang/walle19.js | 7 + world/map/xiangyang/walle2.js | 7 + world/map/xiangyang/walle20.js | 7 + world/map/xiangyang/walle21.js | 7 + world/map/xiangyang/walle22.js | 7 + world/map/xiangyang/walle23.js | 7 + world/map/xiangyang/walle24.js | 7 + world/map/xiangyang/walle25.js | 7 + world/map/xiangyang/walle26.js | 7 + world/map/xiangyang/walle27.js | 7 + world/map/xiangyang/walle28.js | 7 + world/map/xiangyang/walle29.js | 7 + world/map/xiangyang/walle3.js | 7 + world/map/xiangyang/walle4.js | 7 + world/map/xiangyang/walle5.js | 7 + world/map/xiangyang/walle6.js | 7 + world/map/xiangyang/walle7.js | 7 + world/map/xiangyang/walle8.js | 7 + world/map/xiangyang/walle9.js | 7 + world/map/xiangyang/westgate1.js | 10 + world/map/xiangyang/westgate2.js | 8 + world/map/xiangyang/westjie1.js | 7 + world/map/xiangyang/westjie2.js | 7 + world/map/xiangyang/westjie3.js | 7 + world/map/xiaoyao/liangong.js | 6 + world/map/xiaoyao/linjian.js | 4 + world/map/xiaoyao/linjian1.js | 4 + world/map/xiaoyao/linjian2.js | 4 + world/map/xiaoyao/linjian3.js | 5 + world/map/xiaoyao/muban.js | 4 + world/map/xiaoyao/muwu1.js | 4 + world/map/xiaoyao/muwu2.js | 4 + world/map/xiaoyao/muwu3.js | 4 + world/map/xiaoyao/qingcaop.js | 4 + world/map/xiaoyao/shishi.js | 4 + world/map/xiaoyao/shishi2.js | 4 + world/map/xiaoyao/xiuxishi.js | 4 + world/map/yz/banghui.js | 13 + world/map/yz/beidajie1.js | 4 + world/map/yz/beidajie2.js | 4 + world/map/yz/beimen.js | 4 + world/map/yz/biaoju.js | 5 + world/map/yz/by/bingqiku.js | 75 + world/map/yz/by/bingying.js | 28 + world/map/yz/by/damen.js | 11 + world/map/yz/by/tongdao.js | 3 + world/map/yz/cangbao.js | 10 + world/map/yz/cuifu/caizhu.js | 28 + world/map/yz/cuifu/dayuan.js | 16 + world/map/yz/cuifu/dongxiang.js | 24 + world/map/yz/cuifu/houyuan.js | 27 + world/map/yz/cuifu/xixiang.js | 5 + world/map/yz/dangpu.js | 10 + world/map/yz/datiepu.js | 7 + world/map/yz/dongdajie1.js | 5 + world/map/yz/dongdajie2.js | 4 + world/map/yz/dongmen.js | 4 + world/map/yz/duchang.js | 141 + world/map/yz/garments.js | 30 + world/map/yz/guangchang.js | 29 + world/map/yz/hanshui.js | 10 + world/map/yz/home.js | 6 + world/map/yz/hy/dilao.js | 8 + world/map/yz/hy/jiaochang1.js | 11 + world/map/yz/hy/jiaochang2.js | 20 + world/map/yz/hy/jiaochang3.js | 11 + world/map/yz/hy/jiaochang4.js | 9 + world/map/yz/hy/jiaochang5.js | 10 + world/map/yz/hy/tongdao.js | 8 + world/map/yz/hy/yishiting.js | 42 + world/map/yz/kedian.js | 8 + world/map/yz/kuang.js | 10 + world/map/yz/lcy/dating.js | 6 + world/map/yz/lcy/erlou.js | 5 + world/map/yz/lcy/fang1.js | 4 + world/map/yz/lcy/fang2.js | 22 + world/map/yz/lcy/mishi.js | 20 + world/map/yz/leitai/biwu.js | 54 + world/map/yz/leitai/biwu2.js | 85 + world/map/yz/leitai/leitai.js | 70 + world/map/yz/leitai/ltx.js | 5 + world/map/yz/lmw/fang.js | 5 + world/map/yz/lmw/pomaowu.js | 5 + world/map/yz/lmw/xiangzi1.js | 14 + world/map/yz/lmw/xiangzi2.js | 19 + world/map/yz/lmw/xiangzi3.js | 50 + world/map/yz/lw/milin.js | 6 + world/map/yz/lw/milin2.js | 5 + world/map/yz/lw/milin3.js | 179 ++ world/map/yz/lw/shangu.js | 7 + world/map/yz/nandajie1.js | 4 + world/map/yz/nandajie2.js | 4 + world/map/yz/nanmen.js | 4 + world/map/yz/neishi.js | 7 + world/map/yz/qianzhuang.js | 9 + world/map/yz/shuyuan.js | 15 + world/map/yz/tree1.js | 8 + world/map/yz/work.js | 35 + world/map/yz/wuguan.js | 7 + world/map/yz/wumiao.js | 70 + world/map/yz/xidajie1.js | 5 + world/map/yz/xidajie2.js | 4 + world/map/yz/ximen.js | 4 + world/map/yz/yamen.js | 4 + world/map/yz/yaolin.js | 11 + world/map/yz/yaopu.js | 32 + world/map/yz/ymzhengting.js | 6 + world/map/yz/zahuopu.js | 8 + world/map/yz/zhengting.js | 6 + world/map/yz/zuixianlou.js | 6 + world/map/yz/zuixianlou2.js | 6 + world/npc/bj/ao/aobai.js | 59 + world/npc/bj/ao/chushi.js | 20 + world/npc/bj/ao/guanjia.js | 34 + world/npc/bj/ao/jiading.js | 37 + world/npc/bj/ao/wu.js | 36 + world/npc/bj/ao/zhuangyu.js | 52 + world/npc/bj/guanwai/asi.js | 45 + world/npc/bj/guanwai/chuanfu.js | 38 + world/npc/bj/guanwai/diao.js | 25 + world/npc/bj/guanwai/hu.js | 24 + world/npc/bj/guanwai/hufei.js | 81 + world/npc/bj/guanwai/xiong.js | 35 + world/npc/bj/guanwai/yanji.js | 47 + world/npc/bj/lm/heilong.js | 134 + world/npc/bj/lm/xiezi.js | 40 + world/npc/bj/lm/yongwei.js | 41 + world/npc/bj/shenlong/dizi.js | 47 + world/npc/bj/shenlong/dushe.js | 23 + world/npc/bj/shenlong/hong.js | 58 + world/npc/bj/shenlong/lu.js | 50 + world/npc/bj/shenlong/nvdizi.js | 47 + world/npc/bj/shenlong/wugen.js | 58 + world/npc/bj/shenlong/xu.js | 55 + world/npc/bj/shenlong/zhang.js | 58 + world/npc/bj/shenlong/zyshe.js | 23 + world/npc/bj/tdh/chen.js | 42 + world/npc/bj/tdh/dubi.js | 55 + world/npc/bj/tdh/guan.js | 38 + world/npc/bj/tdh/huoji.js | 31 + world/npc/bj/tdh/lama.js | 68 + world/npc/bj/tdh/li.js | 40 + world/npc/bj/tdh/wu.js | 42 + world/npc/bj/tdh/xu.js | 38 + world/npc/bj/tdh/xuan.js | 44 + world/npc/bj/zhuang/furen.js | 63 + world/npc/bj/zhuang/shuanger.js | 53 + world/npc/bj/zhuang/tufei.js | 41 + world/npc/bj/zhuang/zhang.js | 40 + world/npc/emei/jingxin.js | 39 + world/npc/emei/miejue.js | 42 + world/npc/emei/sumengqing.js | 36 + world/npc/emei/zhouzhiruo.js | 43 + world/npc/follower/azi.js | 22 + world/npc/follower/cheng.js | 28 + world/npc/follower/huang.js | 25 + world/npc/follower/lang.js | 26 + world/npc/follower/qing.js | 24 + world/npc/follower/shimei.js | 34 + world/npc/follower/shuang.js | 37 + world/npc/follower/wang.js | 32 + world/npc/follower/wenyi.js | 31 + world/npc/follower/xia.js | 28 + world/npc/follower/xiaolongnv.js | 27 + world/npc/follower/xiaozhao.js | 34 + world/npc/follower/zhang.js | 32 + world/npc/follower/zhou.js | 37 + world/npc/gaibang/hongqigong.js | 44 + world/npc/gaibang/jian.js | 38 + world/npc/gaibang/lu.js | 41 + world/npc/gaibang/zuo.js | 29 + world/npc/huashan/fengbuping.js | 36 + world/npc/huashan/fengqingyang.js | 48 + world/npc/huashan/gaogenming.js | 37 + world/npc/huashan/yuebuqun.js | 47 + world/npc/new/daoshi.js | 43 + world/npc/new/mutouren.js | 17 + world/npc/pub/baodi.js | 19 + world/npc/pub/bing.js | 43 + world/npc/pub/biwu.js | 45 + world/npc/pub/bpguanli.js | 76 + world/npc/pub/ckguanli.js | 23 + world/npc/pub/dadizi.js | 71 + world/npc/pub/gaoshou1.js | 21 + world/npc/pub/guanjia.js | 87 + world/npc/pub/hua.js | 12 + world/npc/pub/hubu.js | 242 ++ world/npc/pub/jiaoxi.js | 55 + world/npc/pub/menpai.js | 18 + world/npc/pub/mpguanli.js | 84 + world/npc/pub/muren.js | 23 + world/npc/pub/paimai.js | 22 + world/npc/pub/qian.js | 21 + world/npc/pub/tiejiang.js | 113 + world/npc/pub/tongren.js | 29 + world/npc/pub/wudao.js | 91 + world/npc/pub/wudao_men.js | 32 + world/npc/pub/wujiang.js | 32 + world/npc/pub/xiaoer.js | 99 + world/npc/pub/xiaoer2.js | 32 + world/npc/pub/yamen.js | 33 + world/npc/pub/yayi.js | 21 + world/npc/pub/yb_npc.js | 23 + world/npc/pub/yingzi.js | 16 + world/npc/shaolin/chengjing.js | 51 + world/npc/shaolin/daojue.js | 45 + world/npc/shaolin/huihe.js | 49 + world/npc/shaolin/qingle.js | 38 + world/npc/shaolin/xuannan.js | 51 + world/npc/shashou/her.js | 37 + world/npc/shashou/lisi.js | 41 + world/npc/shashou/shashou.js | 36 + world/npc/shashou/wu.js | 43 + world/npc/wudang/daotong.js | 27 + world/npc/wudang/guxu.js | 32 + world/npc/wudang/song.js | 43 + world/npc/wudang/zhangsanfeng.js | 50 + world/npc/xiangyang/bing.js | 53 + world/npc/xiangyang/duihuan.js | 32 + world/npc/xiangyang/ge.js | 33 + world/npc/xiangyang/guo.js | 52 + world/npc/xiangyang/menggu1.js | 31 + world/npc/xiangyang/menggu2.js | 31 + world/npc/xiangyang/menggu3.js | 31 + world/npc/xiangyang/menggu4.js | 29 + world/npc/xiangyang/menggu5.js | 30 + world/npc/xiangyang/shouwei1.js | 43 + world/npc/xiangyang/shouwei2.js | 43 + world/npc/xiangyang/shouwei3.js | 42 + world/npc/xiangyang/shouwei4.js | 42 + world/npc/xiangyang/shouwei5.js | 43 + world/npc/xiaoyao/suxinghe.js | 42 + world/npc/xiaoyao/xiaoyaozi.js | 50 + world/npc/xiaoyao/xuemuhua.js | 31 + world/npc/yz/biaotou.js | 17 + world/npc/yz/caipan.js | 16 + world/npc/yz/cheng.js | 32 + world/npc/yz/cuifu/cui.js | 45 + world/npc/yz/cuifu/guanjia.js | 32 + world/npc/yz/cuifu/jiading.js | 33 + world/npc/yz/cuifu/langgou.js | 22 + world/npc/yz/cuifu/yahuan.js | 48 + world/npc/yz/cuifu/yingying.js | 33 + world/npc/yz/hy/jiaotu.js | 106 + world/npc/yz/hy/jiaoxi.js | 78 + world/npc/yz/hy/tiehu.js | 81 + world/npc/yz/hy/yin.js | 82 + world/npc/yz/lcy/guigong.js | 40 + world/npc/yz/lcy/maoshiba.js | 89 + world/npc/yz/lcy/shisong.js | 70 + world/npc/yz/lcy/weichunfang.js | 54 + world/npc/yz/linpingzhi.js | 20 + world/npc/yz/linzhennan.js | 28 + world/npc/yz/lm/liumang.js | 38 + world/npc/yz/lm/lmtou.js | 41 + world/npc/yz/lm/xiaolm.js | 68 + world/npc/yz/lm/zhao.js | 41 + world/npc/yz/lw/lang.js | 28 + world/npc/yz/lw/langwang.js | 110 + world/npc/yz/lw/langwang2.js | 15 + world/npc/yz/lw/she.js | 31 + world/npc/yz/lw/yegou.js | 22 + world/npc/yz/ping.js | 85 + world/npc/yz/shiqingshan.js | 76 + world/npc/yz/tang.js | 60 + world/npc/yz/yang.js | 15 + world/npc/yz/yuhuan.js | 24 + world/npc/yz/zeng.js | 12 + world/npc/yz/zhu.js | 99 + world/npc/yz/zhubanxian.js | 237 ++ world/obj/book/bc.js | 27 + world/obj/book/bk.js | 56 + world/obj/book/book.js | 47 + world/obj/book/ts.js | 20 + world/obj/book/up.js | 11 + world/obj/book/wd.js | 11 + world/obj/book/wudao.js | 19 + world/obj/cash/bian.js | 71 + world/obj/cash/box_sm.js | 21 + world/obj/cash/ck_add.js | 16 + world/obj/cash/fang.js | 25 + world/obj/cash/fangqi.js | 15 + world/obj/cash/gaiming.js | 97 + world/obj/cash/jing.js | 57 + world/obj/cash/new_box.js | 19 + world/obj/cash/pack_add.js | 16 + world/obj/cash/saodang.js | 8 + world/obj/cash/sm.js | 27 + world/obj/cash/tianshifu.js | 9 + world/obj/cash/tool.js | 45 + world/obj/cash/tool_box2.js | 68 + world/obj/cash/tuoli.js | 94 + world/obj/cash/xi.js | 79 + world/obj/drug/age.js | 12 + world/obj/drug/buff.js | 62 + world/obj/drug/dushe.js | 17 + world/obj/drug/exp.js | 63 + world/obj/drug/hr2.js | 12 + world/obj/drug/huirong.js | 12 + world/obj/drug/huoyan.js | 17 + world/obj/drug/limit_mp.js | 52 + world/obj/drug/max_mp.js | 61 + world/obj/drug/meirong.js | 13 + world/obj/drug/mr2.js | 12 + world/obj/drug/pot.js | 58 + world/obj/drug/sdrug.js | 84 + world/obj/drug/skill2.js | 54 + world/obj/drug/xiongdan.js | 16 + world/obj/drug/yao.js | 61 + world/obj/drug/yulu.js | 16 + world/obj/eq/lv0/cloth.js | 11 + world/obj/eq/lv0/dao.js | 12 + world/obj/eq/lv0/duanyi.js | 13 + world/obj/eq/lv0/fei.js | 11 + world/obj/eq/lv0/huang.js | 11 + world/obj/eq/lv0/jd_cloth.js | 11 + world/obj/eq/lv0/jd_shoes.js | 11 + world/obj/eq/lv0/jian.js | 10 + world/obj/eq/lv0/jin.js | 8 + world/obj/eq/lv0/mugun.js | 10 + world/obj/eq/lv0/niaowo.js | 12 + world/obj/eq/lv0/ring.js | 11 + world/obj/eq/lv0/shoes.js | 11 + world/obj/eq/lv0/tiegun.js | 12 + world/obj/eq/lv0/tiezhang.js | 12 + world/obj/eq/lv0/whip.js | 14 + world/obj/eq/lv0/zan.js | 8 + world/obj/eq/lv1/cui_sz.js | 14 + world/obj/eq/lv1/dandao.js | 14 + world/obj/eq/lv1/fuchen.js | 14 + world/obj/eq/lv1/gold_ring.js | 13 + world/obj/eq/lv1/guanfu.js | 13 + world/obj/eq/lv1/jinshezhui.js | 13 + world/obj/eq/lv1/jundao.js | 14 + world/obj/eq/lv1/junfu.js | 13 + world/obj/eq/lv1/lm_cloth.js | 13 + world/obj/eq/lv1/lm_gun.js | 14 + world/obj/eq/lv1/lm_head.js | 13 + world/obj/eq/lv1/lm_jian.js | 13 + world/obj/eq/lv1/lm_shoes.js | 13 + world/obj/eq/lv1/lm_shou.js | 13 + world/obj/eq/lv1/pifeng.js | 13 + world/obj/eq/lv1/qianjinquan.js | 14 + world/obj/eq/lv1/qimeigun.js | 14 + world/obj/eq/lv1/qingmu.js | 11 + world/obj/eq/lv1/wd_cloth.js | 13 + world/obj/eq/lv1/wd_jian.js | 14 + world/obj/eq/lv1/wei_neck.js | 13 + world/obj/eq/lv1/xk_cloth.js | 13 + world/obj/eq/lv1/xk_head.js | 13 + world/obj/eq/lv1/xk_shoes.js | 13 + world/obj/eq/lv2/anqi.js | 15 + world/obj/eq/lv2/ao_bishou.js | 16 + world/obj/eq/lv2/ao_jia.js | 15 + world/obj/eq/lv2/gun.js | 12 + world/obj/eq/lv2/hl_bian.js | 18 + world/obj/eq/lv2/hs_qin.js | 14 + world/obj/eq/lv2/jiangjunjian.js | 15 + world/obj/eq/lv2/js_nang.js | 13 + world/obj/eq/lv2/js_pifeng.js | 14 + world/obj/eq/lv2/js_ring.js | 14 + world/obj/eq/lv2/lm_cloth.js | 28 + world/obj/eq/lv2/lm_jian.js | 28 + world/obj/eq/lv2/lm_pei.js | 26 + world/obj/eq/lv2/lm_pifeng.js | 27 + world/obj/eq/lv2/lm_shoes.js | 26 + world/obj/eq/lv2/lm_tou.js | 27 + world/obj/eq/lv2/sl_cloth.js | 15 + world/obj/eq/lv2/sl_ling.js | 13 + world/obj/eq/lv2/sl_shoes.js | 15 + world/obj/eq/lv2/sl_shou.js | 14 + world/obj/eq/lv2/sl_tou.js | 15 + world/obj/eq/lv2/sl_yao.js | 13 + world/obj/eq/lv2/sl_zhang.js | 17 + world/obj/eq/lv2/wd_shou.js | 14 + world/obj/eq/lv2/wd_tou.js | 14 + world/obj/eq/lv2/yunlongjian.js | 16 + world/obj/eq/new/cloth1.js | 8 + world/obj/eq/new/cloth2.js | 8 + world/obj/food/desk.js | 33 + world/obj/food/desk2.js | 19 + world/obj/food/drink.js | 72 + world/obj/food/food.js | 67 + world/obj/food/hua.js | 12 + world/obj/food/marry.js | 75 + world/obj/money/bp.js | 9 + world/obj/money/cash.js | 12 + world/obj/money/coin.js | 11 + world/obj/money/exp.js | 12 + world/obj/money/g100.js | 9 + world/obj/money/gold.js | 8 + world/obj/money/gongji.js | 14 + world/obj/money/hua.js | 10 + world/obj/money/p1w.js | 16 + world/obj/money/pot.js | 12 + world/obj/money/silver.js | 7 + world/obj/res/cao.js | 24 + world/obj/res/eyupi.js | 12 + world/obj/res/huang.js | 32 + world/obj/res/huolongpi.js | 11 + world/obj/res/langpi.js | 20 + world/obj/res/pimao1.js | 9 + world/obj/res/pimao2.js | 9 + world/obj/res/shexue.js | 10 + world/obj/res/yu.js | 26 + world/obj/sp/bj/jing.js | 101 + world/obj/sp/bj/jiu.js | 8 + world/obj/sp/bj/laofangkey.js | 7 + world/obj/sp/bj/map.js | 10 + world/obj/sp/bj/wu.js | 7 + world/obj/sp/bj/yanji.js | 7 + world/obj/sp/bj/zhu.js | 9 + world/obj/sp/dati.js | 13 + world/obj/sp/dizi.js | 17 + world/obj/sp/mihan.js | 13 + world/obj/sp/new/ksforce.js | 20 + world/obj/sp/new/ksunarmed.js | 20 + world/obj/sp/new/mutou.js | 7 + world/obj/sp/new/qicai.js | 8 + world/obj/sp/npc.js | 110 + world/obj/sp/tool/chu.js | 31 + world/obj/sp/tool/diao.js | 25 + world/obj/sp/tool/er.js | 39 + world/obj/sp/tool/er2.js | 27 + world/obj/sp/tool/exp.js | 36 + world/obj/sp/tool/fuqi.js | 35 + world/obj/sp/tool/shitu.js | 32 + world/obj/sp/tool/sm.js | 20 + world/obj/sp/tool/summon.js | 22 + world/obj/sp/tool/yao.js | 27 + world/obj/sp/tool/zhuisha.js | 54 + world/obj/sp/yz/box1.js | 26 + world/obj/sp/yz/qiantiao.js | 8 + world/obj/sp/yz/xin.js | 16 + world/obj/sp/yz/yaoshi.js | 7 + world/obj/st/st_blu.js | 60 + world/obj/st/st_ds.js | 46 + world/obj/st/st_fy.js | 46 + world/obj/st/st_gj.js | 46 + world/obj/st/st_gre.js | 60 + world/obj/st/st_mz.js | 47 + world/obj/st/st_red.js | 61 + world/obj/st/st_s2.js | 48 + world/obj/st/st_sc.js | 63 + world/obj/st/st_yel.js | 60 + world/obj/st/xuanjing.js | 11 + world/obj/st/yuanjing.js | 11 + world/skill/base/bite.js | 13 + world/skill/base/blade.js | 34 + world/skill/base/club.js | 13 + world/skill/base/dodge.js | 15 + world/skill/base/force.js | 9 + world/skill/base/parry.js | 24 + world/skill/base/staff.js | 13 + world/skill/base/sword.js | 36 + world/skill/base/throwing.js | 13 + world/skill/base/unarmed.js | 35 + world/skill/base/whip.js | 14 + world/skill/blade/hujiadaofa.js | 119 + world/skill/blade/wuhuduanmendao.js | 89 + world/skill/club/baguagun.js | 93 + world/skill/club/juemengun.js | 83 + world/skill/club/mengguqiangfa.js | 124 + world/skill/club/weituogun.js | 71 + world/skill/club/zhongpingqiang.js | 107 + world/skill/dodge/chanchubufa.js | 31 + world/skill/dodge/feiyanzoubi.js | 28 + world/skill/dodge/qingfushenfa.js | 31 + world/skill/dodge/shenxingbaibian.js | 84 + world/skill/dodge/sixiangbu.js | 80 + world/skill/dodge/wuduyanluobu.js | 76 + world/skill/dodge/yixingbufa.js | 32 + world/skill/dodge/yunlongshenfa.js | 34 + world/skill/emei/emeixinfa.js | 24 + world/skill/emei/huifengjian.js | 99 + world/skill/emei/jindingzhang.js | 64 + world/skill/emei/jiuyinbaiguzhao.js | 98 + world/skill/emei/linjizhuang.js | 126 + world/skill/emei/yitianjianfa.js | 120 + world/skill/emei/zhutianbu.js | 31 + world/skill/force/baiyunxinfa.js | 93 + world/skill/force/biboshengong.js | 26 + world/skill/force/heilongxinfa.js | 98 + world/skill/force/lengyueshengong.js | 25 + world/skill/force/longxianggong.js | 138 + world/skill/force/mengguxinfa.js | 81 + world/skill/force/mizongxinfa.js | 24 + world/skill/force/panshishengong.js | 87 + world/skill/force/shenlongxinfa.js | 78 + world/skill/force/yunlongxinfa.js | 92 + world/skill/gaibang/dagoubang.js | 102 + world/skill/gaibang/gaibangxinfa.js | 24 + world/skill/gaibang/huntianqigong.js | 60 + world/skill/gaibang/jiaohuabangfa.js | 69 + world/skill/gaibang/xianglongzhang.js | 173 ++ world/skill/gaibang/xiaoyaoyou.js | 56 + world/skill/huashan/dugujiujian.js | 196 ++ world/skill/huashan/feiyanhuixiang.js | 30 + world/skill/huashan/huashanjianfa.js | 59 + world/skill/huashan/huashanquanfa.js | 29 + world/skill/huashan/huashanxinfa.js | 24 + world/skill/huashan/kuangfengkuaijian.js | 115 + world/skill/huashan/poyuquan.js | 104 + world/skill/huashan/zixiashengong.js | 63 + world/skill/knowage/lianyao.js | 60 + world/skill/knowage/literate.js | 127 + world/skill/monster/bite2.js | 45 + world/skill/monster/dushe.js | 45 + world/skill/shaolin/damojian.js | 62 + world/skill/shaolin/hunyuanyiqi.js | 26 + world/skill/shaolin/ranmudao.js | 109 + world/skill/shaolin/shaolinshenfa.js | 58 + world/skill/shaolin/yijinjing.js | 135 + world/skill/shaolin/yizhichan.js | 70 + world/skill/shashou/chuanxinzhang.js | 81 + world/skill/shashou/feidao.js | 53 + world/skill/shashou/mantianhuayu.js | 111 + world/skill/shashou/shashengjue.js | 110 + world/skill/shashou/shashoubufa.js | 31 + world/skill/shashou/shashouxinfa.js | 24 + world/skill/shashou/taxuexunmei.js | 59 + world/skill/staff/fumozhang.js | 94 + world/skill/staff/shedaoqigong.js | 121 + world/skill/staff/wuchangzhang.js | 80 + world/skill/sword/shenlongjian.js | 97 + world/skill/sword/taishanjianfa.js | 104 + world/skill/sword/tangshijianfa.js | 93 + world/skill/sword/yunlongjian.js | 104 + world/skill/unarmed/baguaquan.js | 83 + world/skill/unarmed/changquan.js | 135 + world/skill/unarmed/dashouyin.js | 91 + world/skill/unarmed/fuhuquan.js | 60 + world/skill/unarmed/houquan.js | 71 + world/skill/unarmed/huagumianzhang.js | 112 + world/skill/unarmed/jingangquan.js | 67 + world/skill/unarmed/jinshezhang.js | 94 + world/skill/unarmed/liuyunzhang.js | 88 + world/skill/unarmed/qianzhuwandushou.js | 150 + world/skill/unarmed/qinlong.js | 118 + world/skill/unarmed/tianchangzhang.js | 78 + world/skill/unarmed/yingzhuagong.js | 81 + world/skill/whip/qiufengfuchen.js | 94 + world/skill/whip/yunlongbian.js | 96 + world/skill/wudang/taijijian.js | 185 ++ world/skill/wudang/taijiquan.js | 118 + world/skill/wudang/taijishengong.js | 67 + world/skill/wudang/tiyunzong.js | 49 + world/skill/wudang/wudangchangquan.js | 65 + world/skill/wudang/wudangjianfa.js | 62 + world/skill/wudang/wudangxinfa.js | 25 + world/skill/xiaoyao/beimingshengong.js | 158 + world/skill/xiaoyao/lingboweibu.js | 72 + world/skill/xiaoyao/liuyangzhang.js | 157 + world/skill/xiaoyao/ruyidao.js | 66 + world/skill/xiaoyao/xiaowuxiang.js | 200 ++ world/skill/xiaoyao/xiaoyaoxinfa.js | 24 + world/skill/xiaoyao/zhemeishou.js | 70 + world/task/boss_task.js | 281 ++ world/task/goods_task.js | 95 + world/task/grow_task.js | 168 ++ world/task/msg.js | 97 + world/task/sm_task.js | 153 + world/task/top_1.js | 178 ++ world/task/wd_task.js | 140 + world/task/xy_task.js | 676 +++++ world/task/ym_task.js | 137 + world/task/ym_task2.js | 197 ++ ...glyphicons-halflings-regular-BKjkU69z.woff | Bin 0 -> 23424 bytes .../glyphicons-halflings-regular-BUJKDMgK.eot | Bin 0 -> 20127 bytes .../glyphicons-halflings-regular-DrwTMapi.ttf | Bin 0 -> 45404 bytes www/assets/index-CD1SkoHj.js | 2529 ++++++++++++++++ www/assets/index-CyhYzrZw.js | 2531 +++++++++++++++++ www/assets/index-klnIecVv.css | 1 + www/index.html | 16 + 1041 files changed, 67405 insertions(+) create mode 100644 .env create mode 100644 api/base.js create mode 100644 api/game.js create mode 100644 api/user.js create mode 100644 config.js create mode 100644 data/db.js create mode 100644 data/def/data.js create mode 100644 data/sql.js create mode 100644 main.js create mode 100644 os/base.js create mode 100644 os/char/chara_comm.js create mode 100644 os/char/chara_equip.js create mode 100644 os/char/chara_move.js create mode 100644 os/char/chara_prop.js create mode 100644 os/char/chara_skill.js create mode 100644 os/char/character.js create mode 100644 os/char/combat.js create mode 100644 os/char/follower.js create mode 100644 os/char/monster.js create mode 100644 os/char/npc.js create mode 100644 os/char/user.js create mode 100644 os/command.js create mode 100644 os/const.js create mode 100644 os/data.js create mode 100644 os/item.js create mode 100644 os/item/container.js create mode 100644 os/item/corpse.js create mode 100644 os/item/equipment.js create mode 100644 os/item/money.js create mode 100644 os/item/obj.js create mode 100644 os/login.js create mode 100644 os/net-ws.js create mode 100644 os/room/area.js create mode 100644 os/room/fam_area.js create mode 100644 os/room/room.js create mode 100644 os/skill/family.js create mode 100644 os/skill/skill.js create mode 100644 os/task/events.js create mode 100644 os/task/playertask.js create mode 100644 os/task/task.js create mode 100644 os/util/data.js create mode 100644 os/util/util.js create mode 100644 os/world.js create mode 100644 os/ws.js create mode 100644 package.json create mode 100644 readme.md create mode 100644 src/api.js create mode 100644 src/base/page.js create mode 100644 src/client.js create mode 100644 src/combat.js create mode 100644 src/confirm.js create mode 100644 src/dialog/base.js create mode 100644 src/dialog/channel.js create mode 100644 src/dialog/events.js create mode 100644 src/dialog/extend.js create mode 100644 src/dialog/jh.js create mode 100644 src/dialog/keys.js create mode 100644 src/dialog/list.js create mode 100644 src/dialog/map.js create mode 100644 src/dialog/master.js create mode 100644 src/dialog/message.js create mode 100644 src/dialog/packet.js create mode 100644 src/dialog/packet2.js create mode 100644 src/dialog/paimai.js create mode 100644 src/dialog/party.js create mode 100644 src/dialog/relation.js create mode 100644 src/dialog/score.js create mode 100644 src/dialog/setting.js create mode 100644 src/dialog/shop.js create mode 100644 src/dialog/skills.js create mode 100644 src/dialog/stats.js create mode 100644 src/dialog/tasks.js create mode 100644 src/dialog/team.js create mode 100644 src/dialog/trade.js create mode 100644 src/fonts/fa-solid-900.woff2 create mode 100644 src/fonts/glyphicons-halflings-regular.eot create mode 100644 src/fonts/glyphicons-halflings-regular.ttf create mode 100644 src/fonts/glyphicons-halflings-regular.woff create mode 100644 src/fonts/glyphicons-halflings-regular.woff2 create mode 100644 src/game/main.js create mode 100644 src/game/tool.js create mode 100644 src/img/loader.gif create mode 100644 src/img/thk.png create mode 100644 src/img/timg.gif create mode 100644 src/index.html create mode 100644 src/login/bind-phone.js create mode 100644 src/login/change-pwd.js create mode 100644 src/login/create-role.js create mode 100644 src/login/index.js create mode 100644 src/login/login-in.js create mode 100644 src/login/news.js create mode 100644 src/login/regist.js create mode 100644 src/login/reset-pwd.js create mode 100644 src/login/roles.js create mode 100644 src/login/server.js create mode 100644 src/main.js create mode 100644 src/map.js create mode 100644 src/message.js create mode 100644 src/process.js create mode 100644 src/script.js create mode 100644 src/setting.js create mode 100644 src/startup.js create mode 100644 src/styles/dialog.css create mode 100644 src/styles/global.css create mode 100644 src/styles/main.css create mode 100644 src/utils/util.js create mode 100644 vite.config.js create mode 100644 web.js create mode 100644 world/area/fb1/fb1.js create mode 100644 world/area/fb1/fb2.js create mode 100644 world/area/fb1/fb3.js create mode 100644 world/area/fb1/fb4.js create mode 100644 world/area/fb1/fb5.js create mode 100644 world/area/fb1/fb5_5.js create mode 100644 world/area/fb1/fb6.js create mode 100644 world/area/fb1/fb8.js create mode 100644 world/area/map/emei.js create mode 100644 world/area/map/gaibang.js create mode 100644 world/area/map/heiying.js create mode 100644 world/area/map/home.js create mode 100644 world/area/map/huashan.js create mode 100644 world/area/map/kezhan.js create mode 100644 world/area/map/leitai.js create mode 100644 world/area/map/new.js create mode 100644 world/area/map/party.js create mode 100644 world/area/map/shaolin.js create mode 100644 world/area/map/shashou.js create mode 100644 world/area/map/ta.js create mode 100644 world/area/map/wudang.js create mode 100644 world/area/map/xiangyang.js create mode 100644 world/area/map/xiaoyao.js create mode 100644 world/area/map/yz.js create mode 100644 world/cmd/action/actions.js create mode 100644 world/cmd/action/answer.js create mode 100644 world/cmd/action/ask.js create mode 100644 world/cmd/action/bai.js create mode 100644 world/cmd/action/caiyao.js create mode 100644 world/cmd/action/challenge.js create mode 100644 world/cmd/action/cr.js create mode 100644 world/cmd/action/cr2.js create mode 100644 world/cmd/action/dazuo.js create mode 100644 world/cmd/action/diaoyu.js create mode 100644 world/cmd/action/dismiss.js create mode 100644 world/cmd/action/follow.js create mode 100644 world/cmd/action/go.js create mode 100644 world/cmd/action/goto.js create mode 100644 world/cmd/action/liaoshang.js create mode 100644 world/cmd/action/look.js create mode 100644 world/cmd/action/look1.js create mode 100644 world/cmd/action/look3.js create mode 100644 world/cmd/action/makelove.js create mode 100644 world/cmd/action/select.js create mode 100644 world/cmd/action/state.js create mode 100644 world/cmd/action/status.js create mode 100644 world/cmd/action/wakuang.js create mode 100644 world/cmd/action/wk.js create mode 100644 world/cmd/admin/call.js create mode 100644 world/cmd/admin/notice.js create mode 100644 world/cmd/admin/recover.js create mode 100644 world/cmd/admin/send.js create mode 100644 world/cmd/admin/shutdown.js create mode 100644 world/cmd/admin/update.js create mode 100644 world/cmd/admin/user.js create mode 100644 world/cmd/battle/combat.js create mode 100644 world/cmd/battle/escape.js create mode 100644 world/cmd/battle/fight.js create mode 100644 world/cmd/battle/kill.js create mode 100644 world/cmd/battle/pfm.js create mode 100644 world/cmd/battle/pk.js create mode 100644 world/cmd/battle/relive.js create mode 100644 world/cmd/battle/spfm.js create mode 100644 world/cmd/channel/chat.js create mode 100644 world/cmd/channel/emote.js create mode 100644 world/cmd/channel/es.js create mode 100644 world/cmd/channel/fam.js create mode 100644 world/cmd/channel/filter.js create mode 100644 world/cmd/channel/pty.js create mode 100644 world/cmd/channel/rumor.js create mode 100644 world/cmd/channel/say.js create mode 100644 world/cmd/channel/sys.js create mode 100644 world/cmd/channel/tell.js create mode 100644 world/cmd/channel/tm.js create mode 100644 world/cmd/comm/clearwait.js create mode 100644 world/cmd/comm/createrole.js create mode 100644 world/cmd/comm/dc.js create mode 100644 world/cmd/comm/deleterole.js create mode 100644 world/cmd/comm/greet.js create mode 100644 world/cmd/comm/info.js create mode 100644 world/cmd/comm/login.js create mode 100644 world/cmd/comm/rel.js create mode 100644 world/cmd/comm/setting.js create mode 100644 world/cmd/comm/shortcut.js create mode 100644 world/cmd/comm/sx.js create mode 100644 world/cmd/comm/systask.js create mode 100644 world/cmd/comm/team.js create mode 100644 world/cmd/comm/title.js create mode 100644 world/cmd/comm/zigong.js create mode 100644 world/cmd/dialog/cha.js create mode 100644 world/cmd/dialog/events.js create mode 100644 world/cmd/dialog/i.js create mode 100644 world/cmd/dialog/jh.js create mode 100644 world/cmd/dialog/list.js create mode 100644 world/cmd/dialog/map.js create mode 100644 world/cmd/dialog/message.js create mode 100644 world/cmd/dialog/qu.js create mode 100644 world/cmd/dialog/relation.js create mode 100644 world/cmd/dialog/reward.js create mode 100644 world/cmd/dialog/score.js create mode 100644 world/cmd/dialog/score2.js create mode 100644 world/cmd/dialog/shop.js create mode 100644 world/cmd/dialog/stats.js create mode 100644 world/cmd/dialog/store.js create mode 100644 world/cmd/dialog/task.js create mode 100644 world/cmd/dialog/tasks.js create mode 100644 world/cmd/dialog/trade.js create mode 100644 world/cmd/extend/auto.js create mode 100644 world/cmd/extend/biwu.js create mode 100644 world/cmd/extend/ex.js create mode 100644 world/cmd/extend/paimai.js create mode 100644 world/cmd/extend/party.js create mode 100644 world/cmd/obj/buy.js create mode 100644 world/cmd/obj/checkobj.js create mode 100644 world/cmd/obj/combine.js create mode 100644 world/cmd/obj/dice.js create mode 100644 world/cmd/obj/drop.js create mode 100644 world/cmd/obj/eq_group.js create mode 100644 world/cmd/obj/equip.js create mode 100644 world/cmd/obj/fenjie.js create mode 100644 world/cmd/obj/get.js create mode 100644 world/cmd/obj/give.js create mode 100644 world/cmd/obj/jinglian.js create mode 100644 world/cmd/obj/lianyao.js create mode 100644 world/cmd/obj/lockobj.js create mode 100644 world/cmd/obj/open.js create mode 100644 world/cmd/obj/packitem.js create mode 100644 world/cmd/obj/receive.js create mode 100644 world/cmd/obj/recobj.js create mode 100644 world/cmd/obj/sell.js create mode 100644 world/cmd/obj/unequip.js create mode 100644 world/cmd/obj/unjinglian.js create mode 100644 world/cmd/obj/unxiangqian.js create mode 100644 world/cmd/obj/use.js create mode 100644 world/cmd/obj/xiangqian.js create mode 100644 world/cmd/skill/checkskill.js create mode 100644 world/cmd/skill/enable.js create mode 100644 world/cmd/skill/fangqi.js create mode 100644 world/cmd/skill/fenpei.js create mode 100644 world/cmd/skill/lianxi.js create mode 100644 world/cmd/skill/sbook.js create mode 100644 world/cmd/skill/sk_group.js create mode 100644 world/cmd/skill/stopstate.js create mode 100644 world/cmd/skill/study.js create mode 100644 world/cmd/skill/xiulian.js create mode 100644 world/cmd/skill/xue.js create mode 100644 world/extends/char/auto_combat.js create mode 100644 world/extends/char/combat.js create mode 100644 world/extends/char/user.js create mode 100644 world/extends/data.js create mode 100644 world/extends/item/eq.js create mode 100644 world/extends/item/obj.js create mode 100644 world/extends/login.js create mode 100644 world/extends/map/area.js create mode 100644 world/extends/map/fam_area.js create mode 100644 world/extends/message.js create mode 100644 world/extends/skill/family.js create mode 100644 world/extends/skill/skill.js create mode 100644 world/extends/stats.js create mode 100644 world/extends/update.js create mode 100644 world/extends/world.js create mode 100644 world/family/emei.js create mode 100644 world/family/gaibang.js create mode 100644 world/family/huashan.js create mode 100644 world/family/liushan.js create mode 100644 world/family/monster.js create mode 100644 world/family/none.js create mode 100644 world/family/shaolin.js create mode 100644 world/family/shashou.js create mode 100644 world/family/wudang.js create mode 100644 world/family/wulang.js create mode 100644 world/family/xiaoyao.js create mode 100644 world/map/banghui/cangku.js create mode 100644 world/map/banghui/damen.js create mode 100644 world/map/banghui/juyitang.js create mode 100644 world/map/banghui/liangong.js create mode 100644 world/map/banghui/lianyao.js create mode 100644 world/map/banghui/yuanzi.js create mode 100644 world/map/bj/ao/andao.js create mode 100644 world/map/bj/ao/anshi.js create mode 100644 world/map/bj/ao/chufang.js create mode 100644 world/map/bj/ao/damen.js create mode 100644 world/map/bj/ao/dayuan.js create mode 100644 world/map/bj/ao/houyuan.js create mode 100644 world/map/bj/ao/laofang.js create mode 100644 world/map/bj/ao/shufang.js create mode 100644 world/map/bj/ao/woshi.js create mode 100644 world/map/bj/shenlong/dadao.js create mode 100644 world/map/bj/shenlong/dadao2.js create mode 100644 world/map/bj/shenlong/damen.js create mode 100644 world/map/bj/shenlong/dating.js create mode 100644 world/map/bj/shenlong/haitan.js create mode 100644 world/map/bj/shenlong/kongdi.js create mode 100644 world/map/bj/shenlong/lin1.js create mode 100644 world/map/bj/shenlong/lin2.js create mode 100644 world/map/bj/shenlong/wuchang.js create mode 100644 world/map/bj/shenlong/xiaowu.js create mode 100644 world/map/bj/tdh/andao.js create mode 100644 world/map/bj/tdh/andao1.js create mode 100644 world/map/bj/tdh/andao2.js create mode 100644 world/map/bj/tdh/ceting.js create mode 100644 world/map/bj/tdh/dating.js create mode 100644 world/map/bj/tdh/hct.js create mode 100644 world/map/bj/tdh/hutong.js create mode 100644 world/map/bj/tdh/kedian.js create mode 100644 world/map/bj/tdh/kedian3.js create mode 100644 world/map/bj/tdh/neishi.js create mode 100644 world/map/bj/zhuang/changlang.js create mode 100644 world/map/bj/zhuang/dalu.js create mode 100644 world/map/bj/zhuang/damen.js create mode 100644 world/map/bj/zhuang/dating.js create mode 100644 world/map/bj/zhuang/dating1.js create mode 100644 world/map/bj/zhuang/dating2.js create mode 100644 world/map/bj/zhuang/dayuan.js create mode 100644 world/map/bj/zhuang/xiaolu.js create mode 100644 world/map/bj/zhuang/xiaolu2.js create mode 100644 world/map/bj/zhuang/xiaowu.js create mode 100644 world/map/emei/chufang.js create mode 100644 world/map/emei/dadian.js create mode 100644 world/map/emei/duguangtai.js create mode 100644 world/map/emei/guangchang.js create mode 100644 world/map/emei/huacang.js create mode 100644 world/map/emei/jinding.js create mode 100644 world/map/emei/liangong.js create mode 100644 world/map/emei/miaomen.js create mode 100644 world/map/emei/qingxiu.js create mode 100644 world/map/emei/xiaowu.js create mode 100644 world/map/emei/xiuxishi.js create mode 100644 world/map/emei/zoulang1.js create mode 100644 world/map/emei/zoulang2.js create mode 100644 world/map/emei/zoulang3.js create mode 100644 world/map/emei/zoulang4.js create mode 100644 world/map/gaibang/andao1.js create mode 100644 world/map/gaibang/andao2.js create mode 100644 world/map/gaibang/andao3.js create mode 100644 world/map/gaibang/andao4.js create mode 100644 world/map/gaibang/mishi.js create mode 100644 world/map/gaibang/pomiao.js create mode 100644 world/map/gaibang/shudong.js create mode 100644 world/map/gaibang/shudongxia.js create mode 100644 world/map/gaibang/xiaowu.js create mode 100644 world/map/home/danjian.js create mode 100644 world/map/home/huayuan.js create mode 100644 world/map/home/liangong.js create mode 100644 world/map/home/lianyao.js create mode 100644 world/map/home/store.js create mode 100644 world/map/home/woshi.js create mode 100644 world/map/home/yuanzi.js create mode 100644 world/map/huashan/canglong.js create mode 100644 world/map/huashan/hole.js create mode 100644 world/map/huashan/jueding.js create mode 100644 world/map/huashan/keting.js create mode 100644 world/map/huashan/liangong.js create mode 100644 world/map/huashan/lianwu.js create mode 100644 world/map/huashan/luoyan.js create mode 100644 world/map/huashan/pianting.js create mode 100644 world/map/huashan/pingdi.js create mode 100644 world/map/huashan/qiaobi.js create mode 100644 world/map/huashan/shangu.js create mode 100644 world/map/huashan/shanlu.js create mode 100644 world/map/huashan/sheshen.js create mode 100644 world/map/huashan/siguoya.js create mode 100644 world/map/huashan/woshi.js create mode 100644 world/map/huashan/xiaojing.js create mode 100644 world/map/huashan/xiaowu.js create mode 100644 world/map/huashan/yunv.js create mode 100644 world/map/huashan/yunvci.js create mode 100644 world/map/huashan/zhandao.js create mode 100644 world/map/huashan/zhenyue.js create mode 100644 world/map/kezhan/fang1.js create mode 100644 world/map/kezhan/fang2.js create mode 100644 world/map/kezhan/fang3.js create mode 100644 world/map/new/new1.js create mode 100644 world/map/new/new2.js create mode 100644 world/map/new/new3.js create mode 100644 world/map/shaolin/banruo.js create mode 100644 world/map/shaolin/cangjing.js create mode 100644 world/map/shaolin/damo.js create mode 100644 world/map/shaolin/damodong.js create mode 100644 world/map/shaolin/daxiong.js create mode 100644 world/map/shaolin/fangzhang.js create mode 100644 world/map/shaolin/guangchang.js create mode 100644 world/map/shaolin/gulou.js create mode 100644 world/map/shaolin/houdian.js create mode 100644 world/map/shaolin/jielv.js create mode 100644 world/map/shaolin/liangong1.js create mode 100644 world/map/shaolin/liangong2.js create mode 100644 world/map/shaolin/lianwu.js create mode 100644 world/map/shaolin/luohan.js create mode 100644 world/map/shaolin/shanmen.js create mode 100644 world/map/shaolin/twdian.js create mode 100644 world/map/shaolin/zhonglou.js create mode 100644 world/map/shaolin/zhulin1.js create mode 100644 world/map/shaolin/zhulin2.js create mode 100644 world/map/shashou/ange1.js create mode 100644 world/map/shashou/ange2.js create mode 100644 world/map/shashou/ange3.js create mode 100644 world/map/shashou/damen.js create mode 100644 world/map/shashou/datang.js create mode 100644 world/map/shashou/jinlou.js create mode 100644 world/map/shashou/liangong.js create mode 100644 world/map/shashou/pingtai.js create mode 100644 world/map/shashou/shufang.js create mode 100644 world/map/shashou/tonglou.js create mode 100644 world/map/shashou/xiuxi.js create mode 100644 world/map/shashou/yinlou.js create mode 100644 world/map/wd/chaotian.js create mode 100644 world/map/wd/guangchang.js create mode 100644 world/map/wd/hutou.js create mode 100644 world/map/wd/liangong.js create mode 100644 world/map/wd/nanyan.js create mode 100644 world/map/wd/sanqing.js create mode 100644 world/map/wd/santian.js create mode 100644 world/map/wd/sheshen.js create mode 100644 world/map/wd/shijie1.js create mode 100644 world/map/wd/taiziyan.js create mode 100644 world/map/wd/tylu.js create mode 100644 world/map/wd/wulao.js create mode 100644 world/map/wd/wuya.js create mode 100644 world/map/wd/xiaolu.js create mode 100644 world/map/wd/xiaolu2.js create mode 100644 world/map/wd/xiaoyuan.js create mode 100644 world/map/wd/zijin.js create mode 100644 world/map/wudao/ding.js create mode 100644 world/map/wudao/east.js create mode 100644 world/map/wudao/men.js create mode 100644 world/map/wudao/north.js create mode 100644 world/map/wudao/south.js create mode 100644 world/map/wudao/ta.js create mode 100644 world/map/wudao/ta2.js create mode 100644 world/map/wudao/up.js create mode 100644 world/map/wudao/west.js create mode 100644 world/map/xiangyang/bingying2.js create mode 100644 world/map/xiangyang/eastgate1.js create mode 100644 world/map/xiangyang/eastgate2.js create mode 100644 world/map/xiangyang/eastjie1.js create mode 100644 world/map/xiangyang/eastjie2.js create mode 100644 world/map/xiangyang/eastjie3.js create mode 100644 world/map/xiangyang/guangchang.js create mode 100644 world/map/xiangyang/northgate1.js create mode 100644 world/map/xiangyang/northgate2.js create mode 100644 world/map/xiangyang/northjie1.js create mode 100644 world/map/xiangyang/northjie2.js create mode 100644 world/map/xiangyang/northjie3.js create mode 100644 world/map/xiangyang/southgate1.js create mode 100644 world/map/xiangyang/southgate2.js create mode 100644 world/map/xiangyang/southjie1.js create mode 100644 world/map/xiangyang/southjie2.js create mode 100644 world/map/xiangyang/southjie3.js create mode 100644 world/map/xiangyang/walle1.js create mode 100644 world/map/xiangyang/walle10.js create mode 100644 world/map/xiangyang/walle11.js create mode 100644 world/map/xiangyang/walle12.js create mode 100644 world/map/xiangyang/walle13.js create mode 100644 world/map/xiangyang/walle14.js create mode 100644 world/map/xiangyang/walle15.js create mode 100644 world/map/xiangyang/walle16.js create mode 100644 world/map/xiangyang/walle17.js create mode 100644 world/map/xiangyang/walle18.js create mode 100644 world/map/xiangyang/walle19.js create mode 100644 world/map/xiangyang/walle2.js create mode 100644 world/map/xiangyang/walle20.js create mode 100644 world/map/xiangyang/walle21.js create mode 100644 world/map/xiangyang/walle22.js create mode 100644 world/map/xiangyang/walle23.js create mode 100644 world/map/xiangyang/walle24.js create mode 100644 world/map/xiangyang/walle25.js create mode 100644 world/map/xiangyang/walle26.js create mode 100644 world/map/xiangyang/walle27.js create mode 100644 world/map/xiangyang/walle28.js create mode 100644 world/map/xiangyang/walle29.js create mode 100644 world/map/xiangyang/walle3.js create mode 100644 world/map/xiangyang/walle4.js create mode 100644 world/map/xiangyang/walle5.js create mode 100644 world/map/xiangyang/walle6.js create mode 100644 world/map/xiangyang/walle7.js create mode 100644 world/map/xiangyang/walle8.js create mode 100644 world/map/xiangyang/walle9.js create mode 100644 world/map/xiangyang/westgate1.js create mode 100644 world/map/xiangyang/westgate2.js create mode 100644 world/map/xiangyang/westjie1.js create mode 100644 world/map/xiangyang/westjie2.js create mode 100644 world/map/xiangyang/westjie3.js create mode 100644 world/map/xiaoyao/liangong.js create mode 100644 world/map/xiaoyao/linjian.js create mode 100644 world/map/xiaoyao/linjian1.js create mode 100644 world/map/xiaoyao/linjian2.js create mode 100644 world/map/xiaoyao/linjian3.js create mode 100644 world/map/xiaoyao/muban.js create mode 100644 world/map/xiaoyao/muwu1.js create mode 100644 world/map/xiaoyao/muwu2.js create mode 100644 world/map/xiaoyao/muwu3.js create mode 100644 world/map/xiaoyao/qingcaop.js create mode 100644 world/map/xiaoyao/shishi.js create mode 100644 world/map/xiaoyao/shishi2.js create mode 100644 world/map/xiaoyao/xiuxishi.js create mode 100644 world/map/yz/banghui.js create mode 100644 world/map/yz/beidajie1.js create mode 100644 world/map/yz/beidajie2.js create mode 100644 world/map/yz/beimen.js create mode 100644 world/map/yz/biaoju.js create mode 100644 world/map/yz/by/bingqiku.js create mode 100644 world/map/yz/by/bingying.js create mode 100644 world/map/yz/by/damen.js create mode 100644 world/map/yz/by/tongdao.js create mode 100644 world/map/yz/cangbao.js create mode 100644 world/map/yz/cuifu/caizhu.js create mode 100644 world/map/yz/cuifu/dayuan.js create mode 100644 world/map/yz/cuifu/dongxiang.js create mode 100644 world/map/yz/cuifu/houyuan.js create mode 100644 world/map/yz/cuifu/xixiang.js create mode 100644 world/map/yz/dangpu.js create mode 100644 world/map/yz/datiepu.js create mode 100644 world/map/yz/dongdajie1.js create mode 100644 world/map/yz/dongdajie2.js create mode 100644 world/map/yz/dongmen.js create mode 100644 world/map/yz/duchang.js create mode 100644 world/map/yz/garments.js create mode 100644 world/map/yz/guangchang.js create mode 100644 world/map/yz/hanshui.js create mode 100644 world/map/yz/home.js create mode 100644 world/map/yz/hy/dilao.js create mode 100644 world/map/yz/hy/jiaochang1.js create mode 100644 world/map/yz/hy/jiaochang2.js create mode 100644 world/map/yz/hy/jiaochang3.js create mode 100644 world/map/yz/hy/jiaochang4.js create mode 100644 world/map/yz/hy/jiaochang5.js create mode 100644 world/map/yz/hy/tongdao.js create mode 100644 world/map/yz/hy/yishiting.js create mode 100644 world/map/yz/kedian.js create mode 100644 world/map/yz/kuang.js create mode 100644 world/map/yz/lcy/dating.js create mode 100644 world/map/yz/lcy/erlou.js create mode 100644 world/map/yz/lcy/fang1.js create mode 100644 world/map/yz/lcy/fang2.js create mode 100644 world/map/yz/lcy/mishi.js create mode 100644 world/map/yz/leitai/biwu.js create mode 100644 world/map/yz/leitai/biwu2.js create mode 100644 world/map/yz/leitai/leitai.js create mode 100644 world/map/yz/leitai/ltx.js create mode 100644 world/map/yz/lmw/fang.js create mode 100644 world/map/yz/lmw/pomaowu.js create mode 100644 world/map/yz/lmw/xiangzi1.js create mode 100644 world/map/yz/lmw/xiangzi2.js create mode 100644 world/map/yz/lmw/xiangzi3.js create mode 100644 world/map/yz/lw/milin.js create mode 100644 world/map/yz/lw/milin2.js create mode 100644 world/map/yz/lw/milin3.js create mode 100644 world/map/yz/lw/shangu.js create mode 100644 world/map/yz/nandajie1.js create mode 100644 world/map/yz/nandajie2.js create mode 100644 world/map/yz/nanmen.js create mode 100644 world/map/yz/neishi.js create mode 100644 world/map/yz/qianzhuang.js create mode 100644 world/map/yz/shuyuan.js create mode 100644 world/map/yz/tree1.js create mode 100644 world/map/yz/work.js create mode 100644 world/map/yz/wuguan.js create mode 100644 world/map/yz/wumiao.js create mode 100644 world/map/yz/xidajie1.js create mode 100644 world/map/yz/xidajie2.js create mode 100644 world/map/yz/ximen.js create mode 100644 world/map/yz/yamen.js create mode 100644 world/map/yz/yaolin.js create mode 100644 world/map/yz/yaopu.js create mode 100644 world/map/yz/ymzhengting.js create mode 100644 world/map/yz/zahuopu.js create mode 100644 world/map/yz/zhengting.js create mode 100644 world/map/yz/zuixianlou.js create mode 100644 world/map/yz/zuixianlou2.js create mode 100644 world/npc/bj/ao/aobai.js create mode 100644 world/npc/bj/ao/chushi.js create mode 100644 world/npc/bj/ao/guanjia.js create mode 100644 world/npc/bj/ao/jiading.js create mode 100644 world/npc/bj/ao/wu.js create mode 100644 world/npc/bj/ao/zhuangyu.js create mode 100644 world/npc/bj/guanwai/asi.js create mode 100644 world/npc/bj/guanwai/chuanfu.js create mode 100644 world/npc/bj/guanwai/diao.js create mode 100644 world/npc/bj/guanwai/hu.js create mode 100644 world/npc/bj/guanwai/hufei.js create mode 100644 world/npc/bj/guanwai/xiong.js create mode 100644 world/npc/bj/guanwai/yanji.js create mode 100644 world/npc/bj/lm/heilong.js create mode 100644 world/npc/bj/lm/xiezi.js create mode 100644 world/npc/bj/lm/yongwei.js create mode 100644 world/npc/bj/shenlong/dizi.js create mode 100644 world/npc/bj/shenlong/dushe.js create mode 100644 world/npc/bj/shenlong/hong.js create mode 100644 world/npc/bj/shenlong/lu.js create mode 100644 world/npc/bj/shenlong/nvdizi.js create mode 100644 world/npc/bj/shenlong/wugen.js create mode 100644 world/npc/bj/shenlong/xu.js create mode 100644 world/npc/bj/shenlong/zhang.js create mode 100644 world/npc/bj/shenlong/zyshe.js create mode 100644 world/npc/bj/tdh/chen.js create mode 100644 world/npc/bj/tdh/dubi.js create mode 100644 world/npc/bj/tdh/guan.js create mode 100644 world/npc/bj/tdh/huoji.js create mode 100644 world/npc/bj/tdh/lama.js create mode 100644 world/npc/bj/tdh/li.js create mode 100644 world/npc/bj/tdh/wu.js create mode 100644 world/npc/bj/tdh/xu.js create mode 100644 world/npc/bj/tdh/xuan.js create mode 100644 world/npc/bj/zhuang/furen.js create mode 100644 world/npc/bj/zhuang/shuanger.js create mode 100644 world/npc/bj/zhuang/tufei.js create mode 100644 world/npc/bj/zhuang/zhang.js create mode 100644 world/npc/emei/jingxin.js create mode 100644 world/npc/emei/miejue.js create mode 100644 world/npc/emei/sumengqing.js create mode 100644 world/npc/emei/zhouzhiruo.js create mode 100644 world/npc/follower/azi.js create mode 100644 world/npc/follower/cheng.js create mode 100644 world/npc/follower/huang.js create mode 100644 world/npc/follower/lang.js create mode 100644 world/npc/follower/qing.js create mode 100644 world/npc/follower/shimei.js create mode 100644 world/npc/follower/shuang.js create mode 100644 world/npc/follower/wang.js create mode 100644 world/npc/follower/wenyi.js create mode 100644 world/npc/follower/xia.js create mode 100644 world/npc/follower/xiaolongnv.js create mode 100644 world/npc/follower/xiaozhao.js create mode 100644 world/npc/follower/zhang.js create mode 100644 world/npc/follower/zhou.js create mode 100644 world/npc/gaibang/hongqigong.js create mode 100644 world/npc/gaibang/jian.js create mode 100644 world/npc/gaibang/lu.js create mode 100644 world/npc/gaibang/zuo.js create mode 100644 world/npc/huashan/fengbuping.js create mode 100644 world/npc/huashan/fengqingyang.js create mode 100644 world/npc/huashan/gaogenming.js create mode 100644 world/npc/huashan/yuebuqun.js create mode 100644 world/npc/new/daoshi.js create mode 100644 world/npc/new/mutouren.js create mode 100644 world/npc/pub/baodi.js create mode 100644 world/npc/pub/bing.js create mode 100644 world/npc/pub/biwu.js create mode 100644 world/npc/pub/bpguanli.js create mode 100644 world/npc/pub/ckguanli.js create mode 100644 world/npc/pub/dadizi.js create mode 100644 world/npc/pub/gaoshou1.js create mode 100644 world/npc/pub/guanjia.js create mode 100644 world/npc/pub/hua.js create mode 100644 world/npc/pub/hubu.js create mode 100644 world/npc/pub/jiaoxi.js create mode 100644 world/npc/pub/menpai.js create mode 100644 world/npc/pub/mpguanli.js create mode 100644 world/npc/pub/muren.js create mode 100644 world/npc/pub/paimai.js create mode 100644 world/npc/pub/qian.js create mode 100644 world/npc/pub/tiejiang.js create mode 100644 world/npc/pub/tongren.js create mode 100644 world/npc/pub/wudao.js create mode 100644 world/npc/pub/wudao_men.js create mode 100644 world/npc/pub/wujiang.js create mode 100644 world/npc/pub/xiaoer.js create mode 100644 world/npc/pub/xiaoer2.js create mode 100644 world/npc/pub/yamen.js create mode 100644 world/npc/pub/yayi.js create mode 100644 world/npc/pub/yb_npc.js create mode 100644 world/npc/pub/yingzi.js create mode 100644 world/npc/shaolin/chengjing.js create mode 100644 world/npc/shaolin/daojue.js create mode 100644 world/npc/shaolin/huihe.js create mode 100644 world/npc/shaolin/qingle.js create mode 100644 world/npc/shaolin/xuannan.js create mode 100644 world/npc/shashou/her.js create mode 100644 world/npc/shashou/lisi.js create mode 100644 world/npc/shashou/shashou.js create mode 100644 world/npc/shashou/wu.js create mode 100644 world/npc/wudang/daotong.js create mode 100644 world/npc/wudang/guxu.js create mode 100644 world/npc/wudang/song.js create mode 100644 world/npc/wudang/zhangsanfeng.js create mode 100644 world/npc/xiangyang/bing.js create mode 100644 world/npc/xiangyang/duihuan.js create mode 100644 world/npc/xiangyang/ge.js create mode 100644 world/npc/xiangyang/guo.js create mode 100644 world/npc/xiangyang/menggu1.js create mode 100644 world/npc/xiangyang/menggu2.js create mode 100644 world/npc/xiangyang/menggu3.js create mode 100644 world/npc/xiangyang/menggu4.js create mode 100644 world/npc/xiangyang/menggu5.js create mode 100644 world/npc/xiangyang/shouwei1.js create mode 100644 world/npc/xiangyang/shouwei2.js create mode 100644 world/npc/xiangyang/shouwei3.js create mode 100644 world/npc/xiangyang/shouwei4.js create mode 100644 world/npc/xiangyang/shouwei5.js create mode 100644 world/npc/xiaoyao/suxinghe.js create mode 100644 world/npc/xiaoyao/xiaoyaozi.js create mode 100644 world/npc/xiaoyao/xuemuhua.js create mode 100644 world/npc/yz/biaotou.js create mode 100644 world/npc/yz/caipan.js create mode 100644 world/npc/yz/cheng.js create mode 100644 world/npc/yz/cuifu/cui.js create mode 100644 world/npc/yz/cuifu/guanjia.js create mode 100644 world/npc/yz/cuifu/jiading.js create mode 100644 world/npc/yz/cuifu/langgou.js create mode 100644 world/npc/yz/cuifu/yahuan.js create mode 100644 world/npc/yz/cuifu/yingying.js create mode 100644 world/npc/yz/hy/jiaotu.js create mode 100644 world/npc/yz/hy/jiaoxi.js create mode 100644 world/npc/yz/hy/tiehu.js create mode 100644 world/npc/yz/hy/yin.js create mode 100644 world/npc/yz/lcy/guigong.js create mode 100644 world/npc/yz/lcy/maoshiba.js create mode 100644 world/npc/yz/lcy/shisong.js create mode 100644 world/npc/yz/lcy/weichunfang.js create mode 100644 world/npc/yz/linpingzhi.js create mode 100644 world/npc/yz/linzhennan.js create mode 100644 world/npc/yz/lm/liumang.js create mode 100644 world/npc/yz/lm/lmtou.js create mode 100644 world/npc/yz/lm/xiaolm.js create mode 100644 world/npc/yz/lm/zhao.js create mode 100644 world/npc/yz/lw/lang.js create mode 100644 world/npc/yz/lw/langwang.js create mode 100644 world/npc/yz/lw/langwang2.js create mode 100644 world/npc/yz/lw/she.js create mode 100644 world/npc/yz/lw/yegou.js create mode 100644 world/npc/yz/ping.js create mode 100644 world/npc/yz/shiqingshan.js create mode 100644 world/npc/yz/tang.js create mode 100644 world/npc/yz/yang.js create mode 100644 world/npc/yz/yuhuan.js create mode 100644 world/npc/yz/zeng.js create mode 100644 world/npc/yz/zhu.js create mode 100644 world/npc/yz/zhubanxian.js create mode 100644 world/obj/book/bc.js create mode 100644 world/obj/book/bk.js create mode 100644 world/obj/book/book.js create mode 100644 world/obj/book/ts.js create mode 100644 world/obj/book/up.js create mode 100644 world/obj/book/wd.js create mode 100644 world/obj/book/wudao.js create mode 100644 world/obj/cash/bian.js create mode 100644 world/obj/cash/box_sm.js create mode 100644 world/obj/cash/ck_add.js create mode 100644 world/obj/cash/fang.js create mode 100644 world/obj/cash/fangqi.js create mode 100644 world/obj/cash/gaiming.js create mode 100644 world/obj/cash/jing.js create mode 100644 world/obj/cash/new_box.js create mode 100644 world/obj/cash/pack_add.js create mode 100644 world/obj/cash/saodang.js create mode 100644 world/obj/cash/sm.js create mode 100644 world/obj/cash/tianshifu.js create mode 100644 world/obj/cash/tool.js create mode 100644 world/obj/cash/tool_box2.js create mode 100644 world/obj/cash/tuoli.js create mode 100644 world/obj/cash/xi.js create mode 100644 world/obj/drug/age.js create mode 100644 world/obj/drug/buff.js create mode 100644 world/obj/drug/dushe.js create mode 100644 world/obj/drug/exp.js create mode 100644 world/obj/drug/hr2.js create mode 100644 world/obj/drug/huirong.js create mode 100644 world/obj/drug/huoyan.js create mode 100644 world/obj/drug/limit_mp.js create mode 100644 world/obj/drug/max_mp.js create mode 100644 world/obj/drug/meirong.js create mode 100644 world/obj/drug/mr2.js create mode 100644 world/obj/drug/pot.js create mode 100644 world/obj/drug/sdrug.js create mode 100644 world/obj/drug/skill2.js create mode 100644 world/obj/drug/xiongdan.js create mode 100644 world/obj/drug/yao.js create mode 100644 world/obj/drug/yulu.js create mode 100644 world/obj/eq/lv0/cloth.js create mode 100644 world/obj/eq/lv0/dao.js create mode 100644 world/obj/eq/lv0/duanyi.js create mode 100644 world/obj/eq/lv0/fei.js create mode 100644 world/obj/eq/lv0/huang.js create mode 100644 world/obj/eq/lv0/jd_cloth.js create mode 100644 world/obj/eq/lv0/jd_shoes.js create mode 100644 world/obj/eq/lv0/jian.js create mode 100644 world/obj/eq/lv0/jin.js create mode 100644 world/obj/eq/lv0/mugun.js create mode 100644 world/obj/eq/lv0/niaowo.js create mode 100644 world/obj/eq/lv0/ring.js create mode 100644 world/obj/eq/lv0/shoes.js create mode 100644 world/obj/eq/lv0/tiegun.js create mode 100644 world/obj/eq/lv0/tiezhang.js create mode 100644 world/obj/eq/lv0/whip.js create mode 100644 world/obj/eq/lv0/zan.js create mode 100644 world/obj/eq/lv1/cui_sz.js create mode 100644 world/obj/eq/lv1/dandao.js create mode 100644 world/obj/eq/lv1/fuchen.js create mode 100644 world/obj/eq/lv1/gold_ring.js create mode 100644 world/obj/eq/lv1/guanfu.js create mode 100644 world/obj/eq/lv1/jinshezhui.js create mode 100644 world/obj/eq/lv1/jundao.js create mode 100644 world/obj/eq/lv1/junfu.js create mode 100644 world/obj/eq/lv1/lm_cloth.js create mode 100644 world/obj/eq/lv1/lm_gun.js create mode 100644 world/obj/eq/lv1/lm_head.js create mode 100644 world/obj/eq/lv1/lm_jian.js create mode 100644 world/obj/eq/lv1/lm_shoes.js create mode 100644 world/obj/eq/lv1/lm_shou.js create mode 100644 world/obj/eq/lv1/pifeng.js create mode 100644 world/obj/eq/lv1/qianjinquan.js create mode 100644 world/obj/eq/lv1/qimeigun.js create mode 100644 world/obj/eq/lv1/qingmu.js create mode 100644 world/obj/eq/lv1/wd_cloth.js create mode 100644 world/obj/eq/lv1/wd_jian.js create mode 100644 world/obj/eq/lv1/wei_neck.js create mode 100644 world/obj/eq/lv1/xk_cloth.js create mode 100644 world/obj/eq/lv1/xk_head.js create mode 100644 world/obj/eq/lv1/xk_shoes.js create mode 100644 world/obj/eq/lv2/anqi.js create mode 100644 world/obj/eq/lv2/ao_bishou.js create mode 100644 world/obj/eq/lv2/ao_jia.js create mode 100644 world/obj/eq/lv2/gun.js create mode 100644 world/obj/eq/lv2/hl_bian.js create mode 100644 world/obj/eq/lv2/hs_qin.js create mode 100644 world/obj/eq/lv2/jiangjunjian.js create mode 100644 world/obj/eq/lv2/js_nang.js create mode 100644 world/obj/eq/lv2/js_pifeng.js create mode 100644 world/obj/eq/lv2/js_ring.js create mode 100644 world/obj/eq/lv2/lm_cloth.js create mode 100644 world/obj/eq/lv2/lm_jian.js create mode 100644 world/obj/eq/lv2/lm_pei.js create mode 100644 world/obj/eq/lv2/lm_pifeng.js create mode 100644 world/obj/eq/lv2/lm_shoes.js create mode 100644 world/obj/eq/lv2/lm_tou.js create mode 100644 world/obj/eq/lv2/sl_cloth.js create mode 100644 world/obj/eq/lv2/sl_ling.js create mode 100644 world/obj/eq/lv2/sl_shoes.js create mode 100644 world/obj/eq/lv2/sl_shou.js create mode 100644 world/obj/eq/lv2/sl_tou.js create mode 100644 world/obj/eq/lv2/sl_yao.js create mode 100644 world/obj/eq/lv2/sl_zhang.js create mode 100644 world/obj/eq/lv2/wd_shou.js create mode 100644 world/obj/eq/lv2/wd_tou.js create mode 100644 world/obj/eq/lv2/yunlongjian.js create mode 100644 world/obj/eq/new/cloth1.js create mode 100644 world/obj/eq/new/cloth2.js create mode 100644 world/obj/food/desk.js create mode 100644 world/obj/food/desk2.js create mode 100644 world/obj/food/drink.js create mode 100644 world/obj/food/food.js create mode 100644 world/obj/food/hua.js create mode 100644 world/obj/food/marry.js create mode 100644 world/obj/money/bp.js create mode 100644 world/obj/money/cash.js create mode 100644 world/obj/money/coin.js create mode 100644 world/obj/money/exp.js create mode 100644 world/obj/money/g100.js create mode 100644 world/obj/money/gold.js create mode 100644 world/obj/money/gongji.js create mode 100644 world/obj/money/hua.js create mode 100644 world/obj/money/p1w.js create mode 100644 world/obj/money/pot.js create mode 100644 world/obj/money/silver.js create mode 100644 world/obj/res/cao.js create mode 100644 world/obj/res/eyupi.js create mode 100644 world/obj/res/huang.js create mode 100644 world/obj/res/huolongpi.js create mode 100644 world/obj/res/langpi.js create mode 100644 world/obj/res/pimao1.js create mode 100644 world/obj/res/pimao2.js create mode 100644 world/obj/res/shexue.js create mode 100644 world/obj/res/yu.js create mode 100644 world/obj/sp/bj/jing.js create mode 100644 world/obj/sp/bj/jiu.js create mode 100644 world/obj/sp/bj/laofangkey.js create mode 100644 world/obj/sp/bj/map.js create mode 100644 world/obj/sp/bj/wu.js create mode 100644 world/obj/sp/bj/yanji.js create mode 100644 world/obj/sp/bj/zhu.js create mode 100644 world/obj/sp/dati.js create mode 100644 world/obj/sp/dizi.js create mode 100644 world/obj/sp/mihan.js create mode 100644 world/obj/sp/new/ksforce.js create mode 100644 world/obj/sp/new/ksunarmed.js create mode 100644 world/obj/sp/new/mutou.js create mode 100644 world/obj/sp/new/qicai.js create mode 100644 world/obj/sp/npc.js create mode 100644 world/obj/sp/tool/chu.js create mode 100644 world/obj/sp/tool/diao.js create mode 100644 world/obj/sp/tool/er.js create mode 100644 world/obj/sp/tool/er2.js create mode 100644 world/obj/sp/tool/exp.js create mode 100644 world/obj/sp/tool/fuqi.js create mode 100644 world/obj/sp/tool/shitu.js create mode 100644 world/obj/sp/tool/sm.js create mode 100644 world/obj/sp/tool/summon.js create mode 100644 world/obj/sp/tool/yao.js create mode 100644 world/obj/sp/tool/zhuisha.js create mode 100644 world/obj/sp/yz/box1.js create mode 100644 world/obj/sp/yz/qiantiao.js create mode 100644 world/obj/sp/yz/xin.js create mode 100644 world/obj/sp/yz/yaoshi.js create mode 100644 world/obj/st/st_blu.js create mode 100644 world/obj/st/st_ds.js create mode 100644 world/obj/st/st_fy.js create mode 100644 world/obj/st/st_gj.js create mode 100644 world/obj/st/st_gre.js create mode 100644 world/obj/st/st_mz.js create mode 100644 world/obj/st/st_red.js create mode 100644 world/obj/st/st_s2.js create mode 100644 world/obj/st/st_sc.js create mode 100644 world/obj/st/st_yel.js create mode 100644 world/obj/st/xuanjing.js create mode 100644 world/obj/st/yuanjing.js create mode 100644 world/skill/base/bite.js create mode 100644 world/skill/base/blade.js create mode 100644 world/skill/base/club.js create mode 100644 world/skill/base/dodge.js create mode 100644 world/skill/base/force.js create mode 100644 world/skill/base/parry.js create mode 100644 world/skill/base/staff.js create mode 100644 world/skill/base/sword.js create mode 100644 world/skill/base/throwing.js create mode 100644 world/skill/base/unarmed.js create mode 100644 world/skill/base/whip.js create mode 100644 world/skill/blade/hujiadaofa.js create mode 100644 world/skill/blade/wuhuduanmendao.js create mode 100644 world/skill/club/baguagun.js create mode 100644 world/skill/club/juemengun.js create mode 100644 world/skill/club/mengguqiangfa.js create mode 100644 world/skill/club/weituogun.js create mode 100644 world/skill/club/zhongpingqiang.js create mode 100644 world/skill/dodge/chanchubufa.js create mode 100644 world/skill/dodge/feiyanzoubi.js create mode 100644 world/skill/dodge/qingfushenfa.js create mode 100644 world/skill/dodge/shenxingbaibian.js create mode 100644 world/skill/dodge/sixiangbu.js create mode 100644 world/skill/dodge/wuduyanluobu.js create mode 100644 world/skill/dodge/yixingbufa.js create mode 100644 world/skill/dodge/yunlongshenfa.js create mode 100644 world/skill/emei/emeixinfa.js create mode 100644 world/skill/emei/huifengjian.js create mode 100644 world/skill/emei/jindingzhang.js create mode 100644 world/skill/emei/jiuyinbaiguzhao.js create mode 100644 world/skill/emei/linjizhuang.js create mode 100644 world/skill/emei/yitianjianfa.js create mode 100644 world/skill/emei/zhutianbu.js create mode 100644 world/skill/force/baiyunxinfa.js create mode 100644 world/skill/force/biboshengong.js create mode 100644 world/skill/force/heilongxinfa.js create mode 100644 world/skill/force/lengyueshengong.js create mode 100644 world/skill/force/longxianggong.js create mode 100644 world/skill/force/mengguxinfa.js create mode 100644 world/skill/force/mizongxinfa.js create mode 100644 world/skill/force/panshishengong.js create mode 100644 world/skill/force/shenlongxinfa.js create mode 100644 world/skill/force/yunlongxinfa.js create mode 100644 world/skill/gaibang/dagoubang.js create mode 100644 world/skill/gaibang/gaibangxinfa.js create mode 100644 world/skill/gaibang/huntianqigong.js create mode 100644 world/skill/gaibang/jiaohuabangfa.js create mode 100644 world/skill/gaibang/xianglongzhang.js create mode 100644 world/skill/gaibang/xiaoyaoyou.js create mode 100644 world/skill/huashan/dugujiujian.js create mode 100644 world/skill/huashan/feiyanhuixiang.js create mode 100644 world/skill/huashan/huashanjianfa.js create mode 100644 world/skill/huashan/huashanquanfa.js create mode 100644 world/skill/huashan/huashanxinfa.js create mode 100644 world/skill/huashan/kuangfengkuaijian.js create mode 100644 world/skill/huashan/poyuquan.js create mode 100644 world/skill/huashan/zixiashengong.js create mode 100644 world/skill/knowage/lianyao.js create mode 100644 world/skill/knowage/literate.js create mode 100644 world/skill/monster/bite2.js create mode 100644 world/skill/monster/dushe.js create mode 100644 world/skill/shaolin/damojian.js create mode 100644 world/skill/shaolin/hunyuanyiqi.js create mode 100644 world/skill/shaolin/ranmudao.js create mode 100644 world/skill/shaolin/shaolinshenfa.js create mode 100644 world/skill/shaolin/yijinjing.js create mode 100644 world/skill/shaolin/yizhichan.js create mode 100644 world/skill/shashou/chuanxinzhang.js create mode 100644 world/skill/shashou/feidao.js create mode 100644 world/skill/shashou/mantianhuayu.js create mode 100644 world/skill/shashou/shashengjue.js create mode 100644 world/skill/shashou/shashoubufa.js create mode 100644 world/skill/shashou/shashouxinfa.js create mode 100644 world/skill/shashou/taxuexunmei.js create mode 100644 world/skill/staff/fumozhang.js create mode 100644 world/skill/staff/shedaoqigong.js create mode 100644 world/skill/staff/wuchangzhang.js create mode 100644 world/skill/sword/shenlongjian.js create mode 100644 world/skill/sword/taishanjianfa.js create mode 100644 world/skill/sword/tangshijianfa.js create mode 100644 world/skill/sword/yunlongjian.js create mode 100644 world/skill/unarmed/baguaquan.js create mode 100644 world/skill/unarmed/changquan.js create mode 100644 world/skill/unarmed/dashouyin.js create mode 100644 world/skill/unarmed/fuhuquan.js create mode 100644 world/skill/unarmed/houquan.js create mode 100644 world/skill/unarmed/huagumianzhang.js create mode 100644 world/skill/unarmed/jingangquan.js create mode 100644 world/skill/unarmed/jinshezhang.js create mode 100644 world/skill/unarmed/liuyunzhang.js create mode 100644 world/skill/unarmed/qianzhuwandushou.js create mode 100644 world/skill/unarmed/qinlong.js create mode 100644 world/skill/unarmed/tianchangzhang.js create mode 100644 world/skill/unarmed/yingzhuagong.js create mode 100644 world/skill/whip/qiufengfuchen.js create mode 100644 world/skill/whip/yunlongbian.js create mode 100644 world/skill/wudang/taijijian.js create mode 100644 world/skill/wudang/taijiquan.js create mode 100644 world/skill/wudang/taijishengong.js create mode 100644 world/skill/wudang/tiyunzong.js create mode 100644 world/skill/wudang/wudangchangquan.js create mode 100644 world/skill/wudang/wudangjianfa.js create mode 100644 world/skill/wudang/wudangxinfa.js create mode 100644 world/skill/xiaoyao/beimingshengong.js create mode 100644 world/skill/xiaoyao/lingboweibu.js create mode 100644 world/skill/xiaoyao/liuyangzhang.js create mode 100644 world/skill/xiaoyao/ruyidao.js create mode 100644 world/skill/xiaoyao/xiaowuxiang.js create mode 100644 world/skill/xiaoyao/xiaoyaoxinfa.js create mode 100644 world/skill/xiaoyao/zhemeishou.js create mode 100644 world/task/boss_task.js create mode 100644 world/task/goods_task.js create mode 100644 world/task/grow_task.js create mode 100644 world/task/msg.js create mode 100644 world/task/sm_task.js create mode 100644 world/task/top_1.js create mode 100644 world/task/wd_task.js create mode 100644 world/task/xy_task.js create mode 100644 world/task/ym_task.js create mode 100644 world/task/ym_task2.js create mode 100644 www/assets/glyphicons-halflings-regular-BKjkU69z.woff create mode 100644 www/assets/glyphicons-halflings-regular-BUJKDMgK.eot create mode 100644 www/assets/glyphicons-halflings-regular-DrwTMapi.ttf create mode 100644 www/assets/index-CD1SkoHj.js create mode 100644 www/assets/index-CyhYzrZw.js create mode 100644 www/assets/index-klnIecVv.css create mode 100644 www/index.html diff --git a/.env b/.env new file mode 100644 index 0000000..0f9873a --- /dev/null +++ b/.env @@ -0,0 +1,13 @@ +# Web 服务器端口 +WEB_PORT=8088 +# 游戏服务器 WebSocket 端口 +WS_PORT=31300 + +# MD5 加密前缀(用于密码加密) +MD5_PREFIX= + +# Session 会话密钥 +SESSION_SECRET= + +# DES 加密向量(16字节,用于数据加解密) +DESIV= diff --git a/api/base.js b/api/base.js new file mode 100644 index 0000000..318690f --- /dev/null +++ b/api/base.js @@ -0,0 +1,145 @@ + + +const crypto = require('crypto'); +const desvi = __CONFIG.DESIV; +const md5add = __CONFIG.MD5; +const SessionKey = 'u'; +const SessionToken = 'p'; + +class Apibase { + constructor(req, res) { + + this.loginUser = null; + this.req = req; + this.res = res; + } + error(code = 500, message) { + return this.res.status(code).json({ error: message }); + } + signIn(id, uname, pwd, level) { + if (!(id > 0)) return null; + let key = this.req.cookies[SessionKey]; + if (!key) { + key = this.sessionKey(); + this.res.cookie(SessionKey, key, { + maxAge: 3600000 * 24 * 180 + }); + } + let cert = this.encryptUser(id, uname, pwd, key, level); + if (!cert) return null; + this.res.cookie(SessionToken, cert, { + maxAge: 3600000 * 24 * 180 + }); + return cert; + } + sessionKey() { + return this.req.session.id; + } + + getUser() { + if (this.loginUser) return this.loginUser; + + let key = this.req.cookies[SessionKey]; + if (!key) { + this.res.cookie(SessionKey, this.sessionKey(), { + maxAge: 3600000 * 24 * 180 + }); + } + let str = this.req.cookies[SessionToken]; + if (!str) return; + this.loginUser = this.deEncryptUser(key, str); + return this.loginUser; + } + deEncryptUser(key, cert) { + let txt = this.deEncrypt(key, cert); + let str = txt.split("%"); + if (str.length !== 5) return null; + let id = parseInt(str[0]); + if (id > 0) + return { + id: id, + name: str[1], + pwd: str[2], + time: parseInt(str[3]), + level: str[4], + }; + return null; + } + deEncrypt(key, str) { + + if (!key || !str) return; + if (key.length > 16) key = key.substr(0, 16); + key = Buffer.from(key, 'utf8'); + let decipher = crypto.createDecipheriv('aes-128-cbc', key, desvi); + //decipher.setAutoPadding(true); + let txt = decipher.update(str, 'base64', 'utf8'); + txt += decipher.final('utf8'); + + return txt; + } + + + + MD5(str) { + let md5 = crypto.createHash('md5'); + let result = md5.update(str + md5add).digest('hex'); + return result.toUpperCase(); + } + encrypt(str, key) { + if (!key || !str) return; + if (key.length > 16) key = key.substr(0, 16); + key = Buffer.from(key, 'utf8'); + let decipher = crypto.createCipheriv('aes-128-cbc', key, desvi); + + // decipher.setAutoPadding(true); + + let txt = decipher.update(str, 'utf8', 'base64'); + + txt += decipher.final('base64'); + return txt; + } + encryptUser(id, uname, pwd, key, level) { + return this.encrypt([id, uname, pwd, + Date.now(), level].join('%'), key); + } + + setSession(key, value) { + this.req.session[key] = value; + } + getSession(key) { + return this.req.session[key]; + } + deleteSession(key) { + delete this.req.session[key]; + } + + + start_sse() { + if (this.res.headersSent) { + throw new Error('已经发送响应头'); + } + this.res.setHeader('Content-Type', 'text/event-stream'); + this.res.setHeader('Cache-Control', 'no-cache'); + this.res.setHeader('Connection', 'keep-alive'); + this.res.flushHeaders(); // 发送响应头 + } + sse(data) { + this.res.write(`data: ${JSON.stringify(data)}\n\n`); // 发送数据 + } + end_sse() { + this.res.end(); + } + guid() { + var str = []; + str.push(parseInt((Date.now() - 1598376101624) / 1000).toString(16)); + let length = 32 - str[0].length; + for (var i = 0; i < length; i++) { + str.push(idstr[parseInt(Math.random() * idstr.length)]); + } + return str.join(''); + } +} + +const idstr = "abcdefghijklmnopqrstuvwxwz0123456789"; + +module.exports = Apibase; diff --git a/api/game.js b/api/game.js new file mode 100644 index 0000000..0c47f31 --- /dev/null +++ b/api/game.js @@ -0,0 +1,47 @@ + + + +const APIBASE = require('./base'); +let SERVERS = null; +const { DB } = __CONFIG; +class GameAPI extends APIBASE { + + async servers(user) { + if (!SERVERS) { + SERVERS = await DB.getServers(); + } + return SERVERS; + } + async reload() { + SERVERS = null; + } + async search_role(paras) { + const { type, value } = paras; + if (!type || !value) return { code: 0, result: "错误参数" }; + if (!ALLOW_TYPES[type]) return { code: 0, result: "错误参数" }; + let cond = ""; + paras = [value] + if (type === "uname") { + cond = "where a.name=?"; + } else if (type === 'name') cond = 'where b.name=? or b.name is null' + else if (type === 'phone') cond = 'where a.phone=?'; + + let result = await DB.query_role(cond, paras); + return { code: 1, result: result }; + } +} + +const ALLOW_TYPES = { + uname: true, + name: true, + phone: true +}; +module.exports = GameAPI; + + + + + + + + diff --git a/api/user.js b/api/user.js new file mode 100644 index 0000000..ce52fb6 --- /dev/null +++ b/api/user.js @@ -0,0 +1,206 @@ + + + +const APIBASE = require('./base'); +const svgCaptcha = require('svg-captcha'); +const { DB } = __CONFIG; +const CODEREG = /^[A-Za-z0-9_]{3,20}$/; +class UserAPI extends APIBASE { + + async login(user) { + let { code, pwd } = user; + + if (!code || !pwd) { + return { code: 0, result: "用户名或密码错误" }; + } + code = code.toLowerCase(); + if (!CODEREG.test(code)) + return { code: 0, result: "用户名格式错误" }; + pwd = this.MD5(pwd); + let result = await DB.getUserBy("name", code); + if (!result) + return { code: 0, result: "用户不存在" }; + if (result.pwd !== pwd) + return { code: 0, result: "用户密码错误" }; + let cert = this.signIn(result.id, result.name, pwd, result.level); + if (cert) + return { code: 1, p: cert, u: this.sessionKey() }; + return { code: 0, result: "登陆失败" }; + } + checkValCode(code) { + if (!code) return false; + let num = this.getSession("valno"); + if (!num) return false; + + return code.toLowerCase() == num.toLowerCase(); + } + async regist(user) { + if (!user.name || !user.pwd) { + return { code: 0, result: "注册失败,缺少数据" }; + } + if (user.name.length > 15 || user.name.length < 3) { + return { code: 0, result: "注册失败,缺少数据" }; + } + if (user.pwd.length < 5) { + return { code: 0, result: "注册失败,缺少数据" }; + } + if (!this.checkValCode(user.valno)) { + return { code: 0, result: "验证码输入错误" }; + } + user.pwd = this.MD5(user.pwd); + user.name = user.name.toLowerCase(); + user.phone = user.phone ?? null; + user.link_user = user.guider > 0 ? user.guider : 0; + if (await DB.getUserBy("name", user.name)) { + return { code: 0, result: "注册失败,账号已经有人使用" }; + } + if (!await DB.createUser(user)) { + return { code: 0, result: "注册失败" }; + } + this.deleteSession("valno"); + this.signIn(user.id, user.name, user.pwd); + return { code: 1 }; + } + async validimage() { + const captcha = svgCaptcha.create({ + size: 4, // 验证码长度 + noise: 2, // 干扰线条数量 + color: true, // 文字是否彩色 + background: '#337AB7', // 背景色 + }); + + this.setSession('valno', captcha.text) + return Buffer.from(captcha.data).toString('base64'); + } + async getphone() { + const user = this.getUser(); + if (!user) + return { code: 0, result: "未登录" }; + let result = await DB.getUserBy("id", user.id); + if (!result) return { code: 0, result: "不存在的用户" }; + return { code: 1, result: result.phone ? result.phone.substring(0, 3) + "********" : "" }; + } + async bindphone(data) { + const user = this.getUser(); + if (!user) + return { code: 0, result: "未登录" }; + let { code, no, pwd } = data; + let result = await DB.getUserBy("id", user.id); + if (!result) return { code: 0, result: "不存在的用户" }; + if (result.phone) { + if (!code || code.length !== 4) + return { code: 0, result: "手机尾号格式错误" }; + if (!result.phone.endsWith(code)) + return { code: 0, result: "错误的手机尾号" }; + user.phone = null; + } else { + if (!no || !/^1\d{10}$/.test(no)) + return { code: 0, result: "手机号格式错误" }; + user.phone = no; + } + pwd = this.MD5(pwd); + if (pwd !== user.pwd) + return { code: 0, result: "密码错误" }; + if (await DB.updateUser(user)) + return { code: 1 }; + return { code: 0 }; + } + + async resetpwd(paras) { + let { + name, phone, vcode, pwd + } = paras; + if (!name || !phone || !pwd) + return { code: 0 }; + const result = await DB.getUserBy("name", name); + if (!result) + return { code: 0, result: "账号不存在" }; + if (!result.phone || result.phone !== phone) { + return { code: 0, result: "手机号验证失败" }; + } + pwd = this.MD5(pwd); + result.pwd = pwd; + if (!await DB.updateUser(result)) { + return { code: 0, result: "密码重置失败。" }; + } + return { code: 1 }; + } + async changepassword(data) { + let { oldpwd, pwd, no } = data; + if (!oldpwd || !pwd) + return { code: 0 }; + oldpwd = this.MD5(oldpwd); + pwd = this.MD5(pwd); + const user = this.getUser(); + if (!user) + return { code: 0, result: "未登录" }; + const result = await DB.getUserBy("id", user.id); + if (!result) + return { code: 0, result: "账号不存在" }; + + if (result.pwd !== oldpwd) { + return { code: 0, result: "原始密码输入错误。" }; + } + if (result.phone) { + if (!no || no.length !== 4) + return { code: 0, result: "手机尾号格式错误" }; + if (!result.phone.endsWith(no)) + return { code: 0, result: "错误的手机尾号" }; + } + user.pwd = pwd; + result.pwd = pwd; + if (!await DB.updateUser(result)) { + return { code: 0, result: "密码修改失败。" }; + } + let cert = this.signIn(user.id, user.name, pwd, user.level); + if (cert) + return { code: 1, p: cert, u: this.sessionKey() }; + return { code: 0, result: "登陆凭证更新失败" }; + + + } + + async GetPhone2(paras) { + let { uid, cert } = paras; debugger + if (!uid || cert !== 'transrole_service') return; + let user = await DB.getUserByID(uid); + if (!user) return ""; + return user.phone; + } +} + +module.exports = UserAPI; + + + + + + + + + + + + +// this.inherits('api/base'); + +// this.define = { +// Login: { method: "Post", paras: ["code", "pwd"] } +// } +// const DB = this.import('/lib/mysql'); +// let servers = null; + +// this.Login = async function (code, pwd) { + + +// } + +// this.GetUser = async function (cond, pars) { + +// let sql = "select ID,Name,EMAIL,PHone,State,Developer,IsFirst from users"; +// if (cond) { +// sql += " where " + cond; +// } +// return await DB.query(sql, pars); + +// } \ No newline at end of file diff --git a/config.js b/config.js new file mode 100644 index 0000000..4fd54af --- /dev/null +++ b/config.js @@ -0,0 +1,29 @@ + + + +module.exports = { + DB: require('./data/sql'), + init: async function () { + if (!(this.WEB_PORT > 1000)) throw new Error('缺少环境配置WEB_PORT'); + if (!(this.def_server.port > 1000)) throw new Error('缺少环境配置WS_PORT'); + if (!this.MD5) throw new Error('缺少环境配置md5'); + if (!this.DESIV) throw new Error('缺少环境配置DESIV'); + if (!this.SESSION_SECRET) throw new Error('缺少环境配置SESSION_SECRET'); + await this.DB.connect('database.db'); + }, + WEB_PORT: parseInt(process.env.WEB_PORT), + CONNECT_LEVEL: 0, + MD5: process.env.MD5_PREFIX, + SESSION_SECRET: process.env.SESSION_SECRET, + HEARTBEAT: 5000, + + DESIV: process.env.DESIV ? Buffer.from(process.env.DESIV, 'utf8') : null, + + def_server: { + ip: "127.0.0.1", + port: parseInt(process.env.WS_PORT), + id: 100, + name: "本地测试", + istest: true + } +}; \ No newline at end of file diff --git a/data/db.js b/data/db.js new file mode 100644 index 0000000..a7ce9e0 --- /dev/null +++ b/data/db.js @@ -0,0 +1,200 @@ +const Database = require("better-sqlite3"); +const path = require("path"); +const fs = require("fs").promises; +const crypto = require("crypto"); + +const stmtCaches = new Map(); + +class SqliteDatabase { + db_path = null; + constructor() { + this.db = null; + } + + // 获取预编译语句(带缓存) + getStmt(sql) { + let stmt = stmtCaches.get(sql); + if (!stmt) { + stmt = this.db.prepare(sql); + stmtCaches.set(sql, stmt); + } + return stmt; + } + + // 初始化数据库 + async init(db_name) { + try { + this.db_path = path.join(__dirname, db_name); + const fileExists = await this.checkDbFileExists(); + + if (!fileExists) { + console.log("数据库文件不存在,正在创建..."); + this.db = new Database(this.db_path); + await this.executeDefaultScripts(); + console.log("数据库初始化完成"); + } else { + console.log("数据库文件已存在,正在连接..."); + this.db = new Database(this.db_path); + await this.executeAlterScripts(); + console.log("数据库连接成功"); + } + } catch (error) { + console.error("数据库初始化失败:", error); + throw error; + } + } + + // 检查数据库文件是否存在 + async checkDbFileExists() { + try { + await fs.access(this.db_path); + return true; + } catch (error) { + return false; + } + } + + // 执行 ALTER 脚本(数据库已存在时) + async executeAlterScripts() { + for (let sql of ALTER_SCRIPTS) { + try { + await this.query(sql); + } catch (error) { + console.error(sql, "查询失败", error); + } + } + } + + // 执行默认建表脚本(数据库新建时) + async executeDefaultScripts() { + for (let sql of DEFAULT_TABLE_SCRIPTS) { + try { + await this.query(sql); + } catch (error) { + console.error(sql, "查询失败", error); + } + } + } + + // 执行 INSERT/UPDATE/DELETE 等操作 + query(sql, params = []) { + return new Promise((resolve, reject) => { + try { + const stmt = this.getStmt(sql); + const info = stmt.run(...params); + resolve({ lastID: info.lastInsertRowid, changes: info.changes }); + } catch (err) { + console.error("SQL执行错误:", err); + reject(err); + } + }); + } + + // 查询单行数据 + get(sql, params = []) { + return new Promise((resolve, reject) => { + try { + const stmt = this.getStmt(sql); + const row = stmt.get(...params); + resolve(row); + } catch (err) { + console.error("SQL查询错误:", err); + reject(err); + } + }); + } + + // 查询多行数据 + all(sql, params = []) { + return new Promise((resolve, reject) => { + try { + const stmt = this.getStmt(sql); + const rows = stmt.all(...params); + resolve(rows); + } catch (err) { + console.error("SQL查询错误:", err); + reject(err); + } + }); + } + + // 关闭数据库连接 + close() { + return new Promise((resolve, reject) => { + try { + if (this.db) { + this.db.close(); + this.db = null; + } + resolve(); + } catch (err) { + console.error("关闭数据库连接失败:", err); + reject(err); + } + }); + } +} + +// 导出单例 +module.exports = new SqliteDatabase(); + +// ---------- 建表及初始脚本 ---------- +const DEFAULT_TABLE_SCRIPTS = [ + `CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name VARCHAR(60) NOT NULL, + pwd VARCHAR(60) NOT NULL, + phone VARCHAR(20), + state INTEGER DEFAULT 1, + level INTEGER DEFAULT 0, + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE (name) + )`, + `CREATE TABLE IF NOT EXISTS servers ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name VARCHAR(60) NOT NULL, + ip VARCHAR(60) NOT NULL, + port VARCHAR(60) NOT NULL, + state INTEGER DEFAULT 1, + isdef INTEGER DEFAULT 0, + istest INTEGER DEFAULT 0, + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + start_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP + )`, + `CREATE TABLE IF NOT EXISTS players ( + id VARCHAR(40) NOT NULL, + name VARCHAR(30) NOT NULL, + userid INTEGER NOT NULL, + sid INTEGER NOT NULL, + level INTEGER DEFAULT 0, + title VARCHAR(30) NOT NULL, + data TEXT, + create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP + )`, + `CREATE TABLE IF NOT EXISTS players_bak ( + id VARCHAR(40) NOT NULL, + name VARCHAR(30) NOT NULL, + userid INTEGER NOT NULL, + sid INTEGER NOT NULL, + level INTEGER DEFAULT 0, + title VARCHAR(30) NOT NULL, + data TEXT, + create_time TIMESTAMP, + update_time TIMESTAMP + )`, + `CREATE UNIQUE INDEX IF NOT EXISTS idx_users_name ON users (name)`, + `CREATE UNIQUE INDEX IF NOT EXISTS idx_players_id ON players (id)`, + `CREATE INDEX IF NOT EXISTS idx_players_userid ON players (userid)`, + `CREATE UNIQUE INDEX IF NOT EXISTS idx_players_name ON players (name)`, + `CREATE UNIQUE INDEX IF NOT EXISTS idx_players_bak_id ON players_bak (id)`, + `INSERT OR IGNORE INTO users(id,name,pwd,level) VALUES(1,'administrator','${MD5("123456")}',6)`, +]; + +function MD5(str) { + let md5 = crypto.createHash("md5"); + let result = md5.update(str + process.env.MD5_PREFIX).digest("hex"); + return result.toUpperCase(); +} + +const ALTER_SCRIPTS = []; diff --git a/data/def/data.js b/data/def/data.js new file mode 100644 index 0000000..6f31cf5 --- /dev/null +++ b/data/def/data.js @@ -0,0 +1 @@ +{ } \ No newline at end of file diff --git a/data/sql.js b/data/sql.js new file mode 100644 index 0000000..9fa5121 --- /dev/null +++ b/data/sql.js @@ -0,0 +1,132 @@ +const db = require('./db'); + + +module.exports = { + + connect: async function (path) { + await db.init(path); + }, + close: function () { + return db.close(); + }, + getUserBy: function (type, value) { + return this.getUser(type + "=?", [value]); + }, + getUserByID: function (id) { + return this.getUser("id=?", [id]); + }, + getUser: function (cond, paras) { + let sql = "select id,name,pwd,phone,state,level from users"; + + if (cond) { + sql += " where " + cond; + } + return db.get(sql, paras); + }, + getUsers: function (cond, paras) { + let sql = "select id,name,pwd,phone,state,create_time from users"; + + if (cond) { + sql += " where " + cond; + } + return db.all(sql, paras); + }, + checkUserName: function (name) { + let sql = "select name,phone from users where name=?";// or phone=? + return db.get(sql, [name]); + }, + updateUser: async function (user) { + let sql = "update users set name=?,phone=?,pwd=? where id=?"; + let result = await db.query(sql, [user.name, user.phone, user.pwd, user.id]); + return result.changes === 1; + }, + createUser: async function (user) { + + let result = await db.query("insert into users(name,pwd,phone) values(?,?,?)", + [user.name, user.pwd, user.phone]); + if (!(result.lastID > 0)) return false; + user.id = result.lastID; + return true; + }, + + + + getServers: function () { + let sql = "select id,name, ip,port,istest,isdef,create_time,start_time from servers"; + + return db.all(sql); + }, + getServer: function (id) { + let sql = "select id,name, ip,port,istest,isdef from servers where id=?"; + + return db.get(sql, [id]); + }, + saveServer: async function (data) { + let sql = "update servers set name=?, ip=?,port=?,istest=?,isdef=? where id=?"; + + let result = await db.query(sql, [data.name, data.ip, data.port, data.istest, data.isdef, data.id]); + + return result.changes === 1; + }, + addServer: async function (data) { + let sql = "insert into servers(name,ip,port,istest,isdef) values(?,?,?,?,?)"; + let result = await db.query(sql, + [data.name, data.ip, data.port, data.istest, data.isdef]); + + return result.lastID; + + }, + deleteServer: function (id) { + return db.query("delete from servers where id =?", [id]); + }, + + getRoles: function (uid, server) { + return db.all("select a.id,a.name,a.title,a.level from players a where a.userid=? and a.sid=?", + [uid, server]); + + }, + addRole: function (role) { + + return db.query("insert into players(userid,id,name,title,level,sid,data) values(?,?,?,?,?,?,?)", + [role.userid, role.id, role.name, role.title, role.level, role.server, role.data]); + + }, + deleteRole: async function (userid, roleid) { + + let sql = "insert into players_bak(id,name,userid,title,level,sid,data,create_time,update_time) select id,name,userid,title,level,sid,data,create_time,update_time from players where id=? and userid=?"; + let result = await db.query(sql, [roleid, userid]); + if (result.changes != 1) + return false; + sql = "delete from players where id=? and userid=?"; + result = await db.query(sql, [roleid, userid]); + if (result.changes != 1) + return false; + return true; + + }, + saveRole: function (role) { + return db.query("update players set name=?,title=?,level=?,data=? where userid=? and id=?", + [role.name, role.title, role.level, role.data, role.userid, role.id]); + }, + exitsRoleName: function (name) { + let sql = "select name from players where name=?";// or phone=? + return db.get(sql, [name]); + }, + + getData: function (id) { + return db.get("select a.id,a.name,a.title,a.level,a.data,b.pwd,b.level user_level from players a left join users b on a.userid=b.id where a.userid=?", + [id]); + }, + updateRoleName: function (id, name) { + + WORLD_DATA.query_db("update players set name=? where id=? ", + [name, id]); + + }, + updateUserid: function (id, fromuserid, touserid) { + WORLD_DATA.query_db("update player set userid=? where id=? and userid=?", + [touserid, id, fromuserid]); + } + +}; + diff --git a/main.js b/main.js new file mode 100644 index 0000000..aff8afd --- /dev/null +++ b/main.js @@ -0,0 +1,58 @@ +"use strict"; + +globalThis['__PATH'] = { + BASE: "./os/", + WORLD: "./world/", + COMMAND: "./world/cmd/", + SKILL: "./world/skill/", + MAP: "./world/map/", + NPC: "./world/npc/", + OBJ: "./world/obj/", + TASK: "./world/task/", + AREA: "./world/area/", + FAMILY: "./world/family/", + EXTENDS: "./world/extends/", + DATA: "./data/", + DEF_DATA: "./data/def/" +}; + + +require('dotenv').config(); + + +const fs = require("fs"); +function readdir(path) { + var files = fs.readdirSync(path); + for (var i = 0; i < files.length; i++) { + var sub_path = path + files[i]; + var stat = fs.statSync(sub_path); + if (stat.isDirectory()) { + readdir(sub_path + "/"); + } else { + require(sub_path); + } + } +} + +globalThis['__CONFIG'] = require('./config'); +async function require_os() { + + const path = require('path'); + for (var item in __PATH) { + __PATH[item] = path.join(__dirname, __PATH[item]); + } + readdir(__PATH.BASE); + await __CONFIG.init(); +} +require_os().then(() => { + WORLD.startup(process.argv[2]); +}); + + +process.on('uncaughtException', (error) => { + console.error('未捕获的异常:', error); + +}); +process.on('unhandledRejection', (reason, promise) => { + console.error('未处理的Promise拒绝:', reason); +}); diff --git a/os/base.js b/os/base.js new file mode 100644 index 0000000..ae610ad --- /dev/null +++ b/os/base.js @@ -0,0 +1,179 @@ +/* + +定义当对象从文件生成时的基类, +当文件内部调用this.inherit(父类名)后,将真正继承父类的原型和实例属性。 +但是文件内部不能修改this.prototype,修改将会作用到父类上面。 +可以用this.XXX扩展属性和方法 +*/ + +BASE = function () { + +} + +BASE.prototype.set = function (pars) { + if (!pars) return; + for (var item in pars) { + this[item] = pars[item]; + } +} +/* +该方法使用直接赋值方式继承父对象的所有原型方法, +如果子对象对原型修改,将会改变父对象的原型。 +所以该方法只能获取父对象的原型不能修改它, + +实际上是作为new的另外一种方式,通过apply获取实例属性,通过__proto__获取父类原型 + +*/ +BASE.prototype.inherits = function (ctor) { + this.__proto__ = ctor.prototype; + ctor.apply(this); +} +/* +create方法由继承自base类的类自己实现,当对象被从文件创建时候调用 +参数fname=该对象的文件的相对路径,ctor=构造方法 +*/ +BASE.prototype.create = function (fname, ctor) { +} +BASE.prototype.add_event = function (fname, func, time) { + ///在time秒内用新的func替换旧的fname方法 + if (!this[fname]) + this[fname] = this.fire_event.bind(this, fname); + if (!this._events) this._events = {}; + if (!this._events[fname]) this._events[fname] = []; + this._events[fname].push({ + func: func, + time: time ? (Date.now() + time) : Number.MAX_SAFE_INTEGER + }); + //var old_func = this[fname]; + //this[fname] = func; + //if (time) this.call_out(() => this[fname] = old_func, time); + //return old_func; +} +BASE.prototype.remove_event = function (name, func) { + if (!this._events) return; + var evts = this._events[name]; + if (!evts) return; + for (var i = 0; i < evts.length; i++) { + if (evts[i].func === func) { + evts.splice(i, 1); + i--; + } + } + + if (!evts.length) { + this._events[name] = null; + this[name] = null; + } +} +BASE.prototype.fire_event = function (name) { + if (!this._events) return; + var evts = this._events[name]; + if (!evts) return; + var dt = Date.now(); + for (var i = 0; i < evts.length; i++) { + if (evts[i].time > dt) { + if (evts[i].func.call(this) == false) return false; + } else { + evts.splice(i, 1); + i--; + } + } + if (!evts.length) { + this._events[name] = null; + this[name] = null; + } +} +/* +生成对象标识,前8位是毫秒级时间戳的36进制形式,后4位随机码, +最起码保证每毫秒生成的标识不会重复 +*/ +var key = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; +BASE.prototype.create_uid = function () { + var str = []; + str.push(Date.now().toString(36)); + var length = key.length; + for (var i = 0; i < 4; i++) { + str.push(key[Math.floor(Math.random() * length)]); + } + return str.join(""); +} +BASE.prototype.random = function (num) { + return Math.floor(Math.random() * num); +} +BASE.prototype.call_out = function (func, time, arg1, arg2) { + return setTimeout(func.bind(this, arg1, arg2), time); +} +BASE.prototype.call_interval = function (func, time, count, end_func) { + count--; + var index = 0; + if (func(index++) === false || count === 0) { + return end_func && end_func(); + } + var handler = 0; + handler = setInterval(function () { + + count--; + if (func(index++) === false || count === 0) { + clearInterval(handler); + end_func && end_func(); + } + }, time); + return handler; +} + + +const vm = require('vm'); +const fs = require("fs"); +//根据文件路径new一个对象 +BASE.ITEMS = {}; +BASE.CREATE = function (path, fname) { + + var ary = BASE.PATH_REG.exec(fname); + if (!ary) { + return console.error("path %s is incorrect:", path + fname); + } + fname = ary[1]; + var paras = ary[2]; + var fkey = path + fname; + var func = BASE.ITEMS[fkey]; + if (func) { + return BASE.NEW(fname, func, paras); + } + const filepath = fkey + ".js"; + try { + const script = fs.readFileSync(filepath); + func = vm.compileFunction(script.toString(), [], + { filename: filepath }); + + BASE.ITEMS[fkey] = func; + return BASE.NEW(fname, func, paras); + } catch (e) { + console.error("create %s%s error:", filepath, e, e.stack); + } +} +BASE.CLONE = function (fname) { +} +BASE.PATH_REG = /^(\w+(?:\/\w+)*)(#\w+)?$/; +BASE.NEW = function (fname, func, par) { + var obj = new BASE(); + func.apply(obj); + obj.path = fname; + obj.create(fname, par); + return obj; +} + +BASE.UPDATE = function (path, fname) { + var ary = BASE.PATH_REG.exec(fname); + if (!ary) { + throw "path " + fname + " is incorrect:"; + } + fname = ary[1]; + var fkey = path + fname; + var data = fs.readFileSync(fkey + ".js"); + var func = new Function(data); + BASE.ITEMS[fkey] = func; + var obj = new BASE(); + func.apply(obj); + obj.path = fname; + obj.update && obj.update(fname, ary[2]); +} diff --git a/os/char/chara_comm.js b/os/char/chara_comm.js new file mode 100644 index 0000000..99737a4 --- /dev/null +++ b/os/char/chara_comm.js @@ -0,0 +1,234 @@ + +require("./character"); + +var level_descs = ["普通百姓", "武士", "武师", "宗师", "武圣", "武帝", "武神"]; +var level_color = ["", "wht", "hig", "hiy", "hiz", "hio", "ord"]; +CHARACTER.prototype.get_level_desc = function () { + if (!this.level) return level_descs[this.level]; + var cc = level_color[this.level]; + return "<" + cc + ">" + level_descs[this.level] + ""; +} +CHARACTER.prototype.get_level_color = function () { + return level_color[this.level]; +} +//发送给当前对象的消息 +CHARACTER.prototype.long_name = function () { + + if (this.title) return this.title + " " + this.name; + return this.name; + +} +CHARACTER.prototype.query_title = function () { + return this.title; +} +CHARACTER.prototype.query_age = function () { + return this.age; +} +CHARACTER.prototype.call = function (isbad) { + return this.family.call(this, isbad); +} +CHARACTER.prototype.callme = function (isbad) { + return this.family.call_me(this); +} +CHARACTER.prototype.fam_call = function (target) { + let age1 = target.query_age(); + let age2 = this.query_age(); + if (age1 < age2) { + return this.gender === 1 ? "师兄" : "师姐"; + } + return this.gender === 1 ? "师弟" : "师妹"; +} +CHARACTER.prototype.call3 = function () { + return this.gender == 1 ? "他" : "她"; +} +CHARACTER.prototype.is_hidden = function () { + return this.hp <= 0 || this.query_temp('hidden'); +} +CHARACTER.prototype.is_team = function (p) { + if (!p) return false; + if (p.team) + return this.team == p.team; + return this.family == p.family; +} +CHARACTER.prototype.send_team = function (msg, nome) { + if (!this.team) return this.send(msg); + for (var i = 0; i < this.team.length; i++) { + if (nome && this.team[i] == this) continue; + this.team[i].send(msg); + } +} +CHARACTER.prototype.query_teamid = function () { + if (this.follow_target) return this.follow_target.query_teamid(); + return null; +} +CHARACTER.prototype.query_status = function () { + var ary = ["{type:\"status\",hp:"]; + ary.push(this.hp); + ary.push(",max_hp:"); + ary.push(this.max_hp); + ary.push(",mp:"); + ary.push(this.mp); + ary.push(",max_mp:"); + ary.push(this.max_mp); + ary.push(",name:\""); + ary.push(this.name); + ary.push("\",id:\""); + ary.push(this.id); + ary.push("\"}"); + return ary.join(""); +} + +CHARACTER.prototype.query_commands = function () { + +} +CHARACTER.prototype.query_desc = function (me, eqcmd) { + var str = []; + str.push(this.long_name()); + str.push("\n"); + var call3 = this == me ? "你" : this.call3(); + str.push(call3, "看起来约", get_agestr(this.query_age()), "岁。\n"); + str.push(call3, "长得", get_perdesc(this), "。\n"); + str.push(call3, get_skill_desc(this.query_skill(this.attack_skill.id)), "。\n"); + str.push(call3, get_status(this), "\n"); + this.format_equipments(call3, str, eqcmd); + return str.join(""); +} + +CHARACTER.prototype.format_equipments = function (call3, str, eqcmd) { + if (this.query_setting("hide_equip")) { + return str.push("看样子", call3, "不想让别人看自己的装备。"); + } else if (this.equipment && this.equipment.length) { + var eqstr = []; + for (var i = 0; i < this.equipment.length; i++) { + var item = this.equipment[i]; + if (!item) continue; + eqstr.push("◆", item.color_name, "\n"); + } + if (eqstr.length) { + return str.push(call3, "装备着:\n", eqstr.join("")); + } + } + str.push(call3, "光着身子,什么都没穿。\n"); +} + +function get_perdesc(obj) { + var ary = obj.gender === 1 ? boy_pers : girl_pers; + var per = obj.per + obj.query_prop("per"); + var index = parseInt(per / 2); + if (index < 0) index = 0; + if (index >= ary.length) index = ary.length - 1; + return ary[index]; +} +function get_agestr(age) { + var index = parseInt((age || 10) / 10); + if (index >= age_strs.length) index = age_strs.length - 1; + return age_strs[index]; +} +function get_skill_desc(level) { + if (!level) return "看上去似乎不会任何武功。"; + + if (level < 1000) + return "的武功看上去似乎" + skill_levels[parseInt(level / 50)]; + var v = parseInt((level - 1000) / 500); + if (v > 6) v = 6; + return "的武功看上去似乎" + skill_levels[v + 20]; +} +function get_status(obj) { + var p = parseInt(obj.hp * 10 / obj.max_hp); + if (p < 0) p = 0; + if (p >= Look_status.length) p = Look_status.length - 1; + return Look_status[p]; +} + +var boy_pers = [ + "眉歪眼斜,瘌头癣脚,不象人样", + "呲牙咧嘴,黑如锅底,奇丑无比", + "面如桔皮,头肿如猪,让人不想再看第二眼", + "贼眉鼠眼,身高三尺,宛若猴状", + "肥头大耳,腹圆如鼓,手脚短粗,令人发笑", + "面颊凹陷,瘦骨伶仃,可怜可叹", + "傻头傻脑,痴痴憨憨,看来倒也老实", + "相貌平平,不会给人留下什么印象", + "膀大腰圆,满脸横肉,恶形恶相", + "腰圆背厚,面阔口方,骨格不凡", + "眉目清秀,端正大方,一表人才", + "双眼光华莹润,透出摄人心魄的光芒", + "举动如行云游水,独蕴风情,吸引所有异性目光", + "双目如星,眉梢传情,所见者无不为之心动", + "粉面朱唇,身姿俊俏,举止风流无限", + "丰神如玉,目似朗星,令人过目难忘", + "面如美玉,粉妆玉琢,俊美不凡", + "飘逸出尘,潇洒绝伦", + "丰神俊朗,长身玉立,宛如玉树临风", + "神清气爽,骨格清奇,宛若仙人", + "一派神人气度,仙风道骨,举止出尘" +]; +var girl_pers = [ + "丑如无盐,状如夜叉", + "歪鼻斜眼,脸色灰败,直如鬼怪一般", + "八字眉,三角眼,鸡皮黄发,让人一见就想吐", + "眼小如豆,眉毛稀疏,手如猴爪,不成人样", + "一嘴大暴牙,让人一看就没好感", + "满脸疙瘩,皮色粗黑,丑陋不堪", + "干黄枯瘦,脸色腊黄,毫无女人味", + "身材瘦小,肌肤无光,两眼无神", + "虽不标致,倒也白净,有些动人之处", + "肌肤微丰,雅淡温宛,清新可人", + "鲜艳妍媚,肌肤莹透,引人遐思", + "娇小玲珑,宛如飞燕再世,楚楚动人", + "腮凝新荔,肌肤胜雪,目若秋水", + "粉嫩白至,如芍药笼烟,雾里看花", + "丰胸细腰,妖娆多姿,让人一看就心跳不已", + "娇若春花,媚如秋月,真的能沉鱼落雁", + "眉目如画,肌肤胜雪,真可谓闭月羞花", + "气质美如兰,才华馥比山,令人见之忘俗", + "灿若明霞,宝润如玉,恍如神妃仙子", + "美若天仙,不沾一丝烟尘", + "宛如玉雕冰塑,似梦似幻,已不再是凡间人物" +]; + +var Look_status = [ + "受伤过重,已经有如风中残烛,随时都可能断气。", + "受伤过重,已经奄奄一息,命在旦夕了。", + "伤重之下已经难以支撑,眼看就要倒在地上。", + "受了相当重的伤,只怕会有生命危险。", + "已经伤痕累累,正在勉力支撑著不倒下去。", + "气息粗重,动作开始散乱,看来所受的伤著实不轻。", + "受伤不轻,看起来状况并不太好。", + "受了几处伤,不过似乎并不碍事。", + "看起来可能受了点轻伤。", + "似乎受了点轻伤,不过光从外表看不大出来。", + "看起来气血充盈,并没有受伤。" +]; + +var age_strs = ["几", "十多", "二十多", "三十多", "四十多", "五十多", "六十多", "七十多", "八十多", "九十多" + , "一百多"]; +var skill_levels = [ + "初学乍练", + "不知所以", + "粗通皮毛", + "渐有所悟", + "半生不熟", + "马马虎虎", + "平淡无奇", + "触类旁通", + "心领神会", + "挥洒自如", + "驾轻就熟", + "出类拔萃", + "初入佳境", + "神乎其技", + "威不可当", + "豁然贯通", + "超群绝伦", + "登峰造极", + "登堂入室", + "一代宗师", + "超凡入圣", + "出神入化", + "独步天下", + "空前绝后", + "旷古绝伦", + "深不可测", + "返璞归真"]; \ No newline at end of file diff --git a/os/char/chara_equip.js b/os/char/chara_equip.js new file mode 100644 index 0000000..4c3caf6 --- /dev/null +++ b/os/char/chara_equip.js @@ -0,0 +1,175 @@ + +require("./character.js"); +CHARACTER.prototype.set_objects = function () { + if (!arguments.length) return; + if (!this.items) this.items = []; + for (var i = 0; i < arguments.length; i++) { + var item = arguments[i]; + var obj = OBJ.CREATE(item[0], item[1]); + if (!obj) continue; + if (item[2] && obj.is_equipment) { + if (!this.equipment) this.equipment = [] + this.equipment[obj.eq_type] = obj; + } else { + this.items.push(obj); + } + } + +} + +CHARACTER.prototype.unequip = function (obj, notsend, recover_time = 0) { + if (!obj || !obj.is_equipment || !this.equipment) return; + if (obj.uneq(this, notsend) == false) { + return false; + } + if (obj != this.equipment[obj.eq_type]) return; + if (!this.items) this.items = []; + this.items.push(obj); + this.equipment[obj.eq_type] = null; + if (obj.eq_type == EQUIP_TYPE.WEAPON) { + this.remove_status('weapon', true); + if (obj.is_shortcut) { + this.send("{type:'addAction',id:'" + obj.id + "',name:'" + obj.name + "'}"); + } + } + + if (obj.eq_type === EQUIP_TYPE.WEAPON) + this.weapon_changed(false); + this.recount(); + if (recover_time > 0 && this.is_player) { + this.set_temp('eq_wea', obj.id, 60000); + } +} + + + +CHARACTER.prototype.equip = function (obj) { + if (!obj || !obj.is_equipment) return; + if (!this.equipment) this.equipment = [] + var equiped = this.equipment[obj.eq_type]; + if (equiped == obj) { + return; + } + if (equiped) { + equiped.uneq(this); + this.equipment[equiped.eq_type] = null; + this.items.push(equiped); + if (equiped.eq_type == EQUIP_TYPE.WEAPON) { + this.remove_status('weapon', true); + } + if (equiped.on_use) { + equiped.notify_action(this, false); + } + if (equiped.is_shortcut) { + this.send("{type:'addAction',id:'" + equiped.id + "',name:'" + equiped.name + "'}"); + } + } + if (obj.eq(this) == false) { + if (equiped) { + if (obj.eq_type === EQUIP_TYPE.WEAPON) + this.weapon_changed(false); + this.recount(); + } + return false; + } + this.items.remove(obj); + this.equipment[obj.eq_type] = obj; + if (obj.eq_type === EQUIP_TYPE.WEAPON) + this.weapon_changed(true); + this.recount(); + if (obj.is_shortcut) { + this.send("{type:'removeAction',id:'" + obj.id + "'}"); + } + if (obj.eq_type == EQUIP_TYPE.WEAPON) { + if (this.fight_type) { + this.release_time = 3000 + Date.now(); + this.send('{type:"dispfm",rtime:3000}'); + } + if (this.query_temp('jxtm')) { + this.remove_status('force'); + } + } +} +const WEAPON_TYPES = { + "sword": true, + "blade": true, + "staff": true, + "club": true, + "whip": true +} +CHARACTER.prototype.weapon_changed = function (iseq) { + this.attack_skill = this.query_used_skill(this.query_weapon_type()); + this.on_skillchanged && this.on_skillchanged(); + if (!this.auto_skills) return; + + for (let item of this.auto_skills) { + if (WEAPON_TYPES[item.type]) { + item.ban_use = !iseq; + } + } +} +CHARACTER.prototype.add_obj = function (obj, count) { + if (!obj) return; + if (typeof obj == "string") { + obj = OBJ.clone_to(obj, this, count); + if (!obj) return; + } else { + obj = this.push_item(obj); + } + return obj; +} +CHARACTER.prototype.remove_obj = function (obj, count) { + if (typeof obj == "string") { + obj = this.find_obj(obj); + } + if (!obj) return; + count = count || obj.count || 1; + this.remove_item(obj, count); + return obj; +} +CHARACTER.prototype.query_weapon = function () { + if (this.equipment) { + return this.equipment[EQUIP_TYPE.WEAPON]; + } +} +CHARACTER.prototype.query_weapon_type = function () { + if (this.equipment) { + var eq = this.equipment[EQUIP_TYPE.WEAPON]; + if (eq) return eq.weapon_type; + } + return WEAPON_TYPE.NONE; +} +CHARACTER.prototype.weapon_name = function () { + if (this.equipment && this.equipment[EQUIP_TYPE.WEAPON]) { + return this.equipment[EQUIP_TYPE.WEAPON].color_name; + } + return ""; +} +CHARACTER.prototype.throwing_name = function () { + if (this.equipment && this.equipment[EQUIP_TYPE.THROWING]) { + return this.equipment[EQUIP_TYPE.THROWING].color_name; + } + return ""; +} +CHARACTER.prototype.can_throwing = function () { + if (this.equipment) { + var th = this.equipment[EQUIP_TYPE.THROWING]; + if (!th) return false; + return true; + } + return false; +} +CHARACTER.prototype.get_equipment = function (type) { + return this.equipment && this.equipment[type]; +} +CHARACTER.prototype.set_drop = function () { + this.drop_list = this.drop_list || []; + for (var i = 0; i < arguments.length; i++) { + this.drop_list.push(arguments[i]); + } +} +CHARACTER.prototype.query_drop = function () { + if (!this.drop_list) return; + return OBJ.create_by_odds(this.drop_list); + +} diff --git a/os/char/chara_move.js b/os/char/chara_move.js new file mode 100644 index 0000000..b8d2016 --- /dev/null +++ b/os/char/chara_move.js @@ -0,0 +1,169 @@ + + +CHARACTER.prototype.moveto = function (rm, leave_msg, in_msg, dir) { + var cur_room = this.environment; + var next_room = rm; + if (typeof rm === "string") { + next_room = ROOM.Get(rm); + if (!next_room) return false; + if (next_room.parent === cur_room.parent) { + if (cur_room.owner) { + next_room = next_room.query_copy(cur_room.owner); + } + } else { + var my_room = next_room.query_copy2(this); + if (my_room) { + next_room = my_room; + } + } + } + if (!next_room) return false; + + if (next_room.is_full()) { + //如果房间人数过多,创建投影 + next_room = next_room.create_shadow(); + if (!next_room) { + //如果创建失败就返回,房间设置不允许投影,或别的原因 + return this.notify("那里人太多了,你过不去。"); + } + } + if (cur_room) { + if (cur_room.do_leave(this, dir, leave_msg) === false) { + return false; + } + } + + next_room.do_enter(this, true, in_msg); + this.notify_follower(dir); + if (cur_room && next_room.parent !== cur_room.parent) { + cur_room.parent.on_leaved(this); + } +} +CHARACTER.prototype.do_follow = function (target) { + if (target) { + if (target.query_setting("no_follow")) { + return this.notify(target.name + "不允许别人跟随。"); + } + if (this.follow_target) { + this.follow_target.follow_targets.remove(this); + this.send_room("$N不再跟随$n一起行动。", this.follow_target); + } + this.follow_target = target; + if (!target.follow_targets) { + target.follow_targets = []; + } + target.follow_targets.push(this); + this.send_room("$N决定跟随$n一起行动。", target); + } else { + if (!this.follow_target) return this.notify("你目前没有跟随别人一起行动。"); + this.follow_target.follow_targets.remove(this); + this.send_room("$N不再跟随$n一起行动。", this.follow_target); + this.follow_target = null; + } +} +CHARACTER.prototype.clear_follow = function () { + if (this.follow_target) { + this.follow_target.follow_targets.remove(this); + this.follow_target = null; + } + if (this.follow_targets) { + for (let item of this.follow_targets) { + item.follow_target = null; + } + this.follow_targets = null; + } +} + +CHARACTER.prototype.notify_follower = function (dir) { + if (this.follow_targets) { + for (var i = 0; i < this.follow_targets.length; i++) { + var item = this.follow_targets[i]; + if (!item.environment) continue; + if (!item.is_player) { + if (item.on_master_leave) { + if (item.on_master_leave(this, this.environment) == false) { + continue; + } + } else { + if (item.environment.is_fb() != this.environment.is_fb()) { + continue; + } + } + //if (item.state && item.set_state) { + // item.set_state(null); + //} + item.moveto(this.environment, + sendOutMessage(item, dir), sendInMessage(item)); + } else { + item.moveto(this.environment, + sendOutMessage(item, dir), sendInMessage(item)); + } + } + } +} + +CHARACTER.prototype.do_escape = function () { + var eny = this.query_enemy(); + if (!eny) return true; + if (eny.on_escape) return eny.on_escape(this); + var is_esc = this.random(this.ds / 2) + this.ds > eny.mz; + if (eny.is_faint) is_esc = true; + if (!is_esc) { + this.send_room("$N转身想跑,$n一把拦住$P:想跑?没门!\n", eny); + this.add_status({ + id: "busy", + name: "忙乱", + duration: this.gjsd, + is_busy: true + }); + } + return is_esc; +} + + +CHARACTER.prototype.team_out = function (msg) { + var tm = this.team; + if (!tm) return; + for (var i = 0; i < tm.length; i++) { + if (!tm[i].is_player && tm[i].master == this.id) { + tm[i].on_teamout && tm[i].on_teamout(); + this.notify(tm[i].name + "退出了队伍。"); + tm[i].team = null; + tm.splice(i, 1); + i--; + } + } + this.team = null; + var iscap = this == tm[0]; + tm.remove(this); + checkTeamfb(this); + if (!tm.length) { + this.send("你的队伍解散了。"); + this.send('{"type":"dialog","dialog":"team",dismiss:true}'); + } else { + var first = tm[0]; + var dissmsg = '{"type":"dialog","dialog":"team",dismiss:true}'; + this.send("你退出了队伍。"); + + + if (tm.length > 1) { + if (iscap) { + first.send_team("" + this.name + msg + "," + first.name + "现在是队长。"); + } else { + first.send_team("" + this.name + msg + "。"); + } + first.send_team('{"type":"dialog","dialog":"team",remove:"' + this.id + '"}'); + this.send(dissmsg); + } else { + if (first.team) { + checkTeamfb(first); + first.send("" + this.name + msg + ",你的队伍解散了。"); + first.team.length = 0; + first.team = null; + first.send(dissmsg); + this.send(dissmsg); + } + } + + } +} \ No newline at end of file diff --git a/os/char/chara_prop.js b/os/char/chara_prop.js new file mode 100644 index 0000000..c09263d --- /dev/null +++ b/os/char/chara_prop.js @@ -0,0 +1,137 @@ + +require("./character.js"); +CHARACTER.prototype.add_prop = function (p, v) { + if (!p) return; + if (!this.prop) { + this.prop = {}; + } + var v1 = this.prop[p] || 0; + + this.prop[p] = v1 + v; +} +CHARACTER.prototype.clear_prop = function () { + this.prop = {}; +} +CHARACTER.prototype.query_prop = function (name) { + if (this.prop) + return this.prop[name] || 0; + return 0; +} +CHARACTER.prototype.query_force_rad = function () { + if (this.force_skill && this.force_skill.force_rad) + return this.force_skill.force_rad || 0.1; + return 0.1; +} +CHARACTER.prototype.add_maxmp = function (count) { + this.max_mp += count; + this.recount(); + this.notify("你增加了" + count + "点内力。"); +} +CHARACTER.prototype.query_temp = function (name, def) { + if (!this.temp) return def; + var item = this.temp[name]; + if (item && item.e) { + if (Date.now() <= item.e) { + return item.v; + } + this.temp[name] = null; + return def; + } + return item ?? def; +} +CHARACTER.prototype.set_temp = function (name, value, time) { + if (!this.temp) this.temp = {}; + if (time) { + this.temp[name] = { + v: value, + e: Date.now() + time + }; + } else { + this.temp[name] = value; + } +} +CHARACTER.prototype.remove_temp = function (name) { + if (!this.temp) return; + this.temp[name] = null; +} + +CHARACTER.prototype.add_temp = function (name, value, time) { + let val = this.query_temp(name, 0) + value; + this.set_temp(name, val, time); + return val; +} + +CHARACTER.prototype.change_prop = function (prop, isadd) { + if (!prop) return; + for (var item in prop) { + switch (item) { + case "desc": + break; + case "skill": + var sks = prop[item]; + for (var sk in sks) { + var lv = this.query_skill(sk, 0); + if (!lv) { + this.add_prop(sk, isadd ? sks[sk] : -sks[sk]); + continue; + } + var sk_base = SKILL.get(sk); + if (!sk_base) continue; + sk_base.release_prop(this, lv); + + this.add_prop(sk, isadd ? sks[sk] : -sks[sk]); + + lv = this.query_skill(sk, 0); + + sk_base.attach_prop(this, lv); + if (this.is_player) { + this.notify('{type:"dialog",dialog:"skills",id:"' + sk + '",level:' + lv + '}'); + } + + } + break; + default: + this.add_prop(item, isadd ? prop[item] : -prop[item]); + break; + } + } +} +CHARACTER.prototype.add_fbscore = function (v, max) { + var fb = this.environment.query_fb_first(this.query_teamid()); + if (!fb) return; + fb.score = (fb.score || 0) + v; + if (max > 0 && fb.score > max) fb.score = max; +} +CHARACTER.prototype.query_fbscore = function (v) { + var first_room = this.environment.query_fb_first(this.query_teamid()); + if (!first_room) return 0; + return first_room.score || 0; +} + +CHARACTER.prototype.add_score = function (val) { + +} + +CHARACTER.prototype.add_combat_prop = function (name, val) { + this.add_prop(name, val); + if (!this.combat_props) this.combat_props = []; + this.combat_props.push([name, val]); + if (name === 'max_hp') { + this.max_hp += val; + } +} + + +CHARACTER.prototype.clear_combat_prop = function (name, val) { + if (this.combat_props) { + for (let i = 0; i < this.combat_props.length; i++) { + this.add_prop(this.combat_props[i][0], -this.combat_props[i][1]); + if (this.combat_props[i][0] === 'max_hp') { + this.max_hp -= this.combat_props[i][1]; + this.notify_hp(); + } + } + this.combat_props = null; + this.recount(); + } +} \ No newline at end of file diff --git a/os/char/chara_skill.js b/os/char/chara_skill.js new file mode 100644 index 0000000..72f2ca9 --- /dev/null +++ b/os/char/chara_skill.js @@ -0,0 +1,566 @@ + +require("./character.js"); +CHARACTER.prototype.query_skill = function (name, def) { + if (!this.skills || !this.skills[name]) return def || 0; + return this.skills[name].level + this.query_prop(name); +} +CHARACTER.prototype.skill_map = function () { + //给NPC初始化技能用的,不做任何判断 + this.skills = this.skills || {}; + for (var i = 0; i < arguments.length; i++) { + var item = arguments[i]; + if (!item) continue; + var skill_base = SKILL.get(item[0]); + if (!skill_base) { + console.log(item[0] + " not exits") + continue; + } + var skill = { + level: item[1] || 1, + exp: 0 + }; + this.skills[skill_base.id] = skill; + if (item[2]) { + var enables = item[2]; + if (typeof enables == "string") enables = [enables]; + for (var j = 0; j < enables.length; j++) { + + skill[enables[j]] = true; + this.skills[enables[j]].enable_skill = item[0]; + } + } + } +} +CHARACTER.prototype.remove_skill = function (skillid) { + var skill = this.skills[skillid]; + if (!skill) return; + var baseskill = SKILL.get(skillid); + if (!baseskill) return false; + + if (baseskill.type == SKILL_TYPES.BASE) { + if (skill.enable_skill) { + var old_skill = SKILL.get(skill.enable_skill); + if (!old_skill || !this.skills[skill.enable_skill]) { + return false; + } + old_skill.disenable(this, skillid); + this.skills[skill.enable_skill][skillid] = false; + } + } else { + for (var key in this.skills) { + if (this.skills[key].enable_skill == skillid) { + + this.skills[key].enable_skill = null; + } + } + } + baseskill.release_prop(this, this.query_skill(skillid)); + delete this.skills[skillid]; + this.init_skill(); + this.recount(); + this.add_score(-baseskill.query_score(skill.level, this)); + baseskill.on_remove && baseskill.on_remove(this); + return true; +} +//增加技能 +CHARACTER.prototype.set_skill = function (skid, level) { + if (!this.skills) this.skills = {}; + var item = this.skills[skid]; + var skill_base = SKILL.get(skid); + if (!skill_base) return; + if (!item) { + item = { + //id: skid, + level: level, + exp: 0 + }; + this.skills[skid] = item; + skill_base.attach_prop(this, level); + } else { + skill_base.release_prop(this, this.query_skill(skid)); + item.level = level; + skill_base.attach_prop(this, this.query_skill(skid)); + } + this.init_skill(); + this.recount(); +} +CHARACTER.prototype.skill_limit = function () { + if (this.exp < 100) return 10; + switch (this.level) { + case 1: return Math.round(Math.pow(this.exp * 20, 1 / 3)); + case 2: return Math.round(Math.pow(this.exp * 30, 1 / 3)); + case 3: return Math.round(Math.pow(this.exp * 40, 1 / 3)); + case 4: return Math.round(Math.pow(this.exp * 50, 1 / 3)); + case 5: return Math.round(Math.pow(this.exp * 60, 1 / 3)); + case 6: return Math.round(Math.pow(this.exp * 60, 1 / 3)); + default: + return Math.round(Math.pow(this.exp * 10, 1 / 3)); + } +} + +CHARACTER.prototype.query_ref_skill = function (skill) { + if (!skill || !skill.ref) return; + var refs = skill.ref.split("/"); + var sp_skill = SKILL.get(refs[0]); + if (sp_skill) { + return sp_skill.get_pfm(refs[1]); + } +} +//判断某个技能是否装备到某个基本技能上 +CHARACTER.prototype.is_enable_skill = function (skid, type) { + if (!this.skills) return; + var item = this.skills[skid]; + if (!item) return; + return item[type]; +} +//装备技能到基本技能 +CHARACTER.prototype.enable_skill = function (base, skill) { + if (!this.skills) return; + var baseskill = this.skills[base]; + if (!baseskill) return; + if (baseskill.enable_skill) { + var old_skill = this.skills[baseskill.enable_skill]; + if (!old_skill) return; + old_skill[base] = false; + + old_skill = SKILL.get(baseskill.enable_skill); + if (old_skill) { + old_skill.disenable(this, base); + } + } + if (skill) { + var sp_skill = this.skills[skill]; + + if (baseskill && sp_skill) { + var sp_skill_base = SKILL.get(skill); + if (!sp_skill_base || sp_skill_base.enable(this, base) !== true) + return false; + baseskill.enable_skill = skill; + sp_skill[base] = true; + } + } else { + baseskill.enable_skill = null; + } + this.init_skill(); + this.recount(); + + return true; +} +//初始化人物使用的技能 +CHARACTER.prototype.init_skill = function () { + this.attack_skill = this.query_used_skill(this.query_weapon_type()); + this.noweapon_skill = this.query_used_skill(WEAPON_TYPE.NONE); + this.dodge_skill = this.query_used_skill(BASE_SKILLS.DODGE); + this.parry_skill = this.query_used_skill(BASE_SKILLS.PARRY); + this.force_skill = this.query_used_skill(BASE_SKILLS.FORCE); + this.on_skillchanged && this.on_skillchanged(); + this.auto_skills = null; +} + +CHARACTER.prototype.query_used_skill = function (skname) { + if (!this.skills) { + return WORLD.DEFAULT_SKILLS[skname]; + } + var skill = this.skills[skname]; + if (skill) { + + var skill_base = SKILL.get(skill.enable_skill || skname); + if (!skill_base) skill.enable_skill = null; + else return skill_base; + } + return WORLD.DEFAULT_SKILLS[skname]; +} +CHARACTER.prototype.query_status = function (sid) { + if (!this.status) return 0; + for (var i = 0; i < this.status.length; i++) { + if (this.status[i].id == sid) { + return this.status[i].count; + } + } + return 0; +} +CHARACTER.prototype.add_status = function (buff, from) { + if (this.hp <= 0) return false; + if (!this.status) this.status = []; + var sid = buff.id; + buff.override = buff.override || 0; + buff.count = buff.count || 1; + buff.max_count = buff.max_count || 10; + + buff.start_time = Date.now(); + if (buff.on_interval) { + buff.over_count = buff.over_count || 0; + } + if (this.ig_control && !buff.no_diff) { + if (buff.is_busy || buff.is_faint || buff.is_miss || buff.is_rash) { + return false; + } + } + if (buff.downside && buff.duration && !buff.no_diff) { + //buff.duration = buff.duration - this.query_prop("diff_downside"); + buff.duration = Math.round(buff.duration * (100 - this.query_prop("diff_downside_per")) / 100); + if (buff.duration <= 0) { + return false; + } + } + if (buff.is_busy && !buff.no_diff) { + if (from) { + buff.duration = buff.duration + from.query_prop("busy"); + buff.duration = buff.duration * (100 + from.query_prop("busy_per")) / 100; + } + buff.duration = buff.duration - this.query_prop("diff_busy"); + buff.duration = Math.round(buff.duration * (100 - this.query_prop("diff_busy_per")) / 100); + if (buff.duration <= 0) { + return false; + } + } + for (var i = 0; i < this.status.length; i++) { + + if (this.status[i].id == sid) { + var item = this.status[i]; + if (item.override != buff.override) return false; + if (item.override == 0) { + //0不覆盖 1叠加 2覆盖替换 + + return false; + } + if (item.override == 1) { + if (item.max_count <= item.count) { + return false; + } + item.count += buff.count; + clearTimeout(item.handler); + if (item.duration) + item.handler = this.call_out(this.remove_status, item.duration, sid); + this.change_buff(item, true, buff.count); + item.start_time = buff.start_time; + this.status_changed(item, "refresh"); + } else { + + item.handler && clearTimeout(item.handler); + this.change_buff(item, false, item.count);//覆盖先移除 后添加 重新计时 + this.status_changed(item, "remove"); + if (buff.duration) + item.handler = this.call_out(this.remove_status, buff.duration, sid); + this.status[i] = buff; + buff.start_time = buff.start_time; + this.change_buff(buff, true, buff.count); + this.status_changed(buff, "add"); + } + return; + } + } + if (buff.duration) + buff.handler = this.call_out(this.remove_status, buff.duration, sid); + this.status.push(buff); + + this.change_buff(buff, true, buff.count); + this.status_changed(buff, "add"); +} + +CHARACTER.prototype.clear_downside = function (type) { + if (!this.status) return; + var removed = "0"; + var count = 0; + for (var i = 0; i < this.status.length; i++) { + var item = this.status[i]; + if ((item.downside || false) == type && !item.no_clear) { + + this.change_buff(item, false, item.count); + item.handler && clearTimeout(item.handler); + this.status.splice(i, 1); + i--; + removed += ',"' + item.id + '"'; + count++; + } + } + if (removed.length == 1 || !this.environment) return; + var items = this.environment.items; + var msg = '{type:"status",id:"' + this.id + '",sid:[' + removed + '],action:"remove"}'; + for (var i = 0; i < items.length; i++) { + var player = items[i]; + if (player.is_player) { + player.send(msg); + } + } + return count; + +} + + +CHARACTER.prototype.clear_combat_status = function () { + if (!this.status || !this.status.length) return; + var removed = "0"; + for (var i = this.status.length - 1; i >= 0; i--) { + var item = this.status[i]; + if (item.only_combat) { + this.change_buff(item, false, item.count); + item.handler && clearTimeout(item.handler); + this.status.splice(i, 1); + removed += ',"' + item.id + '"'; + } + } + if (removed.length == 1 || !this.environment) return; + var items = this.environment.items; + var msg = '{type:"status",id:"' + this.id + '",sid:[' + removed + '],action:"remove"}'; + for (var i = 0; i < items.length; i++) { + var player = items[i]; + if (player.is_player) { + player.send(msg); + } + } +} +CHARACTER.prototype.remvoe_statuses = function (func) { + if (!this.status || !this.status.length) return; + var removed = "0"; + for (var i = this.status.length - 1; i >= 0; i--) { + var item = this.status[i]; + if (func(item)) { + this.change_buff(item, false, item.count); + item.handler && clearTimeout(item.handler); + this.status.splice(i, 1); + removed += ',"' + item.id + '"'; + } + } + if (removed.length == 1 || !this.environment) return; + var items = this.environment.items; + var msg = '{type:"status",id:"' + this.id + '",sid:[' + removed + '],action:"remove"}'; + for (var i = 0; i < items.length; i++) { + var player = items[i]; + if (player.is_player) { + player.send(msg); + } + } +} +CHARACTER.prototype.clear_status = function () { + if (!this.status || !this.status.length) return; + for (var i = 0; i < this.status.length; i++) { + var item = this.status[i]; + this.change_buff(item, false, item.count); + item.handler && clearTimeout(item.handler); + } + this.status.length = 0; + if (!this.environment) return; + var msg = '{type:"status",id:"' + this.id + '",action:"clear"}'; + var items = this.environment.items; + for (var i = 0; i < items.length; i++) { + var player = items[i]; + if (player.is_player) { + player.send(msg); + } + } +} +CHARACTER.prototype.change_buff = function (buff, isadd, buff_count) { + if (isadd) { + if (buff.prop) { + for (var i = 0; i < buff_count; i++) { + this.change_prop(buff.prop, true); + } + this.recount(); + } + if (buff.on_attach) buff.on_attach(this); + if (buff.ig_control) this.ig_control = buff.duration; + + if (buff.start_msg) { + this.send_room(buff.start_msg); + } + if (buff.is_busy) this.is_busy = buff.duration; + if (buff.is_miss) this.is_miss = buff.duration; + if (buff.is_rash) this.is_rash = buff.duration; + if (buff.is_shadow) this.is_shadow = buff.duration; + if (buff.is_faint) { + this.is_faint = buff.duration; + } + } else { + if (buff.prop) { + for (var i = 0; i < buff_count; i++) { + this.change_prop(buff.prop, false); + } + this.recount(); + } + if (buff.on_expire) buff.on_expire(this); + if (buff.is_busy) this.is_busy = 0; + if (buff.is_miss) this.is_miss = 0; + if (buff.is_rash) this.is_rash = 0; + if (buff.ig_control) this.ig_control = 0; + if (buff.is_shadow) this.is_shadow = 0; + if (buff.is_faint) { + this.is_faint = 0; + } + if (this.hp > 0 && buff.finish_msg) { + this.send_room(buff.finish_msg); + } + this.remove_temp(buff.id); + } + +} +CHARACTER.prototype.appdend_status = function (str) { + if (!this.status) return; + var now = Date.now(); + str.push(",status:["); + for (var i = 0; i < this.status.length; i++) { + if (i > 0) str.push(","); + var item = this.status[i]; + str.push('{sid:"'); + str.push(item.id); + str.push('",name:"'); + str.push(item.name); + str.push('",duration:'); + if (item.on_interval) { + str.push(item.duration * item.duration_count); + } else { + str.push(item.duration); + } + str.push(',overtime:'); + str.push(now - item.start_time); + if (item.override === 1) { + str.push(',"count":'); + str.push(item.count); + } + if (item.downside) { + str.push(',downside:'); + str.push(true); + } + str.push('}'); + } + str.push("]"); +} +CHARACTER.prototype.notify_status = function () { + if (!this.status) return; + var str = ['{type:"status",id:\"']; + str.push(this.id); + str.push("\",action:'load',items:["); + var now = Date.now(); + for (var i = 0; i < this.status.length; i++) { + if (i > 0) str.push(","); + var item = this.status[i]; + str.push('{sid:"'); + str.push(item.id); + str.push('",name:"'); + str.push(item.name); + str.push('",duration:'); + if (item.on_interval) { + str.push(item.duration * item.duration_count); + } else { + str.push(item.duration); + } + + str.push(',overtime:'); + str.push(now - item.start_time); + if (item.override === 1) { + str.push(',"count":'); + str.push(item.count); + } + if (item.downside) { + str.push(',downside:'); + str.push(true); + } + str.push('}'); + } + str.push("]}"); + this.send(str.join("")); +} +CHARACTER.prototype.status_changed = function (item, type) { + var str = []; + str.push('{type:"status","action":"'); + str.push(type); + str.push('",id:"'); + str.push(this.id); + str.push('",sid:"'); + str.push(item.id); + str.push('"'); + if (type === "add") { + str.push(',"name":"'); + str.push(item.name); + str.push('","duration":'); + if (item.on_interval) { + str.push(item.duration * item.duration_count); + } else { + str.push(item.duration); + + } + if (item.override === 1) { + str.push(',"count":'); + str.push(item.count); + } + if (item.downside) { + str.push(',downside:'); + str.push(true); + } + } else if (type === "refresh") { + str.push(',count:'); + str.push(item.count); + } + str.push('}'); + if (!this.environment) return; + var msg = str.join(""); + var items = this.environment.items; + for (var i = 0; i < items.length; i++) { + var player = items[i]; + if (player.is_player) { + player.send(msg); + } + } +} +CHARACTER.prototype.remove_status = function (sid, isall) { + if (!this.status) return; + for (var i = this.status.length - 1; i >= 0; i--) { + if (this.status[i].id === sid) { + var item = this.status[i]; + if (item.handler) clearTimeout(item.handler); + item.handler = null; + + + if (item.on_interval && !isall) { + item.over_count++; + if (item.on_interval) { + if (item.on_interval(this, item.over_count) === false) { + item.duration_count = item.duration_count || 2; + item.over_count = item.duration_count; + } + } + if (item.duration_count === 0 || (item.duration_count > 1 && item.duration_count > item.over_count)) { + if (item.duration) + item.handler = this.call_out(this.remove_status, item.duration, sid); + // item.start_time = Date.now(); + return; + } + } + + this.change_buff(item, false, 1); + + if (item.override === 1) { + item.count--; + if (item.count === 0 || isall) { + + this.change_buff(item, false, item.count); + + this.status_changed(item, "remove"); + this._splice_status(i, item); + } else { + if (item.duration) + item.handler = this.call_out(this.remove_status, item.duration, sid); + item.start_time = Date.now(); + this.status_changed(item, "refresh"); + } + } else { + //覆盖和不覆盖的都直接移除 + this.status_changed(item, "remove"); + this._splice_status(i, item); + } + + return; + } + } +} +CHARACTER.prototype._splice_status = function (index, item) { + if (this.status[index] === item) { + return this.status.splice(index, 1); + } + for (var i = 0; i < this.status.length; i++) { + if (this.status[i] === item) { + return this.status.splice(i, 1); + } + } +} + diff --git a/os/char/character.js b/os/char/character.js new file mode 100644 index 0000000..a25b569 --- /dev/null +++ b/os/char/character.js @@ -0,0 +1,351 @@ +require("../item"); +/*global CHARACTER ROOM ITEM*/ +CHARACTER = function () { + this.name = "生物"; + this.hp = this.max_hp = 100; + this.mp = this.max_mp = 100; + this.str = this.con = this.dex = this.int = 20; + this.money = 0; +} +CHARACTER.inherits(ITEM); +CHARACTER.prototype.send = function () { + +} +CHARACTER.prototype.notify = function () { + +} +CHARACTER.prototype.send_commands = function () { + +} +CHARACTER.prototype.notify_fail = function () { + return false; +} +CHARACTER.prototype.is_living = function () { + return this.hp > 0; +} +CHARACTER.prototype.is_in = function (path) { + if (!this.environment) return false; + return this.environment.path === path; +} +CHARACTER.prototype.is_here = function (obj) { + if (!this.environment || !obj.environment) return false; + return this.environment === obj.environment; +} + +CHARACTER.prototype.find_obj = function (oid, parent) { + var items = this.items; + if (parent) items = parent.items; + return this.find_obj_byid(items, oid); +} +CHARACTER.prototype.send_message = function (msg, include_me) { + if (!msg || !this.environment) return; + var list = this.environment.items; + for (var i = 0; i < list.length; i++) { + if (list[i].is_player) { + if (list[i] === this && !include_me) continue; + if (!list[i].no_message) + list[i].notify(msg); + } + } +} +CHARACTER.prototype.send_combat = function (text, target) { + if (!this.environment || !text) return; + var list = this.environment.items; + var th_vision, item; + for (var i = 0; i < list.length; i++) { + item = list[i]; + if (item.is_player) { + if (item === this) { + if (!item.query_setting("no_mcmsg")) + item.notify(splitmessage(this, text, 1, target)); + } else if (item === target) { + if (!item.query_setting("no_mcmsg")) + item.notify(splitmessage(this, text, 2, target)); + } else if (!item.no_message && !item.query_setting("no_combatmsg")) { + if (!th_vision) th_vision = splitmessage(this, text, 3, target); + item.notify(th_vision); + } + } + } +} +CHARACTER.prototype.send_room = function (text, target, excludeself) { + if (!this.environment || !text) return; + var list = this.environment.items; + var th_vision; + for (var i = 0; i < list.length; i++) { + if (list[i].is_player) { + if (list[i] === this) { + !excludeself && list[i].notify(splitmessage(this, text, 1, target)); + } else if (list[i] === target) { + list[i].notify(splitmessage(this, text, 2, target)); + } else if (!list[i].no_message) { + if (!th_vision) th_vision = splitmessage(this, text, 3, target); + list[i].notify(th_vision); + } + } + } +} +CHARACTER.prototype.query_setting = function (name) { + return false; +} +function splitmessage(me, text, type, target) { + if (text.length < 3) return text; + var str = []; + var start = 0; + for (var i = 0; i < text.length; i++) { + if (text[i] === "$") { + start < i && str.push(text.substring(start, i)); + var ch = text[++i]; + start = i + 1; + //type 1本人视角 2目标视角 3第三人称视角 + switch (ch) { + case "N"://本人 + str.push(type === 1 ? "你" : me.name); + break; + case "n"://目标 + str.push(type === 2 ? "你" : target.name); + break; + case "P": + str.push(type === 1 ? "你" : me.call3()); + break; + case "p": + str.push(type === 2 ? "你" : target.call3()); + break; + case "l": + str.push(me.attack_part ? me.attack_part.name : ""); + break; + case "W": + case "w": + str.push(me.weapon_name() || "手"); + break; + case "i": + str.push(target.weapon_name() || "手"); + break; + case "T": + str.push(me.throwing_name()); + break; + + } + } + } + start < i && str.push(text.substring(start, i)); + return str.join(""); +} + +//执行一串命令 +CHARACTER.prototype.command = function (req) { + + if (this.wait_input) { //如果用户等待输入 + this.wait_input.apply(this, [this, req]); + return; + } + var cmd = null, pars = null, start = 0, i = 0; + for (; i < req.length; i++) { + if (req[i] === ' ') { + if (start < i) { + cmd = req.substring(start, i); + pars = req.substring(i + 1); + break; + } + start = i; + } + } + if (!cmd) cmd = req; + this.do_command(cmd, pars); +} +CHARACTER.prototype.do_command = function (cmdName, str) { + + var cmd = WORLD.COMMANDS[cmdName]; + var pars; + if (cmd && cmd.regex && str) { + pars = cmd.regex.exec(str); + pars ? pars[0] = this : pars = [this, str]; + } else { + pars = [this, str]; + } + if (this.do_item_action(this.environment, cmdName, pars)) { + //如果环境触发这个命令就返回 + return; + } + cmd = cmd || WORLD.DEFAULT_COMMAND; + if (cmd) { + if (!this.check_command(cmd)) + return;//不允许执行 + if (cmd.enter.apply(cmd, pars) !== false) { + + return;//命令执行完成。 + } + + } + if (str) { + //如果有参数,尝试找下这个物件 + if (this.do_item_action(this.find_obj(str, this.environment), cmdName, pars)) { + //如果物件触发这个命令就返回 + return; + } + } + this.send("什么?"); +} +CHARACTER.prototype.do_item_action = function (item, cmd, pars) { + if (!item || !item.actions) return; + var cmdItem = item.actions[cmd]; + if (!cmdItem || !cmdItem.action) return; + if (!this.check_command(cmdItem)) + return true;//返回true 不允许执行 + if (cmdItem.action.apply(item, pars) !== false) + return true; //返回true表示不继续执行该命令 +} +CHARACTER.prototype.check_command = function (cmd) { + if (cmd.allow_level > this.user_level) { + this.send("什么?"); + return false; + } + if (this.hp <= 0 && !cmd.allow_die) { + //死亡状态,除了一些特殊指令都不能做 + return this.notify_fail("你现在是灵魂状态,不能那么做。"); + } + if (!cmd.allow_faint && this.is_faint) { + this.send("你正在昏迷中!"); + return false; + } + if (!cmd.allow_state && this.state) { + return this.notify_fail("你正在" + this.state.title + ",没时间这么做。"); + } + if (!cmd.allow_fight && this.fight_type > 0) { + return this.notify_fail("你正在战斗,待会再说。"); + } + if (!cmd.allow_busy && this.is_busy) { + return this.notify_fail("你现在正忙。"); + } + + return true; +} +CHARACTER.prototype.create = function (path, par) { + //模板被创建,实际上没真正用 + if (par) this.path = path + par; + this.on_create && this.on_create(path, par); + + WORLD.NPC_STROE.set(this.path, this); +} +CHARACTER.prototype.update = function (path, par) { + this.create(path, par); +} + +//真正被复制到房间 +CHARACTER.prototype.clone = function () { + if (this.temp) this.temp = Object.create(this.temp); + if (this.prop) this.prop = Object.create(this.prop); + if (this.equipment) { + let eqs = []; + for (let i = 0; i < this.equipment.length; i++) { + let item = this.equipment[i]; + if (item) { + eqs[i] = OBJ.CREATE(item.path); + } + } + this.equipment = eqs; + } + //装备和道具只保留引用应该没事,2个相同NPC的装备和背包是同一个道具 + //好像随从不行 + if (this.items) { + let items = []; + for (let i = 0; i < this.items.length; i++) { + items[i] = OBJ.CREATE(this.items[i].path); + } + this.items = items; + } + this.create_id(); + this.init(); + + this.recount(); + this.hp = this.max_hp; + this.mp = this.max_mp; + this.on_clone && this.on_clone(); +} + + +CHARACTER.prototype.init = function () { + if (this.equipment) { + let groups = {}; + for (let i = 0; i < this.equipment.length; i++) { + let item = this.equipment[i]; + if (item) { + item.change_prop(this, true); + item.on_eq && item.on_eq(this); + if (item && item.group_name) { + groups[item.group_name] = (groups[item.group_name] || 0) + 1; + var prop = item.group_prop(groups[item.group_name]); + if (prop) { + this.change_prop(prop, true); + } + } + } + } + } + if (this.is_player) this.score = 0; + if (this.skills) { + for (let item in this.skills) { + var base_skill = SKILL.get(item); + if (!base_skill) { + delete this.skills[item]; + continue; + } + base_skill.attach_prop(this, this.query_skill(item)); + if (this.is_player) { + this.score += base_skill.query_score(this.skills[item].level, this); + } + + } + } + + this.init_skill(); +} +CHARACTER.EXP_LIMIT = [300000, 3000000, 20000000]; +CHARACTER.prototype.add_exp = function (exp, pot, money) { + if (exp) { + exp += this.query_temp("exp_up", 0); + + } + if (pot) { + pot += this.query_temp("pot_up", 0); + + } + var str = ["你获得了"]; + if (exp) { + this.exp += exp; + str.push(exp); + str.push("点经验"); + } + if (pot) { + this.pot += pot; + if (exp) str.push(","); + str.push(pot); + str.push("点潜能"); + } + if (money) { + + this.money += money; + if (exp || pot) str.push(","); + str.push(UTIL.moneyToStr(money)); + } + if (str.length === 1) return; + str.push("。"); + this.send(str.join("")); +} +CHARACTER.prototype.add_money = function (val) { + this.money += val; + +} +CHARACTER.prototype.check_groupeq = function () { + var eqs = {}; + for (var i = 0; i < this.equipment.length; i++) { + var item = this.equipment[i]; + if (item && item.group_name) { + eqs[item.group_name] = (eqs[item.group_name] || 0) + 1; + var prop = item.group_prop(eqs[item.group_name]); + if (prop) { + this.change_prop(prop, true); + } + } + } +} \ No newline at end of file diff --git a/os/char/combat.js b/os/char/combat.js new file mode 100644 index 0000000..408b255 --- /dev/null +++ b/os/char/combat.js @@ -0,0 +1,250 @@ + +require("./character.js"); +CHARACTER.prototype.begin_attack = function (target, type) { + + if (!target || target === this) return; + if (!this.attack_skill) { + return this.send("error skill"); + } + this.add_enemy(target); + this.fight_type = this.fight_type || 0; + if (type > this.fight_type) { + if (this.force_skill && this.force_skill.on_beginfight) { + this.force_skill.on_beginfight(this, target); + } + if (this.attack_skill && this.attack_skill.on_beginfight) { + this.attack_skill.on_beginfight(this, target); + } + if (!this.fight_type) { + + if (this.attack_handler) clearTimeout(this.attack_handler); + this.attack_handler = this.call_out(this.auto_attack, Math.random() * this.gjsd); + this.send('{type:"combat",start:1}'); + + } + this.fight_type = type; //1fight hp<30% 2 kill 0 + } + +} +CHARACTER.prototype.do_fight = function (target) { + this.begin_attack(target, 1); +} +CHARACTER.prototype.do_kill = function (target) { + if (this.fight_type == 2 && this.query_enemy() == target) return; + this.begin_attack(target, 2); + target.begin_attack(this, 2); + target.notify("看起来" + this.name + "想杀死你!\n"); + this.notify("看起来" + target.name + "想杀死你!\n"); +} +CHARACTER.prototype.add_enemy = function (target) { + if (!this.enemy) { + this.enemy = []; + } + this.enemy.push(target); +} +CHARACTER.prototype.notify_hp = function (type, val) { + if (!this.environment) return; + + var items = this.environment.items; + var str = null; + if (type) { + str = "{type:\"sc\",id:\"" + this.id + "\"," + type + ":" + val + ""; + } else { + var ary = ["{type:\"sc\",id:\""]; + ary.push(this.id); + ary.push("\",hp:"); + ary.push(this.hp); + ary.push(",max_hp:"); + ary.push(this.max_hp); + ary.push(",mp:"); + ary.push(this.mp); + ary.push(",max_mp:"); + ary.push(this.max_mp); + str = ary.join(""); + } + var showdamage = type ? type === "hp" : false; + for (var i = 0; i < items.length; i++) { + var player = items[i]; + if (player.is_player) { + if (showdamage && this.damages && player.query_setting('show_damage')) { + player.send(str + ",damage:" + (this.damages[player.id] || 0) + "}"); + } else { + player.send(str + "}"); + } + } + } +} +CHARACTER.prototype.add_hp = function (v) { + + if (v > this.max_hp - this.hp) v = this.max_hp - this.hp; + else if (v < -this.hp) v = -this.hp; + if (!v) return 0; + + this.hp += v; + this.notify_hp("hp", this.hp); + return v; +} +CHARACTER.prototype.add_mp = function (v) { + var mp = this.mp + v; + if (mp > this.max_mp) mp = this.max_mp; + if (mp < 0) mp = 0; + if (mp === this.mp) return; + this.mp = mp; + this.notify_hp("mp", this.mp); + return v; +} +CHARACTER.prototype.is_fighting = function (p) { + if (!this.fight_type) return false; + if (!this.enemy || !this.enemy.length) { + this.fight_type = 0; + this.clear_combat_status(); + return false; + } + if (p) { + if (p.environment !== this.environment) return false; + return this.enemy.contain(p); + } + return true; +} +CHARACTER.prototype.end_fight = function () { + if (this.enemy) this.enemy.length = 0; + this.release_time = 0; + if (!this.fight_type) return; + + this.send('{type:"combat",end:1}'); + if (this.record_damage && this.hp > 0) this.damages = null; + this.fight_type = 0; + if (this.attack_handler) clearTimeout(this.attack_handler); + this.attack_handler = null; + this.clear_combat_status(); + this.clear_combat_prop(); + return false; +} +CHARACTER.prototype.query_enemy = function () { + if (!this.enemy) return; + for (var i = 0; i < this.enemy.length; i++) { + if (this.enemy[i].hp <= 0 || !this.is_here(this.enemy[i]) + || !this.enemy[i].fight_type) { + this.enemy.splice(i, 1); + i--; + } + } + return this.enemy[0]; +} +CHARACTER.prototype.can_attack = function () { + return this.hp > 0 && this.fight_type > 0 && !this.is_faint && !this.is_busy; +} + +CHARACTER.prototype.end_attack = function (target) { + if (!target) return; + if (!this.fight_type) return; + if (this.attack_skill.on_end_attack) { + this.attack_skill.on_end_attack(this, target); + } + + if (this.fight_type === 1 && target.hp / target.max_hp < 0.3) { + if (target.hp <= 0) target.hp = 1; + if (target.is_faint) { + this.send_room(WINNER_MSG[this.random(4)], target); + } else { + this.send_room(WINNER_MSG.random(), target); + } + target.on_fight_over && target.on_fight_over(this, false); + this.on_fight_over && this.on_fight_over(target, true); + target.end_fight(); + return this.end_fight(); + } else if (target.hp <= 0 && target.die(this) !== false) { + target.end_fight(); + + this.enemy.remove(target); + + if (!this.enemy.length) { + if (this.hp <= 0) { + this.hp = 1; + } + return this.end_fight(); + } + } + return true;//是否继续攻击 +} +CHARACTER.prototype.query_part = function () { + return CHARACTER_PARTS.random(); +} + + +CHARACTER.prototype.full = function () { + + this.hp = this.max_hp; + this.mp = this.max_mp; + this.clear_distime(); + this.release_time = 0; + this.notify_hp(); +} + +CHARACTER.prototype.clear_distime = function (pfmid) { + if (this.auto_skills) { + if (!pfmid) { + for (let i = 0; i < this.auto_skills.length; i++) { + let item = this.auto_skills[i]; + item.release_time = 0; + } + } else { + for (let i = 0; i < this.auto_skills.length; i++) { + let item = this.auto_skills[i]; + if (item.pfm.id === pfmid) { + item.release_time = 0; + break; + } + + } + } + + } +} +CHARACTER.prototype.do_attacks = function (par) { + + var targets = par.targets; + if (!targets) { + targets = new Array(this.enemy.length); + for (var i = 0; i < this.enemy.length; i++) { + targets[i] = this.enemy[i]; + } + } + if (!targets.length) return; + var attack_msg = par.attack_msg; + if (attack_msg === undefined) attack_msg = (par.no_weapon ? this.noweapon_skill : this.attack_skill).query_attack_action(this, targets[0]); + if (attack_msg !== "") this.send_combat(attack_msg, targets[0]); + par.attack_msg = ""; + for (let i = 0; i < targets.length; i++) { + par.target = targets[i]; + this.do_attack(par); + this.end_attack(targets[i]); + } +} +var CHARACTER_PARTS = [ + { name: "左脚", hert: 0.8, crit: 0 }, + { name: "右脚", hert: 0.8, crit: 0 }, + { name: "左腿", hert: 0.85, crit: 0 }, + { name: "右腿", hert: 0.85, crit: 0 }, + { name: "小腹", hert: 0.91, crit: 3 }, + { name: "胸前", hert: 0.95, crit: 4 }, + { name: "后背", hert: 0.97, crit: 4 }, + { name: "头部", hert: 1.2, crit: 10 }, + { name: "颈部", hert: 1.1, crit: 5 }, + { name: "后心", hert: 1, crit: 4 }, + { name: "左肩", hert: 0.85, crit: 1 }, + { name: "右肩", hert: 0.89, crit: 1 }, + { name: "左手", hert: 0.85, crit: 0 }, + { name: "左手", hert: 0.85, crit: 0 }, + { name: "腰间", hert: 0.99, crit: 5 } +]; + +var WINNER_MSG = [ + "$N哈哈大笑,愉快地说道:承让了!", + "$N双手一拱,笑著说道:知道我的厉害了吧!", + "$N哈哈大笑,双手一拱,笑著说道:承让!", + "$N胜了这招,向后跃开三尺,笑道:承让!", + "$n脸色微变,说道:佩服,佩服!", + "$n向后退了几步,说道:这场比试算我输了,佩服,佩服!", + "$n向后一纵,躬身做揖说道:阁下武艺不凡,果然高明!", +]; diff --git a/os/char/follower.js b/os/char/follower.js new file mode 100644 index 0000000..4f949e1 --- /dev/null +++ b/os/char/follower.js @@ -0,0 +1,485 @@ +require("../util/util.js"); +require("./user.js"); +FOLLOWER = function () { + this.hp = this.max_hp = 100; + this.mp = this.max_mp = 100; + this.str = this.con = this.dex = this.int = this.per = this.age = 20; + this.family = FAMILIES.NONE; + this.auto_pfm = true; + this.master = null; + this.level = 3; + this.master_name = null; + this.max_item_count = 10; + this.settings = { + auto_kill: 1, + auto_dice: 1 + }; +} +FOLLOWER.inherits(CHARACTER); +FOLLOWER.prototype.query_setting = function (name) { + if (!this.settings) return 0; + return this.settings[name] || 0; +} +FOLLOWER.prototype.set_setting = function (name, value) { + if (!this.settings) this.settings = {}; + if (!value || value == "0") { + delete this.settings[name]; + } else { + if (value == "1") value = 1; + this.settings[name] = value; + } + + this.login_message = null; +} +FOLLOWER.prototype.send = function (text) { + if (this.listener) { + text = text.replace('你', this.name); + this.listener.send(text); + } +} +FOLLOWER.prototype.notify_fail = function (text) { + this.send(text); + return false; +} +FOLLOWER.prototype.notify = function (text) { + this.send(text); +} + +FOLLOWER.prototype.set_listener = function (me, target) { + if (me.id == this.master) this.listener = target; +} +FOLLOWER.STORES = new Map(); +FOLLOWER.CLEAR = function (me) { + if (!me.follower) return; + for (var i = 0; i < me.follower.length; i++) { + var npc = FOLLOWER.STORES.get(me.id + "_" + me.follower[i].id); + if (npc) { + FOLLOWER.STORES.delete(me.id + "_" + me.follower[i].id); + npc.set_state(null); + npc.environment && npc.environment.item_changed(npc, false); + npc.clear_status(); + } + } +} + +FOLLOWER.RESET = function (me) { + if (!me.follower) return; + for (var i = 0; i < me.follower.length; i++) { + var npc = FOLLOWER.STORES.get(me.id + "_" + me.follower[i].id); + if (npc) { + npc.set_state(null); + npc.environment && npc.environment.item_changed(npc, false); + } + } +} +FOLLOWER.INIT_FROM_USER = function (me, datas) { + + for (var j = 0; j < datas.length; j++) { + var data = datas[j]; + var my_npc = FOLLOWER.STORES.get(me.id + "_" + data.id); + if (my_npc) continue; + if (!datas[j].id) continue; + my_npc = new FOLLOWER(); + var obj = NPC.CLONE(data.path); + for (var i = 0; i < SAVE_NUMPROP.length; i++) { + my_npc[SAVE_NUMPROP[i]] = data.prop[i] || 0; + } + for (var i = 0; i < SAVE_STRPROP.length; i++) { + my_npc[SAVE_STRPROP[i]] = data[SAVE_STRPROP[i]] || obj[SAVE_STRPROP[i]]; + } + my_npc.on_makelove = obj ? obj.on_makelove : null; + my_npc.on_master_enter = obj ? obj.on_master_enter : null; + my_npc.equipment = data.temp; + my_npc.settings = data.settings; + my_npc.skills = data.skills; + my_npc.path = obj.path; + my_npc.items = me.read_items(data.items); + my_npc.equipment = me.read_items(data.eq); + my_npc.level = my_npc.level || obj.level || 3; + my_npc.init(); + my_npc.recount(); + my_npc.hp = my_npc.max_hp; + my_npc.mp = my_npc.max_mp; + FOLLOWER.STORES.set(me.id + "_" + my_npc.id, my_npc); + my_npc.master = me.id; + my_npc.master_name = me.name; + } +} +FOLLOWER.INIT = function (me, par) { + if (!par || !par.path) return; + var npc; + var id = me.id + "_" + par.id; + if (par.id) { + npc = FOLLOWER.STORES.get(id); + if (npc) return npc; + } + var obj = NPC.CLONE(par.path); + if (!obj) return; + npc = new FOLLOWER(); + for (var i = 0; i < SAVE_NUMPROP.length; i++) { + npc[SAVE_NUMPROP[i]] = obj[SAVE_NUMPROP[i]] || 0; + } + for (var i = 0; i < SAVE_STRPROP.length; i++) { + npc[SAVE_STRPROP[i]] = obj[SAVE_STRPROP[i]] || ""; + } + npc.on_makelove = obj.on_makelove; + npc.on_master_enter = obj.on_master_enter; + npc.equipment = obj.equipment; + npc.skills = obj.skills; + npc.items = obj.items; + npc.id = par.id; + npc.path = obj.path; + npc.level = obj.level || 3; + npc.init(); + npc.recount(); + FOLLOWER.STORES.set(id, npc); + npc.master = me.id; + npc.master_name = me.name; + return npc; +} +FOLLOWER.REPLACE = function (me, old, npc) { + if (!old || !npc) return; + var copys = ["str", "con", "dex", "int", "gender", "kar", "per", "name", "title", "desc", "on_master_learn", "on_master_enter"]; + for (var i = 0; i < copys.length; i++) { + old[copys[i]] = npc[copys[i]]; + } + if (!old.skills) old.skills = {}; + if (!old.equipment) old.equipment = []; + if (npc.equipment && npc.equipment[0]) { + if (old.equipment[0]) { + npc.items.push(npc.equipment[0]); + } else { + old.equipment[0] = npc.equipment[0]; + } + npc.equipment[0] = null; + } + if (!old.items) old.items = []; + if (npc.items && npc.items.length) { + for (var i = 0; i < npc.items.length; i++) { + old.items.push(npc.items[i]); + } + npc.items.length = 0; + } + + for (var sk in npc.skills) { + var oldSkill = old.skills[sk]; + if (oldSkill && oldSkill.addin && oldSkill.addin.length) + continue;//已经进阶的不覆盖 + if (!oldSkill || oldSkill.level < npc.skills[sk].level) { + old.skills[sk] = npc.skills[sk]; + } + } + if (npc.exp > old.exp) old.exp = npc.exp; + if (npc.pot > old.pot) old.pot = npc.pot; + if (npc.max_mp > old.max_mp) old.max_mp = npc.max_mp; + + + old.prop = {}; + old.init(); + if (old.status) { + for (var j = old.status.length - 1; j >= 0; j--) { + var item = old.status[j]; + old.change_buff(item, true, item.count); + } + } + old.recount(); + old.master_json = null; + old.color_name = null; + old.on_master_enter = npc.on_master_enter; + old.on_makelove = npc.on_makelove; + old.path = npc.path; + old.level = npc.level > old.level ? npc.level : old.level; + if (old.environment) { + old.environment.item_changed(old, true); + } + for (var i = 0; i < me.follower.length; i++) { + if (me.follower[i].id == old.id) { + me.follower[i].path = npc.path; + break; + } + } +} +FOLLOWER.GET = function (me, par) { + var id = me.id + "_" + par.id; + return FOLLOWER.STORES.get(id); +} +FOLLOWER.CREATE = function (me, par, callback) { + if (!par || !par.path) return; + var id = me.id + "_" + par.id; + var npc = FOLLOWER.STORES.get(id); + if (npc) return callback(npc); + +} +var SAVE_NUMPROP = ["str", "con", "dex", "int", "gender", "max_mp", "limit_mp", "exp", "pot", "kar", "per" + , "hp", "mp", "max_item_count", "money", 'level']; +var SAVE_STRPROP = ["id", "name", "title", "desc"]; +FOLLOWER.prototype.save = function (me) { + var str = ["prop:["]; + for (var i = 0; i < SAVE_NUMPROP.length; i++) { + str.push(this[SAVE_NUMPROP[i]] || 0); + str.push(","); + } + str.push("0],"); + var items = this.items || []; + str.push("items:["); + if (items) { + for (var i = 0; i < items.length; i++) { + if (i > 0) str.push(","); + items[i].save_db(str); + } + } + str.push("]"); + if (this.skills) { + str.push(",skills:"); + str.push(JSON.stringify(this.skills)); + } + if (this.temp) { + str.push(",temp:", this.format_temp(this.temp)); + } + if (this.settings) { + str.push(",settings:"); + str.push(JSON.stringify(this.settings)); + } + if (this.equipment) { + str.push(",eq:["); + for (var i = 0; i < this.equipment.length; i++) { + if (i > 0) str.push(","); + if (this.equipment[i]) this.equipment[i].save_db(str); + else str.push("null"); + } + str.push("]"); + } + return str.join(""); +} +FOLLOWER.SAVE = function (me) { + if (!me.follower) return "[]"; + var str = ["["]; + for (var i = 0; i < me.follower.length; i++) { + var item = me.follower[i]; + if (str.length > 1) str.push(","); + str.push('{path:"'); + str.push(me.follower[i].path); + str.push('",id:"'); + str.push(me.follower[i].id); + str.push('"'); + var npc = FOLLOWER.STORES.get(me.id + "_" + item.id); + if (npc) { + str.push(","); + str.push(npc.save(me)); + } + str.push('}'); + + } + str.push("]"); + return str.join(""); +} +var DIE_MSG = ["\n$N扑在地上挣扎了几下,腿一伸,口中喷出几口鲜血,死了!\n", + "\n$N大叫一声倒在地上,挣扎了几下,死了!\n", + "\n$N口中喷出几口鲜血,倒在地上,死了!\n"]; +FOLLOWER.prototype.die = function (killer) { + if (!this.environment) return; + if (this.on_die && this.on_die(killer) == false) { + this.hp = 1; + return false; + } + this.clear_status(); + this.send_room(DIE_MSG.random()); + var corpse = new CORPSE(); + corpse.init(this, false); + this.environment.item_changed(corpse, true); + this.environment.item_changed(this, false); + this.environment = null; +} + +FOLLOWER.prototype.heart_beat = function (dt) { + if (!this.hp) return; + // this.add_exp(this.grow_level, this.grow_level); + if (!this.fight_type) { + if (this.hp < this.max_hp) { + this.add_hp(parseInt(this.max_hp / 3)); + } + if (this.mp < this.max_mp) { + this.add_mp(parseInt(this.max_mp / 3)); + } + if (this.chat_msg) { + var r = this.random(10); + if (r > 7) + this.send_message(this.chat_msg.random()); + } + } + if (this.state && (!this.fight_type || this.state.allow_fight)) { + this.state.heat_count += 1; + if (this.state.heat_count >= this.state.rate) { + this.state.heat_count = 0; + if (this.state.on_enter(this) === false) { + this.set_state(null, true); + } + } + } +} +FOLLOWER.prototype.set_state = function (state, isauto) { + if (this.state && !state) { + if (this.state.on_stop) { + if (this.state.on_stop(this, isauto) == false) { + return; + } + } + } + this.state = state; + if (state) { + state.rate = state.rate || 1; + state.heat_count = 0; + state.start_time = Date.now(); + } + this.color_name = null; + this.environment && this.environment.item_changed(this, true); + this.master_json = null; +} + +FOLLOWER.prototype.query_mastercommands = function () { + if (this.master_json) return this.master_json; + var json = {}; + json.type = "item"; + json.desc = this.desc; + json.id = this.id; + json.name = this.name; + json.commands = []; + json.commands.push({ + cmd: "look " + this.id, + name: "查看" + }); + json.commands.push({ + cmd: "fight " + this.id, + name: "比试" + }); + json.commands.push({ + cmd: "score " + this.id, + name: "属性" + }); + json.commands.push({ + cmd: "pack " + this.id, + name: "背包" + }); + json.commands.push({ + cmd: "cha " + this.id, + name: "技能" + }); + json.commands.push({ + cmd: "team with " + this.id, + name: "组队" + }); + json.commands.push({ + cmd: "trade " + this.id, + name: "给" + this.call3() + "东西" + }); + if (this.state) { + json.commands.push({ + cmd: "dc " + this.id + " stopstate", + name: "停止" + this.state.title.replace('中', "") + }); + } + if (this.actions) { + for (var i = 0; i < this.actions.length; i++) { + json.commands.push({ + cmd: this.actions[i].cmd, + name: this.actions[i].name + }); + } + } + this.master_json = JSON.stringify(json) + return this.master_json; +} +FOLLOWER.prototype.query_commands = function (player) { + if (player.id == this.master) { + return this.query_mastercommands(player); + } + if (this.json) return this.json; + var json = {}; + json.type = "item"; + json.desc = this.desc; + json.id = this.id; + json.follower = true; + json.commands = []; + json.commands.push({ + cmd: "look " + this.id, + name: "查看" + }); + if (!this.no_fight) + json.commands.push({ + cmd: "fight " + this.id, + name: "比试" + }); + json.commands.push({ + cmd: "kill " + this.id, + name: "击杀" + }); + json.commands.push({ + cmd: "ask " + this.id + " about 主人", + name: "询问主人" + }); + this.json = JSON.stringify(json) + return this.json; +} +FOLLOWER.prototype.on_ask = function (me, par) { + switch (par) { + case "主人": + me.notify(this.name + "说道:我的主人就是" + this.master_name + "呀。"); + break; + } +} +FOLLOWER.prototype.on_teamin = function (me) { + if (!this.team) return; + for (var i = 0; i < this.team.length; i++) { + var tm = this.team[i]; + if (this.master == tm.id) { + this.do_follow(tm); + } + } +} +FOLLOWER.prototype.on_teamout = function (me) { + if (!this.team) return; + for (var i = 0; i < this.team.length; i++) { + var tm = this.team[i]; + if (this.master == tm.id) { + this.do_follow(null); + if (this.environment && this.environment.is_fb()) { + this.environment.item_changed(this, false, this.name + "离开了。"); + } + } + } +} +FOLLOWER.prototype.long_name = function () { + if (this.color_name) return this.color_name; + var str = []; + if (this.title) { + str.push(this.title); + str.push(" "); this.name; + } + str.push(this.name); + if (this.state) { + str.push("<" + this.state.title + ">"); + } + return this.color_name = str.join(""); + +} +FOLLOWER.prototype.on_enter = function (me) { + if (me.id == this.master) { + this.on_master_enter && this.on_master_enter(me); + } +} +FOLLOWER.prototype.on_master_leave = function (me, nextrm) { + if (this.state || !this.team || this.team != me.team) return false; + if (this.hp <= 0) return false; + if (me.environment === this.environment) return false; + + //如果去副本或者家里就跟 + if (nextrm.is_fb() || nextrm.parent.id == "home") { + return true; + } + + + //如果当前是副本就自己回去 + //if (this.environment.is_fb()) + // this.environment.item_changed(this, false, this.name + "离开了。"); + return false; +} \ No newline at end of file diff --git a/os/char/monster.js b/os/char/monster.js new file mode 100644 index 0000000..794934d --- /dev/null +++ b/os/char/monster.js @@ -0,0 +1,114 @@ + +require("../util/util.js"); +require("./character"); +MONSTER = function () { + this.hp = this.max_hp = 100; + this.mp = this.max_mp = 100; this.auto_pfm = true; + this.family = FAMILIES.MONSTER; + this.str = this.con = this.dex = this.int = 20; +} +MONSTER.inherits(CHARACTER); +MONSTER.prototype.can_speek = false; +MONSTER.prototype.init_skill = function () { + this.attack_skill = this.query_used_skill(BASE_SKILLS.BITE); + this.dodge_skill = this.query_used_skill(BASE_SKILLS.DODGE); + this.parry_skill = this.query_used_skill(BASE_SKILLS.PARRY); + this.force_skill = this.query_used_skill(BASE_SKILLS.FORCE); + this.noweapon_skill = this.attack_skill; +} +MONSTER.prototype.query_desc = function (me) { + return this.query_commands(me); +} +MONSTER.prototype.query_commands = function (player) { + + if (this.json) return this.json; + var json = {}; + json.type = "item"; + json.desc = this.name + "\n" + this.desc; + json.id = this.id; + json.commands = []; + json.commands.push({ + cmd: "kill " + this.id, + name: "击杀" + }); + if (this.actions) { + for (var cmd in this.actions) { + if (!this.actions[cmd].name) continue; + json.commands.push({ + cmd: cmd + " " + this.id, + name: this.actions[cmd].name + }); + } + } + this.json = JSON.stringify(json) + return this.json; +} +MONSTER.prototype.call3 = function () { + return "它"; +} + +MONSTER.prototype.destroy = function (msg) { + if (this.environment) { + this.environment.item_changed(this, false, msg); + } +} +MONSTER.prototype.die = function (killer) { + + if (!this.environment) return; + if (this.on_die && this.on_die(killer) === false) { + this.hp = 1; + return false; + } + this.hp = 0; + this.clear_status(); + this.send_message(this.name + "惨嚎一声,死了!"); + var corpse = new CORPSE(); + var isinfb = this.environment.is_fb(); + corpse.init(this, isinfb); + this.die_room = this.environment; + this.environment.item_changed(corpse, true); + this.environment.item_changed(this, false); + if (isinfb && this.score && killer) { + //副本分数 + killer.add_fbscore(this.score); + } + this.on_died && this.on_died(killer, corpse); + WORLD.auto_get(killer, corpse, this); + if (killer && killer.attack_skill && killer.attack_skill.on_enemy_die) { + killer.attack_skill.on_enemy_die(killer, this); + } +} +MONSTER.prototype.query_part = function () { + return MONSTER_PARTS.random(); +} +MONSTER.prototype.heart_beat = function (dt) { + if (!this.fight_type && this.hp > 0) { + if (this.hp < this.max_hp) { + this.add_hp(parseInt(this.max_hp / 2)); + } + if (this.mp < this.max_mp) { + this.add_mp(parseInt(this.max_mp / 2)); + } + if (this.chat_msg) { + var r = this.random(10); + if (r > 5) + this.send_message(this.chat_msg.random()); + } + + + } + +} +var MONSTER_PARTS = [ + { name: "左爪", hert: 0.8, crit: 0 }, + { name: "右爪", hert: 0.8, crit: 0 }, + { name: "后腿", hert: 0.85, crit: 0 }, + { name: "小腹", hert: 0.91, crit: 3 }, + { name: "胸前", hert: 0.95, crit: 4 }, + { name: "背部", hert: 0.97, crit: 4 }, + { name: "头部", hert: 1.2, crit: 10 }, + { name: "颈部", hert: 1.1, crit: 5 }, + { name: "前肢", hert: 0.85, crit: 1 }, + { name: "腰间", hert: 0.99, crit: 5 }, +]; + diff --git a/os/char/npc.js b/os/char/npc.js new file mode 100644 index 0000000..2ef84f6 --- /dev/null +++ b/os/char/npc.js @@ -0,0 +1,227 @@ + +NPC = function () { + this.hp = this.max_hp = 100; + this.mp = this.max_mp = 100; + this.str = this.con = this.dex = this.int = this.per = this.age = 20; + this.family = FAMILIES.NONE; + this.auto_pfm = true; +} +NPC.inherits(CHARACTER); +NPC.prototype.set_chat_msg = function (items, chance) { + if (items) { + this.chat_msg = items; + //this.chat_chance = chance || 10; + } +} +NPC.prototype.do_chat_msg = function () { + if (!this.is_fighting() && this.is_living && this.chat_msg) { + this.do_say(this.chat_msg.random()); + } +} +NPC.prototype.format_equipments = function (call3, str, eqcmd) { + if (this.equipment && this.equipment.length) { + var eqstr = []; + for (var i = 0; i < this.equipment.length; i++) { + var item = this.equipment[i]; + if (!item) continue; + eqstr.push("◆", item.color_name, "\n"); + } + if (eqstr.length) { + return str.push(call3, "装备着:\n", eqstr.join("")); + } + } + str.push(call3, "穿着一件布衣。\n"); +} + +NPC.prototype.set_goods = function () { + if (!arguments.length) return; + this.sell_list = []; + for (var i = 0; i < arguments.length; i++) { + var item = arguments[i]; + var obj = OBJ.CREATE(item); + if (!obj) continue; + obj.count = -1; + this.sell_list.push(obj); + } +} +NPC.prototype.query_commands = function (player) { + + if (this.json) return this.json; + + this.json = this.query_commands_json(player, false); + return this.json; +} + +NPC.prototype.query_commands_json = function (player, isyb) { + var json = {}; + json.type = "item"; + json.desc = this.desc; + json.id = this.id; + json.name = this.name; + json.commands = []; + json.commands.push({ + cmd: "look " + this.id, + name: "查看" + }); + if (!this.no_fight) + json.commands.push({ + cmd: "fight " + this.id, + name: "比试" + }); + json.commands.push({ + cmd: "kill " + this.id, + name: "击杀" + }); + if (this.on_master) { + json.commands.push({ + cmd: "bai " + this.id, + name: "拜师" + }); + } + if (this.on_checkskill || this.on_master) { + json.commands.push({ + cmd: "cha " + this.id, + name: "学习" + }); + json.master = true; + } + if (this.sell_list) { + json.commands.push({ + cmd: "list " + this.id, + name: "购买" + }); + json.trader = true; + } + if (this.question) { + for (var cmd in this.question) { + json.commands.push({ + cmd: "ask " + this.id + " about " + cmd, + name: "询问" + cmd + }); + } + } + if (this.actions) { + for (var cmd in this.actions) { + if (!this.actions[cmd].name) continue; + json.commands.push({ + cmd: cmd + " " + this.id, + name: this.actions[cmd].name + }); + } + } + return JSON.stringify(json); +} +NPC.prototype.update_action = function (acts) { + this.json = null; + this.actions = acts; +} + +var DIE_MSG = ["\n$N扑在地上挣扎了几下,腿一伸,口中喷出几口鲜血,死了!\n", + "\n$N大叫一声倒在地上,挣扎了几下,死了!\n", + "\n$N口中喷出几口鲜血,倒在地上,死了!\n"]; +NPC.prototype.die = function (killer) { + if (!this.environment) return; + if (this.on_die && this.on_die(killer) == false) { + this.hp = 1; + return false; + } + this.hp = 0; + this.clear_status(); + this.send_room(DIE_MSG.random()); + this.clear_follow(); + var corpse = new CORPSE(); + + var isinfb = this.environment.is_fb(); + corpse.init(this, isinfb); + this.die_room = this.environment; + this.environment.item_changed(corpse, true); + this.environment.item_changed(this, false); + if (isinfb && this.score && killer && killer.add_fbscore) { + //副本分数 + killer.add_fbscore(this.score); + } + if (!isinfb && !this.no_refresh && !this.master && !this.die_room.is_shadow) { + this.call_out(this.relive, this.on_master ? 60000 : 300000); + } + this.on_died && this.on_died(killer, corpse); + WORLD.auto_get(killer, corpse, this); + if (killer && killer.attack_skill && killer.attack_skill.on_enemy_die) { + killer.attack_skill.on_enemy_die(killer, this); + } +} + +NPC.prototype.relive = function () { + if (!this.die_room) return; + var room = ROOM.Get(this.die_room.path); + var obj = room.find_obj_bypath(this.path); + if (obj) return; + obj = NPC.CLONE(this.path); + room.item_changed(obj, true); + this.die_room = null; + this.equipment = null; + this.items = null; + this.skills = null; +} +NPC.prototype.destroy = function (msg) { + if (this.environment) { + this.environment.item_changed(this, false, msg); + } + this.clear_follow(); + +} +NPC.prototype.heart_beat = function (dt) { + + if (!this.fight_type) { + if (this.hp < this.max_hp) { + this.add_hp(parseInt(this.max_hp / 2)); + } + if (this.mp < this.max_mp) { + this.add_mp(parseInt(this.max_mp / 2)); + } + if (this.chat_msg) { + if (this.random(10) > 8) + this.send_message(this.chat_msg.random()); + } + this.on_heart_beat && this.on_heart_beat(dt); + } else if (this.hp <= 0) { + var eny = this.query_enemy(); + if (!eny) { + this.hp = 1; + this.fight_type = 0; + } + } + +} + + + +NPC.CREATE = function (path, env, oncreate, count) { + if (!path || !env) return; + + + if (env.environment) env = env.environment; + count = count || 1; + let obj = null; + for (let i = 0; i < count; i++) { + obj = NPC.CLONE(path); + env.item_changed(obj, true); + if (oncreate) oncreate(obj); + } + return obj; +} +NPC.CLONE = function (path) { + let base = NPC.GET(path); + let item = Object.create(base); + item.clone(); + return item; +} +NPC.GET = function (path) { + let base = WORLD.NPC_STROE.get(path); + if (!base) { + base = BASE.CREATE(__PATH.NPC, path); + if (!base) throw new Error('没有人物' + path + "的定义。"); + //这里会自己调用create方法存储到NPC_STROE,记住了吗 + } + return base; +} \ No newline at end of file diff --git a/os/char/user.js b/os/char/user.js new file mode 100644 index 0000000..70032d9 --- /dev/null +++ b/os/char/user.js @@ -0,0 +1,845 @@ +require("./character.js"); +USER = function () { + this.socket = null; + this.family = FAMILIES.NONE; + this.max_item_count = 20; + this.max_store_count = 20; + this.money = 0; + this.request_count = 0; + this.cash_money = 0; + this.score = 0; + this.follower = null; + this.password = ""; + this.loginTime = 0; + this.id_address = null; + this.user_level = 0; + this.eq_group = 0; +}; +USER.inherits(CHARACTER); +USER.prototype.is_player = true; + +USER.prototype.notify = function (text) { + //玩家不能接收消息的状态 不发送 + if (this.socket && !this.is_faint && text && text.length < 30240) + this.socket.send(text); +} +USER.prototype.send = function (text) { + //直接发送消息 不管玩家状态 + if (this.socket && text && text.length < 30240) { + this.socket.send(text); + } +} +USER.prototype.notify_fail = function (text) { + if (this.socket && !this.is_faint) + this.socket.send(text); + return false; +} + +USER.prototype.send_warn = function (content, cmds, time) { + var str = ["{type:\"warn\",content:\""]; + str.push(content); + str.push("\""); + if (time) { + str.push(",time:"); + str.push(time); + } + str.push(",cmds:["); + for (var i = 0; i < cmds.length; i += 2) { + if (i > 0) str.push(","); + str.push("{cmd:\""); + str.push(cmds[i]); + str.push("\",name:\""); + str.push(cmds[i + 1]); + str.push("\"}"); + } + str.push("]}"); + this.send(str.join("")); +} + +USER.prototype.send_commands = function () { + var str = ["{type:\"cmds\",items:["]; + for (var i = 0; i < arguments.length; i += 2) { + if (i > 0) str.push(","); + str.push("{cmd:\""); + str.push(arguments[i]); + str.push("\",name:\""); + str.push(arguments[i + 1]); + str.push("\"}"); + } + str.push("]}"); + this.send(str.join("")); +} +USER.prototype.is_connect = function () { + return this.socket !== null; +} +USER.prototype.send_loginmessage = function () { + if (!this.login_message) { + var str = ['{type:"login"']; + if (this.settings) { + str.push(",setting:") + str.push(JSON.stringify(this.settings)); + this.no_message = this.settings['no_message'] == 1; + } + str.push(",id:\""); + str.push(this.id, '",level:', this.level); + str.push("}"); + this.login_message = str.join(""); + } + + this.send(this.login_message) +} +USER.prototype.relogin = function (newUser) { + if (!newUser.socket) return; + newUser.socket.user = null; + this.socket = newUser.socket; + newUser.socket = null; + this.socket.user = this; + this.send_loginmessage(); + + if (!this.environment) { + var rm = ROOM.Get(this.quit_room); + if (!rm) { + return this.send("出现错误,请联系管理员报告BUG,谢谢!"); + } + this.environment = rm; + } + this.send(this.environment.to_json()); + this.environment.send_exits(this); + this.send(this.environment.items_to_json()); + // if (!WORLD.is_end_cross(this)) { + this.send_room(this.name + "重新连线。"); + if (this.environment.on_relogin) { + this.environment.on_relogin(this); + } + // } + this.disconnect_time = 0; + this.check_state(); + this.on_skillchanged(); +} +USER.prototype.ip = function () { + return this.socket.remoteAddress; +} +USER.prototype.port = function () { + return this.socket.remotePort; +} +USER.prototype.quit = function () { + var rm = this.environment; + if (this.environment) { + + this.team_out("离开了游戏,自动退出队伍"); + this.environment.item_changed(this, false, this.name + "离开了游戏。"); + this.environment = rm; + this.clear_follow(); + this.environment.clear_copy(this); + this.environment.parent.on_leaved(this); + } + this.environment = null; + this.clear_status(); + this.environment = rm; + WORLD.login_out(this); + this.environment = null; + + this.clear_home(); + if (this.socket) { + this.socket.user = null; + this.socket = null; + } +} +USER.prototype.in_world = function () { + //判断是否连线进入过游戏, + return !!this.environment && !!this.socket; +} +USER.prototype.disconnect = function (isreplace) { + if (this.environment && this.socket) { + // this.send_message(this.name + "断线了。"); + if (isreplace) + this.send("有人使用你的角色从别的地址登陆游戏,请重新登陆"); + } + this.disconnect_time = Date.now(); + if (this.socket) { + let socket = this.socket; + this.socket = null; + socket.user = null; + socket.end(); + //if (!socket.destroyed) + // socket.destroy(); + } +} +USER.prototype.loadData = function (role) { + this.id = role.id; + this.name = role.name; + this.level = role.level; + //this.title = role.title;de + //role.data = role.data.toString(); + var data = JSON.toObject(role.data); + for (var i = 0; i < SAVE_NUMPROP.length; i++) { + this[SAVE_NUMPROP[i]] = data.prop[i] || 0; + } + this.quit_room = data.quit_room; + this.items = this.read_items(data.items); + this.stores = this.read_items(data.stores); + this.books = data.books ?? []; + this.equipment = this.read_items(data.eq); + this.settings = data.settings; + + this.skills = data.skills ?? {}; + this.eq_groups = data.eq_groups; + this.sk_groups = data.sk_groups ?? [null, [], []]; + this.temp = data.temp; + this.read_titles(data.titles); + if (data.follower) { + this.follower = []; + FOLLOWER.INIT_FROM_USER(this, data.follower); + for (var i = 0; i < data.follower.length; i++) { + this.follower.push({ + id: data.follower[i].id, + path: data.follower[i].path + }); + } + } + var fam = this.query_temp("family"); + if (fam) { + this.family = FAMILIES[fam] || FAMILIES.NONE; + } + this.user_level = role.user_level; +} +USER.prototype.read_titles = function (titles) { + this.titles = []; + if (!titles) return; + for (let item of titles) { + this.titles.push({ + title: item[0], type: item[1], + use: item[2] === 1 + }); + if (item[2]) { + this.title = item[0]; + } + } +} +USER.prototype.read_items = function (items) { + var objs = []; + if (!items) return objs; + for (var i = 0; i < items.length; i++) { + var item = items[i]; + if (!item) { + objs.push(null); + continue; + } + var obj = OBJ.CREATE(item[0]); + if (obj) { + obj.load_db(item); + obj.on_load(this); + objs.push(obj); + } + + } + return objs; +} +USER.prototype.do_login = function () { + this.init(); + this.recount(); + this.long_name(); + WORLD.STATS.checkStats(this); + this.send_loginmessage(); + if (this.family) this.family.on_login(this); + var rm = ROOM.Get(this.query_temp("new") ? "new/new1" : this.quit_room); + if (!rm || rm.is_fb()) rm = ROOM.Get(DEFAULT_ROOM); + if (rm.is_copy()) { + var copy_room = rm.query_copy2(this); + if (copy_room) { + this.moveto(copy_room, null, this.name + "连线进入这个世界。"); + } else { + if (this.query_temp("new")) { + //还没完成新手教程的,从头开始 + this.set_temp("new", 1); + this.items = [];//清理掉之前的物品 + this.exp = this.pot = this.money = 0; + } + copy_room = rm.create_copy2(this); + this.moveto(copy_room); + } + //如果在副本副本下线,不可能 + + } else { + this.moveto(rm, null, this.name + "连线进入这个世界。"); + } + this.check_state(); +} +var DEFAULT_ROOM = "yz/wumiao"; + + +var SAVE_NUMPROP = ["str", "con", "dex", "int", "gender", "max_mp", "limit_mp", "exp", "pot", "kar", "per" + , "hp", "mp", "max_item_count", "money", "reg_time", + "max_store_count", "cash_money", 'eq_group']; + +USER.prototype.getData = function () { + var str = ["{prop:["]; + for (var i = 0; i < SAVE_NUMPROP.length; i++) { + str.push(this[SAVE_NUMPROP[i]]); + str.push(","); + } + str.push(0); + str.push("],quit_room:\""); + if (this.environment) { + if (this.environment.is_fb() || this.environment.no_save + || this.environment.parent.no_save) { + str.push(this.query_temp("enter_room")); + } else { + str.push(this.environment.path); + } + } else { + str.push(this.query_temp("enter_room", DEFAULT_ROOM)); + } + str.push("\""); + var items = this.items; + if (items) { + str.push(",items:["); + for (let i = 0; i < items.length; i++) { + if (i > 0) str.push(","); + items[i].save_db(str); + } + str.push("]"); + } + items = this.stores; + if (items) { + str.push(",stores:["); + for (let i = 0; i < items.length; i++) { + if (i > 0) str.push(","); + items[i].save_db(str); + } + str.push("]"); + } + items = this.books; + if (items && items.length > 0) { + str.push(',books:["', items.join('", "'), '"]'); + } + if (this.skills) { + str.push(",skills:"); + str.push(JSON.stringify(this.skills)); + } + str.push(",temp:", this.format_temp(this.temp)); + if (this.settings) { + str.push(",settings:"); + str.push(JSON.stringify(this.settings)); + } + if (this.equipment) { + str.push(",eq:["); + for (var i = 0; i < this.equipment.length; i++) { + if (i > 0) str.push(","); + if (this.equipment[i]) this.equipment[i].save_db(str); + else str.push("null"); + } + str.push("]"); + } + if (this.titles) { + str.push(",titles:["); + for (var i = 0; i < this.titles.length; i++) { + if (i > 0) str.push(","); + var item = this.titles[i]; + str.push('["', item.title, '","', item.type, '"'); + if (item.use) str.push(',1'); + str.push(']'); + } + str.push("]"); + } + if (this.follower) { + str.push(",follower:"); + str.push(FOLLOWER.SAVE(this)); + } + str.push(',eq_groups:['); + for (let i = 0; i < this.eq_groups.length; i++) { + if (i > 0) str.push(','); + if (i === this.eq_group || !this.eq_groups[i]) str.push('[]'); + else str.push('["', this.eq_groups[i].join('","'), '"]'); + } + str.push('],sk_groups:['); + for (let i = 0; i < this.sk_groups.length; i++) { + if (i > 0) str.push(','); + if (!this.sk_groups[i]) str.push('0'); + else str.push('["', this.sk_groups[i].join('","'), '"]'); + } + + str.push("]}"); + + var role = {}; + role.id = this.id; + role.userid = this.userid; + role.name = this.name; + role.level = this.level; + role.title = this.title || this.get_level_desc(); + role.data = str.join(""); + return role; +} + + +USER.prototype.save = function () { + + WORLD.DB.saveRole(this.getData()); +} +USER.prototype.die = function (killer) { + if (this.on_die && this.on_die(killer) === false) { + this.hp = 1; + return false; + } + this.clear_status(); + + this.hp = 0; + this.mp = 0; + + this.send_room(DIE_MSG.random()); + var env = this.environment; + if (env.items.length < 10) { + var corpse = new CORPSE(); + corpse.init(this); + env.item_changed(corpse, true); + } + env.item_changed(this, false); + this.environment = env; + this.check_state(); + WORLD.on_user_die(this, killer); + this.on_died(killer); +} +USER.prototype.on_died = function () { + +} +USER.prototype.check_state = function () { + if (this.hp <= 0) { + if (this.state) this.set_state(null); + this.send('{type:"die",commands:[{cmd:"relive",name:"去武庙复活"},{cmd:"relive locale",name:"原地复活"}]}'); + } else { + if (this.state) this.set_state(this.state); + } + + +} +USER.prototype.query_commands = function (player) { + if (this.commands_json) return this.commands_json; + var json = {}; + json.type = "item"; + json.desc = this.long_name(); + json.id = this.id; + json.commands = []; + json.commands.push({ + cmd: "look " + this.id, + name: "查看" + }); + if (player != this) { + if (!this.no_fight) + json.commands.push({ + cmd: "fight " + this.id, + name: "比试" + }); + json.commands.push({ + cmd: "kill " + this.id, + name: "击杀" + }); + + json.commands.push({ + cmd: "team add " + this.id, + name: "邀请组队" + }); + if (this.level > 1 && !this.query_setting("ban_master") && !this.query_temp("tudi") && !this.query_temp("shifu")) { + json.commands.push({ + cmd: "baishi " + this.id, + name: "拜师" + }); + } + } + this.commands_json = JSON.stringify(json) + return this.commands_json; +} +USER.prototype.query_title = function (type) { + if (!this.titles) return null; + for (var i = 0; i < this.titles.length; i++) { + if (this.titles[i].type == type) { + return this.titles[i].title; + } + } +} +USER.prototype.add_title = function (title, type) { + if (!this.titles) this.titles = []; + var obj = { title: title, type: type }; + for (var i = 0; i < this.titles.length; i++) { + if (this.titles[i].type == type) { + obj.use = this.titles[i].use; + this.titles.splice(i, 1); + break; + } + } + if (obj.title) { + if (!this.titles.length) obj.use = true; + this.titles.push(obj); + } + if (obj.use) { + if (!title) { + if (this.titles.length) { + this.titles[0].use = true; + title = this.titles[0].title; + } + } + this.title = title; + this.color_name = null; + if (this.environment) + this.environment.item_changed(this, true); + } + +} +USER.prototype.query_setting = function (name) { + if (!this.settings) return 0; + return this.settings[name] || 0; +} +USER.prototype.set_setting = function (name, value) { + if (!this.settings) this.settings = {}; + + if (!value || value == "0") { + delete this.settings[name]; + } else { + if (value == "1") value = 1; + this.settings[name] = value; + } + + this.login_message = null; +} +USER.prototype.heart_beat = function (dt) { + this.request_count = 0; + if (this.state && (!this.fight_type || this.state.allow_fight)) { + this.state.heat_count += 1; + if (this.state.heat_count >= this.state.rate) { + this.state.heat_count = 0; + if (this.state.on_enter(this, dt) === false) { + this.set_state(null, true); + } + } + } + this.on_heart_beat && this.on_heart_beat(dt); + if (this.disconnect_time) { + //如果断线 在挂机就一天,没有就5分钟下线 + if (dt - this.disconnect_time > (this.state ? 86400000 : 3600000)) { + return this.quit(); + } + } +} +USER.prototype.set_state = function (state, isauto) { + if (this.state && !state) { + if (this.state.on_stop) { + if (this.state.on_stop(this, isauto) == false) { + return; + } + } + this.send("{type:\"state\"}"); + } + this.state = state; + if (state) { + state.rate = state.rate || 1; + state.heat_count = 0; + state.start_time = Date.now(); + var msg = "{type:\"state\",state:\"你正在" + state.title + "\""; + if (state.desc) { + msg += ",desc:" + state.desc; + } + if (state.no_stop) { + msg += ",no_stop:true"; + } + if (state.commands) { + msg += ",commands:" + state.commands; + } + this.send(msg + "}"); + } + this.color_name = null; + if (this.environment) + this.environment.item_changed(this, true); +} + +USER.prototype.get_state = function () { + var str = ""; + if (!this.socket) str += "<断线中>"; + if (this.state) str += ("<" + this.state.title + ">"); + return str; +} +const LEVELS_TITLES = ["普通百姓", "武士", "武师", "宗师", "武圣", "武帝", "武神"]; +USER.prototype.long_name = function () { + if (!this.color_name) { + var cc = this.get_level_color(); + var str = []; + if (cc) { + str.push("<"); + str.push(cc); + str.push(">"); + } + if (this.title) { + str.push(this.title); + str.push(" "); + } + if (!this.title || this.level > 0) { + str.push(LEVELS_TITLES[this.level]); + str.push(" "); + } + str.push(this.name); + if (cc) { + str.push(""); + } + this.color_name = str.join(""); + this.commands_json = null; + } + return this.color_name + this.get_state(); +} + + +USER.prototype.init_tasks = function () { + for (var i = 0; i < WORLD.TASKS.length; i++) { + var task = WORLD.TASKS[i]; + task.on_start && task.on_start(this); + } +} +USER.prototype.query_jingli = function () { + var expend = this.query_temp("ex_jl") || 0; + return 200 - expend + (this.query_temp("add_jl") || 0); +} +const jclimits = [1000, 2000, 3000, 5000, 7000, 10000, 15000]; +USER.prototype.query_jclimit = function () { + return jclimits[this.level] || 1000; +} + + +USER.prototype.add_obj = function (obj, count) { + if (!obj) return; + if (typeof obj == "string") { + obj = OBJ.clone_to(obj, this, count); + if (!obj) return; + } else { + obj = this.push_item(obj); + } + + this.items_changed(obj); + + obj.notify_action(this, true); + return obj; +} +USER.prototype.remove_obj = function (obj, count) { + if (typeof obj == "string") { + obj = this.find_obj(obj); + } + if (!obj) return; + count = count || obj.count || 1; + var newobj = this.remove_item(obj, count); + if (newobj == obj) { + + obj.notify_action(this, false); + } + this.items_changed(obj, count); + return newobj; +} +USER.prototype.items_changed = function (item, drop_count) { + + if (drop_count) { + this.send('{type:"dialog",dialog:"pack",id:"' + item.id + '",remove:' + drop_count + ',money:' + this.money + '}'); + } else { + if (item.is_money) { + return this.send('{type:"dialog",dialog:"pack",money:' + this.money + '}'); + } + var str = ['{type:"dialog",dialog:"pack",']; + + + str.push('name:"'); + str.push(item.color_name); + str.push('",id:"'); + str.push(item.id); + str.push('",count:'); + str.push(item.count); + str.push(',grade:'); + str.push(item.grade); + str.push(',unit:"'); + str.push(item.unit); + str.push('"'); + if (item.is_equipment) { + str.push(',can_eq:1'); + } + if (item.on_use) { + str.push(',can_use:1'); + } + if (item.on_study) { + str.push(',can_study:1'); + } + if (item.on_open) { + str.push(',can_open:1'); + } + if (item.combine_count) { + str.push(',can_combine:' + item.combine_count); + } + str.push(',value:'); + str.push(item.transable ? item.value : 0); + str.push(",money:"); + str.push(this.money); + str.push('}'); + this.send(str.join("")); + } +} + +//初始化人物使用的技能 +USER.prototype.on_skillchanged = function () { + var str = ["{type:\"perform\",skills:["]; + if (this.skills) { + var bases = ["", "force", "unarmed", "dodge", "parry", "throwing"]; + var weapon = this.query_weapon_type(), base_type = null; + if (weapon != WEAPON_TYPE.NONE) bases[0] = weapon; + for (var i = 0; i < bases.length; i++) { + base_type = bases[i]; + if (!base_type) continue; + var base_skill = this.skills[base_type]; + if (base_skill) { + var sp_skill = SKILL.get(base_skill.enable_skill || base_type), pfmitem = null; + if (sp_skill && sp_skill.pfm) { + let sk_level = this.query_skill(base_skill.enable_skill || base_type, 0); + for (var p in sp_skill.pfm) { + pfmitem = sp_skill.pfm[p]; + if (pfmitem.check && !pfmitem.check(this, + sk_level, base_type)) continue; + if (pfmitem.enable_skill && pfmitem.enable_skill != base_type) continue; + if (str.length > 1) str.push(","); + str.push("{id:\""); + str.push(base_type + "." + p); + str.push("\",name:\""); + str.push(pfmitem.query_name(this, base_type)); + str.push("\""); + if (pfmitem.distime) { + str.push(",distime:"); + str.push(pfmitem.query_distime(this)); + } + str.push("}"); + } + } + pfmitem = this.query_ref_skill(this.skills[base_skill.enable_skill]); + if (pfmitem && pfmitem.enable_skill && pfmitem.enable_skill == bases[i]) { + if (str.length > 1) str.push(","); + str.push("{id:\""); + str.push(bases[i] + ".ref"); + str.push("\",name:\""); + str.push(pfmitem.query_name(this, base_type)); + str.push("\""); + if (pfmitem.distime) { + str.push(",distime:"); + str.push(pfmitem.query_distime(this, this.query_skill(base_skill.enable_skill), true)); + } + str.push("}"); + } + } + } + } + str.push("]"); + str.push("}"); + this.send(str.join("")); +} +USER.prototype.go_home = function () { + let my_room = this.query_home(); + this.moveto(my_room, this.name + "向里面走去。"); +} +USER.prototype.query_home = function (rm_name) { + let home = this.query_temp("home"); + if (!home) return null; + if (!rm_name) rm_name = home == 1 ? "home/danjian" : "home/yuanzi"; + let rm = ROOM.Get(rm_name); + let my_room = rm.query_copy2(this); + if (!my_room) { + my_room = rm.create_copy2(this); + } + return my_room; +} + +USER.prototype.add_score = function (val) { + if (!val) return; + this.score += val; + WORLD.STATS.updateScore(this); +} +USER.prototype.add_money = function (val) { + let money = parseInt(this.money + val); + if (!(money >= 0)) return false; + this.money = money; + //this.send(`{"type":"dialog","dialog":"pack","money":${money}}`); + return true; +} +USER.prototype.add_cash = function (count, desc) { + if (!(count > 0 || count < 0)) return; + this.cash_money += count; + WORLD.log(this, count, desc); + if (count >= 0) { + this.notify("你获得了" + count + "元宝。"); + } + this.send(`{"type":"dialog","dialog":"shop","money":[${this.money},${this.cash_money}]}`); + +} + +USER.prototype.query_cash = function (is_cash) { + return this.cash_money; +} +USER.prototype.can_follow = function (npc) { + if (!this.follower) this.follower = []; + var max = this.query_temp("max_follower") || 3; + if (this.follower.length >= max) return false; + for (var i = 0; i < this.follower.length; i++) { + if (this.follower[i].path == npc.path) { + return false; + } + } + return true; +} +USER.prototype.add_follower = function (npc) { + if (!this.can_follow(npc)) return false; + var item = { + path: npc.path, + id: npc.id + }; + this.follower.push(item); + FOLLOWER.INIT(this, item); + return true; +} +USER.prototype.clear_home = function (clear_follower = true) { + var home = ROOM.Get("home/yuanzi"); + if (home) { + home = home.query_copy(this.id) + if (home) + home.clear_copy(this); + } + if (clear_follower) + FOLLOWER.CLEAR(this); + else + FOLLOWER.RESET(this); +} + +USER.prototype.clear_distime = function (pfmid) { + if (!this.temp) return; + if (pfmid) { + this.temp["pfm/" + pfmid] = null; + this.send('{type:"clearDistime",id:"' + pfmid + '"}'); + } else { + for (var key in this.temp) { + if (key.startsWith("pfm/")) { + this.temp[key] = null; + } + } + this.send('{type:"clearDistime"}'); + } +} +var DIE_MSG = ["\n$N扑在地上挣扎了几下,腿一伸,口中喷出几口鲜血,死了!\n", + "\n$N大叫一声倒在地上,挣扎了几下,死了!\n", + "\n$N口中喷出几口鲜血,倒在地上,死了!\n"]; + +USER.prototype.add_combat_prop = function (name, val) { + this.add_prop(name, val); + if (!this.combat_props) this.combat_props = []; + this.combat_props.push([name, val]); + +} + + +USER.prototype.clear_combat_prop = function (name, val) { + if (this.combat_props) { + for (let i = 0; i < this.combat_props.length; i++) { + this.add_prop(this.combat_props[i][0], -this.combat_props[i][1]); + } + this.combat_props = null; + this.recount(); + this.notify_hp(); + } +} \ No newline at end of file diff --git a/os/command.js b/os/command.js new file mode 100644 index 0000000..cd6c831 --- /dev/null +++ b/os/command.js @@ -0,0 +1,47 @@ +/* +所有命令的基类, +自动加载所有定义在__COMMAND文件夹下的命令文件 +*/ + + +COMMAND = function () { + this.allow_fight = true; + this.allow_level = 0; +} + +COMMAND.inherits(BASE); +//将命令绑定到某些对象上 调用obj.do_commandname(); +COMMAND.prototype.for_item = function (item, name) { + if (this.exec) { + name = name || this.command; + item.prototype["do_" + name] = this.exec; + } +} +COMMAND.prototype.create = function (fname) { + // console.error("command %s success", fname); + if (this.command) { + var str = this.command.split(','); + for (var i = 0; i < str.length; i++) { + if (WORLD.COMMANDS[str[i]]) console.error("command %s 重复", fname); + WORLD.COMMANDS[str[i]] = this; + } + } else { + console.error("command %s not have command name", fname); + } +} +COMMAND.prototype.update = function () { + if (this.command) { + var str = this.command.split(','); + for (var i = 0; i < str.length; i++) { + WORLD.COMMANDS[str[i]] = this; + } + } else { + console.error("command %s not have command name", fname); + } +} +COMMAND.DO = function (cmd, par1, par2, par3) { + var cmd = WORLD.COMMANDS[cmd]; + if (cmd) { + cmd.enter(null, par1, par2, par3); + } +} \ No newline at end of file diff --git a/os/const.js b/os/const.js new file mode 100644 index 0000000..9b0c23a --- /dev/null +++ b/os/const.js @@ -0,0 +1,116 @@ +SKILL_TYPES = { + BASE: 0, + SKILL: 1, + KNOWLEDGE: 2 +}; +BASE_SKILLS = { + FORCE: "force", + DODGE: "dodge", + PARRY: "parry", + BITE: "bite" +}; + +EQUIP_TYPE = { + WEAPON: 0, + CLOTH: 1, + SHOES: 2, + HEAD: 3, + CAPE: 4, + RING: 5, + NECKLACE: 6,//项链 + JEWELS: 7,//饰品 + WRIST: 8,//护腕 + WAIST: 9,//腰带 + THROWING: 10// +} +WEAPON_TYPE = { + NONE: "unarmed", + SWORD: "sword", + BLADE: "blade", + STAFF: "staff", + CLUB: "club", + WHIP: "whip", + THROWING: "throwing" +} +PROPERTIES = { + "con1": "先天根骨", + "dex1": "先天身法", + "int1": "先天悟性", + "str1": "先天臂力", + "con": "根骨", + "dex": "身法", + "int": "悟性", + "str": "臂力", + "fy": "防御", + "per": "容貌", + "age": "年龄", + gj: "攻击", + ds: "躲闪", + zj: "招架", + mz: "命中", + bj_per: "暴击", + limit_mp: "内力上限", + gjsd: "攻击速度", + gjsd_per: "攻击速度", + mz_per: "命中", + max_hp: "气血", + max_mp: "内力", + releasetime: "绝招释放时间", + distime: "绝招冷却时间", + expend_mp: "内力消耗", + releasetime_per: "绝招释放时间", + distime_per: "绝招冷却时间", + expend_mp_per: "内力消耗", + add_sh_per: "最终伤害", + add_bjsh_per: "暴击伤害", + diff_sh_per: "伤害减免", + diff_sh: "受到的伤害减少", + diff_fy_per: "忽视对方防御", + fy_per: "防御", + zj_per: "招架", + gj_per: "攻击", + ds_per: "躲闪", + hp_per: "气血", + study_per: "学习效率", + dazuo_per: "打坐效率", + lianxi_per: "练习效率", + busy: "忙乱时间", + busy_per: "忙乱时间", + diff_busy: "忽视忙乱", + diff_busy_per: "忽视忙乱", + diff_bj: "暴击抵抗", + add_sh: "伤害增加", + diff_downside: "负面状态抵抗", + diff_downside_per: "负面状态抵抗", + dazuo: "打坐效率", + + diff_sh_per2: "伤害减免", + diff_fy_per2: "伤害减免", + recover_per: "疗伤效果", + + lianyao1: "炼药效率", + lianyao2: "丹药产出", + + lianyao_exp_per: "炼药获得经验", + no_fy: "无法防御", + no_pfm: "禁止绝招", + kuang_exp: "挖矿经验", + kuang_pot: "挖矿潜能", + + diaoyu_exp: "钓鱼经验", + diaoyu_pot: "钓鱼潜能", + + diaoyu1: "钓鱼效率", + kuang1: "挖矿效率", + caiyao1: "采药效率", + + caiyao_exp: "采药经验", + caiyao_pot: "采药潜能", + + + xiulian_exp: "闭关经验", + shuangxiu: "双修效率", + fenjie: "分解获得的玄晶", + +}; + diff --git a/os/data.js b/os/data.js new file mode 100644 index 0000000..9225acc --- /dev/null +++ b/os/data.js @@ -0,0 +1,123 @@ + +module.exports = { + parties: new Map(), + PAIMAI: new Map(), + temp: {}, + save: function () { + + let str = ["{"]; + this.save_temp(str); + this.on_save(str); + str.push('}'); + return WORLD.DB.saveData(str.join("")); + }, + temp_replacer: function (key, value) { + if (value.e) { + + } + + return value; + }, + save_temp: function (str) { + str.push('temp:', JSON.stringify(this.temp)); + }, + load: async function () { + const data = await WORLD.DB.readData(__PATH.DATA + "data.js"); + this.temp = data.temp ?? {}; + this.on_load(data); + }, + query_temp: function (name, def) { + if (!this.temp) return; + let item = this.temp[name]; + if (item && item.e) { + if (Date.now() <= item.e) { + return item.v; + } + delete this.temp[name]; + return def; + } + return item || def; + }, + set_temp: function (name, value, time) { + if (!this.temp) this.temp = {}; + if (time) { + this.temp[name] = { + v: value, + e: Date.now() + time + }; + } else { + this.temp[name] = value; + } + }, + remove_temp: function (name) { + if (!this.temp) return; + this.temp[name] = null; + }, + + add_temp: function (name, value, time) { + if (!this.temp) this.temp = {}; + let old = this.temp[name]; + if (time) { + if (old && old.e) { + time = Date.now() + time; + if (old.e < Date.now()) { + old.e = time; + old.v = value; + } else { + if (old.e < time) old.e = time; + old.v += value; + } + return old.v; + } else { + let v = value + (old || 0); + this.temp[name] = { + v: v, + e: Date.now() + time + }; + return v; + } + } else { + let v = value + (old || 0); + this.temp[name] = v; + return v; + } + }, + temp_data: {}, + clear_data: function () { + this.temp_data = {}; + } + , + add_data: function (key, user, val) { + if (!val) return; + let data = this.temp_data[key]; + if (!data) data = this.temp_data[key] = {}; + let user_data = data[user.id]; + if (!user_data) user_data = data[user.id] = { name: user.name, value: 0 }; + user_data.value += val; + }, query_max_data: function (key) { + let data = this.temp_data[key]; + if (!data) return; + let userData = null; + for (let key in data) { + let item = data[key]; + if (!userData) userData = item; + else if (item.value > userData.value) { + userData = item; + } + } + return userData; + }, query_min_data: function (key) { + let data = this.temp_data[key]; + if (!data) return; + let userData = null; + for (let key in data) { + let item = data[key]; + if (!userData) userData = item; + else if (item.value < userData.value) { + userData = item; + } + } + return userData; + } +}; + diff --git a/os/item.js b/os/item.js new file mode 100644 index 0000000..169520e --- /dev/null +++ b/os/item.js @@ -0,0 +1,250 @@ +require("./util/util"); +ITEM = function () { + +} +ITEM.inherits(BASE); + + +ITEM.prototype.heart_beat = function (dt) { + +} +ITEM.prototype.init = function () { + +} +//物件对命令的反应有几种方式实现 +//1. 直接实现ON_XXXX,cmd里定义的有直接对象的命令推荐这种,比如on_accept是当别人给你东西时候,on_checkskill当别人学你技能时,适合目标明确的操作 +//2. add_action方式,房间里的指令推荐用这种,虽然也可以实现1,但是因为调用add_action时候还没ID,适合房间的自定义命令和已定义的有目标的命令 +//3. on(xxx)方式,对房间里的命令的反映,适合回应目标不是当前对象,或没有目标的命令 +//actions里定义的动作会作为对象的可用操作发送出去 +//添加物件可以接收的命令,目标是当前对象的 +ITEM.prototype.add_action = function (cmd, name, func) { + if (!cmd) return; + if (!this.actions) this.actions = {}; + var act = this.actions[cmd]; + if (act) { + if (!name) { + act.action = func; + } else { + act.name = name; + } + if (!func) { + act.name = name; + } else { + act.action = func; + } + } else { + act = { + name: name, + action: func + }; + this.actions[cmd] = act; + } + this.json = null; + return act; +} +//移除物件可以接收的命令 +ITEM.prototype.remove_action = function (name, func) { + if (!this.actions) this.actions = {}; + if (typeof (name) === "string") { + delete this.actions[name]; + } else { + for (var i = 0; i < name.length; i++) { + delete this.actions[name[i]]; + } + } + this.json = null; +} +//执行命令 返回true表示已经完成命令,后续不需要执行 +ITEM.prototype.exec = function (cmdName, pars) { + if (this.actions) { + var cmd = this.actions[cmdName]; + if (cmd && cmd.action) { + return cmd.action.apply(this, pars); + } + } + return false; +} +ITEM.prototype.max_item_count = 10; +ITEM.prototype.item_count = function () { + return this.items ? this.items.length : 0; +} +ITEM.prototype.is_full = function (val) { + if (!this.items) return false; + if (val) return this.items.length + val > this.max_item_count; + + return this.items.length >= this.max_item_count; +} +ITEM.prototype.find_obj = function (id) { + return null; +} +ITEM.prototype.find_obj_bypath = function (path, parent) { + parent = parent || this; + if (!parent.items) return; + for (var i = 0; i < parent.items.length; i++) { + if (parent.items[i].path === path) { + return parent.items[i]; + } + } +} +ITEM.prototype.each_item = function (func, parent) { + if (!func) return; + parent = parent || this; + var l = parent.items.length; + for (var i = 0; i < l; i++) { + var item = parent.items[i]; + if (!item) continue; + if (func(item) === false) return; + } +}; +ITEM.prototype.is = function (obj) { + if (!obj) return false; + if (typeof obj === "string") + return this.path === obj; + return this.path === obj.path; +} +ITEM.prototype.remove_item_byid = function (obj, count = 0) { + if (!obj || !this.items) return; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if (item.id === obj) { + if (item.combined && count > 0) { + var subitem = item.uncombine(count); + if (!subitem) return; + if (subitem === item) { + this.items.splice(i, 1); + } + return subitem; + } else { + this.items.splice(i, 1); + return item; + } + } + } + return null; +} +ITEM.prototype.remove_item = function (obj, count) { + if (!obj || !this.items) return; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if (item === obj) { + if (item.combined) { + var subitem = item.uncombine(count); + if (!subitem) return; + if (subitem === item) { + this.items.splice(i, 1); + } + return subitem; + } else { + this.items.splice(i, 1); + return item; + } + } + } + return null; +} +ITEM.prototype.move_item_to = function (obj, count, target) { + if (!obj || !this.items) return; + var moved_obj = this.remove_item(obj, count); + if (!target) return; + return target.push_item(moved_obj); +} +ITEM.prototype.push_item = function (moved_obj) { + if (!moved_obj) return; + if (!this.items) this.items = []; + if (moved_obj.is_money && this.money !== undefined) { + + this.money += moved_obj.value * moved_obj.count; + } else if (moved_obj.combined) { + for (var i = 0; i < this.items.length; i++) { + if (this.items[i].is(moved_obj)) { + this.items[i].combine(moved_obj); + return this.items[i]; + } + } + this.items.push(moved_obj); + } else { + this.items.push(moved_obj); + } + return moved_obj; +} +ITEM.prototype.create_id = function () { + this.id = UTIL.create_id(); + +} +ITEM.prototype.refresh = function () { + this.json = null; +} +ITEM.prototype.is_hidden = function () { + return false; +} +ITEM.prototype.query_create_time = function () { + var id = this.id; + if (!id) return; + var time = parseInt(id.substr(4), 16); + + return new Date(time * 1000 + UTIL.begin); +} + +ITEM.prototype.find_obj_byid = function (items, oid) { + if (!items) return; + for (var i = 0; i < items.length; i++) { + if (items[i].id === oid) { + return items[i]; + } + } +} + +ITEM.prototype.long_name = function () { + return this.name; +} + + + + +ITEM.prototype.create = function (file, ctor) { + this.uid = this.create_uid(); +} +ITEM.prototype.destroy = function () { + +} + +ITEM.prototype.format_temp = function (temp, timeout = 120000) { + if (!temp) return "{}"; + var dt = Date.now() + timeout; + var tmp = ["{"]; + for (var key in temp) { + var v = temp[key]; + if (!v) continue; + if (v.e) { + if (dt > v.e || !v.v) continue; + if (tmp.length > 1) tmp.push(","); + tmp.push("\""); + tmp.push(key); + tmp.push("\":{e:"); + tmp.push(v.e); + tmp.push(",v:"); + if (typeof v.v == "string") { + tmp.push("\""); + tmp.push(v.v); + tmp.push("\""); + } else { + tmp.push(v.v); + } + tmp.push("}"); + } else { + if (tmp.length > 1) tmp.push(","); + tmp.push("\""); + tmp.push(key); + tmp.push("\":"); + if (typeof v == "string") { + tmp.push("\""); + tmp.push(v); + tmp.push("\""); + } else { + tmp.push(v); + } + } + } + tmp.push("}"); + return tmp.join(""); +} \ No newline at end of file diff --git a/os/item/container.js b/os/item/container.js new file mode 100644 index 0000000..535aad9 --- /dev/null +++ b/os/item/container.js @@ -0,0 +1,69 @@ +require("./obj.js"); +CONTAINER = function () { + this.count = 1; + this.combined = false; + +} +CONTAINER.inherits(OBJ); +CONTAINER.prototype.is_container = true; +CONTAINER.prototype.on_get = function () { + return false; +} +CONTAINER.prototype.set_items = function () { + for (var i = 0; i < arguments.length; i++) { + var item = arguments[i]; + if (item) { + if (typeof item == "string") { + OBJ.clone_to(item, this); + } else if (item.length) { + OBJ.clone_to(item[0], this,item[1]); + } + } + } +} +CONTAINER.prototype.query_items = function () { + return this.items; +} +//这个单纯的字符串描述 +CONTAINER.prototype.get_desc = function (me) { + var str = [this.color_name, this.desc]; + var items = this.query_items(me); + if (items && items.length) { + str.push("它里面有:"); + for (var i = 0; i "; + this.environment = player.environment; + this.desc = "然而" + player.call3() + "已经死了,只剩下一具尸体静静地躺在这里。"; + this.items = player.query_drop(); + if (!iskeep) this.call_out(this.disappear, 60000); + +} +CORPSE.prototype.query_items = function (player) { + if (this.environment.is_fb() && player.team) { + if (!this.no_drops) { + this.no_drops = []; + for (var i = 0; i < player.team.length; i++) { + if (!this.environment.query_temp(player, player.team[i].id)) { + this.no_drops.push(player.team[i].id); + } + } + this.on_getitem = this.check_get; + } + } + return this.items; +} +CORPSE.prototype.clear_items = function (me, noget) { + this.items.length = 0; + if (noget && noget.length) this.items = noget; +} +CORPSE.prototype.check_get = function (player, item) { + if (!this.no_drops) return true; + if (this.no_drops.indexOf(player.id) == -1) return true; + player.notify('你不可以拾取' + item.color_name + "。"); + return false; +} +CORPSE.prototype.disappear = function () { + if (this.items) this.items.length = 0; + if (this.environment) { + this.environment.notify("一阵风吹去," + this.name + "已经不见了。"); + this.environment.item_changed(this, false); + } +} + +CORPSE.prototype.query_desc = function (me) { + if (this.json) return this.json; + var obj = {}; + obj.type = "item"; + obj.desc = this.get_desc(me); + obj.id = this.id; + obj.commands = []; + obj.commands.push({ + cmd: "get all from " + this.id, + name: "全部拾取" + }); + if (this.no_alloc) { + return JSON.stringify(obj); + } + this.json = JSON.stringify(obj); + return this.json; +} + diff --git a/os/item/equipment.js b/os/item/equipment.js new file mode 100644 index 0000000..193f1c0 --- /dev/null +++ b/os/item/equipment.js @@ -0,0 +1,450 @@ + +require("../util/util.js"); +EQUIPMENT = function () { + this.eq_type = EQUIP_TYPE.WEAPON; + this.level = 0; + this.exp = 0; + this.grade = 0; + this.count = 1; + this.combined = false; + this.showAction = true; + this.allow_fight = true; + this.otype = 4; +} +EQUIPMENT.inherits(OBJ); +EQUIPMENT.prototype.is_equipment = true; +EQUIPMENT.prototype.transable = true; +//EQUIPMENT.prototype.eq_msg = "$N装备上$n。"; +//EQUIPMENT.prototype.uneq_msg = "$N脱下$n。"; +EQUIPMENT.prototype.change_prop = function (me, is_attach) { + me.change_prop(this.prop, is_attach); + if (this.st_prop) { + for (var i = 0; i < this.st_prop.length; i++) { + me.change_prop(this.st_prop[i].prop, is_attach); + } + } +} +EQUIPMENT.prototype.notify_action = function (me, isadd) { + if (!this.on_use) return; + isadd = me.equipment[this.eq_type] == this; + if (isadd) + me.send("{type:'addAction',id:'" + this.id + "',name:'" + this.name + "',distime:" + (this.distime || 0) + "}"); + else + me.send("{type:'removeAction',id:'" + this.id + "'}"); +} +EQUIPMENT.prototype.check = function (me) { + if (!this.condition) return true; + for (var key in this.condition) { + var val = this.condition[key]; + switch (key) { + case "skill": + for (var sk in val) { + if (me.query_skill(sk, 0) < val[sk]) { + var sk_base = SKILL.get(sk); + + return me.notify_fail("你的" + sk_base.color_name + "等级不够" + val[sk] + ",无法装备" + this.color_name + "。"); + } + } + break; + case "str1": + case "con1": + case "dex1": + case "int1": + if (me[key.replace("1", "")] < val) { + return me.notify_fail("你的先天" + PROPERTIES[key] + "不够" + val + ",无法装备" + this.color_name + "。");; + } + break; + case "str": + case "con": + case "dex": + case "int": + if (me[key] + me.query_prop(key) < val) { + return me.notify_fail("你的" + PROPERTIES[key] + "不够" + val + ",无法装备" + this.color_name + "。");; + } + break; + case "gender": + if (me.gender != val) return me.notify_fail("你不是" + (val == 1 ? "男性" : "女性") + ",无法装备" + this.color_name + "。"); + break; + case "desc": + break; + default: + var me_val = me[key] || 0; + me_val = me_val + me.query_prop(key); + if (!me_val || me_val < val) { + + return me.notify_fail("你的" + PROPERTIES[key] + "不够" + val + ",无法装备" + this.color_name + "。");; + } + break; + } + } + return true; +} +EQUIPMENT.prototype.eq = function (me, notsend) { + if (this.check(me) == false) { + return false; + } + if (this.on_eq && this.on_eq(me) == false) { + return false; + } + this.change_prop(me, true); + this.check_group(me, true); + //me.add_score(this.query_score()); + if (!notsend) { + if (this.eq_msg) + me.send_room(this.eq_msg, this); + else { + var msg; + switch (this.eq_type) { + case EQUIP_TYPE.WEAPON: + msg = "$N抽出一" + this.unit + this.color_name + "拿在手上。"; + break; + case EQUIP_TYPE.CLOTH: + case EQUIP_TYPE.SHOES: + case EQUIP_TYPE.PANTS: + msg = "$N穿上一" + this.unit + this.color_name + "。"; + break; + case EQUIP_TYPE.RING: + msg = "$N拿出一" + this.unit + this.color_name + "戴在手上。"; + break; + case EQUIP_TYPE.NECKLACE: + case EQUIP_TYPE.JEWELS: + case EQUIP_TYPE.WRIST: + msg = "$N戴上一" + this.unit + this.color_name + "。"; + break; + default: + msg = "$N装备上一" + this.unit + this.color_name + "。"; + break; + } + me.send_room(msg, this); + } + } + me.send('{type:"dialog",dialog:"pack",id:"' + this.id + '",eq:' + this.eq_type + '}'); +} +EQUIPMENT.prototype.uneq = function (me, notsend) { + this.on_uneq && this.on_uneq(me); + this.change_prop(me, false); + this.check_group(me, false); + //me.add_score(-this.query_score()); + + if (!notsend) { + if (this.uneq_msg) + me.send_room(this.uneq_msg, this); + else { + var msg; + switch (this.eq_type) { + case EQUIP_TYPE.WEAPON: + msg = "$N收回手中的" + this.color_name + "。"; + break; + case EQUIP_TYPE.CLOTH: + case EQUIP_TYPE.SHOES: + case EQUIP_TYPE.PANTS: + case EQUIP_TYPE.WRIST: + msg = "$N将" + this.color_name + "脱了下来。"; + break; + case EQUIP_TYPE.RING: + case EQUIP_TYPE.NECKLACE: + case EQUIP_TYPE.JEWELS: + msg = "$N将" + this.color_name + "取了下来。"; + break; + default: + msg = "$N脱下一" + this.unit + this.color_name + "。"; + break; + } + me.send_room(msg, this); + } + + } + + me.send('{type:"dialog",dialog:"pack",id:"' + this.id + '",uneq:' + this.eq_type + '}'); +} + +EQUIPMENT.prototype.condition_tostring = function (str) { + if (!this.condition) return; + for (var key in this.condition) { + var val = this.condition[key]; + switch (key) { + case "skill": + for (var sk in val) { + var sk_base = SKILL.get(sk); + str.push(sk_base.name + "要求:" + val[sk] + "级"); + } + break; + case "desc": + str.push(desc); + break; + case "gender": + str.push("性别要求:" + (val == 1 ? "男" : "女")); + break; + default: + str.push(PROPERTIES[key] + "要求:" + val); + break; + } + str.push("\n"); + } +} +EQUIPMENT.prototype.parts = ['武器', '衣服', '鞋', '头部', '披风', '戒指', '项链', '饰品', '护腕', '腰带', '暗器']; +EQUIPMENT.prototype.qualities = ["普通", "精良", "高级", "稀有", "绝世", "传说", "神器"]; + +EQUIPMENT.prototype.get_desc = function (me) { + var str = [this.color_name]; + str.push("\n"); + str.push(this.parts[this.eq_type]); + //str.push("\n"); + //str.push(this.query_quality()); + str.push("\n"); + this.condition_tostring(str); + + if (this.desc) str.push(this.desc); + str.push("\n"); + if (this.prop) { + str.push("<"); + str.push(this.query_grade_color()); + str.push(">"); + str.push(UTIL.prop_toString(this.prop)); + + str.push("\n"); + } + if (this.st_prop) { + for (var i = 0; i < this.st_prop.length; i++) { + str.push(this.st_prop[i].name); + str.push("\n"); + } + } + if (this.hole_count) { + for (var i = 0; i < this.hole_count; i++) { + str.push("◇"); + } + } + this.query_group_desc(me, str); + return str.join(""); +} + + +EQUIPMENT.prototype.query_quality = function () { + return this.qualities[this.grade]; +} +const level_desc = ["", "☆", "★", "★☆", "★★", "★★☆", "★★★", + "★★★☆", "★★★★", "★★★★☆", "★★★★★", "★★★★★☆", "★★★★★★"]; +EQUIPMENT.prototype.level_up = function (lev) { + var cc = this.query_grade_color(); + + this.prop = {}; + this.level = lev; + this.levelchange_prop(); + this.color_name = "<" + cc + ">" + level_desc[this.level] + this.name + ""; + this.json = null; +} + + +EQUIPMENT.prototype.levelData = [ + 0, 10, 20, 40, 70, 110, 160, 220, 290, 370, 460, 560, 670 +]; +EQUIPMENT.prototype.levelchange_prop = function () { + if (!(this.level >= 0 && this.level < 13)) return; + const base_props = this.original_prop ?? Object.getPrototypeOf(this).prop; + var val = this.levelData[this.level]; + for (var key in base_props) { + var value = base_props[key]; + switch (key) { + case "desc": + case "str1": + case "con1": + case "dex1": + case "int1": + case "per": + case "kar": + case "skill": + this.prop[key] = value; + break; + + case "fy_per": + case "zj_per": + case "mz_per": + case "hp_per": + case "ds_per": + case "gj_per": + case "diff_busy": + case "busy_per": + case "caiyao1": + case "diaoyu1": + case "kuang1": + case "lianyao1": + case "diff_sh": + case "expend_mp": + this.prop[key] = value + parseInt(value * val / 1000); + break; + case "diff_downside_per": + case "gjsd": + case "releasetime": + case "distime": + case "diff_downside": + case "distime_per": + case "releasetime_per": + case "gjsd_per": + + case "bj_per": + case "diff_bj": + case "add_bjsh_per": + + case "add_sh_per": + case "diff_busy_per": + case "diff_sh_per": + case "diff_fy_per": + case "expend_mp_per": + case "busy": + this.prop[key] = value; + break; + default: + if (PROPERTIES[key]) + this.prop[key] = value + parseInt(value * val / 100); + else + this.prop[key] = value; + break; + } + } +} +EQUIPMENT.prototype.clear_stone = function () { + if (!this.st_prop) return; + + this.hole_count += (this.st_prop.length); + this.st_prop.length = 0; +} +EQUIPMENT.prototype.push_stone = function (stone) { + if (!stone || !stone.prop) return false; + if (!this.hole_count) return false; + + if (!this.st_prop) this.st_prop = []; + this.hole_count--; + var cc = stone.query_grade_color(); + var str = ["<", cc, ">◆", stone.name, " "]; + str.push(UTIL.prop_toString(stone.prop, " ")); + str.push(""); + + this.json = null; + this.st_prop.push({ + id: stone.id, + path: stone.path, + name: str.join(""), + prop: stone.prop, + grade: stone.grade + }); +} +EQUIPMENT.prototype.clone = function (me) { + var obj = OBJ.CREATE(this.path); + if (this.temp) { + obj.temp = {}; + for (var key in this.temp) { + obj.temp[key] = this.temp[key]; + } + } + obj.on_reload && obj.on_reload(me); + obj.level_up(this.level); + obj.st_prop = this.st_prop; + return obj; +} + + + +EQUIPMENT.prototype.save_db = function (str) { + str.push('["', this.path, '","', this.id, '",', this.level); + if (this.st_prop && this.st_prop.length) { + str.push(",["); + for (var i = 0; i < this.st_prop.length; i++) { + if (i > 0) str.push(","); + str.push('"', this.st_prop[i].path, '"'); + } + str.push("]"); + } + // else { + // str.push(',[]'); + // } + if (this.is_locked) + str.push(',1'); + if (this.temp) + str.push(",", this.format_temp(this.temp)); + str.push("]"); +} +EQUIPMENT.prototype.load_db = function (data) { + //const [path, id, level, sts, locked,temp] = data; + this.id = data[1]; + if (data[2] > 0) { + this.level = data[2]; + } + for (let i = 3; i < data.length; i++) { + let value = data[i]; + if (value === 1) this.is_locked = true; + else if (Array.isArray(value)) { + for (var j = 0; j < value.length; j++) { + var st_item = OBJ.CREATE(value[j]); + if (st_item) { + this.push_stone(st_item); + } + } + } else if (typeof value === 'object') { + this.temp = value; + } + } + +} +EQUIPMENT.prototype.on_load = function (me) { + this.on_reload && this.on_reload(me); + if (this.level > 0) { + this.level_up(this.level); + } +} + +EQUIPMENT.prototype.VALUES = [100, 1000, 2000, 10000, 100000, 1000000, 100000000]; +EQUIPMENT.prototype.on_create = function (path, par) { + this.value = this.VALUES[this.grade]; + +} + +EQUIPMENT.prototype.query_group_desc = function (me, str) { + if (!this.group_prop || !this.group_name) return; + var count = 0; + if (me && me.equipment) { + for (var i = 0; i < me.equipment.length; i++) { + if (me.equipment[i] && me.equipment[i].group_name == this.group_name) { + count++; + } + } + } + for (var i = 2; i < 8; i++) { + var prop = this.group_prop(i); + if (prop) { + var cc = i <= count ? this.query_grade_color() : "blk"; + + str.push("<"); + str.push(cc); + str.push(">"); + str.push("\n"); + str.push(UTIL.to_c(i)); + str.push("件套:"); + str.push(UTIL.prop_toString(prop, " ")); + str.push(""); + } + } + + +} + +EQUIPMENT.prototype.check_group = function (me, isadd) { + if (!this.group_prop || !this.group_name) return; + var count = isadd ? 1 : 0; + for (var i = 0; i < me.equipment.length; i++) { + if (me.equipment[i] && me.equipment[i].group_name == this.group_name) { + count++; + } + } + var prop = this.group_prop(count); + if (prop) { + me.change_prop(prop, isadd); + } + +} \ No newline at end of file diff --git a/os/item/money.js b/os/item/money.js new file mode 100644 index 0000000..f0edeed --- /dev/null +++ b/os/item/money.js @@ -0,0 +1,25 @@ +require("../item/obj.js"); +MONEY = function () { + this.is_cash = false; + this.combined = true; + this.count = 1; +} +MONEY.inherits(OBJ); +MONEY.prototype.is_money = true; +MONEY.prototype.transable = true; + +MONEY.prototype.create = function () { + this.create_id(); + if (this.is_cash) { + this.color_name = "" + this.name + ""; + } else { + if (this.value == 1) + this.color_name = "" + this.name + ""; + else if (this.value == 100) + this.color_name = "" + this.name + ""; + else + this.color_name = "" + this.name + ""; + } + +} + diff --git a/os/item/obj.js b/os/item/obj.js new file mode 100644 index 0000000..8933375 --- /dev/null +++ b/os/item/obj.js @@ -0,0 +1,228 @@ + +OBJ = function () { + this.unit = "个"; + this.path = null; + this.count = 1; + this.combined = true; + this.grade = 0; + this.otype = 0; +} + +OBJ.inherits(ITEM); +OBJ.prototype.transable = false; +OBJ.prototype.init = function (me) { + this.on_init && this.on_init(me); +} +OBJ.prototype.long_name = function () { + if (this.combined) return UTIL.to_c(this.count) + this.unit + this.color_name; + return this.color_name; +} +OBJ.prototype.unit_name = function (count) { + return UTIL.to_c(count || this.count) + this.unit + this.color_name; + +} +OBJ.prototype.item_to_json = function () { + return `["${this.name}","${this.id}",${this.count},${this.grade},"${this.unit}",${parseInt(this.value / 10)},${this.is_equipment ? 1 : 0},${this.on_use ? 1 : 0},${this.on_study ? 1 : 0},${this.on_open ? 1 : 0},${this.combine_count > 0 ? this.combine_count : 0}]`; +} +OBJ.prototype.query_commands = function (me) { + return this.query_desc(me); +} +OBJ.prototype.query_desc = function (me) { + if (this.json) return this.json; + var obj = {}; + obj.type = "item"; + obj.id = this.id; + obj.desc = this.get_desc(me); + obj.commands = []; + obj.commands.push({ + cmd: "get " + this.id, + name: "捡起" + }); + + this.json = JSON.stringify(obj) + return this.json; +} +OBJ.prototype.get_desc = function () { + return this.color_name + "\n" + this.desc; +} +OBJ.prototype.uncombine = function (spcount) { + if (!spcount || spcount === this.count) return this; + if (spcount < this.count) { + var item = this.clone(); + item.count = spcount; + this.count -= spcount; + return item; + } +} +OBJ.prototype.clone = function () { + var item = OBJ.CREATE(this.path); + if (this.temp) { + item.temp = Object.assign({}, this.temp); + } + return item; +} +OBJ.prototype.combineTemp = function (target, source) { + if (!source) return target; + if (!target) return source; + for (let key in source) { + let val = source[key]; + if (val && typeof val === "number") { + let thisVal = target[key]; + if (!thisVal) { + target[key] = val; + } else if (typeof thisVal === "number") { + target[key] = thisVal > val ? thisVal : val; + } + } + } + return target; +} +OBJ.prototype.combine = function (obj) { + if (this.is(obj)) { + if (obj.temp || this.temp) { + this.temp = this.combineTemp(this.temp, obj.temp); + } + this.count += (obj.count || 0); + } +} + + +OBJ.clone_to = function (otype, to, count) { + if (!otype || !to) return; + var item = OBJ.CREATE(otype); + if (!item) return; + count = count || 1; + if (item.is_money && to.money != undefined) { + item.count = count; + to.money += item.value * item.count; + return item; + } + if (!to.items) to.items = []; + if (item.combined) { + for (var i = 0; i < to.items.length; i++) { + if (to.items[i].is(item)) { + to.items[i].count += count; + return to.items[i]; + } + } + + item.count = count; + to.items.push(item); + } else { + to.items.push(item); + for (var i = 0; i < count - 1; i++) { + item = OBJ.CREATE(otype, 1); + to.items.push(item); + } + } + return item; +} +OBJ.prototype.save_db = function (str) { + str.push('["', this.path, '","', this.id, '",', this.count); + if (this.is_locked) { + str.push(',1'); + } + if (this.temp) + str.push(",", this.format_temp(this.temp)); + str.push(']'); + +} +OBJ.prototype.load_db = function (data) { + //path, id, count, temp or lock + + this.id = data[1]; + if (data[2] > 1) this.count = data[2]; + if (data[3]) { + if (data[3] === 1) { + this.is_locked = true; + } else if (typeof data[3] === 'object') { + this.temp = data[3]; + return; + } + } + if (data[4]) this.temp = data[4]; +} + +OBJ.prototype.on_load = function (me) { + this.on_reload && this.on_reload(me); +} + +OBJ.prototype.on_clone = function () { + +} +OBJ.CREATE = function (otype, count) { + let base = WORLD.OBJ_STROE.get(otype); + if (!base) { + base = BASE.CREATE(__PATH.OBJ, otype); + if (!base) throw new Error('没有物品' + otype + "的定义。"); + //这里会自己调用create方法存储到OBJ_STROE,记住了吗 + } + + // var item = BASE.CREATE(__PATH.OBJ, otype); + // if (!item) return; + let item = Object.create(base); + item.create_id(); + item.on_clone(); + if (count > 1) + item.count = count; + return item; +} +var grade_color = ["wht", "hig", "hic", "hiy", "HIZ", "hio", "ord"]; + +OBJ.prototype.create = function (path, par) { + if (par) this.path = path + par; + this.create_id(); + this.on_create && this.on_create(path, par); + var cc = grade_color[this.grade]; + this.color_name = "<" + cc + ">" + this.name + ""; + WORLD.OBJ_STROE.set(this.path, this); +} +OBJ.prototype.update = function (path, par) { + this.create(path, par); +} + + + +OBJ.prototype.query_grade_color = function () { + return grade_color[this.grade]; +} + +OBJ.prototype.notify_action = function (me, isadd) { + if (!this.on_use) return; + if (!this.showAction) return; + if (isadd) + me.send("{type:'addAction',id:'" + this.id + "',name:'" + this.name + "',distime:" + (this.distime || 0) + "}"); + else + me.send("{type:'removeAction',id:'" + this.id + "'}"); +} + +OBJ.prototype.query_temp = CHARACTER.prototype.query_temp; +OBJ.prototype.set_temp = CHARACTER.prototype.set_temp; +OBJ.prototype.remove_temp = CHARACTER.prototype.remove_temp; + +OBJ.prototype.add_temp = CHARACTER.prototype.add_temp; +OBJ.create_by_odds = function (args) { + var items = []; + if (!args) return items; + let drop = null, per = null, + obj = null; + for (var i = 0; i < args.length; i++) { + drop = args[i]; + if (!drop) continue; + + per = Math.random() * 10000; + obj = (drop.odds || 10000) > per ? drop.obj : drop.fall_obj; + if (obj) { + if (drop.min_count) hit_count = 0; + var count = drop.count || 1; + if (drop.min && drop.max) { + count = Math.floor(Math.random() * (drop.max - drop.min + 1)) + drop.min; + } + if (count > 0) { + if (obj instanceof Array) obj = obj.random(); + items.push(OBJ.CREATE(obj, count)); + } + } + } + return items; +} diff --git a/os/login.js b/os/login.js new file mode 100644 index 0000000..31f0704 --- /dev/null +++ b/os/login.js @@ -0,0 +1,38 @@ + +var crypto = require('crypto'); +module.exports = { + max_idcount: 10, + max_ipcount: 12, + login_error: function (user, msg, close = true) { + user.send(`{type:'loginerror',msg:'${msg}'}`); + if (close) + user.socket?.end(); + return false; + }, + encryptUser: function (key, session) { + if (!key || !session) return null; + if (key.length >= 16) key = key.substr(0, 16); + try { + key = Buffer.from(key, 'utf8'); + var decipher = crypto.createDecipheriv('aes-128-cbc', key, __CONFIG.DESIV); + var txt = decipher.update(session, 'base64', 'utf8'); + txt += decipher.final('utf8'); + var str = txt.split("%"); + if (str.length !== 5) return null; + var id = parseInt(str[0]); + if (id > 0) + return { + id: id, + name: str[1], + pwd: str[2], + loginTime: parseInt(str[3]), + level: parseInt(str[4]) + }; + } catch (e) { + return null; + } + + } + + +} diff --git a/os/net-ws.js b/os/net-ws.js new file mode 100644 index 0000000..02f54cc --- /dev/null +++ b/os/net-ws.js @@ -0,0 +1,340 @@ +"use strict"; +var crypto = require('crypto'); +var fs = require("fs"); +function wsServer(options) { + var evt = ["Close", "Error", "SocketIn", "Connect", "Receive", + "ClientError", "ClientClose", "ClientTimeout"]; + for (var i = 0; i < evt.length; i++) { + this["on" + evt[i]] = function () { + } + } + this.options = options.SSL ? { + key: fs.readFileSync(options.KEY), + cert: fs.readFileSync(options.CERT), + requestCert: true, + rejectUnauthorized: true, + passphrase: options.PASSWORD, + ca: [fs.readFileSync(options.CERT)] + } : null; + this.ssl = options.SSL; +} +wsServer.prototype.listen = function (port, func) { + + var net = require(this.ssl ? 'tls' : 'net'); + var tcpserver = net.createServer(this.options, onClientConnect.bind(this)); + tcpserver.listen(port, func); + tcpserver.on('close', this.onClose.bind(this)); + tcpserver.on('error', this.onError.bind(this)); + this.tcpServer = tcpserver; +} +wsServer.prototype.send = function (msg, socket) { + socket.send(msg); +} +wsServer.prototype.close = function () { + return new Promise((resolve) => { + this.tcpServer.close(resolve); + }); +} + +module.exports = wsServer; +function onClientConnect(socket) { + + socket.send = function (msg) { + if (msg) + this.protocol.sendData(msg, socket); + } + socket.on('close', this.onClientClose.bind(this, socket)); + socket.on('error', this.onClientError.bind(this, socket)); + var $this = this; + socket.setTimeout(3000); + socket.on('timeout', this.onClientTimeout.bind(this, socket)); + $this.onSocketIn(socket); + socket.on('data', function (data) { + if (socket.protocol) { + socket.protocol.readData(data, socket, $this); + } else { + var header = readHeader(data); + socket.requestHeader = header; + if (header["Sec-WebSocket-Key"]) { + socket.protocol = protocols.var1; + } else if (header["Sec-WebSocket-Key1"]) { + socket.protocol = protocols.var2; + } else { + socket.protocol = protocols.tcp; + socket.protocol.readData(data, socket, $this); + return; + } + socket.protocol.handShake(header, socket, data); + $this.onConnect(socket); + } + }); +} +var protocols = { + var1: { + handShake: function (header, socket) { + var hasher = crypto.createHash("sha1"); + hasher.update(header["Sec-WebSocket-Key"] + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); + var hashmsg = hasher.digest().toString('base64'); + var origin = header.Origin; + var protocol = header['sec-websocket-protocol']; + if (protocol) + protocol.split(/, */); + var respon = ["HTTP/1.1 101 Switching Protocols", + "Connection: Upgrade", + "Upgrade: WebSocket", + `Sec-WebSocket-Accept:${hashmsg}`, + `Sec-WebSocket-Origin:${origin}`]; + if (protocol) respon.push(`Sec-WebSocket-Protocol: ${protocol}`); + //var extens = header["Sec-Websocket-Extensions"]; + //if (extens) { + // respon.push(`Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits`); + //} + respon.push("\r\n"); + socket.write(respon.join("\r\n")); + }, + readData: function (data, socket, server) { + var start = 0; + while (start < data.length) { + var iseof = (data[start] >> 7) > 0; + var frameType = data[start++] & 0xF; + var hasMask = (data[start] >> 7) > 0; + var length = (data[start++] & 0x7F); + if (length == 126) { + length = data.readUInt16BE(start); + start = start + 2; + } + else if (length == 127) { + length = data.readUInt32BE(start); + start = start + 4; + return; + } + var markIndex = start; + start = start + 4; + for (let i = 0; i < length; i++) { + data[start] = data[start] ^ data[markIndex + (i % 4)]; + start++; + } + switch (frameType) { + case FrameTypes.Close: + socket.end(); + // server.onClientClose(socket); + break; + case FrameTypes.Binary: + break; + case FrameTypes.Ping: + break; + case FrameTypes.Pong: + break; + case FrameTypes.Text: + var msg = data.toString("utf8", markIndex + 4, markIndex + 4 + length); + server.onReceive(msg, socket); + break; + default: + break; + } + } + }, + sendData: function (text, socket) { + var textBuffer = Buffer.from(text); + var length = textBuffer.length; + var data; + if (length < 126) { + data = Buffer.alloc(length + 2); + data[0] = 129; + data.writeUInt8(length, 1); + textBuffer.copy(data, 2); + } + else if (length >= 126 && length < 65536) { + data = Buffer.alloc(length + 4); + data[0] = 129; + data.writeUInt8(126, 1); + data.writeUInt16BE(length, 2); + textBuffer.copy(data, 4); + } else { + data = Buffer.alloc(length + 10); + data[0] = 0x81; + data[1] = 127; + data.writeUInt32BE(0, 2); + data.writeUInt32BE(length, 6); + textBuffer.copy(data, 10); + } + socket.write(data); + } + }, + var2: { + handShake: function (header, socket, buffer) { + var key1 = header["Sec-WebSocket-Key1"]; + var key2 = header["Sec-WebSocket-Key2"]; + + var origin = header["Origin"]; + + var n1 = getNumber(key1); + n1 = parseInt(n1); + n1 = n1 / getSpace(key1); + + var n2 = getNumber(key2); + n2 = parseInt(n2); + n2 = n2 / getSpace(key2); + + var buf = Buffer.alloc(16); + + buf.writeIntBE(n1, 0, 4, true); + + buf.writeIntBE(n2, 4, 4, true); + + buffer.copy(buf, 8, buffer.length - 8, buffer.length); + + var hasherbs = crypto.createHash("md5"); + hasherbs = hasherbs.update(buf); + hasherbs = hasherbs.digest(); + + var host = "ws://" + header["Host"] + "/"; + var headers = [ + "HTTP/1.1 101 WebSocket Protocol Handshake", + "Upgrade: WebSocket", + "Connection: Upgrade", + "Sec-WebSocket-Origin:" + origin, + "Sec-WebSocket-Location:" + host + , "\r\n" + ]; + socket.write(headers.join("\r\n")); + socket.write(hasherbs); + }, + buffer: null + , + readData: function (data, socket, server) { + var start = 0; + while (start < data.length) { + if (data[start] != 0) { + break;//error + } + var end = start + 1; + while (data[end] != 255 && end < data.length) { + end++; + } + var msg = data.toString("utf8", start + 1, end); + server.onReceive(msg, socket); + start = end + 1; + } + }, + sendData: function (text, socket) { + var textBuffer = Buffer.from(text, "utf-8"); + var length = textBuffer.length; + + var wrappedBytes = Buffer.alloc(length + 2); + wrappedBytes[0] = 0; + textBuffer.copy(wrappedBytes, 1); + wrappedBytes[wrappedBytes.length - 1] = 255; + socket.write(wrappedBytes); + } + }, + tcp: { + + readData: function (data, socket, server) { + + var start = 0; + if (socket.unread_data) { + data = Buffer.concat([socket.unread_data, data], socket.unread_data.length + data.length); + socket.unread_data = null; + } + let isread = false; + while (start < data.length) { + let length = data.readUInt8(start); + let index = start + 1; + if (length === 254) { + //不够读长度咋办 + length = data.readUInt16BE(index); + index += 2; + } else if (length === 255) { + length = data.readUInt32BE(index); + index += 4; + } + if (data.length < index + length) { + socket.unread_data = isread ? data.slice(start) : data; + return; + } + let msg = data.toString("utf8", index, index + length); + + isread = true; + + server.onTcpReceive(msg, socket); + + start = index + length; + + } + }, + sendData: function (text, socket) { + var textBuffer = Buffer.from(text); + var length = textBuffer.length; + var data; + if (length < 254) { + data = Buffer.alloc(length + 1); + data.writeUInt8(length); + textBuffer.copy(data, 1); + } + else if (length >= 254 && length < 65536) { + data = Buffer.alloc(length + 3); + data.writeUInt8(254); + data.writeUInt16BE(length, 1); + textBuffer.copy(data, 3); + } else { + data = Buffer.alloc(length + 5); + data.writeUInt8(255); + data.writeUInt32BE(length, 1); + textBuffer.copy(data, 5); + } + socket.write(data); + } + } +}; + +function getNumber(str) { + return str.replace(/\D/g, ""); + +} +function getSpace(str) { + return str.replace(/\S/g, "").length; +} +function readHeader(data) { + var header = {}, key, flag = 0; + for (var i = 0; i < data.length; i++) { + switch (data[i]) { + case 0x0D://\r + key && (header[key] = data.toString("utf8", flag, i)); + break; + case 0x0A://\n + key = null; + flag = i + 1; + break; + case 0x3A://: + if (!key) { + key = data.toString("utf8", flag, i); + data[i + 1] == 0x20 ? flag = i + 2 : flag = i + 1; + } + break; + } + } + if (flag < data.length) { + header.CONTENT = data.toString("utf8", flag); + + } + return header; +} +var FrameTypes = +{ + Continuation: 0, + Text: 1, + Binary: 2, + Close: 8, + Ping: 9, + Pong: 10, +}; + +//%x0 代表一个继续帧 +//%x1 代表一个文本帧 +//%x2 代表一个二进制帧 +//%x3-7 保留用于未来的非控制帧 +//%x8 代表连接关闭 +//%x9 代表ping +//%xA 代表pong +//%xB-F 保留用于未来的控制帧 \ No newline at end of file diff --git a/os/room/area.js b/os/room/area.js new file mode 100644 index 0000000..4c5aa3f --- /dev/null +++ b/os/room/area.js @@ -0,0 +1,135 @@ +AREA = function () { + this.rooms = []; + this.map = []; + this.name = ""; + this.is_area = false; + this.first = null; + this.is_show = true; + this.is_copy = false; + this.expend = 10; + this.is_multi = false; + this.index = 0; + this.exp = 1000; + this.pot = 1000; +} +AREA.inherits(BASE); +AREA.prototype.create = function (path) { + WORLD.AREAS.push(this); + if (this.family) { + FAMILIES[this.family].area = this; + } +} +AREA.Get = function (id) { + if (!WORLD.AREAS) return; + for (var i = 0; i < WORLD.AREAS.length; i++) { + if (WORLD.AREAS[i].id == id) return WORLD.AREAS[i]; + } +} +AREA.prototype.on_leaved = function (me) { + //离开后 +} +AREA.prototype.on_leave = function (me) { + //进入前 + return true; +} +AREA.prototype.on_enterd = function (me) { + //进入后 +} +AREA.prototype.on_enter = function (me) { + //进入前 + return true; +} +AREA.prototype.find_area = function (path) { +} +AREA.prototype.is_record = function (diff) { + return this["record_" + diff]; +} +AREA.prototype.query_exp = function () { + var lv = this.fb_index || 0; + return 1000 + lv * 100; +} + +AREA.prototype.query_desc = function () { + return this.desc; +} + +AREA.prototype.clear = function () { + this.json = null; + this.drop_list = null; + this.diff_drop_list = null; +} +AREA.prototype.query_drops = function (isdiff) { + if (isdiff) return this.query_diff_drops(); + if (this.drop_list) return this.drop_list; + var items = []; + for (var i = 0; i < this.rooms.length; i++) { + var rm = this.rooms[i]; + for (var j = 0; j < rm.items.length; j++) { + if (rm.items[j].drop_list) { + items.push(rm.items[j].drop_list); + } + + } + } + this.query_npc_drops(this.drop_npcs0, items); + this.drop_list = items; + return this.drop_list; +} +AREA.prototype.query_npc_drops = function (npcs, items) { + if (!npcs || !npcs.length) return; + for (var i = 0; i < npcs.length; i++) { + var npc = NPC.GET(npcs[i]); + if (!npc || !npc.drop_list) continue; + items.push(npc.drop_list) + } +} +AREA.prototype.query_diff_drops = function (isdiff) { + if (this.diff_drop_list) return this.diff_drop_list; + var items = []; + for (var i = 0; i < this.rooms.length; i++) { + var rm = this.rooms[i]; + for (var j = 0; j < rm.items.length; j++) { + if (rm.items[j].drop_list) { + items.push(rm.items[j].drop_list); + } + } + } + this.query_npc_drops(this.drop_npcs1, items); + this.diff_drop_list = items; + return this.diff_drop_list; +} +AREA.prototype.update = function (path) { + WORLD.COMMANDS["jh"].map_json = null; + for (var i = 0; i < WORLD.AREAS.length; i++) { + if (WORLD.AREAS[i].path == path) { + var old_area = WORLD.AREAS[i]; + WORLD.AREAS[i] = this; + this.rooms = old_area.rooms; + if (this.rooms) { + for (let room of this.rooms) { + room.parent = this; + } + } + old_area.rooms = null; + if (this.family) { + FAMILIES[this.family].area = this; + } + return; + } + } + this.create(path); +} +AREA.Get = function (id) { + for (var i = 0; i < WORLD.AREAS.length; i++) { + if (WORLD.AREAS[i].id == id) { + return WORLD.AREAS[i]; + } + } +} +AREA.prototype.query_drop_items = function () { + return this.drop_items; +} +AREA.prototype.query_actions = function () { + return this.actions; +} + diff --git a/os/room/fam_area.js b/os/room/fam_area.js new file mode 100644 index 0000000..9d33d96 --- /dev/null +++ b/os/room/fam_area.js @@ -0,0 +1,5 @@ +FAMILY_AREA = function () { + +} +FAMILY_AREA.inherits(AREA); + diff --git a/os/room/room.js b/os/room/room.js new file mode 100644 index 0000000..4073f70 --- /dev/null +++ b/os/room/room.js @@ -0,0 +1,692 @@ + +ROOM = function () { + this.name = "房间"; + this.desc = ""; + this.items = []; + this.parent = null; +} +ROOM.inherits(ITEM); +ROOM.prototype.max_item_count = 50; + +ROOM.prototype.do_leave = function (obj, dir, leave_msg) { + if (this.on_leave && this.on_leave(obj, dir) == false) { + return false; + } + if (this.item_changed(obj, false, leave_msg, dir) == false) { + return false; + } + +} +ROOM.prototype.do_enter = function (obj, isshow, in_msg) { + this.on_before_enter && this.on_before_enter(obj); + if (obj.is_player) { + obj.send(this.to_json()); + this.send_exits(obj); + } + this.item_changed(obj, true, in_msg); + this.on_enter && this.on_enter(obj); +} +ROOM.prototype.item_changed = function (obj, isin, changed_msg, dir) { + if (!obj) return; + var msg; + var obj_index = -1, isshow = !obj.query_temp('hidden'); + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if (item == obj) { + obj_index = i; + continue; + } + if (item.is_player && isshow) { + if (!msg) msg = this.item_json(obj, isin); + item.send(msg); + + if (changed_msg && item != obj && !item.query_setting("off_move")) { + item.send(changed_msg); + } + + } else { + if (obj.hp) { + if (isin && item.on_enter) { + item.on_enter(obj); + } else if (!isin && item.on_leave) { + if (item.on_leave(obj, dir) == false) return false; + } + } + } + } + + if (isin) { + obj.environment = this; + if (obj_index == -1) { + this.items.push(obj); + if (obj.is_player) obj.send(this.items_to_json()); + + } else if (obj.is_player) { + if (!msg) msg = this.item_json(obj, isin); + obj.send(msg); + } + } else if (obj_index > -1) { + this.items.splice(obj_index, 1); + obj.environment = null; + } +} +ROOM.prototype.item_json = function (item, isin) { + if (!item) return ""; + var str = []; + if (isin) { + str.push('{"type":"itemadd",'); + str.push("id:\""); + str.push(item.id); + str.push("\",name:\""); + str.push(item.long_name()); + str.push("\""); + if (item.is_player) { + str.push(",p:1"); + } + if (item.appdend_status) { + str.push(",mp:"); + str.push(item.mp); + str.push(",hp:"); + str.push(item.hp); + str.push(",max_mp:"); + str.push(item.max_mp); + str.push(",max_hp:"); + str.push(item.max_hp); + item.appdend_status(str); + } + str.push("}"); + } else { + str.push('{"type":"itemremove",id:"'); + str.push(item.id); + str.push('"}'); + } + return str.join(""); +} +ROOM.prototype.items_to_json = function () { + var str = ['{"type":"items","items":[']; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if (!item.is_hidden()) { + str.push("{id:\""); + str.push(item.id); + str.push("\",name:\""); + str.push(item.long_name()); + str.push("\""); + if (item.is_player) { + str.push(",p:1"); + } else { + if (!item.item_types) { + item.item_types = item.hp > 0 ? `,m:${(item.on_checkskill || item.on_master) ? 1 : 0},l:${item.sell_list ? 1 : 0},f:${item.master ? 1 : 0}` : ",o:1"; + } + str.push(item.item_types); + } + if (item.appdend_status) { + str.push(",mp:"); + str.push(item.mp); + str.push(",hp:"); + str.push(item.hp); + str.push(",max_mp:"); + str.push(item.max_mp); + str.push(",max_hp:"); + str.push(item.max_hp); + + item.appdend_status(str); + } + str.push("},"); + } + } + str.push("0]}"); + return str.join(""); +} + +ROOM.prototype.set_npc = function () { + + for (var i = 0; i < arguments.length; i++) { + var name = arguments[i]; + if (typeof name == "string") name = [name, 1]; + var obj_path = name[0]; + if (!obj_path) continue; + for (var j = 0; j < name[1]; j++) { + var obj = NPC.CLONE(obj_path); + if (obj) { + this.items.push(obj); + obj.environment = this; + } + } + } +} +ROOM.prototype.set_obj = function (names) { + + for (var i = 0; i < arguments.length; i++) { + var name = arguments[i]; + if (typeof name == "string") name = [name, 1]; + var obj = OBJ.CREATE(name[0], name[1]); + if (obj) { + this.items.push(obj); + } + + } + +} +ROOM.prototype.set_item = function (id, name, desc, commands) { + this.hidden_items = this.hidden_items || []; + + if (commands && typeof commands[0] == "string") { + commands = [commands]; + } + let hidden_item = { + id: id, + name: name, + desc: desc, + commands: commands, + query_desc: on_look_hidden_item, + environment: this + }; + + this.hidden_items.push(hidden_item); + if (commands) { + for (var j = 0; j < commands.length; j++) { + this.add_action(commands[j][0], null, commands[j][2]); + } + //添加隐藏物品的命令到房间的actions,命令不能重复 + } + return hidden_item; +} + +function on_look_hidden_item(player) { + if (this.json) return this.json; + var json = {}; + json.type = "item"; + json.desc = this.desc; + if (this.commands) { + json.commands = []; + for (var i = 0; i < this.commands.length; i++) { + if (this.commands[i][1]) + json.commands.push({ + cmd: this.commands[i][0] + " " + this.id, + name: this.commands[i][1] + }); + } + } + this.json = JSON.stringify(json) + return this.json; +} +ROOM.prototype.find_obj = function (oid) { + var items = this.items; + if (!items) return; + var item = this.find_obj_byid(items, oid); + if (item) return item; + if (!this.hidden_items) return; + for (var i = 0; i < this.hidden_items.length; i++) { + if (this.hidden_items[i].id == oid) return this.hidden_items[i]; + } +} +ROOM.prototype.find_by_path = function (path) { + var items = this.items; + if (!items) return; + for (var i = 0; i < items.length; i++) { + if (items[i].path == path) { + return items[i]; + } + } +} +ROOM.prototype.is_here = function (path) { + var items = this.items; + if (!items) return; + for (var i = 0; i < items.length; i++) { + if (items[i].path == path) { + return true; + } + } +} +ROOM.prototype.notify = function (msg) { + if (!this.items) return; + for (var i = 0; i < this.items.length; i++) { + if (this.items[i].is_player) { + this.items[i].notify(msg); + } + } +} +ROOM.prototype.query_exits = function (dir) { + if (this.exits && this.exits[dir]) return true; + return false; +} +ROOM.prototype.add_exit = function (dir, rm) { + this.exits = this.exits || {}; + this.exits[dir] = rm; + this.exits_changed(); +} +ROOM.prototype.remove_exit = function (dir) { + this.exits = this.exits || {}; + delete this.exits[dir]; + this.exits_changed(); +} + +ROOM.prototype.exits_changed = function () { + this.room_exits_json = null; + for (var i = 0; i < this.items.length; i++) { + if (this.items[i].is_player) + this.send_exits(this.items[i]); + } +} +ROOM.prototype.send_exits = function (player) { + player.send(this.exitsto_roomjson()); +} +ROOM.prototype.exitsto_roomjson = function () { + if (this.room_exits_json) return this.room_exits_json; + var obj = {}; + obj.type = "exits"; + obj.items = {}; + if (this.exits) { + for (var dir in this.exits) { + if (!this.exits[dir]) continue; + var rm = ROOM.Get(this.exits[dir]); + if (!rm) continue; + obj.items[dir] = rm.name; + } + } + this.room_exits_json = JSON.stringify(obj); + return this.room_exits_json; +} +ROOM.prototype.to_json = function () { + if (this.json) return this.json; + var obj = {}; + obj.type = "room"; + obj.path = this.path; + obj.name = this.long_name; + obj.desc = this.desc; + obj.commands = []; + if (this.actions) { + for (var cmd in this.actions) { + var name = this.actions[cmd].name; + if (name) + obj.commands.push({ + cmd: cmd, + name: name + }); + } + } + if (this.is_copy_room && !this.parent.not_fb) { + obj.commands.push({ + cmd: "cr", + name: "完成副本" + }); + } + this.json = JSON.stringify(obj); + return this.json; + +} +ROOM.prototype.query_commands = function () { + if (this.commands_json) return this.commands_json; + var json = {}; + json.type = "command"; + + json.commands = []; + if (this.actions) { + for (var cmd in this.actions) { + json.commands.push({ + name: this.actions[cmd].name, + cmd: cmd + }); + } + } + + this.commands_json = JSON.stringify(json) + return this.commands_json; +} +ROOM.prototype.refresh = function (obj) { + this.json = null; + this.commands_json = null; + this.room_exits_json = null; + var rmname = this.parent.name + "-" + this.name; + if (this.parent.not_fb || !this.parent.is_copy) { + this.long_name = rmname; + } else { + this.long_name = rmname + "(副本区域)"; + } + if (obj) { + for (var i = 0; i < this.items.length; i++) { + if (this.items[i].is_player) { + this.items[i].send(this.to_json()); + this.send_exits(this.items[i]); + this.items[i].send(this.items_to_json()); + } + } + // this.send_exits(obj); + } + +} +ROOM.prototype.get_path = function () { + if (this.path) return this.path; + var str = this.name; + var area = this.area; + while (area) { + str = area.name + "-" + str; + area = area.parent; + } + this.path = str; + return this.path; +} +ROOM.prototype.query_recover_room = function () { + var area = this.parent; + while (area) { + if (area.recover_room) { + return area.recover_room; + } + area = area.parent; + } + return "yz/wumiao"; +} +ROOM.prototype.create = function (file) { + var base_room = WORLD.ROOMS[file]; + + if (base_room) { + this.parent = base_room.parent; + if (this.parent.is_copy) { + //副本区域 + if (this.parent.not_fb) { + this.long_name = base_room.long_name; + } else { + this.long_name = base_room.long_name + "(副本区域)"; + } + this.create_time = Date.now(); + this.is_copy_room = true; + } else { + //投影区域 房间人满了后 + this.is_shadow = true; + this.long_name = base_room.long_name;//+ "(" + UTIL.to_c(base_room.shadow_rooms.length + 1) + "号)"; + + } + WORLD.RUN_ROOMS.push(this); + } else { + this.initBaseRoom(file); + } + + this.on_create && this.on_create(); +} +ROOM.prototype.initBaseRoom = function (file) { + WORLD.ROOMS[file] = this; + + var area = getAreaByPath(this.path); + + this.parent = area; + if (!area || !area.is_copy) { + //如果是副本,第一个被创建的不放在运行的房间 + WORLD.RUN_ROOMS.push(this); + } + if (area) { + if (!area.rooms) area.rooms = []; + for (var i = 0; i < area.rooms.length; i++) { + if (area.rooms[i].path == this.path) { + area.rooms.splice(i, 1); + break; + } + } + area.rooms.push(this); + this.long_name = area.name + "-" + this.name; + } else { + + this.long_name = this.name; + } +} +ROOM.prototype.update = function (file) { + this.on_create && this.on_create(); + var oldroom = WORLD.ROOMS[file]; + this.initBaseRoom(file); + if (!oldroom) return; + if (oldroom.copy_rooms) { + this.copy_rooms = {}; + for (var key in oldroom.copy_rooms) { + var rm = oldroom.copy_rooms[key]; + var newRm = BASE.CREATE(__PATH.MAP, this.path); + this.replaceRoom(rm, newRm); + newRm.owner = key; + this.copy_rooms[key] = newRm; + } + oldroom.copy_rooms = null; + } else { + if (ROOM.public_rooms) { + for (var i = 0; i < ROOM.public_rooms.length; i++) { + if (ROOM.public_rooms[i] == oldroom) { + ROOM.public_rooms[i] = this; + break; + } + } + } + } +} +ROOM.prototype.replaceRoom = function (oldroom, newRoom) { + var items = oldroom.items; + for (var i = 0; i < items.length; i++) { + if (items[i].is_player || items[i].master) { + newRoom.items.push(items[i]); + items[i].environment = newRoom; + } + } + oldroom.destroy(); +} +ROOM.prototype.destroy = function () { + this.items.length = 0; + this.owner = null; +} +ROOM.prototype.heart_beat = function (dt) { + for (var i = 0; i < this.items.length; i++) { + if (!this.items[i].is_player) + this.items[i].heart_beat(dt); + } + this.on_heart_beat && this.on_heart_beat(dt); +} +ROOM.prototype.is_copy = function () { + if (!this.parent) return false; + return this.parent.is_copy; +} +ROOM.prototype.is_fb = function () { + if (!this.parent) return false; + return this.parent.is_copy && !this.parent.not_fb; +} +ROOM.prototype.is_enter = function () { + if (!this.parent) return false; + return this.parent.first == this.path; +} +ROOM.prototype.query_fb_first = function (id) { + //查询副本入口 + if (!this.parent || !this.parent.is_copy || !this.parent.rooms) return; + return this.parent.rooms[0].query_copy(id); +} +ROOM.prototype.query_copy = function (id) { + + if (!this.copy_rooms) this.copy_rooms = {}; + return this.copy_rooms[id]; +} +ROOM.prototype.query_copy2 = function (user) { + var id = this.parent.query_owner(user); + if (!id) return this; + return this.query_copy(id); +} +ROOM.prototype.clear_copy = function (me) { + //清除复制的副本,四个位置,换地图,完成副本,复活,彻底掉线 + //但是又不能清除不是自己的副本,比如帮派 + if (!this.owner) return; + let id = this.parent.query_owner(me); + if (id !== this.owner) return;//只能清除自己或队伍创建的副本 + var name = "fb/"; + for (var key in me.temp) { + if (key.startsWith(name)) { + me.temp[key] = null; + } + } + if (me.team) { + for (var i = 0; i < me.team.length; i++) { + let tm = me.team[i]; + if (tm !== me && tm.environment && tm.environment.parent === this.parent + && tm.environment.owner == this.owner) { + return; + } + } + } + this.clear_by_area(this.parent, this.owner); +} + +ROOM.prototype.create_copy2 = function (me, diff_type) { + + var id = this.parent.query_owner(me); + if (!id) return; + return this.create_copy(id, diff_type || 0); +} +ROOM.prototype.create_copy = function (id, diff_type) { + //第一次创建副本,从入口开始创建,把所在区域所有房间都创建一遍 + if (!this.parent) return; + // var rooms = []; + this.create_by_area(this.parent, id, diff_type); + //this.add_fbroom(rooms); + return this.query_copy(id); +} +ROOM.prototype.create_by_area = function (area, id, diff_type) { + if (area.rooms) { + for (var i = 0; i < area.rooms.length; i++) { + var base_room = area.rooms[i]; + var copy_room = BASE.CREATE(__PATH.MAP, base_room.path); + if (!copy_room) continue; + copy_room.set_difficulty(diff_type); + if (!base_room.copy_rooms) base_room.copy_rooms = {}; + base_room.copy_rooms[id] = copy_room; + copy_room.owner = id; + } + } + if (area.areas) { + for (var i = 0; i < area.areas.length; i++) { + this.create_by_area(area.areas[i], id); + } + } +} +ROOM.prototype.create_shadow = function () { + //当房间人满了后 进入房间就另外创建一个房间投影,这种类型的房间最好不要放NPC,物品 + //这种房间创建了不销毁,重复使用 + if (this.is_copy_room || this.no_shadow) return; + + if (!this.shadow_rooms) this.shadow_rooms = []; + for (var i = 0; i < this.shadow_rooms.length; i++) { + if (!this.shadow_rooms[i].is_full()) { + return this.shadow_rooms[i]; + } + } + var shadow = BASE.CREATE(__PATH.MAP, this.path); + if (shadow) { + this.shadow_rooms.push(shadow); + } + return shadow; +} +ROOM.prototype.clear_by_area = function (area, id) { + if (area.rooms) { + for (var i = 0; i < area.rooms.length; i++) { + var base_room = area.rooms[i]; + if (base_room.copy_rooms) { + var rm = base_room.copy_rooms[id]; + if (rm) { + WORLD.RUN_ROOMS.remove(rm); + rm.destroy(); + delete base_room.copy_rooms[id]; + + } + + } + } + } + if (area.areas) { + for (var i = 0; i < area.areas.length; i++) { + this.clear_by_area(area.areas[i], id); + } + } +} + +function getAreaByPath(path) { + var index = path.lastIndexOf("/"); + path = path.substr(0, index + 1); + var items = WORLD.AREAS; + for (var i = 0; i < items.length; i++) { + if (items[i].room_path == path) return items[i]; + } +} +ROOM.Get = function (path) { + var rm = WORLD.ROOMS[path]; + + if (!rm) return console.log("room %s is not exist", path); + // if (!rm) throw new Error(path + "is not exist"); + return rm; +} + + +//房间存储数据,存在当前用户或队伍的房间区域的第一个房间里面,在副本销毁时候会释放 +ROOM.prototype.query_temp = function (me, name, def) { + var first = this.query_fb_first(me.query_teamid()); + if (!first) return; + if (!first.temp) return; + var item = first.temp[name]; + if (item && item.e) { + if (Date.now() <= item.e) { + return item.v; + } + first.temp[name] = null; + return def; + } + return item || def; +} +ROOM.prototype.set_temp = function (me, name, value, time) { + var first = this.query_fb_first(me.query_teamid()); + if (!first) return; + if (!first.temp) first.temp = {}; + if (time) { + first.temp[name] = { + v: value, + e: Date.now() + time + }; + } else { + first.temp[name] = value; + } +} +ROOM.prototype.add_temp = function (me, name, value, time) { + let val = this.query_temp(me, name, 0) + value; + this.set_temp(me, name, val, time); + return val; +} +ROOM.RANDOM = function () { + if (!this.public_rooms) { + this.public_rooms = []; + for (var i = 0; i < WORLD.AREAS.length; i++) { + if (WORLD.AREAS[i].is_area && !WORLD.AREAS[i].is_public) { + var rms = WORLD.AREAS[i].rooms; + + for (var j = 0; j < rms.length; j++) { + if (rms[j].max_item_count > 1) + this.public_rooms.push(rms[j]); + } + } + } + } + return this.public_rooms.random(); +} +ROOM.prototype.set_difficulty = function (type) { + this.on_set_difficulty && this.on_set_difficulty(type); +} +ROOM.prototype.send = function (msg) { + for (var i = 0; i < this.items.length; i++) { + if (this.items[i].is_player) { + this.items[i].send(msg); + } + } +} +ROOM.prototype.find_me = function () { + for (var i = 0; i < this.items.length; i++) { + if (this.items[i].is_player) { + return this.items[i]; + } + } +} +ROOM.prototype.query = function (id) { + let room = ROOM.Get(id); + if (!room) return null; + if (this.owner) { + return room.query_copy(this.owner); + } + return room; +} diff --git a/os/skill/family.js b/os/skill/family.js new file mode 100644 index 0000000..fd7d9fe --- /dev/null +++ b/os/skill/family.js @@ -0,0 +1,94 @@ +FAMILY = function () { + this.titles = []; + this.npcs = []; + this.battle_family = null; + //this.scores = new Map(); + this.battle_score = 0; + this.battle_gift = 0; + this.can_battle = false; +} + +FAMILY.inherits(BASE); +FAMILIES = {}; +FAMILY.prototype.set_titles = function () { + for (var i = 0; i < arguments.length; i++) { + this.titles.push(arguments[i]); + } +} +FAMILY.prototype.create = function (path) { + FAMILIES[this.id] = this; + +} +FAMILY.prototype.update = function (path) { + FAMILIES[this.id] = this; +} +FAMILY.prototype.query_title = function (level) { + return this.titles[level]; +} + + +FAMILY.prototype.query_temp = CHARACTER.prototype.query_temp; +FAMILY.prototype.set_temp = CHARACTER.prototype.set_temp; +FAMILY.prototype.remove_temp = CHARACTER.prototype.remove_temp; +FAMILY.prototype.add_temp = CHARACTER.prototype.add_temp; + +FAMILY.prototype.send = function (str) { + for (var i = 0; i < WORLD.USERS.length; i++) { + if (WORLD.USERS[i].family == this) { + WORLD.USERS[i].send(str); + } + } +} +FAMILY.prototype.is_battle = function (fam) { + return this.battle_family == fam.id; +} +FAMILY.prototype.add_score = function (me, sc) { + this.battle_score += sc; +} + + + +CHARACTER.prototype.send_fam = function (str) { + this.family.send(str); +} +FAMILY.prototype.create_name = function () { + return UTIL.random_name(this.gender); +} +FAMILY.prototype.query_skill = function (grade) { + if (!this.skill_levels) { + this.skill_levels = []; + for (var i = 0; i < this.skills.length; i++) { + if (!this.skill_levels[this.skills[i].grade]) { + this.skill_levels[this.skills[i].grade] = []; + } + this.skill_levels[this.skills[i].grade].push(this.skills[i]); + } + } + if (grade >= this.skill_levels.length) grade = this.skill_levels.length - 1; + return this.skill_levels[grade].random(); +} +FAMILY.prototype.query_skills = function (grade) { + if (!this.skill_levels) { + this.skill_levels = []; + for (var i = 0; i < this.skills.length; i++) { + if (!this.skill_levels[this.skills[i].grade]) { + this.skill_levels[this.skills[i].grade] = []; + } + this.skill_levels[this.skills[i].grade].push(this.skills[i]); + } + } + if (grade >= this.skill_levels.length) grade = this.skill_levels.length - 1; + return this.skill_levels[grade]; +} +FAMILY.prototype.add_gongji = function (me, count) { + if (!count) return; + me.add_temp("gongji", count); + if (count < 0) return; + if (!this.tops) this.tops = {}; + var old = this.tops[me.id]; + if (!old) this.tops[me.id] = { name: me.name, score: count }; + else { + old.score += count; + } +} + diff --git a/os/skill/skill.js b/os/skill/skill.js new file mode 100644 index 0000000..fd2a993 --- /dev/null +++ b/os/skill/skill.js @@ -0,0 +1,648 @@ +/*global SKILL_TYPES SKILL BASE PROPERTIES WORLD FAMILIES*/ + +require("../util/util.js"); +SKILL = function () { + this.id = ""; + this.name = ""; + this.type = SKILL_TYPES.SKILL; + this.grade = 1; + this.score = 0; +} +SKILL.inherits(BASE); +SKILL.prototype.query_attack_action = function (me, target) { + if (this.attack_actions) + return this.attack_actions.random(); + return ""; +} +SKILL.prototype.query_dodge_action = function () { + if (!this.dodge_actions) { + return ""; + } + return this.dodge_actions.random(); +} +SKILL.prototype.query_parry_action = function (me, target, w2) { + var w1 = me.query_weapon(); + w2 = w2 || target.query_weapon(); + var act; + if (w1 && w2) { + act = this.weapon_vs_weapon_actions || this.parry_actions; + } else if (w1) { + act = this.weapon_vs_unarmed_actions || this.parry_actions; + } else if (w2) { + act = this.unarmed_vs_weapon_actions || this.parry_actions; + } else { + act = this.parry_actions; + } + + if (!act) { + act = this.parry_actions = SKILL.get("parry").parry_actions; + } + + if (act) { + return act.random(); + } +} + +SKILL.prototype.level_exp = function (lv, me) { + var grd = this.query_grade(me); + return (lv + 1) * (grd + 1) * 5; +} +SKILL.prototype.query_needexp = function (level, me) { + if (level > 100) { + var grd = this.query_grade(me); + var exp = (100 + level) * (level - 100) / 2; + return exp * (grd + 1) * 5; + } else { + return 0; + } +} + + +SKILL.prototype.set_default = function (type) { + WORLD.DEFAULT_SKILLS[type] = this; +} + +SKILL.prototype.release_prop = function (me, lv) { + if (!lv) return; + var prop = this.query_prop(lv, me); + if (prop) { + me.change_prop(prop, false); + } + prop = this.query_enable_prop(lv, me); + if (prop) { + for (var item in prop) { + if (me.is_enable_skill(this.id, item)) { + me.change_prop(prop[item], false); + } + } + } + prop = this.query_addin_prop(me, lv); + if (prop) { + if (this.is_enable(me)) { + me.change_prop(prop, false); + } + } +} + +SKILL.prototype.attach_prop = function (me, lv) { + if (!lv) return; + var prop = this.query_prop(lv, me); + if (prop) { + me.change_prop(prop, true); + } + prop = this.query_enable_prop(lv, me); + if (prop) { + for (var item in prop) { + if (me.is_enable_skill(this.id, item)) { + me.change_prop(prop[item], true); + } + } + } + prop = this.query_addin_prop(me, lv); + if (prop) { + if (this.is_enable(me)) { + me.change_prop(prop, true); + } + } +} +SKILL.prototype.query_enable_prop = function (lv) { + +} +SKILL.prototype.query_prop = function (lv) { + +} + +SKILL.prototype.query_grade = function (me) { + var sk = me.skills[this.id]; + var lv = this.grade; + if (sk) { + if (sk.addin) + lv += sk.addin.length; + if (sk.ref) + lv += 1; + } + + return lv; +} +SKILL.prototype.query_color_name = function (me) { + + var desc = level_color[this.query_grade(me)]; + return "<" + desc + ">" + this.name + ""; +} + +SKILL.prototype.query_addin_prop = function (me, lv) { + var sk = me.skills[this.id]; + if (sk.addin && sk.addin.length) { + var prop = {}; + var grd = this.grade + sk.addin.length; + for (let slot of sk.addin) { + let item = this.query_slot(slot); + if (!item) continue; + if (item.prop) { + prop[item.prop] = (prop[item.prop] ?? 0) + + parseInt(item.value(lv, grd)); + } + } + return prop; + } + return null; +} +SKILL.prototype.is_enable = function (me) { + if (this.type !== SKILL_TYPES.SKILL) return true; + var skill = me.skills[this.id]; + for (var i = 0; i < this.can_enables.length; i++) { + if (skill[this.can_enables[i]]) return true; + } + return false; +} +SKILL.prototype.is_enable2 = function (me, baseskill) { + var skill = me.skills[this.id]; + + return skill ? skill[baseskill] : false; +} +//激活技能,附加装备的部分属性 +SKILL.prototype.enable = function (me, type) { + if (!this.can_enables || !this.can_enables.contain(type)) return false; + if (this.on_enable && this.on_enable(me, type) === false) return false; + var lv = me.query_skill(this.id); + var prop = this.query_enable_prop(lv); + if (prop) { + var enable_prop = prop[type]; + if (enable_prop) { + me.change_prop(enable_prop, true); + } + } + //附加进阶属性 + prop = this.query_addin_prop(me, lv); + if (prop) { + if (!this.is_enable(me)) { + me.change_prop(prop, true); + } + } + return true; +} +//取消激活技能,解除装备的部分属性 +SKILL.prototype.disenable = function (me, type) { + this.on_disenable && this.on_disenable(me, type); + var lv = me.query_skill(this.id); + var prop = this.query_enable_prop(lv); + if (prop) { + var enable_prop = prop[type]; + if (enable_prop) { + me.change_prop(enable_prop, false); + } + } + + + //附加进阶属性 + prop = this.query_addin_prop(me, lv); + if (prop) { + if (!this.is_enable(me)) { + + me.change_prop(prop, false); + } + } + return true; +} +SKILL.prototype.do_learn = function (me) { + if (this.on_learn && this.on_learn(me) === false) return false; + if (this.learn_condition) { + for (var key in this.learn_condition) { + var val = this.learn_condition[key]; + switch (key) { + case "skill": + for (var sk in val) { + if (me.query_skill(sk, 0) < val[sk] && me.query_skill(sk + "2", 0) < val[sk]) { + var sk_base = SKILL.get(sk); + + return me.notify_fail("你的" + sk_base.color_name + "等级不够" + val[sk] + ",无法学习" + this.color_name + "。"); + } + } + break; + case "str1": + case "con1": + case "dex1": + case "int1": + if (me.is_player && me[key.replace("1", "")] < val) { + return me.notify_fail("你的" + PROPERTIES[key] + "不够" + val + ",无法学习" + this.color_name + "。"); + } + break; + case "str": + case "con": + case "dex": + case "int": + if (me[key] + me.query_prop(key) < val) { + return me.notify_fail("你的" + PROPERTIES[key] + "不够" + val + ",无法学习" + this.color_name + "。"); + } + break; + case "gender": + if (me.gender !== val) return me.notify_fail("你不是" + (val === 1 ? "男性" : val === 2 ? "女性" : "无性") + ",无法学习" + this.color_name + "。"); + break; + case "desc": + break; + default: + var me_val = me[key] || 0; + me_val = me_val + me.query_prop(key); + if (!me_val || me_val < val) { + + return me.notify_fail("你的" + PROPERTIES[key] + "不够" + val + ",无法学习" + this.color_name + "。"); + } + break; + } + } + } else { + if (this.type === SKILL_TYPES.SKILL && this.can_enables) { + for (var i = 0; i < this.can_enables.length; i++) { + if (!me.query_skill(this.can_enables[i], 0)) { + var skill = SKILL.get(this.can_enables[i]); + return me.notify_fail("你还不会" + skill.color_name + ",无法学习" + this.color_name + "。"); + } + } + } + } + return true; +} + +SKILL.prototype.condition_tostring = function (me) { + if (this.learn_condition_string) return this.learn_condition_string; + var str = []; + if (this.learn_condition) { + for (var key in this.learn_condition) { + var val = this.learn_condition[key]; + switch (key) { + case "skill": + for (var sk in val) { + var sk_base = SKILL.get(sk); + str.push(sk_base.name + ":" + val[sk] + "级"); + } + break; + case "desc": + str.push(val); + break; + case "gender": + str.push("性别:" + (val === 1 ? "男" : (val === 2 ? "女" : "无性"))); + break; + default: + str.push(PROPERTIES[key] + ":" + val); + break; + } + } + } + this.learn_condition_string = str.join("\n"); + return this.learn_condition_string; +} +SKILL.prototype.item_to_json = function (str, skill_item, me) { + str.push('{"id":"'); + str.push(this.id); + + str.push('","name":"'); + str.push(this.query_color_name(me)); + str.push('",grade:', this.query_grade(me)); + str.push(',"level":'); + str.push(me.query_skill(this.id)); + str.push(',"exp":'); + skill_item.exp = skill_item.exp || 0; + str.push(parseInt(skill_item.exp * 100 / this.level_exp(skill_item.level, me))); + if (this.can_enables) { + str.push(',"can_enables":['); + for (var i = 0; i < this.can_enables.length; i++) { + if (i > 0) str.push(","); + str.push('"'); + str.push(this.can_enables[i]); + str.push('"'); + } + str.push(']'); + } + + if (skill_item.enable_skill) { + str.push(',"enable_skill":"'); + str.push(skill_item.enable_skill); + str.push('"'); + } + str.push('}'); +} +SKILL.prototype.add_exp = function (me, exp) { + var skill = me.skills[this.id]; + if (!skill) { + skill = { + // id: this.id, + level: 0, + exp: 0 + }; + var str = ['{type:"dialog",dialog:"skills",item:']; + this.item_to_json(str, skill, me); + str.push("}"); + me.notify(str.join("")); + me.skills[this.id] = skill; + if (this.type === SKILL_TYPES.BASE) { + me.init_skill(); + } + } + var need_exp = this.level_exp(skill.level, me); + skill.exp += exp; + if (skill.exp >= need_exp) { + this.release_prop(me, me.query_skill(this.id)); + var sum_score = 0; + var color_name = this.query_color_name(me); + var one_score = this.query_one_score(me); + while (skill.exp >= need_exp) { + skill.exp -= need_exp; + need_exp = this.level_exp(skill.level, me); + me.notify("你的" + color_name + "等级提升了!"); + skill.level++; + if (skill.level > 100) + sum_score += one_score; + } + var lv = me.query_skill(this.id); + this.attach_prop(me, lv); + me.notify('{type:"dialog",dialog:"skills",id:"' + this.id + '",level:' + lv + ',exp:' + parseInt(skill.exp * 100 / need_exp) + '}'); + me.recount(); + me.add_score(sum_score); + return true; + } else { + me.notify('{type:"dialog",dialog:"skills",id:"' + this.id + '",exp:' + parseInt(skill.exp * 100 / need_exp) + '}'); + } +} +SKILL.prototype.query_score = function (lv, me) { + if (lv <= 100) return 0; + return (lv - 100) * this.query_one_score(me); +} + +SKILL.prototype.query_one_score = function (me) { + var sc = 0; + if (this.type === SKILL_TYPES.SKILL) { + sc = this.query_grade(me); + } else if (this.type === SKILL_TYPES.BASE) { + sc = 1; + } + return sc; +} +SKILL.prototype.grade_up = function (me, target_skill) { + var skill = me.skills[this.id]; + if (!skill || !(skill.level >= 1000)) return false; + + if (me.remove_skill(this.id) === false) return false; + me.notify('{type:"dialog",dialog:"skills",remove:"' + this.id + '"}'); + var pot = this.query_needexp(skill.level, me); + var lv = pot * 2 / 5 / (target_skill.grade + 1); + skill = { + level: parseInt(Math.pow(lv, 0.5)), + exp: 0 + }; + me.skills[target_skill.id] = skill; + var str = ['{type:"dialog",dialog:"skills",item:']; + target_skill.item_to_json(str, skill, me); + str.push("}"); + me.notify(str.join("")); + me.add_score(target_skill.query_score(skill.level, me)); + target_skill.attach_prop(me, skill.level); + me.recount(); + return true; +} +SKILL.prototype.get_pfm = function (name) { + if (this.pfm) { + return this.pfm[name]; + } +} +SKILL.prototype.set_pfm = function (name, obj) { + if (!this.pfm) { + this.pfm = {}; + } + this.pfm[name] = obj; +} +var level_color = ["wht", "hig", "hic", "hiy", "hiz", "hio", "ord"]; +var level_desc = ["基本技能", "普通技能", "高级技能", "稀有武技", "绝世武功", "绝世神功", "无上神武"]; + +SKILL.prototype.create = function (fname) { + if (WORLD.SKILLS[this.id]) { + console.log("%s [%s] is repeated ", this.id, fname); + } + this.update(fname); +} +SKILL.prototype.store = function () { + if (this.type === SKILL_TYPES.KNOWLEDGE + || this.type === SKILL_TYPES.BASE + ) return; + for (var i = 0; i < this.can_enables.length; i++) { + if (!SKILL[this.can_enables[i]]) SKILL[this.can_enables[i]] = new Array(7); + if (!SKILL[this.can_enables[i]][this.grade]) SKILL[this.can_enables[i]][this.grade] = []; + SKILL[this.can_enables[i]][this.grade].push(this); + } +} + +SKILL.prototype.update = function (fname) { + WORLD.SKILLS[this.id] = this; + var fam = this.family || FAMILIES.NONE; + if (!fam.skills2) fam.skills2 = []; + if (!fam.skills) fam.skills = []; + if (!fam.skills3) fam.skills3 = []; + if (!fam.skills4) fam.skills4 = []; + var isAddIn = false; + var ary = this.source_skill ? + (this.is_ultimate ? fam.skills3 : fam.skills2) : + (this.is_ultimate ? fam.skills4 : fam.skills); + if (this.type === SKILL_TYPES.KNOWLEDGE || this.is_hidden) { + if (!fam.skills0) fam.skills0 = []; + ary = fam.skills0; + } + for (var i = 0; i < ary.length; i++) { + if (ary[i].id === this.id) { + ary[i] = this; + isAddIn = true; + break; + } + if (ary[i].grade > this.grade) { + ary.splice(i, 0, this); + isAddIn = true; + break; + } + } + if (!isAddIn) { + ary.push(this); + } + this.store(); + + var desc = level_color[this.grade]; + this.color_name = "<" + desc + ">" + this.name + ""; + if (this.pfm) { + for (var key in this.pfm) { + var pfm = this.pfm[key]; + if (pfm.enable_skill === 'sword' || pfm.enable_skill === 'blade' || pfm.enable_skill === 'whip' + || pfm.enable_skill === 'staff' || pfm.enable_skill === 'club') { + pfm.is_weapon = true; + } + pfm.id = this.id + "/" + key; + pfm.pid = key; + pfm.__proto__ = PERFORM.prototype; + } + } +} +SKILL.get = function (id) { + return WORLD.SKILLS[id]; +} +SKILL.prototype.query_desc = function (me, lv) { + var str = []; + var grd = this.query_grade(me); + var cc = level_color[grd]; + str.push("<" + cc + ">" + this.name + ""); + str.push("\n"); + if (this.family) { + str.push(this.family.name); + } else { + str.push("公共"); + } + str.push(level_desc[grd]); + str.push("\n"); + + str.push(this.desc); + str.push("\n"); + var prop = this.query_prop(lv, me); + if (prop) { + str.push("<"); + str.push(cc); + str.push(">"); + str.push(UTIL.prop_toString(prop)); + str.push("\n"); + } + prop = this.query_enable_prop(lv, me); + var isEnable = this.type === SKILL_TYPES.KNOWLEDGE; + if (prop) { + for (var item in prop) { + var is_enable = me.is_enable_skill(this.id, item); + if (is_enable) isEnable = true; + str.push("<"); + str.push(is_enable ? cc : "blk"); + str.push(">当装备为"); + str.push(SKILL.get(item).name); + str.push("时:\n"); + str.push(UTIL.prop_toString(prop[item])); + str.push("\n"); + } + } + var sk = me.skills[this.id]; + if (sk && sk.addin && sk.addin.length) { + str.push("\n<"); + str.push(isEnable ? cc : "blk"); + str.push(">"); + + let grd = this.grade + sk.addin.length; + for (let slot of sk.addin) { + let item = this.query_slot(slot); + if (item) { + str.push("◆"); + if (item.name) { + str.push(item.name); + str.push(" "); + } + str.push(item.format(parseInt(item.value(lv, grd)))); + str.push("\n"); + } + } + str.push("\n"); + } + if (this.pfm) { + str.push("绝招\n"); + for (let item in this.pfm) { + var p_item = this.pfm[item]; + if (!p_item.name) continue; + this.query_pfm_desc(me, p_item, str, lv); + str.push("\n\n"); + + } + } + if (sk && sk.ref) { + var refs = sk.ref.split("/"); + var sp_skill = SKILL.get(refs[0]); + if (sp_skill) { + var pfm = sp_skill.get_pfm(refs[1]); + if (pfm) { + this.query_pfm_desc(me, pfm, str, lv, sp_skill.name); + str.push("\n\n"); + } + } + + + } + return str.join(""); +} +SKILL.prototype.query_slot = function (index) { + if (index < 500) { + return SKILL.PROPERTIES[index]; + } else { + return this.slots ? this.slots[index - 500] : null; + } +} +SKILL.REF_CD = 2; +SKILL.SLOTS = {}; +SKILL.prototype.query_pfm_desc = function (me, p_item, str, lv, pname) { + var canuse = !p_item.check || p_item.check(me, lv) === true; + var color = canuse ? "hic" : "red"; + if (pname) color = 'hir'; + str.push("<"); + str.push(color); + str.push(">【"); + if (pname) { + str.push(pname); + str.push("•"); + + } + str.push(p_item.name); + str.push("】"); + if (!canuse) { + str.push(p_item.use_condition || ""); + } + str.push(""); + if (pname) lv = parseInt(lv / 2); + str.push("\n内力消耗:"); + str.push(p_item.query_mp(me, lv)); + str.push("\t出招时间:"); + str.push(p_item.query_releasetime(me, lv) / 1000); + str.push("秒\t冷却时间:"); + str.push(p_item.query_distime(me, lv, pname) / 1000); + str.push("秒\n"); + str.push(p_item.query_desc(me, lv)); +} + + +PERFORM = function () { + this.name = ""; +} +PERFORM.inherits(BASE); + +PERFORM.prototype.query_name = function (me) { + return this.name; +} + +PERFORM.prototype.change_distime = function (me, id, add_time) { + if (me.is_player) { + var dis_time = me.temp["pfm/" + id]; + if (dis_time) { + if (add_time) + dis_time.e += add_time; + else { + add_time = -dis_time.time; + dis_time.e = 1; + } + me.notify('{type:"changepfm",id:"' + id + '",time:' + add_time + '}'); + } + } else if (me.auto_skills) { + for (var i = 0; i < me.auto_skills.length; i++) { + var item = me.auto_skills[i]; + if (item.pfm === this) { + if (add_time) + item.release_time += add_time; + else + item.release_time = 0; + } + } + } + +} diff --git a/os/task/events.js b/os/task/events.js new file mode 100644 index 0000000..3e88d08 --- /dev/null +++ b/os/task/events.js @@ -0,0 +1,49 @@ + +EVENTS = function () { + +} +EVENTS.inherits(BASE); + +EVENTS.add = function (item) { + if (!item || !item.id) return; + Object.setPrototypeOf(item, EVENT_BASE); + const items = WORLD.USER_EVENTS; + for (var i = 0; i < items.length; i++) { + if (items[i].id == item.id) { + items[i] = item; + return this.notify(item, 1); + } + } + items.push(item); + this.notify(item, 0); +} +EVENTS.ACTIONS = ['add', 'update', 'finish']; +EVENTS.notify = function (item, act) { + let users = WORLD.USERS; + let msg = `{type: "dialog", dialog: "events",${EVENTS.ACTIONS[act]}:1}`; + for (let user of users) { + if (!user.socket) continue; + if (item.check && !item.check(user)) + continue; + user.send(msg); + } +} +EVENTS.remove = function (id) { + if (!id) return; + const items = WORLD.USER_EVENTS; + for (var i = 0; i < items.length; i++) { + if (items[i].id == id) { + EVENTS.notify(items[i], 2); + return items.splice(i, 1); + } + } +} + +const EVENT_BASE = { + query_desc: function () { + return this.desc; + }, + query_grade: function () { + return this.grade; + } +}; \ No newline at end of file diff --git a/os/task/playertask.js b/os/task/playertask.js new file mode 100644 index 0000000..6778da2 --- /dev/null +++ b/os/task/playertask.js @@ -0,0 +1,48 @@ +require("../util/util"); +USERTASK = function () { + +} +USERTASK.inherits(BASE); + +USERTASK.prototype.create = function (path) { + WORLD.TASKS.push(this); + + this.on_create && this.on_create(); +} +USERTASK.prototype.update = function (path) { + this.on_create && this.on_create(); + for (var i = 0; i < WORLD.TASKS.length; i++) { + if (WORLD.TASKS[i].path == path) { + WORLD.TASKS[i] = this; + return; + } + } + WORLD.TASKS.push(this); +} +USERTASK.prototype.query_title = function () { + +} +USERTASK.prototype.start = function () { + +} +USERTASK.prototype.query_desc = function () { + +} +USERTASK.prototype.query_state = function () { + //0 不显示 1,进行中,2.可领取 3.已完成 +} +USERTASK.RUN = function (id, player) { + for (var i = 0; i < WORLD.TASKS.length; i++) { + if (WORLD.TASKS[i].id == id) { + return WORLD.TASKS[i].start(player); + } + } + return false; +} +USERTASK.GET = function (id) { + for (var i = 0; i < WORLD.TASKS.length; i++) { + if (WORLD.TASKS[i].id == id) { + return WORLD.TASKS[i]; + } + } +} \ No newline at end of file diff --git a/os/task/task.js b/os/task/task.js new file mode 100644 index 0000000..c9bc99d --- /dev/null +++ b/os/task/task.js @@ -0,0 +1,36 @@ + +TASK = function () { + +} +TASK.inherits(BASE); +TASK.prototype.create = function () { + WORLD.SYSTEMTASKS.push(this); + this.startup(); +} +TASK.GET = function (id) { + for (var i = 0; i < WORLD.SYSTEMTASKS.length; i++) { + if (WORLD.SYSTEMTASKS[i].id == id) { + return WORLD.SYSTEMTASKS[i]; + } + } +} +TASK.prototype.update = function (path) { + var oldtask = null; + for (var i = 0; i < WORLD.SYSTEMTASKS.length; i++) { + if (WORLD.SYSTEMTASKS[i].path == path) { + WORLD.SYSTEMTASKS[i].stop(); + oldtask = WORLD.SYSTEMTASKS[i]; + WORLD.SYSTEMTASKS[i] = this; + } + } + if (!oldtask) { + WORLD.SYSTEMTASKS.push(this); + } + this.startup(oldtask); +} +TASK.prototype.startup = function () { + +} +TASK.prototype.stop = function () { + +} \ No newline at end of file diff --git a/os/util/data.js b/os/util/data.js new file mode 100644 index 0000000..f193368 --- /dev/null +++ b/os/util/data.js @@ -0,0 +1,154 @@ + +const fs_sync = require("fs"); +const fs = fs_sync.promises; + +const DB = __CONFIG.DB; + +module.exports = { + close: function () { + return DB.close(); + }, + getRoles: function (userid, server) { + return DB.getRoles(userid, server); + }, + addRole: async function (role) { + return await DB.addRole(role); + }, + deleteRole: function (userid, roleid) { + return DB.deleteRole(userid, roleid); + }, + saveRole: function (role) { + return DB.saveRole(role); + }, + saveRoles: async function (roles) { + const dt = new Date(); + const path = __PATH.DATA + "bak/data" + dt.getFullYear() + "-" + (dt.getMonth() + 1) + "-" + dt.getDate() + "-" + dt.getHours() + ".js"; + const stream = fs_sync.createWriteStream(path, { flags: 'a' }); + try { + stream.write('['); + for (let role of roles) { + await DB.saveRole(role); + this.localBak(stream, role); + + } + stream.write('0]'); + } catch (error) { + console.error('备份数据失败:', error); + } finally { + stream.end(); + } + + }, + localBak: function (stream, role) { + stream.write('{id:"'); + stream.write(role.id); + stream.write('",name:"'); + stream.write(role.name); + stream.write('",userid:'); + stream.write(role.userid.toString()); + stream.write(',title:"'); + stream.write(role.title); + stream.write('",level:'); + stream.write(role.level.toString()); + stream.write(',data:'); + stream.write(role.data); + stream.write('},'); + }, + saveRequest: function (recs) { + var dt = new Date(); + var f = dt.getFullYear() + "-" + (dt.getMonth() + 1) + "-" + dt.getDate(); + var path = __PATH.DATA + "req/request" + f + ".txt"; + var ary = []; + for (var i = 0; i < recs.length; i++) { + var r = recs[i]; + ary.push(r.time); + ary.push(" "); + ary.push(r.user); + ary.push(" "); + ary.push(r.cmd); + ary.push("\r\n"); + } + return fs.appendFile(path, ary.join("")); + }, + saveLogs: function (logs) { + var dt = new Date(); + var f = dt.getFullYear() + "-" + (dt.getMonth() + 1) + "-" + dt.getDate(); + var path = __PATH.DATA + "log/log" + f + ".txt"; + var ary = []; + for (var i = 0; i < logs.length; i++) { + var r = logs[i]; + ary.push(r.time); + ary.push(" "); + ary.push(r.user); + ary.push(" "); + ary.push(r.cmd); + ary.push(" "); + ary.push(r.msg); + ary.push("\r\n"); + } + return fs.appendFile(path, ary.join("")); + }, + saveData: async function (content) { + let path = __PATH.DATA + "data.js"; + let dt = new Date(); + var f = dt.getFullYear() + "-" + (dt.getMonth() + 1) + "-" + dt.getDate(); + let _dst = __PATH.DATA + "/temp/temp" + f + ".js"; + await fs.copyFile(path, _dst); + return fs.writeFile(path, content); + }, readData: async function () { + let path = __PATH.DATA + "data.js"; + try { + const data = await fs.readFile(path); + return JSON.toObject(data); + } catch (error) { + console.error('数据读取失败', path, error); + } + }, + getRoleData: function (userid, id) { + + return DB.getData(userid, id); + }, + change_name: function (id, name) { + return DB.updateRoleName(id, name); + }, + change_userid: function (id, fromuserid, touserid) { + return DB.updateUserid(id, fromuserid, touserid); + }, + check_file: async function (path) { + try { + await fs.access(path) + return true; + } catch (error) { + return false; + } + }, + initDataDir: async function () { + __PATH.BASE_DATA = __PATH.DATA; + __PATH.DATA = __PATH.DATA + WORLD.SERVERID + "/"; + + if (!await this.check_file(__PATH.DATA)) { + console.log('创建备份文件夹....'); + await fs.mkdir(__PATH.DATA); + } + var paths = await fs.readdir(__PATH.DEF_DATA); + for (var i = 0; i < paths.length; i++) { + var _src = __PATH.DEF_DATA + paths[i]; + var _dst = __PATH.DATA + paths[i]; + if (!await this.check_file(_dst)) { + var stat = await fs.stat(_src); + if (stat.isFile()) { + await fs.copyFile(_src, _dst); + console.log('创建备份文件 ', _dst, "...."); + } else { + await fs.mkdir(_dst); + console.log('创建备份文件夹 ', _dst, "...."); + } + } + + } + }, + getServers: function () { + return DB.getServers(); + } +}; + diff --git a/os/util/util.js b/os/util/util.js new file mode 100644 index 0000000..6640052 --- /dev/null +++ b/os/util/util.js @@ -0,0 +1,406 @@ + + +const util = require('util'); +const JSON5 = require('json5'); +//nodejs自带的原型继承方法 +Function.prototype.inherits = function (superCtor) { + + util.inherits(this, superCtor); +} +Array.prototype.remove = function (item) { + for (var i = 0; i < this.length; i++) { + if (this[i] == item) { + this.splice(i, 1); + return true; + } + } +} +Array.prototype.contain = function (item) { + for (var i = 0; i < this.length; i++) { + if (this[i] === item) { + return true; + } + } + return false; +} +Array.prototype.random = function (index) { + index = index || this.length; + return this[Math.floor(Math.random() * this.length)]; +} +JSON.toObject = function (str) { + return JSON5.parse(str); + +} +UTIL = { + empty: function () { + }, + require: function (str) { + return require(str); + }, + is_gift: function () { + return false; + }, + wrandom: function (me, max, rate = 86400000) { + let key = parseInt(me.id[0], 36); + if (!(key >= 0)) key = 1; + let time = Math.floor(Date.now() / rate) + key; + return time % max; + }, + moneyToStr: function (value) { + if (!value) return ""; + var str = []; + if (value >= 10000) { + str.push(parseInt(value / 10000) + "两黄金"); + value = value % 10000; + } + if (value > 100) { + str.push(parseInt(value / 100) + "两白银"); + value = value % 100; + } + if (value > 0) { + str.push(value + "个铜板"); + } + return str.join(""); + }, + timeSpan: function (time) { + let str = []; + if (time > 86400000) { + str.push(Math.floor(time / 86400000), '天'); + time = time % 86400000; + } + if (time > 3600000) { + str.push(Math.floor(time / 3600000), '小时'); + time = time % 3600000; + } + if (time > 60000) { + str.push(Math.floor(time / 60000), '分钟'); + time = time % 60000; + } + str.push(Math.floor(time / 1000), '秒'); + return str.join(""); + }, + C_STR: "零一二三四五六七八九", + C_STR2: ["", "十", "百", "千", "万", "亿"], + C_STR3: ["", "万", "亿"], + to_c: function (num) { + if (!num) return ""; + var str = ""; + var count = 0; + var add = 0;//0=0,1=数 2=百十千 3=万亿 + while (num) { + var d = num % 10; + if (count) { + if (count % 4 == 0 && add != 3) { + str = UTIL.C_STR3[count / 4] + str; + add = 3; + } else if (d && add != 2) { + str = UTIL.C_STR2[count % 4] + str; + add = 2; + } + } + if (d) { + if (d != 1 || num > 10 || count % 4 != 1) + str = UTIL.C_STR[d] + str; + add = 1; + } else if (add == 1) { + str = UTIL.C_STR[d] + str; + add = 0; + } + num = parseInt(num / 10); + count++; + } + return str; + }, + htmlEncode: function (str) { + if (!str) return str; + return str.replace(/>/g, ">") + .replace(/ 0 ? + str.push(PROPERTIES[item] + ":-" + (prop[item] * count / 1000) + "秒") + : + str.push(PROPERTIES[item] + ":+" + (-prop[item] * count / 1000) + "秒"); + break; + case "diff_busy": + case "busy": + case "gjsd": + case "diff_downside": + prop[item] > 0 ? + str.push(PROPERTIES[item] + ":+" + (prop[item] * count / 1000) + "秒") + : + str.push(PROPERTIES[item] + ":" + (prop[item] * count / 1000) + "秒"); + break; + case "expend_mp_per": + case "distime_per": + case "releasetime_per": + prop[item] > 0 ? + str.push(PROPERTIES[item] + ":-" + (prop[item] * count) + "%") + : + str.push(PROPERTIES[item] + ":+" + (prop[item] * -count) + "%"); + break; + case "lianxi_per": + case "dazuo_per": + case "study_per": + case "add_sh_per": + case "add_bjsh_per": + case "busy_per": + case "gjsd_per": + case "bj_per": + case "zj_per": + case "ds_per": + case "fy_per": + case "diff_sh_per": + case "diff_sh_per2": + case "diff_fy_per": + case "diff_fy_per2": + case "diff_busy_per": + case "mz_per": + case "gj_per": + case "diff_bj": + case "hp_per": + case "money_per": + case "diff_downside_per": + case "recover_per": + prop[item] > 0 ? + str.push(PROPERTIES[item] + ":+" + (prop[item] * count) + "%") + : + str.push(PROPERTIES[item] + ":" + (prop[item] * count) + "%"); + break; + case "skill": + var skills = prop[item]; + for (var sk in skills) { + var sk_base = SKILL.get(sk); + if (sk_base) + str.push(sk_base.name + ":+" + skills[sk] + "级"); + } + + break; + case "age": + prop[item] > 0 ? + str.push(PROPERTIES[item] + ":-" + prop[item] * count + "岁") + : + str.push(PROPERTIES[item] + ":+" + (-prop[item]) * count + "岁"); + break; + case "expend_mp": + prop[item] > 0 ? + str.push(PROPERTIES[item] + ":-" + prop[item] * count) + : + str.push(PROPERTIES[item] + ":+" + (-prop[item]) * count); + break; + default: + let p = PROPERTIES[item]; + if (p) { + prop[item] > 0 ? + str.push(PROPERTIES[item] + ":+" + prop[item] * count) + : + str.push(PROPERTIES[item] + ":" + prop[item] * count); + } else { + p = SKILL.SLOTS[item]; + if (p) { + str.push(p.format(prop[item] * count)); + } + } + + break; + } + } + return str.join(sp || "\n"); + }, + diff_time: function (next_hour) { + //到清理临时temp( 明天5点)的时间 + next_hour = next_hour || 5; + var dt = new Date(); + var hour = dt.getHours(); + var day = dt.getDate(); + if (hour >= next_hour) day = day + 1; + dt = new Date(dt.getFullYear(), dt.getMonth(), day, next_hour); + return dt - Date.now(); + }, + diff_week_time: function (next_hour) { + //到清理临时temp( 每周一5点)的时间 + next_hour = next_hour || 5; + var date = new Date(); + var week = date.getDay(); + week = week == 0 ? 1 : 8 - week; + if (week == 7 && date.getHours() < next_hour) { + week = 0; + } + var next_date = new Date(date.getFullYear(), date.getMonth(), date.getDate() + week, next_hour); + + + return next_date - Date.now(); + }, diff_month_time: function (next_hour) { + + //到清理临时temp( 每周一5点)的时间 + next_hour = next_hour || 5; + var date = new Date(); + + if (date.getDate() > 1 || date.getHours() >= next_hour) { + date = new Date(date.setMonth(date.getMonth() + 1, 1)); + } + + var next_date = new Date(date.getFullYear(), date.getMonth(), 1, next_hour); + // me.send(next_date.getFullYear() + "年" + (date.getMonth() + 1)+ "月" + 1 + "日" + next_hour); + + return next_date - Date.now(); + }, + logs: [], + log: function (msg) { + + this.logs.push({ + dt: Date.now, + content: msg + }); + }, + saveLog: function () { + if (!this.logs) return; + + var fs = require("fs"); + var dt = new Date(); + var path = __PATH.DATA + "log/"; + if (!fs.existsSync(path)) { + fs.mkdirSync(path); + } + var file = path + (dt.getMonth() + 1) + "-" + dt.getDate() + "-" + dt.getHours() + ".log"; + fs.writeFileSync(path, JSON.stringify(this.logs)); + }, + idstr: "0123456789abcdefghijklmnopqrstuvwxwz", + begin: 1490276099978, + create_id: function () { + var str = []; + for (var i = 0; i < 4; i++) { + str.push(this.idstr[parseInt(Math.random() * this.idstr.length)]); + } + str.push(parseInt((Date.now() - this.begin) / 1000).toString(16)); + return str.join(""); + }, + random_name: function (s, t) { + t = t || (parseInt(Math.random() * 2) + 1); + var str = []; + if (t == 2) { + var key = parseInt(Math.random() * this.name0.length); + if (key % 2 == 1) key -= 1; + str.push(this.name0[key++]); + str.push(this.name0[key]); + } else { + str.push(this.name1[parseInt(Math.random() * this.name1.length)]); + } + if (s == 0) { + str.push(this.name2[parseInt(Math.random() * this.name2.length)]); + } else { + str.push(this.name3[parseInt(Math.random() * this.name3.length)]); + } + if (parseInt(Math.random() * 4) > 1) { + if (s == 0) { + str.push(this.name2[parseInt(Math.random() * this.name2.length)]); + } else { + str.push(this.name3[parseInt(Math.random() * this.name3.length)]); + } + } + return str.join(""); + }, + name0: "万俟司马上官欧阳夏侯诸葛闻人东方赫连皇甫尉迟公羊澹台公冶宗政濮阳淳于单于太叔申屠公孙仲孙轩辕令狐锺离宇文长孙慕容鲜于闾丘司徒司空丌官司寇子车颛孙端木巫马公西乐正公良拓拔夹谷谷梁梁丘左丘东门西门", + name1: "赵钱孙李周吴郑王冯陈楮卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛奚范彭郎", + + name2: "世舜丞主产仁仇仓仕仞任伋众伸佐佺侃侪促俟信俣修倝倡倧偿储僖僧僳儒俊伟列则刚创前剑助劭势勘参叔吏嗣士壮孺守宽宾宋宗宙宣实宰尊峙峻崇崈川州巡帅庚战才承拯操斋昌晁暠曹曾珺玮珹琒琛琩琮琸瑎玚璟璥瑜生畴矗矢石磊砂碫示社祖祚祥禅稹穆竣竦综缜绪舱舷船蚩襦轼辑轩子杰榜碧葆莱蒲天乐东钢铎铖铠铸铿锋镇键镰馗旭骏骢骥驹驾骄诚诤赐慕端征坚建弓强彦御悍擎攀旷昂晷健冀凯劻啸柴木林森朴骞寒函高魁魏鲛鲲鹰丕乒候冕勰备宪宾密封山峰弼彪彭旁日明昪昴胜汉涵汗浩涛淏清澜浦澉澎澔瀚瀛灏沧虚豪豹辅辈迈邶合部阔雄霆震韩俯颁颇频颔风飒飙飚马亮仑仝代儋利力劼勒卓哲喆展帝弛弢弩彰征律德志忠思振挺掣旲旻昊昮晋晟晸朕朗段殿泰滕炅炜煜煊炎选玄勇君稼黎利贤谊金鑫辉墨欧有友闻问", + + name3: "筠柔竹霭凝晓欢霄枫芸菲寒伊亚宜姬舒影荔枝思丽秀娟英华慧巧美娜静淑惠珠翠雅芝玉萍红娥玲芬芳燕彩春菊勤珍贞莉兰凤洁梅琳素云莲真环雪荣妹霞香月莺媛艳瑞凡佳嘉琼桂娣叶璧璐娅琦晶妍茜秋珊莎锦黛青倩婷姣婉娴瑾颖露瑶怡婵雁蓓纨仪荷丹蓉眉君琴蕊薇菁梦岚苑婕馨瑗琰韵融园艺咏卿聪澜纯毓悦昭冰爽琬茗羽希宁欣飘育滢馥", + + getLunar: function (date) { + date = date || new Date(); + //农历函数开始 + var lunarInfo = new Array(0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, //1990 + 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, 0x14b63); + function lYearDays(y) { + var i, sum = 348; + for (i = 0x8000; i > 0x8; i >>= 1) sum += (lunarInfo[y - 1900] & i) ? 1 : 0; + return (sum + leapDays(y)); + } + function leapDays(y) { + if (leapMonth(y)) return ((lunarInfo[y - 1900] & 0x10000) ? 30 : 29); + else return (0); + } + function leapMonth(y) { + return (lunarInfo[y - 1900] & 0xf); + } + function monthDays(y, m) { + return ((lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29); + } + function Lunar(y, m, d) { + var i, leap = 0, + temp = 0; + var offset = (Date.UTC(y, m, d) - Date.UTC(1900, 0, 31)) / 86400000; + for (i = 1900; i < 2050 && offset > 0; i++) { + temp = lYearDays(i); + offset -= temp; + } + if (offset < 0) { + offset += temp; + i--; + } + this.year = i; + leap = leapMonth(i); + this.isLeap = false; + for (i = 1; i < 13 && offset > 0; i++) { + if (leap > 0 && i == (leap + 1) && this.isLeap == false) { + --i; + this.isLeap = true; + temp = leapDays(this.year); + } else { + temp = monthDays(this.year, i); + } + if (this.isLeap == true && i == (leap + 1)) this.isLeap = false; + offset -= temp; + } + if (offset == 0 && leap > 0 && i == leap + 1) if (this.isLeap) { + this.isLeap = false; + } else { + this.isLeap = true; --i; + } + if (offset < 0) { + offset += temp; --i; + } + this.month = i; + this.day = offset + 1; + } + + return new Lunar(date.getFullYear(), date.getMonth(), date.getDate()); + }, + isLunar15: function (dt) { + let issuc = WORLD.DATA.query_temp('lunar15', 0); + if (issuc === 0) { + let now = dt || new Date(); + let hour = now.getHours(); + var lunar = UTIL.getLunar(now); + if ((lunar.day === 14 && hour >= 5) || lunar.day === 15 + || (lunar.day === 16 && hour < 5)) { + + WORLD.DATA.set_temp('lunar15', 1, UTIL.diff_time()); + issuc = 1; + } else { + WORLD.DATA.set_temp('lunar15', -1, UTIL.diff_time()); + issuc = -1; + } + } + return issuc > 0; + + } + + +}; diff --git a/os/world.js b/os/world.js new file mode 100644 index 0000000..79bb7ee --- /dev/null +++ b/os/world.js @@ -0,0 +1,341 @@ + +require("./util/util"); +const db = require("./util/data"); +WORLD = { + USERS: [], + COMMANDS: {}, + SKILLS: {}, + ROOMS: {}, + RUN_ROOMS: [], + DEFAULT_SKILLS: {}, + AREAS: [], + TASKS: [], + SYSTEMTASKS: [], + USER_EVENTS: [], + OBJ_STROE: new Map(), + NPC_STROE: new Map(), + HEARTBEATCOUNT: 0, + RECEIVED: [], + LOGS: [], + SERVERID: 0, + SERVERS: [], + CONNECT_COUNT: 0, + DATA: require('./data'), + USERLOGIN: require('./login'), + DB: db, + SocketCount: 0, + LISTENER: require("./ws"), + max_connect_count: 1100, + max_user_count: 5100, + MESSAGE: { + stores: new Map(), + NOTICES: [], + }, + STATS: { + TOPS: [], + EXP: [], + SCORE: [], + WEAPON: [], + }, + status: -1,//-1关闭 0正常 >1 用户等级>连接 + SocketIn: function () { + this.SocketCount++; + }, + connect: function (socket) { + if (WORLD.status < 0) + return socket.end(); + if (!WORLD.check_connect(socket)) + return socket.end(); + + socket.user = new USER(); + + socket.user.socket = socket; + socket.user.wait_input = this.USERLOGIN.check_session.bind(this.USERLOGIN); + + socket.setTimeout(60000); + }, + check_connect: function (socket) { + return true; + }, + before_login: function (user) { + if (this.status < 0) return false; + if (this.status === 0) return true; + return this.status <= user.user_level; + }, + disconnect: function (socket) { + if (socket.user) { + socket.user.socket = null; + socket.user.disconnect(); + } + this.SocketCount--; + if (socket.oserver) { + socket.oserver.disconnect(); + socket.oserver = null; + } + }, request: function (request, socket) { + if (!request) return; + var user = socket.user; + if (!user) { + return; + } + if (user.request_count > 20) { + return user.send("不要急,慢慢来。"); + } + user.request_count = user.request_count + 1; + var time = Date.now(); + try { + user.command(request); + } catch (e) { + console.log(user.name, "命令错误:", request, e.message, e.stack); + WORLD.log(user, request, e.message + e.stack); + } + WORLD.RECEIVED.push({ + time: time, + cmd: request + " " + (Date.now() - time).toString(), + user: user.id + }); + if (WORLD.RECEIVED.length > 1000) { + WORLD.saveRequest(); + } + }, saveRequest: function () { + db.saveRequest(WORLD.RECEIVED); + WORLD.RECEIVED.length = 0; + }, + startup: async function (sid) { + if (sid) { + sid = parseInt(sid); + this.SERVERS = await db.getServers(); + this.SERVER = this.getServer(sid); + } else { + this.SERVER = __CONFIG.def_server; + } + + if (!this.SERVER) throw "服务器设置错误,无法启动"; + this.SERVERID = this.SERVER.id; + + await db.initDataDir(); + loadResource(); + await this.DATA.load(); + await this.LISTENER.start(this.SERVER.port); + console.log("服务", this.SERVER.name, "(" + this.SERVERID + ")启动"); + console.log("ws://" + this.SERVER.ip + ":" + this.SERVER.port); + this.heart_beat_service = setInterval(WORLD.heart_beat, __CONFIG.HEARTBEAT); + + this.status = __CONFIG.CONNECT_LEVEL ?? 0; + this.on_startup(); + if (this.status > 0) + console.log('当前允许级别' + this.status + "账号登陆"); + }, + + + sendAll: function (msg) { + for (var i = 0; i < WORLD.USERS.length; i++) { + WORLD.USERS[i].send(msg); + } + }, + getUser: function (id) { + if (!id) return; + for (var i = 0; i < WORLD.USERS.length; i++) { + if (WORLD.USERS[i].id == id) return WORLD.USERS[i]; + } + + }, find_user: function (name) { + if (!name) return; + for (var i = 0; i < WORLD.USERS.length; i++) { + if (WORLD.USERS[i].name == name) return WORLD.USERS[i]; + } + }, + on_user_login: function (user) { + + }, + on_user_cross_login: function (user) { + + }, + on_startup: function () { + + }, + on_user_quit: function (user) { + + }, + on_user_relogin: function (user) { + + } + , + on_heart_beat: function (user) { + + }, + heart_beat: function () { + var avtived_obj = null; + try { + const dt = Date.now(); + WORLD.CONNECT_COUNT = 0; + for (let i = 0; i < WORLD.USERS.length; i++) { + avtived_obj = WORLD.USERS[i]; + if (avtived_obj.socket) WORLD.CONNECT_COUNT++; + avtived_obj.heart_beat(dt); + } + WORLD.on_heart_beat(dt); + for (let i = 0; i < WORLD.RUN_ROOMS.length; i++) { + avtived_obj = WORLD.RUN_ROOMS[i]; + avtived_obj.heart_beat(dt); + } + WORLD.HEARTBEATCOUNT++; + if (WORLD.HEARTBEATCOUNT > 720) { + WORLD.HEARTBEATCOUNT = 0; + WORLD.save(); + console.log("数据已备份%d", Date.now() - dt); + } + } catch (e) { + console.log(avtived_obj ? (avtived_obj.path ?? avtived_obj.name) : "", "心跳错误:", e, e.stack); + WORLD.log(null, e.message, e.stack); + } + + }, + login_out: function (user) { + this.on_user_quit(user); + if (user.serverid === WORLD.SERVERID) { + user.save(); + } + WORLD.USERS.remove(user); + + if (user.socket) { + try { + user.socket.end(); + user.socket.destroy(); + } catch (e) { + console.log(e.message, e.stack); + } + } + }, send: function (text) { + for (var i = 0; i < this.USERS.length; i++) { + this.USERS[i].send(text); + } + }, log: function (user, cmd, msg) { + WORLD.LOGS.push({ + time: Date.now(), + cmd: cmd, + user: user ? user.name : "", + msg: msg + }); + if (WORLD.LOGS.length > 500) { + db.saveLogs(WORLD.LOGS); + WORLD.LOGS.length = 0; + } + }, saveLog: function () { + db.saveLogs(WORLD.LOGS); + WORLD.LOGS.length = 0; + } + , + is_server: function (user) { + return user.serverid == WORLD.SERVERID; + }, + save: async function () { + + var roles = []; + for (var i = 0; i < WORLD.USERS.length; i++) { + if (WORLD.USERS[i].serverid != WORLD.SERVERID) continue; + roles.push(WORLD.USERS[i].getData()); + } + try { + console.time('saved'); + await db.saveRoles(roles); + console.log('玩家数据已保存'); + await this.DATA.save(); + console.log('全局数据已经保存'); + await this.saveLog(); + await this.saveRequest(); + console.log('日志数据已经保存'); + console.timeEnd('saved'); + return true; + } catch (error) { + console.error('玩家数据保存失败', error.message); + return false; + } + }, + writeHeapSnapshot: function () { + let v8 = UTIL.require('v8'); + let dt = new Date(); + let fname = __PATH.DATA + "/" + dt.getFullYear() + "_" + dt.getMonth() + "_" + + dt.getDate() + "_" + dt.getHours() + "_" + dt.getMinutes() + ".heapsnapshot"; + v8.writeHeapSnapshot(fname); + console.log('快照保存到', fname); + } + , + loadLocalData: function () { + let data = db.getLocalRoles(); + if (!data || !data.length) return; + console.log("加载上次未保存的本地用户%d", data.length); + for (let i = 0; i < data.length; i++) { + let user = new USER(); + user.loadData(data[i]); + this.USERS.push(user); + } + db.deleteLocalRoles(); + }, + on_cross_response: function (id, sid) { + //允许跨服 + }, + can_cross: function (id) { + //允许跨服 + }, on_user_die: function (me, killer, corpse) { + + }, on_resource_loaded: function () { + + } +}; +function loadResource() { + let fs = require("fs"); + function readdir(basePath, path) { + path = path || basePath; + let files = fs.readdirSync(path); + let count = 0; + for (let i = 0; i < files.length; i++) { + let sub_path = path + files[i]; + let stat = fs.statSync(sub_path); + if (stat.isDirectory()) { + count += readdir(basePath, sub_path + "/"); + } else { + let fname = sub_path.replace(basePath, "").replace(".js", ""); + BASE.CREATE(basePath, fname); + count++; + } + } + return count; + } + try { + let sum = 0; + let count = readdir(__PATH.EXTENDS); + console.log("%s %d ", __PATH.EXTENDS, count); + sum += count; + count = readdir(__PATH.COMMAND); + console.log("%s%d ", __PATH.COMMAND, count); + sum += count; + count = readdir(__PATH.FAMILY); + console.log("%s %d ", __PATH.FAMILY, count); + sum += count; + + + count = readdir(__PATH.OBJ); + console.log("%s %d ", __PATH.OBJ, count); + sum += count; + + count = readdir(__PATH.AREA); + console.log("%s %d ", __PATH.AREA, count); + sum += count; + + count = readdir(__PATH.SKILL); + console.log("%s %d ", __PATH.SKILL, count); + sum += count; + + count = readdir(__PATH.MAP); + console.log("%s %d ", __PATH.MAP, count); + sum += count; + count = readdir(__PATH.TASK); + console.log("%s %d ", __PATH.TASK, count); + sum += count; + console.log('资源脚本加载%d', sum); + WORLD.on_resource_loaded(); + } catch (e) { + console.log("error: ", e, e.stack); + } +} diff --git a/os/ws.js b/os/ws.js new file mode 100644 index 0000000..aa40827 --- /dev/null +++ b/os/ws.js @@ -0,0 +1,49 @@ + +const ws = require("./net-ws"); +const server = new ws({ + SSL: false, + KEY: "", + CERT: "", + PASSWORD: "" +}); +server.start = async function (port) { + return new Promise((resolve) => { + this.listen(port, resolve); + }); +} +// WORLD.LISTENER = server; +server.onConnect = function (socket) { + WORLD.connect(socket); +} +server.onSocketIn = function (socket) { + + WORLD.SocketIn(socket); + +} +server.onReceive = function (msg, socket) { + WORLD.request(msg, socket); +} +server.onClose = function (msg, socket) { + console.log("server closed"); +} +server.onClientClose = function (socket, e) { + + WORLD.disconnect(socket); + if (!socket.destroyed) { + socket.destroy(); + } +} +server.onClientTimeout = function (socket, e) { + if (socket && (!socket.user || !socket.user.id)) { + socket.end(); + } +} +server.onClientError = function (socket, e) { + if (socket && socket.user) { + if (!socket.destroyed) { + socket.destroy(); + } + } +} + +module.exports = server; diff --git a/package.json b/package.json new file mode 100644 index 0000000..ef19eb6 --- /dev/null +++ b/package.json @@ -0,0 +1,38 @@ +{ + "name": "msmud", + "version": "0.0.1", + "description": "", + "main": "web.js", + "bin": "web.js", + "scripts": { + "web": "node web.js", + "web-debug": "node --inspect-brk web.js", + "mix": "node pack.js", + "os": "node main.js", + "os-debug": "node --inspect-brk main.js", + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "start": "concurrently \"npm run web\" \"npm run os\"", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "better-sqlite3": "^12.10.0", + "cookie-parser": "^1.4.7", + "dotenv": "^17.4.2", + "express": "^5.1.0", + "express-session": "^1.18.1", + "jquery": "^4.0.0", + "json5": "^2.2.3", + "pino": "^9.7.0", + "pino-http": "^10.5.0", + "pino-roll": "^3.1.0", + "svg-captcha": "^1.4.0", + "vite": "^8.0.14" + }, + "devDependencies": { + "concurrently": "^9.1.2" + } +} \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..2595480 --- /dev/null +++ b/readme.md @@ -0,0 +1 @@ +# wsmud diff --git a/src/api.js b/src/api.js new file mode 100644 index 0000000..e0fef85 --- /dev/null +++ b/src/api.js @@ -0,0 +1,64 @@ +import Util from './utils/util.js'; + +export default { + Login: function (code, pwd, cb) { + return Util.Post('api/user/login', { code: code, pwd: pwd }, cb); + }, + IsRegistValidation: function (cb) { + return Util.Get('UserAPI/IsRegistValidation', cb); + }, + ValidationImage: function (cb) { + return Util.Get('api/user/validimage', cb); + }, + Regist: function (user, cb) { + return Util.Post('api/user/regist', user, cb); + }, + Enter: function (guider, cb) { + return Util.Get('e', [guider], cb); + }, + ChangePassword: function (oldpwd, pwd, no, cb) { + return Util.Post('api/user/changepassword', { oldpwd: oldpwd, pwd: pwd, no: no }, cb); + }, + LoginOut: function (cb) { + return Util.Get('UserAPI/LoginOut', cb); + }, + GetRoles: function (userid, cb) { + return Util.Get('UserAPI/GetRoles', [userid], cb); + }, + AddRole: function (player, cb) { + return Util.Post('UserAPI/AddRole', { player: player }, cb); + }, + GetUser: function (cb) { + return Util.Get('UserAPI/GetUser', cb); + }, + Search: function (userid, key, type, cb) { + return Util.Get('UserAPI/Search', [userid, key, type], cb); + }, + ResetPassword: function (userid, cb) { + return Util.Get('UserAPI/ResetPassword', [userid], cb); + }, + RecoverUser: function (pid, cb) { + return Util.Get('UserAPI/RecoverUser', [pid], cb); + }, + LoadPlayer: function (pid, isDelete, cb) { + return Util.Get('UserAPI/LoadPlayer', [pid, isDelete], cb); + }, + GetPhone: function (cb) { + return Util.Get('api/user/getphone', cb); + }, + BindPhone: function (code, no, pwd, cb) { + return Util.Post('api/user/bindphone', { code: code, no: no, pwd: pwd }, cb); + }, + SendValidateCode: function (no, cb) { + return Util.Get('UserAPI/SendValidateCode', [no], cb); + }, + ResetPasswordByPhone: function (name, phone, vcode, pwd, cb) { + return Util.Post('api/user/resetpwd', { name: name, phone: phone, vcode: vcode, pwd: pwd }, cb); + }, + NewServer: function (cb) { + return Util.Get('UserAPI/NewServer', cb); + }, + GetServer: function (cb) { + return Util.Get('api/game/servers', cb); + } +}; diff --git a/src/base/page.js b/src/base/page.js new file mode 100644 index 0000000..d1991a8 --- /dev/null +++ b/src/base/page.js @@ -0,0 +1,139 @@ +export class Page { + constructor(filePath) { + this._filePath = filePath; + this.$children = null; + this.$parent = null; + this.$el = null; + this.id = null; + this.template = ''; + this.css = ''; + } + + filePath() { + return this._filePath; + } + + mount(parent, options) { + const tpl = document.createElement('template'); + tpl.innerHTML = this.render(options); + parent.append(tpl.content); + this.$el = parent.lastElementChild; + if (this.on_mount) this.on_mount(this.$el); + if (this.$children) { + this.$children.forEach(com => { + if (com.on_mount) com.on_mount(com.id ? document.getElementById(com.id) : this.$el); + }); + } + } + + render(options) { + return this.template; + } + + _injectStyle() { + if (!this.css || this._style_dom) return; + const style = document.createElement('style'); + style.textContent = this.css; + document.head.append(style); + this._style_dom = style; + } + + unmount() { + if (this.$el) this.$el.remove(); + this.$el = null; + if (this.on_unmount) this.on_unmount(); + if (this.$children) this.$children.forEach(com => { if (com.on_unmount) com.on_unmount(); }); + if (this.$parent && this.$parent.$children) { + this.$parent.$children = this.$parent.$children.filter(com => com !== this); + } + this.$parent = null; + this.$children = null; + } + + destroy() { + if (this.on_destroy) this.on_destroy(); + if (this._style_dom) this._style_dom.remove(); + } + + insert(options) { + if (!options) throw new Error('选项不能为空'); + if (typeof options === 'string') options = { url: options }; + const ComClass = options.Class; + if (!ComClass) throw new Error(`组件类不存在`); + const com = new ComClass(); + if (!this.$children) this.$children = []; + this.$children.push(com); + com.$parent = this; + if (options.id) { + this['$' + options.id] = com; + com.id = options.id; + } + return com.render(options); + } + + onCompile() { + this._injectStyle(); + } +} + +export function EventsMixin(target) { + target.prototype.handlers = Object.create(null); + target.prototype.on = function (type, func, ctx) { + return this._addListener(type, func, ctx, false); + }; + target.prototype.once = function (type, func, ctx) { + return this._addListener(type, func, ctx, true); + }; + target.prototype._addListener = function (type, func, ctx, once) { + if (typeof func !== 'function') { + console.warn('事件注册失败:回调必须是函数'); + return this; + } + if (!this.handlers[type]) { + this.handlers[type] = { listeners: [], cache: [] }; + } + const handler = this.handlers[type]; + handler.listeners.push({ fn: func, ctx, once }); + if (handler.cache.length) { + handler.cache.forEach(data => this._runListeners(handler, data)); + handler.cache = []; + } + return this; + }; + target.prototype.emit = function (type, data, delay = true, clear = false) { + const handler = this.handlers[type]; + if (!handler) { + if (delay) this.handlers[type] = { listeners: [], cache: [data] }; + return this; + } + if (!handler.listeners.length) { + if (delay) handler.cache.push(data); + return this; + } + this._runListeners(handler, data); + if (clear) delete this.handlers[type]; + return this; + }; + target.prototype._runListeners = function (handler, data) { + for (let i = handler.listeners.length - 1; i >= 0; i--) { + const { fn, ctx, once } = handler.listeners[i]; + if (fn.call(ctx, data) === false || once) handler.listeners.splice(i, 1); + } + }; + target.prototype.off = function (type, func) { + const handler = this.handlers[type]; + if (!handler) return this; + if (typeof func !== 'function') { + delete this.handlers[type]; + return this; + } + handler.listeners = handler.listeners.filter(item => item.fn !== func); + if (!handler.listeners.length) delete this.handlers[type]; + return this; + }; + target.prototype.removeAll = function (type) { + if (type) delete this.handlers[type]; + else this.handlers = Object.create(null); + return this; + }; +} diff --git a/src/client.js b/src/client.js new file mode 100644 index 0000000..7debbd0 --- /dev/null +++ b/src/client.js @@ -0,0 +1,192 @@ + +import * as Util from './utils/util.js'; + +let IsConnecting = false; +let ChangeServer = false; +export let GameClient = null; +export let SelectedServer = null; +export let LastCommand = null; +const SessionKey = "u"; +const SessionToken = "p"; + +export function connectServer(server, pid) { + if (IsConnecting) return; + + SelectedServer = server; + console.log("重新连接", GameClient == null ? "未连接" : "已连接"); + closeServer(); + GameClient = new WSClient(server.ip, server.port); + IsConnecting = true; + GameClient.OnError = (err) => { + IsConnecting = false; + if (err) { + if (err.isTrusted) err = "服务器没有响应,请稍后重试"; + showLoader("连接失败:" + err + ""); + } + } + GameClient.OnConnect = () => { + IsConnecting = false; + if (!pid && !Process.player) { + showLoader('正在获取角色列表...'); + SendCommand(Util.GetUserCookie(SessionKey) + " " + Util.GetUserCookie(SessionToken)); + } else { + if (pid) { + SendCommand(Util.GetUserCookie(SessionKey) + " " + Util.GetUserCookie(SessionToken) + " " + pid + " " + server.ID); + } else { + SendCommand(Util.GetUserCookie(SessionKey) + " " + Util.GetUserCookie(SessionToken) + " " + Process.player); + } + } + } + + GameClient.OnClose = () => { + IsConnecting = false; + if (ChangeServer) { + ChangeServer = false; + return; + } + if (GameClient.Connected()) return; + + if (Process.player) { + Process.clear(); + ReceiveMessage("你的连接中断了..."); + } else { + setTimeout(() => { + hide2show($("#slist_panel")); + }, 3000); + } + } + GameClient.OnData = ReceiveData; + GameClient.OnMessage = ReceiveMessage; + GameClient.Connect(); +} + +export function isConnected() { + if (!GameClient) return false; + return GameClient.Connected(); +} + +export function SendCommand(cmd) { + if (IsConnecting) return; + if (!GameClient || !GameClient.Connected()) { + LastCommand = cmd; + ReceiveMessage("连接中断,正在重新连线..."); + return connectServer(SelectedServer); + } + Dialog.extend.record(cmd); + GameClient.Send(cmd); +} + +export function onLogin() { + if (LastCommand) { + SendCommand(LastCommand); + LastCommand = null; + } +} + +export function ReceiveMessage(x) { + if (Dialog.extend.message_filter(x)) return; + Process.message.push(x); + Process.message.scroll2end(); + Dialog.extend.trigger(x); +} + +export function ReceiveData(data) { + if (Dialog.extend.data_filter(data)) return; + var func = Process[data.type]; + func && func(data); + Dialog.extend.process(data); +} + +export function closeServer() { + if (GameClient && GameClient.Connected()) { + GameClient.Destroy(); + } + GameClient = null; +} + +export function showInputError(inp, msg) { + $(inp).focus().parent().find(".input-error").remove(); + $("
" + msg + "
").insertAfter(inp); +} + +export function hide2show(elem2, callback) { + var elem1; + var p = $(".login-content").children(); + for (var i = 0; i < p.length; i++) { + if ($(p[i]).css("display") != "none") { + elem1 = $(p[i]); break; + } + } + if (!elem1) elem1 = $("#login_panel"); + elem1.animate({ opacity: 0 }, "fast", function () { + elem1.hide(); + if (elem2 == ".container") $(".login-content").hide(); + else $(".login-content").show(); + if (elem2) { + elem2 = $(elem2); + elem2.show(); + elem2.css("opacity", "0"); + elem2.animate({ opacity: 1 }, "slow", callback); + } + }); +} + +export function showLoader(msg, elem) { + var p = $(".login-content").children(); + for (var i = 0; i < p.length; i++) { + if ($(p[i]).css("display") != "none" + && !$(p[i]).is(".signinfo")) { + $(p[i]).hide(); + } + } + var loader = $("#loader").css("opacity", 1).show(); + loader.find("#loader_msg").html(msg); +} + +let wsindex = 0; +export class WSClient { + constructor(ip, port) { + this.IP = ip; + this.Port = port; + } + Connect(callback) { + try { + var pol = location.protocol == "http:" ? "ws" : "wss"; + this.ws = new WebSocket('ws://' + this.IP + ':' + this.Port); + this.ws.onopen = this.OnConnect; + this.ws.onclose = this.OnClose.bind(this); + this.ws.onerror = this.OnError; + this.ws.onmessage = this.OnReceived.bind(this); + this.index = wsindex++; + } catch (e) { + this.OnError && this.OnError(e); + } + } + OnReceived(evt) { + if (!evt || !evt.data) return; + var data = evt.data; + if (data[0] == '{' || data[0] == '[') { + var func = new Function("return " + data + ";"); + this.OnData(func()); + } else { + this.OnMessage(data); + } + } + Send(text) { + try { + this.ws.send(text); + } catch (e) { + ReceiveMessage(e); + } + } + Destroy() { + this.ws.onclose = null; + this.ws.close(); + } + Close() { + this.ws.close(); + } + Connected() { + return this.ws && this.ws.readyState == 1; + } +} diff --git a/src/combat.js b/src/combat.js new file mode 100644 index 0000000..909f9b4 --- /dev/null +++ b/src/combat.js @@ -0,0 +1,400 @@ + +import Setting from './setting.js'; + +const Combat = { + IsShow: false, + Skills: null, + actions: null, + room_actions: null, + object_actions: null, + Scroll: function (e) { + let div = $(this)[0]; + div.scrollLeft += e.originalEvent.deltaY; + }, + Show: function () { + if (Combat.IsShow) return Combat.Hide(); + if (!this.object_actions) SendCommand("actions"); + Combat.IsShow = true; + if (!Setting.off_hp) { + $(".room-item>.item-status").show(); + } + $(".combat-panel").removeClass("hide"); + this.refActions(); + Process.message.scroll2end(); + // $(".right-bar")[0].style.bottom = ($(".combat-panel").height() + $(".bottom-bar").height()) + "px"; + }, + Hide: function () { + Combat.IsShow = false; + if (!Setting.off_hp) { + $(".room-item>.item-status").hide(); + } + $(".combat-panel").addClass("hide"); + // $(".right-bar")[0].style.bottom = null; + }, ShowRoomCommands: function (room) { + + this.room = room; + this.room_actions = room.commands; + if (!Combat.IsShow) return; + this.refActions(); + // let panel = $(".room-commands"); + // if (this.room_actions) { + // for (let item of this.room_actions) { + // panel.find('[cmd="' + item.cmd + '"]').remove(); + // } + // } + // let cmds = room.commands ?? []; + // Dialog.extend.append(cmds, 'action', room); + // this.room = room; + // this.room_actions = cmds; + // if (!Combat.IsShow) return; + // this.append_items(cmds, panel); + }, + def_actions: [{ cmd: "dazuo", name: "打坐" }, + { cmd: "liaoshang", name: "疗伤" }], + + refActions: function () { + let actions = [...this.def_actions]; + this.actions = actions; + if (this.room) { + Dialog.extend.append(actions, 'action', this.room); + } + this.create_actions(); + }, + ShowActions: function (data) { + this.object_actions = data.actions ?? []; + this.refActions(); + if (data.skills) + this.ShowPFM(data); + }, + ShowPFM: function (data) { + this.Skills = data.skills || []; + this.create_skillItems(data.skills); + }, + append_items: function (items, parent) { + if (!items) return; + for (let item of items) { + item.elem = + $(`${item.name}`) + .appendTo(parent); + if (item.disper > 0) { + item.elem.css("backgroundSize", item.disper + "% 100%"); + } + } + }, create_actions: function (items) { + var panel = $(".room-commands").empty(); + this.append_items(this.actions, panel); + this.append_items(this.object_actions, panel); + this.append_items(this.room_actions, panel); + + }, DisObj: function (data) { + if (!this.object_actions) return; + var cmd = data.act ? data.id : "use " + data.id; + for (var i = 0; i < this.object_actions.length; i++) { + var item = this.object_actions[i]; + if (item.cmd === cmd) { + if (data.remove) { + this.object_actions.splice(i, 1); + return item.elem.remove(); + } + else { + this.ANI_OBJ(item, data.time, data.time); + } + } + } + }, AddObj: function (id, name) { + if (!this.object_actions) return; + var cmd = "use " + id; + for (var i = 0; i < this.object_actions.length; i++) { + var item = this.object_actions[i]; + if (item.cmd == cmd) return; + } + this.object_actions.push({ + cmd: "use " + id, + name: name.replace(/\<.+?\>/g, "") + }); + this.create_actions(); + } + , ANI_OBJ: function (obj, time, ani_time) { + + let elem = obj.elem; + if (!elem) return; + var cur_per = ani_time * 100 / time; + if (cur_per > 0) { + elem.css("backgroundSize", cur_per + "% 100%"); + } else { + if (cur_per < 0) cur_per = 0; + elem.css("backgroundSize", "0% 100%"); + } + obj.disper = cur_per; + setTimeout(Combat.ANI_OBJ, 1000, obj, time, ani_time - 1000); + } + , create_skillItems: function (items) { + var elem = $(".combat-commands").empty(); + if (!items.length) return; + for (var i = 0; i < items.length; i++) { + var html = []; + html.push(""); + html.push(items[i].name); + // html.push(""); + html.push(""); + // items[i].shadow = $(html.join("")).appendTo(elem).find(".shadow")[0]; + items[i].elem = $(html.join("")).appendTo(elem); + } + }, ChangeDistime: function (data) { + var pfmid = data.id.replace("/", "."); + for (var j = 0; j < Combat.dis_pfms.length; j++) { + if (Combat.dis_pfms[j].id == pfmid) { + Combat.dis_pfms[j].ani_time += data.time; + break; + } + } + }, ClearDistime: function (data) { + if (!Combat.dis_pfms) return; + var pfmid = data.id ? data.id.replace("/", ".") : data.id; + for (var j = 0; j < Combat.dis_pfms.length; j++) { + if (!pfmid || Combat.dis_pfms[j].id == pfmid) { + Combat.dis_pfms[j].ani_time = 0; + } + + } + }, redisable: function () { + Combat.dis_pfms = []; + for (var i = 0; i < Combat.Skills.length; i++) { + var skill = Combat.Skills[i]; + Combat.dis_pfms.push({ + id: skill.id, + distime: skill.distime, + ani_time: skill.distime + }); + } + if (!Combat.time_handler) { + Combat.ANI_PFM(); + } + }, On_Perform: function (data) { + if (!this.Skills) return; + if (data.id === 'all' && !data.rtime) return this.redisable(); + if (data.id) + data.id = data.id.replace('/', '.'); + data.rtime = data.rtime || 0; + data.distime = data.distime || 0; + if (!this.dis_pfms) this.dis_pfms = []; + for (var i = 0; i < this.dis_pfms.length; i++) { + + if (this.dis_pfms[i].id == data.id) { + data.id = null; + this.dis_pfms[i].distime = data.distime; + this.dis_pfms[i].ani_time = data.distime; + continue; + } + if (this.dis_pfms[i].ani_time < data.rtime) { + this.dis_pfms[i].ani_time = data.rtime; + this.dis_pfms[i].distime = data.rtime; + } + } + if (data.id) { + this.dis_pfms.push({ + id: data.id, + distime: data.distime, + ani_time: data.distime + }); + } + Combat.ani_time = Combat.ani_time ?? 0; + if (data.rtime > Combat.ani_time) { + Combat.distime = data.rtime; + Combat.ani_time = data.rtime; + } + if (!this.time_handler) { + Combat.ANI_PFM(); + } + }, PFM_INTERVAL: 300 + , ANI_PFM: function () { + var p = 0; + if (Combat.distime > 0) + p = Combat.ani_time * 100 / Combat.distime; + for (var i = 0; i < Combat.Skills.length; i++) { + var skill = Combat.Skills[i]; + var cur_per = p; + for (var j = 0; j < Combat.dis_pfms.length; j++) { + if (Combat.dis_pfms[j].id == skill.id && Combat.dis_pfms[j].distime) { + cur_per = Combat.dis_pfms[j].ani_time * 100 / Combat.dis_pfms[j].distime; + if (cur_per < 0) { + Combat.dis_pfms.splice(j, 1); + } else { + Combat.dis_pfms[j].ani_time -= Combat.PFM_INTERVAL; + } + break; + } + } + if (cur_per > 0) { + if (cur_per < 0) cur_per = 0; + skill.elem.css("backgroundSize", cur_per + "% 100%"); + } else { + skill.elem.css("backgroundSize", "0% 100%"); + } + } + + if (Combat.ani_time > 0 || Combat.dis_pfms.length) { + Combat.time_handler = setTimeout(Combat.ANI_PFM, Combat.PFM_INTERVAL); + } else { + Combat.time_handler = null; + } + Combat.ani_time -= Combat.PFM_INTERVAL; + }, + StatusChanged: function (data) { + var items = $(".room-item"); + for (var i = 0; i < items.length; i++) { + var item = $(items[i]); + if (item.attr("itemid") == data.id) { + this.UpdaeBar(data, "mp", item); + this.UpdaeBar(data, "hp", item); + break; + } + } + }, UpdaeBar: function (data, type, item) { + var val = data[type], max = 0; + if (val == undefined) return; + + var bar = item.find("." + type + ">.progress-bar"); + if (data["max_" + type]) { + max = data["max_" + type]; + bar.attr("max", max); + } else { + max = parseInt(bar.attr("max")); + } + if (Setting.show_hpnum && type == "hp") { + + item.find(".progress-num").html("[" + Process.get_hpnum(val, max) + "/" + max + ']'); + } + bar.css("width", Combat.CountWidth(val, max) + "%"); + if (Setting.show_damage && data.damage && data.id != Process.player) { + var per = 0; + if (data.damage == -1) { + per = parseInt((max - val) * 1000 / max) / 10; + } else { + per = parseInt(data.damage * 1000 / max) / 10; + } + bar = item.find(".item-damage"); + if (!bar.length) { + bar = $('[0%]').appendTo(item.find('.item-name')); + } + bar.html("[" + per + '%]'); + } + + } + + , CountWidth: function (d1, d2) { + if (d2 == 0) return 0; + var d = d1 * 100 / d2; + if (d >= 100) return 100; + if (d < 0) return 0; + return d; + }, Perform: function () { + var elem = $(this); + if (elem.is("disable")) return; + var pfmid = elem.attr("pid"); + if (!pfmid) return; + SendCommand("perform " + pfmid); + // Combat.On_Perform({ id: pfmid }); + }, + STATUS: {}, + AppendStatusItem: function (id, elem, status) { + var stitem = { elem: elem, items: {} }; + if (status) { + for (var i = 0; i < status.length; i++) { + this.StatusItem_add(stitem, status[i]); + } + } + this.STATUS[id] = stitem; + } + , StatusItemChanged: function (data) { + + var func = Combat["StatusItem_" + data.action]; + func && func.call(Combat, this.STATUS[data.id], data); + + }, StatusItem_add: function (statu_item, item) { + if (!statu_item) return; + var str = []; + str.push(''); + str.push(item.name); + if (item.count != undefined) { + str.push("x"); + str.push(item.count); + } + str.push(''); + statu_item.items[item.sid] = { + elem: $(str.join("")).appendTo(statu_item.elem)[0], + name: item.name, + count: item.count, + duration: item.duration, + anitime: item.duration - (item.overtime || 0) + }; + if (item.duration > 0) + Combat.StatusItemANI(statu_item.items[item.sid]); + }, + StatusItem_remove: function (player_status, data) { + if (!player_status) return; + var ids = data.sid; + if (typeof ids == "string") ids = [ids]; + for (var i = 0; i < ids.length; i++) { + var item = player_status.items[ids[i]]; + if (item) { + $(item.elem).remove(); + item.handler && clearTimeout(item.handler); + delete player_status.items[ids[i]]; + } + } + + }, + StatusItem_refresh: function (player_status, data) { + if (!player_status) return; + var item = player_status.items[data.sid]; + if (!item) return; + var text = item.elem.firstChild; + var shadow = item.elem.lastChild; + item.count = data.count; + item.elem.innerHTML = item.name + "x" + item.count + shadow.outerHTML; + item.handler && clearTimeout(item.handler); + item.anitime = item.duration; + Combat.StatusItemANI(item); + }, StatusItem_override: function (player_status, data) { + + var item = player_status.items[data.sid]; + if (!item) return; + item.handler && clearTimeout(item.handler); + item.anitime = item.duration; + Combat.StatusItemANI(item); + }, + StatusItem_clear: function (player_status, data) { + if (!player_status) return; + for (var sid in player_status.items) { + var item = player_status.items[sid]; + if (item) { + $(item.elem).remove(); + clearTimeout(item.handler); + } + } + player_status.items = {}; + }, + StatusItemANI: function (item) { + var shadow = item.elem.lastChild; + var p = item.anitime * 100 / item.duration; + if (p < 0) p = 0; + shadow.style.right = p + "%"; + item.anitime = item.anitime - 1000; + if (p > 0) { + item.handler = setTimeout(Combat.StatusItemANI, 1000, item); + } else { + //elem.parent().remove(); + item.handler = 0; + } + + } + +}; +export default Combat; diff --git a/src/confirm.js b/src/confirm.js new file mode 100644 index 0000000..81aad25 --- /dev/null +++ b/src/confirm.js @@ -0,0 +1,315 @@ + + +export const Confirm = { + DEFAULT: { + + onOK: function () { }, + footer: true, + + btn_text: "确认" + }, + Show: function (par) { + this.Init(); + + + this.Parameter = Object.assign({}, this.DEFAULT, par); + this.content.empty().append(this.Parameter.content); + this.element.show(); + if (this.Parameter.footer) { + this.btn.show(); + this.btn.find(".btn-text").html(this.Parameter.btn_text); + } else { + this.btn.hide(); + } + this.isShow = true; + }, Close: function (isok) { + if (!Confirm.isShow) return; + Confirm.element.hide(); + Confirm.isShow = false; + if (!isok && this.Parameter.onCancle) + this.Parameter.onCancle(); + }, + Init: function () { + if (this._init) return; + this.element = $(``).appendTo(document.body); + this.content = this.element.find(".dialog-content"); + this.btn = this.element.find(".dialog-btn"); + this.element.on("click", ".btn-ok", function (e) { + if (Confirm.Parameter.content === Confirm.count_element) { + var text = Confirm.count_element.find("input"); + var v = parseInt(text.val()); + if (v.toString() == "NaN") v = 0; + if (v > Confirm.max_count) v = Confirm.max_count; + Confirm.Parameter.onOK(v); + } else { + Confirm.Parameter.onOK(); + } + Confirm.Close(true); + return false; + }); + this.element.on("click", ".btn", function (e) { + var count = Confirm.max_count || 1000; + var elem = $(e.target); + var type = parseInt(elem.attr("ac")); + var text = elem.parent().find("input"); + var v = parseInt(text.val()); + if (v.toString() == "NaN") v = 0; + if (type == -10) { + v -= 10; + } else if (type == 10) { + if (v == 1) v = 0; + v += 10; + } else if (type == 1) { + v = count; + } else { + v = 1; + } + if (v < 1) v = 1; + else if (v > count) v = count; + text.val(v); + return false; + }); + this._init = true; + } + + , Process: function (pars) { + var cmd = pars[1]; + var npc = ""; + if (cmd == "dc") { + cmd = pars[3]; + npc = pars.splice(1, 2); + npc = npc[0] + " " + npc[1] + " "; + } + var func = this["Show_" + cmd]; + func && func.call(this, pars, npc); + }, get_countelement: function (count, maxcount) { + if (!this.count_element) { + this.count_element = $('
最少减10加10最多
'); + + } + if (count) this.count_element.find("input").val(count); + else this.count_element.find("input").val(1); + if (maxcount) maxcount = parseInt(maxcount); + this.max_count = maxcount || 1000; + return this.count_element; + }, Show_shop: function (p, maxcount) { + var objid = p[2]; + if (!objid) return; + var obj = Dialog.shop.get_item(objid); + if (!obj) return; + let count = p[3] ? parseInt(p[3]) : -1; + this.Show({ + content: this.get_countelement(1, count == -1 ? 9999 : count), + btn_text: "购买" + obj.name, + onOK: function (v) { + if (!(v > 0)) return; + SendCommand("shop " + objid + " " + v); + } + }); + }, + Show_buy: function (p) { + var objid = p[3]; + if (!objid) return; + var count = parseInt(p[2]); + + this.Show({ + content: this.get_countelement(1, count == -1 ? 9999 : count), + btn_text: "购买", + onOK: function (v) { + if (!(v > 0)) return; + SendCommand("buy " + v + " " + objid + " from " + p[5]); + } + }); + }, + Show_greet: function (p) { + this.Show({ + content: this.get_countelement(1, 99), + btn_text: "送花", + onOK: function (v) { + if (!(v > 0)) return; + SendCommand("greet " + v); + } + }); + }, Show_sell: function (p) { + var objid = p[3]; + if (!objid) return; + + this.Show({ + content: this.get_countelement(p[2], p[2]), + btn_text: "卖出", + onOK: function (v) { + if (!(v > 0)) return; + SendCommand("sell " + v + " " + objid + " to " + p[5]); + } + }); + }, Show_store: function (p) { + var objid = p[3]; + if (!objid) return; + if (p[2] == 1) { + return SendCommand((Dialog.list.is_bookshelf ? "sj " : "") + "store " + objid); + } + this.Show({ + content: this.get_countelement(p[2], p[2]), + btn_text: "存入", + onOK: function (v) { + if (!(v > 0)) return; + SendCommand((Dialog.list.is_bookshelf ? "sj " : "") + "store " + v + " " + objid); + } + }); + }, Show_fenjie: function (p, npc) { + var objid = p[2]; + if (!objid) return; + var obj = Dialog.pack.isShow ? Dialog.pack.get_item(objid) : Dialog.pack2.get_item(objid); + if (!obj) return; + if (obj.name.indexOf("★") == -1) return SendCommand("fenjie " + objid); + this.Show({ + content: "是否确认分解" + obj.name + "?", + btn_text: "确认分解", + onOK: function () { + SendCommand(npc + "fenjie " + objid); + } + }); + + }, Show_qu: function (p) { + var objid = p[2]; + if (!objid) return; + var obj = Dialog.list.find_item(3, objid); + if (!obj) return; + if (obj.count === 1) { + return SendCommand((Dialog.list.is_bookshelf ? "sj " : "") + "qu 1 " + objid); + } + this.Show({ + content: this.get_countelement(obj.count, obj.count), + btn_text: "取出", + onOK: function (v) { + if (!(v > 0)) return; + SendCommand((Dialog.list.is_bookshelf ? "sj " : "") + "qu " + v + " " + objid); + } + }); + }, Show_drop: function (p, npc) { + var objid = p[3]; + if (!objid) return; + var obj = Dialog.pack.isShow ? Dialog.pack.get_item(objid) : Dialog.pack2.get_item(objid); + if (!obj) return; + this.Show({ + content: p[2] == 1 ? "是否确认丢掉" + obj.name + "?" : this.get_countelement(p[2], p[2]), + btn_text: "丢掉", + onOK: function (v) { + if (p[2] == 1) { + return SendCommand(npc + "drop " + objid); + } + if (!(v > 0)) return; + SendCommand(npc + "drop " + v + " " + objid); + } + }); + }, Show_give: function (p, npc) { + var objid = p[4]; + if (!objid) return; + var obj = Dialog.pack2.get_item(objid); + if (!obj) return; + if (obj.count == 1) return SendCommand(npc + "give " + Process.player + " 1 " + objid); + this.Show({ + content: this.get_countelement(obj.count, obj.count), + btn_text: "拿来", + onOK: function (v) { + if (!(v > 0)) return; + SendCommand(npc + "give " + Process.player + " " + v + " " + objid); + } + }); + }, Show_trade_add: function (obj) { + if (!obj) return; + this.Show({ + content: this.get_countelement(obj.count, obj.count), + btn_text: "确定", + onOK: function (v) { + if (!(v > 0)) return; + var moveobj = Util.Clone(obj); + moveobj.count = v; + Dialog.trade.add_trade(moveobj); + } + }); + }, Show_fangqi: function (p, npc) { + var objid = p[2]; + if (!objid) return; + var skill = npc ? Dialog.master.skills[objid] : Dialog.skills.skills[objid]; + if (!skill) return; + this.Show({ + content: "是否确认放弃技能" + skill.name + "?", + onOK: function () { + SendCommand(npc + "fangqi " + objid); + } + }); + }, Show_combine: function (p, npc) { + var objid = p[2]; + if (!objid) return; + var obj = Dialog.pack.get_item(objid); + if (!obj) return; + var com = parseInt(p[3]); + if (!com) return; + var max_count = parseInt(obj.count / com); + if (max_count == 1) { + return SendCommand("combine " + objid); + } + this.Show({ + content: this.get_countelement(max_count), + btn_text: "合成", + onOK: function (v) { + if (!(v > 0)) return; + SendCommand(npc + "combine " + objid + " " + v); + } + }); + } + , Show_pay: function () { + + SendCommand('pay 0 ' + (/mobile/i.test(navigator.userAgent) ? "m" : "c")); + } +}; + + + +export const Warn = { + Elemes: [], + Show: function (data) { + var html = ["
"]; + + html.push("
"); + html.push(data.content); + html.push("
"); + html.push("
"); + for (var i = 0; i < data.cmds.length; i++) { + var cmd = data.cmds[i]; + html.push(""); + html.push(cmd.name); + html.push(""); + } + html.push("
"); + var elem = $(html.join("")).appendTo(".bottom-bar"); + this.Elemes.push(elem); + this.Settop(); + var func = this.Close.bind(this, elem); + if (data.time) { + window.setTimeout(func, data.time); + } + elem.on("click", "span", func); + } + , Close: function (elem) { + if (this.Elemes.indexOf(elem) > -1) { + elem.remove(); + this.Elemes.Remove(elem); + this.Settop(); + } + }, Settop: function () { + var height = $('.bottom-bar').height() + 8; + for (var i = 0; i < Warn.Elemes.length; i++) { + var elem = Warn.Elemes[i]; + elem.css("bottom", height); + height += elem.height() + 14; + } + } +}; diff --git a/src/dialog/base.js b/src/dialog/base.js new file mode 100644 index 0000000..13df4e6 --- /dev/null +++ b/src/dialog/base.js @@ -0,0 +1,137 @@ + +import DialogScore from './score.js'; +import DialogMap from './map.js'; +import DialogKeys from './keys.js'; +import DialogSetting from './setting.js'; +import DialogExtend from './extend.js'; +import DialogChannel from './channel.js'; +import DialogPack from './packet.js'; +import DialogSkills from './skills.js'; +import DialogTasks from './tasks.js'; +import DialogShop from './shop.js'; +import DialogMessage from './message.js'; +import DialogStats from './stats.js'; +import DialogJh from './jh.js'; +import DialogRelation from './relation.js'; +import DialogTeam from './team.js'; +import DialogParty from './party.js'; +import DialogTrade from './trade.js'; +import DialogEvents from './events.js'; +import DialogPm from './paimai.js'; +import DialogPack2 from './packet2.js'; +import DialogMaster from './master.js'; +import DialogList from './list.js'; + + + +const Dialog = { + isShow: false, + curItem: null, + score: DialogScore, + map: DialogMap, + keys: DialogKeys, + setting: DialogSetting, + extend: DialogExtend, + channel: DialogChannel, + pack: DialogPack, + skills: DialogSkills, + tasks: DialogTasks, + shop: DialogShop, + message: DialogMessage, + stats: DialogStats, + jh: DialogJh, + relation: DialogRelation, + team: DialogTeam, + party: DialogParty, + trade: DialogTrade, + events: DialogEvents, + pm: DialogPm, + pack2: DialogPack2, + master: DialogMaster, + list: DialogList, + + show: function (name, data) { + if (!name) return; + const dialog = this[name]; + if (!dialog) throw new Error('没有' + name); + if (!dialog.created) { + dialog.init(); + dialog.created = true; + } + if (!data) { + if (this.isShow && name == this.curItem) return this.hide(); + if (this.curItem && name != this.curItem) { + Dialog[Dialog.curItem].close && Dialog[Dialog.curItem].close(); + Dialog[Dialog.curItem].isShow = false; + Dialog.contentElement.empty(); + } + this.init(); + this.curItem = name; + dialog.show(data); + Process.message.scroll2end(); + } else { + dialog.onData(data); + } + }, + select: function (name) { + if (this.isShow && name == this.curItem) return this.hide(); + if (this.curItem && name != this.curItem) { + Dialog[Dialog.curItem].close && Dialog[Dialog.curItem].close(); + Dialog[Dialog.curItem].isShow = false; + Dialog.contentElement.empty(); + } + this.init(); + this.curItem = name; + }, + init: function () { + if (this.isShow) return; + if (!this.isInit) { + this.contentElement = $(".dialog>.dialog-content"); + this.titleElement = $(".dialog>.dialog-header>.dialog-title"); + this.iconElement = $(".dialog>.dialog-header>.dialog-icon"); + this.footerElement = $(".dialog>.dialog-footer") + .on("click", ".footer-item", Dialog.footerClick); + this.hiddenElement = $(".hidden-item"); + this.element = $(".dialog"); + $(".dialog>.dialog-header>.dialog-close").on("click", Dialog.hide); + this.isInit = true; + } + $(".content-room").addClass("hide"); + this.element.removeClass("hide"); + this.isShow = true; + }, + hide: function () { + if (Dialog[Dialog.curItem].hide && Dialog[Dialog.curItem].hide() == false) return; + Dialog.close(); + }, + footerClick: function () { + var elem = $(this); + if (elem.is(".select")) return; + var cmd = elem.attr("for"); + elem.parent().find(".footer-item.select").removeClass("select"); + elem.addClass("select"); + Dialog[Dialog.curItem].footerChanged(cmd, elem); + }, + title: function (title) { + Dialog.titleElement.html(title); + }, + icon: function (css) { + this.iconElement.attr("class", "dialog-icon glyphicon glyphicon-" + css); + }, + footer: function (html) { + html ? this.footerElement.html(html) : this.footerElement.empty(); + }, + close: function () { + if (!Dialog.isShow) return; + Dialog.isShow = false; + $(".content-room").removeClass("hide"); + Dialog.element.addClass("hide"); + }, + injectStyle: function (css) { + const style = document.createElement("style"); + style.textContent = css; + document.head.append(style); + }, +}; + +export default Dialog; diff --git a/src/dialog/channel.js b/src/dialog/channel.js new file mode 100644 index 0000000..e41d96b --- /dev/null +++ b/src/dialog/channel.js @@ -0,0 +1,118 @@ + + +export default { + footer: [["全部", ""], ["世界", "chat"], ["队伍", "tm"], ["门派", "fam"], ["全区", "es"], ["帮派", "pty"], ["系统", "sys"]], + isScroll: true, + last_click: 0, + show: function () { + if (Date.now() - this.last_click > 500) { + this.last_click = Date.now(); + return; + } + if (Dialog.channel.isShow) return; + Dialog.select("channel"); + Dialog.icon("comment"); + Dialog.title(""); + Dialog.footer(""); + for (var i = 0; i < Dialog.channel.footer.length; i++) { + var elem = $("" + + Dialog.channel.footer[i][0] + "").appendTo(Dialog.footerElement); + if (i == 0) elem.addClass("select"); + } + Dialog.contentElement.html("").append(Process.ChannelElement.addClass("channel-dialog")); + + Dialog.channel.isShow = true; + Dialog.channel.scrollBottom(); + + }, hide: function () { + Dialog.channel.footerChanged(""); + Process.ChannelElement.removeClass("channel-dialog").insertBefore(".content-message"); + + this.scrollBottom(); + this.isShow = false; + }, close: function () { + this.hide(); + }, scrollBottom: function () { + Process.channel.scroll2end(); + }, + footerChanged: function (type) { + if (Dialog.channel.select_item == type) return; + Dialog.channel.select_item = type; + + Process.channel.clear(); + for (var i = 0; i < this.datas.length; i++) { + var item = this.datas[i]; + if (!type || item[0] == type) { + Process.channel.push(item[1]); + } + } + Process.channel.scroll2end(); + }, datas: [], + createElement: function (data, isTop) { + var color = "hic"; + var name = ""; + switch (data.ch) { + case "tm": + color = "hig"; + name = "队伍"; + break; + case "fam": + color = "hiy"; + name = data.fam || "门派"; + break; + case "rumor": + color = "him"; + name = "谣言"; + data.name = "某人"; + break; + case "sys": + color = "hir"; + name = "系统"; + data.name = ""; + break; + case "es": + color = "hio"; + name = data.server; + data.uid = null; + break; + case "pty": + color = "hiz"; + name = "帮派"; + break; + default: + name = ["闲聊", "闲聊", "闲聊", "宗师", "武圣", "武帝", "武神"][data.lv]; + if (data.lv6) { + name = ["武神", "剑神", "刀皇", "兵主", "战神"][data.lv6]; + } + break; + } + var html = ["<", color, ">【"]; + html.push(name); + html.push("】"); + if (data.name) { + html.push(""); + html.push(data.name); + html.push(":"); + } + html.push(data.content); + // if (isTop) { + // html.push("\n"); + // } + var str = html.join(""); + if (this.datas.length > 800) { + this.datas.length = 0; + this.datas.splice(0, 200); + } + if (data.ch == "rumor") data.ch = "sys"; + this.datas.push([ + data.ch, str + ]); + if (this.select_item && this.select_item != data.ch) { + return ""; + } + return str; + } + +}; diff --git a/src/dialog/events.js b/src/dialog/events.js new file mode 100644 index 0000000..5ca54e9 --- /dev/null +++ b/src/dialog/events.js @@ -0,0 +1,136 @@ + +import { showFlag } from '../game/tool.js'; + +const events_css = ` + +.dialog-events { + max-height: 32em; + margin-bottom: 0.5em; + margin-top: 0.5em; +} + +.dialog-events>.empty { + text-align: center; + color: gray; + margin-bottom: 3em; + margin-top: 3em; +} + +.dialog-events>.event-item { + border-radius: 6px; + background-color: #111111; + border-left-width: 4px; + border-left-style: solid; + position: relative; + margin-top: 0.5em; + padding-left: 0.5em; +} + +.event-item h3 { + margin: 0px; + padding-top: 0.5em; + color: var(--border-color) +} + +.event-item .event-desc { + white-space: pre-wrap; + margin: 0; + padding-top: 0.5em; + padding-bottom: 0.5em; +} + +.event-item>.event-btn { + width: 7em; + border-left: 1px solid var(--border-color); + text-align: center; + font-weight: bold; + background-color: transparent; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + color: var(--border-color); +} + +`; + +export default { + unRead: 0, + init: function () { + Dialog.injectStyle(events_css); + }, + hide: function () { + this.element.remove(); + this.isShow = false; + }, onData: function (data) { + if (data.close) return Dialog.hide(); + if (!data.items) { + if (data.finish) this.unRead--; + else this.unRead++; + return this.showUnread(); + } + this.items = data.items; + this.create_items(); + }, showUnread: function () { + showFlag("events", this.unRead); + }, + show: function () { + if (!this.element) + this.element = $("
"); + SendCommand("events"); + if (this.isShow) return; + + Dialog.title("活动"); + Dialog.icon("dashboard"); + this.unRead = 0; + this.showUnread(); + Dialog.footer(""); + this.element.appendTo(Dialog.contentElement); + this.isShow = true; + }, + create_items: function () { + let str = []; + for (let i = 0; i < this.items.length; i++) { + const [id, title, desc, grade, time, command] = this.items[i]; + str.push("

"); + str.push(title) + str.push("

"); + str.push("
");
+            str.push(desc);
+            if (time > 0)
+                str.push('\n', this.format_time(time), '');
+            str.push("
"); + + str.push("", command); + else str.push(">进行中"); + str.push(""); + str.push("
"); + } + if (!str.length) str.push('
暂无活动
'); + this.element.html(str.join("")); + Dialog.footer('共有' + this.items.length + '项活动正在进行'); + + }, format_time: function (time) { + let dt = new Date(time); + let now = new Date(); + let day = dt.getDate(); + let hour = dt.getHours(); + let minu = dt.getMinutes(); + let str = ['持续到']; + if (now.getFullYear() !== dt.getFullYear()) + str.push(dt.getFullYear(), '年'); + if (now.getMonth() !== dt.getMonth()) + str.push(this.format_num(dt.getMonth() + 1), '月', this.format_num(day), '日'); + else if (day !== now.getDate()) + str.push(this.format_num(day), '日'); + str.push(this.format_num(hour), ':', this.format_num(minu)); + + return str.join(""); + + }, format_num: function (num) { + return num > 9 ? num.toString() : "0" + num.toString(); + } +}; diff --git a/src/dialog/extend.js b/src/dialog/extend.js new file mode 100644 index 0000000..3cc93cb --- /dev/null +++ b/src/dialog/extend.js @@ -0,0 +1,629 @@ + +import Util from '../utils/util.js'; +import { ReceiveMessage } from '../client.js'; + +export default { + types: [ + { + name: "自定义快捷操作", value: "button", for: [ + { name: "动作栏", value: "action" }, + { name: "地图", value: "map" }, + { name: "背包道具", value: "pack" }, + { name: "技能", value: "skill" }, + { name: "师父/随从技能", value: "mskill" }, + { name: "房间物体", value: "item" }, + ] + } + // , { + // name: "触发", value: "trigger", + // for: [ + // { name: "文本触发", value: "message" }, + // { name: "事件处理", value: "data" }, + // ] + // }, { + // name: "过滤", value: "filter", + // for: [ + // { name: "文本过滤", value: "fmessage" }, + // { name: "事件过滤", value: "fdata" }, + // ] + // } + ], + init: function (elem) { + elem.on('click', '[ecmd]', this.onButtonClick); + elem.on('click', '.setting-item', this.onClickRow); + elem.on("click", ".switch", this.switchClick); + elem.on("change", "select", this.selectChanged); + if (this.element) return; + this.element = elem; + let html = []; + html.push('
'); + this.append_settings(html); + html.push("
"); + this.append_edit(html); + elem.html(html.join("")); + this.edit_elem = this.element.find('.extend-add'); + this.list_elem = this.element.find('.extend-list'); + }, + refresh_list: function () { + let html = []; + this.append_settings(html); + this.list_elem.html(html.join("")); + }, + append_settings: function (html) { + let items = this.setting, index = 0; + for (let item of items) { + html.push(this.create_item(item, index++)); + } + }, + action_types: { + button: "快捷操作", + trigger: "触发器", + filter: "过滤器" + }, + regex: { + message: true, + fmessage: true + }, + for_types: { + map: "地图", + action: "动作栏", + pack: "背包道具", + skill: "技能", + item: "房间物体", + mskill: "师父/随从技能", + message: "文本", + data: "事件", + fmessage: "文本", + fdata: "事件" + }, + create_item: function (item, index) { + let html = []; + html.push('
'); + html.push('
'); + html.push(this.for_types[item.for], this.action_types[item.type], '【', item.name, '】'); + html.push('
'); + let isopend = false; + if (item.on && item.on[Process.player]) isopend = true; + + html.push(''); + + html.push('
'); + return html.join(""); + }, + selectChanged: function () { + let elem = $(this); + if (elem.attr('prop') !== 'type') { + const fortype = elem.val(); + elem.parent().next().find('.extend-row-header').html( + Dialog.extend.regex[fortype] ? "正则表达式" : "可选参数" + ); + return; + } + let type = elem.val() + let items = null; + for (let item of Dialog.extend.types) { + if (type === item.value) { + items = item.for; + break; + } + } + if (!items) return; + elem = elem.parent().next().find('select'); + let html = []; + for (let item of items) { + html.push(''); + } + elem.html(html.join("")); + }, + switchClick: function () { + let elem = $(this); + let text_elem = elem.find(".switch-text"); + let text = text_elem.text(); + let is_open = text !== "开始记录"; + let is_selected = false; + if (elem.is(".on")) { + elem.removeClass("on"); + is_open && text_elem.html("关"); + } else { + elem.addClass("on"); + is_open && text_elem.html("开"); + is_selected = true; + } + if (!is_open) { + if (is_selected) { + Dialog.close(); + Dialog.extend.start_record(); + } else { + Dialog.extend.stop_record(); + } + } else { + let item = Dialog.extend.setting[elem.parent().attr("sid")]; + if (item) { + if (!item.on) item.on = {}; + if (is_selected) { + item.on[Process.player] = 1; + } else { + delete item.on[Process.player]; + } + Dialog.extend.save_extend(item); + } + } + + return false; + }, + start_record: function () { + if (this.is_record) return; + this.is_record = true; + this.prev_time = 0; + this.record_cmds = []; + ReceiveMessage('开始记录你的操作命令。'); + Process.state({ state: "正在记录你的操作命令" }); + }, + excluded: { + score: true, score2: true, pack: true, cha: true, tasks: true, + message: true, relation: true, shop: true, team: true, jh: true + }, + excluded_check: [ + (x) => x.startsWith('jh') && x.indexOf('start') < 0, + (x) => x.startsWith('stats'), + (x) => x.startsWith('map'), + (x) => x.startsWith('look') + ], + record: function (cmd) { + if (!this.is_record) return; + if (this.excluded[cmd]) return; + for (let check of this.excluded_check) { + if (check(cmd)) return; + } + let now = Date.now(); + if (this.prev_time > 0) { + this.record_cmds.push('#wait ' + (now - this.prev_time)); + } + this.record_cmds.push(cmd); + this.prev_time = now; + }, + stop_record: function () { + if (!this.is_record) return; + this.is_record = false; + ReceiveMessage('已停止记录你的操作命令。'); + this.edit_elem.find('.switch').removeClass('on'); + if (this.record_cmds.length > 0) { + Dialog.show('setting'); + Dialog.setting.footerChanged(3); + this.edit_elem.show(); + this.list_elem.hide(); + this.edit_elem.find('textarea').val(this.record_cmds.join(";")); + Process.state(); + } + }, + helper: "
  • 可用命令参考
  • 可用变量参考
  • 参数用法参考
  • ", + append_edit: function (html) { + html.push('
    '); + html.push('
    '); + html.push(''); + html.push("
    提示/描述/说明
    "); + html.push("
    "); + + html.push('
    '); + html.push('
    扩展类型
    "); + html.push("
    "); + let item1 = this.types[0]; + html.push('
    '); + html.push('
    可用选项
    "); + html.push("
    "); + + html.push('
    '); + html.push(''); + html.push("
    可选参数
    "); + html.push("
    "); + + html.push('
    '); + html.push(''); + html.push("
    "); + html.push(' 开始记录'); + html.push("
      "); + html.push(this.helper); + html.push("
    "); + + html.push("
    "); + + html.push("
    "); + }, onClickRow: function () { + var elem = $(this); + var item = Dialog.extend.setting[elem.attr("sid")]; + if (!item) return; + Dialog.extend.selected_item = item; + if (!Dialog.extend.edit_button) { + Dialog.extend.edit_button = + $('
    '); + } + Dialog.extend.edit_button.insertAfter(elem); + }, + show: function (elem) { + this.init(elem); + if (!this.footer_buttons) {// + this.footer_buttons = $('
    导入导出添加扩展
    '); + } + Dialog.footerElement.append(this.footer_buttons); + }, + command: function (cmd) { + const func = this['cmd_' + cmd]; + if (func) func.call(this); + }, + cmd_import: function () { + if (!this.fileinput) { + let elem = $('')[0]; + document.body.appendChild(elem); + this.fileinput = elem; + elem.addEventListener('change', function (e) { + const file = e.target.files[0]; + if (!file) { + return ReceiveMessage('未选择扩展文件。'); + } + const fileExt = file.name.split('.').pop().toLowerCase(); + const validMimeTypes = ['application/json', 'text/json', 'text/plain']; + if (fileExt !== 'json' && !validMimeTypes.includes(file.type)) { + e.target.value = ''; + return ReceiveMessage('请选择有效的JSON文件!'); + } + const reader = new FileReader(); + reader.onload = function (event) { + try { + const jsonObj = JSON.parse(event.target.result); + Dialog.extend.setting = jsonObj.items; + Dialog.extend.refresh_list(); + Dialog.extend.save_extend(); + ReceiveMessage("扩展文件加载成功。"); + } catch (error) { + console.error("JSON解析错误:", error); + ReceiveMessage('扩展文件加载失败。'); + } + }; + reader.onerror = function () { + console.error("文件读取错误:", reader.error); + ReceiveMessage('扩展文件读取失败。'); + }; + reader.readAsText(file, 'utf-8'); + }); + } + this.fileinput.click(); + + }, + cmd_export: function () { + try { + let jsonObj = { + id: Process.player, + version: "0.1", + items: Dialog.extend.setting, + }; + const jsonStr = JSON.stringify(jsonObj, null, 2); + if (window.android && typeof window.android.saveJsonFile === "function") { + // 传递文件名和JSON内容给安卓 + window.android.saveJsonFile("武神扩展.json", jsonStr); + ReceiveMessage(`扩展导出为本地文件【武神扩展.json】。`); + } else { + const blob = new Blob([jsonStr], { type: "application/json;charset=utf-8" }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.style.display = "none "; + a.download = '武神扩展.json'; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + ReceiveMessage(`扩展导出为本地文件【武神扩展.json】。`); + } + } catch (error) { + console.error("保存JSON文件失败:", error); + alert("文件保存失败,请重试!"); + } + }, + hide: function () { + if (this.is_record) { + this.stop_record(); + } + if (this.list_elem.is('.hide')) { + this.list_elem.removeClass('hide'); + this.edit_elem.addClass('hide'); + return false; + } + this.footer_buttons.remove(); 59 + }, close: function () { + + }, + default_extend: [ + { + name: "全部击杀", + type: "button", for: "action", + content: "kill @npc" + }, + { + name: "全部拾取", + type: "button", for: "action", + content: "get all from @item(尸体)" + }, + { + name: "返回武庙", + type: "button", for: "map", + paras: "name(扬州)", + content: "jh fam 0 start;go north;go north;go west" + }, + { + name: "练习到指定等级", + type: "button", for: "skill", + content: "lianxi @id @input" + }, + { + name: "学习到指定等级", + type: "button", for: "mskill", + content: "xue @input @id from @master" + } + ], + init_extend: function () { + if (!this.setting) + this.setting = Util.storage.getItem('extends') ?? this.default_extend; + this.init_extend_group(); + }, + init_extend_group: function () { + this.groups = {}; + for (let item of this.setting) { + this.init_extend_item(item); + } + }, + save_extend: function () { + Util.storage.setItem('extends', this.setting); + this.init_extend_group(); + Combat.refActions(); + }, + init_extend_item: function (item) { + let group = this.groups[item.for]; + if (!group) group = this.groups[item.for] = []; + let cmd = item.content; + if (item.on === true) { + item.on = {}; + item.on[Process.player] = 1; + } + if (!cmd || !item.on || !item.on[Process.player]) return; + if (cmd[0] !== '#') cmd = '#' + cmd; + + group.push({ + name: item.name, + extend: true, + check: this.regex[item.for] ? + this.match(item.paras) : this.condtion(item.paras), + cmd: cmd + }); + }, + match: function (paras) { + try { + if (!paras) return null; + return this.express.match.bind(this, new RegExp(paras)); + } catch (e) { + console.error(e); + return null; + } + }, + exp_reg: /(\w+)\((>=|<=|!=|>|<)?(.+?)\)/g, + condtion: function (paras) { + if (!paras) return null; + let match = null; + let funcs = []; + while (match = this.exp_reg.exec(paras)) { + let prop = match[1]; + let oper = match[2]; + let para = match[3]; + if (!prop || !para) return null; + if (oper) { + let func = this.express[oper]; + if (!func) return null; + funcs.push(func.bind(this, prop, para)); + } else { + if (para[0] === '/' && para[para.length - 1] === '/') + funcs.push(this.express.match_prop.bind(this, prop, new RegExp(para.substring(1, para.length - 1)))); + else + funcs.push(this.express.def.bind(this, prop, para)); + } + } + return funcs.length > 0 ? funcs : null; + }, express: { + ">=": function (prop, value, obj) { + return obj[prop] >= parseInt(value); + }, ">": function (prop, value, obj) { + return obj[prop] > parseInt(value); + }, "<": function (prop, value, obj) { + return obj[prop] < parseInt(value); + }, "<=": function (prop, value, obj) { + return obj[prop] <= parseInt(value); + }, "=": function (prop, value, obj) { + return obj[prop] = parseInt(value); + }, "!=": function (prop, value, obj) { + return obj[prop] != parseInt(value); + }, + match: function (regex, text) { + let result = regex.exec(text); + if (!result) return false; + SCRIPT.lAST_MATCHES = result; + return true; + }, + match_prop: function (prop, regex, obj) { + let str = obj[prop]; + if (!str || !regex) return false; + return regex.test(str); + }, + def: function (prop, value, obj) { + let str = obj[prop]; + if (typeof str === 'number') + return str === parseInt(value); + else if (typeof str === 'boolean') + return str && str.toString() === value; + return str && str.indexOf(value) > -1; + } + }, + query: function (type, para) { + let cmds = []; + this.append(cmds, type, para); + return cmds; + }, + append: function (cmds, type, para) { + let items = this.groups[type]; + if (!items) return; + for (let item of items) { + if (this.check_para(item, para)) { + cmds.push(item) + } + } + }, + message_filter: function (mes) { + + }, + data_filter: function () { + + }, + trigger: function (msg) { + if (!this.groups) return; + let items = this.groups.message; + if (!items) return; + for (let item of items) { + if (!item.check) continue; + if (item.check(msg)) { + SCRIPT.run(item.cmd); + } + } + }, + process: function (data) { + if (!this.groups) return; + let items = this.groups.data; + if (!items) return; + for (let item of items) { + if (this.check_para(item, data)) { + SCRIPT.LAST_DATA = data; + SCRIPT.run(item.cmd); + } + } + }, + check_para: function (item, para) { + if (!item.check) return true; + for (let func of item.check) { + if (!func(para)) return false; + } + return true; + }, + onButtonClick: function () { + let paras = $(this).attr('ecmd').split('_'); + let cmd = paras[0]; + paras[0] = $(this); + let func = Dialog.extend['cmd_' + cmd]; + func && func.apply(Dialog.extend, paras); + }, cmd_add: function () { + this.edit_elem.removeClass('hide'); + this.list_elem.addClass('hide'); + this.edit_elem.attr("sid", '-1'); + let elems = this.edit_elem.find('input, textarea'); + for (let elem of elems) { + $(elem).val(""); + } + }, + cmd_up: function () { + this.cmd_move(-1); + }, + cmd_down: function () { + this.cmd_move(1); + }, + cmd_move: function (mv) { + let item = this.selected_item; + if (!item) return; + let index = this.setting.indexOf(item); + let index2 = this.setting.indexOf(item) + mv; + if (index2 < 0 || index2 >= this.setting.length) + return; + this.setting.splice(index, 1); + this.setting.splice(index2, 0, item); + this.refresh_list(); + this.save_extend(); + + }, + cmd_edit: function () { + let item = this.selected_item; + if (!item) return; + this.edit_elem.show(); + this.list_elem.hide(); + this.edit_elem.attr("sid", this.setting.indexOf(item)); + let elems = this.edit_elem.find('input, textarea, select'); + for (let elem of elems) { + let val = $(elem).val(); + let val2 = item[elem.getAttribute('prop')]; + if (val2 !== val) { + $(elem).val(val2).change();; + } + } + + }, + cmd_save: function () { + let index = parseInt(this.edit_elem.attr('sid')); + + let elems = this.edit_elem.find('input, textarea, select'); + let item = {}; + for (let elem of elems) { + item[elem.getAttribute("prop")] = elem.value; + } + if (!item.name) return this.show_error('name'); + if (!item.type) return this.show_error('type'); + if (!item.content) return this.show_error('content'); + if (item.paras) { + if (Dialog.extend.regex[item.for]) { + item.check = this.match(item.paras); + } else { + item.check = this.condtion(item.paras); + } + if (!item.check) return this.show_error('paras'); + } + this.hide(); + $(this.create_item(item, this.setting.length)).appendTo(this.list_elem); + + if (index < 0) { + this.setting.push(item); + } else { + item.on = this.setting[index].on; + this.setting[index] = item; + this.refresh_list(); + } + this.save_extend(); + + }, cmd_remove: function () { + let item = this.selected_item; + if (!item) return; + this.setting.Remove(item); + this.refresh_list(); + this.save_extend(); + }, + show_error: function (key) { + let elem = this.element.find('[prop="' + key + '"]').parent(); + elem.addClass('error-shake'); + setTimeout(() => { + elem.removeClass('error-shake'); + }, 1500); + }, cmd_show: function (elem, t) { + let infos = SCRIPT.helper[t]; + if (!infos) return; + let html = []; + for (let i = 0; i < infos.length; i++) { + html.push('
  • ', infos[i], '
  • '); + } + let ul = elem.parent(); + ul.html(html.join("")); + ul.next().html('返回').attr('ecmd', 'return'); + }, + cmd_return: function (elem) { + elem.html('保存').attr('ecmd', 'save').prev().html(this.helper); + } +}; diff --git a/src/dialog/jh.js b/src/dialog/jh.js new file mode 100644 index 0000000..1856c01 --- /dev/null +++ b/src/dialog/jh.js @@ -0,0 +1,530 @@ + + +const jh_fam = { + name: "门派", + items: null, + selected_index: 0, + type: "fam", + onDetail: function (data) { + var fb = this.items[data.index]; + if (!fb) return; + fb.type = '门派'; + fb.desc = data.desc; + fb.sp = data.sp; + fb.actions = data.actions; + fb.skills = data.skills; + return this.showDetail(fb); + }, + showDetail: function (fb) { + var html = ["
    "];
    +        html.push(fb.name);
    +        html.push("\n");
    +        html.push(fb.desc);
    +        if (fb.sp) {
    +            html.push("\n特点:");
    +            html.push(fb.sp);
    +            html.push("\n");
    +        }
    +
    +        this.append_actions(html, fb);
    +        html.push('
    进入地图'); + let cmds = []; + Dialog.extend.append(cmds, 'map', fb); + for (let item of cmds) { + html.push('', item.name, ''); + } + html.push('
    '); + if (fb.skills) { + html.push(fb.skills); + } + + html.push("
    "); + this.descElement.html(html.join("")); + this.select(fb.index); + }, + append_actions: function (html, fb) { + let actions = fb.actions ?? []; + html.push('
    '); + for (let item of actions) { + html.push('
    '); + html.push('', item[2] ?? "", ""); + if (item[1]) + html.push('', item[1], ""); + html.push('
    '); + } + + html.push('
    '); + }, + show: function (left_panel, right_panel) { + var html = []; + for (var i = 0; i < this.items.length; i++) { + var fb = this.items[i]; + html.push('
    ', fb.name, "
    "); + fb.index = i; + } + left_panel.html(html.join("")); + this.listElement = left_panel; + this.descElement = right_panel; + this.onClickItem(this.selected_index); + }, select: function (index) { + var elem = this.listElement.find("div[index='" + index + "']"); + if (elem.length && !elem.is(".selected")) { + var top = elem[0].offsetTop; + var height = this.listElement.height(); + if (top > height / 2) { + top = (height - elem.height()) / 2; + this.listElement[0].scrollTop = top; + } + if (this.selectedItem) this.selectedItem.removeClass("selected"); + this.selectedItem = elem; + this.selectedItem.addClass("selected"); + this.selected_index = index; + } + }, onClickItem: function (index) { + const item = this.items[index]; + if (!item.desc) SendCommand("jh " + this.type + " " + index); + else this.showDetail(item); + this.select(index); + }, + append_footer: function () { + let fb = this.items[this.selected_index]; + Dialog.footerElement.find('.item-commands'). + html(`进入地图`); + } +}; +const jh_fb = { + name: "副本", + type: "fb", + items: null, + selected_index: -1, + select: jh_fam.select, + onClickItem: jh_fam.onClickItem, + onDetail: function (data) { + var fb = this.items[data.index]; + if (!fb) return; + fb.type = '副本'; + fb.desc = data.desc; + fb.reward = data.reward; + fb.diffs = data.diffs; + fb.status = data.status; + return this.showDetail(fb); + }, update_unlock: function (unlock) { + this.unlock = unlock; + for (let i = 0; i < this.items.length; i++) { + this.items[i].unlock = unlock >= i; + } + if (this.selected_index < 0) + this.selected_index = unlock; + + }, show: function (left_panel, right_panel) { + this.listElement = left_panel; + this.descElement = right_panel; + var html = ["
    "]; + for (var i = 0; i < this.items.length; i++) { + var fb = this.items[i]; + html.push('
    ', fb.name, "
    "); + } + html.join("
    "); + this.listElement.html(html.join("")); + this.onClickItem(this.selected_index); + }, + show_first: function (elem) { + let text = elem.prev().html(); + text && ReceiveMessage(text); + }, + fb_models: ['普通', '困难', '组队'], + showDetail: function (fb) { + var html = ["
    "];
    +        html.push(fb.name);
    +        if (fb.unlock) {
    +            html.push("\n已解锁\n");
    +        } else {
    +            html.push("\n未解锁\n");
    +        }
    +        html.push(fb.desc);
    +        this.append_status(html, fb);
    +        if (fb.unlock && fb.diffs) {
    +            html.push('
    '); + for (let i = 0; i < fb.diffs.length; i++) { + if (fb.diffs[i]) + html.push('', this.fb_buttons[i], ''); + } + let cmds = []; + Dialog.extend.append(cmds, 'map', fb); + for (let item of cmds) { + html.push('', item.name, ''); + } + html.push('
    '); + } + html.push(fb.reward); + html.push("
    "); + this.descElement.html(html.join("")); + this.select(fb.index); + + }, append_status: function (html, fb) { + const sts = fb.status ?? []; + if (!sts.length) return; + html.push('
    '); + for (let i = 0; i < sts.length; i++) { + let status = sts[i]; + if (!status) continue; + if (status[0] === 1) { + html.push('
    '); + html.push('由', status[1], "首次通过", ""); + html.push('', this.fb_models[i], ""); + html.push('
    '); + } else { + html.push('
    '); + html.push('该模式尚未完成首杀', + status[1] ? ",称号奖励:" + status[1] : "", + ""); + html.push('', this.fb_models[i], ""); + html.push('
    '); + } + } + html.push('
    '); + }, + fb_buttons: ['进入副本', '困难模式', '组队进入'], + append_footer: function () { + let fb = this.items[this.selected_index]; + let html = []; + if (fb.unlock) { + for (let i = 0; i < fb.diffs.length; i++) { + if (fb.diffs[i]) + html.push('', this.fb_buttons[i], ''); + } + } + Dialog.footerElement.find('.item-commands').html(html.join("")); + } +}; +const jh_ar = { + name: "禁地", + items: null, + type: "ar", + selected_index: 0, + select: jh_fam.select, + onClickItem: jh_fam.onClickItem, + append_status: jh_fb.append_status, + append_actions: jh_fam.append_actions, + fb_models: ['普通', '普通', '组队'], + onDetail: function (data) { + var fb = this.items[data.index]; + if (!fb) return; + fb.type = '禁地'; + fb.desc = data.desc; + fb.actions = data.actions; + fb.status = data.status; + fb.reward = data.reward; + return this.showDetail(fb); + }, update_unlock: function (unlock) { + for (let i = 0; i < this.items.length; i++) { + this.items[i].unlock = (unlock & Math.pow(2, i)) !== 0; + } + }, show: function (left_panel, right_panel) { + var html = ["
    "]; + let count = Math.max(this.items.length, 10); + for (var i = 0; i < count; i++) { + var fb = this.items[i]; + html.push('
    ', fb.name, "
    "); + fb.index = i; + } else { + html.push('"> 
    '); + } + } + html.join("
    "); + this.listElement = left_panel; + this.descElement = right_panel; + this.listElement.html(html.join("")); + this.onClickItem(this.selected_index); + + }, showDetail: function (fb) { + var html = ["
    "];
    +        html.push(fb.name);
    +        if (fb.unlock) {
    +            html.push("\n已解锁\n");
    +        } else {
    +            html.push("\n未解锁\n");
    +        }
    +        html.push(fb.desc, '\n');
    +        this.append_status(html, fb);
    +        this.append_actions(html, fb);
    +        if (fb.unlock) {
    +            html.push('
    '); + html.push(`进入地图`); + let cmds = []; + Dialog.extend.append(cmds, 'map', fb); + for (let item of cmds) { + html.push('', item.name, ''); + } + html.push('
    '); + } + html.push(fb.reward); + html.push("
    "); + this.descElement.html(html.join("")); + this.select(fb.index); + + }, + append_footer: function () { + let fb = this.items[this.selected_index]; + if (fb.unlock) + Dialog.footerElement.find('.item-commands'). + html(`进入地图`); + else + Dialog.footerElement.find('.item-commands').empty(); + } +}; +const MAP_TYPES = { + fb: jh_fb, + fam: jh_fam, + ar: jh_ar +}; +export default { + init: function () { + Dialog.injectStyle(jh_css); + }, + close: function () { + this.element.remove(); + this.isShow = false; + }, + onData: function (data) { + if (data.close) { + return Dialog.isShow && Dialog.hide(); + } + if (data.desc) return this.selected_item.onDetail(data); + + if (data.unlock !== undefined || data.unlock2 !== undefined) { + return this.update_lock(data); + } + if (data.refresh !== undefined && this.isLoad) { + let dialog = MAP_TYPES[data.t]; + let item = dialog.items[data.refresh]; + if (item && item.desc) { + item.desc = null; + let index = dialog.items.indexOf(item); + if (dialog.selected_index == index) { + dialog.onClickItem(index); + } + } + return; + } + if (!data.fbs) return; + jh_fam.items = data.families.map(function (x) { return { name: x, unlock: false }; }); + jh_fb.items = data.fbs.map(function (x) { return { name: x }; }); + jh_ar.items = data.areas.map(function (x) { return { name: x, unlock: false }; }); + this.selected_item.show(this.listElement, this.descElement); + }, + show: function () { + if (this.isShow) return; + if (!this.element) + this.element = $("
    "); + this.listElement = this.element.find(".fb-left").on("click", + ".fb-item,.fam-item", this.item_click); + this.descElement = this.element.find(".fb-right"); + Dialog.title("江湖"); + Dialog.icon("home"); + this.element.appendTo(Dialog.contentElement); + this.isShow = true; + if (this.isLoad) { + SendCommand("jh fb lock"); + } else { + SendCommand("jh"); + this.isLoad = true; + this.selected_item = this.footers[0]; + } + this.create_footer(); + }, + selected_item: null, + footers: [jh_fam, jh_fb, jh_ar], + create_footer: function () { + var html = []; + for (var i = 0; i < this.footers.length; i++) { + let item = this.footers[i]; + html.push("" + + this.footers[i].name + ""); + } + html.push('
    '); + Dialog.footerElement.html(html.join("")); + }, item_click: function () { + var elem = $(this); + if (elem.is(".selected")) return; + let index = elem.attr("index"); + if (index !== undefined) + Dialog.jh.selected_item.onClickItem(index); + }, + update_lock: function (data) { + if (data.unlock >= 0 && jh_fb.items) { + jh_fb.update_unlock(data.unlock); + if (this.selected_item === jh_fb) + jh_fb.show(this.listElement, this.descElement); + } + if (data.unlock2 >= 0 && jh_ar.items) { + jh_ar.update_unlock(data.unlock2); + if (this.selected_item === jh_ar) + jh_ar.show(this.listElement, this.descElement); + } + + }, + footerChanged: function (index) { + let item = this.footers[index]; + if (item == this.selected_item) return; + this.selected_item = item; + Dialog.footerElement.find('.item-commands').empty(); + item.show(this.listElement, this.descElement); + } +}; + +const jh_css = ` + + +.dialog-fb { + height: 25.5em; + overflow-y: hidden; + display: flex; + flex-direction: row; +} + +.dialog-fb>.fb-left { + width: 12.5em; + height: 100%; + text-align: center; + margin-top: 0.5em; + overflow-y: auto; +} + +.dialog-fb>.fb-right { + flex: 1; + height: 100%; + overflow-y: auto; + padding-left: 0.5em; +} + +.fb-actions { + margin-top: 0.5em; +} + +.fb-actions>.fb-action { + line-height: 2em; + padding-left: 1em; + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + border-left-color: gray; + white-space: nowrap; + overflow-x: auto; + margin-bottom: 0.5em; + background-color: #111; + cursor: pointer; + display: flex; + flex-direction: row; +} + +.fb-actions>.fb-action>.action-desc { + flex: 1; + text-overflow: ellipsis; + white-space: nowrap; + color: gray; + overflow: hidden; +} + +.fb-actions>.fb-action>.action-name { + flex: 0; + background-color: #222; + padding-left: 1em; + padding-right: 1em; +} + +.fb-actions>.fb-action>.action-name:hover { + background-color: #333; +} + +.fb-actions>.finshed { + border-left-color: #00FF00; +} + +.fb-actions>.finshed>.action-desc { + color: #00FF00; +} + +.dialog-fb>.fb-right>pre { + white-space: pre-wrap; + margin: 0.5em 0.5em 2em 0.5em; +} + +.dialog-fb>.fb-left>.fb-content { + height: 100%; + overflow: auto; +} + +.dialog-fb>.fb-left>.fb-content>.fb-item { + line-height: 2em; + padding-left: 1.5em; + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + border-left-color: gray; + white-space: nowrap; + overflow-x: auto; + margin-bottom: 0.5em; + background-color: #111; + cursor: pointer; +} + + +.dialog-fb>.fb-left>.fam-item { + line-height: 2em; + padding-left: 0.5em; + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + border-left-color: gray; + white-space: nowrap; + overflow-x: auto; + margin-bottom: 0.5em; + background-color: #111; + cursor: pointer; +} + +.dialog-fb>.fb-left>.fb-content>.line { + height: 1.25em; + width: 0px; + border-left: 1px solid #343434; + margin-left: auto; + margin-right: auto; + margin-top: -1em; + margin-bottom: -1em; +} + +.dialog-fb>.fb-left>.fb-content>.lock { + border-color: #bebebe; + color: #bebebe !important; + opacity: 0.6; +} + +.dialog-fb>.fb-left>.fb-content .selected, +.dialog-fb>.fb-left>.selected { + border-color: #00ff00; + color: #00ff00; +} + +.dialog-fb>.fb-left>.fb-content>.lock:before { + font-family: 'Glyphicons Halflings'; + content: "\\e033"; + float: left; + margin-left: 0.25em; + opacity: 0.6; +} +`; diff --git a/src/dialog/keys.js b/src/dialog/keys.js new file mode 100644 index 0000000..c56d923 --- /dev/null +++ b/src/dialog/keys.js @@ -0,0 +1,194 @@ + +import Util from '../utils/util.js'; +import SCRIPT from '../script.js'; + +const Keys = { + groups: [{ + name: "移动", + items: [ + { name: "左", key: null, cmd: "#go @dir(left)" }, + { name: "右", key: null, cmd: "#go @dir(right)" }, + { name: "上", key: null, cmd: "#go @dir(up)" }, + { name: "下", key: null, cmd: "#go @dir(down)" }, + { name: "左上", key: null, cmd: "#go @dir(leftup)" }, + { name: "左下", key: null, cmd: "#go @dir(leftdown)" }, + { name: "右上", key: null, cmd: "#go @dir(rightup)" }, + { name: "右下", key: null, cmd: "#go @dir(rightdown)" } + ] + }, { + name: "菜单", + items: [ + { name: "属性", key: null, cmd: "#menu score" }, + { name: "背包", key: null, cmd: "#menu pack" }, + { name: "技能", key: null, cmd: "#menu skills" }, + { name: "任务", key: null, cmd: "#menu tasks" }, + { name: "商城", key: null, cmd: "#menu shop" }, + { name: "社交", key: null, cmd: "#menu message" }, + { name: "排行", key: null, cmd: "#menu stats" }, + { name: "设置", key: null, cmd: "#menu setting" }, + { name: "动作", key: null, cmd: "#menu showcombat" }, + { name: "活动", key: null, cmd: "#menu events" }, + { name: "聊天", key: null, cmd: "#menu showchat" }, + { name: "停止", key: null, cmd: "#menu stopstate" }, + { name: "江湖", key: null, cmd: "#menu jh" } + ] + } + ], + setting: null, + show: function (elem) { + this.element = elem; + this.init(); + elem.on('click', '.skey-item', this.item_clicked); + document.body.addEventListener('keydown', this.record_press); + }, hide: function () { + document.body.removeEventListener('keydown', this.record_press); + }, close: function () { + document.body.removeEventListener('keydown', this.record_press); + }, + record_press: function (e) { + let item = Dialog.keys.select_item; + if (!item) return; + let keyitem = Dialog.keys.get_item(item.attr("sid")); + if (!keyitem) return; + if (e.keyCode === 8 || e.keyCode === 27) { + Dialog.keys.save_setting(keyitem, null); + return item.find('.skey-key').html(''); + } + let code = Dialog.keys.get_key_code(e); + Dialog.keys.save_setting(keyitem, code); + item.find('.skey-key').html(keyitem.key); + e.preventDefault(); + e.stopPropagation(); + }, get_key_code: function (e) { + let code = e.code; + if (e.ctrlKey) { + if (e.key === "Control") return; + code = "Ctrl+" + code; + } + if (e.altKey) { + if (e.key === "Alt") return; + code = "Alt+" + code; + } + if (e.shiftKey) { + if (e.key === "Shift") return; + code = "Shift+" + code; + } + return code; + + }, save_setting: function (item, key) { + item.key = key; + if (!this.setting) this.setting = {}; + if (!key) { + key = this.id2keys[item.id]; + if (key) delete this.setting[key]; + delete this.id2keys[item.id]; + } + else if (key) { + if (this.setting[key]) { + if (this.setting[key] === item.id) { + return; + } + let old_item = this.get_item(this.setting[key]); + if (old_item) { + old_item.key = null; + this.element.find('.skey-item[sid="' + + old_item.id + '"]>.skey-key').html(""); + } + } + this.setting[key] = item.id; + } + Util.storage.setItem('keys', this.setting); + }, get_item: function (id) { + if (this.groups.length === 2) this.init(); + let sid = id.split('_'); + let group = Dialog.keys.groups[parseInt(sid[0])]; + if (!group) return; + let keyitem = group.items[parseInt(sid[1])]; + return keyitem; + }, + default_keys: { + "KeyW": "0_2", "KeyA": "0_0", "KeyR": "0_6", + "KeyD": "0_1", "KeyS": "0_3", "KeyQ": "0_4" + }, + init_key: function () { + if (this.load_storage) return; + if (Util.isMobile) return; + this.load_storage = true; + this.setting = Util.storage.getItem('keys'); + window.addEventListener('keydown', this.keypress); + this.id2keys = {}; + if (!this.setting) return; + for (let key in this.setting) { + this.id2keys[this.setting[key]] = key; + } + }, + keypress: function (e) { + if (e.target !== document.body) return; + let setting = Dialog.keys.setting; + if (!setting) return; + let code = Dialog.keys.get_key_code(e); + if (setting[code]) { + let item = Dialog.keys.get_item(setting[code]); + if (item) { + SCRIPT.run(item.cmd); + e.preventDefault(); + } + } + }, + item_clicked: function () { + let item = Dialog.keys.select_item; + if (item) item.removeClass('selected'); + Dialog.keys.select_item = $(this).addClass('selected'); + + }, + init: function () { + if (this.groups.length > 2) return; + let setting = this.id2keys || {}, id = null, j = 0; + for (let group of this.groups) { + for (let i = 0; i < group.items.length; i++) { + id = j + "_" + i; + group.items[i].id = id; + group.items[i].key = setting[id]; + } j++; + } + let group = { name: "动作栏", items: [] }; + for (let i = 0; i < 12; i++) { + + id = "2_" + i; + group.items.push({ + name: "栏位" + (i + 1), id: id, + cmd: "#action " + i, key: setting[id] + }); + } + this.groups.push(group); + group = { name: "技能栏", items: [] }; + for (let i = 0; i < 12; i++) { + id = "3_" + i; + group.items.push({ + name: "栏位" + + (i + 1), id: id, cmd: "#pfm " + i, key: setting[id] + }); + } + this.groups.push(group); + this.element && this.create_html(); + }, + create_html: function () { + let html = []; + let i = 0, j = 0; + for (let group of this.groups) { + html.push('

    ', group.name, '

    '); + j = 0; + for (let item of group.items) { + html.push('
    '); + html.push('
    ', item.name, '
    '); + html.push('
    ', item.key, '
    '); + html.push('
    '); + j++; + } + i++; + } + this.element.html(html.join("")); + } +}; + +export default Keys; diff --git a/src/dialog/list.js b/src/dialog/list.js new file mode 100644 index 0000000..13eef51 --- /dev/null +++ b/src/dialog/list.js @@ -0,0 +1,274 @@ + +import Util from '../utils/util.js'; +export default { + init: function () { + Dialog.pack.init(); + }, + hide: function () { + this.element.remove(); + this.isShow = false; + }, + close: function () { + this.hide(); + }, + updateitem: function (data) { + if (data.store) { + if (!this.stores || !this.isShow) + return Dialog.pack.onData({ remove: data.store, id: data.id }); + var item = this.find_item(1, data.id); + var store_item = this.find_item(3, data.storeid); + if (!item) { + item = Object.assign({}, store_item); + item.id = data.id; item.count = (-data.store); + Dialog.pack.items.push(item); + } else { + item.count -= data.store; + } + if (!store_item) { + store_item = Object.assign({}, item); + store_item.id = data.storeid; store_item.count = data.store; + this.stores.push(store_item); + } else { + store_item.count += data.store; + } + this.store_count = data.sum ?? this.stores.length; + if (store_item.count == 0) this.stores.Remove(store_item); + if (item.count == 0) Dialog.pack.items.Remove(item); + + } else if (data.sell) { + var item = this.find_item(2, data.id); + if (item) { + item.count -= data.sell; + return this.create_items(this.selllist, this.leftElement, 2, this.selllist.length); + } + } + if (this.isstore && this.isShow) { + this.create_items(this.stores, this.leftElement, 3, + Math.max(this.max_store_count, 100));// this.max_store_count + + Dialog.title("你的仓库中有" + this.store_count + "/" + this.max_store_count + "件物品"); + } + this.update_pack(); + if (data.money != undefined) this.show_footer(data.money); + }, find_item: function (otype, id) { + var items = Dialog.pack.items; + if (otype == 2) items = this.selllist; + else if (otype == 3) items = this.stores; + for (var i = 0; i < items.length; i++) { + if (items[i].id == id) { return items[i]; } + } + }, formatItems: function (data) { + let items = []; + for (let item of data) { + items.push({ + name: item[0], id: item[1], + count: item[2], grade: item[3], + unit: item[4], value: item[5] + }); + } + return items; + }, onData: function (data) { + if (data.id) { + return this.updateitem(data); + } + var gongji = data.gongji ?? data.jungong ?? data.yaoyuan ?? data.mvalue; + if (data.selllist) { + this.show(); + this.isstore = false; + this.gongji = gongji; + this.money_name = null; + this.typeElement.hide(); + this.selllist = this.formatItems(data.selllist); + if (data.gongji >= 0) this.money_name = '门派功绩'; + else if (data.jungong >= 0) this.money_name = "军功"; + else if (data.yaoyuan >= 0) this.money_name = "妖元"; + else this.money_name = data.mtype; + this.create_items(this.selllist, this.leftElement, 2, this.selllist.length); + Dialog.titleElement.html(data.title); + Dialog.icon("shopping-cart"); + if (data.seller) this.seller = data.seller; + this.update_pack(); + } else if (data.stores) { + this.show(); + this.typeElement.show(); + this.isstore = true; + this.stores = Dialog.pack.formatItems(data.stores); + if (data.sum > 0) { + this.typeElement.show(); + this.store_count = data.sum; + } + else { + this.typeElement.hide(); + this.store_count = data.stores.length; + } + this.create_items(this.stores, this.leftElement, 3, + Math.max(data.max_store_count, 100)); + this.leftElement[0].scrollTop = 0; + Dialog.titleElement.html("你的仓库中有" + this.store_count + "/" + + data.max_store_count + "件物品"); + this.max_store_count = data.max_store_count; + Dialog.icon("lock"); + this.update_pack(); + } + if (gongji >= 0) { + this.gongji = gongji; + this.show_footer(gongji); + } + }, + show: function (data) { + if (!Dialog.isShow || Dialog.curItem != "list") + Dialog.show("list"); + if (this.rightElement) { + this.rightElement.show(); + if (Dialog.pack.objelement) Dialog.pack.objelement.remove(); + } + if (this.isShow) return; + if (!this.element) { + this.element = $('
    道具
    秘籍
    宝石
    资源
    装备
    '); + var children = this.element.children(); + this.typeElement = $(children[0]) + this.typeElement.hide(); + this.leftElement = $(children[1]); + this.rightElement = $(children[2]); + } + this.element.on("click", ".obj-item", Dialog.list.item_click); + this.element.on("click", ".otype-item", Dialog.list.otype_click); + this.element.appendTo(Dialog.contentElement.empty()); + this.isShow = true; + + }, + selected_type: 0, + otype_click: function () { + let type = $(this).attr('otype'); + let index = parseInt(type); + let store = Dialog.list; + if (!store.stores) return; + if (index === store.selected_type) return; + let type_elems = store.typeElement.children(); + $(type_elems[store.selected_type]).removeClass('select'); + store.selected_type = parseInt(type); + $(type_elems[index]).addClass('select'); + SendCommand('store ' + index); + }, + show_footer: function (money) { + money = this.money_name ? this.gongji : money; + let cmd = this.isstore ? "store" : "sell"; + if (this.isstore) { + var str = this.money_name ? ("你目前有" + money + "" + + this.money_name + "") : ("你身上有" + Util.moneyToStr(money)); + Dialog.footerElement.html("
    " + str + "存仓库
    "); + } else { + var str = this.money_name ? ("你目前有" + money + "" + + this.money_name + "") : ("你身上有" + Util.moneyToStr(money)); + Dialog.footerElement.html("
    " + str + "清理杂物
    "); + } + }, update_pack: function () { + var items = Dialog.pack.items; + if (!items) SendCommand("pack"); + else { + this.create_items(items, this.rightElement, 1, Dialog.pack.max_count); + this.show_footer(Dialog.pack.money); + } + + }, + create_items: function (items, elem, otype, max_count) { + var html = []; + //otype 1自己的物品 2,贩卖的物品 + var list = items; + if (otype === 1 || otype === 3) { + list = Dialog.pack.sort_items(items); + } + for (var i = 0; i < max_count; i++) { + var item = list[i]; + // if (otype === 3 && item + // && item.otype !== this.selected_type) continue; + html.push('
    '); + if (otype === 1) { + html.push(''); + html.push(item.name); + html.push(''); + } else { + html.push(item.name); + } + html.push(""); + if (otype == 2) { + html.push("每"); + html.push(item.unit); + html.push(this.money_name ? (item.value + "" + this.money_name + "") + : Util.moneyToStr(item.value)); + if (item.count == -1) { + html.push(":大量现货"); + } else { + html.push(":剩余"); + html.push(item.count); + html.push(item.unit); + } + + } else if (otype === 1 && !this.isstore) { + if (item.value) { + html.push("每"); + html.push(item.unit); + html.push(Util.moneyToStr(item.value)); + html.push(":"); + html.push(item.count); + html.push(item.unit); + } else { + html.push("不可出售"); + } + + } else if (item.count > 1) { + html.push(item.count); + html.push(item.unit); + } + html.push(''); + } else { + html.push('">'); + } + + html.push('
    '); + } + elem.html(html.join("")); + + } + , item_click: function () { + var elem = $(this); + var obj = elem.attr("obj"); + var otype = elem.attr("otype"); + var item = Dialog.list.find_item(otype, obj); + if (!item) return; + var html = ["
    "]; + if (Dialog.list.isstore) { + if (otype == 3) { + html.push('查看'); + html.push('取出'); + } else if (otype == 1) { + html.push('查看'); + html.push('存到仓库'); + } + } else { + if (otype == 2) { + html.push('查看'); + if (item.count) + html.push('购买'); + } else if (otype == 1) { + + html.push('查看'); + html.push('卖掉'); + } + } + + + html.push("
    "); + Dialog.list.element.find(".item-commands").remove(); + + elem = $(html.join("")).insertAfter(elem); + Util.checkScroll(elem); + } +}; diff --git a/src/dialog/map.js b/src/dialog/map.js new file mode 100644 index 0000000..5b39f46 --- /dev/null +++ b/src/dialog/map.js @@ -0,0 +1,35 @@ + +import MAP from '../map.js'; + +export default { + onData: function (data) { + Dialog.title(data.title || "地图"); + }, + init: function () { + + }, + show: function () { + Dialog.init(); + var rm = MAP.Room.name; + var index = rm.indexOf('-'); + if (index > -1) { + rm = rm.substr(0, index); + } + Dialog.title(rm); + Dialog.footer(""); + this.element = $(".map"); + Dialog.contentElement.append(this.element); + Dialog.icon("map-marker"); + Dialog.iconElement.attr("class", "dialog-icon glyphicon glyphicon-map-marker"); + + }, + hide: function () { + this.element.remove(); + if ($(".map-panel").children().length == 0) + this.element.appendTo(".map-panel"); + + }, + close: function () { + this.hide(); + } +}; diff --git a/src/dialog/master.js b/src/dialog/master.js new file mode 100644 index 0000000..a0594c7 --- /dev/null +++ b/src/dialog/master.js @@ -0,0 +1,156 @@ + +import Util from '../utils/util.js'; +import SCRIPT from '../script.js'; + +export default { + isShow: false, + init: function () { + Dialog.skills.init(); + this.createSkillItems = Dialog.skills.createSkillItems; + this.createSkillItem = Dialog.skills.createSkillItem; + this.updateSkill = Dialog.skills.updateSkill; + this.updateSkillItem = Dialog.skills.updateSkillItem; + this.showdesc = Dialog.skills.showdesc; + this.isEnable = Dialog.skills.isEnable; + this.close = Dialog.skills.close; + }, + hide: function () { + if (this.skill_element) { + this.skill_element.remove(); + this.skill_element = null; + this.element.removeClass("hide-item"); + Dialog.footer(""); + return false; + } + this.isShow = false; + }, + + onData: function (data) { + if (data.desc) { + return this.showdesc(data); + } + if (data.id) { + //更新技能状态 + return this.updateSkill(data); + } + if (data.books) { + return this.showBooks(); + } + if (data.remove && data.from === this.master) { + this.items.Remove(this.skills[data.remove]); + var skill = this.skills[data.remove]; + for (var i = 0; i < this.items.length; i++) { + if (this.items[i].enable_skill == data.remove) { + this.items[i].enable_skill = null; + } + } + delete this.skills[data.remove]; + return this.createSkillItems(this.items); + } + if (!data.master && !data.follower) return; + Dialog.show("master"); + this.master = data.master || data.follower; + this.is_follower = !!data.follower; + var skills = {}; + for (var i = 0; i < data.items.length; i++) { + var item = data.items[i]; + skills[item.id] = item; + } + this.skills = skills; + this.items = data.items; + Dialog.title(data.title); + Dialog.icon("book"); + this.createSkillItems(data.items, skills); + if (data.limit) { + if (this.is_follower) { + let str = ['']; + str.push(''); + str.push("", data.target, "目前的技能上限为", data.limit, ""); + Dialog.footer(str.join("")); + } + else + Dialog.footer("你目前的技能上限为" + data.limit + ""); + } + }, + create_footer: function () { + + }, + selectedItem: 0, + footerChanged: function (index) { + index = parseInt(index); + if (index === this.selectedItem) return; + this.selectedItem = index; + if (index === 0) { + this.element.removeClass("dialog-books"); + this.createSkillItems(this.items, this.skills); + } else { + if (!Dialog.skills.books) SendCommand('sbook'); + else this.showBooks(); + return this.element.addClass("dialog-books"); + } + }, showBooks: function () { + if (!this.isShow || !this.is_follower) return; + var html = []; + var books = Dialog.skills.sort_items(Dialog.skills.books); + for (let item of books) { + html.push('
    '); + html.push('
    ', item.name, '
    '); + html.push('
    查看
    '); + html.push('
    学习
    '); + html.push('
    '); + } + this.element.html(html.join("")); + }, + show: function () { + if (this.isShow) return; + if (!this.element) { + this.element = $('
    '); + } + this.element.on("click", ".skill-item", this.item_click); + this.element.appendTo(Dialog.contentElement); + this.element.removeClass("hide-item"); + this.isShow = true; + }, item_click: function () { + var elem = $(this); + var item = Dialog.master.skills[elem.attr("skid")]; + if (!item) return; + var html = ["
    "]; + html.push('查看详细'); + html.push('学习'); + + item.master = 1; + if (Dialog.master.is_follower) { + var bf = 'dc ' + Dialog.master.master; + html.push('遗忘'); + html.push('练习'); + if (item.can_enables) { + for (var i = 0; i < item.can_enables.length; i++) { + var baseSkill = Dialog.master.skills[item.can_enables[i]]; + if (!baseSkill) continue; + if (baseSkill.enable_skill != item.id) + html.push('装备' + baseSkill.name + ''); + else { + html.push('取消装备' + baseSkill.name + ''); + } + } + } + if (item.enable_skill) { + var sp_skill = Dialog.master.skills[item.enable_skill]; + if (sp_skill) html.push('取消装备' + sp_skill.name + ''); + else item.enable_skill = null; + } + item.master = 0; + } + SCRIPT.LAST_OBJ = item; + let commands = Dialog.extend.query('mskill', item); + for (let item of commands) { + html.push('', item.name, ''); + } + html.push("
    "); + Dialog.master.element.find(".item-commands").remove(); + $(html.join("")).insertAfter(elem); + Util.checkScroll(elem); + } +} diff --git a/src/dialog/message.js b/src/dialog/message.js new file mode 100644 index 0000000..fd77c0c --- /dev/null +++ b/src/dialog/message.js @@ -0,0 +1,456 @@ + + +import { showFlag } from '../game/tool.js'; +export default { + init: function () { + + Dialog.injectStyle(message_css); + }, + close: function () { + + this.element.remove(); + this.isShow = false; + }, hide: function () { + if (this.detailID) { + this.hide_detail(); + return false; + } + }, hide_detail: function () { + this.element.removeClass("detail"); + this.detailID = null; + Dialog.footerElement.find('.item-commands').empty(); + }, + selected_item: 0, + messages: [], + isLoad: false, + unRead: 0, + onData: function (data) { + if (data.receive) return this.updateMessageState(data.receive, data.index); + if (data.items) { + return this.createMessageDetail(data.id, data.items); + } + if (data.clear) return this.clear_message(data.clear); + + if (data.unRead != undefined) { + this.unRead = data.unRead; + } + if (data.messages) { + for (var i = 0; i < data.messages.length; i++) { + this.addMessage(data.messages[i]); + } + } + + if (data.message) { + if (!this.isShow) this.unRead++; + if (this.messages) + this.addMessage(data.message); + if (data.message.id == "notice") { + this.showNotice(data.message); + } + } + if (this.element) + this.showMessages(); + if (this.isShow) { + if (data.message && this.element.is(".detail") + & this.detailID == data.message.id) { + this.detailElement.prepend($(this.createMessageDetailItem(data.message.id, + data.message.name, data.message))); + } + } else + this.showUnread(); + + }, showUnread: function () { + if (this.unRead) showFlag("message", this.unRead); + else showFlag("message", 0); + }, + addMessage: function (msg) { + for (let i = 0; i < this.messages.length; i++) { + if (this.messages[i].id == msg.id) { + this.messages[i] = msg; + return; + } + } + this.messages.push(msg); + }, clear_message: function (type) { + for (let i = 0; i < this.messages.length; i++) { + let from = this.messages[i].id; + if ((type === true && from !== 'notice') || from == type) { + this.messages.splice(i, 1); + i--; + } + } + this.showMessages(); + if (!this.isShow) return; + if (this.element.is(".detail") + & (type === true || this.detailID == type)) { + this.hide_detail(); + } + }, + show: function (data) { + this.unRead = 0; + this.showUnread(); + if (this.isShow) return; + this.isShow = true; + Dialog.title("消息"); + Dialog.icon("envelope"); + this.create_footer(); + this.footerChanged(this.selected_item); + if (this.isLoad) return; + SendCommand("message"); + this.isLoad = true; + + // this.element.on("click", ".detail-item", this.showDetailCommand); + }, + inner_show: function () { + + Dialog.title("消息"); + Dialog.icon("envelope"); + this.element.on("click", + ".message-item", this.showMessageDetail); + }, + inner_close: function () { + this.element.remove(); + this.isShow = false; + }, + footers: ["消息", "队伍", "关系", "帮派"], + footerElements: ["message", "team", "relation", "party"], + create_footer: function () { + var html = []; + for (var i = 0; i < this.footers.length; i++) { + html.push("" + + this.footers[i] + ""); + } + html.push(''); + Dialog.footer(html.join("")); + + + }, footerChanged: function (index) { + //if (index == this.selected_item) return; + this.selected_item = index; + Dialog.footerElement.find('.item-commands').empty(); + this.showChild(); + }, showChild: function () { + var child = Dialog[this.footerElements[this.selected_item]]; + //if (this.selectedChild == child) return; + if (this.selectedChild) this.selectedChild.inner_close(); + if (!child.element) child.element = child.createElement(); + Dialog.contentElement.html(child.element); + child.inner_show(); + + this.selectedChild = child; + }, showNotice: function (nt) { + var str = ["\n系统公告\n"]; + var dt = new Date(nt.time); + str.push(dt.getFullYear()); + str.push("年"); + str.push(dt.getMonth() + 1); + str.push("月"); + str.push(dt.getDate()); + str.push("日 "); + str.push(dt.getHours()); + str.push("时"); + str.push(dt.getMinutes()); + str.push("分\n"); + str.push(nt.content); + str.push("\n"); + ReceiveMessage(str.join("")); + }, showMessages: function (newmsg) { + var str = []; + for (var i = 0; i < this.messages.length; i++) { + var msg = this.messages[i]; + str.push("
    "); + str.push(msg.name); + + str.push(""); + str.push(this.getTimedesc(msg.time)); + str.push(""); + str.push("
    "); + str.push("
    "); + str.push(msg.content); + str.push("
    "); + str.push("
    "); + } + if (!str.length) str.push('
    暂无新消息
    '); + if (!this.listElement) this.listElement = this.element.find(".message-list"); + this.listElement.html(str.join("")); + + }, getTimedesc: function (long) { + var now = new Date(); + var time = new Date(long); + var dt = (now - time) / 1000; + if (dt < 60) return "刚刚"; + else if (dt < 3600) return parseInt(dt / 60) + "分钟前"; + else if (time.getFullYear() == now.getFullYear() && time.getMonth() == now.getMonth()) { + var diff_day = time.getDate() - now.getDate(); + var msg = "今天 " + this.add_zero(time.getHours()) + ":" + this.add_zero(time.getMinutes()); + if (diff_day == 0) return msg; + else if (diff_day == 1) return "昨天 " + msg; + else if (diff_day == 2) return "前天 " + msg; + + } + var str = (time.getMonth() + 1) + "月" + time.getDate() + "日 " + this.add_zero(time.getHours()) + ":" + this.add_zero(time.getMinutes()); + if (now - time > 2332800000) { + str += "即将过期"; + } + return str; + + }, add_zero: function (num) { + if (num < 10) return "0" + num; + return num; + }, showMessageDetail: function () { + var id = $(this).attr("fromid"); + if (!id) return; + SendCommand("message " + id); + Dialog.message.element.addClass("detail"); + + }, getMessageitem: function (id) { + for (var i = 0; i < this.messages.length; i++) { + if (this.messages[i].id == id) return this.messages[i]; + } + }, createMessageDetail: function (id, items) { + if (!this.detailElement) { + this.detailElement = this.element.find(".detail-list"); + } + var msg = this.getMessageitem(id); + if (!msg) return; + var str = []; + this.detailID = id; + let has_rec = false; + for (var i = 0; i < items.length; i++) { + var item = items[i]; + str.push(this.createMessageDetailItem(id, msg.name, item)); + if (item.attach && !item.rec) { + has_rec = true; + } + } + this.detailElement.html(str.join("")); + let cmds = ""; + if (id !== 'notice') { + cmds = `删除领取全部`; + } + Dialog.footerElement.find('.item-commands').html(cmds); + + }, createMessageDetailItem: function (id, name, item) { + var str = []; + str.push("
    "); + str.push(""); + str.push(name); + str.push(""); + str.push(""); + str.push(this.getTimedesc(item.time)); + str.push(""); + str.push("
    ");
    +        str.push(item.content);
    +        str.push("
    "); + if (item.attach) { + for (var j = 0; j < item.attach.length; j++) { + str.push("
    "); + str.push(item.attach[j].name); + str.push("
    "); + } + if (item.rec) { + str.push("
    已领取
    "); + } else { + str.push("
    领取
    "); + } + } + str.push("
    "); + return str.join(""); + }, + createElement: function () { + return $('
    '); + }, updateMessageState: function (rec, index) { + if (this.detailID != rec) return; + const elem = this.detailElement.find(".detail-item[index='" + index + "']>.detail-rec"); + elem.html("已领取").removeAttr('cmd'); + } +}; +const message_css = ` + +.dialog-message{ + height: 25em; + max-height: 30em; +} + +.dialog-message>.message-list>.empty{ + color: #505050; + padding-top: 1em; + text-align: center; +} + +.dialog-message>.message-list>.message-item { + + padding-left: 1em; + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + border-left-color: gray; + white-space: nowrap; + overflow-x: auto; + margin-top: 0.5em; + margin-bottom: 0.5em; + background-color: #111; + cursor: pointer; + +} + +.dialog-message>.message-list>.message-item>.message-title { + color: #FFFF00; + line-height: 2em; +} + +.dialog-message>.message-list>.message-item>.message-content { + white-space: break-spaces; + word-wrap: break-word; + text-overflow: ellipsis; + overflow: hidden; + margin-bottom: 0.5em; +} + +.dialog-message>.message-list>.message-item>.message-title>.message-time { + float: right; + margin-right: 0.5em; + +} + +.detail { + min-height: 25em; + max-height: 25em; +} + +.detail>.message-list { + display: none; +} + +.dialog-message>.detail-list { + display: none; +} + +.detail>.detail-list { + display: block; +} + + +.dialog-team, +.dialog-party, +.dialog-relation { + height: 25em; + max-height: 30em; +} + +.dialog-team>.empty { + color: #505050; + padding-top: 1em; + text-align: center; +} + +.dialog-team>.team-item { + padding-left: 0.5em; + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + border-left-color: gray; + white-space: nowrap; + overflow-x: auto; + margin-top: 0.5em; + margin-bottom: 0.5em; + background-color: #111; + line-height: 2em; + cursor: pointer; +} + +.dialog-team>.team-item>.item-commands { + padding-left: 2em; +} + +.dialog-team>.team-item>.team-flag { + width: 2em; + display: inline-block; + text-align: center; + color: #FFFF00 +} + +.dialog-team>.team-item>.team-name { + display: inline-block; +} + +.dialog-relation>.relation-item { + padding-left: 0.5em; + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + border-left-color: gray; + white-space: nowrap; + overflow-x: auto; + margin-top: 0.5em; + margin-bottom: 0.5em; + background-color: #111; + line-height: 2em; + display: flex; + flex-direction: row; +} + +.dialog-relation>.relation-item>.relation-desc { + flex: 1; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.dialog-relation>.relation-item>.relation-cmd { + flex: 0; + background-color: #222; + padding-left: 1em; + padding-right: 1em; + cursor: pointer; + border-left: 2px solid #111; +} + +.detail-item { + margin-bottom: 0.5em; + margin-top: 0.5em; + padding: 0.5em; + background-color: #111; + padding-left: 1em; + border-radius: 4px; + border-top-width: 2px; + border-top-style: solid; + border-top-color: gray; + white-space: nowrap; + overflow-x: auto; + margin-top: 0.5em; + margin-bottom: 0.5em; + background-color: #111; +} + +.detail-item>.detail-name { + color: #FFFF00; +} + +.detail-item>.detail-time { + margin-left: 1em; + color: gray; +} + +.detail-item>.detail-content { + white-space: pre-wrap; +} + +.detail-item>.detail-rec { + margin-top: 1em; + background-color: #222; + color: gray; + display: inline-block; + font-size: 0.8em; + padding-left: 1em; + padding-right: 1em; + border-radius: 1em; + cursor: pointer; +} + +`; diff --git a/src/dialog/packet.js b/src/dialog/packet.js new file mode 100644 index 0000000..521b3b4 --- /dev/null +++ b/src/dialog/packet.js @@ -0,0 +1,701 @@ +import Setting from '../setting.js'; +import Util from '../utils/util.js'; +import SCRIPT from '../script.js'; +import Combat from '../combat.js'; + + +export default { + close: function () { + this.hide(); + this.element.remove(); + //Dialog.footerElement.addClass("hide"); + this.isShow = false; + this.skill_element_id = null; + this.element.removeClass("hide-item"); + }, + hide: function () { }, + init: function () { + if (!this.created) { + Dialog.injectStyle(packet_css); + Dialog.injectStyle(list_css); + } + this.created = true; + }, + command_before: '', + updateitem: function (data) { + if (data.money != undefined) { + this.money = data.money; + this.show_moeny(); + } + if (data.eq_group !== undefined) { + this.eq_group = data.eq_group; + this.show_moeny(); + } + else if (data.eq != undefined && this.items) { + for (var i = 0; i < this.items.length; i++) { + if (this.items[i].id == data.id) { + this.eqs[data.eq] = this.items[i]; + this.items.splice(i, 1); + + break; + } + } + this.show_items(); + } else if (data.uneq != undefined && this.items) { + var item = this.eqs[data.uneq]; + item.can_eq = 1; + item.count = 1; + this.items.push(item); + this.eqs[data.uneq] = null; + + this.show_items(); + + } + else if (data.locked >= 0) { + let item = this.get_item(data.id); + if (item) { + item.is_lock = data.locked; + let elem = this.packElement.find('[oindex="' + data.id + '"]'); + item.is_lock ? elem.addClass('lock') : elem.removeClass('lock'); + } + } else if (data.jldesc) { + var str = []; + str.push(data.jldesc); + str.push(""); + str.push('精炼'); + str.push('精炼到满级'); + str.push(""); + this.show_sub(str.join("")); + } else if (data.xqdesc) { + var str = []; + str.push(data.xqdesc); + str.push(""); + for (var i = 0; i < data.stones.length; i++) { + var st = data.stones[i]; + str.push('镶嵌' + st.name + '
    '); + } + str.push("
    "); + this.show_sub(str.join("")); + } + else if (data.desc) { + var str = []; + str.push(data.desc); + str.push(""); + var from = data.from; + if (from == "eq") { + str.push('取消装备'); + } else if (from == "item") { + var obj = this.get_item(data.id); + SCRIPT.LAST_OBJ = obj; + if (obj) { + this.create_item_command(obj, str, data.commands); + } + } else if (from == "store") { + str.push('取出'); + } else if (from == "sj") { + str.push('取出'); + } + else { + str.push('购买'); + } + str.push(""); + this.show_sub(str.join("")); + } else if (data.remove && this.items) {//丢掉的 + var items = this.items; + for (var i = 0; i < items.length; i++) { + if (items[i].id == data.id) { + if (data.remove >= items[i].count) { + items.splice(i, 1); + Combat.DisObj(data); + } else { + items[i].count -= data.remove; + } + break; + } + } + if (this.isShow) + this.show_items(); + else return false; + + } else if (data.name && this.items) {//更新的 + var item = this.get_item(data.id); + if (item) { + item.count = data.count; + item.name = data.name; + } else { + this.items.push(data); + } + if (this.isShow) + this.show_items(); + else return false; + } else if (data.max_item_count) { + this.max_count = data.max_item_count; + ReceiveMessage((Dialog.pack2.isShow ? Dialog.pack2.target_name : "你") + "的背包容量扩充为" + this.max_count + "。"); + this.show_items(); + } else return false; + return true; + }, + get_item: function (id, items) { + items = items || this.items; + if (!items) return; + for (var i = 0; i < items.length; i++) { + if (items[i] && items[i].id == id) return items[i]; + } + }, show_sub: function (str) { + if (this.objelement) this.objelement.remove(); + var parent = this.packElement; + + if (Dialog.list.isShow) { + parent = Dialog.list.rightElement; + } + this.objelement = $("
    " + str + "
    ").appendTo( + parent.parent()).on("click", function () { + this.objelement.remove(); + this.objelement = null; + parent.show(); + }.bind(this)); + parent.hide(); + }, onData: function (data) { + if (data.items) { + this.eqs = this.formatEqs(data.eqs || []); + this.money = data.money; + this.eq_group = data.eq_group; + this.items = this.formatItems(data.items); + this.max_count = data.max_item_count; + if (this.isShow) { + this.show_items(); + this.show_moeny(); + } + } else { + if (Dialog.pack2.isShow && !data.name) return Dialog.pack2.onData(data); + if (this.updateitem(data)) return; + } + if (!this.isShow) { + if (Dialog.list.isShow) { + return Dialog.list.update_pack(data); + } + if (Dialog.trade.isShow) { + return Dialog.trade.update_pack(data); + } + } + + }, + formatPackItem: function (item) { + return { + name: item[0], id: item[1], + count: item[2], grade: item[3], + unit: item[4], value: item[5], + can_eq: item[6], can_use: item[7], + can_study: item[8], can_open: item[9], + can_combine: item[10], is_lock: item[11], + otype: item[12] + }; + } + , formatItems: function (data) { + let items = []; + for (let item of data) { + items.push(this.formatPackItem(item)); + } + return items; + }, formatEqs: function (data) { + let items = []; + for (let item of data) { + if (!item) items.push(item); + else items.push({ + name: item[0], id: item[1], + grade: item[2], can_use: item[3], is_lock: item[4] + }); + } + return items; + }, + + + show_moeny: function () { + if (!this.isShow) return;//+ "清理包裹" + let mstr = Util.moneyToStr(this.money); + let str = []; + for (let i = 0; i < 3; i++) { + str.push('', i + 1, ''); + } + str.push("
    "); + if (this.packElement.is('.cleanup')) { + + str.push("取消"); + str.push("自动存仓"); + str.push("清理杂物"); + str.push("确定
    "); + } else { + str.push("你", (mstr ? "身上有" + + mstr : "身上没有任何银两")); + str.push("整理包裹"); + } + + Dialog.footer(str.join("")); + + }, cleanup_cmds: { cleanup: true, cancle: true, store: true, sell: true }, + footerChanged: function (cmd, elem) { + if (this.cleanup_cmds[cmd]) + return this.cleanup(cmd, elem); + let index = parseInt(cmd) - 1; + if (!(index >= 0 && index < 3)) return; + SendCommand('eqgroup ' + index); + }, + cleanup: function (cmd, elem) { + let pack = this; + elem.removeClass('select'); + if (pack.packElement.is('.cleanup')) { + if (cmd == 'cleanup') { + pack.packElement.find('.obj-item>.selected'). + each(this.cleanup_item); + } else if (cmd == 'store') { + SendCommand((this.command_before ?? "") + 'store all'); + } else if (cmd == 'sell') { + SendCommand((this.command_before ?? "") + 'sell all'); + } + pack.packElement.removeClass("cleanup"); + this.show_moeny(); + } + else { + pack.packElement.find(".item-commands").remove(); + pack.packElement.addClass("cleanup"); + pack.show_items(); + this.show_moeny(); + } + }, + cleanup_item: function (x, y) { + let elem = $(y); + let item = elem.parent().attr('oindex'); + let cmd = elem.attr('cmd'); + SendCommand(cmd + " " + item); + }, + show_items: function () { + if (!this.packElement) return; + this.createItems(); + this.create_eqs(); + Dialog.icon("briefcase"); + var name = this.target_name || "你"; + Dialog.title((this.items && this.items.length) ? (name + "身上共有" + this.items.length + "/" + this.max_count + "件物品") : (name + "身上没有任何东西")); + + }, + init_element: function () { + if (!this.element) { + this.element = $('
    武器
    衣服' + + '
    头部
    ' + + '披风
    戒指
    项链' + + '
    饰品
    护腕
    ' + + '
    腰带
    暗器
    '); + this.packElement = this.element.find(".obj-list"); + this.eqElement = this.element.find(".eq-list"); + } + }, + show: function () { + if (!Dialog.isShow) Dialog.show(); + if (this.objelement) { + this.objelement.remove(); + this.objelement = null; + this.packElement && this.packElement.show(); + } + if (this.isShow) return SendCommand(this.items ? "pack none" : "pack"); + this.isShow = true; + this.init_element(); + this.packElement.on("click", ".obj-item", Dialog.pack.item_click) + this.eqElement.on("click", ".eq-item", Dialog.pack.eqitem_click); + this.packElement.removeClass('cleanup'); + this.element.appendTo(Dialog.contentElement); + + if (!this.items) SendCommand("pack"); + else { + SendCommand("pack none"); + this.show_items(); + } + }, + + create_eqs: function () { + var items = this.eqElement.children(); + for (var i = 0; i < items.length; i++) { + var eq = this.eqs[i]; + if (eq) { + $(items[i]).attr('class', + 'eq-item grade' + eq.grade).attr("oindex", i).find('.eq-name').html(eq.name); + } else { + $(items[i]).attr('class', + "eq-item empty").attr("oindex", "").find('.eq-name').html(""); + } + } + }, levels: { + "wht": 0, "hig": 1, "hic": 2, "hiy": 3, "hiz": 4, "hio": 5, "ord": 6 + }, + sort_items: function (items) { + if (!items || !Setting.auto_sortitem) return items; + var list = []; + for (var i = 0; i < items.length; i++) { + var item = items[i]; + var isok = false; + for (var j = 0; j < list.length; j++) { + if (item.grade < list[j].grade) { + list.splice(j, 0, item); + isok = true; + break; + } + } + if (!isok) { + list.push(item); + } + } + return list; + }, + createItems: function () { + if (!this.items) return; + var items = Dialog.pack.sort_items(this.items); + var html = []; + let is_cleanup = this.packElement?.is('.cleanup'); + for (var i = 0; i < this.max_count; i++) { + var item = items[i]; + + if (item) { + html.push('
    '); + html.push(item.name); + if (this.show_type == 1) { + html.push(""); + html.push("每"); + html.push(item.unit); + html.push(Util.moneyToStr(item.value)); + html.push(":"); + html.push(item.count); + html.push(item.unit); + html.push(''); + } else if (item.count > 1) { + html.push(""); + html.push(item.count); + html.push(item.unit); + html.push(''); + } + if (is_cleanup) { + if (item.grade > 0) { + html.push("存仓库"); + } + if (item.can_combine && item.count >= item.can_combine) { + html.push("合成"); + } + if (this.target_name) { + html.push("拿来"); + } + if (item.can_eq && item.grade > 0) { + html.push("卖掉"); + html.push("分解"); + } else if (item.value > 0) { + html.push("卖掉"); + } else if (!item.grade) { + html.push("丢掉"); + } + } + } else { + html.push('
    '); + } + html.push('
    '); + } + this.packElement.html(html.join("")); + + }, create_item_command: function (item, html, commands) { + html.push('丢掉'); + //if (item.count > 1) { + // html.push('全部丢掉'); + //} + html.push('', item.is_lock ? "解锁" : "锁定", ''); + if (item.can_eq) { + html.push('装备'); + if (!this.command_before) { + html.push('精炼'); + html.push('镶嵌'); + html.push('设置快速装备'); + } + html.push('分解'); + + } + if (item.can_use) { + html.push('使用'); + if (!item.can_eq && !this.command_before) { + html.push('设置快速使用'); + } + } + if (item.can_open) { + html.push('打开'); + } + if (item.can_study) { + html.push('学习'); + } + if (item.can_combine && item.count >= item.can_combine) { + html.push('合成'); + } + if (this.command_before) { + html.push('拿来'); + } + commands = commands || []; + Dialog.extend.append(commands, 'pack', item); + for (var i = 0; i < commands.length; i++) { + if (commands[i].extend) + html.push('', commands[i].name, ''); + else + html.push('', commands[i].name, ''); + } + } + , item_click: function (e) { + let elem = $(e.target); + let is_cleanup = Dialog.pack.packElement.is('.cleanup'); + if (is_cleanup && elem.is('.obj-oper')) + return Dialog.pack.item_cleanup(elem); + elem = $(this); + var obj = elem.attr("oindex"); + if (!obj) return; + var item = Dialog.pack.get_item(obj); + Dialog.pack.packElement.find(".item-commands").remove(); + if (!item) return; + SCRIPT.LAST_OBJ = item; + var html = [""]; + html.push('查看'); + Dialog.pack.create_item_command(item, html); + html.push(""); + elem = $(html.join("")).insertAfter(elem); + Util.checkScroll(elem); + }, + eqitem_click: function () { + var item = Dialog.pack.eqs[$(this).attr("oindex")]; + if (!item) return; + SendCommand("checkobj " + item.id + " from eq"); + }, item_cleanup: function (elem) { + if (elem.is('.selected')) elem.removeClass('selected'); + else { + elem.parent().find('.selected').removeClass('selected'); + elem.addClass('selected'); + } + return false; + } +}; + + + +const packet_css = ` + +.dialog-pack { + min-width: 360px; + overflow-x: auto; + padding-top: 0.5em; +} + + +.dialog-pack>.obj-list { + width: 50%; + display: inline-block; + overflow-y: auto; + height: 25.625em; +} + + +.obj-list>.obj-item { + + margin-left: 0.5em; +} + +.dialog-pack>.obj-desc { + padding: 0.25em; + margin: 0px; + white-space: pre-wrap; + width: 45%; + height: 25.625em; + display: inline-block; + float: left; + overflow-y: auto; +} + + +.eq-list { + width: 50%; + display: inline-block; + float: left; +} + +.eq-list>.eq-item { + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + white-space: nowrap; + overflow-x: auto; + margin-bottom: 0.5em; + background-color: #111; + cursor: pointer; +} + +.eq-list>.empty { + border-color: gray; + color: gray; +} + +.eq-list>.eq-item>.eq-name { + white-space: nowrap; + padding-left: 0.3125em; +} + +.eq-list>.eq-item>.eq-type { + background-color: #333; + color: gray; + line-height: 1.875em; + display: inline-block; + height: 1.875em; + width: 3em; + text-align: center; +} + +.obj-list>.obj-item { + background-color: #111; + line-height: 1.875em; + min-height: 1.875em; + padding-left: 0.3125em; + + overflow-x: auto; + white-space: nowrap; + margin-bottom: 0.5em; + border-radius: 4px; +} + +.obj-list>.lock:before { + content: "\e033"; + font-family: 'Glyphicons Halflings'; + font-size: 0.8em; + margin-right: 0.2em; + color: var(--border-color); + +} + +.obj-item>.obj-oper { + float: right; + margin-right: 0.625em; + padding-left: 0.5em; + padding-right: 0.5em; + line-height: 1.5em; + background-color: #222; + border-radius: 0.5em; + margin-top: 0.2em; + color: gray; + display: none; + cursor: pointer; + user-select: none; +} + +.cleanup>.obj-item>.obj-oper { + display: inline-block; +} + +.cleanup>.obj-item>.selected { + color: #00FF00; +} + + + +.obj-item>.obj-count, +.obj-item>.obj-value { + float: right; + margin-right: 0.625em; +} + +.cleanup>.obj-item>.obj-value, +.cleanup>.obj-item>.obj-count { + display: none; +} + + +.obj-list>.disabled { + opacity: 0.5; +} + + + +`; + +const list_css = ` + +.dialog-list { + width: 100%; + white-space: nowrap; + overflow-x: auto; + padding-top: 0.5em; + display: flex; + flex-direction: row; +} + +.dialog-list>.otype-list { + width: 6em; +} + +.dialog-list>.otype-list>.otype-item { + white-space: nowrap; + line-height: 2em; + width: 5em; + text-align: center; + background-color: #111; + border-radius: 4px; + margin-bottom: 0.5em; + margin-right: 0.5em; + margin-left: 0.5em; + text-align: center; + cursor: pointer; +} + +.dialog-list>.otype-list>.select { + background-color: #222; + color: #00ff00; + border-left-width: 2px; + border-left-style: solid; + border-left-color: #00ff00; +} + +.dialog-list>.trade-list, +.dialog-list>.obj-list { + + height: 21.25em; + display: inline-block; + overflow-y: auto; + flex: 1; +} + + +.dialog-list>.obj-desc { + padding: 0.25em; + margin: 0px; + white-space: pre-wrap; + flex: 1; + overflow-y: auto; +} + +.dialog-list>.trade-list { + + height: 21.25em; + display: inline-block; + overflow-y: auto; + flex: 1; +} +.trade-list>.obj-item { + background-color: #111; + line-height: 1.875em; + min-height: 1.875em; + padding-left: 0.3125em; + + overflow-x: auto; + white-space: nowrap; + margin-bottom: 0.5em; + border-radius: 4px; +} + +.trade-list>.lock:before { + content: "\e033"; + font-family: 'Glyphicons Halflings'; + font-size: 0.8em; + margin-right: 0.2em; + color: var(--border-color); + +}`; diff --git a/src/dialog/packet2.js b/src/dialog/packet2.js new file mode 100644 index 0000000..65e1d6b --- /dev/null +++ b/src/dialog/packet2.js @@ -0,0 +1,111 @@ +import SCRIPT from '../script.js'; +import Util from '../utils/util.js'; + + +export default { + init: function () { + Dialog.pack.init(); + // this.cleanup_cmds = Dialog.pack.cleanup_cmds; + // this.formatEqs = Dialog.pack.formatEqs; + // this.formatItems = Dialog.pack.formatItems; + // this.formatPackItem = Dialog.pack.formatPackItem; + // this.createItems = Dialog.pack.createItems; + // this.create_eqs = Dialog.pack.create_eqs; + // this.init_element = Dialog.pack.init_element; + // this.show_items = Dialog.pack.show_items; + // this.updateitem = Dialog.pack.updateitem; + // this.footerChanged = Dialog.pack.footerChanged; + // this.cleanup = Dialog.pack.cleanup; + + this.show_sub = Dialog.pack.show_sub; + this.close = Dialog.pack.close; + this.get_item = Dialog.pack.get_item; + this.create_item_command = Dialog.pack.create_item_command; + }, + onData: function (data) { + + this.show(); + if (data.items) { + this.eqs = this.formatEqs(data.eqs || []); + this.money = data.money; + this.id = data.id; + this.command_before = "dc " + this.id + " "; + this.items = this.formatItems(data.items); + this.target_name = data.name; + this.max_count = data.max_item_count; + this.show_items(); + this.show_moeny(); + } else { + this.updateitem(data) + } + + }, + show_moeny: function () { + if (!this.isShow) return;//+ "清理包裹
    " + let mstr = Util.moneyToStr(this.money); + let str = []; + str.push("
    "); + if (this.packElement.is('.cleanup')) { + + str.push("取消"); + str.push("自动存仓"); + str.push("清理杂物"); + str.push("确定
    "); + } else { + str.push(this.target_name, (mstr ? "身上有" + + mstr : "身上没有任何银两")); + str.push("整理"); + } + Dialog.footer(str.join("")); + + }, + cleanup_item: function (x, y) { + let elem = $(y); + let item = elem.parent().attr('oindex'); + let cmd = elem.attr('cmd'); + SendCommand(Dialog.pack2.command_before + " " + cmd + " " + item); + }, + hide: function () { + this.element.remove(); + this.isShow = false; + }, + show: function () { + if (!Dialog.isShow) Dialog.show("pack2"); + if (this.objelement) { + this.objelement.remove(); + this.objelement = null; + this.packElement && this.packElement.show(); + } + if (this.isShow) return; + this.isShow = true; + this.init_element(); + this.packElement.on("click", ".obj-item", this.item_click) + this.eqElement.on("click", ".eq-item", this.eqitem_click); + this.element.appendTo(Dialog.contentElement); + } + , item_click: function (e) { + let elem = $(e.target); + let is_cleanup = Dialog.pack2.packElement.is('.cleanup'); + if (is_cleanup && elem.is('.obj-oper')) + return Dialog.pack.item_cleanup(elem); + elem = $(this); + var obj = elem.attr("oindex"); + if (!obj) return; + var item = Dialog.pack2.get_item(obj); + Dialog.pack2.element.find(".item-commands").remove(); + if (!item) return; + SCRIPT.LAST_OBJ = item; + var html = [""]; + html.push('查看'); + Dialog.pack2.create_item_command(item, html); + html.push(""); + elem = $(html.join("")).insertAfter(elem); + Util.checkScroll(elem); + + }, eqitem_click: function () { + var item = Dialog.pack2.eqs[$(this).attr("oindex")]; + if (!item) return; + SendCommand(Dialog.pack2.command_before + " checkobj " + item.id + " from eq"); + } + +}; diff --git a/src/dialog/paimai.js b/src/dialog/paimai.js new file mode 100644 index 0000000..cff88f2 --- /dev/null +++ b/src/dialog/paimai.js @@ -0,0 +1,156 @@ + + +const paimai_css = ` +.dialog-pms { + max-height: 32em; + margin-bottom: 0.5em; +} + +.dialog-pms>.empty { + text-align: center; + margin-top: 3em; + margin-bottom: 3em; + color: gray; +} + +.dialog-pms>.pm-item { + border-radius: 6px; + background-color: #111111; + border-left-width: 4px; + border-left-style: solid; + border-left-color: gray; + position: relative; + padding-left: 0.5em; + line-height: 2em; + margin-top: 0.5em; + cursor: pointer; +} + +.dialog-pms>.selected { + border-left-color: #00ff00; + background-color: #222; +} + +.dialog-pms>.pm-item>.pm-title { + width: 10em; + +} + +.dialog-pms>.pm-item>.pm-desc { + min-width: 10em; + flex: 1; +} + +.dialog-pms>.pm-item>.pm-mem { + + padding-right: 1em; + color: gray; + font-size: 0.8em; +} + +.dialog-pms>.pm-item>.pm-add { + width: 4em; + border-left: 1px solid #343434; + text-align: center; + color: #008080 +} + +.dialog-pms>.pm-item>.pm-add:hover { + background-color: #333; +} +`; + +function format_time_span(time) { + let diff = Math.floor((time) / 1000); + if (diff < 0) diff = 0; + if (diff > 3600) { + let str = Math.floor(diff / 3600) + "小时"; + diff = diff % 3600; + str += Math.floor(diff / 60) + "分"; + return str; + } + let str = Math.floor(diff / 60) + "分"; + diff = diff % 60; + + return str + diff + "秒"; + +} + +export default { + init: function () { + Dialog.injectStyle(paimai_css); + }, + close: function () { + this.element.remove(); + this.isShow = false; + }, onData: function (data) { + if (data.list) { + this.show(); + this.create_items(data.list); + } else if (data.item) { + this.update_item(data.item); + } + }, + show: function () { + if (!Dialog.isShow || Dialog.curItem != "pm") + Dialog.show("pm"); + if (!this.element) + this.element = $("
    "); + if (this.isShow) return; + Dialog.title("拍卖行"); + Dialog.icon("shopping-cart"); + Dialog.footer(""); + this.element.appendTo(Dialog.contentElement); + this.element.on('click', '.pm-item', this.select_item); + this.isShow = true; + }, + select_item: function () { + let elem = $(this); + let dialog = Dialog.pm; + if (dialog.selected_item) + dialog.selected_item.removeClass('selected'); + dialog.selected_item = elem; + dialog.selected_item.addClass('selected'); + }, update_item: function (item) { + let elem = this.element.find('.pm-item[oid="' + item[0] + '"]'); + if (elem) elem.replaceWith(this.create_item(item)); + }, + create_items: function (list) { + let str = []; + for (let i = 0; i < list.length; i++) { + str.push(this.create_item(list[i])); + } + if (!str.length) str.push('
    暂无拍卖
    '); + this.element.html(str.join("")); + Dialog.footer('共有' + + list.length + '项道具正在拍卖'); + + }, create_item: function (item) { + let str = []; + const [id, name, money, time, uname] = item; + str.push("
    "); + str.push("
    "); + str.push(name); + str.push("
    "); + + str.push("
    "); + if (uname) { + str.push(uname, '最后出价', moneyToStr(money),); + } else { + str.push('当前价格', moneyToStr(money),); + } + str.push("
    "); + + str.push("
    "); + str.push('剩余:', format_time_span(time), ''); + str.push("
    "); + str.push("
    "); + str.push('出价'); + str.push("
    "); + str.push("
    "); + return str.join(""); + }, + format_num: function (num) { + return num > 9 ? num.toString() : "0" + num.toString(); + } +}; diff --git a/src/dialog/party.js b/src/dialog/party.js new file mode 100644 index 0000000..d7d8b78 --- /dev/null +++ b/src/dialog/party.js @@ -0,0 +1,268 @@ + + +const party_css = ` +.dialog-party>wht { + display: inline-block; + height: 15rem; + line-height: 15rem; + text-align: center; + width: 100%; +} + +.dialog-party>.dialog-party-add { + margin-top: 2em; + text-align: center; +} + +.dialog-party>.dialog-party-add>input { + border: 1px solid gray; + background-color: transparent; + color: unset; + resize: none; + margin-top: 1em; + margin-bottom: 1em; + line-height: 2em; + border-radius: 0.5em; + text-align: center; +} + +.dialog-party>.party-title { + font-size: 2rem; + width: 100%; + text-align: center; + height: 2rem; + line-height: 2rem; + margin-top: 0.25em; + margin-bottom: 0.25em; + opacity: 0.7; + font-weight: bold; + +} + +.dialog-party>.party-notice { + padding-top: 0.25em; + padding-bottom: 0.25em; + color: #00FFFF; + line-height: 2em; +} + +.dialog-party>.party-notice>*>span { + + width: 3em; + display: inline-block; + padding-right: 0.5em; +} + +.dialog-party>.party-title>.party-count { + + font-size: 1rem; +} + +.dialog-party>.party-title>*>.glyphicon { + + padding-right: 0.5em; + float: left; +} + +.dialog-party>.party-roles { + + overflow-x: hidden; + overflow-y: auto; +} + +.dialog-party>.party-roles>.party-role, +.dialog-party>.party-item { + + padding-left: 0.5em; + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + border-left-color: gray; + white-space: nowrap; + overflow-x: auto; + margin-top: 0.5em; + margin-bottom: 0.5em; + background-color: #111; + line-height: 2em; + cursor: pointer; +} + +.dialog-party>.party-item { + display: flex; +} + +.dialog-party>.party-item>.party-item-name { + padding-left: 0.5em; + flex: 1; +} + +.dialog-party>.party-item>.party-item-sc { + + flex: 0; + margin-left: 1em; + margin-right: 1em; +} + +.dialog-party>.party-item>.party-item-cmd { + flex: 0; + background-color: #222; + padding-left: 1em; + padding-right: 1em; +} + +.dialog-party>.party-roles>.party-role>.role-level { + + width: 3em; + display: inline-block; +} + +.dialog-party>.party-roles>.party-role>.role-name { + padding-left: 0.5em; +} + +.dialog-party>.party-roles>.party-role>.role-sc { + float: right; + padding-right: 0.5rem; + +} +`; + +export default { + init: function () { + Dialog.injectStyle(party_css); + }, + createElement: function () { + return $('
    '); + }, + inner_show: function () { + //需要优化 + SendCommand("party load"); + this.isShow = true; + Dialog.title(""); + this.element.on("click", '.party-role', this.show_commands); + Dialog.icon("flag"); + }, + levels: ["", "帮主", "副帮主", "长老", "堂主", "帮众"], + level_roles: [1, 20, 30, 40, 50, 60], + level: 5, + get_role: function (id) { + if (!this.roles) return; + for (var i = 0; i < this.roles.length; i++) { + if (this.roles[i].id == id) return this.roles[i]; + } + }, + command: function (type) { + if (type === 'create') { + + let str = ['
    ']; + str.push('
    创建帮派需要500两黄金,请输入帮派名称(2-5字中文):
    '); + + str.push(''); + + str.push("
    取消确定
    "); + str.push('
    '); + this.element.html(str.join("")); + } else if (type === 'cancle') { + this.empty('你还没有加入帮派'); + } else if (type === 'create2') { + let val = $('.dialog-party-add>input').val(); + if (!val || val.length > 5 || val.length < 2) + return ReceiveMessage("帮派名字需要是2-5中文字符。"); + SendCommand('party create2 ' + val); + } + + }, empty: function (str) { + this.element.html("" + str + "
    创建帮派加入帮派
    "); + + }, + show_list: function (data) { + if (!data.list.length) return this.empty('现在没有已经创建的帮派'); + var str = []; + for (let item of data.list) { + str.push("
    "); + str.push(""); + str.push(item[0]); + str.push(""); + str.push("人数:"); + str.push(item[1]); + str.push(""); + str.push("加入"); + str.push("
    "); + } + this.element.html(str.join("")); + }, + onData: function (data) { + if (data.list) return this.show_list(data); + if (!data.name) { + return this.empty('你还没有加入帮派'); + } + var party = data; + + Dialog.title('帮派【' + party.name + '】 ' + data.roles.length + "/" + this.level_roles[data.level] + ""); + var str = []; + // str.push("
    "); + // str.push(party.name); + // str.push("(" + data.roles.length + "/" + this.level_roles[data.level] + ")"); + // str.push("
    "); + if (party.notice) { + str.push("
    "); + str.push(party.notice); + str.push("
    "); + } + str.push("
    "); + for (var i = 0; i < party.roles.length; i++) { + var role = party.roles[i]; + if (role.id == Process.player) { + this.level = role.level; + } + str.push("
    "); + str.push(""); + str.push(this.levels[role.level]); + str.push(""); + str.push(""); + str.push(role.name); + str.push(""); + str.push(""); + str.push(role.sc); + str.push(""); + str.push("
    "); + } + str.push("
    "); + this.roles = data.roles; + this.element.html(str.join("")); + }, show_commands: function () { + var role = Dialog.party.get_role($(this).attr("roleid")); + if (!role) return; + var html = ["
    "]; + + + if (role.id == Process.player) { + html.push('退出帮派'); + if (Dialog.party.level == 1) { + html.push('解散'); + } + } else { + if (role.level > Dialog.party.level - 1 && role.level > 2) + html.push('提升为' + (Dialog.party.levels[role.level - 1]) + ''); + if (role.level > Dialog.party.level && role.level < 5) { + html.push('降级为' + (Dialog.party.levels[role.level + 1]) + ''); + } + if (Dialog.party.level == 1 && role.level == 2) { + html.push('让位'); + } + if (role.level > Dialog.party.level) + html.push('开除'); + if (role.online) { + html.push('邀请组队'); + } + } + if (html.length == 1) return; + html.push("
    "); + Dialog.party.element.find(".item-commands").remove(); + $(html.join("")).insertAfter(this); + }, + inner_close: function () { + this.element.remove(); + this.isShow = false; + } +}; diff --git a/src/dialog/relation.js b/src/dialog/relation.js new file mode 100644 index 0000000..91c2ef9 --- /dev/null +++ b/src/dialog/relation.js @@ -0,0 +1,94 @@ + + +export default { + init: function () { }, + createElement: function () { + return $('
    '); + }, + inner_show: function () { + SendCommand("relation"); + this.isShow = true; + Dialog.title("关系"); + Dialog.icon("heart"); + }, + onData: function (data) { + var str = []; + str.push("
    "); + str.push("
    "); + if (data.husband) { + str.push("你的丈夫:"); + str.push(data.husband); + } else if (data.wife) { + str.push("你的妻子:"); + str.push(data.wife); + } else { + str.push("你目前没有结婚。"); + } + str.push("
    "); + if (data.wife || data.husband) { + str.push("
    ❀送花❀
    "); + str.push("
    解除关系
    "); + } + str.push("
    "); + + str.push("
    "); + str.push("
    "); + if (data.shifu) { + str.push("你的师父:"); + str.push(data.shifu); + } else if (data.tudi) { + str.push("你的徒弟:"); + str.push(data.tudi); + + } else { + str.push("你目前没有拜师,也没有收徒。"); + } + str.push("
    "); + if (data.shifu) { + str.push("
    请安
    "); + str.push("
    出师
    "); + + str.push("
    "); + } else if (data.tid) { + str.push("
    解除关系
    "); + } + str.push(""); + + if (data.st != undefined) { + str.push("
    "); + str.push("当师徒组队完成副本后将获得额外奖励,本周已完成" + data.st + "/10。", '
    '); + str.push("
    邀请组队
    "); + str.push("
    "); + } + if (data.reward) { + str.push("
    "); + str.push(data.reward) + str.push("
    "); + } + str.push(""); + if (data.fls) { + for (let item of data.fls) { + if (!item) continue; + str.push("
    "); + str.push("
    你的家人:", item[0]); + if (item[2]) { + str.push(',已', item[2], format_time_span(item[3])); + str.push('
    '); + str.push("
    停止
    "); + } else { + str.push('空闲中
    '); + str.push("
    采药
    "); + str.push("
    钓鱼
    "); + str.push("
    挖矿
    "); + } + str.push(""); + } + } + this.element.html(str.join("")); + }, + inner_close: function () { + this.element.remove(); + this.isShow = false; + } +}; diff --git a/src/dialog/score.js b/src/dialog/score.js new file mode 100644 index 0000000..4895abd --- /dev/null +++ b/src/dialog/score.js @@ -0,0 +1,333 @@ + + +export default { + footer: [["属性", null], + ["详细", null], ["称号", null]], + + selectIndex: 0, + onData: function (data) { + console.log(data); + this.data = data; + this.init_elem(); + Dialog.titleElement.html(data.name); + Dialog.icon("user"); + if (data.titles) { + this.titles = data.titles; + this.create_titles(); + } else { + if (data.id && data.id != this.uid) { + this.uid = data.id; + if (this.uid != Process.player) { + Dialog.footerElement.find(".footer-item:eq(2)").hide(); + } else { + Dialog.footerElement.find(".footer-item:eq(2)").show(); + } + } + var panel = $(data.name ? this.footer[0][1] : this.footer[1][1]); + var elems = panel.find("span"); + for (var i = 0; i < elems.length; i++) { + var elem = $(elems[i]); + var prop = elem.attr("data-prop"); + if (prop) { + elem.html(data[prop] || 0); + } + } + } + }, + init: function () { + this.footer[0][1] = $(this.template_score); + this.footer[1][1] = $(this.template_score2); + this.footer[2][1] = $(this.template_title); + Dialog.injectStyle(this.css); + }, + init_elem: function () { + Dialog.init(); + Dialog.curItem = "score"; + if (this.isShow) return; + Dialog.footer(""); + + for (var i = 0; i < this.footer.length; i++) { + $("" + + this.footer[i][0] + "").appendTo(Dialog.footerElement); + } + this.isShow = true; + this.footerChanged(this.selectIndex); + + }, + show: function (nosend) { + if (nosend) return; + if (!this.selectIndex) SendCommand("score"); + else if (this.selectIndex == 1) SendCommand("score2"); + else SendCommand("score title"); + this.init_elem(); + }, + close: function () { + this.footer[this.selectIndex][1].remove(); + Dialog.footer(""); + this.isShow = false; + }, + footerChanged: function (item) { + item = parseInt(item); + this.footer[this.selectIndex][1].remove(); + this.selectIndex = item; + + var panel = $(this.footer[this.selectIndex][1]).appendTo(Dialog.contentElement.empty()); + if (item == 1) { + if (this.uid && Process.player != this.uid) + SendCommand("score2 " + this.uid); + else + SendCommand("score2"); + } + else if (item == 2) { + if (!this.titles) + SendCommand("score title"); + panel.on("click", ".btn-noused", function (e) { + var elem = $(e.target); + if (elem.is("red")) elem = elem.parent(); + var index = parseInt(elem.attr("index")); + for (var i = 0; i < this.titles.length; i++) { + if (i == index) this.titles[i].use = this.titles[i].use ? false : true; + else this.titles[i].use = false; + } + SendCommand("title " + index); + this.create_titles(); + }.bind(this)); + } + }, + + create_titles: function () { + var panel = $(".dialog-titles"); + var html = []; + for (var i = 0; i < this.titles.length; i++) { + html.push("
    "); + html.push(this.titles[i].title); + html.push(""); + html.push(this.titles[i].use ? "取消" : "使用"); + html.push(""); + + html.push("
    "); + } + panel.html(html.length ? html.join("") : "
    你还没有获得任何称号
    "); + }, + + + template_score: ` +
    +
    + + 【性别】 + + + 【等级】 +
    + + 【年龄】 + 14
    + + 【经验】 + + 0 + + 【潜能】 + + 0 +
    +
    +
    + 【气血】 + + 0 / 0 +
    +
    + 【内力】 + + 0 / 0 +
    + + 【内力上限】 + + 0
    + + 【精力】 + + 0 +
    +
    + + 【臂力】 + + 0 + (+0) + + + 【根骨】 + + 0 + (+0) +
    + + 【身法】 + + 0 + (+0) + + + 【悟性】 + + 0 + (+0) +
    + + 【容貌】 + + 0 + +
    +
    + + 【攻击】 + + 0 + + 【防御】 + + 0
    + + 【命中】 + + 0 + + 【躲闪】 + + 0
    + + 【招架】 + + 0 + + 【暴击】 + + 0
    + + 【攻击速度】 + + 0 +
    +
    + + 【门派】 + + 无门无派
    + + 【师傅】 + +
    + + 【功绩】 + + 0
    +
    +
    `, + template_score2: `
    + + 【最终伤害】 + + + 0 + +
    + + 【忽视防御】 + + + 0 +
    + + + 【暴击伤害】 + + + 0 + +
    + + + 【伤害减免】 + + + 0 + +
    + + 【暴击抵抗】 + + + 0 +
    + + 【释放时间减少】 + + + 0 +
    + + 【忙乱时间】 + + + 0 +
    + + 【忽视忙乱】 + + + 0 +
    + + 【冷却时间减少】 + + + 0 +
    + + 【内力消耗减少】 + + + 0 +
    + + 【负面抵抗】 + + + 0 +
    + + 【打坐效率】 + + + 0 +
    + + 【学习效率】 + + + 0 +
    + + 【练习效率】 + + + 0 + +
    `, + template_title: `
    +
    +`, + + +}; diff --git a/src/dialog/setting.js b/src/dialog/setting.js new file mode 100644 index 0000000..9d290e0 --- /dev/null +++ b/src/dialog/setting.js @@ -0,0 +1,1087 @@ + +import Util from '../utils/util.js'; +import Setting from '../setting.js'; +import { GameClient, hide2show, ReceiveMessage } from '../client.js'; + +export default { + footer: [["显示", "setting"], ["高级", "custom"] + , ["快捷键", "keys"], ["扩展", "extend"] + ], + selectitem: null, + init: function () { + if (this.settingElement) return; + if (Util.isMobile) this.footer.splice(2, 1); + + this.settingElement = $(setting_template); + this.extendElement = $(extend_template); + this.keysElement = $(keys_template); + this.customElement = $(custom_template); + Dialog.injectStyle(setting_css); + var elems = $(".setting>.setting-item"); + for (var i = 0; i < elems.length; i++) { + var item = $(elems[i]); + var prop = item.attr("for"); + if (!prop) continue; + var value = Setting[prop]; + switch (prop) { + case "fontsize": + this.select_color(item.find(".color-item"), value, "fontSize"); + break; + case "font": + this.select_color(item.find(".color-item"), value, "fontFamily"); + break; + case "fontcolor": + this.select_color(item.find(".color-item"), value, "backgroundColor"); + break; + case "backcolor": + this.select_color(item.find(".color-item"), value, "backgroundColor"); + break; + case "combat_size": + case "menu_size": + case "dialog_size": + this.select_value(item.find(".color-item"), value); + break; + case "auto_pfm": + case "auto_pfm2": + if (value) { + item.find(".switch ").addClass("on"); + item.find(".switch-text").html("开"); + $("#" + prop).show().val(value); + } + break; + case "auto_work": + if (value) { + item.find(".switch ").addClass("on"); + item.find(".switch-text").html("开"); + $("#" + prop).show().val(value != 1 ? value : ""); + } + break; + default: + if (value == 1) { + item.find(".switch ").addClass("on"); + item.find(".switch-text").html("开"); + } + break; + } + } + }, + show: function () { + if (this.isShow) return; + this.footerChanged("setting"); + Dialog.icon("cog"); + Dialog.title("设置"); + Dialog.footerElement.empty(); + for (var i = 0; i < this.footer.length; i++) { + var elem = $("" + + this.footer[i][0] + "").appendTo(Dialog.footerElement); + if (i == 0) elem.addClass("select"); + } + this.isShow = true; + }, select_color: function (elems, value, style) { + for (var i = 0; i < elems.length; i++) { + if (elems[i].style[style] == value) { + $(elems[i]).addClass("select"); + } else { + $(elems[i]).removeClass("select"); + } + } + }, select_value: function (elems, value) { + for (var i = 0; i < elems.length; i++) { + if ($(elems[i]).attr('value') == value) { + $(elems[i]).addClass("select"); + } else { + $(elems[i]).removeClass("select"); + } + } + }, + footerChanged: function (item) { + + let elem = this[item + "Element"]; + if (!elem || elem === this.selectitem) return this.child?.command(item); + this.selectitem && this.selectitem.remove(); + this.selectitem = elem; + if (this.child) this.child.hide(); + this.child = null; + + if (item == "setting") { + this.selectitem.on("click", ".switch", this.switchClick); + this.selectitem.on("click", ".color-item", this.colorClick); + } else if (item == "custom") { + this.selectitem.on("click", ".switch", this.switchClick); + this.selectitem.on("click", ".setting-ok", this.save_custom); + } else { + this.child = Dialog[item]; + this.child.show(this.selectitem); + } + this.selectitem.appendTo(Dialog.contentElement); + }, helpClick: function () { + var elem = $(this); + var act = elem.attr("action"); + switch (act) { + case "tologin": + break; + case "torole": + GameClient.Close(); + hide2show("#role_panel", function () { + Process.player = null; + Process.clear(); + }); + break; + case "toserver": + Process.player = null; + GameClient.Close(); + break; + default: + + break; + } + }, + close_help: function () { + if (this.frame) { + this.frame.remove(); + this.selectitem.removeClass("help-detl"); + this.frame = null; + } + }, hide: function () { + if (this.child && this.child.hide() === false) { + return false; + } + this.close(); + }, close: function () { + this.child?.close(); + this.selectitem?.remove(); + this.isShow = false; + this.selectitem = null; + this.child = null; + } + , save_custom: function () { + if ($(".dialog-custom>.setting-item[for='auto_pfm']>.switch").is(".on")) { + var val = $("#auto_pfm").val(); + if (!val) return ReceiveMessage("你没有设置自动出招的绝招。"); + if (val.length > 300) return ReceiveMessage("你设置的出招过长。"); + Setting.save("auto_pfm", val); + } + if ($(".dialog-custom>.setting-item[for='auto_pfm2']>.switch").is(".on")) { + var val = $("#auto_pfm2").val(); + if (!val) return ReceiveMessage("你没有设置自动反击的绝招。"); + if (val.length > 300) return ReceiveMessage("你设置的出招过长。"); + Setting.save("auto_pfm2", val); + } + if ($(".dialog-custom>.setting-item[for='auto_work']>.switch").is(".on")) { + var val = $("#auto_work").val(); + if (val && val.length > 400) return ReceiveMessage("你设置的过长。"); + Setting.save("auto_work", val || 1); + } + ReceiveMessage("设置已保存。"); + + }, get_pfms: function (id) { + if (!Combat.Skills) { + return ReceiveMessage("你没有可用的绝招设置。"); + } + var str = []; + for (var i = 0; i < Combat.Skills.length; i++) { + if (str.length > 0) str.push(","); + str.push(Combat.Skills[i].id); + + } + $("#" + id).val(str.join("")); + ReceiveMessage("已预设置为你默认的绝招(未保存),你可以修改为适合你的出招顺序后点击保存"); + + + }, switchClick: function (e) { + var elem = $(this); + var forProp = elem.parent().attr("for"); + //if (!forProp) return; + var value = 0; + if (elem.is(".on")) { + elem.removeClass("on"); + elem.find(".switch-text").html("关"); + } else { + elem.addClass("on"); + elem.find(".switch-text").html("开"); + value = 1; + } + switch (forProp) { + case "auto_pfm": + case "auto_pfm2": + if (value) { + $("#" + forProp).show(); + Dialog.setting.get_pfms(forProp); + Setting[forProp] = 0; + } else { + $("#" + forProp).hide(); + Setting.save(forProp, 0); + } + break; + case "auto_work": + if (value) { + $("#" + forProp).show(); + } else { + $("#" + forProp).hide(); + Setting.save(forProp, 0); + } + break; + default: + Setting.save(forProp, value); + break; + } + e.cancelable = true; + return false; + }, + COLORS: { + "rgb(255, 255, 255)": "#fff", + "rgb(189, 195, 199)": "#bdc3c7", + "rgb(0, 128, 0)": "#008000" + } + , colorClick: function () { + var elem = $(this); + if (elem.is(".select")) return; + var par = elem.parent(); + par.children().removeClass("select"); + elem.addClass("select"); + var forProp = par.closest(".setting-item").attr("for"); + if (!forProp) return; + var value = ""; + switch (forProp) { + case "combat_size": + case "dialog_size": + case "menu_size": + value = elem.attr('value'); + break; + case "fontsize": + value = elem[0].style.fontSize; + break; + case "fontcolor": + value = Dialog.setting.COLORS[elem[0].style.backgroundColor] ?? ""; + break; + case "backcolor": + value = elem[0].style.backgroundColor; + break; + case "font": + value = elem[0].style.fontFamily; + if (!value) value = "none"; + break; + } + Setting.save(forProp, value); + } +}; + + +const setting_template = ` +
    + +

    房间信息

    +
    + + 不显示房间描述 + + + + + + 关 + + +
    +
    + + 出口描述使用方向描述 + + + + + + 关 + + +
    +
    + + 在房间列出NPC或道具的可用命令 + + + + + + 关 + + +
    + +
    + + 在命令栏列出房间内的可用物品 + + + + + + 关 + + +
    +
    + + 自己始终显示在房间物品第一列 + + + + + + 关 + + +
    + +
    + + 切换房间时不清空上房间信息 + + + + + + 关 + + +
    +
    + + 不显示玩家进出房间描述 + + + + + + 关 + + +
    +
    + + 隐藏玩家列表(只显示自己和NPC) + + + + + + 关 + + +
    +
    + + 聊天信息不分开显示 + + + + + + 关 + + +
    +
    + + 按品质自动排列背包和技能 + + + + + + 关 + + +
    +
    + + 不显示其他玩家或NPC的房间消息(基本忽略所有战斗,动作描述,慎用) + + + + + + 关 + + +
    +
    + + 动作栏显示快捷操作 + + + + + + 关 + + +
    + +

    战斗信息

    + +
    + + 战斗时自动打开战斗面板 + + + + + + 关 + + +
    +
    + + 战斗时自动隐藏房间信息 + + + + + + 关 + + +
    +
    + + 不显示其他玩家的战斗信息 + + + + + + 关 + + +
    +
    + + 不显示自己的普通战斗信息 + + + + + + 关 + + +
    +
    + + 动作栏允许换行 + + + + + + 关 + + +
    +
    + + 技能栏允许换行 + + + + + + 关 + + +
    + +
    + + 显示血量为数字 + + + + + + 关 + + +
    +
    + + 关闭血条显示 + + + + + + 关 + + +
    +
    + + 显示伤害统计 + + + + + + 关 + + +
    +

    基本设置

    +
    + + 全屏显示 + + + + + + 关 + + +
    +
    + + 字体(仅浏览器) + + + + + + + +
    +
    + + 字体大小 + + + + + + + +
    + +
    + + 正常字体颜色 + + + + + + +
    +
    + + 底部操作栏大小 + + + 0.8 + 0.9 + x1 + x1.2 + +
    +
    + + 顶部窗口大小 + + + 0.8 + 0.9 + x1 + x1.2 + +
    +
    + + 菜单栏大小 + + + 0.8 + 0.9 + x1 + x1.2 + +
    +

    游戏设置

    +
    + + 不接受玩家拜师 + + + + + + 关 + + +
    +
    + + 不接受玩家组队邀请 + + + + + + 关 + + +
    +
    + + 隐藏自己的装备 + + + + + + 关 + + +
    +
    + + 允许其他玩家查看自己的自创武功 + + + + + + 关 + + +
    +
    + + 不接受比试 + + + + + + 关 + + +
    + +
    + + PK保护 + + + + + + 关 + + +
    +

    频道设置

    +
    + + 屏蔽公共频道 + + + + + + 关 + + +
    +
    + + 屏蔽门派频道 + + + + + + 关 + + +
    +
    + + 屏蔽全区频道 + + + + + + 关 + + +
    +
    + + 屏蔽帮派频道 + + + + + + 关 + + +
    +
    +`; +const custom_template = `
    + +
    + + 当你击杀玩家或NPC时,自动出招 + + + + + + 关 + + +
    + +
    + + 当你被玩家击杀时,自动反击 + + + + + + 关 + + +
    + +
    + + 当你学习,练习,打坐中断后,自动去挖矿或以下操作 + + + + + + 关 + + +
    + + +
    + + 当你击杀NPC后自动拾取战利品 + + + + + + 关 + + +
    + + + + +
    `; +const keys_template = `
    `; +const extend_template = `
    `; + + +const setting_css = ` +.setting { + padding-bottom: 0.625em; + height: 30em; +} + +.setting-item { + line-height: 2em; + padding-left: 1em; + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + border-left-color: gray; + white-space: nowrap; + overflow-x: auto; + margin-bottom: 0.5em; + background-color: #111; + cursor: pointer; + display: flex; + flex-direction: row; +} + +.setting-item>.title { + margin-right: 0.625em; + flex: 1; + text-align: left; + white-space: initial; +} + +.setting-item>.color-list { + + margin-right: 1em; +} +.color-list>.color-item { + width: 3em; + height: 1.25em; + display: inline-block; + border: 2px solid #cecece; + line-height: 1.25em; + text-align: center; + border-radius: 1em; + box-sizing: content-box; +} + +.color-list>.select { + border-color: #ff0000; +} +.setting-item>.button { + flex: 0; + background-color: #222; + padding-left: 1em; + padding-right: 1em; + border-left: 1px solid gray; +} + +.setting-item>.button:active { + background-color: #111; +} + + +.setting>h3 { + color: #C0C0C0; + border-bottom: 1px solid #343434; + padding-bottom: 0.5em; +} + +.setting>.settingbox { + margin-left: 0.625em; + border: 1px solid gray; + background-color: transparent; + color: unset; + resize: none; + width: 98%; + height: 3rem; +} + +.setting>.setting-ok { + border: 1px solid gray; + background-color: transparent; + color: unset; + width: 5rem; + height: 1.7rem; + margin-top: 1rem; + margin-bottom: 3rem; +} + +.dialog-skeys { + height: 30em; + overflow-y: auto; +} + + +.dialog-skeys>.selected { + border-left-color: #00FF00; + color: #00FF00; +} + + + +.extend-list { + margin-top: 0.5em; + height: 30em; + text-align: center; +} + +.extend-list>.buttons { + text-align: center; +} + +.extend-list>.buttons>button { + margin: 0.5em; + color: gray; + background-color: #111; + line-height: 2em; +} + + +.extend-add { + display: flex; + flex-direction: column; + margin-top: 0.5em; + height: 30em; +} + + +.extend-row { + line-height: 2em; + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + border-left-color: gray; + white-space: nowrap; + overflow-x: auto; + margin-bottom: 0.5em; + background-color: #111; + cursor: pointer; + display: flex; + flex-direction: row; + border-top: 1px solid #222; + border-bottom: 1px solid #222; + border-right: 1px solid transparent; +} + +.extend-row>.extend-input { + flex: 1; + border: none; + outline: none; + background-color: black; + color: #cecece; + padding-left: 1em; +} + +.extend-row>input { + height: 2em; +} + +.extend-row>textarea { + height: 100%; + resize: none +} + +.extend-row>.extend-menus { + display: flex; + flex-direction: column; +} + +.extend-row>.extend-row-header { + width: 8em; + text-align: center; +} + +.extend-help { + padding-inline-start: 0.5em; + width: 100%; + text-align: center; + color: gray; + flex: 1; + overflow: auto; + list-style-position: inside; + text-align: left; + white-space: normal; + line-height: 1.5em; +} + +.extend-menus>.switch { + margin-top: 1em; + width: 7em; + margin-left: 0.5em; +} + +.extend-menus>button { + margin: 1em 0px; + color: gray; + background-color: #111; +} + +.skey-item { + line-height: 2em; + padding-left: 1em; + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + border-left-color: gray; + white-space: nowrap; + overflow-x: auto; + margin-bottom: 0.5em; + background-color: #111; + cursor: pointer; + display: flex; + flex-direction: row; +} + +.skey-item>.skey-name { + flex: 1; + text-overflow: ellipsis; + white-space: nowrap; + color: gray; + overflow: hidden; +} + +.skey-item>.skey-key { + background-color: #222; + width: 7em; + text-align: center; +} + +.switch { + display: inline-block; + position: relative; + height: 2em; + width: 5em; + line-height: 2em; + border-radius: 1em; + background: #222; + cursor: pointer; + -ms-user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; + vertical-align: middle; + text-align: center; +} + +.switch>.switch-button { + position: absolute; + left: 0px; + height: 2em; + width: 2em; + border-radius: 1em; + background: gray; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); + transition: 0.3s; + -webkit-transition: 0.3s; + left: 0px; +} + +.switch>.switch-text { + color: #898989; + margin-left: 0.625em; +} + +.on { + background-color: #008000; +} + +.on>.switch-button { + right: 0px; + left: auto; + background-color: #eee; +} + +.on>.switch-text { + margin-right: 0.625em; + margin-left: 0px; + color: #eee; +} +`; diff --git a/src/dialog/shop.js b/src/dialog/shop.js new file mode 100644 index 0000000..e5b1e6b --- /dev/null +++ b/src/dialog/shop.js @@ -0,0 +1,274 @@ + + +import Util from '../utils/util.js'; +export default { + init: function () { + Dialog.injectStyle(shop_css); + }, + selected_item: 0, + close: function () { + this.element.remove(); + this.isShow = false; + }, onData: function (data) { + if (data.money) { + let ms = data.money ?? [0, 0]; + this.money = ms[0]; + this.cash_money = ms[1]; + if (ms.length > 2) { + this.footers = ["黄金", "元宝", '活动']; + this.act_money = ms[2]; + this.act_name = data.mtype ?? "积分"; + } + this.create_footer(); + } + if (data.remove) { + let item = this.get_item(data.remove); + if (item) item.removed = true; + return this.show_items(); + } + if (data.item) { + let [id, count] = data.item; + let item = this.get_item(id); + if (item) { + item.count = count; + this.show_items(); + } + return; + } + + if (!data.idx) return; + this.idx = data.idx; + this.list0 = this.format_items(data.selllist[0], 0); + this.list1 = this.format_items(data.selllist[1], 1); + if (data.selllist.length > 2) + this.list2 = this.format_items(data.selllist[2], 2); + + this.show_items(); + }, + footerChanged: function (index) { + + this.selected_item = parseInt(index); + this.show_items(); + this.create_footer(); + }, footers: ["黄金", "元宝"], + create_footer: function () { + if (!this.isShow) return; + var html = []; + for (var i = 0; i < this.footers.length; i++) { + html.push("" + + this.footers[i] + ""); + } + if (this.selected_item === 0) { + html.push('
    ', + this.money > 0 ? "你身上有" + Util.moneyToStr(this.money) : "你身上没有银两" + , '
    '); + } else if (this.selected_item === 1) { + html.push('
    ', + this.cash_money > 0 ? "你身上有" + this.cash_money + + "元宝" : "你身上没有元宝" + , '账号转入
    '); + } else if (this.selected_item === 2) { + html.push('
    ', + "你身上有", this.act_money > 0 ? this.act_money : 0 + , this.act_name); + } + Dialog.footer(html.join("")); + }, + format_items: function (ary, mtype) { + let items = []; + for (let data of ary) { + if (!data) continue; + let item = { + id: data[0], name: data[1], + desc: data[2], value: data[3], grade: data[4], + discount: data[5] + }; + if (data[6]) { + item.limit = data[6]; + item.count = data[7]; + } + if (item.discount < 1) { + if (mtype === 0) + item.price0 = "" + item.value + "两黄金"; + else if (mtype === 1) + item.price0 = "" + item.value + "元宝"; + else if (mtype === 2) + item.price0 = "" + item.value + this.act_name + ""; + item.value = item.value * item.discount; + } + if (mtype === 0) { + if (item.value >= 1) + item.price = "" + item.value + "两黄金"; + else + item.price = "" + (item.value * 100) + "两白银"; + } else if (mtype === 1) { + item.price = "" + item.value + "元宝"; + } else if (mtype === 2) { + item.price = item.value + this.act_name; + + } + + items.push(item); + } + return items; + } + , show_items: function () { + if (!this.isShow) return; + this.create_items([this.list0, this.list1, this.list2][this.selected_item]); + }, get_item: function (id) { + + if (this.list0) for (let item of this.list0) if (item.id === id) return item; + if (this.list1) for (let item of this.list1) if (item.id === id) return item; + if (this.list2) for (let item of this.list2) if (item.id === id) return item; + }, + show: function (data) { + if (!this.element) { + this.element = $("
    "); + } + Dialog.title("商品列表"); + Dialog.icon("shopping-cart"); + this.isShow = true; + this.element.appendTo(Dialog.contentElement); + if (!this.idx) SendCommand("shop"); + else SendCommand("shop " + this.idx); + }, create_items: function (items) { + let str = []; + for (let i = 0; i < items.length; i++) { + let item = items[i]; + if (item.removed) { + items.splice(i, 1); + i--; + continue; + } + str.push("
    "); + + str.push('
    ', item.name, '
    '); + if (item.limit > 0) + str.push("(", item.count, "/", item.limit, ")"); + + str.push("
    "); + str.push("
    ");
    +            str.push(item.desc)
    +            str.push("
    "); + str.push("
    '); + if (item.price0) { + str.push(' ', item.price0, ' '); + } + str.push(item.price); + str.push("
    "); + str.push("
    "); + } + this.element.find('.dialog-shop').html(str.join("")); + } +}; + +const shop_css = ` + +.dialog-shop-content { + height: 25em; +} + +.dialog-shop { + max-height: 32em; + padding-bottom: 0.5em; + margin-top: 0.5em; +} + +.dialog-shop>.shop-item { + border-radius: 6px; + background-color: #111111; + border-left-width: 4px; + border-left-style: solid; + position: relative; + margin-bottom: 0.5em; + padding-left: 0.5em; + display: flex; + flex-direction: row; +} + +.shop-item-title { + display: flex; + flex-direction: row; + line-height: 2em; + place-items: 1em; +} + +.shop-item-title>.shop-item-name { + margin: 0px; + color: var(--border-color); + font-weight: bold; +} + +.shop-item-title>.discount-tag { + + background: linear-gradient(135deg, #ff3e3e 0%, #ff9100 100%); + color: white; + width: 4em; + font-weight: bold; + text-align: center; + border-radius: 0.5em; + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.2); + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); +} + + + +.dialog-shop>.shop-item .shop-desc { + margin: 0; + padding-top: 0.5em; + padding-bottom: 0.5em; + white-space: pre-wrap; +} + +.dialog-shop>.shop-item .shop-label { + background: linear-gradient(110deg, transparent 0%, rgba(255, 159, 28, 0.8) 50%, transparent 100%); + + animation: shine 3s infinite linear; + color: #fff; + font-size: 12px; + padding: 2px 8px; + border-radius: 4px; + font-weight: bold; +} + + +.dialog-shop>.shop-item>.shop-btn { + width: 8em; + display: inline-block; + border-left: 1px solid var(--border-color); + text-align: center; + font-weight: bold; + background-color: transparent; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + background-color: #222; + flex-wrap: wrap; +} + +.dialog-shop-footer { + text-align: right; + padding-right: 0.5em; +} + +.dialog-shop-footer>span { + line-height: 1.8em; + margin-left: 1em; + color: #808000; + display: inline-block; + padding-right: 1em; + text-align: center; + text-decoration: underline; + border-right: 1px solid #808000; +} + +`; diff --git a/src/dialog/skills.js b/src/dialog/skills.js new file mode 100644 index 0000000..bab7013 --- /dev/null +++ b/src/dialog/skills.js @@ -0,0 +1,534 @@ +import Setting from '../setting.js'; +import Util from '../utils/util.js'; +import SCRIPT from '../script.js'; + + +export default { + isShow: false, + selectItem: ".dialog-skills", + init: function () { + if (!this.created) + Dialog.injectStyle(skills_css); + this.created = true; + }, + hide: function () { + if (this.skill_element) { + this.skill_element.remove(); + this.skill_element = null; + this.element.removeClass("hide-item"); + this.create_footer(); + this.skill_element_id = null; + return false; + } + }, + close: function () { + this.hide(); + this.element.remove(); + //Dialog.footerElement.addClass("hide"); + this.isShow = false; + this.skill_element_id = null; + this.element.removeClass("hide-item"); + }, + limit: 0, + selected_item: -1, + showdesc: function (data) { + if (!this.isShow) return; + this.element.find(".item-commands").remove(); + if (this.skill_element) this.skill_element.remove(); + this.skill_element = $("
    ").html(data.desc).appendTo(this.element);
    +        // Dialog.title(data.title);
    +        this.skill_element_id = data.id;
    +        this.element.addClass("hide-item");
    +        let html = ['
    ']; + + if (this.master) { + html.push('学习'); + if (this.is_follower) { + html.push('进阶'); + html.push('遗忘'); + } + + } else { + if (data.is_custom) + html.push('推演'); + html.push('进阶'); + html.push('融合'); + html.push('遗忘'); + } + html.push('
    '); + Dialog.footer(html.join("")); + + }, + footerChanged: function (index, ref) { + if (index == this.selected_item && !ref) return; + this.selected_item = index; + Dialog.skills.element.find(".item-commands").remove(); + if (index == 2) { + if (!this.books) SendCommand('sbook'); + else this.showBooks(); + return this.element.addClass("dialog-books"); + } + if (this.element.is('.dialog-books')) { + this.element.removeClass('dialog-books'); + this.create_footer(); + return this.createSkillItems(this.items); + } + if (index == 0) { + this.element.find('.base').removeClass('hide'); + this.element.find(".skill").addClass('hide'); + } else if (index == 1) { + this.element.find('.base').addClass('hide'); + this.element.find(".skill").removeClass('hide'); + } + }, + footers: ["基础", "特殊", "书架"], + eq_group: 0, + create_footer: function (isbook) { + var footers = this.footers; + var html = []; + for (var i = 0; i < footers.length; i++) { + html.push("" + + footers[i] + ""); + } + // if (isbook) + // html.push("你的书架目前有" + this.books.length + "本秘籍"); + // else + // html.push("你目前的技能上限为" + this.limit + ""); + if (!isbook) { + for (let i = 0; i < 3; i++) { + html.push('', 3 - i, ''); + } + } + Dialog.footer(html.join("")); + }, + eq_group_click: function () { + let group = parseInt($(this).attr('group')); + if (group >= 0) SendCommand('skgroup ' + group); + }, + updateSkill: function (data) { + if (!this.skills) return; + var item = this.skills[data.id]; + if (!item) { + + return this.addSkill(item); + } + if (data.name) + item.name = data.name; + if (data.grade >= 0 && data.grade !== item.grade) { + item.grade = data.grade; + if (item.can_enables) { + for (let sk of item.can_enables) { + let base_skill = this.skills[sk]; + if (base_skill && base_skill.enable_skill === data.id) { + this.updateSkillItem(base_skill); + } + } + } + } + if (data.enable) { + if (item.enable_skill) { + var old_skill = item.enable_skill; + item.enable_skill = null; + this.skills[old_skill][data.id] = false; + this.updateSkillItem(this.skills[old_skill]); + } + this.skills[data.enable][data.id] = true; + item.enable_skill = data.enable; + this.updateSkillItem(this.skills[data.enable]); + this.updateSkillItem(this.skills[data.id]); + } else if (data.exp != undefined || data.level != undefined) { + if (data.level >= 0) item.level = data.level; + if (data.exp >= 0) item.exp = data.exp; + if (data.can_enables) item.can_enables = data.can_enables; + this.updateSkillItem(item); + } + else if (data.enable == false) { + if (item.enable_skill) { + var old_skill = item.enable_skill; + this.skills[old_skill][data.id] = false; + item.enable_skill = null; + this.updateSkillItem(this.skills[old_skill]); + this.updateSkillItem(this.skills[data.id]); + } + } + + }, updateSkillItem: function (item) { + var sk_elem = this.element.find(".skill-item[skid='" + item.id + "']"); + if (sk_elem) { + let hide = sk_elem.css('display') === 'none'; + sk_elem.replaceWith(this.createSkillItem(item)); + if (hide) sk_elem.hide(); + } + }, + addSkill: function (item) { + + if (!this.items || !item) return; + if (this.skills[item.id]) { + return this.updateSkill(item); + } + this.items.push(item); + this.skills[item.id] = item; + this.items = this.sort_items(this.items); + this.createSkillItems(this.items); + }, format_books: function (data) { + let books = []; + + for (let i = 0; i < data.length; i++) { + books.push({ + name: data[i][0], + grade: data[i][1], + id: i + }); + } + return books; + }, + onData: function (data) { + if (data.book) { + if (!this.books) return; + this.books.push({ name: data.book[0], grade: data.book[1], id: data.book[2] }); + if (this.isShow && this.selected_item == 2) { + return this.showBooks(); + } + return; + } + if (data.books) { + this.books = this.format_books(data.books); + if (this.isShow || !Dialog.master.isShow) + return this.showBooks(); + else + return Dialog.master.showBooks(); + } + if (data.id && !data.desc) { + if (data.from) + return this.updateSkill.call(Dialog.master, data); + return this.updateSkill(data); + } + if (data.item) { + if (Dialog.master.isShow && Dialog.master.is_follower) { + return this.addSkill.call(Dialog.master, data.item); + } + return this.addSkill(data.item); + } + if (!this.isShow) { + if (Dialog.master.isShow) + return Dialog.master.onData(data); + } + + if (data.desc) { + if (data.id) this.updateSkill(data); + return this.showdesc(data); + } + + + if (data.remove && this.items) { + if (data.from && data.from !== Process.player) return; + this.items.Remove(this.skills[data.remove]); + + for (var i = 0; i < this.items.length; i++) { + if (this.items[i].enable_skill == data.remove) { + this.items[i].enable_skill = null; + } + } + delete this.skills[data.remove]; + if (this.skill_element && this.skill_element_id === data.remove) { + this.hide(); + } + return this.createSkillItems(this.items); + } + if (data.items) { + this.title = data.title; + Dialog.title(this.title + ",等级上限" + data.limit + "级"); + Dialog.icon("book"); + this.items = this.sort_items(data.items); + this.skills = {}; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + this.skills[item.id] = item; + } + if (this.items.length > 10 && this.selected_item < 0) { + this.footerChanged(0); + } + this.createSkillItems(this.items); + } + if (data.sk_group >= 0) { + this.sk_group = data.sk_group; + this.limit = data.limit; + this.create_footer(); + } + if (data.limit >= 0) { + this.limit = data.limit; + Dialog.title(this.title + ",等级上限" + this.limit + "级"); + } + }, + show: function () { + if (this.isShow) return; + this.isShow = true; + if (!this.element) { + // this.container = $('
    1
    2
    3
    '); + this.element = $('
    '); + Dialog.footerElement + .on("click", ".sk-group", Dialog.skills.eq_group_click); + } + this.element.on("click", ".skill-item", Dialog.skills.item_click); + //Dialog.footerElement.remveClass("hide"); + this.element.appendTo(Dialog.contentElement); + //this.container.appendTo(Dialog.contentElement); + this.element.removeClass("hide-item"); + if (!this.items) SendCommand("cha"); + else { + SendCommand("cha none"); + Dialog.icon("book"); + this.create_footer(); + } + }, + isEnable: function (item, skills) { + if (!item.can_enables) return false; + for (var i = 0; i < item.can_enables.length; i++) { + var base_skill = skills[item.can_enables[i]]; + if (base_skill && base_skill.enable_skill == item.id) return true; + } + return false; + }, + showBooks: function () { + var html = []; + var books = this.sort_items(this.books); + for (let item of books) { + html.push('
    '); + html.push('
    ', item.name, '
    '); + html.push('
    查看
    '); + html.push('
    学习
    '); + html.push('
    '); + } + this.element.html(html.join("")); + this.create_footer(true); + }, + createSkillItem: function (item, skills) { + skills = skills || this.skills; + var html = []; + html.push('
    '); + + html.push(''); + html.push(item.name); + // html.push(''); + if (item.enable_skill && skills) { + var sp_skill = skills[item.enable_skill]; + if (sp_skill) { + html.push('已装备:'); + html.push(wrap_name(sp_skill)); + html.push(""); + } + + } + + html.push(''); + // var lv_desc = this.get_lvdesc(item.level); + //push(lv_desc.replace(">", ">" + item.level + '级 / ' + item.exp + "%" + ' ')); + html.push(item.level); + html.push('级 / '); + html.push(item.exp); + html.push("%"); + html.push(' '); + html.push(Dialog.skills.get_lvdesc(item.level)); + html.push('
    '); + return html.join(""); + }, + sort_items: function (items) { + if (!items || !Setting.auto_sortitem) return items; + var list = []; + for (var i = 0; i < items.length; i++) { + var item = items[i]; + var isok = false; + for (var j = 0; j < list.length; j++) { + if (item.grade > list[j].grade) { + list.splice(j, 0, item); + isok = true; + break; + } + } + if (!isok) { + list.push(item); + } + } + return list; + }, + createSkillItems: function (items, skills) { + let html = []; + for (var i = 0; i < items.length; i++) { + html.push(this.createSkillItem(items[i], skills)); + } + this.element.html(html.join("")); + + }, level_color: ["wht", "hig", "hic", "hij", "hiz", "hio", "ord"] + , get_lvdesc: function (level) { + if (level < 1000) + return Dialog.skills.skill_levels[parseInt(level / 50)]; + var v = parseInt((level - 1000) / 500); + if (v > 6) v = 6; + return Dialog.skills.skill_levels[v + 20]; + }, + skill_levels: [ + "初学乍练", "不知所以", "粗通皮毛", "渐有所悟", + "半生不熟", "马马虎虎", "平淡无奇", "触类旁通", + "心领神会", "挥洒自如", "驾轻就熟", "出类拔萃", + "初入佳境", "神乎其技", "威不可当", + "豁然贯通", "超群绝伦", "登峰造极", "登堂入室", + "一代宗师", "超凡入圣", "出神入化", "独步天下", + "空前绝后", "旷古绝伦", "深不可测", "返璞归真"] + , + item_click: function () { + var elem = $(this); + var html = ["
    "]; + var item = Dialog.skills.skills[elem.attr("skid")]; + if (!item) return; + html.push('查看详细'); + if (item.can_enables) { + for (var i = 0; i < item.can_enables.length; i++) { + var baseSkill = Dialog.skills.skills[item.can_enables[i]]; + if (!baseSkill) continue; + if (baseSkill.enable_skill != item.id) + html.push('装备' + baseSkill.name + ''); + else { + html.push('取消装备' + baseSkill.name + ''); + } + } + } + if (item.enable_skill) { + var sp_skill = Dialog.skills.skills[item.enable_skill]; + if (sp_skill) html.push('取消装备' + sp_skill.name + ''); + else item.enable_skill = null; + } + html.push('遗忘'); + html.push('练习'); + SCRIPT.LAST_OBJ = item; + let commands = Dialog.extend.query('skill', item); + for (let item of commands) { + html.push('', item.name, ''); + } + html.push("
    "); + Dialog.skills.element.find(".item-commands").remove(); + $(html.join("")).insertAfter(elem); + Util.checkScroll(elem.next()); + } +}; +const level_desc = ["wht", "hig", "hic", "hiy", "him", "hio", 'ord']; +function wrap_name(obj) { + let tag = level_desc[obj.grade]; + return `<${tag}>${obj.name}`; +} +const skills_css = ` +.dialog-skills { + overflow-y: auto; + min-height: 15em; + max-height: 35em; +} + +.hide-item {} + +.dialog-skills>pre { + padding: 0px; + margin: 0px; + white-space: pre-wrap; +} + +.dialog-skills>.skill-item { + line-height: 2em; + padding-left: 1.5em; + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + white-space: nowrap; + overflow-x: auto; + margin-bottom: 0.5em; + background-color: #111; + cursor: pointer; +} + + +.hide-item>.skill-item { + display: none; +} + +.dialog-skills>.dialog-books>.skill-item { + display: none; +} + +.dialog-skills>.skill-item>.skill-level { + float: right; + margin-right: 0.625em; +} + +.dialog-skills>.skill-item>.enable-flag { + display: none; + color: var(--border-color); + line-height: 2em; +} + +.dialog-skills>.enable { + padding-left: 0px; +} + +.dialog-skills>.enable>.enable-flag { + display: inline-block; + padding-left: 0.25em; + padding-right: 0.25em; +} + +.dialog-skills>.skill-item>.enable_skill { + margin-left: 0.5em; +} + +.dialog-skills>.enable>.item-commands { + padding-left: 1em; +} + +.dialog-skills>.book-item { + line-height: 2em; + padding-left: 1.5em; + border-radius: 4px; + border-left-width: 2px; + border-left-style: solid; + white-space: nowrap; + overflow-x: auto; + margin-bottom: 0.5em; + background-color: #111; + cursor: pointer; + display: flex; + flex-direction: row; +} + +.dialog-skills>.book-item>.book-name { + flex: 1; + text-overflow: ellipsis; + white-space: nowrap; + color: var(--border-color); + overflow: hidden; +} + +.dialog-skills>.book-item>.book-action { + flex: 0; + background-color: #222; + padding-left: 1em; + padding-right: 1em; +} + +`; diff --git a/src/dialog/stats.js b/src/dialog/stats.js new file mode 100644 index 0000000..894f972 --- /dev/null +++ b/src/dialog/stats.js @@ -0,0 +1,354 @@ + + +const STATS_SILDER1 = [["总榜", ''], ["武当派", 'wudang'], ["少林派", 'shaolin'], ["华山派", 'huashan'], +["峨眉派", 'emei'], ["逍遥派", 'xiaoyao'], ["丐帮", 'gaibang'], ["杀手楼", 'shashou'], +["无门无派", 'none']]; +const STATS_SILDER2 = [ + ["武器", ""], ["衣服", "cloth"], ["鞋", "shoes"], ["头部", "head"], + ["披风", "cape"], ["戒指", "ring"], ["项链", "necklace"], ["饰品", "jewels"], + ["护腕", "wrist"], ["腰带", "waist"], ["暗器", "throwing"] +]; +export default { + footers: [{ cmd: "score", name: "综合榜", selected_silder: "", silder: STATS_SILDER1 }, + { cmd: "top", name: "高手榜", selected_silder: "", silder: STATS_SILDER1 }, + { cmd: "weapon", name: "兵器谱", selected_silder: "", silder: STATS_SILDER2 }, + { cmd: "exp", name: "经验榜", selected_silder: "", silder: STATS_SILDER1 }, + { cmd: "mp", name: "内力榜", selected_silder: "", silder: STATS_SILDER1 }, + { cmd: "money", name: "富豪榜", selected_silder: "", silder: STATS_SILDER1 } + ], + selectedItem: 0, + init: function () { + Dialog.injectStyle(stats_css); + }, + close: function () { + this.element.remove(); + this.isShow = false; + }, onData: function (data) { + if (data.close) return Dialog.hide(); + if (data.tops) { + if (data.top) { + this.show_desc("你目前在第" + data.top + "名,积分" + data.sc); + } else { + this.show_desc("你目前没有上榜,积分:" + data.sc); + } + + return this.create_tops(data.tops, data); + } + if (data.weapons) { + this.show_desc(""); + return this.create_weapons(data.weapons); + } + if (data.scores) { + this.show_desc("你目前的评分:" + data.score); + return this.create_scores(data.scores); + } + if (data.items) { + this.create_other(data.items, data.st); + let dt = new Date(data.time); + data.fam = data.fam ?? ""; + this["last_" + data.st + data.fam] = { + items: data.items, + time: data.time + 60000, + score: data.score + }; + if (data.score) + this.show_desc("你目前的评分:" + data.score); + else + this.show_desc("上次更新:" + dt.getHours() + ":" + dt.getMinutes()); + } + + }, create_other: function (items, type) { + var html = []; + for (var i = 0; i < 20; i++) { + html.push("
    "); + html.push(this.top_names[i]); + html.push("、"); + html.push(""); + let role = items[i] ?? ["无", 0]; + html.push(role[0]); + html.push(""); + html.push(""); + html.push(role[1]); + html.push(""); + html.push("
    ") + } + this.container.html(html.join("")); + }, + silderClick: function () { + let elem = $(this); + let type = elem.attr("stype"); + let item = Dialog.stats.selectedItem; + if (item.selected_silder === type) return; + item.selected_silder = type; + elem.parent().find('.select').removeClass('select'); + elem.addClass('select'); + Dialog.stats.load_stats(); + }, + create_silder: function (items) { + let str = []; + items = items || []; + let tab = this.selectedItem; + for (let item of items) { + str.push('
    ', item[0], "
    "); + } + this.left_silder.html(str.join("")); + }, + top_names: ["一 ", "二 ", "三 ", "四 ", "五 ", + "六 ", "七 ", "八 ", "九 ", "十 ", + "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十"], + create_scores: function (items, data) { + var html = []; + for (var i = 0; i < 20; i++) { + html.push("
    "); + html.push(this.top_names[i]); + html.push("、"); + html.push(""); + let role = items[i] ?? ["无", ""]; + html.push(role[0]); + html.push(""); + html.push(""); + html.push(role[1]); + html.push(""); + html.push("
    ") + } + this.container.html(html.join("")); + + }, + fam_names: { + emei: "峨眉第", wudang: "武当第", huashan: "华山第", + xiaoyao: "逍遥第", gaibang: "丐帮第", shaolin: "少林第", shashou: "杀手第", + none: "散修第" + }, + create_tops: function (items, data) { + var html = []; + for (var i = 0; i < items.length; i++) { + html.push("
    "); + html.push(data.fam ? this.fam_names[data.fam] : "天下第"); + html.push(this.top_names[i]); + html.push(""); + html.push(""); + html.push(items[i][0]); + html.push(""); + html.push(""); + html.push(items[i][1]); + html.push(""); + html.push("
    ") + } + this.container.html(html.join("")); + this.top = data.top; + }, create_weapons: function (items) { + var html = []; + for (var i = 0; i < 10; i++) { + html.push("
    "); + let role = items[i] ?? ["无", ""]; + html.push(this.top_names[i]); + html.push("、"); + html.push(""); + html.push(role[0]); + html.push(""); + html.push(""); + html.push(role[1]); + html.push(""); + html.push("
    ") + } + this.container.html(html.join("")); + }, + show: function () { + if (!this.selectedItem) this.selectedItem = this.footers[0]; + this.load_stats(); + if (!this.element) { + + this.element = $("
    "); + + this.container = $("
    ").appendTo(this.element); + this.left_silder = this.element.find('.stats-container-left'); + this.create_silder(this.selectedItem.silder); + } + if (this.isShow) return; + this.create_footer(); + Dialog.icon("stats"); + Dialog.title(this.selectedItem.name); + + Dialog.contentElement.html(this.element); + this.element.on("click", ".top-item", this.itemClick); + this.left_silder.on("click", ".stats-silder ", this.silderClick); + this.isShow = true; + }, load_stats: function () { + let type = this.selectedItem.cmd; + let fam = this.selectedItem.selected_silder; + //if (this.ban_silder[fam]) fam = ""; + let data = this["last_" + type + fam]; + if (data && data.time > Date.now()) { + let dt = new Date(data.time); + let str = ""; + if (data.score) str = "你目前的评分:" + data.score; + else str = "上次更新:" + dt.getHours() + ":" + dt.getMinutes(); + this.show_desc(str); + return this.create_other(data.items, type); + } + let str = "stats " + type; + if (fam) str = str + " " + fam; + SendCommand(str); + }, create_footer: function () { + var html = []; + for (var i = 0; i < this.footers.length; i++) { + var foot = this.footers[i]; + html.push("" + + foot.name + ""); + } + html.push(""); + Dialog.footer(html.join("")); + }, show_desc: function (msg) { + Dialog.footerElement.find(".stats-span").html(msg); + }, + footerChanged: function (index) { + var item = this.footers[index]; + if (item == this.selectedItem) return; + this.selectedItem = item; + Dialog.title(this.selectedItem.name); + this.create_silder(this.selectedItem.silder); + this.load_stats(); + + + }, + itemClick: function () { + var elem = $(this); + var index = parseInt(elem.attr("top")); + var type = Dialog.stats.selectedItem.cmd; + + var html = ["
    "]; + var stype = Dialog.stats.selectedItem.selected_silder; + if (type === 'top') { + html.push('查看'); + if (!Dialog.stats.top || index < Dialog.stats.top) { + html.push('挑战'); + } + html.push('查看规则和奖励'); + } else { + html.push('查看'); + html.push('查看奖励'); + } + html.push("
    "); + Dialog.stats.element.find(".item-commands").remove(); + $(html.join("")).insertAfter(elem); + } +}; + +const stats_css = ` + +.stats-container { + display: flex; + flex-direction: row; + height: 25em; + margin-top: 0.5em; +} + +.stats-container>.stats-container-left { + overflow-y: auto; +} + +.stats-container-left>.stats-silder { + white-space: nowrap; + line-height: 2em; + width: 5em; + text-align: center; + background-color: #111; + border-radius: 4px; + margin-bottom: 0.5em; + margin-right: 0.5em; + margin-left: 0.5em; + text-align: center; + cursor: pointer; +} + +.stats-container-left>.select { + background-color: #222; + color: #00ff00; + border-left-width: 2px; + border-left-style: solid; + border-left-color: #00ff00; +} + +.dialog-stats { + flex: 1; + overflow: auto; +} + +.dialog-stats>.top-item { + white-space: nowrap; + line-height: 2em; + padding-left: .5em; + border-radius: 4px; + white-space: nowrap; + overflow-x: auto; + margin-bottom: 0.5em; + background-color: #111; + cursor: pointer; + color: inherit; +} + +.dialog-stats>.top-item>.top-title { + display: inline-block; + font-weight: bold; + height: 1.875em; + line-height: 1.875em; + padding-left: 1em; + margin-right: 1em; +} + +.dialog-stats>.top-item>.top-sc { + float: right; + margin-right: 1em; + line-height: 1.875em; + font-weight: bold; + font-style: italic; +} + + + +.dialog-stats>.top1>.top-sc { + color: #FFA500; +} + +.dialog-stats>.top2>.top-sc { + color: #912CEE; +} + +.dialog-stats>.top3>.top-sc { + color: #FFD700; +} + +.dialog-stats>.top-item>.top-name { + height: 1.875em; + line-height: 1.875em; +} + +.dialog-stats>.top-item>.item-commands { + padding-left: 3.125em; +} + +.stats-span { + float: right; + padding-right: 10px; + color: #C0C0C0; + line-height: 2.5em; +} +`; diff --git a/src/dialog/tasks.js b/src/dialog/tasks.js new file mode 100644 index 0000000..d052f2b --- /dev/null +++ b/src/dialog/tasks.js @@ -0,0 +1,169 @@ + + +const task_css = ` + +.dialog-tasks { + max-height: 32em; + margin-bottom: 0.5em; + margin-top: 0.5em; +} + +.dialog-tasks>.task-item { + border-radius: 6px; + background-color: #111111; + border-left-width: 4px; + border-left-style: solid; + position: relative; + margin-top: 0.5em; + padding-left: 0.5em; +} + +.dialog-tasks>.none { + border-left-color: #808080 +} + + + +.dialog-tasks>.finish { + border-left-color: #00ff00 +} + +.dialog-tasks>.over { + border-left-color: #008080 +} + +.dialog-tasks>.none>.task-btn { + border-left-color: #808080; + color: #808080; +} + +.dialog-tasks>.finish>.task-btn { + border-left-color: #00ff00; + color: #00ff00; + background-color: #00ff0033; +} + +.dialog-tasks>.over>.task-btn { + border-left-color: #008080; + color: #008080; +} + +.task-item h3 { + margin: 0px; + padding-top: 0.5em; +} + +.task-item .task-desc { + + margin: 0; + padding-top: 0.5em; + padding-bottom: 0.5em; + white-space: pre-wrap; +} + +.task-item>.task-btn { + width: 4.5em; + display: inline-block; + border-left: 1px solid #343434; + text-align: center; + font-weight: bold; + background-color: transparent; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; +} + +.task-item>.task-btn:hover { + background-color: #222; +} + +.dialog-tasks>.task-item>.start { + color: gray; +} + +.dialog-tasks>.task-item>.finish { + color: #00ff00; +} + +.dialog-tasks>.task-item>.over { + color: #ebebeb; +} +`; + +export default { + init: function () { + + Dialog.injectStyle(task_css); + }, + close: function () { + this.element.remove(); + this.isShow = false; + }, update_item: function (data) { + for (var i = 0; i < this.items.length; i++) { + if (this.items[i].id == data.id) { + if (data.state) { + this.items[i].title = data.title; + this.items[i].state = data.state; + this.items[i].desc = data.desc; + } else { + this.items.splice(i, 1); + } + + break; + } + } + this.create_items(); + }, onData: function (data) { + + if (data.id) return this.update_item(data); + Dialog.title("任务列表"); + Dialog.icon("exclamation-sign"); + this.items = data.items; + this.create_items(); + }, + show: function () { + if (!this.element) + this.element = $("
    "); + SendCommand("tasks"); + if (this.isShow) return; + this.element.appendTo(Dialog.contentElement); + + this.isShow = true; + }, + status_css: ['', 'none', 'finish', 'over'], + create_items: function () { + var str = []; + var has_fin = false; + for (var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + str.push("

    "); + str.push(item.title) + str.push("

    "); + str.push("
    ");
    +            str.push(item.desc);
    +
    +            //str.push('');
    +            str.push("
    "); + str.push("进行中"); + } else if (item.state == 2) { + str.push(" cmd=\"task "); + str.push(item.id); + str.push(' fin"'); + has_fin = true; + str.push(">可领取"); + } else if (item.state == 3) { + str.push(">已完成"); + } + str.push(""); + str.push("
    "); + } + this.element.html(str.join("")); + + Dialog.footer(""); + } +}; diff --git a/src/dialog/team.js b/src/dialog/team.js new file mode 100644 index 0000000..f94846a --- /dev/null +++ b/src/dialog/team.js @@ -0,0 +1,75 @@ + + +export default { + init: function () { }, + createElement: function () { + return $('
    '); + }, + inner_show: function () { + SendCommand("team"); + this.isShow = true; + Dialog.title("队伍"); + this.element.on("click", ".team-item", this.clickItem); + Dialog.icon("list"); + }, + items: [], + onData: function (data) { + if (data.items) { + this.items = data.items; + if (data.items.length) this.isCap = data.items[0].id == Process.player; + else this.isCap = 0; + } + if (data.dismiss) { + this.items.length = 0; + this.isCap = false; + } + if (data.remove) { + if (!this.items.length) return; + for (var i = 0; i < this.items.length; i++) { + if (this.items[i].id == data.remove) { + this.items.splice(i, 1); + break; + } + } + } + this.createItems(); + }, + inner_close: function () { + this.element.remove(); + this.isShow = false; + }, createItems: function () { + if (!this.element) return; + var str = []; + for (var i = 0; i < this.items.length; i++) { + var msg = this.items[i]; + str.push("
    "); + str.push(""); + str.push(i > 0 ? "" : ""); + str.push(""); + str.push(""); + str.push(msg.name); + str.push(""); + str.push("
    "); + } + if (!str.length) str.push('
    你还没有加入任何队伍。
    '); + this.element.html(str.join("")); + }, clickItem: function () { + var elem = $(this); + var item = Dialog.team.items[elem.attr("index")]; + if (!item) return; + var html = ["
    "]; + html.push('查看'); + var isCap = Dialog.team.items[0].id == Process.player; + if (isCap && item.id != Process.player) { + html.push('移出队伍'); + } else if (item.id == Process.player) { + html.push('退出队伍'); + } + if (isCap && item.id == Process.player) { + html.push('更改分配方式'); + } + html.push("
    "); + Dialog.team.element.find(".item-commands").remove(); + $(html.join("")).appendTo(elem); + } +}; diff --git a/src/dialog/trade.js b/src/dialog/trade.js new file mode 100644 index 0000000..b8d3430 --- /dev/null +++ b/src/dialog/trade.js @@ -0,0 +1,148 @@ + +import Util from '../utils/util.js'; + +export default { + init: function () { + Dialog.pack.init(); + }, + hide: function () { + this.element.remove(); + this.isShow = false; + }, + close: function () { + this.hide(); + }, onData: function (data) { + if (!this.isShow) { + Dialog.show("trade"); + } + Dialog.title("和" + data.name + "交易中"); + var items = Dialog.pack.items; + this.trade_target = data.target; + this.trade_list.length = 0; + if (!Dialog.pack.items) SendCommand("pack"); + else this.update_pack(); + Dialog.pack.isShow = false; + this.create_items(this.leftElement.empty(), this.trade_list, this.max_count); + }, + update_pack: function (data) { + this.create_items(this.rightElement.empty(), Dialog.pack.items, Dialog.pack.max_count); + }, + max_count: 10, + trade_list: [], + show: function (data) { + if (this.isShow) return; + Dialog.init(); + Dialog.curItem = "trade"; + if (!this.element) { + this.element = $('
    '); + this.leftElement = $(this.element.children()[0]); + this.rightElement = $(this.element.children()[1]); + } + this.leftElement.on("click", ".obj-item", this.left_click); + this.rightElement.on("click", ".obj-item", this.right_click); + this.element.appendTo(Dialog.contentElement.empty()); + this.create_footer(); + this.isShow = true; + + }, create_footer: function () { + var html = ["
    "]; + html.push("确定"); + html.push("取消"); + html.push('
    '); + Dialog.footer(html.join("")); + }, confirm: function (cmd) { + if (cmd === 'ok' && this.trade_list.length) { + for (var i = 0; i < this.trade_list.length; i++) { + SendCommand("give " + this.trade_target + + " " + this.trade_list[i].count + " " + this.trade_list[i].id); + } + } + Dialog.hide(); + + }, + create_items: function (elem, items, max) { + var html = []; + items = Dialog.pack.sort_items(items); + for (var i = 0; i < max; i++) { + var item = items[i]; + html.push('
    "); + html.push(item.name); + if (item.count > 1) { + html.push(""); + html.push(item.count); + html.push(item.unit); + html.push(''); + } + } else { + html.push('">'); + } + html.push('
    '); + } + elem.html(html.join("")); + }, left_click: function () { + var elem = $(this); + var obj = elem.attr("oindex"); + if (!obj) return; + var item = null; + for (var i = 0; i < Dialog.trade.trade_list.length; i++) { + if (Dialog.trade.trade_list[i].id == obj) { + item = Dialog.trade.trade_list[i]; + break; + } + } + if (!item) return; + Dialog.trade.cancle_trade(item); + return false; + }, enable_item: function (obj, isenable) { + var elem = this.rightElement.find(".obj-item[oindex='" + obj.id + "']"); + if (!elem.length) return; + if (isenable) { + elem.removeClass("disabled"); + } else { + elem.addClass("disabled"); + } + } + , + right_click: function () { + var elem = $(this); + if (elem.is(".disabled")) return; + var obj = elem.attr("oindex"); + if (!obj) return; + + var item = Dialog.pack.get_item(obj); + + if (!item) return; + if (item.count > 1) { + Confirm.Show_trade_add(item); + } else { + Dialog.trade.add_trade(item); + } + return false; + }, add_trade: function (obj) { + for (var i = 0; i < this.trade_list.length; i++) { + if (obj.id == this.trade_list[i].id) { + this.trade_list[i].count += obj.count; + return this.create_items(); + } + } + this.trade_list.push(obj); + this.create_items(this.leftElement.empty(), this.trade_list, this.max_count); + this.enable_item(obj, false); + }, + cancle_trade: function (obj) { + for (var i = 0; i < this.trade_list.length; i++) { + if (obj.id == this.trade_list[i].id) { + this.trade_list.splice(i, 1); + i--; + } + } + this.create_items(this.leftElement.empty(), this.trade_list, this.max_count); + this.enable_item(obj, true); + } +} diff --git a/src/fonts/fa-solid-900.woff2 b/src/fonts/fa-solid-900.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..16721020f0a7172e5d8a8a8484192a7a8fbd67cb GIT binary patch literal 158220 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

    J5RPh~>9IQEDv|8fkW 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

    aj6P+xsdz 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 literal 0 HcmV?d00001 diff --git a/src/fonts/glyphicons-halflings-regular.eot b/src/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..b93a4953fff68df523aa7656497ee339d6026d64 GIT binary patch literal 20127 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 G`u_lkUM?>H literal 0 HcmV?d00001 diff --git a/src/fonts/glyphicons-halflings-regular.woff2 b/src/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..64539b54c3751a6d9adb44c8e3a45ba5a73b77f0 GIT binary patch literal 18028 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 literal 0 HcmV?d00001 diff --git a/src/game/main.js b/src/game/main.js new file mode 100644 index 0000000..332db63 --- /dev/null +++ b/src/game/main.js @@ -0,0 +1,275 @@ + +import { Page } from '../base/page.js'; +import Combat from '../combat.js'; +import MAP from '../map.js'; +import * as ToolAction from './tool.js'; +import Dialog from '../dialog/base.js'; +import { Confirm } from '../confirm.js'; +import { Warn } from '../confirm.js'; +import Process from '../process.js'; +import Setting from '../setting.js'; +import SCRIPT from '../script.js'; + +let isShowChat = false; + +class GameMainPage extends Page { + constructor() { + super(); + this.template = ` +

    +`; + + } + + on_mount() { + $(".container").on("click", ContainerCommand); + $(".channel-box").on("click", "span", ChannelChanged); + + $(".combat-commands").on("click", ".pfm-item", Combat.Perform).on('wheel', Combat.Scroll); + $(".room-commands").on('wheel', Combat.Scroll); + $(".sender-box").on("keyup", OnSendBoxKeyDown); + + $(".room_items").on("click", ".room-item", Process.selectItem); + $(".bottom-bar").on("click", '.tool-item,.state-bar,.item-command', MenuClick); + $(".map-panel").on("click", open_map); + $(".sender-btn").on("click", SendChatMessage); + + $(".room_exits").on("pointerdown", + Process.before_click_exits).on("pointerup", Process.click_exits); + $(".room-title>.map-icon").on("click", MAP.LoadMap.bind(MAP)); + } +} + +let last_click = 0; +function open_map() { + last_click = last_click || 0; + if (Date.now() - last_click > 500) { + last_click = Date.now(); + return; + } + Dialog.show("map"); +} +function MenuClick(item) { + var cmd = $(this).attr("command"); + if (!cmd) { + cmd = $(this).attr("cmd"); + if (cmd) SendCommand(cmd); + return false; + } + return HandlerMenuCommand(cmd); +} +function HandlerMenuCommand(cmd) { + switch (cmd) { + case "showtool": + ToolAction.ShowTools(); + break; + case "showchat": + return ShowChat(); + case "showcombat": + + return Combat.Show(); + case "stopstate": + if (Dialog.extend.is_record) + return Dialog.extend.stop_record(); + SendCommand("state stop"); + break; + case "stateinfo": + SendCommand("state info"); + break; + default: + Dialog.show(cmd); + break; + } + return false; +} +function ShowChat() { + var elem = $(".chat-panel").toggleClass("hide"); + if (!elem.is(".hide")) { + isShowChat = true; + elem.find("input").val("").focus(); + } else { + isShowChat = false; + } + return false; +} +function OnSendBoxKeyDown(e) { + if (e.keyCode == 13) { + SendChatMessage(); + } +} +function SendChatMessage() { + var value = $(".sender-box").val(); + if (!value) return; + if (value.length > 100) return ReceiveMessage("你输入的内容太多了。"); + var channel = $(".channel-box").attr("channel"); + $(".sender-box").val("").focus(); + SendCommand(channel + " " + value + ""); + +} + +function ChannelChanged() { + var elem = $(this); + var ch = elem.attr("channel"); + if (ch == "emote") { + return ShowEmotePanel(); + } + + if (elem.is(".selected")) return; + var parent = elem.parent(); + parent.children().removeClass("selected"); + elem.addClass("selected"); + parent.attr("channel", ch); + $(".sender-box").focus(); + return false; +} +function ShowEmotePanel() { + var panel = $(".channel-emotes"); + if (panel.is(".hide")) { + panel.removeClass("hide"); + if (!Process.emtoes) { + SendCommand("emote"); + Process.emtoes = []; + $(".sender-box").blur(); + panel.on("click", "span", function () { + var text = $(this).html(); + $(".sender-box").val("*" + text).focus(); + $(".channel-emotes").addClass("hide"); + }); + } + } else { + $(".channel-emotes").addClass("hide"); + } +} +function ContainerCommand(e) { + var elem = $(e.target); + var cmd = elem.attr("cmd"); + if (!cmd) cmd = elem.parent().attr("cmd"); + if (cmd) { + let char = cmd[0]; + if (char == "_") { + var str = cmd.split(" "); + switch (str[0]) { + case "_confirm": + Confirm.Process(str); + break; + case "_setting": + Setting.save(str[1], str[2]); + break; + case "_trade": + Dialog.trade.confirm(str[1]); + break; + case "_close": + Warn.Close(elem); + break; + case "_hide": + break; + case "_closed": + Dialog.hide(); + case "_party": + Dialog.party.command(str[1]); + break; + + } + } else if (char === '#') { + SCRIPT.run(cmd); + } + else { + SendCommand(cmd); + if (!elem.closest('.dialog-fb').length && + elem.closest(".dialog-content").length > 0) { + elem.closest(".item-commands").remove(); + } + } + return false; + } else { + if (isShowChat) { + if (!elem.closest(".chat-panel").length) { + $(".chat-panel").addClass("hide"); + isShowChat = false; + } + } + } + Confirm.Close(); +} + +export default GameMainPage; +window.HandlerMenuCommand = HandlerMenuCommand; diff --git a/src/game/tool.js b/src/game/tool.js new file mode 100644 index 0000000..03e9a4f --- /dev/null +++ b/src/game/tool.js @@ -0,0 +1,89 @@ + + +let tools = null; +let hideTool = null; +let bottom_tools = null; +let ToolState = 0; +let ToolOpacity = 0; +let ToolSpeed = 0; + +export function InitTools() { + if (!tools) { + tools = $(".right-bar>.tool-item"); + hideTool = $(".br-tool"); + bottom_tools = $('.bottom-bar>.tool-item'); + } +} + +export function ShowTools() { + InitTools(); + if (ToolState == 1) return; + if (ToolState == 0) {//显示 + for (var i = 0; i < tools.length; i++) { + tools[i].style.display = ""; + tools[i].style.opacity = 0; + } + ToolSpeed = 200; + ToolOpacity = 0; + $(hideTool).removeClass("hide-tool"); + } else {//隐藏 + ToolOpacity = 100; + ToolSpeed = 100; + $(hideTool).addClass("hide-tool"); + } + window.setTimeout(ShowToolsAnimate.bind(null, ToolState), 100); + ToolState = 1; +} + +export function ShowToolsAnimate(type) { + if (type == 0) { + ToolOpacity = ToolOpacity + ToolSpeed; + var to = ToolOpacity; + for (var i = tools.length - 1; i >= 0; i--) { + if (to < 0) tools[i].style.opacity = 0; + else if (to > 100) tools[i].style.opacity = 1; + else tools[i].style.opacity = to / 100; + to -= 20; + if (to < 0) break; + } + ToolOpacity -= 30; + if (to < 100) { + window.setTimeout(ShowToolsAnimate.bind(null, type), 100); + } else { + ToolState = 2; + } + } else { + ToolOpacity = ToolOpacity - ToolSpeed; + var to = ToolOpacity; + for (var i = 0; i < tools.length; i++) { + if (to < 0) tools[i].style.opacity = 0; + else if (to > 100) tools[i].style.opacity = 1; + else tools[i].style.opacity = to / 100 * 1; + to += 20; + if (to >= 100) break; + } + ToolOpacity -= 20; + if (to >= 0) { + window.setTimeout(ShowToolsAnimate.bind(null, type), 100); + } else { + ToolState = 0; + for (var i = 0; i < tools.length; i++) { + tools[i].style.display = "none"; + } + } + } +} + +export function showFlag(cmd, val) { + InitTools(); + if (val < 0) val = 0; + else if (val > 99) val = 99; + let tool = tools.filter("[command='" + cmd + "']"); + if (!tool.length) + tool = bottom_tools.filter("[command='" + cmd + "']"); + if (val) { + tool.find(".tag").removeClass("hide"); + } else { + tool.find(".tag").addClass("hide"); + } +} diff --git a/src/img/loader.gif b/src/img/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..e656a87986a795342bcef10ac624fe77f446ee94 GIT binary patch literal 1024 zcmZ?wbhEHblw*)%c*?-Y00J`^(q@7gLyu7W&+X?L671|4;A*62zzp(_;!hS%E(UuB z9guH8-gISiIWWJ#Lr1Fr#F8RU7K`}-jSZe_qt<(7lytqV+W%m~kL|44TZ7);oGG{a z{)Zhke&^TSzVTH!|LW$QmE{dt)y<{t9i2%?26HiRG4KJgE1T+p`2r3s9DPg=H=J-$ zn;D?|NnF)xW$0^@>a$t>aW4g>_iD`!Rzx@nq*D;AQyZeQzG=yWAKF%or!qdj?9o~t zk}c%jnzi$4{`M83J)NlrKdVdRmO7#87Xj-xg6QwJZwzYCvFbg!^vm}euk~lN0y{#3 zwjO!+Df(&I$*7G&GGUA7rsZtz=rL|3R{Ff&nsroYtNXfZ(o?lg zqI-Y`>;MIz0~iD(SPvzBJn=_xX226;t=OQ|;mfC5oh@7FnH$W3>S~bBUD>1#%nxu7 z;b=elME|6TS?6i>5UHtAbI&JV)nGv==Kv~&*r5nk&cJXev9R)w?tC|uDL3YbtqxxE zHDjsQ<`XK$f0z-v*nqm=kpi@Yp^t&cNMQi#ga<0fdHwbcLZk;OGtd}#+=7g$Z%_fn z?bHiPH%s)IEpN*DWOY?*r@!uuSF8z}pBi2~T_U&8oqz|3iWEeE0V5?qfkA>1ccfTz F0RaE78AJd8 literal 0 HcmV?d00001 diff --git a/src/img/thk.png b/src/img/thk.png new file mode 100644 index 0000000000000000000000000000000000000000..0f437b0217d575b33b0b65c69c3891fb8e784fbc GIT binary patch literal 66145 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­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

    @Ao>_xJ|9M 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�lN+8BZIdS0t^Nw#rg?>hu^g5pls_Na?8! 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 S)p!H}e+sgyGBr}>q5lI+6+^@T literal 0 HcmV?d00001 diff --git a/src/img/timg.gif b/src/img/timg.gif new file mode 100644 index 0000000000000000000000000000000000000000..46d41edc5a10416822f5ac12c51593c7839a4d9f GIT binary patch literal 46803 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

    +`; + } + + bind() { + Client.hide2show("#bind_panel"); + API.GetPhone(function (x) { + $("#phone_valid").val(""); + $("#phone_pwd").val(""); + if (x.code !== 1) + return $(".input-error").html(x.result); + $(".input-error").remove(); + let phone = x.result; + if (phone) { + $("#phone_no").prop("disabled", true).val(phone); + $('#phone_valid').parent().show().prev().show(); + $("#phone_no").prev().html("你已绑定手机,再次验证会取消绑定"); + $("#phone_no").parent().next().find('span:last()').html("解除绑定"); + } else { + $("#phone_no").prop("disabled", false).val(""); + $("#phone_no").prev().html("你要绑定的手机(不验证,目前仅作为二级密码验证使用)"); + $('#phone_valid').parent().hide().prev().hide(); + $("#phone_no").parent().next().find('span:last()').html("绑定"); + } + }); + } + + check() { + var phone = $("#phone_no"); + var phone_no = "", valid_no = ""; + if (!phone.is(":disabled")) { + phone_no = phone.val(); + if (!phone_no) return Client.showInputError("#phone_no", "请输入你的帐号绑定的手机号码"); + if (!/^1\d{10}$/.test(phone_no)) return Client.showInputError("#phone_no", "手机号码格式错误"); + } else { + valid_no = $("#phone_valid").val(); + if (!valid_no) return Client.showInputError($("#phone_valid").parent(), "请输入你接收到的六位验证码"); + if (!/^\d{4}$/.test(valid_no)) return Client.showInputError($("#phone_valid").parent(), "请输入六位数字的验证码"); + } + var pwd2 = $("#phone_pwd").val(); + if (!pwd2) return Client.showInputError("#phone_pwd", "请重复输入你的新密码"); + if (pwd2.length < 6 || pwd2.length > 20) return Client.showInputError("#phone_pwd", "密码长度在6到20之间"); + + API.BindPhone(valid_no, phone_no, pwd2, function (x) { + if (x.code < 1) { + Client.showInputError($("#phone_valid").parent(), x.result ?? "绑定失败"); + Client.hide2show("#bind_panel"); + } else { + Client.hide2show("#role_panel"); + } + }); + } +} + +export default BindPhonePage; diff --git a/src/login/change-pwd.js b/src/login/change-pwd.js new file mode 100644 index 0000000..c45172f --- /dev/null +++ b/src/login/change-pwd.js @@ -0,0 +1,82 @@ + +import { Page } from '../base/page.js'; +import API from '../api.js'; +import * as Client from '../client.js'; + +class ChangePwdPage extends Page { + constructor() { + super(); + this.template = ` + +`; + + } + + open() { + Client.hide2show("#pwd_panel"); + API.GetPhone(function (x) { + if (x.code !== 1) return Client.showInputError("#update_pwd1", "获取绑定的手机号失败"); + + if (x.result) { + $("#pwd_phone").prop("disabled", true).val(x.result); + $("#pwd_bind").show(); + } else { + $("#pwd_phone").prop("disabled", false).val(""); + $("#pwd_bind").hide(); + } + }); + } + + update() { + $('#pwd_panel').find('.input-error').remove(); + var pwd1 = $("#update_pwd1").val(); + var pwd2 = $("#update_pwd2").val(); + var pwd3 = $("#update_pwd3").val(); + if (pwd1.length < 6 || pwd1.length > 20) return Client.showInputError("#update_pwd1", "密码长度在6到20之间"); + if (pwd2.length < 6 || pwd2.length > 20) return Client.showInputError("#update_pwd2", "密码长度在6到20之间"); + if (pwd3 != pwd2) return Client.showInputError("#update_pwd3", "两次密码输入不一致"); + var valid_no; + if ($("#pwd_bind").is(":visible")) { + valid_no = $("#pwd_no").val(); + if (!valid_no) return Client.showInputError($("#pwd_no").parent(), "请输入你绑定的手机尾号"); + if (!/^\d{4}$/.test(valid_no)) return Client.showInputError($("#pwd_no").parent(), "请输入你绑定的手机尾号"); + } + + Client.showLoader("正在修改密码", "#pwd_panel"); + API.ChangePassword(pwd1, pwd2, valid_no, function (x) { + if (x.code) { + Client.hide2show($("#slist_panel")); + } else { + Client.showInputError("#update_pwd1", x.result || '修改失败'); + Client.hide2show("#pwd_panel"); + } + }); + } +} + +export default ChangePwdPage; diff --git a/src/login/create-role.js b/src/login/create-role.js new file mode 100644 index 0000000..edbc984 --- /dev/null +++ b/src/login/create-role.js @@ -0,0 +1,89 @@ + +import { Page } from '../base/page.js'; +import API from '../api.js'; +import * as Client from '../client.js'; +import { RefreshInput } from './roles.js'; + +window.RefreshInput = RefreshInput; + +class CreateRolePage extends Page { + constructor() { + super(); + this.template = ` + + +
    +
      +
    • 创建你的角色卡
    • +
    • +
      +
      +

      你的称呼,2-5个中文字符

      +
      +
      + +
      +

      你的性别

      +
      + + +
      +
      +

      你的先天属性

      +
      + + + + + + + + + + + + + +
      臂力:根骨:
      身法:悟性:
      +
      需要在15-30之间,并且总和等于80
      +
    • +
    • 创建
    • +
    • 返回
    • +
    +
    +`; + } + + create() { + var player = {}; + player.name = $("#reg_name").val(); + player.gender = $("#gender_0").is(":checked") ? 1 : 2; + player.str = parseInt($("#reg_str").val()); + player.con = parseInt($("#reg_con").val()); + player.dex = parseInt($("#reg_dex").val()); + player.int = parseInt($("#reg_int").val()); + + if (!/^[\u4E00-\u9FA5]{2,5}$/.test(player.name)) return Client.showInputError("#reg_name", "名称格式错误,只能使用2-5位中文字符"); + if (player.str < 15 || player.str > 30) return Client.showInputError("#reg_name", "臂力需要在15-30之间"); + if (player.con < 15 || player.con > 30) return Client.showInputError("#reg_name", "根骨需要在15-30之间"); + if (player.dex < 15 || player.dex > 30) return Client.showInputError("#reg_name", "身法需要在15-30之间"); + if (player.int < 15 || player.int > 30) return Client.showInputError("#reg_name", "悟性需要在15-30之间"); + if (player.str + player.con + player.dex + player.int != 80) return Client.showInputError("#reg_name", "先天属性需要在15-30之间,并且总和等于80"); + Client.showLoader("正在创建角色", "#addrole_panel"); + SendCommand("createrole " + player.name + " " + player.gender + " " + player.str + " " + player.con + " " + player.dex + " " + player.int); + } +} + +export default CreateRolePage; diff --git a/src/login/index.js b/src/login/index.js new file mode 100644 index 0000000..01c80a8 --- /dev/null +++ b/src/login/index.js @@ -0,0 +1,139 @@ + +import { Page } from '../base/page.js'; +import Server from './server.js'; +import Util from '../utils/util.js'; +import Regist from './regist.js'; +import Roles from './roles.js'; +import ResetPwd from './reset-pwd.js'; +import ChangePwd from './change-pwd.js'; +import BindPhone from './bind-phone.js'; +import CreateRole from './create-role.js'; +import News from './news.js'; +import LoginIn from './login-in.js'; +import * as Client from '../client.js'; + +const server = new Server(); +const loginIn = new LoginIn(); +const regist = new Regist(); +const roles = new Roles(); +const resetPwd = new ResetPwd(); +const changePwd = new ChangePwd(); +const bindPhone = new BindPhone(); +const createRole = new CreateRole(); +const news = new News(); 4 + +function showNews() { + let nid = $(this).attr('nid'); + Client.hide2show($("#new_panel ")); + $("#news_frame").attr("src", "/news/" + nid + ".html"); +} + +class LoginPage extends Page { + constructor() { + super(); + this.template = ` + + ${loginIn.template} + + ${server.template} + ${bindPhone.template} + + ${changePwd.template} + ${resetPwd.template} + + ${regist.template} + ${roles.template} + ${news.template} + ${createRole.template} +
    ©2017 武神传说
    +

    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 W>7oNq^af6W@UfVIxYMJ$-v0+ryumU6 literal 0 HcmV?d00001 diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..ebc5f71 --- /dev/null +++ b/src/index.html @@ -0,0 +1,15 @@ + + + + + + MUD游戏 + + + + + + + + \ No newline at end of file diff --git a/src/login/bind-phone.js b/src/login/bind-phone.js new file mode 100644 index 0000000..daa39c4 --- /dev/null +++ b/src/login/bind-phone.js @@ -0,0 +1,84 @@ + +import { Page } from '../base/page.js'; +import Util from '../utils/util.js'; +import API from '../api.js'; +import * as Client from '../client.js'; + +class BindPhonePage extends Page { + constructor() { + super(); + this.template = ` +

    +`; + + } + + on_mount() { + $(".login-content").on("click", ".panel_item", (e) => this.LoginCommand(e)); + $(".role-list").on("click", ".role-item", function () { + $(this).parent().find(".select").removeClass("select"); + $(this).addClass("select"); + }); + + $('.new-list>li').on('click', showNews); + var key = Util.GetUserCookie("p"); + if (!key) { + return $("#login_panel").show(); + } + server.showServers(); + } + + LoginCommand(e) { + var cmd = $(e.currentTarget).attr("command"); + switch (cmd) { + case "ToRolePanel": + Client.hide2show($("#role_panel")); + break; + case "ToServerPanel": + Client.closeServer(); + Client.hide2show($("#slist_panel")); + break; + case "ToLogin": + Client.hide2show($("#login_panel")); + break; + case "Forget": + Client.hide2show($("#reset_panel")); + break; + case "CancleRegist": + Client.hide2show($("#login_panel")); + break; + case "Down": + Client.hide2show($("#download")); + break; + case "ToRegist": + Client.hide2show($("#regist_panel")); + regist.open(); + break; + case "Regist": + regist.regist(); + break; + case "SelectServer": + server.selectServer(); + break; + case "LoginIn": + loginIn.loginIn(); + break; + case "ResetPwd": + resetPwd.reset(); + break; + case "AddRole": + roles.addRole(); + break; + case "SelectRole": + roles.select(); + break; + case "CreateRole": + createRole.create(); + break; + case "BindPhone": + bindPhone.bind(); + break; + case "CheckValid": + bindPhone.check(); + break; + case "UpdatePwd": + changePwd.update(); + break; + case "ToUpdate": + changePwd.open(); + break; + case "ReLogin": + loginIn.relogin(); + break; + case "DeleteRole": + roles.delete(); + break; + } + } +} + +export default LoginPage; +export { roles }; \ No newline at end of file diff --git a/src/login/login-in.js b/src/login/login-in.js new file mode 100644 index 0000000..798aff3 --- /dev/null +++ b/src/login/login-in.js @@ -0,0 +1,70 @@ + +import { Page } from '../base/page.js'; +import API from '../api.js'; +import * as Client from '../client.js'; +import ServerPage from './server.js'; +import loader from '../img/loader.gif'; + +const server = new ServerPage(); + +class LoginInPage extends Page { + constructor() { + super(); + this.template = ` +