# HG changeset patch # User Wuzzy # Date 1519257820 -3600 # Node ID 2d0f3e12fcad26efe73a4ac515a489a704ca48ef # Parent 8b42562dcada77283735b8121cd931dfb68d0c16 SimpleMission: Add support for failure texts in the stats screen diff -r 8b42562dcada -r 2d0f3e12fcad share/hedgewars/Data/Scripts/SimpleMission.lua --- a/share/hedgewars/Data/Scripts/SimpleMission.lua Wed Feb 21 22:43:03 2018 +0100 +++ b/share/hedgewars/Data/Scripts/SimpleMission.lua Thu Feb 22 01:03:40 2018 +0100 @@ -126,6 +126,9 @@ GOAL TYPES: - type name of goal type + - failText Optional. For non-goals, this text will be shown in the stats if mission fails due to this non-goal + being completed. For goals which fail, this text will be displayed at failure. Note that + all normal goals have sensible default fail texts. - type="destroy" Gear must be destroyed - id Gear to destroy - type="teamDefeat" Team must be defeated @@ -292,6 +295,15 @@ end end + _G.sm.criticalGearFailText = function(gearSmid) + local gear = _G.sm.goalGears[gearSmid] + if GetGearType(gear) == gtHedgehog then + return string.format(loc("%s is dead, who was critical to this mission!"), GetHogName(gear)) + else + return loc("We have lost an object which was critical to this mission.") + end + end + _G.sm.checkGoal = function(goal) if goal.type == "destroy" then return getGearValue(_G.sm.goalGears[goal.id], "sm_destroyed") @@ -303,7 +315,7 @@ return true else -- Fail if the crate was collected by enemy - return "fail" + return "fail", loc("The enemy has taken a crate which we really needed!") end else for c=1, #goal.collectors do @@ -312,12 +324,12 @@ end end -- Fail if the crate was collected by someone who was not supposed to get it - return "fail" + return "fail", loc("The wrong hedgehog has taken the crate.") end else -- Fail goal if crate was destroyed if getGearValue(_G.sm.goalGears[goal.id], "sm_destroyed") then - return "fail" + return "fail", loc("A crate critical to this mission has been destroyed.") end return false end @@ -327,7 +339,7 @@ return (TotalRounds) >= goal.rounds elseif goal.type == "inZone" then if getGearValue(_G.sm.goalGears[goal.id], "sm_destroyed") then - return "fail" + return "fail", criticalGearFailText(goal.id) end local gX, gY = GetGearPosition(_G.sm.goalGears[goal.id]) -- 4 sub-goals, each optional @@ -341,14 +353,16 @@ if goal.type == "distGearPos" then if getGearValue(_G.sm.goalGears[goal.id], "sm_destroyed") then -- Fail if gear was destroyed - return "fail" + return "fail", criticalGearFailText(goal.id) end gX, gY = GetGearPosition(_G.sm.goalGears[goal.id]) tX, tY = goal.x, goal.y elseif goal.type == "distGearGear" then - if getGearValue(_G.sm.goalGears[goal.id1], "sm_destroyed") or getGearValue(_G.sm.goalGears[goal.id2], "sm_destroyed") then - -- Fail if one of the gears was destroyed - return "fail" + -- Fail if one of the gears was destroyed + if getGearValue(_G.sm.goalGears[goal.id1], "sm_destroyed") then + return "fail", criticalGearFailText(goal.id1) + elseif getGearValue(_G.sm.goalGears[goal.id2], "sm_destroyed") then + return "fail", criticalGearFailText(goal.id2) end gX, gY = GetGearPosition(_G.sm.goalGears[goal.id1]) tX, tY = GetGearPosition(_G.sm.goalGears[goal.id2]) @@ -368,11 +382,16 @@ return sm.isInSuddenDeath elseif goal.type == "damage" then local damage = goal.damage or 1 - local tookEnoughDamage = getGearValue(_G.sm.goalGears[goal.id], "sm_maxDamage") >= damage - if getGearValue(_G.sm.goalGears[goal.id], "sm_destroyed") then + local gear = _G.sm.goalGears[goal.id] + local tookEnoughDamage = getGearValue(gear, "sm_maxDamage") >= damage + if getGearValue(gear, "sm_destroyed") then -- Fail if gear was destroyed without taking enough damage first if not tookEnoughDamage and goal.canDestroy == false then - return "fail" + if GetGearType(gear) == gtHedgehog then + return "fail", string.format(loc("%s has been killed before taking enough damage first."), GetHogName(gear)) + else + return "fail", loc("An object has been destroyed before it took enough damage.") + end else -- By default, succeed if gear was destroyed return true @@ -383,27 +402,27 @@ local drowned = getGearValue(_G.sm.goalGears[goal.id], "sm_drowned") -- Fail if gear was destroyed by something other than drowning if not drowned and getGearValue(_G.sm.goalGears[goal.id], "sm_destroyed") then - return "fail" + return "fail", criticalGearFailText(goal.id) end return drowned elseif goal.type == "poison" then if getGearValue(_G.sm.goalGears[goal.id], "sm_destroyed") then - return "fail" + return "fail", criticalGearFailText(goal.id) end return GetEffect(_G.sm.goalGears[goal.id], hePoisoned) >= 1 elseif goal.type == "freeze" then if getGearValue(_G.sm.goalGears[goal.id], "sm_destroyed") then - return "fail" + return "fail", criticalGearFailText(goal.id) end return GetEffect(_G.sm.goalGears[goal.id], heFrozen) >= 256 elseif goal.type == "cure" then if getGearValue(_G.sm.goalGears[goal.id], "sm_destroyed") then - return "fail" + return "fail", criticalGearFailText(goal.id) end return GetEffect(_G.sm.goalGears[goal.id], hePoisoned) == 0 elseif goal.type == "melt" then if getGearValue(_G.sm.goalGears[goal.id], "sm_destroyed") then - return "fail" + return "fail", criticalGearFailText(goal.id) end return GetEffect(_G.sm.goalGears[goal.id], heFrozen) == 0 elseif goal.type == "waterSkip" then @@ -411,7 +430,7 @@ local hasEnoughSkips = getGearValue(_G.sm.goalGears[goal.id], "sm_waterSkips") >= skips -- Fail if gear was destroyed before it got the required number of skips if not hasEnoughSkips and getGearValue(_G.sm.goalGears[goal.id], "sm_destroyed") then - return "fail" + return "fail", criticalGearFailText(goal.id) end return hasEnoughSkips elseif goal.type == "teamDefeat" then @@ -429,9 +448,15 @@ _G.sm.checkGoals = function() if params.customGoals ~= nil and #params.customGoals > 0 then for key, goal in pairs(params.customGoals) do - local done = _G.sm.checkGoal(goal) + local done, defaultFailText = _G.sm.checkGoal(goal) if done == false or done == "fail" then - return done + local failText + if goal.failText then + failText = goal.failText + else + failText = customFailText + end + return done, failText end end return true @@ -448,7 +473,7 @@ for key, nonGoal in pairs(params.customNonGoals) do local done = _G.sm.checkGoal(nonGoal) if done == true then - return true + return true, nonGoal.failText end end end @@ -480,9 +505,13 @@ return end _G.sm.checkRegularVictory() - if _G.sm.checkNonGoals() == true or _G.sm.checkGoals() == "fail" then - _G.sm.lose() - elseif _G.sm.checkGoals() == true then + local nonGoalStatus, nonGoalFailText = _G.sm.checkNonGoals() + local goalStatus, goalFailText = _G.sm.checkGoals() + if nonGoalStatus == true then + _G.sm.lose(nonGoalFailText) + elseif goalStatus == "fail" then + _G.sm.lose(goalText) + elseif goalStatus == true then _G.sm.win() end end @@ -502,11 +531,14 @@ end end - _G.sm.lose = function() + _G.sm.lose = function(failReason) if not _G.sm.gameEnded then _G.sm.gameEnded = true AddCaption(loc("Scenario failed!"), 0xFFFFFFFF, capgrpGameState) SendStat(siGameResult, loc("You lose!")) + if failReason then + SendStat(siCustomAchievement, failReason) + end if GetHogLevel(CurrentHedgehog) == 0 then SetState(CurrentHedgehog, bor(GetState(CurrentHedgehog), gstLoser)) SetState(CurrentHedgehog, band(GetState(CurrentHedgehog), bnot(gstHHDriven)))