--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Scripts/Multiplayer/Capture_the_Flag.lua Fri Dec 24 00:53:50 2010 -0500
@@ -0,0 +1,597 @@
+--------------------------------
+-- CAPTURE_THE_FLAG_CUSTOM 0.3
+-- by mikade
+--------------------------------
+
+-- Version History
+---------
+-- 0.1
+---------
+
+-- [conversion from map-dependant CTF_Blizzard to map independant Capture the Flag]
+-- added an intial starting stage where flagspawn is decided by the players (weapon set will require a jetpack unless I set)
+-- changed the flag from a crate to a visual gear, and all associated methods and checks relating to flags (five hours later, lol)
+-- changed starting/respawning positioning to accommodate different map sizes
+-- added another circle to mark flag spawn
+-- added gameFlag filter
+-- changed scoring feedback
+-- cleaned up some code
+
+-- removing own flag from spawning point no longer possible
+-- destroying flags no longer possible.
+-- added basic glowing circle effect to spawn area
+-- added expanding circle to fgear itself
+
+-- removed teleporters
+-- removed random crate drops (this should be decided by scheme)
+-- removed set map criteria like minesNum, turnTime, explosives etc. except for sudden death
+-- removed weapon defintions
+-- removed placement and respawning methods, hopefully divideTeams will have this covered
+
+---------
+-- 0.2
+---------
+
+-- [now with user friendliness]
+-- flag is now placed wherever you end up at the end of your first turn, this ensures that it is always placed by turn 3
+-- removed a bunch of backup code and no-longer needed variables / methods from CTF_Blizzard days
+-- removed an aura that was still mistakenly hanging about
+-- added an in-game note about placements
+-- added an in-game note about the rules of the game
+-- added translation support and loc()'ed everything
+-- changed things so the seed is no longer always the same...
+
+-- In this version:
+---------
+-- 0.3
+---------
+-- [fufufufu kamikaze fix]
+-- added nill checks to make sure the player doesn't generate errors by producing a nil value in hhs[] when he uses kamikaze
+-- added a check to make sure the player doesn't kamikaze straight down and make the flag's starting point underwater
+-- added a check to make sure the player drops the flag if he has it and he uses kamikaze
+
+-----------------
+--SCRIPT BEGINS
+-----------------
+
+-- enable awesome translaction support so we can use loc() wherever we want
+loadfile(GetDataPath() .. "Scripts/Locale.lua")()
+
+---------------------------------------------------------------
+----------lots of bad variables and things
+----------because someone is too lazy
+----------to read about tables properly
+------------------ "Oh well, they probably have the memory"
+
+local gameStarted = false
+local gameTurns = 0
+
+--------------------------
+-- hog and team tracking variales
+--------------------------
+
+local numhhs = 0 -- store number of hedgehogs
+local hhs = {} -- store hedgehog gears
+
+local numTeams -- store the number of teams in the game
+local teamNameArr = {} -- store the list of teams
+local teamSize = {} -- store how many hogs per team
+local teamIndex = {} -- at what point in the hhs{} does each team begin
+
+-------------------
+-- flag variables
+-------------------
+
+local fPlaced = {} -- has the flag been placed TRUE/FALSE
+
+local fGear = {} -- pointer to the visual gears that represent the flag
+local fGearX = {}
+local fGearY = {}
+
+local fThief = {} -- pointer to the hogs who stole the flags
+local fIsMissing = {} -- have the flags been destroyed or captured
+local fNeedsRespawn = {} -- do the flags need to be respawned
+local fCaptures = {} -- the team "scores" how many captures
+local fSpawnX = {} -- spawn X for flags
+local fSpawnY = {} -- spawn Y for flags
+
+local fThiefX = {}
+local fThiefY = {}
+local FTTC = 0 -- flag thief tracker counter
+
+local fSpawnC = {} -- spawn circle marker
+local fCirc = {} -- flag/carrier marker circles
+local fCol = {} -- colour of the clans
+
+local fGearRad = 0
+local fGearRadMin = 5
+local fGearRadMax = 33
+local fGearTimer = 0
+
+------------------------
+--flag methods
+------------------------
+
+function CheckScore(teamID)
+
+ if teamID == 0 then
+ alt = 1
+ elseif teamID == 1 then
+ alt = 0
+ end
+
+ if fCaptures[teamID] == 3 then
+ for i = 0, (numhhs-1) do
+ if hhs[i] ~= nil then
+ if GetHogClan(hhs[i]) == alt then
+ SetEffect(hhs[i], heResurrectable, false)
+ SetHealth(hhs[i],0)
+ end
+ end
+ end
+ if CurrentHedgehog ~= nil then
+ ShowMission(loc("GAME OVER!"), loc("Victory for the ") .. GetHogTeamName(CurrentHedgehog), loc("Hooray!"), 0, 0)
+ end
+ end
+
+end
+
+function DoFlagStuff(gear)
+
+ if (gear == fGear[0]) then
+ wtf = 0
+ bbq = 1
+ elseif (gear == fGear[1]) then
+ wtf = 1
+ bbq = 0
+ end
+
+ -- player has successfully captured the enemy flag
+ if (GetHogClan(CurrentHedgehog) == wtf) and (CurrentHedgehog == fThief[bbq]) and (fIsMissing[wtf] == false) then
+
+ DeleteVisualGear(fGear[wtf])
+ fGear[wtf] = nil -- the flag has now disappeared
+
+ fIsMissing[wtf] = false
+ fNeedsRespawn[wtf] = true
+ fIsMissing[bbq] = false
+ fNeedsRespawn[bbq] = true
+ fCaptures[wtf] = fCaptures[wtf] +1
+ ShowMission(loc("You have SCORED!!"), GetHogTeamName(CurrentHedgehog) .. ": " .. fCaptures[wtf], loc("Opposing Team: ") .. fCaptures[bbq], 0, 0)
+ PlaySound(sndVictory)
+ fThief[bbq] = nil -- player no longer has the enemy flag
+ CheckScore(wtf)
+
+ --if the player is returning the flag
+ elseif (GetHogClan(CurrentHedgehog) == wtf) and (fIsMissing[wtf] == true) then
+
+ DeleteVisualGear(fGear[wtf])
+ fGear[wtf] = nil -- the flag has now disappeared
+
+ fNeedsRespawn[wtf] = true
+ HandleRespawns() -- this will set fIsMissing[wtf] to false :)
+ AddCaption(loc("Flag returned!"))
+
+ --if the player is taking the enemy flag
+ elseif GetHogClan(CurrentHedgehog) == bbq then
+
+ DeleteVisualGear(fGear[wtf])
+ fGear[wtf] = nil -- the flag has now disappeared
+
+ fIsMissing[wtf] = true
+ for i = 0,numhhs-1 do
+ if CurrentHedgehog ~= nil then
+ if CurrentHedgehog == hhs[i] then
+ fThief[wtf] = hhs[i]
+ end
+ end
+ end
+ AddCaption(loc("Flag captured!"))
+
+ --below line doesnt usually get called
+ --else
+ -- now gets called if you go over your own flag, presumably
+ --AddCaption("Hmm... that wasn't supposed to happen...")
+ end
+
+end
+
+function CheckFlagProximity()
+
+ for i = 0, 1 do
+ if fGear[i] ~= nil then
+
+ g1X = fGearX[i]
+ g1Y = fGearY[i]
+
+ g2X, g2Y = GetGearPosition(CurrentHedgehog)
+
+ q = g1X - g2X
+ w = g1Y - g2Y
+ dist = (q*q) + (w*w)
+
+ if dist < 500 then --1600
+ DoFlagStuff(fGear[i])
+ end
+ end
+ end
+
+end
+
+
+function HandleRespawns()
+
+ for i = 0, 1 do
+
+ if fNeedsRespawn[i] == true then
+ fGear[i] = AddVisualGear(fSpawnX[i],fSpawnY[i],vgtCircle,0,true)
+ fGearX[i] = fSpawnX[i]
+ fGearY[i] = fSpawnY[i]
+ --fGear[i] = SpawnAmmoCrate(fSpawnX[i],fSpawnY[i],amSkip)
+ fNeedsRespawn[i] = false
+ fIsMissing[i] = false -- new, this should solve problems of a respawned flag being "returned" when a player tries to score
+ AddCaption(loc("Flag respawned!"))
+ end
+
+ end
+
+end
+
+
+function FlagThiefDead(gear)
+
+ if (gear == fThief[0]) then
+ wtf = 0
+ bbq = 1
+ elseif (gear == fThief[1]) then
+ wtf = 1
+ bbq = 0
+ end
+
+ if fThief[wtf] ~= nil then
+ -- falls into water
+ --ShowMission(LAND_HEIGHT, fThiefY[wtf], (LAND_HEIGHT - fThiefY[wtf]), 0, 0)
+ if (LAND_HEIGHT - fThiefY[wtf]) < 15 then
+ fIsMissing[wtf] = true
+ fNeedsRespawn[wtf] = true
+ HandleRespawns()
+ --AddCaption("hah??")
+ else --normally
+ fGearX[wtf] = fThiefX[wtf]
+ fGearY[wtf] = fThiefY[wtf]
+ fGear[wtf] = AddVisualGear(fGearX[wtf],fGearY[wtf],vgtCircle,0,true)
+ --fGear[wtf] = AddVisualGear(fThiefX[wtf],fThiefY[wtf],vgtCircle,0,true)
+ end
+
+ AddVisualGear(fThiefX[wtf], fThiefY[wtf], vgtBigExplosion, 0, false)
+ fThief[wtf] = nil
+ end
+
+end
+
+function HandleCircles()
+
+ fGearTimer = fGearTimer + 1
+ if fGearTimer == 50 then
+ fGearTimer = 0
+ fGearRad = fGearRad + 1
+ if fGearRad > fGearRadMax then
+ fGearRad = fGearRadMin
+ end
+ end
+
+ for i = 0, 1 do
+
+ --SetVisualGearValues(fSpawnC[i], fSpawnX[i],fSpawnY[i], 20, 200, 0, 0, 100, 50, 3, fCol[i]) -- draw a circ for spawning area
+
+ if fIsMissing[i] == false then -- draw a flag marker at the flag's spawning place
+ SetVisualGearValues(fCirc[i], fSpawnX[i],fSpawnY[i], 20, 20, 0, 10, 0, 33, 3, fCol[i])
+ if fGear[i] ~= nil then -- draw the flag gear itself
+ SetVisualGearValues(fGear[i], fSpawnX[i],fSpawnY[i], 20, 200, 0, 0, 100, fGearRad, 2, fCol[i])
+ end
+ elseif (fIsMissing[i] == true) and (fNeedsRespawn[i] == false) then
+ if fThief[i] ~= nil then -- draw circle round flag carrier
+ SetVisualGearValues(fCirc[i], fThiefX[i], fThiefY[i], 20, 200, 0, 0, 100, 33, 3, fCol[i])
+ --AddCaption("circle marking carrier")
+ elseif fThief[i] == nil then -- draw cirle round dropped flag
+ --g1X,g1Y,g4,g5,g6,g7,g8,g9,g10,g11 = GetVisualGearValues(fGear[i])
+ --SetVisualGearValues(fCirc[i], g1X, g1Y, 20, 200, 0, 0, 100, 33, 2, fCol[i])
+ SetVisualGearValues(fCirc[i], fGearX[i], fGearY[i], 20, 200, 0, 0, 100, 33, 3, fCol[i])
+ --AddCaption('dropped circle marker')
+ if fGear[i] ~= nil then -- flag gear itself
+ --SetVisualGearValues(fGear[i], g1X, g1Y, 20, 200, 0, 0, 100, 10, 4, fCol[i])
+ SetVisualGearValues(fGear[i], fGearX[i], fGearY[i], 20, 200, 0, 0, 100, fGearRad, 2, fCol[i])
+ --AddCaption('dropped flag itself')
+ end
+ end
+ end
+
+ if fNeedsRespawn[i] == true then -- if the flag has been destroyed, no need for a circle
+ SetVisualGearValues(fCirc[i], fSpawnX[i],fSpawnY[i], 20, 200, 0, 0, 100, 0, 0, fCol[i])
+ --AddCaption("needs respawn = true. flag 'destroyed'?")
+ end
+ end
+
+end
+
+------------------------
+-- general methods
+------------------------
+
+function CheckDistance(gear1, gear2)
+
+ g1X, g1Y = GetGearPosition(gear1)
+ g2X, g2Y = GetGearPosition(gear2)
+
+ g1X = g1X - g2X
+ g1Y = g1Y - g2Y
+ z = (g1X*g1X) + (g1Y*g1Y)
+
+ dist = z
+
+ return dist
+
+end
+
+function RebuildTeamInfo()
+
+
+ -- make a list of individual team names
+ for i = 0, 5 do
+ teamNameArr[i] = i
+ teamSize[i] = 0
+ teamIndex[i] = 0
+ end
+ numTeams = 0
+
+ for i = 0, (numhhs-1) do
+
+ z = 0
+ unfinished = true
+ while(unfinished == true) do
+
+ newTeam = true
+ tempHogTeamName = GetHogTeamName(hhs[i]) -- this is the new name
+
+ if tempHogTeamName == teamNameArr[z] then
+ newTeam = false
+ unfinished = false
+ end
+
+ z = z + 1
+
+ if z == TeamsCount then
+ unfinished = false
+ if newTeam == true then
+ teamNameArr[numTeams] = tempHogTeamName
+ numTeams = numTeams + 1
+ end
+ end
+
+ end
+
+ end
+
+ -- find out how many hogs per team, and the index of the first hog in hhs
+ for i = 0, numTeams-1 do
+
+ for z = 0, numhhs-1 do
+ if GetHogTeamName(hhs[z]) == teamNameArr[i] then
+ if teamSize[i] == 0 then
+ teamIndex[i] = z -- should give starting index
+ end
+ teamSize[i] = teamSize[i] + 1
+ --add a pointer so this hog appears at i in hhs
+ end
+ end
+
+ end
+
+end
+
+function StartTheGame()
+
+ gameStarted = true
+ AddCaption(loc("Game Started!"))
+
+ for i = 0, 1 do
+
+ -- if someone uses kamikaze downwards, this can happen as the hog won't respawn
+ if (LAND_HEIGHT - fSpawnY[i]) < 0 then
+ tempG = AddGear(0, 0, gtTarget, 0, 0, 0, 0)
+ FindPlace(tempG, true, 0, LAND_WIDTH, true)
+ fSpawnX[i], fSpawnY[i] = GetGearPosition(tempG)
+ DeleteGear(tempG)
+ end
+
+ fGear[i] = AddVisualGear(fSpawnX[i],fSpawnY[i],vgtCircle,0,true)
+ fCirc[i] = AddVisualGear(fSpawnX[i],fSpawnY[i],vgtCircle,0,true)
+ fSpawnC[i] = AddVisualGear(fSpawnX[i],fSpawnY[i],vgtCircle,0,true)
+
+ fGearX[i] = fSpawnX[i]
+ fGearY[i] = fSpawnY[i]
+
+ fCol[i] = GetClanColor(i)
+ fIsMissing[i] = false
+ fNeedsRespawn[i] = false
+ fCaptures[i] = 0
+
+ --SetVisualGearValues(zxc, 1000,1000, 20, 100, 0, 10, 1, 100, 5, GetClanColor(0))
+
+ SetVisualGearValues(fSpawnC[i], fSpawnX[i],fSpawnY[i], 20, 100, 0, 10, 0, 75, 5, fCol[i])
+ --SetVisualGearValues(fCirc[i], fSpawnX[i],fSpawnY[i], 20, 20, 0, 10, 0, 33, 3, fCol[i])
+
+
+ end
+
+end
+
+------------------------
+-- game methods
+------------------------
+
+function onGameInit()
+
+ -- Things we don't modify here will use their default values.
+
+ GameFlags = band(bor(GameFlags, gfDivideTeams), bnot(gfKing + gfForts))
+ SuddenDeathTurns = 99 -- suddendeath is off, effectively
+ --TurnTime = 30000 -- (was 30) The time the player has to move each round (in ms)
+ --Delay = 10 -- The delay between each round
+
+end
+
+
+function onGameStart()
+
+ --ShowMission(loc(caption), loc(subcaption), loc(goal), 0, 0)
+ ShowMission(loc("CAPTURE THE FLAG"), loc("by mikade"), loc("CUSTOM BUILD 0.2"), 0, 0)
+
+ RebuildTeamInfo()
+
+ -- should gfDivideTeams do this automatically?
+ --[[for i = 0, (TeamsCount-1) do
+ for g = teamIndex[i], (teamIndex[i]+teamSize[i]-1) do
+ if GetHogClan(hhs[g]) == 0 then
+ FindPlace(hhs[g], false, 0, LAND_WIDTH/2)
+ elseif GetHogClan(hhs[g]) == 1 then
+ FindPlace(hhs[g], false, LAND_WIDTH/2, LAND_WIDTH)
+ end
+ end
+ end]]
+
+ fPlaced[0] = false
+ fPlaced[1] = false
+
+ --zxc = AddVisualGear(fSpawnX[i],fSpawnY[i],vgtCircle,0,true)
+
+
+ --SetVisualGearValues(zxc, 1000,1000, 20, 255, 1, 10, 0, 200, 1, GetClanColor(0))
+ --minO,max0 -glowyornot --pulsate timer -- fuckall -- radius -- width -- colour
+end
+
+
+function onNewTurn()
+
+ gameTurns = gameTurns + 1
+
+ if lastTeam ~= GetHogTeamName(CurrentHedgehog) then
+ lastTeam = GetHogTeamName(CurrentHedgehog)
+ end
+
+ --AddCaption("Handling respawns")
+ if gameStarted == true then
+ HandleRespawns()
+ --new method of placing starting flags
+ elseif gameTurns == 1 then
+ ShowMission(loc("CAPTURE THE FLAG"), loc("Flags will be placed where each team ends their turn."), "", 0, 0)
+ elseif gameTurns == 2 then
+ fPlaced[0] = true
+ ShowMission(loc("CAPTURE THE FLAG"), loc("RULES OF THE GAME [Press ESC to view]"), loc(" - Return the enemy flag to your base to score | - First team to 3 captures wins | - You may only score when your flag is in your base | - Hogs will drop the flag if killed, or drowned | - Dropped flags may be returned or recaptured | - Hogs respawn when killed"), 0, 0)
+ elseif gameTurns == 3 then
+ fPlaced[1] = true
+ StartTheGame()
+ end
+
+end
+
+function onGameTick()
+
+ -- onRessurect calls AFTER you have resurrected,
+ -- so keeping track of x,y a few milliseconds before
+ -- is useful
+ --FTTC = FTTC + 1
+ --if FTTC == 100 then
+ -- FTTC = 0
+ for i = 0,1 do
+ if fThief[i] ~= nil then
+ fThiefX[i] = GetX(fThief[i])
+ fThiefY[i] = GetY(fThief[i])
+ end
+ end
+ --end
+
+ -- things we wanna check often
+ if (CurrentHedgehog ~= nil) then
+ --AddCaption(LAND_HEIGHT - GetY(CurrentHedgehog))
+ --AddCaption(GetX(CurrentHedgehog) .. "; " .. GetY(CurrentHedgehog))
+ --CheckTeleporters()
+
+ end
+
+ if gameStarted == true then
+ HandleCircles()
+ if CurrentHedgehog ~= nil then
+ CheckFlagProximity()
+ end
+ elseif CurrentHedgehog ~= nil then -- if the game hasn't started yet, keep track of where we are gonna put the flags on turn end
+
+ if GetHogClan(CurrentHedgehog) == 0 then
+ i = 0
+ elseif GetHogClan(CurrentHedgehog) == 1 then
+ i = 1
+ end
+
+ fSpawnX[i] = GetX(CurrentHedgehog)
+ fSpawnY[i] = GetY(CurrentHedgehog)
+
+ end
+
+end
+
+function onGearResurrect(gear)
+
+ --AddCaption("A gear has been resurrected!")
+
+ -- mark the flag thief as dead if he needed a respawn
+ for i = 0,1 do
+ if gear == fThief[i] then
+ FlagThiefDead(gear)
+ end
+ end
+
+ -- should be covered by gfDivideTeams, actually
+ -- place hogs belonging to each clan either left or right side of map
+ --if GetHogClan(gear) == 0 then
+ -- FindPlace(gear, false, 0, LAND_WIDTH/2)
+ --elseif GetHogClan(gear) == 1 then
+ -- FindPlace(gear, false, LAND_WIDTH/2, LAND_WIDTH)
+ --end
+
+ AddVisualGear(GetX(gear), GetY(gear), vgtBigExplosion, 0, false)
+
+end
+
+function onGearDamage(gear, damage)
+--
+end
+
+function onGearAdd(gear)
+
+ if GetGearType(gear) == gtHedgehog then
+ hhs[numhhs] = gear
+ numhhs = numhhs + 1
+ SetEffect(gear, heResurrectable, true)
+ end
+
+end
+
+function onGearDelete(gear)
+
+ if GetGearType(gear) == gtHedgehog then
+ --AddCaption("gear deleted!")
+ for i = 0, (numhhs-1) do
+ if gear == hhs[i] then
+
+ for i = 0,1 do
+ if gear == fThief[i] then
+ FlagThiefDead(gear)
+ end
+ end
+ hhs[i] = nil
+ --AddCaption("for real")
+ end
+ end
+ end
+
+end