# HG changeset patch # User mikade # Date 1314829718 -7200 # Node ID a962d0823f49548ff72b2d50d03efea9ee3c81ee # Parent 0ed1f543f301c6afd2d9e7966cf1b0d505d7e6da onHogAttack hook. Might reposition this later. Updates to Tumbler gameplay mode -- Better HUD -- Allow more user customization -- Bugfix for new gear spawns -- Performance tweaks -- Variety of small gameplay changes diff -r 0ed1f543f301 -r a962d0823f49 hedgewars/HHHandlers.inc --- a/hedgewars/HHHandlers.inc Wed Aug 31 15:50:39 2011 -0400 +++ b/hedgewars/HHHandlers.inc Thu Sep 01 00:28:38 2011 +0200 @@ -423,7 +423,8 @@ end end else Message:= Message and not gmAttack; end; - TargetPoint.X := NoPointX + TargetPoint.X := NoPointX; + ScriptCall('onHogAttack'); end; procedure AfterAttack; diff -r 0ed1f543f301 -r a962d0823f49 share/hedgewars/Data/Scripts/Multiplayer/Tumbler.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/Tumbler.lua Wed Aug 31 15:50:39 2011 -0400 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Tumbler.lua Thu Sep 01 00:28:38 2011 +0200 @@ -1,36 +1,41 @@ ------------------------------------ -- TUMBLER --- v.0.6 +-- v.0.7 ------------------------------------ loadfile(GetDataPath() .. "Scripts/Locale.lua")() loadfile(GetDataPath() .. "Scripts/Tracker.lua")() ---local fMod = 1 --.15 local fMod = 1000000 -- use this for dev and .16+ games -local moveTimer = 0 + local leftOn = false local rightOn = false local upOn = false local downOn = false +local preciseOn = false -local preciseOn = false ---local HJumpOn = false ---local LJumpON = false -local fireTimer = 0 -local scoreTag = nil local wep = {} local wepAmmo = {} +local wepCol = {} local wepIndex = 0 local wepCount = 0 +local fGears = 0 + +local mineSpawn +local barrelSpawn + local roundKills = 0 +local barrelsEaten = 0 +local minesEaten = 0 +local moveTimer = 0 +local fireTimer = 0 local TimeLeftCounter = 0 local TimeLeft = 0 local stopMovement = false local tumbleStarted = false -local beam = false +local vTag = {} ------------------------ -- version 0.4 @@ -72,38 +77,173 @@ -- modified crate frequencies a bit -- added some simple kill-based achievements, i think +------------------------ +-- version 0.7 +------------------------ + +-- a few code optimisations/performance tweaks +-- removed some deprecated code +-- fix a potential spawn bug + +-- improved HUD (now shows ammo counts) +-- improved user feedback (less generic messages) +-- colour-coded addcaptions to match hud :) + +-- base tumbling time now equals scheme turntime +-- tumbling time extension is now based on the amount of health contained in crate +-- new mines per turn based on minesnum +-- new barrels per turn based on explosives + +-- added 2 more achievements: barrel eater and mine eater (like kills, don't do anything atm) +-- slightly increased grab distance for explosives/mines +-- slightly increased flamer velocity +-- slightly decreased flamer volume +-- added a flame vaporiser (based on number of flame gears?) +-- give tumblers an extra 47 health on the start of their tumble to counter the grenade (exp) +-- refocus camera on tumbler on newturn (not on crates, barrels etc) +-- increase delay: yes, yes, eat your hearts out + +-- commit log +-- Better HUD +-- Allow more user customization +-- Bugfix for new gear spawns +-- Performance tweaks +-- Variety of small gameplay changes + --------------------------- -- some other ideas/things --------------------------- --[[ --- fix "ammo extended" message to be non-generic +-- add better gameflag handling -- fix flamer "shots remaining" message on start or choose a standard versus % -- add more sounds --- make barrels always explode? --- persistent ammo? --- allow custom turntime? --- dont hurt tumblers and restore their health at turn end? +-- better barrel/minespawn effects +-- separate grab distance for mines/barrels +-- [probably not] make barrels always explode? +-- [probably not] persistent ammo? +-- [probably not] dont hurt tumblers and restore their health at turn end? ]] -function DrawTags() + +---------------------------------------------------------------- +---------------------------------------------------------------- + +local flames = {} +local fGearValues = {} + +function runOnflames(func) + for k, gear in ipairs(flames) do + func(gear) + end +end + +function trackFGear(gear) + table.insert(flames, gear) +end + +function trackFGearDeletion(gear) + fGearValues[gear] = nil + for k, g in ipairs(flames) do + if g == gear then + table.remove(flames, k) + break + end + end +end + +function getFGearValue(gear, key) + if fGearValues[gear] ~= nil then + return fGearValues[gear][key] + end + return nil +end + +function setFGearValue(gear, key, value) + found = false + for id, values in pairs(fGearValues) do + if id == gear then + values[key] = value + found = true + end + end + if not found then + fGearValues[gear] = { [key] = value } + end +end + +function decreaseFGearValue(gear, key) + for id, values in pairs(fGearValues) do + if id == gear then + values[key] = values[key] - 1 + end + end +end + +function HandleLife(gear) + + decreaseFGearValue(gear, "L") + if getFGearValue(gear, "L") == 0 then + AddVisualGear(GetX(gear), GetY(gear), vgtSmoke, 0, false) + DeleteGear(gear) + end + +end + +---------------------------------------------------------------- +---------------------------------------------------------------- + +function HideTags() + + for i = 0, 3 do + SetVisualGearValues(vTag[i],0,0,0,0,0,1,0, 0, 240000, 0xffffff00) + end + +end + +function DrawTag(i) zoomL = 1.3 - DeleteVisualGear(scoreTag) - scoreTag = AddVisualGear(0, 0, vgtHealthTag, 0, false) - g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(scoreTag) + xOffset = 40 + + if i == 0 then + yOffset = 40 + tCol = 0xffba00ff --0xffed09ff --0xffba00ff + tValue = TimeLeft + elseif i == 1 then + zoomL = 1.1 + yOffset = 70 + tCol = wepCol[0] + tValue = wepAmmo[0] + elseif i == 2 then + zoomL = 1.1 + xOffset = 40 + 35 + yOffset = 70 + tCol = wepCol[1] + tValue = wepAmmo[1] + elseif i == 3 then + zoomL = 1.1 + xOffset = 40 + 70 + yOffset = 70 + tCol = wepCol[2] + tValue = wepAmmo[2] + end + + DeleteVisualGear(vTag[i]) + vTag[i] = AddVisualGear(0, 0, vgtHealthTag, 0, false) + g1, g2, g3, g4, g5, g6, g7, g8, g9, g10 = GetVisualGearValues(vTag[i]) SetVisualGearValues ( - scoreTag, --id - -(ScreenWidth/2) + 45, --xoffset - ScreenHeight - 50, --yoffset + vTag[i], --id + -(ScreenWidth/2) + xOffset, --xoffset + ScreenHeight - yOffset, --yoffset 0, --dx 0, --dy zoomL, --zoom 1, --~= 0 means align to screen g7, --frameticks - TimeLeft, --value + tValue, --value 240000, --timer - 0xffba00ff --GetClanColor( GetHogClan(CurrentHedgehog) ) + tCol --GetClanColor( GetHogClan(CurrentHedgehog) ) ) end @@ -123,22 +263,34 @@ -- yes that was my justification for a non generic method function CheckProximityToExplosives(gear) - if (GetGearDistance(gear) < 1300) then + if (GetGearDistance(gear) < 1400) then if (GetGearType(gear) == gtExplosives) then - - wepAmmo[0] = wepAmmo[0] + 1 + + wepAmmo[0] = wepAmmo[0] + 1 PlaySound(sndShotgunReload) DeleteGear(gear) - AddCaption(loc("Ammo extended!")) - + AddCaption(wep[0] .. " " .. loc("ammo extended!"), wepCol[0], capgrpAmmoinfo ) + DrawTag(1) + + barrelsEaten = barrelsEaten + 1 + if barrelsEaten == 5 then + AddCaption(loc("Achievement Unlocked") .. ": " .. loc("Barrel Eater!"),0xffba00ff,capgrpMessage2) + end + elseif (GetGearType(gear) == gtMine) then - wepAmmo[2] = wepAmmo[2] + 1 + wepAmmo[1] = wepAmmo[1] + 1 PlaySound(sndShotgunReload) DeleteGear(gear) - AddCaption(loc("Ammo extended!")) - end + AddCaption(wep[1] .. " " .. loc("ammo extended!"), wepCol[1], capgrpAmmoinfo ) + DrawTag(2) + + minesEaten = minesEaten + 1 + if minesEaten == 5 then + AddCaption(loc("Achievement Unlocked") .. ": " .. loc("Mine Eater!"),0xffba00ff,capgrpMessage2) + end + end else --AddCaption("There is nothing here...") @@ -150,103 +302,38 @@ function CheckProximity(gear) dist = GetGearDistance(gear) - --15000 - if ((dist < 15000) and (beam == true)) and - ( (GetGearType(gear) == gtMine) or (GetGearType(gear) == gtExplosives) ) then - -- ndx, ndy = GetGearVelocity(CurrentHedgehog) - -- SetGearVelocity(gear, ndx, ndy) - --AddCaption("hello???") - elseif (dist < 1600) and (GetGearType(gear) == gtCase) then - - if GetHealth(gear) > 0 then + + if (dist < 1600) and (GetGearType(gear) == gtCase) then + + if GetHealth(gear) > 0 then - AddCaption(loc("Tumbling Time Extended!")) - TimeLeft = TimeLeft + 5 --5s - DrawTags() + AddCaption(loc("Tumbling Time Extended!"), 0xffba00ff, capgrpMessage2 ) + + TimeLeft = TimeLeft + HealthCaseAmount --5 --5s + DrawTag(0) --PlaySound(sndShotgunReload) else - wepAmmo[1] = wepAmmo[1] + 800 + wepAmmo[2] = wepAmmo[2] + 800 PlaySound(sndShotgunReload) - AddCaption(loc("Ammo extended!")) + AddCaption(wep[2] .. " " .. loc("fuel extended!"), wepCol[2], capgrpAmmoinfo ) + DrawTag(3) end - + DeleteGear(gear) end end ---[[function ProjectileTrack(gear) - - if (GetGearType(gear) == gtMine) or (GetGearType(gear) == gtExplosives) then - - dist = GetGearDistance(gear) - - alt = 1 - if (dist < 30000) then - alt = -1 - end - - if (dist < 60000) - --and (dist > 16000) - then - - --if (GetGearType(gear) == gtShell) then - turningSpeed = 0.1*fMod*alt - --end - - dx, dy = GetGearVelocity(gear) - - if GetX(gear) > GetX(CurrentHedgehog) then - dx = dx - turningSpeed - else - dx = dx + turningSpeed - end +function ChangeWeapon() - if GetY(gear) > GetY(CurrentHedgehog) then - dy = dy - turningSpeed - else - dy = dy + turningSpeed - end - - - if (GetGearType(gear) == gtShell) then - dxlimit = 0.4*fMod - dylimit = 0.4*fMod - end - - if dx > dxlimit then - dx = dxlimit - end - if dy > dylimit then - dy = dylimit - end - if dx < -dxlimit then - dx = -dxlimit - end - if dy < -dylimit then - dy = -dylimit - end - - SetGearVelocity(gear, dx, dy) - - end - + wepIndex = wepIndex + 1 + if wepIndex == wepCount then + wepIndex = 0 end -end]] - - -function ChangeWeapon() - - --new - wepIndex = wepIndex + 1 - if wepIndex == wepCount then - wepIndex = 0 - end - - AddCaption(wep[wepIndex] .. " " .. loc("selected!"), GetClanColor(GetHogClan(CurrentHedgehog)),capgrpAmmoinfo ) - AddCaption(wepAmmo[wepIndex] .. " " .. loc("shots remaining."), GetClanColor(GetHogClan(CurrentHedgehog)),capgrpMessage2) + AddCaption(wep[wepIndex] .. " " .. loc("selected!"), wepCol[wepIndex],capgrpAmmoinfo ) + AddCaption(wepAmmo[wepIndex] .. " " .. loc("shots remaining."), wepCol[wepIndex],capgrpMessage2) end @@ -259,7 +346,7 @@ if (CurrentHedgehog ~= nil) and (stopMovement == false) and (tumbleStarted == true) and (wepAmmo[wepIndex] > 0) then wepAmmo[wepIndex] = wepAmmo[wepIndex] - 1 - AddCaption(wepAmmo[wepIndex] .. " " .. loc("shots remaining."), GetClanColor(GetHogClan(CurrentHedgehog)),capgrpMessage2) + AddCaption(wepAmmo[wepIndex] .. " " .. loc("shots remaining."), wepCol[wepIndex],capgrpMessage2) if wep[wepIndex] == loc("Barrel Launcher") then morte = AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtExplosives, 0, 0, 0, 1) @@ -268,10 +355,12 @@ x = x*2 y = y*2 SetGearVelocity(morte, x, y) - + DrawTag(1) + elseif wep[wepIndex] == loc("Mine Deployer") then morte = AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtMine, 0, 0, 0, 0) SetTimer(morte, 1000) + DrawTag(2) end end @@ -285,26 +374,14 @@ end function onHJump() - -- pick up explosives if nearby them + -- pick up explosives/mines if nearby them if (CurrentHedgehog ~= nil) and (stopMovement == false) and (tumbleStarted == true) then runOnGears(CheckProximityToExplosives) end end function onLJump() - -- for attracting mines and explosives if the beam is on - --[[if (CurrentHedgehog ~= nil) and (stopMovement == false) and (tumbleStarted == true) then - if beam == false then - beam = true - AddCaption(loc("Mine-attractor on!")) - else - beam = false - AddCaption(loc("Mine-attractor off!")) - end - end]] - ChangeWeapon() - end ----------------- @@ -353,22 +430,53 @@ -------------------------- function onGameInit() - --Theme = "Hell" CaseFreq = 0 - HealthCaseProb = 0 + HealthCaseProb = 0 + Delay = 1000 + + mineSpawn = MinesNum + if mineSpawn > 4 then + mineSpawn = 4 + end + + barrelSpawn = Explosives + if barrelSpawn > 4 then + barrelSpawn = 4 + end + + --MinesNum = 0 + --Explosives = 0 + + for i = 0, 3 do + vTag[0] = AddVisualGear(0, 0, vgtHealthTag, 0, false) + end + + HideTags() + + wep[0] = loc("Barrel Launcher") + wep[1] = loc("Mine Deployer") + wep[2] = loc("Flamer") + + wepCol[0] = 0x78818eff + wepCol[1] = 0xa12a77ff + wepCol[2] = 0xf49318ff + + wepCount = 3 + end function onGameStart() - + ShowMission ( "TUMBLER", loc("a Hedgewars mini-game"), loc("Eliminate the enemy hogs to win.") .. "|" .. " " .. "|" .. - --loc("Round Limit") .. ": " .. roundLimit .. "|" .. - --loc("Turn Time") .. ": " .. (TurnTime/1000) .. loc("sec") .. "|" .. - --" " .. "|" .. + loc("New Mines Per Turn") .. ": " .. (mineSpawn) .. "|" .. + loc("New Barrels Per Turn") .. ": " .. (barrelSpawn) .. "|" .. + loc("Time Extension") .. ": " .. (HealthCaseAmount) .. loc("sec") .. "|" .. + " " .. "|" .. loc("Movement: [Up], [Down], [Left], [Right]") .. "|" .. loc("Fire") .. ": " .. loc("[Left Shift]") .. "|" .. @@ -381,72 +489,66 @@ loc("Ammo is reset at the end of your turn.") .. "|" .. "", 4, 4000 - ) - - scoreTag = AddVisualGear(0, 0, vgtHealthTag, 0, false) - --DrawTags() - - SetVisualGearValues(scoreTag,0,0,0,0,0,1,0, 0, 240000, 0xffffff00) - - wep[0] = loc("Barrel Launcher") - wep[1] = loc("Flamer") - wep[2] = loc("Mine Deployer") - wepCount = 3 + ) end function onNewTurn() - + stopMovement = false tumbleStarted = false - beam = false - -- randomly create 2 new barrels and 3 mines on the map every turn - for i = 0, 1 do - gear = AddGear(0, 0, gtExplosives, 0, 0, 0, 0) + -- randomly create new barrels mines on the map every turn (can be disabled by setting mine/barrels to 0 in scheme) + for i = 0, barrelSpawn-1 do + gear = AddGear(100, 100, gtExplosives, 0, 0, 0, 0) SetHealth(gear, 100) - FindPlace(gear, false, 0, LAND_WIDTH) - tempE = AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false) + if FindPlace(gear, false, 0, LAND_WIDTH, false) ~= nil then + tempE = AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false) + end end - for i = 0, 2 do - gear = AddGear(0, 0, gtMine, 0, 0, 0, 0) - FindPlace(gear, false, 0, LAND_WIDTH) - tempE = AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false) + for i = 0, mineSpawn-1 do + gear = AddGear(100, 100, gtMine, 0, 0, 0, 0) + if FindPlace(gear, false, 0, LAND_WIDTH, false) ~= nil then + tempE = AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false) + end end + -- randomly spawn time extension crates / flamer fuel on the map r = GetRandom(100) if r > 50 then - SpawnHealthCrate(0, 0) + gear = SpawnHealthCrate(0, 0) end r = GetRandom(100) if r > 70 then - SpawnAmmoCrate(0, 0, amSkip) + gear = SpawnAmmoCrate(0, 0, amSkip) end - --DrawTags() - SetVisualGearValues(scoreTag,0,0,0,0,0,1,0, 0, 240000, 0xffffff00) + HideTags() --reset ammo counts wepAmmo[0] = 2 - wepAmmo[1] = 50 - wepAmmo[2] = 1 + wepAmmo[1] = 1 + wepAmmo[2] = 50 -- 50000 -- 50 wepIndex = 2 ChangeWeapon() roundKills = 0 + barrelsEaten = 0 + minesEaten = 0 + + FollowGear(CurrentHedgehog) end function DisableTumbler() stopMovement = true - beam = false upOn = false down = false leftOn = false rightOn = false - SetVisualGearValues(scoreTag,0,0,0,0,0,1,0, 0, 240000, 0xffffff00) + HideTags() end function onGameTick() @@ -456,33 +558,27 @@ if (TurnTimeLeft > 0) and (TurnTimeLeft ~= TurnTime) then --AddCaption(loc("Good to go!")) tumbleStarted = true - TimeLeft = 30 + TimeLeft = (TurnTime/1000) AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtGrenade, 0, 0, 0, 1) - DrawTags() + SetHealth(CurrentHedgehog, GetHealth(CurrentHedgehog) + 47) -- new + for i = 0, 3 do + DrawTag(i) + end end end if (CurrentHedgehog ~= nil) and (tumbleStarted == true) then - --AddCaption(GetX(CurrentHedgehog) .. ";" .. GetY(CurrentHedgehog) ) - - runOnGears(CheckProximity) -- crates and mines - - --if beam == true then - -- runOnGears(ProjectileTrack) - --end + runOnGears(CheckProximity) -- crates -- Calculate and display turn time TimeLeftCounter = TimeLeftCounter + 1 if TimeLeftCounter == 1000 then TimeLeftCounter = 0 TimeLeft = TimeLeft - 1 - - if TimeLeft >= 0 then - --AddCaption(TimeLeft) - DrawTags() + DrawTag(0) end end @@ -496,6 +592,8 @@ if moveTimer == 100 then -- 100 moveTimer = 0 + runOnflames(HandleLife) + --------------- -- new trail code --------------- @@ -540,8 +638,6 @@ dy = dy + 0.1*fMod end - - SetGearVelocity(CurrentHedgehog, dx, dy) end @@ -550,18 +646,19 @@ --flamer -- fireTimer = fireTimer + 1 - if fireTimer == 5 then -- 5 --10 + if fireTimer == 6 then -- 5 --10 fireTimer = 0 if (wep[wepIndex] == loc("Flamer") ) and (preciseOn == true) and (wepAmmo[wepIndex] > 0) and (stopMovement == false) and (tumbleStarted == true) then - wepAmmo[wepIndex] = wepAmmo[wepIndex] - 1 - AddCaption( - loc("Flamer") .. ": " .. - (wepAmmo[wepIndex]/800*100) - (wepAmmo[wepIndex]/800*100)%2 .. "%", - GetClanColor(GetHogClan(CurrentHedgehog)), + wepAmmo[wepIndex] = wepAmmo[wepIndex] - 1 + AddCaption( + loc("Flamer") .. ": " .. + (wepAmmo[wepIndex]/800*100) - (wepAmmo[wepIndex]/800*100)%2 .. "%", + wepCol[2], capgrpMessage2 - ) + ) + DrawTag(3) dx, dy = GetGearVelocity(CurrentHedgehog) shell = AddGear(GetX(CurrentHedgehog), GetY(CurrentHedgehog), gtFlame, 0, 0, 0, 0) @@ -582,16 +679,14 @@ ydev = ydev*-1 end - --*13 --8 - SetGearVelocity(shell, (dx*4)+(xdev*fMod), (dy*4)+(ydev*fMod)) --10 + --*13 --8 *-4 + SetGearVelocity(shell, (dx*4.5)+(xdev*fMod), (dy*4.5)+(ydev*fMod)) --10 end end -- - - end @@ -600,7 +695,6 @@ function isATrackedGear(gear) if (GetGearType(gear) == gtExplosives) or (GetGearType(gear) == gtMine) or - (GetGearType(gear) == gtShell) or -- new -- gtBall (GetGearType(gear) == gtCase) then return(true) @@ -609,7 +703,6 @@ end end - --[[function onGearDamage(gear, damage) if gear == CurrentHedgehog then -- You are now tumbling @@ -618,50 +711,60 @@ function onGearAdd(gear) - if isATrackedGear(gear) then + if GetGearType(gear) == gtFlame then + + trackFGear(gear) + + fGears = fGears +1 + + if fGears < 80 then + setFGearValue(gear,"L",30) + else + setFGearValue(gear,"L",5) --3 + end + + elseif isATrackedGear(gear) then trackGear(gear) end - --if GetGearType(gear) == gtBall then - -- SetTimer(gear, 15000) - --end - end function onGearDelete(gear) - if isATrackedGear(gear) then + if GetGearType(gear) == gtFlame then + trackFGearDeletion(gear) + fGears = fGears -1 + + elseif isATrackedGear(gear) then trackDeletion(gear) + + -- achievements? prototype + elseif GetGearType(gear) == gtHedgehog then + + if GetHogTeamName(gear) ~= GetHogTeamName(CurrentHedgehog) then + + roundKills = roundKills + 1 + if roundKills == 2 then + AddCaption(loc("Double Kill!"),0xffba00ff,capgrpMessage2) + elseif roundKills == 3 then + AddCaption(loc("Killing spree!"),0xffba00ff,capgrpMessage2) + elseif roundKills >= 4 then + AddCaption(loc("Unstoppable!"),0xffba00ff,capgrpMessage2) + end + + elseif gear == CurrentHedgehog then + DisableTumbler() + + elseif gear ~= CurrentHedgehog then + AddCaption(loc("Friendly Fire!"),0xffba00ff,capgrpMessage2) + end + end if CurrentHedgehog ~= nil then FollowGear(CurrentHedgehog) end - if gear == CurrentHedgehog then - DisableTumbler() - end +end - -- achievements? prototype - if GetGearType(gear) == gtHedgehog then - if GetHogTeamName(gear) ~= GetHogTeamName(CurrentHedgehog) then - - roundKills = roundKills + 1 - if roundKills == 2 then - AddCaption(loc("Double Kill!"),0xffba00ff,capgrpMessage2) - elseif roundKills == 3 then - AddCaption(loc("Killing spree!"),0xffba00ff,capgrpMessage2) - elseif roundKills >= 4 then - AddCaption(loc("Unstoppable!"),0xffba00ff,capgrpMessage2) - end - - elseif gear ~= CurrentHedgehog then - AddCaption(loc("Friendly Fire!"),0xffba00ff,capgrpMessage2) - end - - end - - - -end