diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 943b8146..5e39e7c6 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -102,36 +102,14 @@ var code = ' \n'; return code; */; -shopcommonevent - : '公共事件版商店 id' IdString '快捷名称' EvalString '未开启不显示' Bool BGNL? '执行的公共事件 id' EvalString '参数列表' JsonEvalString? - -/* shopcommonevent -tooltip : 全局商店, 执行一个公共事件 -helpUrl : https://h5mota.com/games/template/_docs/#/ -default : ["shop1","回收钥匙商店",false,"回收钥匙商店",""] -if (JsonEvalString_0) { - if (!(JSON.parse(JsonEvalString_0) instanceof Array)) - throw new Error('参数列表必须是个有效的数组!'); -} -var code = { - 'id': IdString_0, - 'textInList': EvalString_0, - 'mustEnable': Bool_0, - 'commonEvent': EvalString_1 -} -if (JsonEvalString_0) code.args = JSON.parse(JsonEvalString_0); -code=JSON.stringify(code,null,2)+',\n'; -return code; -*/; - shopsub - : '商店 id' IdString '标题' EvalString? '图像' IdString? BGNL? Newline '文字' EvalString? BGNL? Newline '快捷名称' EvalString '共用次数' Bool '未开启不显示' Bool BGNL? Newline '消耗' EvalString BGNL? Newline '(访问次数:临时变量A;当前消耗:临时变量B)' BGNL? Newline shopChoices+ BEND + : '商店 id' IdString '标题' EvalString? '图像' IdString? BGNL? Newline '文字' EvalString? BGNL? Newline '快捷名称' EvalString '未开启不显示' Bool '不可预览' Bool BGNL? Newline shopChoices+ BEND /* shopsub -tooltip : 全局商店,消耗填-1表示每个选项的消耗不同,正数表示消耗数值 +tooltip : 全局商店 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 -default : ["shop1","贪婪之神","blueShop","勇敢的武士啊, 给我${temp:B}金币就可以:","1F金币商店",false,false,"20+10*temp:A*(temp:A+1)"] +default : ["shop1","贪婪之神","blueShop","勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:","金币商店",false,false] var title=''; if (EvalString_0==''){ if (IdString_1=='') title=''; @@ -144,9 +122,8 @@ var code = { 'id': IdString_0, 'text': title+EvalString_1, 'textInList': EvalString_2, - 'commonTimes': Bool_0, - 'mustEnable': Bool_1, - 'need': EvalString_3, + 'mustEnable': Bool_0, + 'disablePreview': Bool_1, 'choices': 'choices_asdfefw' } code=JSON.stringify(code,null,2).split('"choices_asdfefw"').join('[\n'+shopChoices_0+']')+',\n'; @@ -154,30 +131,21 @@ return code; */; shopChoices - : '商店选项' EvalString '使用条件' EvalString BGNL? Newline '图标' IdString? '颜色' ColorString? Colour '出现条件' EvalString? BGNL? Newline shopEffect+ + : '商店选项' EvalString '使用条件' EvalString BGNL? Newline '图标' IdString? '颜色' ColorString? Colour '出现条件' EvalString? BGNL? Newline action+ BEND /* shopChoices tooltip : 商店选项,商店消耗是-1时,这里的消耗对应各自选项的消耗,商店消耗不是-1时这里的消耗不填 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 -default : ["攻击+1","status:money>=temp:B","","","rgba(255,255,255,1)",""] +default : ["攻击+1","status:money>=20+2*flag:shop1","","","rgba(255,255,255,1)",""] colour : this.subColor ColorString_0 = ColorString_0 ? (', "color": ['+ColorString_0+']') : ''; EvalString_2 = EvalString_2 && (', "condition": "'+EvalString_1+'"') IdString_0 = IdString_0? (', "icon": "'+IdString_0+'"'):''; -var code = '{"text": "'+EvalString_0+'", "need": "'+EvalString_1+'"'+IdString_0+ColorString_0+EvalString_2+', "effect": [\n'+shopEffect_0+']},\n'; +var code = '{"text": "'+EvalString_0+'", "need": "'+EvalString_1+'"'+IdString_0+ColorString_0+EvalString_2+', "action": [\n'+action_0+']},\n'; return code; */; -shopEffect - : idString_e AssignOperator_List expression - - -/* shopEffect -colour : this.subColor -return '{"name": "'+idString_e_0+'", "operator": "'+AssignOperator_List_0+'", "value": "'+expression_0+'"},\n'; -*/; - shopitem : '道具商店 id' IdString '快捷名称' EvalString '未开启不显示' Bool BGNL? Newline shopItemChoices+ BEND @@ -216,6 +184,28 @@ var code = '{"id": "' + IdString_0 + '"' + IntString_0 + EvalString_0 + EvalStri return code; */; +shopcommonevent + : '公共事件商店 id' IdString '快捷名称' EvalString '未开启不显示' Bool BGNL? '执行的公共事件名' EvalString '参数列表' JsonEvalString? + +/* shopcommonevent +tooltip : 全局商店, 执行一个公共事件 +helpUrl : https://h5mota.com/games/template/_docs/#/ +default : ["shop1","回收钥匙商店",false,"回收钥匙商店",""] +if (JsonEvalString_0) { + if (!(JSON.parse(JsonEvalString_0) instanceof Array)) + throw new Error('参数列表必须是个有效的数组!'); +} +var code = { + 'id': IdString_0, + 'textInList': EvalString_0, + 'mustEnable': Bool_0, + 'commonEvent': EvalString_1 +} +if (JsonEvalString_0) code.args = JSON.parse(JsonEvalString_0); +code=JSON.stringify(code,null,2)+',\n'; +return code; +*/; + //afterBattle 事件编辑器入口之一 afterBattle_m : '战斗结束后' BGNL? Newline action+ BEND @@ -1236,15 +1226,16 @@ return code; */; openShop_s - : '打开全局商店' IdString Newline + : '启用全局商店' IdString '同时打开' Bool Newline /* openShop_s tooltip : 全局商店 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=openshop%EF%BC%9A%E6%89%93%E5%BC%80%E4%B8%80%E4%B8%AA%E5%85%A8%E5%B1%80%E5%95%86%E5%BA%97 colour : this.dataColor -default : ["shop1"] -var code = '{"type": "openShop", "id": "'+IdString_0+'"},\n'; +default : ["shop1", true] +Bool_0 = Bool_0 ? (', "open": true') : ''; +var code = '{"type": "openShop", "id": "'+IdString_0+'"'+Bool_0+'},\n'; return code; */; @@ -2742,8 +2733,8 @@ Global_Value_List Global_Flag_List - : '显示当前楼层'|'显示勇士图标'|'显示当前等级'|'启用生命上限'|'显示生命值'|'显示魔力值'|'显示攻击力'|'显示防御力'|'显示护盾值'|'显示金币值'|'显示经验值'|'允许等级提升'|'升级扣除模式'|'显示钥匙数量'|'显示绿钥匙'|'显示破炸飞'|'显示毒衰咒'|'显示当前技能'|'楼梯边才能楼传'|'楼传平面塔模式'|'破墙镐四方向'|'炸弹四方向'|'冰冻徽章四方向'|'铁门不需要钥匙'|'开启加点'|'开启负伤'|'夹击不超伤害值'|'循环计算临界'|'允许轻按'|'允许走到将死领域'|'允许瞬间移动'|'允许查看禁用商店'|'阻激夹域后禁用快捷商店'|'虚化前景层'|'检查控制台' - /*Global_Flag_List ['s:enableFloor','s:enableName','s:enableLv', 's:enableHPMax', 's:enableHP', 's:enableMana', 's:enableAtk', 's:enableDef', 's:enableMDef', 's:enableMoney', 's:enableExp', 's:enableLevelUp', 's:levelUpLeftMode', 's:enableKeys', 's:enableGreenKey', 's:enablePZF', 's:enableDebuff', 's:enableSkill', 'flyNearStair', 'flyRecordPosition', 'pickaxeFourDirections', 'bombFourDirections', 'snowFourDirections', 'steelDoorWithoutKey', 'enableAddPoint', 'enableNegativeDamage', 'betweenAttackMax', 'useLoop', 'enableGentleClick', 'canGoDeadZone', 'enableMoveDirectly', 'enableDisabledShop', 'disableShopOnDamage', 'blurFg']*/; + : '显示当前楼层'|'显示勇士图标'|'显示当前等级'|'启用生命上限'|'显示生命值'|'显示魔力值'|'显示攻击力'|'显示防御力'|'显示护盾值'|'显示金币值'|'显示经验值'|'允许等级提升'|'升级扣除模式'|'显示钥匙数量'|'显示绿钥匙'|'显示破炸飞'|'显示毒衰咒'|'显示当前技能'|'楼梯边才能楼传'|'楼传平面塔模式'|'破墙镐四方向'|'炸弹四方向'|'冰冻徽章四方向'|'铁门不需要钥匙'|'开启加点'|'开启负伤'|'夹击不超伤害值'|'循环计算临界'|'允许轻按'|'允许走到将死领域'|'允许瞬间移动'|'阻激夹域后禁用快捷商店'|'虚化前景层'|'检查控制台' + /*Global_Flag_List ['s:enableFloor','s:enableName','s:enableLv', 's:enableHPMax', 's:enableHP', 's:enableMana', 's:enableAtk', 's:enableDef', 's:enableMDef', 's:enableMoney', 's:enableExp', 's:enableLevelUp', 's:levelUpLeftMode', 's:enableKeys', 's:enableGreenKey', 's:enablePZF', 's:enableDebuff', 's:enableSkill', 'flyNearStair', 'flyRecordPosition', 'pickaxeFourDirections', 'bombFourDirections', 'snowFourDirections', 'steelDoorWithoutKey', 'enableAddPoint', 'enableNegativeDamage', 'betweenAttackMax', 'useLoop', 'enableGentleClick', 'canGoDeadZone', 'enableMoveDirectly', 'disableShopOnDamage', 'blurFg']*/; Colour : 'sdeirughvuiyasdeb'+ //为了被识别为复杂词法规则 @@ -2916,20 +2907,12 @@ ActionParser.prototype.parse = function (obj,type) { var buildsub = function(obj,parser,next){ var text_choices = null; for(var ii=obj.choices.length-1,choice;choice=obj.choices[ii];ii--) { - var text_effect = null; - choice.effect = choice.effect || []; - for (var jj=choice.effect.length-1,effect;effect=choice.effect[jj];jj--) { - text_effect = MotaActionBlocks['shopEffect'].xmlText([ - parser.tryToUseEvFlag_e('idString_e', [effect.name]), effect.operator || '=', - MotaActionBlocks['evalString_e'].xmlText([effect.value]), text_effect - ]); - } text_choices=MotaActionBlocks['shopChoices'].xmlText([ - choice.text,choice.need||'',choice.icon,choice.color,'rgba('+choice.color+')',choice.condition,text_effect,text_choices]); + choice.text,choice.need||'',choice.icon,choice.color,'rgba('+choice.color+')',choice.condition,parser.parseList(choice.action),text_choices]); } var info = parser.getTitleAndPosition(obj.text || ''); return MotaActionBlocks['shopsub'].xmlText([ - obj.id,obj[0],info[1],info[3],obj.textInList,obj.commonTimes,obj.mustEnable,obj.need,text_choices,next + obj.id,obj[0],info[1],info[3],obj.textInList,obj.mustEnable,obj.disablePreview,text_choices,next ]); } var buildcommentevent = function(obj,parser,next){ @@ -3279,7 +3262,7 @@ ActionParser.prototype.parseAction = function() { break; case "openShop": // 打开一个全局商店 this.next = MotaActionBlocks['openShop_s'].xmlText([ - data.id,this.next]); + data.id,data.open||false,this.next]); break; case "disableShop": // 禁用一个全局商店 this.next = MotaActionBlocks['disableShop_s'].xmlText([ diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index e1c570ff..b2ef109c 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -38,19 +38,16 @@ editor_blockly = function () { },'autoEvent'), MotaActionBlocks['changeFloor_m'].xmlText(), MotaActionFunctions.actionParser.parse([{ - "id": "moneyShop1", - "text": "\t[贪婪之神,blueShop]勇敢的武士啊, 给我\${temp:B}金币就可以:", - "textInList": "1F金币商店", - "need": "20+10*temp:A*(temp:A+1)", + "id": "shop1", + "text": "\t[贪婪之神,blueShop]勇敢的武士啊, 给我\${20+2*flag:shop1}金币就可以:", + "textInList": "1F金币商店", "choices": [ - {"text": "生命+800", "need": "status:money>=temp:B", "effect": [ - {"name": "status:money", "operator": "-=", "value": "temp:B"}, - {"name": "status:hp", "operator": "+=", "value": "800"}, - ]}, - {"text": "攻击+4", "need": "status:money>=temp:B", "effect": [ - {"name": "status:money", "operator": "-=", "value": "temp:B"}, - {"name": "status:atk", "operator": "+=", "value": "4"}, - ]}, + {"text": "生命+800", "need": "status:money>=20+2*flag:shop1", "action": [ + {"type": "comment", "text": "新版商店中需要手动扣减金币和增加访问次数"}, + {"type": "setValue", "name": "status:money", "operator": "-=", "value": "20+2*flag:shop1"}, + {"type": "setValue", "name": "flag:shop1", "operator": "+=", "value": "1"}, + {"type": "setValue", "name": "status:hp", "operator": "+=", "value": "800"} + ]} ] },{ "id": "itemShop", diff --git a/_server/table/data.comment.js b/_server/table/data.comment.js index f2e96178..5b11ee0d 100644 --- a/_server/table/data.comment.js +++ b/_server/table/data.comment.js @@ -667,12 +667,6 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_docs": "允许瞬移", "_data": "是否允许瞬间移动" }, - "enableDisabledShop": { - "_leaf": true, - "_type": "checkbox", - "_docs": "商店预览", - "_data": "是否允许查看未开启状态的快捷商店内容;如果此项为真,则对于未开启状态的商店允许查看其内容(但不能购买)" - }, "disableShopOnDamage": { "_leaf": true, "_type": "checkbox", diff --git a/_server/table/functions.comment.js b/_server/table/functions.comment.js index d8fd7de3..c70d1df5 100644 --- a/_server/table/functions.comment.js +++ b/_server/table/functions.comment.js @@ -87,12 +87,6 @@ var functions_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "textarea", "_lint": true, "_data": "特殊地形后" - }, - "canUseQuickShop": { - "_leaf": true, - "_type": "textarea", - "_lint": true, - "_data": "能否快捷商店" } } }, diff --git a/_server/table/plugins.comment.js b/_server/table/plugins.comment.js index ec02f2ff..f012cdc1 100644 --- a/_server/table/plugins.comment.js +++ b/_server/table/plugins.comment.js @@ -14,13 +14,19 @@ var plugins_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_range": "typeof(thiseval)=='string'", "_data": "自定义插件" }, + "shop": { + "_leaf": true, + "_type": "textarea", + "_range": "typeof(thiseval)=='string'", + "_data": "全局商店" + }, "drawLight": { "_leaf": true, "_type": "textarea", "_range": "typeof(thiseval)=='string' || thiseval==null", "_data": "灯光效果" }, - "drawItemShop": { + "itemShop": { "_leaf": true, "_type": "textarea", "_range": "typeof(thiseval)=='string' || thiseval==null", diff --git a/libs/actions.js b/libs/actions.js index de3809c0..094dd966 100644 --- a/libs/actions.js +++ b/libs/actions.js @@ -260,9 +260,6 @@ actions.prototype._sys_keyDown_lockControl = function (keyCode) { case 'replayRemain': this._keyDownSL(keyCode); break; - case 'shop': - this._keyDownShop(keyCode); - break; case 'selectShop': case 'switchs': case 'settings': @@ -346,9 +343,6 @@ actions.prototype._sys_keyUp_lockControl = function (keyCode, altKey) { case 'viewMaps': this._keyUpViewMaps(keyCode); break; - case 'shop': - this._keyUpShop(keyCode); - break; case 'selectShop': this._keyUpQuickShop(keyCode); break; @@ -476,7 +470,6 @@ actions.prototype._sys_onmove_choices = function (x, y) { switch (core.status.event.id) { case 'action': if (core.status.event.data.type != 'choices') break; - case 'shop': case 'selectShop': case 'switchs': case 'settings': @@ -614,9 +607,6 @@ actions.prototype._sys_onclick_lockControl = function (x, y) { case 'settings': this._clickSettings(x, y); break; - case 'shop': - this._clickShop(x, y); - break; case 'selectShop': this._clickQuickShop(x, y); break; @@ -792,10 +782,6 @@ actions.prototype._sys_longClick_lockControl = function (x, y) { return true; } } - // 长按商店连续购买 - if (core.status.event.id == 'shop' && x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) { - return this._clickShop(x, y); - } // 长按可以跳过等待事件 if (core.status.event.id == 'action' && core.status.event.data.type == 'sleep' && !core.status.event.data.current.noSkip) { @@ -1280,61 +1266,28 @@ actions.prototype._keyUpViewMaps = function (keycode) { return; } -////// 商店界面时的点击操作 ////// -actions.prototype._clickShop = function (x, y) { - var shop = core.status.event.data.shop; - var choices = shop.choices; - if (x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) { - var topIndex = this.HSIZE - parseInt(choices.length / 2) + (core.status.event.ui.offset || 0); - if (y >= topIndex && y < topIndex + choices.length) { - return core.events._useShop(shop, y - topIndex); - } - // 离开 - else if (y == topIndex + choices.length) { - core.events._exitShop(); - } - else return false; - } - return true; -} - -actions.prototype._keyDownShop = function (keycode) { - // 商店界面长按空格连续购买 - if (keycode == 32 && core.status.event.selection != core.status.event.data.shop.choices.length) { - this._selectChoices(core.status.event.data.shop.choices.length + 1, keycode, this._clickShop); - return; - } - this._keyDownChoices(keycode); -} - -////// 商店界面时,放开某个键的操作 ////// -actions.prototype._keyUpShop = function (keycode) { - if (keycode == 27 || keycode == 88) { - core.events._exitShop(); - return; - } - if (keycode != 32 || core.status.event.selection == core.status.event.data.shop.choices.length) { - this._selectChoices(core.status.event.data.shop.choices.length + 1, keycode, this._clickShop); - return; - } - return; -} - ////// 快捷商店界面时的点击操作 ////// actions.prototype._clickQuickShop = function (x, y) { - var keys = Object.keys(core.status.shops).filter(function (shopId) { - return core.status.shops[shopId].visited || !core.status.shops[shopId].mustEnable - }); + var shopIds = core.listShopIds(); if (x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) { - var topIndex = this.HSIZE - parseInt(keys.length / 2) + (core.status.event.ui.offset || 0); - if (y >= topIndex && y < topIndex + keys.length) { - core.events.openShop(keys[y - topIndex], true); - if (core.status.event.id == 'shop') - core.status.event.data.fromList = true; + var topIndex = this.HSIZE - parseInt(shopIds.length / 2) + (core.status.event.ui.offset || 0); + if (y >= topIndex && y < topIndex + shopIds.length) { + var shopId = shopIds[y - topIndex]; + if (!core.canOpenShop(shopId)) { + core.drawTip('当前项尚未开启'); + return; + } + var message = core.canUseQuickShop(shopId); + if (message == null) { + // core.ui.closePanel(); + core.openShop(shopIds[y - topIndex], false); + } else { + core.drawTip(message); + } } // 离开 - else if (y == topIndex + keys.length) + else if (y == topIndex + shopIds.length) core.ui.closePanel(); return; } @@ -1347,10 +1300,7 @@ actions.prototype._keyUpQuickShop = function (keycode) { core.ui.closePanel(); return; } - var keys = Object.keys(core.status.shops).filter(function (shopId) { - return core.status.shops[shopId].visited || !core.status.shops[shopId].mustEnable - }); - this._selectChoices(keys.length + 1, keycode, this._clickQuickShop); + this._selectChoices(core.listShopIds().length + 1, keycode, this._clickQuickShop); return; } diff --git a/libs/control.js b/libs/control.js index 0f3dfe5f..a4f5ae89 100644 --- a/libs/control.js +++ b/libs/control.js @@ -1010,9 +1010,9 @@ control.prototype.checkBlock = function () { control.prototype._checkBlock_disableQuickShop = function () { // 禁用快捷商店 if (core.flags.disableShopOnDamage) { - for (var shopId in core.status.shops) { - core.status.shops[shopId].visited = false; - } + Object.keys(core.status.shops).forEach(function (shopId) { + core.setShopVisited(shopId, false); + }); } } @@ -1517,36 +1517,13 @@ control.prototype._replayAction_fly = function (action) { control.prototype._replayAction_shop = function (action) { if (action.indexOf("shop:")!=0) return false; - var sps=action.substring(5).split(":"); - var shopId=sps[0], selections=sps[1].split(""); - if (selections.length == 0) return false; - var shop=core.status.shops[shopId]; - if (!shop || !shop.visited) return false; - // --- 判定commonEvent或item - if (shop.commonEvent || shop.item) { - core.openShop(shopId, false); - core.replay(); + var shopId = action.substring(5); + if (core.canUseQuickShop(shopId) != null || !core.canOpenShop(shopId)) { + this._replay_error(shopId); return true; } - var choices = shop.choices; - core.status.event.selection = parseInt(selections.shift()); - core.events.openShop(shopId, false); - var topIndex = core.__HALF_SIZE__ - parseInt(choices.length / 2) + (core.status.event.ui.offset || 0); - var shopInterval = setInterval(function () { - if (!core.actions._clickShop(core.__HALF_SIZE__, topIndex+core.status.event.selection)) { - clearInterval(shopInterval); - core.control._replay_error(action); - return; - } - if (selections.length==0) { - clearInterval(shopInterval); - core.actions._clickShop(core.__HALF_SIZE__, topIndex+choices.length); - core.replay(); - return; - } - core.status.event.selection = parseInt(selections.shift()); - core.events.openShop(shopId, false); - }, core.control.__replay_getTimeout()); + core.openShop(shopId, false); + core.replay(); return true; } diff --git a/libs/events.js b/libs/events.js index 6778633c..80d2be26 100644 --- a/libs/events.js +++ b/libs/events.js @@ -1506,16 +1506,13 @@ events.prototype._action_unloadEquip = function (data, x, y, prefix) { } events.prototype._action_openShop = function (data, x, y, prefix) { - core.status.shops[data.id].visited = true; - this.setEvents([]); - if (!core.isReplaying()) - this.openShop(data.id); - if (core.status.event.id == 'action') - core.doAction(); + core.setShopVisited(data.id, true); + if (data.open) core.openShop(data.id, true); + core.doAction(); } events.prototype._action_disableShop = function (data, x, y, prefix) { - this.disableQuickShop(data.id); + core.setShopVisited(data.id, false); core.doAction(); } @@ -2347,8 +2344,17 @@ events.prototype.openQuickShop = function (fromUserAction) { // --- 如果只有一个商店,则直接打开之 if (Object.keys(core.status.shops).length == 1) { var shopId = Object.keys(core.status.shops)[0]; - if (core.status.event.id != null || !this._checkStatus('shop', false)) return; - core.events.openShop(shopId, true); + if (core.status.event.id != null) return; + if (!core.canOpenShop(shopId)) { + core.drawTip("当前无法打开快捷商店!"); + return; + } + var message = core.canUseQuickShop(shopId); + if (message != null) { + core.drawTip(message); + return; + } + core.openShop(shopId, false); return; } @@ -2497,16 +2503,6 @@ events.prototype.addValue = function (name, value, prefix) { this.setValue(name, '+=', value, prefix); } -////// 执行一个表达式的effect操作 ////// -events.prototype.doEffect = function (effect, need, times) { - effect.split(";").forEach(function (expression) { - var arr = expression.split("+="); - if (arr.length != 2) return; - var name=arr[0], value=core.calValue(arr[1], null, need, times); - core.addValue(name, value); - }); -} - ////// 设置一个怪物属性 ////// events.prototype.setEnemy = function (id, name, value, prefix) { if (!core.hasFlag('enemyInfo')) { @@ -2874,87 +2870,6 @@ events.prototype._jumpHero_finished = function (animate, ex, ey, callback) { if (callback) callback(); } -////// 打开一个全局商店 ////// -events.prototype.openShop = function (shopId, needVisited) { - var shop = core.status.shops[shopId]; - shop.times = shop.times || 0; - if (shop.commonTimes) shop.times = core.getFlag('commonTimes', 0); - var reason = core.events.canUseQuickShop(shop.id); - if (reason != null) return core.drawTip(reason); - - if (needVisited && !shop.visited) { - if (!core.flags.enableDisabledShop || shop.commonEvent || shop.item) { - if (shop.times == 0) core.drawTip("该项尚未开启"); - else core.drawTip("该项已失效"); - core.ui.closePanel(); - return; - } - else { - core.drawTip("该商店尚未开启,只能浏览不可使用"); - } - } - else shop.visited = true; - - if (shop.item) { - core.status.route.push("shop:" + shopId + ":0"); - if (core.openItemShop) { - core.openItemShop(shopId); - } else { - core.insertAction("道具商店插件不存在!请检查是否存在该插件!"); - } - return; - } else if (shop.commonEvent) { - core.status.route.push("shop:"+shopId+":0"); - core.insertAction({"type": "insert", "name": shop.commonEvent, "args": shop.args}); - return; - } - core.ui.drawShop(shopId); -} - -events.prototype._useShop = function (shop, index) { - if (!shop.visited) { - core.drawTip(shop.times ? "该商店已失效" : "该商店尚未开启"); - return false; - } - var use = shop.use, choice = shop.choices[index]; - var times = shop.times, need = core.calValue(choice.need || shop.need, null, null, times); - if (need > core.getStatus(use)) { - core.drawTip("你的" + (use == 'money' ? "金币" : "经验") + "不足"); - return false; - } - core.status.event.selection = index; - core.status.event.data.actions.push(index); - core.setStatus(use, core.getStatus(use) - need); - core.doEffect(choice.effect, need, times); - core.updateStatusBar(); - shop.times++; - if (shop.commonTimes) core.setFlag('commonTimes', shop.times); - this.openShop(shop.id); - return true; -} - -events.prototype._exitShop = function () { - if (core.status.event.data.actions.length > 0) { - core.status.route.push("shop:" + core.status.event.data.id + ":" + core.status.event.data.actions.join("")); - } - core.status.event.data.actions = []; - core.status.boxAnimateObjs = []; - if (core.status.event.data.fromList) - core.ui.drawQuickShop(); - else - core.ui.closePanel(); -} - -////// 禁用一个全局商店 ////// -events.prototype.disableQuickShop = function (shopId) { - core.status.shops[shopId].visited = false; -} - -////// 能否使用快捷商店 ////// -events.prototype.canUseQuickShop = function (shopId) { - return this.eventdata.canUseQuickShop(shopId); -} - ////// 设置角色行走图 ////// events.prototype.setHeroIcon = function (name, noDraw) { name = core.getMappedName(name); diff --git a/libs/ui.js b/libs/ui.js index c69461fd..6aea41ff 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -443,12 +443,14 @@ ui.prototype._uievent_drawIcon = function (data) { ////// 结束一切事件和绘制,关闭UI窗口,返回游戏进程 ////// ui.prototype.closePanel = function () { - // 清除全部临时变量 - Object.keys(core.status.hero.flags).forEach(function (name) { - if (name.startsWith("@temp@")) { - delete core.status.hero.flags[name]; - } - }); + if (core.status.hero && core.status.hero.flags) { + // 清除全部临时变量 + Object.keys(core.status.hero.flags).forEach(function (name) { + if (name.startsWith("@temp@")) { + delete core.status.hero.flags[name]; + } + }); + } this.clearUI(); core.maps.generateGroundPattern(); core.updateStatusBar(true); @@ -1552,11 +1554,9 @@ ui.prototype.drawSettings = function () { ////// 绘制快捷商店选择栏 ////// ui.prototype.drawQuickShop = function () { core.status.event.id = 'selectShop'; - var shopList = core.status.shops, keys = Object.keys(shopList).filter(function (shopId) { - return shopList[shopId].visited || !shopList[shopId].mustEnable - }); + var shopList = core.status.shops, keys = core.listShopIds(); var choices = keys.map(function (shopId) { - return {"text": shopList[shopId].textInList, "color": shopList[shopId].visited?null:"#999999"}; + return {"text": shopList[shopId].textInList, "color": core.isShopVisited(shopId) ? null : "#999999"}; }); choices.push("返回游戏"); this.drawChoices(null, choices); @@ -2038,33 +2038,6 @@ ui.prototype.drawCenterFly = function () { return; } -////// 绘制全局商店 -ui.prototype.drawShop = function (shopId) { - var shop = core.status.shops[shopId]; - var actions = [], fromList = (core.status.event.data||{}).fromList, selection = core.status.event.selection; - if (core.status.event.data && core.status.event.data.actions) actions=core.status.event.data.actions; - - core.ui.closePanel(); - core.lockControl(); - core.status.event.id = 'shop'; - core.status.event.data = {'id': shopId, 'shop': shop, 'actions': actions, 'fromList': fromList}; - core.status.event.selection = selection; - - var times = shop.times, need=core.calValue(shop.need, null, null, times); - var content = "\t["+shop.name+","+shop.icon+"]" + core.replaceText(shop.text, null, need, times); - var use = shop.use=='exp'?'经验':'金币'; - var choices = []; - for (var i=0;i= 0) { @@ -596,7 +596,7 @@ utils.prototype._decodeRoute_decodeOne = function (decodeObj, c) { decodeObj.ans.push("choices:" + nxt); break; case "S": - decodeObj.ans.push("shop:" + nxt + ":" + this._decodeRoute_getNumber(decodeObj, true)); + decodeObj.ans.push("shop:" + nxt); break; case "T": decodeObj.ans.push("turn"); diff --git a/main.js b/main.js index 74da7a29..e6206b82 100644 --- a/main.js +++ b/main.js @@ -597,7 +597,7 @@ main.statusBar.image.keyboard.onclick = function (e) { main.core.openKeyBoard(true); } -////// 点击状态栏中的快捷商店键盘时 ////// +////// 点击状态栏中的快捷商店时 ////// main.statusBar.image.shop.onclick = function (e) { e.stopPropagation(); @@ -610,7 +610,7 @@ main.statusBar.image.shop.onclick = function (e) { main.core.openQuickShop(true); } -////// 点击金币时也可以开启虚拟键盘 ////// +////// 点击金币时也可以开启快捷商店 ////// main.statusBar.image.money.onclick = function (e) { e.stopPropagation(); diff --git a/project/data.js b/project/data.js index a4adb924..86e3be31 100644 --- a/project/data.js +++ b/project/data.js @@ -299,31 +299,98 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = ], "shops": [ { - "id": "moneyShop1", - "text": "\t[贪婪之神,blueShop]勇敢的武士啊, 给我${temp:B}金币就可以:", + "id": "shop1", + "text": "\t[贪婪之神,blueShop]勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:", "textInList": "1F金币商店", - "commonTimes": false, "mustEnable": false, - "need": "20+10*temp:A*(temp:A+1)", + "disablePreview": false, "choices": [ { "text": "生命+800", - "need": "status:money>=temp:B", - "effect": [ + "need": "status:money>=20+2*flag:shop1", + "action": [ { - "name": "status:money", - "operator": "-=", - "value": "temp:B" + "type": "comment", + "text": "新版商店中需要手动扣减金币和增加访问次数" }, { + "type": "setValue", + "name": "status:money", + "operator": "-=", + "value": "20+2*flag:shop1" + }, + { + "type": "setValue", + "name": "flag:shop1", + "operator": "+=", + "value": "1" + }, + { + "type": "setValue", "name": "status:hp", "operator": "+=", "value": "800" + } + ] + }, + { + "text": "攻击+4", + "need": "status:money>=20+2*flag:shop1", + "action": [ + { + "type": "comment", + "text": "新版商店中需要手动扣减金币和增加访问次数" }, { - "name": "flag:xxx", - "operator": "=", - "value": "temp:B" + "type": "setValue", + "name": "status:money", + "operator": "-=", + "value": "20+2*flag:shop1" + }, + { + "type": "setValue", + "name": "flag:shop1", + "operator": "+=", + "value": "1" + }, + { + "type": "setValue", + "name": "status:atk", + "operator": "+=", + "value": "4" + } + ] + } + ] + }, + { + "id": "shop2", + "text": "\t[贪婪之神,pinkShop]勇敢的武士啊, 给我一定经验就可以:", + "textInList": "1F经验商店", + "mustEnable": false, + "disablePreview": true, + "choices": [ + { + "text": "等级+1(100经验)", + "need": "status:exp>=100", + "action": [ + { + "type": "setValue", + "name": "status:exp", + "operator": "-=", + "value": "100" + }, + { + "type": "setValue", + "name": "status:lv", + "operator": "+=", + "value": "1" + }, + { + "type": "setValue", + "name": "status:hp", + "operator": "+=", + "value": "1000" } ] } @@ -338,12 +405,13 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = { "id": "yellowKey", "number": 10, - "money": "10" + "money": "10", + "sell": "5" } ] }, { - "id": "keyShop1", + "id": "keyShop", "textInList": "回收钥匙商店", "mustEnable": false, "commonEvent": "回收钥匙商店" @@ -442,7 +510,6 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = "ignoreChangeFloor": true, "canGoDeadZone": false, "enableMoveDirectly": true, - "enableDisabledShop": true, "disableShopOnDamage": false, "blurFg": false } diff --git a/project/events.js b/project/events.js index d98dcfda..e51ac0a4 100644 --- a/project/events.js +++ b/project/events.js @@ -244,7 +244,7 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 = "回收钥匙商店": [ { "type": "comment", - "text": "此事件在全局商店中被引用了(全局商店keyShop1)" + "text": "此事件在全局商店中被引用了(全局商店keyShop)" }, { "type": "comment", diff --git a/project/floors/sample1.js b/project/floors/sample1.js index 5149304d..7260bac0 100644 --- a/project/floors/sample1.js +++ b/project/floors/sample1.js @@ -229,13 +229,15 @@ main.floors.sample1= "1,0": [ { "type": "openShop", - "id": "moneyShop1" + "id": "shop1", + "open": true } ], "5,0": [ { "type": "openShop", - "id": "expShop1" + "id": "shop2", + "open": true } ], "7,7": [ diff --git a/project/functions.js b/project/functions.js index c63fa1fe..90073aaa 100644 --- a/project/functions.js +++ b/project/functions.js @@ -429,18 +429,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // if (id == 'lavaNet') core.removeBlock(x, y); }, - "canUseQuickShop": function(shopId) { - // 当前能否使用某个快捷商店 - // shopId:快捷商店ID - // 如果返回一个字符串,表示不能,字符串为不能使用的提示 - // 返回null代表可以使用 - - // 检查当前楼层的canUseQuickShop选项是否为false - if (core.status.thisMap.canUseQuickShop === false) - return '当前楼层不能使用快捷商店。'; - - return null; -} }, "enemys": { "getSpecials": function () { @@ -943,17 +931,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = 'maps': core.maps.saveMap(), 'route': core.encodeRoute(core.status.route), 'values': values, - 'shops': {}, 'version': core.firstData.version, "time": new Date().getTime() }; - // 设置商店次数 - for (var shopId in core.status.shops) { - data.shops[shopId] = { - 'times': core.status.shops[shopId].times || 0, - 'visited': core.status.shops[shopId].visited || false - }; - } return data; }, @@ -963,13 +943,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = // 重置游戏和路线 core.resetGame(data.hero, data.hard, data.floorId, core.maps.loadMap(data.maps), data.values); core.status.route = core.decodeRoute(data.route); - // 加载商店信息 - for (var shopId in core.status.shops) { - if (data.shops[shopId]) { - core.status.shops[shopId].times = data.shops[shopId].times; - core.status.shops[shopId].visited = data.shops[shopId].visited; - } - } // 文字属性,全局属性 core.status.textAttribute = core.getFlag('textAttribute', core.status.textAttribute); var toAttribute = core.getFlag('globalAttribute', core.status.globalAttribute); diff --git a/project/plugins.js b/project/plugins.js index 3f25e0f6..12f2712b 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -84,6 +84,142 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ctx.globalCompositeOperation = 'source-over'; // 可以在任何地方(如afterXXX或自定义脚本事件)调用函数,方法为 core.plugin.xxx(); } +}, + "shop": function () { + // 【全局商店】相关的功能 + // + // 打开一个全局商店 + // shopId:要打开的商店id;noRoute:是否不计入录像 + this.openShop = function (shopId, noRoute) { + var shop = core.status.shops[shopId]; + // Step 1: 检查能否打开此商店 + if (!this.canOpenShop(shopId)) { + core.drawTip("该商店尚未开启"); + return false; + } + + // Step 2: (如有必要)记录打开商店的脚本事件 + if (!noRoute) { + core.status.route.push("shop:" + shopId); + } + + // Step 3: 检查道具商店 or 公共事件 + if (shop.item) { + if (core.openItemShop) { + core.openItemShop(shopId); + } else { + core.insertAction("道具商店插件不存在!请检查是否存在该插件!"); + } + return; + } + if (shop.commonEvent) { + core.insertAction({ "type": "insert", "name": shop.commonEvent, "args": shop.args }); + return; + } + + // Step 4: 执行标准公共商店 + core.insertAction(this._convertShop(shop)); + return true; + } + + ////// 将一个全局商店转变成可预览的公共事件 ////// + this._convertShop = function (shop) { + return [{ + "type": "while", + "condition": "true", + "data": [ + // 检测能否访问该商店 + { + "type": "if", + "condition": "core.isShopVisited('" + shop.id + "')", + "true": [ + // 可以访问,直接插入执行效果 + { "type": "function", "function": "function() { core.plugin._convertShop_replaceChoices('" + shop.id + "', false) }" }, + ], + "false": [ + // 不能访问的情况下:检测能否预览 + { + "type": "if", + "condition": shop.disablePreview, + "true": [ + // 不可预览,提示并退出 + "当前无法访问该商店!", + { "type": "break" }, + ], + "false": [ + // 可以预览:将商店全部内容进行替换 + { "type": "tip", "text": "当前处于预览模式,不可购买" }, + { "type": "function", "function": "function() { core.plugin._convertShop_replaceChoices('" + shop.id + "', true) }" }, + ] + } + ] + } + ] + }]; + } + + this._convertShop_replaceChoices = function (shopId, previewMode) { + var shop = core.status.shops[shopId]; + var choices = (shop.choices || []).filter(function (choice) { + if (choice.condition == null || choice.condition == '') return true; + try { return core.calValue(choice.condition); } catch (e) { return true; } + }).map(function (choice) { + var ableToBuy = core.calValue(choice.need); + return { + "text": choice.text, + "icon": choice.icon, + "color": ableToBuy && !previewMode ? choice.color : [153, 153, 153, 1], + "action": ableToBuy && !previewMode ? choice.action : [ + { "type": "tip", "text": previewMode ? "预览模式下不可购买" : "购买条件不足" } + ] + }; + }).concat({ "text": "离开", "action": [{ "type": "break" }] }); + core.insertAction({ "type": "choices", "text": shop.text, "choices": choices }); + } + + /// 是否访问过某个快捷商店 + this.isShopVisited = function (id) { + if (!core.hasFlag("__shops__")) core.setFlag("__shops__", {}); + var shops = core.getFlag("__shops__"); + if (!shops[id]) shops[id] = {}; + return shops[id].visited; + } + + /// 当前应当显示的快捷商店列表 + this.listShopIds = function () { + return Object.keys(core.status.shops).filter(function (id) { + return core.isShopVisited(id) || !core.status.shops[id].mustEnable; + }); + } + + /// 是否能够打开某个商店 + this.canOpenShop = function (id) { + if (this.isShopVisited(id)) return true; + var shop = core.status.shops[id]; + if (shop.item || shop.commonEvent || shop.mustEnable) return false; + return true; + } + + /// 启用或禁用某个快捷商店 + this.setShopVisited = function (id, visited) { + if (!core.hasFlag("__shops__")) core.setFlag("__shops__", {}); + var shops = core.getFlag("__shops__"); + if (!shops[id]) shops[id] = {}; + if (visited) shops[id].visited = true; + else delete shops[id].visited; + } + + /// 能否使用快捷商店 + this.canUseQuickShop = function (id) { + // 如果返回一个字符串,表示不能,字符串为不能使用的提示 + // 返回null代表可以使用 + + // 检查当前楼层的canUseQuickShop选项是否为false + if (core.status.thisMap.canUseQuickShop === false) + return '当前楼层不能使用快捷商店。'; + return null; + } + }, "itemShop": function () { // 道具商店相关的插件 @@ -97,6 +233,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = var totalPage = 0; var totalMoney = 0; var list = []; + var shopInfo = null; // 商店信息 + var choices = []; // 商店选项 var bigFont = core.ui._buildFont(20, false), middleFont = core.ui._buildFont(18, false); @@ -143,9 +281,8 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } // Step 2:获得列表并展示 - var choices = core.status.shops[shopId].choices; list = choices.filter(function (one) { - if (one.condition != null) { + if (one.condition != null && one.condition != '') { try { if (!core.calValue(one.condition)) return false; } catch (e) {} } return (type == 0 && one.money != null) || (type == 1 && one.sell != null); @@ -369,6 +506,10 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = page = 0; selectItem = null; selectCount = 0; + shopInfo = flags.__shops__[shopId]; + if (shopInfo.choices == null) shopInfo.choices = core.clone(core.status.shops[shopId].choices); + choices = shopInfo.choices; + core.insertAction([{ "type": "while", "condition": "true", @@ -386,36 +527,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = ]); } - // Write item number to save - core.control.saveData = function () { - var data = this.controldata.saveData(); - for (var shopId in core.status.shops) { - if (core.status.shops[shopId].item) { - data.shops[shopId].choices = core.status.shops[shopId].choices.map(function (t) { - return { - number: t.number, - money_count: t.money_count || 0, - sell_count: t.sell_count || 0 - } - }); - } - } - return data; - } - - core.control.loadData = function (data, callback) { - this.controldata.loadData(data, callback); - for (var shopId in data.shops) { - if (data.shops[shopId].choices) { - for (var i = 0; i < data.shops[shopId].choices.length; ++i) { - core.status.shops[shopId].choices[i].number = data.shops[shopId].choices[i].number; - core.status.shops[shopId].choices[i].money_count = data.shops[shopId].choices[i].money_count; - core.status.shops[shopId].choices[i].sell_count = data.shops[shopId].choices[i].sell_count; - } - } - } - } - }, "smoothCamera": function () {